From 24c931c220bd314553b5bf663735327acff53206 Mon Sep 17 00:00:00 2001 From: Ville Juven Date: Tue, 1 Oct 2024 13:39:42 +0300 Subject: [PATCH] arm64_task/pthread_start: Set sp_el0 upon starting user process As the handling of sp_el0 was moved from the context switch routine to exception entry/exit, we must set sp_el0 explicitly when the user process is first started. --- arch/arm64/src/common/arm64_internal.h | 2 +- arch/arm64/src/common/arm64_pthread_start.c | 4 +++- arch/arm64/src/common/arm64_task_start.c | 4 +++- arch/arm64/src/common/arm64_vectors.S | 12 +++++++----- 4 files changed, 14 insertions(+), 8 deletions(-) diff --git a/arch/arm64/src/common/arm64_internal.h b/arch/arm64/src/common/arm64_internal.h index 508a4e44bc915..de5bc209806d2 100644 --- a/arch/arm64/src/common/arm64_internal.h +++ b/arch/arm64/src/common/arm64_internal.h @@ -261,7 +261,7 @@ EXTERN uint8_t g_idle_topstack[]; /* End+1 of heap */ void arm64_new_task(struct tcb_s *tak_new); void arm64_jump_to_user(uint64_t entry, uint64_t x0, uint64_t x1, - uint64_t *regs) noreturn_function; + uint64_t sp_el0, uint64_t *regs) noreturn_function; /* Low level initialization provided by chip logic */ diff --git a/arch/arm64/src/common/arm64_pthread_start.c b/arch/arm64/src/common/arm64_pthread_start.c index 8132884cf8394..3b693455b858c 100644 --- a/arch/arm64/src/common/arm64_pthread_start.c +++ b/arch/arm64/src/common/arm64_pthread_start.c @@ -68,6 +68,8 @@ void up_pthread_start(pthread_trampoline_t startup, pthread_startroutine_t entrypt, pthread_addr_t arg) { + struct tcb_s *rtcb = this_task(); + /* Set up to enter the user-space pthread start-up function in * unprivileged mode. We need: * @@ -78,7 +80,7 @@ void up_pthread_start(pthread_trampoline_t startup, */ arm64_jump_to_user((uint64_t)startup, (uint64_t)entrypt, (uint64_t)arg, - this_task()->xcp.initregs); + (uint64_t)rtcb->xcp.ustkptr, rtcb->xcp.initregs); } #endif /* !CONFIG_BUILD_FLAT && __KERNEL__ && !CONFIG_DISABLE_PTHREAD */ diff --git a/arch/arm64/src/common/arm64_task_start.c b/arch/arm64/src/common/arm64_task_start.c index 0d20f693e5a04..a0219a5cf6850 100644 --- a/arch/arm64/src/common/arm64_task_start.c +++ b/arch/arm64/src/common/arm64_task_start.c @@ -65,6 +65,8 @@ void up_task_start(main_t taskentry, int argc, char *argv[]) { + struct tcb_s *rtcb = this_task(); + /* Set up to return to the user-space _start function in * unprivileged mode. We need: * @@ -75,7 +77,7 @@ void up_task_start(main_t taskentry, int argc, char *argv[]) */ arm64_jump_to_user((uint64_t)taskentry, (uint64_t)argc, (uint64_t)argv, - this_task()->xcp.initregs); + (uint64_t)rtcb->xcp.ustkptr, rtcb->xcp.initregs); } #endif /* !CONFIG_BUILD_FLAT */ diff --git a/arch/arm64/src/common/arm64_vectors.S b/arch/arm64/src/common/arm64_vectors.S index e23bbcff916aa..0c0605ca72b8b 100644 --- a/arch/arm64/src/common/arm64_vectors.S +++ b/arch/arm64/src/common/arm64_vectors.S @@ -107,10 +107,11 @@ SECTION_FUNC(text, up_saveusercontext) * the kernel is ready to give control to the user task in user space. * * arm64_jump_to_user(entry, x0, x1, regs) - * entry: process entry point - * x0: parameter 0 for process - * x1: parameter 1 for process - * regs: integer register save area to use + * entry: process entry point + * x0: parameter 0 for process + * x1: parameter 1 for process + * sp_el0: user stack pointer + * regs: integer register save area to use * ****************************************************************************/ @@ -118,10 +119,11 @@ SECTION_FUNC(text, up_saveusercontext) GTEXT(arm64_jump_to_user) SECTION_FUNC(text, arm64_jump_to_user) msr daifset, #IRQ_DAIF_MASK - mov sp, x3 + mov sp, x4 str x0, [sp, #8 * REG_ELR] str x1, [sp, #8 * REG_X0] str x2, [sp, #8 * REG_X1] + str x3, [sp, #8 * REG_SP_EL0] mrs x0, spsr_el1 and x0, x0, #~SPSR_MODE_MASK #orr x0, x0, #SPSR_MODE_EL0T # EL0T=0x00, out of range for orr