Fix some ARMv7-M syscall logic
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@5736 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
parent
8a44d95b14
commit
8159804f9c
@ -127,8 +127,11 @@ struct xcptcontext
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_NUTTX_KERNEL
|
#ifdef CONFIG_NUTTX_KERNEL
|
||||||
/* The following holds the return address from a system call */
|
/* The following holds the return address and the exc_return value needed
|
||||||
|
* return from a system call.
|
||||||
|
*/
|
||||||
|
|
||||||
|
uint32_t excreturn;
|
||||||
uint32_t sysreturn;
|
uint32_t sysreturn;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* arch/arm/src/armv7-m/up_svcall.c
|
* arch/arm/src/armv7-m/up_svcall.c
|
||||||
*
|
*
|
||||||
* Copyright (C) 2009, 2011-2012 Gregory Nutt. All rights reserved.
|
* Copyright (C) 2009, 2011-2013 Gregory Nutt. All rights reserved.
|
||||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -151,7 +151,11 @@ int up_svcall(int irq, FAR void *context)
|
|||||||
svcdbg(" R8: %08x %08x %08x %08x %08x %08x %08x %08x\n",
|
svcdbg(" R8: %08x %08x %08x %08x %08x %08x %08x %08x\n",
|
||||||
regs[REG_R8], regs[REG_R9], regs[REG_R10], regs[REG_R11],
|
regs[REG_R8], regs[REG_R9], regs[REG_R10], regs[REG_R11],
|
||||||
regs[REG_R12], regs[REG_R13], regs[REG_R14], regs[REG_R15]);
|
regs[REG_R12], regs[REG_R13], regs[REG_R14], regs[REG_R15]);
|
||||||
svcdbg(" PSR=%08x\n", regs[REG_XPSR]);
|
#ifdef REG_EXC_RETURN
|
||||||
|
svcdbg(" PSR: %08x LR: %08x\n", regs[REG_XPSR], current_regs[REG_EXC_RETURN]);
|
||||||
|
#else
|
||||||
|
svcdbg(" PSR: %08x\n", regs[REG_XPSR]);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Handle the SVCall according to the command in R0 */
|
/* Handle the SVCall according to the command in R0 */
|
||||||
|
|
||||||
@ -246,23 +250,22 @@ int up_svcall(int irq, FAR void *context)
|
|||||||
{
|
{
|
||||||
struct tcb_s *rtcb = sched_self();
|
struct tcb_s *rtcb = sched_self();
|
||||||
|
|
||||||
/* Make sure that we got here from a privileged thread and
|
/* Make sure that there is a saved syscall return address. */
|
||||||
* that there is a saved syscall return address.
|
|
||||||
*/
|
|
||||||
|
|
||||||
DEBUGASSERT(rtcb->xcp.sysreturn != 0 &&
|
svcdbg("sysreturn: %08x excreturn: %08x\n",
|
||||||
regs[REG_EXC_RETURN] == EXC_RETURN_PRIVTHR);
|
rtcb->xcp.sysreturn, rtcb->xcp.excreturn);
|
||||||
|
DEBUGASSERT(rtcb->xcp.sysreturn != 0);
|
||||||
|
|
||||||
/* Setup to return to the saved syscall return address in
|
/* Setup to return to the saved syscall return address in
|
||||||
* unprivileged mode.
|
* the original mode.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
current_regs[REG_PC] = rtcb->xcp.sysreturn;
|
current_regs[REG_PC] = rtcb->xcp.sysreturn;
|
||||||
current_regs[REG_EXC_RETURN] = EXC_RETURN_UNPRIVTHR;
|
current_regs[REG_EXC_RETURN] = rtcb->xcp.excreturn;
|
||||||
rtcb->xcp.sysreturn = 0;
|
rtcb->xcp.sysreturn = 0;
|
||||||
|
|
||||||
/* The return value must be in R0-R1. dispatch_syscall() temporarily
|
/* The return value must be in R0-R1. dispatch_syscall() temporarily
|
||||||
* moved the value to R2.
|
* moved the value for R0 to R2.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
current_regs[REG_R0] = current_regs[REG_R2];
|
current_regs[REG_R0] = current_regs[REG_R2];
|
||||||
@ -280,21 +283,22 @@ int up_svcall(int irq, FAR void *context)
|
|||||||
#ifdef CONFIG_NUTTX_KERNEL
|
#ifdef CONFIG_NUTTX_KERNEL
|
||||||
FAR struct tcb_s *rtcb = sched_self();
|
FAR struct tcb_s *rtcb = sched_self();
|
||||||
|
|
||||||
/* Verify the the SYS call number is within range */
|
/* Verify that the SYS call number is within range */
|
||||||
|
|
||||||
DEBUGASSERT(current_regs[REG_R0] < SYS_maxsyscall);
|
DEBUGASSERT(current_regs[REG_R0] < SYS_maxsyscall);
|
||||||
|
|
||||||
/* Make sure that we got here from a unprivileged thread and that
|
/* Make sure that we got here that there is a no saved syscall
|
||||||
* there is a no saved syscall return address.
|
* return address. We cannot yet handle nested system calls.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
DEBUGASSERT(rtcb->xcp.sysreturn == 0 &&
|
DEBUGASSERT(rtcb->xcp.sysreturn == 0);
|
||||||
regs[REG_EXC_RETURN] == EXC_RETURN_UNPRIVTHR);
|
|
||||||
|
|
||||||
/* Setup to return to dispatch_syscall in privileged mode. */
|
/* Setup to return to dispatch_syscall in privileged mode. */
|
||||||
|
|
||||||
rtcb->xcp.sysreturn = regs[REG_PC];
|
rtcb->xcp.sysreturn = regs[REG_PC];
|
||||||
regs[REG_PC] = (uint32_t)dispatch_syscall;
|
rtcb->xcp.excreturn = current_regs[REG_EXC_RETURN];
|
||||||
|
|
||||||
|
current_regs[REG_PC] = (uint32_t)dispatch_syscall;
|
||||||
current_regs[REG_EXC_RETURN] = EXC_RETURN_PRIVTHR;
|
current_regs[REG_EXC_RETURN] = EXC_RETURN_PRIVTHR;
|
||||||
|
|
||||||
/* Offset R0 to account for the reserved values */
|
/* Offset R0 to account for the reserved values */
|
||||||
|
@ -239,19 +239,16 @@ int up_swint0(int irq, FAR void *context)
|
|||||||
{
|
{
|
||||||
struct tcb_s *rtcb = sched_self();
|
struct tcb_s *rtcb = sched_self();
|
||||||
|
|
||||||
/* Make sure that we got here from a privileged thread and
|
/* Make sure that there is a saved syscall return address. */
|
||||||
* that there is a saved syscall return address.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#error "Missing logic -- need to test for privileged mode"
|
DEBUGASSERT(rtcb->xcp.sysreturn != 0);
|
||||||
DEBUGASSERT(rtcb->xcp.sysreturn != 0 && ???);
|
|
||||||
|
|
||||||
/* Setup to return to the saved syscall return address in
|
/* Setup to return to the saved syscall return address in
|
||||||
* unprivileged mode.
|
* the original mode.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
current_regs[REG_EPC] = rtcb->xcp.sysreturn;
|
current_regs[REG_EPC] = rtcb->xcp.sysreturn;
|
||||||
#error "Missing logic -- need to set for unprivileged mode"
|
#error "Missing logic -- need to restore the original mode"
|
||||||
rtcb->sysreturn = 0;
|
rtcb->sysreturn = 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -267,20 +264,19 @@ int up_swint0(int irq, FAR void *context)
|
|||||||
#ifdef CONFIG_NUTTX_KERNEL
|
#ifdef CONFIG_NUTTX_KERNEL
|
||||||
FAR struct tcb_s *rtcb = sched_self();
|
FAR struct tcb_s *rtcb = sched_self();
|
||||||
|
|
||||||
/* Verify the the SYS call number is within range */
|
/* Verify that the SYS call number is within range */
|
||||||
|
|
||||||
DEBUGASSERT(current_regs[REG_A0] < SYS_maxsyscall);
|
DEBUGASSERT(current_regs[REG_A0] < SYS_maxsyscall);
|
||||||
|
|
||||||
/* Make sure that we got here from an unprivileged thread and that
|
/* Make sure that we got here that there is a no saved syscall
|
||||||
* there is a no saved syscall return address.
|
* return address. We cannot yet handle nested system calls.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#error "Missing logic -- Need to set unprivileged mode"
|
DEBUGASSERT(rtcb->xcp.sysreturn == 0);
|
||||||
DEBUGASSERT(rtcb->xcp.sysreturn == 0 && ???);
|
|
||||||
|
|
||||||
/* Setup to return to dispatch_syscall in privileged mode. */
|
/* Setup to return to dispatch_syscall in privileged mode. */
|
||||||
|
|
||||||
rtcb->sysreturn = regs[REG_EPC]
|
rtcb->sysreturn = regs[REG_EPC];
|
||||||
regs[REG_EPC] = (uint32_t)dispatch_syscall;
|
regs[REG_EPC] = (uint32_t)dispatch_syscall;
|
||||||
#error "Missing logic -- Need to set privileged mode"
|
#error "Missing logic -- Need to set privileged mode"
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user