diff --git a/arch/arm64/include/irq.h b/arch/arm64/include/irq.h index 933ded64667..debac2522a0 100644 --- a/arch/arm64/include/irq.h +++ b/arch/arm64/include/irq.h @@ -280,6 +280,9 @@ struct xcptcontext /* task stack reg context */ uint64_t *regs; +#ifndef CONFIG_BUILD_FLAT + uint64_t *initregs; +#endif /* task context, for signal process */ diff --git a/arch/arm64/src/common/arm64_initialstate.c b/arch/arm64/src/common/arm64_initialstate.c index b61f01b3b26..6e10432a436 100644 --- a/arch/arm64/src/common/arm64_initialstate.c +++ b/arch/arm64/src/common/arm64_initialstate.c @@ -108,6 +108,10 @@ void arm64_new_task(struct tcb_s * tcb) pinitctx->tpidr_el1 = (uint64_t)tcb; tcb->xcp.regs = (uint64_t *)pinitctx; + +#ifndef CONFIG_BUILD_FLAT + tcb->xcp.initregs = tcb->xcp.regs; +#endif } /**************************************************************************** diff --git a/arch/arm64/src/common/arm64_pthread_start.c b/arch/arm64/src/common/arm64_pthread_start.c index f063c9b2848..db80db228b6 100644 --- a/arch/arm64/src/common/arm64_pthread_start.c +++ b/arch/arm64/src/common/arm64_pthread_start.c @@ -68,8 +68,11 @@ void up_pthread_start(pthread_trampoline_t startup, pthread_startroutine_t entrypt, pthread_addr_t arg) { - struct tcb_s *tcb = this_task(); - uint64_t spsr; + uint64_t *regs = this_task()->xcp.initregs; + + /* This must be performed atomically, the C-section ends upon user entry */ + + enter_critical_section(); /* Set up to enter the user-space pthread start-up function in * unprivileged mode. We need: @@ -80,11 +83,10 @@ void up_pthread_start(pthread_trampoline_t startup, * SPSR = user mode */ - tcb->xcp.regs[REG_ELR] = (uint64_t)startup; - tcb->xcp.regs[REG_X0] = (uint64_t)entrypt; - tcb->xcp.regs[REG_X1] = (uint64_t)arg; - spsr = tcb->xcp.regs[REG_SPSR] & ~SPSR_MODE_MASK; - tcb->xcp.regs[REG_SPSR] = spsr | SPSR_MODE_EL0T; + regs[REG_ELR] = (uint64_t)startup; + regs[REG_X0] = (uint64_t)entrypt; + regs[REG_X1] = (uint64_t)arg; + regs[REG_SPSR] = (regs[REG_SPSR] & ~SPSR_MODE_MASK) | SPSR_MODE_EL0T; /* Fully unwind the kernel stack and drop to user space */ @@ -94,8 +96,8 @@ void up_pthread_start(pthread_trampoline_t startup, "mov sp, x0\n" /* Stack pointer = context */ "b arm64_exit_exception\n" : - : "r" (tcb->xcp.regs) - : "memory" + : "r" (regs) + : "x0", "memory" ); PANIC(); diff --git a/arch/arm64/src/common/arm64_task_start.c b/arch/arm64/src/common/arm64_task_start.c index fd91e7b378e..5e3501eee6f 100644 --- a/arch/arm64/src/common/arm64_task_start.c +++ b/arch/arm64/src/common/arm64_task_start.c @@ -65,8 +65,11 @@ void up_task_start(main_t taskentry, int argc, char *argv[]) { - struct tcb_s *tcb = this_task(); - uint64_t spsr; + uint64_t *regs = this_task()->xcp.initregs; + + /* This must be performed atomically, the C-section ends upon user entry */ + + enter_critical_section(); /* Set up to return to the user-space _start function in * unprivileged mode. We need: @@ -77,11 +80,10 @@ void up_task_start(main_t taskentry, int argc, char *argv[]) * SPSR = user mode */ - tcb->xcp.regs[REG_ELR] = (uint64_t)taskentry; - tcb->xcp.regs[REG_X0] = (uint64_t)argc; - tcb->xcp.regs[REG_X1] = (uint64_t)argv; - spsr = tcb->xcp.regs[REG_SPSR] & ~SPSR_MODE_MASK; - tcb->xcp.regs[REG_SPSR] = spsr | SPSR_MODE_EL0T; + regs[REG_ELR] = (uint64_t)taskentry; + regs[REG_X0] = (uint64_t)argc; + regs[REG_X1] = (uint64_t)argv; + regs[REG_SPSR] = (regs[REG_SPSR] & ~SPSR_MODE_MASK) | SPSR_MODE_EL0T; /* Fully unwind the kernel stack and drop to user space */ @@ -91,8 +93,8 @@ void up_task_start(main_t taskentry, int argc, char *argv[]) "mov sp, x0\n" /* Stack pointer = context */ "b arm64_exit_exception\n" : - : "r" (tcb->xcp.regs) - : "memory" + : "r" (regs) + : "x0", "memory" ); PANIC();