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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

optee内核中栈的介绍(二)

發(fā)布時間:2025/3/21 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 optee内核中栈的介绍(二) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

快速鏈接:
.
👉👉👉 個人博客筆記導(dǎo)讀目錄(全部) 👈👈👈


相關(guān)推薦:
1、optee的棧指針和棧內(nèi)存的介紹
2、optee aarch64體系下棧的設(shè)計(jì)(sp_el0/sp_el1)

文章目錄

        • 1、在optee中的棧內(nèi)存:
        • 2、optee中的棧指針
        • 3、在不同階段使用不同的棧內(nèi)存和棧指針
        • 3、開機(jī)時對所有棧的初始化
        • 4、init_thread_stacks 將thread stack地址寫入到thread結(jié)構(gòu)體的變量中
        • 5、thread結(jié)構(gòu)體的變量中的棧地址寫入到sp寄存器中
        • 6、abt/tmp stack

1、在optee中的棧內(nèi)存:

  • Secure monitor stack (128 bytes),綁定cpu, 給armv7使用的
  • Temp stack (small ~1KB) 128,綁定cpu, 狀態(tài)切換時使用的, 使用該棧時interrupt是關(guān)閉的
  • Abort stack (medium ~2KB),綁定cpu, 取數(shù)據(jù)或取指令異常時,使用這個棧.
    如果是user發(fā)生的abort,那么kill掉TA,如果是kernel發(fā)生的abort,那么kernel可能會掛掉
  • Thread stack (large ~8KB) 給進(jìn)程使用的

(1)、aarch32/aarch64各個棧內(nèi)存size的定義

#ifdef CFG_WITH_ARM_TRUSTED_FW #define STACK_TMP_OFFS 0 #else #define STACK_TMP_OFFS SM_STACK_TMP_RESERVE_SIZE //Secure monitor stack #endif#ifdef ARM32 #ifdef CFG_CORE_SANITIZE_KADDRESS #define STACK_TMP_SIZE (3072 + STACK_TMP_OFFS) #else #define STACK_TMP_SIZE (1536 + STACK_TMP_OFFS) //Temp stack #endif #define STACK_THREAD_SIZE 8192 // Thread stack#ifdef CFG_CORE_SANITIZE_KADDRESS #define STACK_ABT_SIZE 3072 #else #define STACK_ABT_SIZE 2048 //Abort stack #endif#endif /*ARM32*/#ifdef ARM64 #define STACK_TMP_SIZE (2048 + STACK_TMP_OFFS) //Temp stack #define STACK_THREAD_SIZE 8192 // Thread stack#if TRACE_LEVEL > 0 #define STACK_ABT_SIZE 3072 //Abort stack #else #define STACK_ABT_SIZE 1024 #endif #endif /*ARM64*/struct thread_ctx threads[CFG_NUM_THREADS]; //optee中的thread slot

(2)、棧內(nèi)存的定義
其實(shí)就是在".nozi_stack"的section段定義一些數(shù)組. 通過數(shù)組定義可以發(fā)現(xiàn)tmp、abt是和cpu core綁定的.thread_stack是和線程綁定的

#define DECLARE_STACK(name, num_stacks, stack_size, linkage) \ linkage uint32_t name[num_stacks] \[ROUNDUP(stack_size + STACK_CANARY_SIZE, STACK_ALIGNMENT) / \sizeof(uint32_t)] \__attribute__((section(".nozi_stack"), \aligned(STACK_ALIGNMENT)))DECLARE_STACK(stack_tmp, CFG_TEE_CORE_NB_CORE, STACK_TMP_SIZE, static); DECLARE_STACK(stack_abt, CFG_TEE_CORE_NB_CORE, STACK_ABT_SIZE, static); #ifndef CFG_WITH_PAGER DECLARE_STACK(stack_thread, CFG_NUM_THREADS, STACK_THREAD_SIZE, static); #endif

2、optee中的棧指針

armv7-A/aarch32
temp stack : SP_SVC、SP_IRQ、SP_FIQ
abort : use sp_abt
thread : use sp_svc

armv8-a/aarch64
只有兩個棧指針:sp_el1、sp_el0

3、在不同階段使用不同的棧內(nèi)存和棧指針

