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:
patacongo 2013-03-12 21:53:18 +00:00
parent 8a44d95b14
commit 8159804f9c
3 changed files with 33 additions and 30 deletions

View File

@ -127,8 +127,11 @@ struct xcptcontext
#endif
#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;
#endif

View File

@ -1,7 +1,7 @@
/****************************************************************************
* 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>
*
* 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",
regs[REG_R8], regs[REG_R9], regs[REG_R10], regs[REG_R11],
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 */
@ -246,23 +250,22 @@ int up_svcall(int irq, FAR void *context)
{
struct tcb_s *rtcb = sched_self();
/* Make sure that we got here from a privileged thread and
* that there is a saved syscall return address.
*/
/* Make sure that there is a saved syscall return address. */
DEBUGASSERT(rtcb->xcp.sysreturn != 0 &&
regs[REG_EXC_RETURN] == EXC_RETURN_PRIVTHR);
svcdbg("sysreturn: %08x excreturn: %08x\n",
rtcb->xcp.sysreturn, rtcb->xcp.excreturn);
DEBUGASSERT(rtcb->xcp.sysreturn != 0);
/* 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_EXC_RETURN] = EXC_RETURN_UNPRIVTHR;
current_regs[REG_EXC_RETURN] = rtcb->xcp.excreturn;
rtcb->xcp.sysreturn = 0;
/* 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];
@ -280,21 +283,22 @@ int up_svcall(int irq, FAR void *context)
#ifdef CONFIG_NUTTX_KERNEL
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);
/* Make sure that we got here from a unprivileged thread and that
* there is a no saved syscall return address.
/* Make sure that we got here that there is a no saved syscall
* return address. We cannot yet handle nested system calls.
*/
DEBUGASSERT(rtcb->xcp.sysreturn == 0 &&
regs[REG_EXC_RETURN] == EXC_RETURN_UNPRIVTHR);
DEBUGASSERT(rtcb->xcp.sysreturn == 0);
/* Setup to return to dispatch_syscall in privileged mode. */
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;
/* Offset R0 to account for the reserved values */

View File

@ -239,19 +239,16 @@ int up_swint0(int irq, FAR void *context)
{
struct tcb_s *rtcb = sched_self();
/* Make sure that we got here from a privileged thread and
* that there is a saved syscall return address.
*/
/* Make sure 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
* unprivileged mode.
* the original mode.
*/
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;
}
break;
@ -267,20 +264,19 @@ int up_swint0(int irq, FAR void *context)
#ifdef CONFIG_NUTTX_KERNEL
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);
/* Make sure that we got here from an unprivileged thread and that
* there is a no saved syscall return address.
/* Make sure that we got here that there is a no saved syscall
* 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. */
rtcb->sysreturn = regs[REG_EPC]
rtcb->sysreturn = regs[REG_EPC];
regs[REG_EPC] = (uint32_t)dispatch_syscall;
#error "Missing logic -- Need to set privileged mode"