optee CA/TA flow

在这里插入图片描述

在这里插入图片描述
TEEC_InvokeCommand 为例

CA—normal world EL0

//imx-optee-client\libteec\src\tee_client_api.c
TEEC_InvokeCommand
  ioctl(session->ctx->fd, TEE_IOC_INVOKE, &buf_data)

通过syscall陷入内核态driver

linux driver—normal world EL1

tee_ioctl  // drivers\tee\tee_core.c
  tee_ioctl_invoke
    ctx->teedev->desc->ops->invoke_func
      optee_invoke_func  // drivers\tee\optee\call.c
        // Does and SMC to OP-TEE in secure world 
        // and handles eventual resulting Remote 
        // Procedure Calls (RPC) from OP-TEE.
        // Returns return code from secure world, 0 is OK
        optee_do_call_with_arg
          optee->invoke_fn  // get_invoke_func
            optee_smccc_smc
              arm_smccc_smc
                __arm_smccc_smc
                  SMCCC SMCCC_SMC
                    smc #0  //同步异常陷入EL3,执行bl31的中断向量表

其中 ops->invoke_func 在 linux\drivers\tee\optee\core.c 中注册

static const struct tee_driver_ops optee_ops = {
    .get_version = optee_get_version,
    .open = optee_open,
    .release = optee_release,
    .open_session = optee_open_session,
    .close_session = optee_close_session,
    .invoke_func = optee_invoke_func,
    .cancel_req = optee_cancel_req,
    .shm_register = optee_shm_register,
    .shm_unregister = optee_shm_unregister,
};

bl31—EL3

https://blog.csdn.net/orlando19860122/article/details/117034843

// atf\bl31\aarch64\runtime_exceptions.S
sync_exception_aarch64 //从EL1跳转到EL3,即从低到高
  handle_sync_exception
    smc_handler64
      // 根据x0计算出一个runtime service(opteed_smc_handler),然后跳转
      blr x15
      // el3_exit 函数最后调用 eret 从 el3 跳到 secure el1
      // 跳转到optee os的入口 fast_smc_entry、yield_smc_entry
      b el3_exit

https://blog.csdn.net/yiyueming/article/details/72885273

opteed_smc_handler------Runtime Service
opteed_smc_handler
  // 保存non sercure world context
  cm_el1_sysregs_context_save(NON_SECURE);

  // Set appropriate entry for SMC.
  // fast_smc_entry or yield_smc_entry
  cm_set_elr_el3(SECURE, (uint64_t)
                    &optee_vector_table->fast_smc_entry);
  cm_set_elr_el3(SECURE, (uint64_t)
                    &optee_vector_table->yield_smc_entry);
  
  // 保存 sercure world context
  cm_el1_sysregs_context_restore(SECURE)
  SMC_RET4 // 返回smc_handler64继续执行 b el3_exit

optee os—secure world EL1

std

vector_std_smc_entry  //  core\arch\arm\kernel\thread_optee_smc_a64.S
  bl thread_handle_std_smc  // core\arch\arm\kernel\thread_optee_smc.c
    thread_alloc_and_run
      __thread_alloc_and_run(a0, a1, a2, a3, a4, a5, 0, 0,
                   thread_std_smc_entry)
        //core\arch\arm\kernel\thread_optee_smc_a64.S
        thread_std_smc_entry
          __thread_std_smc_entry
            std_smc_entry
              call_entry_std
                tee_entry_std
                  __tee_entry_std // core\tee\entry_std.c
                    case OPTEE_MSG_CMD_INVOKE_COMMAND:
                      entry_invoke_command(arg, num_params)
                        tee_ta_invoke_command
                           ts_ctx->ops->enter_invoke_cmd(&sess->ts_sess, cmd)
                             //core\kernel\user_ta.c
                             user_ta_enter_invoke_cmd
                               user_ta_enter
                                 //sercure world os space->user space
                                 //返回到user space中 参数 entry_func
                                 thread_enter_user_mode
  smc #0

uta—secure world EL0

thread_enter_user_mode 从 sercure world os space(EL1、optee os)返回到sercure world user space(EL0、uta),返回地址是该函数的入参entry_func,TA_InvokeCommandEntryPoint,去执行uta的函数。执行完返回,最后调用 smc #0,触发异常,跳转到EL3。