(1)、在optee啟動時到第一次回到normal world,使用的是temp stack,棧指針是sp_svc
(2)、當(dāng)cpu從REE回來時,如果是fast call,則使用temp stack
如果是std call,將切換到thread slot 的棧中. 當(dāng)std call執(zhí)行完成了,再切回temp stack
(3)、當(dāng)發(fā)生RPC調(diào)用時thread_rpc(…),也回切回到temp stack,直到從normal再回來.
(4)、當(dāng)foriegin中斷發(fā)生時,類似于RPC調(diào)用

aarch64
只有兩個棧指針:sp_el1、sp_el0
當(dāng)有exception進(jìn)來,先使用sp_el1,再分配sp_el0
切換sp_el0時,spsel要配置成0

3、開機(jī)時對所有棧的初始化

在init_canaries()函數(shù)中,其實(shí)就是往棧首棧尾分別寫入0xdededede和0xabababab

static void init_canaries(void) { #ifdef CFG_WITH_STACK_CANARIESsize_t n; #define INIT_CANARY(name) \for (n = 0; n < ARRAY_SIZE(name); n++) { \uint32_t *start_canary = &GET_START_CANARY(name, n); \uint32_t *end_canary = &GET_END_CANARY(name, n); \\*start_canary = START_CANARY_VALUE; \*end_canary = END_CANARY_VALUE; \FMSG("#Stack canaries for %s[%zu] with top at %p\n", \#name, n, (void *)(end_canary - 1)); \FMSG("watch *%p\n", (void *)end_canary); \}INIT_CANARY(stack_tmp);INIT_CANARY(stack_abt); #ifndef CFG_WITH_PAGER //我們是沒有定義這個的INIT_CANARY(stack_thread); #endif #endif/*CFG_WITH_STACK_CANARIES*/ }#define START_CANARY_VALUE 0xdededede #define END_CANARY_VALUE 0xabababab

4、init_thread_stacks 將thread stack地址寫入到thread結(jié)構(gòu)體的變量中

其實(shí)就是讓當(dāng)前進(jìn)程結(jié)構(gòu)體中的threads[thread_id].stack_va_end變量,指向當(dāng)前進(jìn)程對應(yīng)的thread stack的數(shù)組
sp – GET_STACK(stack_thread[n]) – 指向當(dāng)前進(jìn)程對應(yīng)的thread stack的數(shù)組
threads[thread_id].stack_va_end – 當(dāng)前進(jìn)程的結(jié)構(gòu)體的變量

static void init_thread_stacks(void) {size_t n;/* Assign the thread stacks */for (n = 0; n < CFG_NUM_THREADS; n++) {if (!thread_init_stack(n, GET_STACK(stack_thread[n])))panic("thread_init_stack failed");} }bool thread_init_stack(uint32_t thread_id, vaddr_t sp) {if (thread_id >= CFG_NUM_THREADS)return false;threads[thread_id].stack_va_end = sp;return true; }

5、thread結(jié)構(gòu)體的變量中的棧地址寫入到sp寄存器中

thread->regs.sp = thread->stack_va_end;

#ifdef ARM32 static void init_regs(struct thread_ctx *thread,struct thread_smc_args *args) {thread->regs.pc = (uint32_t)thread_std_smc_entry;/** Stdcalls starts in SVC mode with masked foreign interrupts, masked* Asynchronous abort and unmasked native interrupts.*/thread->regs.cpsr = read_cpsr() & ARM32_CPSR_E;thread->regs.cpsr |= CPSR_MODE_SVC | CPSR_A |(THREAD_EXCP_FOREIGN_INTR << ARM32_CPSR_F_SHIFT);/* Enable thumb mode if it's a thumb instruction */if (thread->regs.pc & 1)thread->regs.cpsr |= CPSR_T;/* Reinitialize stack pointer */thread->regs.svc_sp = thread->stack_va_end;/** Copy arguments into context. This will make the* arguments appear in r0-r7 when thread is started.*/thread->regs.r0 = args->a0;thread->regs.r1 = args->a1;thread->regs.r2 = args->a2;thread->regs.r3 = args->a3;thread->regs.r4 = args->a4;thread->regs.r5 = args->a5;thread->regs.r6 = args->a6;thread->regs.r7 = args->a7; } #endif /*ARM32*/ #ifdef ARM64 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; } #endif /*ARM64*/

6、abt/tmp stack

在thread_init_per_cpu()來將棧地址寫入到sp寄存器

void thread_init_per_cpu(void) {size_t pos = get_core_pos();struct thread_core_local *l = thread_get_core_local();init_sec_mon(pos);set_tmp_stack(l, GET_STACK(stack_tmp[pos]) - STACK_TMP_OFFS);set_abt_stack(l, GET_STACK(stack_abt[pos]));thread_init_vbar(get_excp_vect()); }

aarch32在調(diào)用set_tmp_stack()/set_abt_stack()時就已經(jīng)將棧地址寫入到sp寄存器了

#ifdef ARM32 static void set_tmp_stack(struct thread_core_local *l, vaddr_t sp) {l->tmp_stack_va_end = sp;thread_set_irq_sp(sp);thread_set_fiq_sp(sp); }static void set_abt_stack(struct thread_core_local *l, vaddr_t sp) {l->abt_stack_va_end = sp;thread_set_abt_sp((vaddr_t)l);thread_set_und_sp((vaddr_t)l); } #endif /*ARM32*/

將abt stack地址寫入到sp_abt

FUNC thread_set_abt_sp , : UNWIND( .fnstart) UNWIND( .cantunwind)mrs r1, cpsr //先保存cpsrcps #CPSR_MODE_ABT //切回到abt modemov sp, r0 //將abt stack地址寫入到sp_abtmsr cpsr, r1 //回復(fù)cpsrbx lr UNWIND( .fnend) END_FUNC thread_set_abt_sp

也就是設(shè)置棧地址時,伴隨著模式切換

aarch32在調(diào)用set_tmp_stack()/set_abt_stack()時只是將棧地址寫入到了l->tmp_stack_va_end和l->abt_stack_va_end變量

#ifdef ARM64 static void set_tmp_stack(struct thread_core_local *l, vaddr_t sp) {/** We're already using the tmp stack when this function is called* so there's no need to assign it to any stack pointer. However,* we'll need to restore it at different times so store it here.*/l->tmp_stack_va_end = sp; }static void set_abt_stack(struct thread_core_local *l, vaddr_t sp) {l->abt_stack_va_end = sp; } #endif /*ARM64*/

在std進(jìn)來時,獲取tmp stack,然后寫入到sp
bl thread_get_tmp_sp
mov sp, x0

FUNC thread_std_smc_entry , :/* pass x0-x7 in a struct thread_smc_args */sub sp, sp, #THREAD_SMC_ARGS_SIZEstore_xregs sp, THREAD_SMC_ARGS_X0, 0, 7mov 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, 23add sp, sp, #THREAD_SMC_ARGS_SIZE/* Mask all maskable exceptions before switching to temporary stack */msr daifset, #DAIFBIT_ALLbl thread_get_tmp_spmov sp, x0bl thread_state_freeldr x0, =TEESMC_OPTEED_RETURN_CALL_DONEmov x1, x20mov x2, x21mov x3, x22mov x4, x23smc #0b . /* SMC should not return */ END_FUNC thread_std_smc_entry

在rpc調(diào)用時,同樣如此
bl thread_get_tmp_sp
mov sp, x0 /* Switch to tmp stack */

/* void thread_rpc(uint32_t rv[THREAD_RPC_NUM_ARGS]) */ FUNC thread_rpc , :/* Read daif and create an SPSR */mrs x1, daiforr x1, x1, #(SPSR_64_MODE_EL1 << SPSR_64_MODE_EL_SHIFT)/* Mask all maskable exceptions before switching to temporary stack */msr daifset, #DAIFBIT_ALLpush x0, xzrpush x1, x30bl thread_get_ctx_regsldr x30, [sp, #8]store_xregs x0, THREAD_CTX_REGS_X19, 19, 30mov x19, x0bl thread_get_tmp_sppop x1, xzr /* Match "push x1, x30" above */mov x2, spstr x2, [x19, #THREAD_CTX_REGS_SP]ldr x20, [sp] /* Get pointer to rv[] */mov sp, x0 /* Switch to tmp stack */adr x2, .thread_rpc_returnmov w0, #THREAD_FLAGS_COPY_ARGS_ON_RETURNbl thread_state_suspendmov x4, x0 /* Supply thread index */ldr w0, =TEESMC_OPTEED_RETURN_CALL_DONEload_wregs x20, 0, 1, 3 /* Load rv[] into w0-w2 */smc #0b . /* SMC should not return */

總結(jié)

以上是生活随笔為你收集整理的optee内核中栈的介绍(二)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。