diff --git a/core/arch/arm/include/kernel/thread_private_arch.h b/core/arch/arm/include/kernel/thread_private_arch.h index 450d4171fae..d52f96b4236 100644 --- a/core/arch/arm/include/kernel/thread_private_arch.h +++ b/core/arch/arm/include/kernel/thread_private_arch.h @@ -191,13 +191,18 @@ void thread_resume_from_rpc(uint32_t thread_id, uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3); /* - * Suspends current thread and temorarily exits to non-secure world. - * This function returns later when non-secure world returns. + * The thread_rpc() function suspends current thread and temporarily exits + * to non-secure world. This function returns later when non-secure world + * returns. * * The purpose of this function is to request services from non-secure * world. */ #define THREAD_RPC_NUM_ARGS 4 +#ifdef ARM64 +void thread_rpc_spsr(uint32_t rv[THREAD_RPC_NUM_ARGS], uint64_t spsr); +void __thread_rpc(uint32_t rv[THREAD_RPC_NUM_ARGS]); + #ifdef CFG_CORE_FFA struct thread_rpc_arg { union { @@ -216,8 +221,18 @@ struct thread_rpc_arg { }; }; -void thread_rpc(struct thread_rpc_arg *rpc_arg); +static inline void thread_rpc(struct thread_rpc_arg *rpc_arg) +{ + __thread_rpc(rpc_arg->pad); +} #else +static inline void thread_rpc(uint32_t rv[THREAD_RPC_NUM_ARGS]) +{ + __thread_rpc(rv); +} +#endif +#endif +#ifdef ARM32 void thread_rpc(uint32_t rv[THREAD_RPC_NUM_ARGS]); #endif diff --git a/core/arch/arm/kernel/abort.c b/core/arch/arm/kernel/abort.c index f35a4064823..72fbfc84f62 100644 --- a/core/arch/arm/kernel/abort.c +++ b/core/arch/arm/kernel/abort.c @@ -359,6 +359,7 @@ static void handle_user_mode_panic(struct abort_info *ai) { struct thread_ctx *tc __maybe_unused = NULL; uint32_t daif = 0; + uint32_t pan_bit = 0; /* * It was a user exception, stop user execution and return @@ -380,9 +381,12 @@ static void handle_user_mode_panic(struct abort_info *ai) ai->regs->apiakey_lo = tc->keys.apia_lo; #endif + if (IS_ENABLED(CFG_PAN) && feat_pan_implemented() && read_pan()) + pan_bit = SPSR_64_PAN; daif = (ai->regs->spsr >> SPSR_32_AIF_SHIFT) & SPSR_32_AIF_MASK; /* XXX what about DAIF_D? */ - ai->regs->spsr = SPSR_64(SPSR_64_MODE_EL1, SPSR_64_MODE_SP_EL0, daif); + ai->regs->spsr = SPSR_64(SPSR_64_MODE_EL1, SPSR_64_MODE_SP_EL0, daif) | + pan_bit; } #endif /*ARM64*/ diff --git a/core/arch/arm/kernel/thread.c b/core/arch/arm/kernel/thread.c index 4720c251e4d..66833b3a086 100644 --- a/core/arch/arm/kernel/thread.c +++ b/core/arch/arm/kernel/thread.c @@ -412,6 +412,22 @@ void thread_resume_from_rpc(uint32_t thread_id, uint32_t a0, uint32_t a1, } #ifdef ARM64 +static uint64_t spsr_from_pstate(void) +{ + uint64_t spsr = SPSR_64(SPSR_64_MODE_EL1, SPSR_64_MODE_SP_EL0, 0); + + spsr |= read_daif(); + if (IS_ENABLED(CFG_PAN) && feat_pan_implemented() && read_pan()) + spsr |= SPSR_64_PAN; + + return spsr; +} + +void __thread_rpc(uint32_t rv[THREAD_RPC_NUM_ARGS]) +{ + thread_rpc_spsr(rv, spsr_from_pstate()); +} + vaddr_t thread_get_saved_thread_sp(void) { struct thread_core_local *l = thread_get_core_local(); @@ -1072,8 +1088,7 @@ static void setup_unwind_user_mode(struct thread_scall_regs *regs) #endif #ifdef ARM64 regs->elr = (uintptr_t)thread_unwind_user_mode; - regs->spsr = SPSR_64(SPSR_64_MODE_EL1, SPSR_64_MODE_SP_EL0, 0); - regs->spsr |= read_daif(); + regs->spsr = spsr_from_pstate(); /* * Regs is the value of stack pointer before calling the SVC * handler. By the addition matches for the reserved space at the diff --git a/core/arch/arm/kernel/thread_optee_smc_a64.S b/core/arch/arm/kernel/thread_optee_smc_a64.S index 541dd257d7a..1b08414c2d6 100644 --- a/core/arch/arm/kernel/thread_optee_smc_a64.S +++ b/core/arch/arm/kernel/thread_optee_smc_a64.S @@ -177,12 +177,8 @@ FUNC thread_std_smc_entry , : panic_at_smc_return END_FUNC thread_std_smc_entry -/* void thread_rpc(uint32_t rv[THREAD_RPC_NUM_ARGS]) */ -FUNC thread_rpc , : - /* Read daif and create an SPSR */ - mrs x1, daif - orr x1, x1, #(SPSR_64_MODE_EL1 << SPSR_64_MODE_EL_SHIFT) - +/* void thread_rpc_spsr(uint32_t rv[THREAD_RPC_NUM_ARGS], uint64_t spsr) */ +FUNC thread_rpc_spsr , : /* Mask all maskable exceptions before switching to temporary stack */ msr daifset, #DAIFBIT_ALL push x0, xzr @@ -236,8 +232,8 @@ FUNC thread_rpc , : pop x16, xzr /* Get pointer to rv[] */ store_wregs x16, 0, 0, 3 /* Store w0-w3 into rv[] */ ret -END_FUNC thread_rpc -DECLARE_KEEP_PAGER thread_rpc +END_FUNC thread_rpc_spsr +DECLARE_KEEP_PAGER thread_rpc_spsr /* * void thread_foreign_intr_exit(uint32_t thread_index) diff --git a/core/arch/arm/kernel/thread_spmc_a64.S b/core/arch/arm/kernel/thread_spmc_a64.S index b15ef918c8a..83488f66eea 100644 --- a/core/arch/arm/kernel/thread_spmc_a64.S +++ b/core/arch/arm/kernel/thread_spmc_a64.S @@ -115,12 +115,8 @@ FUNC spmc_sp_thread_entry , : END_FUNC spmc_sp_thread_entry #endif -/* void thread_rpc(struct thread_rpc_arg *rpc_arg) */ -FUNC thread_rpc , : - /* Read daif and create an SPSR */ - mrs x1, daif - orr x1, x1, #(SPSR_64_MODE_EL1 << SPSR_64_MODE_EL_SHIFT) - +/* void thread_rpc_spsr(uint32_t rv[THREAD_RPC_NUM_ARGS], uint64_t spsr) */ +FUNC thread_rpc_spsr , : /* Mask all maskable exceptions before switching to temporary stack */ msr daifset, #DAIFBIT_ALL push x0, xzr @@ -176,7 +172,7 @@ FUNC thread_rpc , : pop x16, xzr /* Get pointer to rv[] */ store_wregs x16, 0, 0, 3 /* Store w0-w3 into rv[] */ ret -END_FUNC thread_rpc +END_FUNC thread_rpc_spsr /* * void thread_foreign_intr_exit(uint32_t thread_index)