From b9114bca364df11711df1e525a162d7ae64cba57 Mon Sep 17 00:00:00 2001 From: Alvin Chang Date: Sun, 18 Aug 2024 22:29:38 +0800 Subject: [PATCH] core: riscv: Improve thread user mode record The following steps descript the program flow of kernel context during entering and exiting user mode: 1. thread_enter_user_mode(): prepare user mode context 2. __thread_enter_user_mode(): allocate thread_user_mode_rec from kernel stack, and save kernel RA and callee-saved registers into thread_user_mode_rec. Save kernel SP into thread context. Enter user mode context. If there is an user ecall which should return to kernel mode: 3. ecall_from_user(): Already set kernel SP, GP, and TP. 4. setup_unwind_user_mode(): prepare to return to kernel mode. If there is an user abort: 3. abort_from_user(): Already set kernel SP, GP, and TP. 4. handle_user_mode_panic(): prepare to return to kernel mode. 5. XRET to kernel mode with kernel SP, GP, and TP. 6. thread_unwind_user_mode(): Restore kernel RA and callee-saved registers from thread_user_mode_rec. Thus, it's unnecessary to save kernel SP and GP into thread_user_mode_rec, since they have already set by trap handler and it is unnecessary to set them again in thread_unwind_user_mode(). Also, rename THREAD_USER_MODE_REC_XX to their register names. Signed-off-by: Alvin Chang --- .../include/kernel/thread_private_arch.h | 8 +++--- core/arch/riscv/kernel/asm-defines.c | 10 +++---- core/arch/riscv/kernel/thread_rv.S | 26 +++++++------------ 3 files changed, 17 insertions(+), 27 deletions(-) diff --git a/core/arch/riscv/include/kernel/thread_private_arch.h b/core/arch/riscv/include/kernel/thread_private_arch.h index 48bc2b5e903..9195847d7b6 100644 --- a/core/arch/riscv/include/kernel/thread_private_arch.h +++ b/core/arch/riscv/include/kernel/thread_private_arch.h @@ -51,11 +51,11 @@ struct thread_user_mode_rec { unsigned long pad; /* * x[] is used to save registers for user/kernel context-switching - * 0-3: ra-tp - * 4-6: s0-s1 - * 6-15: s2-s11 + * 0: ra + * 1-2: s0-s1 + * 3-12: s2-s11 */ - unsigned long x[16]; + unsigned long x[13]; }; extern long thread_user_kcode_offset; diff --git a/core/arch/riscv/kernel/asm-defines.c b/core/arch/riscv/kernel/asm-defines.c index 471e5041153..c517b9e7c6e 100644 --- a/core/arch/riscv/kernel/asm-defines.c +++ b/core/arch/riscv/kernel/asm-defines.c @@ -55,14 +55,12 @@ DEFINES /* struct thread_user_mode_rec */ DEFINE(THREAD_USER_MODE_REC_CTX_REGS_PTR, offsetof(struct thread_user_mode_rec, ctx_regs_ptr)); - DEFINE(THREAD_USER_MODE_REC_X1, + DEFINE(THREAD_USER_MODE_REC_RA, offsetof(struct thread_user_mode_rec, x[0])); - DEFINE(THREAD_USER_MODE_REC_X4, + DEFINE(THREAD_USER_MODE_REC_S0, + offsetof(struct thread_user_mode_rec, x[1])); + DEFINE(THREAD_USER_MODE_REC_S2, offsetof(struct thread_user_mode_rec, x[3])); - DEFINE(THREAD_USER_MODE_REC_X8, - offsetof(struct thread_user_mode_rec, x[4])); - DEFINE(THREAD_USER_MODE_REC_X18, - offsetof(struct thread_user_mode_rec, x[6])); DEFINE(THREAD_USER_MODE_REC_SIZE, sizeof(struct thread_user_mode_rec)); /* struct thread_abort_regs */ diff --git a/core/arch/riscv/kernel/thread_rv.S b/core/arch/riscv/kernel/thread_rv.S index ad733a8d7b0..08cfa8f02fd 100644 --- a/core/arch/riscv/kernel/thread_rv.S +++ b/core/arch/riscv/kernel/thread_rv.S @@ -537,30 +537,22 @@ END_FUNC trap_from_user /* * void thread_unwind_user_mode(uint32_t ret, uint32_t exit_status0, - * uint32_t exit_status1); + * uint32_t exit_status1); * See description in thread.h */ FUNC thread_unwind_user_mode , : - /* Store the exit status */ load_xregs sp, THREAD_USER_MODE_REC_CTX_REGS_PTR, REG_A3, REG_A5 sw a1, (a4) sw a2, (a5) - - /* Save user callee regs */ + /* Save user callee-saved regs */ store_xregs a3, THREAD_CTX_REG_S0, REG_S0, REG_S1 store_xregs a3, THREAD_CTX_REG_S2, REG_S2, REG_S11 - store_xregs a3, THREAD_CTX_REG_SP, REG_SP, REG_TP - - /* Restore kernel callee regs */ - mv a1, sp - - load_xregs a1, THREAD_USER_MODE_REC_X1, REG_RA, REG_GP - load_xregs a1, THREAD_USER_MODE_REC_X8, REG_S0, REG_S1 - load_xregs a1, THREAD_USER_MODE_REC_X18, REG_S2, REG_S11 - + /* Restore kernel ra(thread_enter_user_mode()) & callee-saved regs */ + load_xregs sp, THREAD_USER_MODE_REC_RA, REG_RA + load_xregs sp, THREAD_USER_MODE_REC_S0, REG_S0, REG_S1 + load_xregs sp, THREAD_USER_MODE_REC_S2, REG_S2, REG_S11 add sp, sp, THREAD_USER_MODE_REC_SIZE - /* Return from the call of thread_enter_user_mode() */ ret END_FUNC thread_unwind_user_mode @@ -579,9 +571,9 @@ FUNC __thread_enter_user_mode , : */ addi sp, sp, -THREAD_USER_MODE_REC_SIZE store_xregs sp, THREAD_USER_MODE_REC_CTX_REGS_PTR, REG_A0, REG_A2 - store_xregs sp, THREAD_USER_MODE_REC_X1, REG_RA, REG_GP - store_xregs sp, THREAD_USER_MODE_REC_X8, REG_S0, REG_S1 - store_xregs sp, THREAD_USER_MODE_REC_X18, REG_S2, REG_S11 + store_xregs sp, THREAD_USER_MODE_REC_RA, REG_RA + store_xregs sp, THREAD_USER_MODE_REC_S0, REG_S0, REG_S1 + store_xregs sp, THREAD_USER_MODE_REC_S2, REG_S2, REG_S11 /* * Save the kernel stack pointer in the thread context