diff --git a/core/arch/arm/kernel/link_dummies.c b/core/arch/arm/kernel/link_dummies.c index 373db8d2edd..12b7f9acf37 100644 --- a/core/arch/arm/kernel/link_dummies.c +++ b/core/arch/arm/kernel/link_dummies.c @@ -22,9 +22,11 @@ TEE_Result __section(".text.dummy.init_teecore") init_teecore(void) return TEE_SUCCESS; } -void __section(".text.dummy.__thread_std_smc_entry") -__thread_std_smc_entry(struct thread_smc_args *args __unused) +uint32_t __section(".text.dummy.__thread_std_smc_entry") +__thread_std_smc_entry(uint32_t a0 __unused, uint32_t a1 __unused, + uint32_t a2 __unused, uint32_t a3 __unused) { + return 0; } void __section(".text.dummy.__wq_rpc") __wq_rpc(uint32_t func __unused, int id __unused, diff --git a/core/arch/arm/kernel/thread_optee_smc.c b/core/arch/arm/kernel/thread_optee_smc.c index f6d0e73bce4..8c068862626 100644 --- a/core/arch/arm/kernel/thread_optee_smc.c +++ b/core/arch/arm/kernel/thread_optee_smc.c @@ -153,44 +153,44 @@ static struct mobj *map_cmd_buffer(paddr_t pargi __unused, } #endif /*CFG_CORE_DYN_SHM*/ -static void std_smc_entry(struct thread_smc_args *smc_args) +static uint32_t std_smc_entry(uint32_t a0, uint32_t a1, uint32_t a2, + uint32_t a3 __unused) { paddr_t parg = 0; struct optee_msg_arg *arg = NULL; uint32_t num_params = 0; struct mobj *mobj = NULL; + uint32_t rv = 0; - if (smc_args->a0 != OPTEE_SMC_CALL_WITH_ARG) { - EMSG("Unknown SMC 0x%" PRIx64, (uint64_t)smc_args->a0); + if (a0 != OPTEE_SMC_CALL_WITH_ARG) { + EMSG("Unknown SMC 0x%"PRIx32, a0); DMSG("Expected 0x%x", OPTEE_SMC_CALL_WITH_ARG); - smc_args->a0 = OPTEE_SMC_RETURN_EBADCMD; - return; + return OPTEE_SMC_RETURN_EBADCMD; } - parg = (uint64_t)smc_args->a1 << 32 | smc_args->a2; + parg = reg_pair_to_64(a1, a2); /* Check if this region is in static shared space */ if (core_pbuf_is(CORE_MEM_NSEC_SHM, parg, sizeof(struct optee_msg_arg))) { mobj = get_cmd_buffer(parg, &num_params); } else { - if (parg & SMALL_PAGE_MASK) { - smc_args->a0 = OPTEE_SMC_RETURN_EBADADDR; - return; - } + if (parg & SMALL_PAGE_MASK) + return OPTEE_SMC_RETURN_EBADADDR; mobj = map_cmd_buffer(parg, &num_params); } if (!mobj || !ALIGNMENT_IS_OK(parg, struct optee_msg_arg)) { EMSG("Bad arg address 0x%" PRIxPA, parg); - smc_args->a0 = OPTEE_SMC_RETURN_EBADADDR; mobj_free(mobj); - return; + return OPTEE_SMC_RETURN_EBADADDR; } arg = mobj_get_va(mobj, 0); assert(arg && mobj_is_nonsec(mobj)); - smc_args->a0 = tee_entry_std(arg, num_params); + rv = tee_entry_std(arg, num_params); mobj_free(mobj); + + return rv; } /* @@ -199,14 +199,17 @@ static void std_smc_entry(struct thread_smc_args *smc_args) * Note: this function is weak just to make it possible to exclude it from * the unpaged area. */ -void __weak __thread_std_smc_entry(struct thread_smc_args *args) +uint32_t __weak __thread_std_smc_entry(uint32_t a0, uint32_t a1, uint32_t a2, + uint32_t a3) { + uint32_t rv = 0; + #ifdef CFG_VIRTUALIZATION virt_on_stdcall(); #endif - std_smc_entry(args); + rv = std_smc_entry(a0, a1, a2, a3); - if (args->a0 == OPTEE_SMC_RETURN_OK) { + if (rv == OPTEE_SMC_RETURN_OK) { struct thread_ctx *thr = threads + thread_get_id(); tee_fs_rpc_cache_clear(&thr->tsd); @@ -217,6 +220,8 @@ void __weak __thread_std_smc_entry(struct thread_smc_args *args) thr->rpc_mobj = NULL; } } + + return rv; } bool thread_disable_prealloc_rpc_cache(uint64_t *cookie) diff --git a/core/arch/arm/kernel/thread_optee_smc_a32.S b/core/arch/arm/kernel/thread_optee_smc_a32.S index cb7fbfafa65..af6e8073ea0 100644 --- a/core/arch/arm/kernel/thread_optee_smc_a32.S +++ b/core/arch/arm/kernel/thread_optee_smc_a32.S @@ -161,17 +161,8 @@ KEEP_PAGER thread_vector_table FUNC thread_std_smc_entry , : UNWIND( .fnstart) UNWIND( .cantunwind) - /* Pass r0-r7 in a struct thread_smc_args */ - push {r0-r7} - mov r0, sp bl __thread_std_smc_entry - /* - * Load the returned r0-r3 into preserved registers and skip the - * "returned" r4-r7 since they will not be returned to normal - * world. - */ - pop {r4-r7} - add sp, #(4 * 4) + mov r4, r0 /* Save return value for later */ /* Disable interrupts before switching to temporary stack */ cpsid aif @@ -182,9 +173,9 @@ UNWIND( .cantunwind) ldr r0, =TEESMC_OPTEED_RETURN_CALL_DONE mov r1, r4 - mov r2, r5 - mov r3, r6 - mov r4, r7 + mov r2, #0 + mov r3, #0 + mov r4, #0 smc #0 b . /* SMC should not return */ UNWIND( .fnend) diff --git a/core/arch/arm/kernel/thread_optee_smc_a64.S b/core/arch/arm/kernel/thread_optee_smc_a64.S index 49aa05b36a2..0019baf7d5c 100644 --- a/core/arch/arm/kernel/thread_optee_smc_a64.S +++ b/core/arch/arm/kernel/thread_optee_smc_a64.S @@ -133,21 +133,8 @@ END_FUNC thread_vector_table KEEP_PAGER thread_vector_table FUNC thread_std_smc_entry , : - /* pass x0-x7 in a struct thread_smc_args */ - sub sp, sp, #THREAD_SMC_ARGS_SIZE - store_xregs sp, THREAD_SMC_ARGS_X0, 0, 7 - mov x0, sp - - /* Call the registered handler */ bl __thread_std_smc_entry - - /* - * Load the returned x0-x3 into preserved registers and skip the - * "returned" x4-x7 since they will not be returned to normal - * world. - */ - load_xregs sp, THREAD_SMC_ARGS_X0, 20, 23 - add sp, sp, #THREAD_SMC_ARGS_SIZE + mov w20, w0 /* Save return value for later */ /* Mask all maskable exceptions before switching to temporary stack */ msr daifset, #DAIFBIT_ALL @@ -157,10 +144,10 @@ FUNC thread_std_smc_entry , : bl thread_state_free ldr x0, =TEESMC_OPTEED_RETURN_CALL_DONE - mov x1, x20 - mov x2, x21 - mov x3, x22 - mov x4, x23 + mov w1, w20 + mov x2, #0 + mov x3, #0 + mov x4, #0 smc #0 b . /* SMC should not return */ END_FUNC thread_std_smc_entry diff --git a/core/arch/arm/kernel/thread_private.h b/core/arch/arm/kernel/thread_private.h index cf9153ae210..1fbd13fe77e 100644 --- a/core/arch/arm/kernel/thread_private.h +++ b/core/arch/arm/kernel/thread_private.h @@ -147,8 +147,16 @@ void thread_excp_vect_workaround(void); void thread_excp_vect_workaround_a15(void); void thread_excp_vect_end(void); -/* Handles a stdcall, r0-r7 holds the parameters */ -void thread_std_smc_entry(void); +/* + * Assembly function as the first function in a thread. Handles a stdcall, + * a0-a3 holds the parameters. Hands over to __thread_std_smc_entry() when + * everything is set up and does some post processing once + * __thread_std_smc_entry() returns. + */ +void thread_std_smc_entry(uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3); +uint32_t __thread_std_smc_entry(uint32_t a0, uint32_t a1, uint32_t a2, + uint32_t a3); + /* * Resumes execution of currently active thread by restoring context and @@ -204,8 +212,6 @@ void thread_set_fiq_sp(vaddr_t sp); /* Checks stack canaries */ void thread_check_canaries(void); -void __thread_std_smc_entry(struct thread_smc_args *args); - void thread_alloc_and_run(uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3); void thread_resume_from_rpc(uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4, uint32_t a5);