baron · 3月28日 · 四川

optee中的线程向量表(thread_vector_table)

快速连接

👉👉👉【精选】ARMv8/ARMv9架构入门到精通-目录 👈👈👈


 title=

1、向量表的定义

在thread_a64.S中:

/*
 * Vector table supplied to ARM Trusted Firmware (ARM-TF) at
 * initialization.
 *
 * Note that ARM-TF depends on the layout of this vector table, any change
 * in layout has to be synced with ARM-TF.
 */
FUNC thread_vector_table , :
    b    vector_std_smc_entry
    b    vector_fast_smc_entry
    b    vector_cpu_on_entry
    b    vector_cpu_off_entry
    b    vector_cpu_resume_entry
    b    vector_cpu_suspend_entry
    b    vector_fiq_entry
    b    vector_system_off_entry
    b    vector_system_reset_entry
END_FUNC thread_vector_table
KEEP_PAGER thread_vector_table

这个向量表地址,会被传到ATF中,保存在全局变量中

2、向量表的注册

在optee初始化时,generic_boot_init_primary函数获取该向量表的地址:

struct thread_vector_table *
generic_boot_init_primary(unsigned long pageable_part, unsigned long u __unused,
              unsigned long fdt)
{
    init_primary_helper(pageable_part, PADDR_INVALID, fdt);
    return &thread_vector_table;
}

_start函数调用的generic_boot_init_primary

FUNC _start , :
    mov    x19, x0        /* Save pagable part address */
    mov    x20, x2        /* Save DT address */

    adr    x0, reset_vect_table
    msr    vbar_el1, x0
    isb

    set_sctlr_el1
    isb

#ifdef CFG_WITH_PAGER
    /*
     * Move init code into correct location and move hashes to a
     * temporary safe location until the heap is initialized.
     *
     * The binary is built as:
     * [Pager code, rodata and data] : In correct location
     * [Init code and rodata] : Should be copied to __init_start
     * [Hashes] : Should be saved before initializing pager
     *
     */
    adr    x0, __init_start    /* dst */
    adr    x1, __data_end        /* src */
    adr    x2, __tmp_hashes_end    /* dst limit */
    /* Copy backwards (as memmove) in case we're overlapping */
    sub    x2, x2, x0        /* len */
    add    x0, x0, x2        /* __init_start + len = __init_end */
    add    x1, x1, x2        /* __data_end + len */
    adr    x2, __init_start
copy_init:
    ldp    x3, x4, [x1, #-16]!
    stp    x3, x4, [x0, #-16]!
    cmp    x0, x2
    b.gt    copy_init
#endif

    /*
     * Clear .bss, this code obviously depends on the linker keeping
     * start/end of .bss at least 8 byte aligned.
     */
    adr_l    x0, __bss_start
    adr_l    x1, __bss_end
clear_bss:
    str    xzr, [x0], #8
    cmp    x0, x1
    b.lt    clear_bss

    /* Setup SP_EL0 and SP_EL1, SP will be set to SP_EL0 */
    set_sp

    /* Enable aborts now that we can receive exceptions */
    msr    daifclr, #DAIFBIT_ABT

    adr_l    x0, __text_start
#ifdef CFG_WITH_PAGER
    adrp    x1, __tmp_hashes_end
    add    x1, x1, :lo12:__tmp_hashes_end
#else
    adrp    x1, __end
    add    x1, x1, :lo12:__end
#endif
    sub    x1, x1, x0
    bl    dcache_inv_range

    /* Enable Console */
    bl    console_init

    bl    core_init_mmu_map
    bl    core_init_mmu_regs
    bl    cpu_mmu_enable
    bl    cpu_mmu_enable_icache
    bl    cpu_mmu_enable_dcache

    mov    x0, x19        /* pagable part address */
    mov    x1, #-1
    mov    x2, x20        /* DT address */
    bl    generic_boot_init_primary

    /*
     * In case we've touched memory that secondary CPUs will use before
     * they have turned on their D-cache, clean and invalidate the
     * D-cache before exiting to normal world.
     */
    mov    x19, x0
    adr_l    x0, __text_start
#ifdef CFG_WITH_PAGER
    adrp    x1, __tmp_hashes_end
    add    x1, x1, :lo12:__tmp_hashes_end
#else
    adrp    x1, __end
    add    x1, x1, :lo12:__end
#endif
    sub    x1, x1, x0
    bl    dcache_cleaninv_range


    /*
     * Clear current thread id now to allow the thread to be reused on
     * next entry. Matches the thread_init_boot_thread in
     * generic_boot.c.
     */
    bl     thread_clr_boot_thread

    /* Pass the vector address returned from main_init */
    mov    x1, x19
    mov    x0, #TEESMC_OPTEED_RETURN_ENTRY_DONE
    smc    #0
    b    .    /* SMC should not return */
END_FUNC _start
KEEP_INIT _start

然后我们剖析下,这个线程向量表地址记录到哪里去了?
在这里插入图片描述
可以看出,optee读取到线程向量表后,将该地址放到X1参数中,然后调用smc切换到ATF

在ATF中,我们看opteed_smc_handler()函数,有如下片段,我们可以看到,在optee初始化完毕后,将线程量表表保存到X1中,然后调用smc(cmd=TEESMC_OPTEED_RETURN_ENTRY_DONE)切回到ATF,ATF中将该向量表保存到全局变量中optee_vectors

switch (smc_fid) {
/*
 * OPTEE has finished initialising itself after a cold boot
 */
case TEESMC_OPTEED_RETURN_ENTRY_DONE:
    /*
     * Stash the OPTEE entry points information. This is done
     * only once on the primary cpu
     */
    assert(optee_vectors == NULL);
    optee_vectors = (optee_vectors_t *) x1;

    if (optee_vectors) {
        set_optee_pstate(optee_ctx->state, OPTEE_PSTATE_ON);

        /*
         * OPTEE has been successfully initialized.
         * Register power management hooks with PSCI
         */
        psci_register_spd_pm_hook(&opteed_pm);

        /*
         * Register an interrupt handler for S-EL1 interrupts
         * when generated during code executing in the
         * non-secure state.
         */
        flags = 0;
        set_interrupt_rm_flag(flags, NON_SECURE);
        rc = register_interrupt_type_handler(INTR_TYPE_S_EL1,
                    opteed_sel1_interrupt_handler,
                    flags);
        if (rc)
            panic();
    }

    /*
     * OPTEE reports completion. The OPTEED must have initiated
     * the original request through a synchronous entry into
     * OPTEE. Jump back to the original C runtime context.
     */
    opteed_synchronous_sp_exit(optee_ctx, x1);

当从REE--->ATF--->TEE流程时,在ATF中其实就是跳转到的optee_vector表中指向的函数

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);
}

关注"Arm精选"公众号,备注进ARM交流讨论区。
图片1.png

推荐阅读
关注数
9466
内容数
212
以易懂、渐进、有序的方式,深入探讨ARMv8/ARMv9架构的核心概念。我们将从基础知识开始,逐步深入,覆盖最新的架构,不再纠缠于过时技术。本系列内容包含但不限于ARM基础、SOC芯片基础、Trustzone、gic、异常和中断、AMBA、Cache、MMU等内容,并将持续更新。
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息