Skip to content

Commit

Permalink
core: __thread_std_smc_entry() takes arguments by value
Browse files Browse the repository at this point in the history
__thread_std_smc_entry() and thread_std_smc_entry() takes their
arguments by value instead of a structure containing all the registers.
The arguments are also reduced to only allow the four first 32-bit
registers, r0-r3 or w0-w3.  The returned values is reduced to a single
32-bit value. This saves a bit of stack space but also makes it more
clear which registers are passed back and forth.

Acked-by: Jerome Forissier <[email protected]>
Signed-off-by: Jens Wiklander <[email protected]>
  • Loading branch information
jenswi-linaro authored and jforissier committed Aug 26, 2019
1 parent e9f46c7 commit 6e558fa
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 53 deletions.
6 changes: 4 additions & 2 deletions core/arch/arm/kernel/link_dummies.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
37 changes: 21 additions & 16 deletions core/arch/arm/kernel/thread_optee_smc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

/*
Expand All @@ -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);
Expand All @@ -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)
Expand Down
17 changes: 4 additions & 13 deletions core/arch/arm/kernel/thread_optee_smc_a32.S
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
Expand Down
23 changes: 5 additions & 18 deletions core/arch/arm/kernel/thread_optee_smc_a64.S
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand 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
Expand Down
14 changes: 10 additions & 4 deletions core/arch/arm/kernel/thread_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit 6e558fa

Please sign in to comment.