diff options
Diffstat (limited to 'nuttx/arch/arm/src/armv7-m/up_svcall.c')
-rw-r--r-- | nuttx/arch/arm/src/armv7-m/up_svcall.c | 59 |
1 files changed, 45 insertions, 14 deletions
diff --git a/nuttx/arch/arm/src/armv7-m/up_svcall.c b/nuttx/arch/arm/src/armv7-m/up_svcall.c index 8321cd3bb..8f7efc1da 100644 --- a/nuttx/arch/arm/src/armv7-m/up_svcall.c +++ b/nuttx/arch/arm/src/armv7-m/up_svcall.c @@ -237,9 +237,9 @@ int up_svcall(int irq, FAR void *context) } break; - /* R0=SYS_syscall_return: This a switch context command: + /* R0=SYS_syscall_return: This a syscall return command: * - * void up_sycall_return(void); + * void up_syscall_return(void); * * At this point, the following values are saved in context: * @@ -256,23 +256,54 @@ int up_svcall(int irq, FAR void *context) /* Make sure that there is a saved syscall return address. */ - 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 * the original mode. */ - current_regs[REG_PC] = rtcb->xcp.sysreturn; - current_regs[REG_EXC_RETURN] = rtcb->xcp.excreturn; - rtcb->xcp.sysreturn = 0; + regs[REG_PC] = rtcb->xcp.sysreturn; + 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 for R0 into R2. */ - current_regs[REG_R0] = current_regs[REG_R2]; + regs[REG_R0] = regs[REG_R2]; + } + break; +#endif + + /* R0=SYS_task_start: This a user task start + * + * void up_task_start(main_t taskentry, int argc, FAR char *argv[]) noreturn_function; + * + * At this point, the following values are saved in context: + * + * R0 = SYS_task_start + * R1 = taskentry + * R2 = argc + * R3 = argv + */ + +#ifdef CONFIG_NUTTX_KERNEL + case SYS_task_start: + { + /* Set up to return to the user-space task start-up function in + * unprivileged mode. + */ + + regs[REG_PC] = (uint32_t)USERSPACE->task_startup; + regs[REG_EXC_RETURN] = EXC_RETURN_UNPRIVTHR; + + /* Change the paramter ordering to match the expection of struct + * userpace_s task_startup: + */ + + regs[REG_R0] = regs[REG_R1]; /* Task entry */ + regs[REG_R1] = regs[REG_R2]; /* argc */ + regs[REG_R2] = regs[REG_R3]; /* argv */ } break; #endif @@ -289,7 +320,7 @@ int up_svcall(int irq, FAR void *context) /* Verify that the SYS call number is within range */ - DEBUGASSERT(current_regs[REG_R0] < SYS_maxsyscall); + DEBUGASSERT(regs[REG_R0] < SYS_maxsyscall); /* Make sure that we got here that there is a no saved syscall * return address. We cannot yet handle nested system calls. @@ -299,15 +330,15 @@ int up_svcall(int irq, FAR void *context) /* Setup to return to dispatch_syscall in privileged mode. */ - rtcb->xcp.sysreturn = regs[REG_PC]; - rtcb->xcp.excreturn = current_regs[REG_EXC_RETURN]; + rtcb->xcp.sysreturn = regs[REG_PC]; + rtcb->xcp.excreturn = regs[REG_EXC_RETURN]; - current_regs[REG_PC] = (uint32_t)dispatch_syscall; - current_regs[REG_EXC_RETURN] = EXC_RETURN_PRIVTHR; + regs[REG_PC] = (uint32_t)dispatch_syscall; + regs[REG_EXC_RETURN] = EXC_RETURN_PRIVTHR; /* Offset R0 to account for the reserved values */ - current_regs[REG_R0] -= CONFIG_SYS_RESERVED; + regs[REG_R0] -= CONFIG_SYS_RESERVED; #else slldbg("ERROR: Bad SYS call: %d\n", regs[REG_R0]); #endif |