From 256ff9a480238dfd1d30b7dfb3d61835991b3ee7 Mon Sep 17 00:00:00 2001 From: patacongo Date: Thu, 14 Mar 2013 22:44:06 +0000 Subject: Switch to user-mode before starting a new task git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@5742 42af7a65-404d-4744-a932-0658087f49c3 --- nuttx/arch/arm/src/armv6-m/svcall.h | 13 +++++-- nuttx/arch/arm/src/armv6-m/up_initialstate.c | 23 +++--------- nuttx/arch/arm/src/armv6-m/up_svcall.c | 55 ++++++++++++++++++++++------ 3 files changed, 59 insertions(+), 32 deletions(-) (limited to 'nuttx/arch/arm/src/armv6-m') diff --git a/nuttx/arch/arm/src/armv6-m/svcall.h b/nuttx/arch/arm/src/armv6-m/svcall.h index 46a385631..f453cad55 100644 --- a/nuttx/arch/arm/src/armv6-m/svcall.h +++ b/nuttx/arch/arm/src/armv6-m/svcall.h @@ -57,9 +57,9 @@ #ifdef CONFIG_NUTTX_KERNEL # ifndef CONFIG_SYS_RESERVED -# error "CONFIG_SYS_RESERVED must be defined to the value 4" -# elif CONFIG_SYS_RESERVED != 4 -# error "CONFIG_SYS_RESERVED must have the value 4" +# error "CONFIG_SYS_RESERVED must be defined to the value 5" +# elif CONFIG_SYS_RESERVED != 5 +# error "CONFIG_SYS_RESERVED must have the value 5" # endif #endif @@ -93,6 +93,13 @@ */ #define SYS_syscall_return (3) + +/* SYS call 3: + * + * void up_task_start(main_t taskentry, int argc, FAR char *argv[]) noreturn_function; + */ + +#define SYS_task_start (4) #endif /************************************************************************************ diff --git a/nuttx/arch/arm/src/armv6-m/up_initialstate.c b/nuttx/arch/arm/src/armv6-m/up_initialstate.c index 3e7e3a48f..646d148c1 100644 --- a/nuttx/arch/arm/src/armv6-m/up_initialstate.c +++ b/nuttx/arch/arm/src/armv6-m/up_initialstate.c @@ -126,26 +126,13 @@ void up_initial_state(struct tcb_s *tcb) #endif #endif /* CONFIG_PIC */ - /* Set privileged- or unprivileged-mode, depending on how NuttX is - * configured and what kind of thread is being started. + /* All tasks start via a stub function in kernel space. So all + * tasks must start in privileged thread mode. If CONFIG_NUTTX_KERNEL + * is defined, then that stub function will switch to unprivileged + * mode before transferring control to the user task. */ -#ifdef CONFIG_NUTTX_KERNEL - if ((tcb->flags & TCB_FLAG_TTYPE_MASK) != TCB_FLAG_TTYPE_KERNEL) - { - /* It is a normal task or a pthread. Set user mode */ - - xcp->regs[REG_EXC_RETURN] = EXC_RETURN_UNPRIVTHR; - } - else - { - /* If the kernel build is not selected -OR- if this is a kernel - * thread, then start it in privileged thread mode. - */ - - xcp->regs[REG_EXC_RETURN] = EXC_RETURN_PRIVTHR; - } -#endif /* CONFIG_NUTTX_KERNEL */ + xcp->regs[REG_EXC_RETURN] = EXC_RETURN_PRIVTHR; /* Enable or disable interrupts, based on user configuration */ diff --git a/nuttx/arch/arm/src/armv6-m/up_svcall.c b/nuttx/arch/arm/src/armv6-m/up_svcall.c index b1bf1e4ec..f36e92297 100644 --- a/nuttx/arch/arm/src/armv6-m/up_svcall.c +++ b/nuttx/arch/arm/src/armv6-m/up_svcall.c @@ -232,9 +232,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: * @@ -260,15 +260,48 @@ int up_svcall(int irq, FAR void *context) * unprivileged mode. */ - current_regs[REG_PC] = rtcb->xcp.sysreturn; - current_regs[REG_EXC_RETURN] = EXC_RETURN_UNPRIVTHR; - rtcb->xcp.sysreturn = 0; + regs[REG_PC] = rtcb->xcp.sysreturn; + regs[REG_EXC_RETURN] = EXC_RETURN_UNPRIVTHR; + rtcb->xcp.sysreturn = 0; /* The return value must be in R0-R1. dispatch_syscall() temporarily * moved the value to 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 @@ -285,7 +318,7 @@ int up_svcall(int irq, FAR void *context) /* Verify the 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 from an unprivileged thread and that * there is a no saved syscall return address. @@ -296,13 +329,13 @@ int up_svcall(int irq, FAR void *context) /* Setup to return to dispatch_syscall in privileged mode. */ - rtcb->xcp.sysreturn = regs[REG_PC]; - regs[REG_PC] = (uint32_t)dispatch_syscall; - current_regs[REG_EXC_RETURN] = EXC_RETURN_PRIVTHR; + rtcb->xcp.sysreturn = regs[REG_PC]; + 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 -- cgit v1.2.3