日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[ATF]-smc指令详解

發布時間:2025/3/21 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [ATF]-smc指令详解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

        • 1、在linux中發起smc的調用
        • 2、陷入ATF的smc同步異常后,調用handler和exit_el3返回linux
        • 3、fast call和std call的定義
        • 4、fast call和std call有什么不同?


★★★ 友情鏈接 : 個人博客導讀首頁—點擊此處 ★★★

思考:
(1)、在linux中執行smc指令后,是如何調用到ATF中的opteed_smc_handler函數的?
(2)、ATF又是如何返回到linux的?
(3)、fast call和std call又是怎樣區分的?

1、在linux中發起smc的調用

SMCCC是一個宏,( \instr #0 )這一行其實就是( smc #0),就是smc調用

在調用smc之前,x0-x8值對應的分別是arm_smccc_smc(a0, a1, a2, a3, a4, a5, a6, a7, res)中的參數。

.macro SMCCC instr .cfi_startproc \instr #0 ldr x4, [sp] stp x0, x1, [x4, #ARM_SMCCC_RES_X0_OFFS] stp x2, x3, [x4, #ARM_SMCCC_RES_X2_OFFS] ret .cfi_endproc .endm /** void arm_smccc_smc(unsigned long a0, unsigned long a1, unsigned long a2,* unsigned long a3, unsigned long a4, unsigned long a5,* unsigned long a6, unsigned long a7, struct arm_smccc_res *res)*/ ENTRY(arm_smccc_smc)SMCCC smc ENDPROC(arm_smccc_smc) static void optee_smccc_smc(unsigned long a0, unsigned long a1,unsigned long a2, unsigned long a3,unsigned long a4, unsigned long a5,unsigned long a6, unsigned long a7,struct arm_smccc_res *res) {arm_smccc_smc(a0, a1, a2, a3, a4, a5, a6, a7, res); }

invoke_fn = get_invoke_func(np); 這里會指向optee_smccc_smc

2、陷入ATF的smc同步異常后,調用handler和exit_el3返回linux

調用smc之后,cpu觸發同步異常,進入ATF的sync_exception_aarch64—>handle_sync_exception—>smc_handler64處理函數

smc_handler64片段:

smc_handler64: ......adr x11, (__RT_SVC_DESCS_START__ + RT_SVC_DESC_HANDLE) .....ldr x15, [x11, w10, uxtw] .....blr x15b el3_exit

RT_SVC_DESCS_START + RT_SVC_DESC_HANDLE指向我們在opteed_main.c中注冊的handler函數

DECLARE_RT_SVC(opteed_fast,OEN_TOS_START,OEN_TOS_END,SMC_TYPE_FAST,opteed_setup,opteed_smc_handler );/* Define an OPTEED runtime service descriptor for standard SMC calls */ DECLARE_RT_SVC(opteed_std,OEN_TOS_START,OEN_TOS_END,SMC_TYPE_STD,NULL,opteed_smc_handler );

在執行完handler函數后,el3_exit調用ERET指令,恢復異常前的PC指針和PSTATE,回到EL1

3、fast call和std call的定義

(1)、在linux的optee_smc.h中,定義了fast call和std call的funcid

#define OPTEE_SMC_STD_CALL_VAL(func_num) \ARM_SMCCC_CALL_VAL(ARM_SMCCC_STD_CALL, ARM_SMCCC_SMC_32, \ARM_SMCCC_OWNER_TRUSTED_OS, (func_num)) #define OPTEE_SMC_FAST_CALL_VAL(func_num) \ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, ARM_SMCCC_SMC_32, \ARM_SMCCC_OWNER_TRUSTED_OS, (func_num))

在構造funcid宏時,如果是std call,cmd_id的31位需是0,如果是fast call,funcid的31位需是1

#define ARM_SMCCC_STD_CALL 0 #define ARM_SMCCC_FAST_CALL 1 #define ARM_SMCCC_TYPE_SHIFT 31

(2)、在optee中 ,對應的也定義了fast和std的type

#define SMC_TYPE_FAST 1 #define SMC_TYPE_STD 0

并且分別注冊了std服務和fast服務,雖然指向的是同一個函數

/* Define an OPTEED runtime service descriptor for fast SMC calls */ DECLARE_RT_SVC(opteed_fast,OEN_TOS_START,OEN_TOS_END,SMC_TYPE_FAST,opteed_setup,opteed_smc_handler );/* Define an OPTEED runtime service descriptor for standard SMC calls */ DECLARE_RT_SVC(opteed_std,OEN_TOS_START,OEN_TOS_END,SMC_TYPE_STD,NULL,opteed_smc_handler );

然后我們再看看,同步異常中斷中,跳轉的時候,如何解析TYPE的

代碼片段

smc_handler64: ....../* Get the unique owning entity number */ubfx x16, x0, #FUNCID_OEN_SHIFT, #FUNCID_OEN_WIDTHubfx x15, x0, #FUNCID_TYPE_SHIFT, #FUNCID_TYPE_WIDTH ......ldr x15, [x11, w10, uxtw] ......blr x15b el3_exit

使用ubfx指令,將FUNCID_TYPE_SHIFT和FUNCID_TYPE_WIDTH解析出來,放在了x15中
(3)、fast call和std call的funcid的定義,在ARM文檔中有規定

4、fast call和std call有什么不同?

linux—>ATF—>optee的過程中,有fast call和std call,那么在這fast和std中有什么不同呢
(1)、在ATF中,將optee傳過來的線程向量表中fast_smc_entry或std_smc_entry寫入到ELR_EL3中

if (GET_SMC_TYPE(smc_fid) == SMC_TYPE_FAST) {cm_set_elr_el3(SECURE, (uint64_t)&optee_vectors->fast_smc_entry); } else {cm_set_elr_el3(SECURE, (uint64_t)&optee_vectors->std_smc_entry); }

(2)、在optee中 fast call會執行thread_handle_fast_smc函數,然后立即執行funcid對應的函數
例如在我們的optee中,定義了如下fast call:

void tee_entry_fast(struct thread_smc_args *args) {switch (args->a0) {/* Generic functions */case OPTEE_SMC_CALLS_COUNT:tee_entry_get_api_call_count(args);break;case OPTEE_SMC_CALLS_UID:tee_entry_get_api_uuid(args);break;case OPTEE_SMC_CALLS_REVISION:tee_entry_get_api_revision(args);break;case OPTEE_SMC_CALL_GET_OS_UUID:tee_entry_get_os_uuid(args);break;case OPTEE_SMC_CALL_GET_OS_REVISION:tee_entry_get_os_revision(args);break;/* OP-TEE specific SMC functions */case OPTEE_SMC_GET_SHM_CONFIG:tee_entry_get_shm_config(args);break;case OPTEE_SMC_L2CC_MUTEX:tee_entry_fastcall_l2cc_mutex(args);break;case OPTEE_SMC_EXCHANGE_CAPABILITIES:tee_entry_exchange_capabilities(args);break;case OPTEE_SMC_DISABLE_SHM_CACHE:tee_entry_disable_shm_cache(args);break;case OPTEE_SMC_ENABLE_SHM_CACHE:tee_entry_enable_shm_cache(args);break;case OPTEE_SMC_BOOT_SECONDARY:tee_entry_boot_secondary(args);break;default:args->a0 = OPTEE_SMC_RETURN_UNKNOWN_FUNCTION;break;} }

std call執行thread_handle_std_smc函數,該函數中不會立即執行funcid對應的函數,會進行調度等
在我們的optee中,有如下是std call:

void __weak tee_entry_std(struct thread_smc_args *smc_args) {paddr_t parg;struct optee_msg_arg *arg = NULL; /* fix gcc warning */uint32_t num_params = 0; /* fix gcc warning */struct mobj *mobj;if (smc_args->a0 != OPTEE_SMC_CALL_WITH_ARG) {EMSG("Unknown SMC 0x%" PRIx64, (uint64_t)smc_args->a0);DMSG("Expected 0x%x\n", OPTEE_SMC_CALL_WITH_ARG);smc_args->a0 = OPTEE_SMC_RETURN_EBADCMD;return;}parg = (uint64_t)smc_args->a1 << 32 | smc_args->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;}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;}arg = mobj_get_va(mobj, 0);assert(arg && mobj_is_nonsec(mobj));/* Enable foreign interrupts for STD calls */thread_set_foreign_intr(true);switch (arg->cmd) {case OPTEE_MSG_CMD_OPEN_SESSION:entry_open_session(smc_args, arg, num_params);break;case OPTEE_MSG_CMD_CLOSE_SESSION:entry_close_session(smc_args, arg, num_params);break;case OPTEE_MSG_CMD_INVOKE_COMMAND:entry_invoke_command(smc_args, arg, num_params);break;case OPTEE_MSG_CMD_CANCEL:entry_cancel(smc_args, arg, num_params);break;case OPTEE_MSG_CMD_REGISTER_SHM:register_shm(smc_args, arg, num_params);break;case OPTEE_MSG_CMD_UNREGISTER_SHM:unregister_shm(smc_args, arg, num_params);break;default:EMSG("Unknown cmd 0x%x\n", arg->cmd);smc_args->a0 = OPTEE_SMC_RETURN_EBADCMD;}mobj_free(mobj); }

總結,CA和TA的通信,都是std call,如open invoke close…,其它的基本是fast call

總結

以上是生活随笔為你收集整理的[ATF]-smc指令详解的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。