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
/* Mask all maskable exceptions before switching to temporary stack */
msr daifset, #DAIFBIT_ALL
bl thread_get_tmp_sp
mov sp, x0
bl thread_state_free
ldr x0, =TEESMC_OPTEED_RETURN_CALL_DONE
mov x1, x20
mov x2, x21
mov x3, x22
mov x4, x23
smc #0
b . /* SMC should not return */
END_FUNC thread_std_smc_entry
和fast_smc 类是std_smc的入口函数如下:
LOCAL_FUNC vector_std_smc_entry , :
sub sp, sp, #THREAD_SMC_ARGS_SIZE
store_xregs sp, THREAD_SMC_ARGS_X0, 0, 7
mov x0, sp
bl thread_handle_std_smc
/*
* Normally thread_handle_std_smc() should return via
* thread_exit(), thread_rpc(), but if thread_handle_std_smc()
* hasn't switched stack (error detected) it will do a normal "C"
* return.
*/
load_xregs sp, THREAD_SMC_ARGS_X0, 1, 8
add sp, sp, #THREAD_SMC_ARGS_SIZE
ldr x0, =TEESMC_OPTEED_RETURN_CALL_DONE
smc #0
b . /* SMC should not return */
END_FUNC vector_std_smc_entry
在vector_std_smc_entry 中调用thread_handle_std_smc
void thread_handle_std_smc(struct thread_smc_args *args)
{
thread_check_canaries();
if (args->a0 == OPTEE_SMC_CALL_RETURN_FROM_RPC)
thread_resume_from_rpc(args);
else
thread_alloc_and_run(args);
}
由于是第一次因此args->a0 不等于OPTEE_SMC_CALL_RETURN_FROM_RPC,因此走thread_alloc_and_run
static void thread_alloc_and_run(struct thread_smc_args *args)
{
size_t n;
struct thread_core_local *l = thread_get_core_local();
bool found_thread = false;
assert(l->curr_thread == -1);
//通过spin lock 保护,找到一个可以运行的thread,从这里看出optee里面的thread都是预先申请好的,在使用的时候需要遍历threads 找到一个state是THREAD_STATE_FREE的才可以使用
lock_global();
for (n = 0; n < CFG_NUM_THREADS; n++) {
if (threads[n].state == THREAD_STATE_FREE) {
threads[n].state = THREAD_STATE_ACTIVE;
found_thread = true;
break;
}
}
unlock_global();
//如果没有知道free thread就直接退出了
if (!found_thread) {
args->a0 = OPTEE_SMC_RETURN_ETHREAD_LIMIT;
return;
}
l->curr_thread = n;
threads[n].flags = 0;
//设置thread 要执行的函数
init_regs(threads + n, args);
/* Save Hypervisor Client ID */
threads[n].hyp_clnt_id = args->a7;
thread_lazy_save_ns_vfp();
//执行thread
thread_resume(&threads[n].regs);
}
static void init_regs(struct thread_ctx *thread,
struct thread_smc_args *args)
{
thread->regs.pc = (uint64_t)thread_std_smc_entry;
/*
* Stdcalls starts in SVC mode with masked foreign interrupts, masked
* Asynchronous abort and unmasked native interrupts.
*/
thread->regs.cpsr = SPSR_64(SPSR_64_MODE_EL1, SPSR_64_MODE_SP_EL0,
THREAD_EXCP_FOREIGN_INTR | DAIFBIT_ABT);
/* Reinitialize stack pointer */
thread->regs.sp = thread->stack_va_end;
/*
* Copy arguments into context. This will make the
* arguments appear in x0-x7 when thread is started.
*/
thread->regs.x[0] = args->a0;
thread->regs.x[1] = args->a1;
thread->regs.x[2] = args->a2;
thread->regs.x[3] = args->a3;
thread->regs.x[4] = args->a4;
thread->regs.x[5] = args->a5;
thread->regs.x[6] = args->a6;
thread->regs.x[7] = args->a7;
/* Set up frame pointer as per the Aarch64 AAPCS */
thread->regs.x[29] = 0;
}
在init_regs中通过thread->regs.pc = (uint64_t)thread_std_smc_entry; 来设定这个thread执行函数是thread_std_smc_entry
void __thread_std_smc_entry(struct thread_smc_args *args)
{
thread_std_smc_handler_ptr(args);
if (args->a0 == OPTEE_SMC_RETURN_OK) {
struct thread_ctx *thr = threads + thread_get_id();
tee_fs_rpc_cache_clear(&thr->tsd);
if (!thread_prealloc_rpc_cache) {
thread_rpc_free_arg(thr->rpc_carg);
thr->rpc_carg = 0;
thr->rpc_arg = 0;
}
}
}
执行thread_std_smc_handler_ptr。这个函数是在init_handles中赋值的,是由个个厂家自己实现的,参考fast_smc 一文中的说明
/* 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
/* Mask all maskable exceptions before switching to temporary stack */
msr daifset, #DAIFBIT_ALL
bl thread_get_tmp_sp
mov sp, x0
bl thread_state_free
ldr x0, =TEESMC_OPTEED_RETURN_CALL_DONE
mov x1, x20
mov x2, x21
mov x3, x22
mov x4, x23
smc #0
b . /* SMC should not return */
END_FUNC thread_std_smc_entry
和fast_smc 类是std_smc的入口函数如下:
LOCAL_FUNC vector_std_smc_entry , :
sub sp, sp, #THREAD_SMC_ARGS_SIZE
store_xregs sp, THREAD_SMC_ARGS_X0, 0, 7
mov x0, sp
bl thread_handle_std_smc
/*
* Normally thread_handle_std_smc() should return via
* thread_exit(), thread_rpc(), but if thread_handle_std_smc()
* hasn't switched stack (error detected) it will do a normal "C"
* return.
*/
load_xregs sp, THREAD_SMC_ARGS_X0, 1, 8
add sp, sp, #THREAD_SMC_ARGS_SIZE
ldr x0, =TEESMC_OPTEED_RETURN_CALL_DONE
smc #0
b . /* SMC should not return */
END_FUNC vector_std_smc_entry
在vector_std_smc_entry 中调用thread_handle_std_smc
void thread_handle_std_smc(struct thread_smc_args *args)
{
thread_check_canaries();
if (args->a0 == OPTEE_SMC_CALL_RETURN_FROM_RPC)
thread_resume_from_rpc(args);
else
thread_alloc_and_run(args);
}
由于是第一次因此args->a0 不等于OPTEE_SMC_CALL_RETURN_FROM_RPC,因此走thread_alloc_and_run
static void thread_alloc_and_run(struct thread_smc_args *args)
{
size_t n;
struct thread_core_local *l = thread_get_core_local();
bool found_thread = false;
assert(l->curr_thread == -1);
//通过spin lock 保护,找到一个可以运行的thread,从这里看出optee里面的thread都是预先申请好的,在使用的时候需要遍历threads 找到一个state是THREAD_STATE_FREE的才可以使用
lock_global();
for (n = 0; n < CFG_NUM_THREADS; n++) {
if (threads[n].state == THREAD_STATE_FREE) {
threads[n].state = THREAD_STATE_ACTIVE;
found_thread = true;
break;
}
}
unlock_global();
//如果没有知道free thread就直接退出了
if (!found_thread) {
args->a0 = OPTEE_SMC_RETURN_ETHREAD_LIMIT;
return;
}
l->curr_thread = n;
threads[n].flags = 0;
//设置thread 要执行的函数
init_regs(threads + n, args);
/* Save Hypervisor Client ID */
threads[n].hyp_clnt_id = args->a7;
thread_lazy_save_ns_vfp();
//执行thread
thread_resume(&threads[n].regs);
}
static void init_regs(struct thread_ctx *thread,
struct thread_smc_args *args)
{
thread->regs.pc = (uint64_t)thread_std_smc_entry;
/*
* Stdcalls starts in SVC mode with masked foreign interrupts, masked
* Asynchronous abort and unmasked native interrupts.
*/
thread->regs.cpsr = SPSR_64(SPSR_64_MODE_EL1, SPSR_64_MODE_SP_EL0,
THREAD_EXCP_FOREIGN_INTR | DAIFBIT_ABT);
/* Reinitialize stack pointer */
thread->regs.sp = thread->stack_va_end;
/*
* Copy arguments into context. This will make the
* arguments appear in x0-x7 when thread is started.
*/
thread->regs.x[0] = args->a0;
thread->regs.x[1] = args->a1;
thread->regs.x[2] = args->a2;
thread->regs.x[3] = args->a3;
thread->regs.x[4] = args->a4;
thread->regs.x[5] = args->a5;
thread->regs.x[6] = args->a6;
thread->regs.x[7] = args->a7;
/* Set up frame pointer as per the Aarch64 AAPCS */
thread->regs.x[29] = 0;
}
在init_regs中通过thread->regs.pc = (uint64_t)thread_std_smc_entry; 来设定这个thread执行函数是thread_std_smc_entry
void __thread_std_smc_entry(struct thread_smc_args *args)
{
thread_std_smc_handler_ptr(args);
if (args->a0 == OPTEE_SMC_RETURN_OK) {
struct thread_ctx *thr = threads + thread_get_id();
tee_fs_rpc_cache_clear(&thr->tsd);
if (!thread_prealloc_rpc_cache) {
thread_rpc_free_arg(thr->rpc_carg);
thr->rpc_carg = 0;
thr->rpc_arg = 0;
}
}
}
执行thread_std_smc_handler_ptr。这个函数是在init_handles中赋值的,是由个个厂家自己实现的,参考fast_smc 一文中的说明