bl31—EL3

异常进入EL3以后,我们知道之前退出EL3的时候sp_el3指向的是secure context,因此再进入EL3了,用到sp_el3就是指向secure context的。前面的执行流程相同,只是到了opteed_smc_handler函数,跳过了前面caller is secure的分支,因为我们是从secure的环境进入的,直接到了后面 switch(smc_fid) 的逻辑。

// atf\bl31\aarch64\runtime_exceptions.S
sync_exception_aarch64 //从EL1跳转到EL3,即从低到高
  handle_sync_exception
    smc_handler64
      // 根据x0计算出一个runtime service(opteed_smc_handler),然后跳转
      blr x15
      // el3_exit 函数最后调用 eret 从 el3 跳到 secure el1
      b el3_exit

opteed_smc_handler------Runtime Service

opteed_smc_handler
  // Returning from OPTEE
  switch (smc_fid) {
    //...
    case TEESMC_OPTEED_RETURN_CALL_DONE:
      assert(handle == cm_get_context(SECURE));
	  cm_el1_sysregs_context_save(SECURE);
 
	  /* Get a reference to the non-secure context */
	  ns_cpu_context = cm_get_context(NON_SECURE);
	  assert(ns_cpu_context);
 
	  /* Restore non-secure state */
	  cm_el1_sysregs_context_restore(NON_SECURE);
	  cm_set_next_eret_context(NON_SECURE);
      //返回到b el3_exit,然后通过eret返回到REE侧的EL1
      SMC_RET4(ns_cpu_context, x1, x2, x3, x4);

由于从secure el1返回的时候,x0带的参数是TEESMC_OPTEED_RETURN_CALL_DONE,即smc_fid = TEESMC_OPTEED_RETURN_CALL_DONE。所以我们直接看这个分支的处理函数。

  • 首先保存了secure el1的sys寄存器,用于下次secure调用
  • 获取non-secure的context,这个在之前是保过的
    然后恢复non-secure el1的sys寄存器
  • 设置non-secure的context,用于下次non-secure的调用,注意这里会配置sp_el3寄存器,指向了non-secure context,也就是为什么在最开始,我们从non-secure调用下来,默认使用的是non-secure context,就是每次使用完毕以后,在这里都会设置一下,供下次使用。
  • 设置了non-secure context的前4个变量a0~a3为x1, x2, x3, x4。其实就是thread_handle_fast_smc调用结束后的x0, x1, x2, x3。现在算是把原本的值填回到了本来的位置。然后return返回。

返回后的位置是smc_handler64最后一行,最后smc_handler64通过el3_exit返回到了REE侧的EL1。后面列一下SMC中断退出后硬件做的一些事情的伪代码。可以看到硬件从spsr_el3恢复了PSTATE,说明了此时unmask了fiq和irq。

linux driver—normal world EL1

又回到了REE侧的EL1,我们上次走到这里还是只调用了一个smc #0,我们继续看arm_smccc_smc在调用smc以后的逻辑,即SMCCC的宏:

	.macro SMCCC instr
	\instr	#0  /* 执行instr参数的内容,即执行smc切换 */
	ldr	x4, [sp]  /* 切换返回,出栈操作,恢复现场 */
	stp	x0, x1, [x4, #ARM_SMCCC_RES_X0_OFFS]
	stp	x2, x3, [x4, #ARM_SMCCC_RES_X2_OFFS]
	ldr	x4, [sp, #8]
	cbz	x4, 1f /* no quirk structure */
	ldr	x9, [x4, #ARM_SMCCC_QUIRK_ID_OFFS]
	cmp	x9, #ARM_SMCCC_QUIRK_QCOM_A6
	b.ne	1f
	str	x6, [x4, ARM_SMCCC_QUIRK_STATE_OFFS]
1:	ret  //返回到 el0 继续执行
	.endm

根据SMC CALL CONVENTION规则,参数前8个是通过x0x7传递,第9个通过栈传递,现在我们看到的sp就是保存返回结果的结构体地址。我们从前面的分析知道,目前,OPTEE返回的结果保存在x0x3的寄存器里,所以我们看到后的操作就是把x0~x3的值写到保存结果的结构体,即struct arm_smccc_res res;

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值