std_smc 调用流程

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 一文中的说明
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值