optee userpace TA程序中的栈的设置
生活随笔
收集整理的這篇文章主要介紹了
optee userpace TA程序中的栈的设置
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
文章目錄
- 1、openssession結構體
- 2、user TA棧的地址獲取
- 3、invoke的流程:
- 4、thread_enter_user_mode中設置棧地址
★★★ 友情鏈接 : 個人博客導讀首頁—點擊此處 ★★★
思考: - TA怎樣被裝載到內存? - TTA是在共享內存中運行的,還是在TEE內存中運行的? - TTA的第一條指令是怎樣執行的? - TTA的棧、堆如何分配的? - TCA調用TA的共享內存,在TA中如何map的? - T切換TA時,系統都做了哪些事情?1、openssession結構體
在opensession的時候,會將session注冊到TEE內存中,以鏈表方式存在
struct tee_ta_session {TAILQ_ENTRY(tee_ta_session) link;TAILQ_ENTRY(tee_ta_session) link_tsd;struct tee_ta_ctx *ctx; /* TA context */TEE_Identity clnt_id; /* Identify of client */bool cancel; /* True if TAF is cancelled */bool cancel_mask; /* True if cancel is masked */TEE_Time cancel_time; /* Time when to cancel the TAF */void *user_ctx; /* ??? */uint32_t ref_count; /* reference counter */struct condvar refc_cv; /* CV used to wait for ref_count to be 0 */struct condvar lock_cv; /* CV used to wait for lock */int lock_thread; /* Id of thread holding the lock */bool unlink; /* True if session is to be unlinked */ #if defined(CFG_TA_GPROF_SUPPORT)struct sample_buf *sbuf; /* Profiling data (PC sampling) */ #endif };2、user TA棧的地址獲取
堆和棧的大小,都是在User_ta_header_defines.h文件種定義的:
#define TA_STACK_SIZE (2 * 1024) #define TA_DATA_SIZE (4 * 1024 * 1024 + 32 * 1024)在opensession的時候,將棧的地址map到TA虛擬地址空間
/* Add stack segment */utc->stack_addr = 0;res = vm_map(utc, &utc->stack_addr, utc->mobj_stack->size,TEE_MATTR_URW | TEE_MATTR_PRW, utc->mobj_stack,0);3、invoke的流程:
先看一個枚舉數組,這是kernel mode與TA通信的三個接口,僅此三個.
或者也可以說,這是CA和TA通信的3個接口
invoke的流程:
tee_entry_std -->tee_ta_invoke_command()---->user_ta_enter_invoke_cmd()—>user_ta_enter()
分析invoke函數:
static TEE_Result user_ta_enter_open_session(struct tee_ta_session *s,struct tee_ta_param *param, TEE_ErrorOrigin *eo) {return user_ta_enter(eo, s, UTEE_ENTRY_FUNC_OPEN_SESSION, 0, param); -------//這里cmd是invoke }從下面函數可以看出, TA運行時的stack是從TA binray解析出來的
static TEE_Result user_ta_enter(TEE_ErrorOrigin *err,struct tee_ta_session *session,enum utee_entry_func func, uint32_t cmd,struct tee_ta_param *param) {TEE_Result res;struct utee_params *usr_params;uaddr_t usr_stack;struct user_ta_ctx *utc = to_user_ta_ctx(session->ctx);TEE_ErrorOrigin serr = TEE_ORIGIN_TEE;struct tee_ta_session *s __maybe_unused;void *param_va[TEE_NUM_PARAMS] = { NULL };/* Map user space memory */res = tee_mmu_map_param(utc, param, param_va); //---------------將param參數(共享內存)map到TEE中if (res != TEE_SUCCESS)goto cleanup_return;/* Switch to user ctx */tee_ta_push_current_session(session);/* Make room for usr_params at top of stack */usr_stack = utc->stack_addr + utc->mobj_stack->size; //----------------解析棧地址usr_stack -= ROUNDUP(sizeof(struct utee_params), STACK_ALIGNMENT);usr_params = (struct utee_params *)usr_stack;init_utee_param(usr_params, param, param_va);res = thread_enter_user_mode(func, tee_svc_kaddr_to_uref(session),//----------------進入userspace,并跳轉到entry_func(vaddr_t)usr_params, cmd, usr_stack,utc->entry_func, utc->is_32bit,&utc->ctx.panicked, &utc->ctx.panic_code);clear_vfp_state(utc);/** According to GP spec the origin should allways be set to the* TA after TA execution*/serr = TEE_ORIGIN_TRUSTED_APP;if (utc->ctx.panicked) {DMSG("tee_user_ta_enter: TA panicked with code 0x%x\n",utc->ctx.panic_code);serr = TEE_ORIGIN_TEE;res = TEE_ERROR_TARGET_DEAD;}/* Copy out value results */update_from_utee_param(param, usr_params);s = tee_ta_pop_current_session();assert(s == session); cleanup_return:/** Clear the cancel state now that the user TA has returned. The next* time the TA will be invoked will be with a new operation and should* not have an old cancellation pending.*/session->cancel = false;/** Can't update *err until now since it may point to an address* mapped for the user mode TA.*/*err = serr;return res; }4、thread_enter_user_mode中設置棧地址
uint32_t thread_enter_user_mode(unsigned long a0, unsigned long a1,unsigned long a2, unsigned long a3, unsigned long user_sp,unsigned long entry_func, bool is_32bit,uint32_t *exit_status0, uint32_t *exit_status1) {uint32_t spsr;tee_ta_update_session_utime_resume();if (!get_spsr(is_32bit, entry_func, &spsr)) {*exit_status0 = 1; /* panic */*exit_status1 = 0xbadbadba;return 0;}return __thread_enter_user_mode(a0, a1, a2, a3, user_sp, entry_func,spsr, exit_status0, exit_status1); } /** uint32_t __thread_enter_user_mode(unsigned long a0, unsigned long a1,* unsigned long a2, unsigned long a3, unsigned long user_sp,* unsigned long user_func, unsigned long spsr,* uint32_t *exit_status0, uint32_t *exit_status1)**/ FUNC __thread_enter_user_mode , :ldr x8, [sp]/** Create the and fill in the struct thread_user_mode_rec*/sub sp, sp, #THREAD_USER_MODE_REC_SIZEstore_xregs sp, THREAD_USER_MODE_REC_EXIT_STATUS0_PTR, 7, 8store_xregs sp, THREAD_USER_MODE_REC_X19, 19, 30/** Switch to SP_EL1* Disable exceptions* Save kern sp in x19*/msr daifset, #DAIFBIT_ALLmov x19, sp ------------------------將kernel mode下的 sp(sp_el0)保存到X19中msr spsel, #1 ------------------------從此刻開始,kernel mode下sp使用sp_el1/** Save the kernel stack pointer in the thread context*//* get pointer to current thread context */get_thread_ctx sp, 21, 20, 22/** Save kernel stack pointer to ensure that el0_svc() uses* correct stack pointer*/str x19, [x21, #THREAD_CTX_KERN_SP] ---------- 將棧地址保存到全局變量中,因為userspace程序可能會主動調用kernel mode,然后使用kernel mode下的棧/** Initialize SPSR, ELR_EL1, and SP_EL0 to enter user mode*/msr spsr_el1, x6/* Set user sp */mov x13, x4 /* Used when running TA in Aarch32 */ --------------------將棧地址寫入到R13msr sp_el0, x4 /* Used when running TA in Aarch64 */ --------------------將棧地址寫入到sp_el0/* Set user function */msr elr_el1, x5/* Set frame pointer (user stack can't be unwound past this point) */mov x29, #0 --------------------------------------------------------- ELR清0/* Jump into user mode */store_xregs sp, THREAD_CORE_LOCAL_X0, 0, 1b eret_to_el0 END_FUNC __thread_enter_user_mode總結
以上是生活随笔為你收集整理的optee userpace TA程序中的栈的设置的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: optee:kernel space调用
- 下一篇: optee中User TA的加载/验签和