optee中utee syscall的实现(系统调用实现)
快速鏈接:
.
👉👉👉 個人博客筆記導讀目錄(全部) 👈👈👈
相關鏈接:
Linux Kernel中的系統調用分析
文章目錄
- 1、GP internal API調用utee func
- 2、utee func組的定義
- 3、utee func的實現其實是一段調用SVC了的匯編函數
- 4、異常向量表的el0_svc實現
- 5、thread_svc_handler--->user_ta_handle_svc
- 6、user_ta_handle_svc中調用tee_svc_syscall_table數組中map的具體函數
- 7、tee_svc_syscall_table函數數組的定義
我們就以TEE_CipherInit為例,講述一下系統調用的流程,先看一張框圖如下:
總結也寫在前面,其實不必深究具體原理,我們只要知道:
1、usersapce層的系統調用函數,一定會調用到svc指令
2、當userspace層調用了utee_xxx, 底層對應著syscall_xxx函數。
例如,userspace調用utee_open_ta_session(),那么底層就會走進syscall_open_ta_session()中
1、GP internal API調用utee func
/* Cryptographic Operations API - Symmetric Cipher Functions */void TEE_CipherInit(TEE_OperationHandle operation, const void *IV,uint32_t IVLen) {TEE_Result res;if (operation == TEE_HANDLE_NULL)TEE_Panic(0);if (operation->info.operationClass != TEE_OPERATION_CIPHER)TEE_Panic(0);if (!(operation->info.handleState & TEE_HANDLE_FLAG_KEY_SET) ||!(operation->key1))TEE_Panic(0);if (operation->operationState != TEE_OPERATION_STATE_INITIAL)TEE_ResetOperation(operation);operation->operationState = TEE_OPERATION_STATE_ACTIVE;res = utee_cipher_init(operation->state, IV, IVLen);if (res != TEE_SUCCESS)TEE_Panic(res);operation->buffer_offs = 0;operation->info.handleState |= TEE_HANDLE_FLAG_INITIALIZED; }2、utee func組的定義
在utee_syscalls_asm.s定義了一系列函數,UTEE_SYSCALL是一個用于定義函數的宏
(lib\libutee\arch\arm\utee_syscalls_asm.s)UTEE_SYSCALL utee_return, TEE_SCN_RETURN, 1UTEE_SYSCALL utee_log, TEE_SCN_LOG, 2UTEE_SYSCALL __utee_panic, TEE_SCN_PANIC, 2UTEE_SYSCALL utee_get_property, TEE_SCN_GET_PROPERTY, 7UTEE_SYSCALL utee_get_property_name_to_index, \TEE_SCN_GET_PROPERTY_NAME_TO_INDEX, 4UTEE_SYSCALL utee_open_ta_session, TEE_SCN_OPEN_TA_SESSION, 5UTEE_SYSCALL utee_close_ta_session, TEE_SCN_CLOSE_TA_SESSION, 1UTEE_SYSCALL utee_invoke_ta_command, TEE_SCN_INVOKE_TA_COMMAND, 5UTEE_SYSCALL utee_get_cancellation_flag, \TEE_SCN_GET_CANCELLATION_FLAG, 1UTEE_SYSCALL utee_check_access_rights, TEE_SCN_CHECK_ACCESS_RIGHTS, 3UTEE_SYSCALL utee_unmask_cancellation, TEE_SCN_UNMASK_CANCELLATION, 1UTEE_SYSCALL utee_mask_cancellation, TEE_SCN_MASK_CANCELLATION, 1UTEE_SYSCALL utee_wait, TEE_SCN_WAIT, 1UTEE_SYSCALL utee_get_time, TEE_SCN_GET_TIME, 2UTEE_SYSCALL utee_set_ta_time, TEE_SCN_SET_TA_TIME, 1UTEE_SYSCALL utee_cryp_state_alloc, TEE_SCN_CRYP_STATE_ALLOC, 5UTEE_SYSCALL utee_cryp_state_copy, TEE_SCN_CRYP_STATE_COPY, 2UTEE_SYSCALL utee_cryp_state_free, TEE_SCN_CRYP_STATE_FREE, 1UTEE_SYSCALL utee_hash_init, TEE_SCN_HASH_INIT, 3UTEE_SYSCALL utee_hash_update, TEE_SCN_HASH_UPDATE, 3UTEE_SYSCALL utee_hash_final, TEE_SCN_HASH_FINAL, 5UTEE_SYSCALL utee_cipher_init, TEE_SCN_CIPHER_INIT, 3UTEE_SYSCALL utee_cipher_update, TEE_SCN_CIPHER_UPDATE, 5UTEE_SYSCALL utee_cipher_final, TEE_SCN_CIPHER_FINAL, 5UTEE_SYSCALL utee_cryp_obj_get_info, TEE_SCN_CRYP_OBJ_GET_INFO, 2UTEE_SYSCALL utee_cryp_obj_restrict_usage, \TEE_SCN_CRYP_OBJ_RESTRICT_USAGE, 2UTEE_SYSCALL utee_cryp_obj_get_attr, TEE_SCN_CRYP_OBJ_GET_ATTR, 4UTEE_SYSCALL utee_cryp_obj_alloc, TEE_SCN_CRYP_OBJ_ALLOC, 3UTEE_SYSCALL utee_cryp_obj_close, TEE_SCN_CRYP_OBJ_CLOSE, 1UTEE_SYSCALL utee_cryp_obj_reset, TEE_SCN_CRYP_OBJ_RESET, 1UTEE_SYSCALL utee_cryp_obj_populate, TEE_SCN_CRYP_OBJ_POPULATE, 3UTEE_SYSCALL utee_cryp_obj_copy, TEE_SCN_CRYP_OBJ_COPY, 2UTEE_SYSCALL utee_cryp_derive_key, TEE_SCN_CRYP_DERIVE_KEY, 4UTEE_SYSCALL utee_cryp_random_number_generate, \TEE_SCN_CRYP_RANDOM_NUMBER_GENERATE, 2UTEE_SYSCALL utee_authenc_init, TEE_SCN_AUTHENC_INIT, 6UTEE_SYSCALL utee_authenc_update_aad, TEE_SCN_AUTHENC_UPDATE_AAD, 3UTEE_SYSCALL utee_authenc_update_payload, \TEE_SCN_AUTHENC_UPDATE_PAYLOAD, 5UTEE_SYSCALL utee_authenc_enc_final, TEE_SCN_AUTHENC_ENC_FINAL, 7UTEE_SYSCALL utee_authenc_dec_final, TEE_SCN_AUTHENC_DEC_FINAL, 7UTEE_SYSCALL utee_asymm_operate, TEE_SCN_ASYMM_OPERATE, 7UTEE_SYSCALL utee_asymm_verify, TEE_SCN_ASYMM_VERIFY, 7UTEE_SYSCALL utee_storage_obj_open, TEE_SCN_STORAGE_OBJ_OPEN, 5UTEE_SYSCALL utee_storage_obj_create, TEE_SCN_STORAGE_OBJ_CREATE, 8UTEE_SYSCALL utee_storage_obj_del, TEE_SCN_STORAGE_OBJ_DEL, 1UTEE_SYSCALL utee_storage_obj_rename, TEE_SCN_STORAGE_OBJ_RENAME, 3UTEE_SYSCALL utee_storage_alloc_enum, TEE_SCN_STORAGE_ENUM_ALLOC, 1UTEE_SYSCALL utee_storage_free_enum, TEE_SCN_STORAGE_ENUM_FREE, 1UTEE_SYSCALL utee_storage_reset_enum, TEE_SCN_STORAGE_ENUM_RESET, 1UTEE_SYSCALL utee_storage_start_enum, TEE_SCN_STORAGE_ENUM_START, 2UTEE_SYSCALL utee_storage_next_enum, TEE_SCN_STORAGE_ENUM_NEXT, 4UTEE_SYSCALL utee_storage_obj_read, TEE_SCN_STORAGE_OBJ_READ, 4UTEE_SYSCALL utee_storage_obj_write, TEE_SCN_STORAGE_OBJ_WRITE, 3UTEE_SYSCALL utee_storage_obj_trunc, TEE_SCN_STORAGE_OBJ_TRUNC, 2UTEE_SYSCALL utee_storage_obj_seek, TEE_SCN_STORAGE_OBJ_SEEK, 3UTEE_SYSCALL utee_cryp_obj_generate_key, \TEE_SCN_CRYP_OBJ_GENERATE_KEY, 4UTEE_SYSCALL utee_cache_operation, TEE_SCN_CACHE_OPERATION, 33、utee func的實現其實是一段調用SVC了的匯編函數
在調用svc指令之前,將TEE_SCN_CIPHER_INIT寫入到了X8寄存器
.macro UTEE_SYSCALL name, scn, num_argsFUNC \name , :.if \num_args > TEE_SVC_MAX_ARGS || \num_args > 8.error "Too many arguments for syscall".endif #if defined(CFG_SYSCALL_WRAPPERS_MCOUNT) && !defined(__LDELF__).if \scn != TEE_SCN_RETURNstp x29, x30, [sp, #-80]!mov x29, spstp x0, x1, [sp, #16]stp x2, x3, [sp, #32]stp x4, x5, [sp, #48]stp x6, x7, [sp, #64]mov x0, x30bl _mcountldp x0, x1, [sp, #16]ldp x2, x3, [sp, #32]ldp x4, x5, [sp, #48]ldp x6, x7, [sp, #64]ldp x29, x30, [sp], #80.endif #endifmov x8, #(\scn)svc #0retEND_FUNC \name.endmFUNC utee_panic, :stp x29, x30, [sp, #-16]!mov x1, spbl __utee_panic/* Not reached */END_FUNC utee_panic4、異常向量表的el0_svc實現
觸發svc異常后,將會跳轉到Optee的el0_svc向量表中,在該函數中調用了bl thread_svc_handler
LOCAL_FUNC el0_svc , :/* get pointer to current thread context in x0 */get_thread_ctx sp, 0, 1, 2/* load saved kernel sp */ldr x0, [x0, #THREAD_CTX_KERN_SP]/* Keep pointer to initial recod in x1 */mov x1, sp/* Switch to SP_EL0 and restore kernel sp */msr spsel, #0mov x2, sp /* Save SP_EL0 */mov sp, x0/* Make room for struct thread_svc_regs */sub sp, sp, #THREAD_SVC_REG_SIZEstp x30,x2, [sp, #THREAD_SVC_REG_X30]/* Restore x0-x3 */ldp x2, x3, [x1, #THREAD_CORE_LOCAL_X2]ldp x0, x1, [x1, #THREAD_CORE_LOCAL_X0]/* Prepare the argument for the handler */store_xregs sp, THREAD_SVC_REG_X0, 0, 14mrs x0, elr_el1mrs x1, spsr_el1store_xregs sp, THREAD_SVC_REG_ELR, 0, 1mov x0, sp/** Unmask native interrupts, Serror, and debug exceptions since we have* nothing left in sp_el1. Note that the SVC handler is excepted to* re-enable foreign interrupts by itself.*/ #if defined(CFG_ARM_GICV3)msr daifclr, #(DAIFBIT_IRQ | DAIFBIT_ABT | DAIFBIT_DBG) #elsemsr daifclr, #(DAIFBIT_FIQ | DAIFBIT_ABT | DAIFBIT_DBG) #endif/* Call the handler */bl thread_svc_handler/* Mask all maskable exceptions since we're switching back to sp_el1 */msr daifset, #DAIFBIT_ALL/** Save kernel sp we'll had at the beginning of this function.* This is when this TA has called another TA because* __thread_enter_user_mode() also saves the stack pointer in this* field.*/msr spsel, #1get_thread_ctx sp, 0, 1, 2msr spsel, #0add x1, sp, #THREAD_SVC_REG_SIZEstr x1, [x0, #THREAD_CTX_KERN_SP]/* Restore registers to the required state and return*/load_xregs sp, THREAD_SVC_REG_ELR, 0, 1msr elr_el1, x0msr spsr_el1, x1load_xregs sp, THREAD_SVC_REG_X2, 2, 14mov x30, spldr x0, [x30, #THREAD_SVC_REG_SP_EL0]mov sp, x0b_if_spsr_is_el0 w1, 1fldp x0, x1, [x30, THREAD_SVC_REG_X0]ldr x30, [x30, #THREAD_SVC_REG_X30]return_from_exception1: ldp x0, x1, [x30, THREAD_SVC_REG_X0]ldr x30, [x30, #THREAD_SVC_REG_X30]msr spsel, #1store_xregs sp, THREAD_CORE_LOCAL_X0, 0, 1b eret_to_el0 END_FUNC el0_svc5、thread_svc_handler—>user_ta_handle_svc
thread_svc_handler調用了handle_svc
/** Note: this function is weak just to make it possible to exclude it from* the unpaged area.*/ void __weak thread_svc_handler(struct thread_svc_regs *regs) {struct tee_ta_session *sess = NULL;uint32_t state = 0;/* Enable native interrupts */state = thread_get_exceptions();thread_unmask_exceptions(state & ~THREAD_EXCP_NATIVE_INTR);thread_user_save_vfp();/* TA has just entered kernel mode */tee_ta_update_session_utime_suspend();/* Restore foreign interrupts which are disabled on exception entry */thread_restore_foreign_intr();tee_ta_get_current_session(&sess);assert(sess && sess->ctx->ops && sess->ctx->ops->handle_svc);if (sess->ctx->ops->handle_svc(regs)) {/* We're about to switch back to user mode */tee_ta_update_session_utime_resume();} else {/* We're returning from __thread_enter_user_mode() */setup_unwind_user_mode(regs);} }而handle_svc指向user_ta_handle_svc
static const struct tee_ta_ops user_ta_ops __rodata_unpaged = {.enter_open_session = user_ta_enter_open_session,.enter_invoke_cmd = user_ta_enter_invoke_cmd,.enter_close_session = user_ta_enter_close_session,.dump_state = user_ta_dump_state, #ifdef CFG_FTRACE_SUPPORT.dump_ftrace = user_ta_dump_ftrace, #endif.destroy = user_ta_ctx_destroy,.get_instance_id = user_ta_get_instance_id,.handle_svc = user_ta_handle_svc, };6、user_ta_handle_svc中調用tee_svc_syscall_table數組中map的具體函數
user_ta_handle_svc調用tee_svc_syscall_table[scn].fn
bool user_ta_handle_svc(struct thread_svc_regs *regs) {size_t scn;size_t max_args;syscall_t scf;COMPILE_TIME_ASSERT(ARRAY_SIZE(tee_svc_syscall_table) ==(TEE_SCN_MAX + 1));get_scn_max_args(regs, &scn, &max_args);trace_syscall(scn);if (max_args > TEE_SVC_MAX_ARGS) {DMSG("Too many arguments for SCN %zu (%zu)", scn, max_args);set_svc_retval(regs, TEE_ERROR_GENERIC);return true; /* return to user mode */}if (scn > TEE_SCN_MAX)scf = (syscall_t)syscall_not_supported;elsescf = tee_svc_syscall_table[scn].fn;ftrace_syscall_enter(scn);set_svc_retval(regs, tee_svc_do_call(regs, scf));ftrace_syscall_leave();/** Return true if we're to return to user mode,* thread_svc_handler() will take care of the rest.*/return scn != TEE_SCN_RETURN && scn != TEE_SCN_PANIC; }scn是從x8取出的,正是userspace寫入的TEE_SCN_CIPHER_INIT
#ifdef ARM64 static void get_scn_max_args(struct thread_svc_regs *regs, size_t *scn,size_t *max_args) {if (((regs->spsr >> SPSR_MODE_RW_SHIFT) & SPSR_MODE_RW_MASK) ==SPSR_MODE_RW_32) {*scn = regs->x7;*max_args = regs->x6;} else {*scn = regs->x8;*max_args = 0;} } #endif /*ARM64*/7、tee_svc_syscall_table函數數組的定義
/** This array is ordered according to the SYSCALL ids TEE_SCN_xxx*/ static const struct syscall_entry tee_svc_syscall_table[] = {SYSCALL_ENTRY(syscall_sys_return),SYSCALL_ENTRY(syscall_log),SYSCALL_ENTRY(syscall_panic),SYSCALL_ENTRY(syscall_get_property),SYSCALL_ENTRY(syscall_get_property_name_to_index),SYSCALL_ENTRY(syscall_open_ta_session),SYSCALL_ENTRY(syscall_close_ta_session),SYSCALL_ENTRY(syscall_invoke_ta_command),SYSCALL_ENTRY(syscall_check_access_rights),SYSCALL_ENTRY(syscall_get_cancellation_flag),SYSCALL_ENTRY(syscall_unmask_cancellation),SYSCALL_ENTRY(syscall_mask_cancellation),SYSCALL_ENTRY(syscall_wait),SYSCALL_ENTRY(syscall_get_time),SYSCALL_ENTRY(syscall_set_ta_time),SYSCALL_ENTRY(syscall_cryp_state_alloc),SYSCALL_ENTRY(syscall_cryp_state_copy),SYSCALL_ENTRY(syscall_cryp_state_free),SYSCALL_ENTRY(syscall_hash_init),SYSCALL_ENTRY(syscall_hash_update),SYSCALL_ENTRY(syscall_hash_final),SYSCALL_ENTRY(syscall_cipher_init),SYSCALL_ENTRY(syscall_cipher_update),SYSCALL_ENTRY(syscall_cipher_final),SYSCALL_ENTRY(syscall_cryp_obj_get_info),SYSCALL_ENTRY(syscall_cryp_obj_restrict_usage),SYSCALL_ENTRY(syscall_cryp_obj_get_attr),SYSCALL_ENTRY(syscall_cryp_obj_alloc),SYSCALL_ENTRY(syscall_cryp_obj_close),SYSCALL_ENTRY(syscall_cryp_obj_reset),SYSCALL_ENTRY(syscall_cryp_obj_populate),SYSCALL_ENTRY(syscall_cryp_obj_copy),SYSCALL_ENTRY(syscall_cryp_derive_key),SYSCALL_ENTRY(syscall_cryp_random_number_generate),SYSCALL_ENTRY(syscall_authenc_init),SYSCALL_ENTRY(syscall_authenc_update_aad),SYSCALL_ENTRY(syscall_authenc_update_payload),SYSCALL_ENTRY(syscall_authenc_enc_final),SYSCALL_ENTRY(syscall_authenc_dec_final),SYSCALL_ENTRY(syscall_asymm_operate),SYSCALL_ENTRY(syscall_asymm_verify),SYSCALL_ENTRY(syscall_storage_obj_open),SYSCALL_ENTRY(syscall_storage_obj_create),SYSCALL_ENTRY(syscall_storage_obj_del),SYSCALL_ENTRY(syscall_storage_obj_rename),SYSCALL_ENTRY(syscall_storage_alloc_enum),SYSCALL_ENTRY(syscall_storage_free_enum),SYSCALL_ENTRY(syscall_storage_reset_enum),SYSCALL_ENTRY(syscall_storage_start_enum),SYSCALL_ENTRY(syscall_storage_next_enum),SYSCALL_ENTRY(syscall_storage_obj_read),SYSCALL_ENTRY(syscall_storage_obj_write),SYSCALL_ENTRY(syscall_storage_obj_trunc),SYSCALL_ENTRY(syscall_storage_obj_seek),SYSCALL_ENTRY(syscall_obj_generate_key),SYSCALL_ENTRY(syscall_not_supported),SYSCALL_ENTRY(syscall_not_supported),SYSCALL_ENTRY(syscall_not_supported),SYSCALL_ENTRY(syscall_not_supported),SYSCALL_ENTRY(syscall_not_supported),SYSCALL_ENTRY(syscall_not_supported),SYSCALL_ENTRY(syscall_not_supported),SYSCALL_ENTRY(syscall_not_supported),SYSCALL_ENTRY(syscall_not_supported),SYSCALL_ENTRY(syscall_not_supported),SYSCALL_ENTRY(syscall_not_supported),SYSCALL_ENTRY(syscall_not_supported),SYSCALL_ENTRY(syscall_not_supported),SYSCALL_ENTRY(syscall_not_supported),SYSCALL_ENTRY(syscall_not_supported),SYSCALL_ENTRY(syscall_cache_operation), }; 《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的optee中utee syscall的实现(系统调用实现)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux Kernel中gicv3实现
- 下一篇: MTK的LK代码异常向量表解析