baron · 3月27日 · 四川

在linux、optee、ATF中的中断异常向量表

快速连接

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


 title=

1、在linux中的异常向量表

(1)、arm64的异常向量表-(irq,fiq,svc......)

armv8-arch64架构下,linux kernel的异常量表,再entry.S中:

/*
 * Exception vectors.
 */

    .align    11
ENTRY(vectors)
    kernel_ventry    1, sync_invalid            // Synchronous EL1t
    kernel_ventry    1, irq_invalid            // IRQ EL1t
    kernel_ventry    1, fiq_invalid            // FIQ EL1t
    kernel_ventry    1, error_invalid        // Error EL1t

    kernel_ventry    1, sync                // Synchronous EL1h
    kernel_ventry    1, irq                // IRQ EL1h
    kernel_ventry    1, fiq_invalid            // FIQ EL1h
    kernel_ventry    1, error_invalid        // Error EL1h

    kernel_ventry    0, sync                // Synchronous 64-bit EL0
    kernel_ventry    0, irq                // IRQ 64-bit EL0
    kernel_ventry    0, fiq_invalid            // FIQ 64-bit EL0
    kernel_ventry    0, error_invalid        // Error 64-bit EL0

#ifdef CONFIG_COMPAT
    kernel_ventry    0, sync_compat, 32        // Synchronous 32-bit EL0
    kernel_ventry    0, irq_compat, 32        // IRQ 32-bit EL0
    kernel_ventry    0, fiq_invalid_compat, 32    // FIQ 32-bit EL0
    kernel_ventry    0, error_invalid_compat, 32    // Error 32-bit EL0
#else
    kernel_ventry    0, sync_invalid, 32        // Synchronous 32-bit EL0
    kernel_ventry    0, irq_invalid, 32        // IRQ 32-bit EL0
    kernel_ventry    0, fiq_invalid, 32        // FIQ 32-bit EL0
    kernel_ventry    0, error_invalid, 32        // Error 32-bit EL0
#endif
END(vectors)

我们这里讲解如下四行:

kernel_ventry    1, irq                // IRQ EL1h
kernel_ventry    0, irq                // IRQ 64-bit EL0
kernel_ventry    1, sync                // Synchronous EL1h
kernel_ventry    0, sync                // Synchronous 64-bit EL0

kernel_ventry是宏,翻译后的函数名分别是:
el1_irq
el0_riq
el1_sync
el0_sync
对应的函数入口我们就找到了,也就是说,当触发irq异常、或svc异常时会跳转到这几个函数中。

(2)、arm32的异常向量表-(irq,fiq,swi......)

在arch架构下,linux kernel的同步异常向量表__stubs_start 和 异步异常向量表__vectors_start,在entry-armv.S中:

    .section .stubs, "ax", %progbits
__stubs_start:
    @ This must be the first word
    .word    vector_swi

    .section .vectors, "ax", %progbits
__vectors_start:
    W(b)    vector_rst
    W(b)    vector_und
    W(ldr)    pc, __vectors_start + 0x1000
    W(b)    vector_pabt
    W(b)    vector_dabt
    W(b)    vector_addrexcptn
    W(b)    vector_irq
    W(b)    vector_fiq

2、在optee中的异常向量表

optee中的异常向量表thread_excp_vect
其中el0_sync_a64和el0_sync_a32是同步异常处理函数,当执行svc指令是会调用该函数;

#define INV_INSN    0
    .section .text.thread_excp_vect
    .align    11, INV_INSN
FUNC thread_excp_vect , :
    /* -----------------------------------------------------
     * EL1 with SP0 : 0x0 - 0x180
     * -----------------------------------------------------
     */
    .align    7, INV_INSN
el1_sync_sp0:
    store_xregs sp, THREAD_CORE_LOCAL_X0, 0, 3
    b    el1_sync_abort
    check_vector_size el1_sync_sp0

    .align    7, INV_INSN
el1_irq_sp0:
    store_xregs sp, THREAD_CORE_LOCAL_X0, 0, 3
    b    elx_irq
    check_vector_size el1_irq_sp0

    .align    7, INV_INSN
el1_fiq_sp0:
    store_xregs sp, THREAD_CORE_LOCAL_X0, 0, 3
    b    elx_fiq
    check_vector_size el1_fiq_sp0

    .align    7, INV_INSN
el1_serror_sp0:
    b    el1_serror_sp0
    check_vector_size el1_serror_sp0

    /* -----------------------------------------------------
     * Current EL with SP1: 0x200 - 0x380
     * -----------------------------------------------------
     */
    .align    7, INV_INSN
el1_sync_sp1:
    b    el1_sync_sp1
    check_vector_size el1_sync_sp1

    .align    7, INV_INSN
el1_irq_sp1:
    b    el1_irq_sp1
    check_vector_size el1_irq_sp1

    .align    7, INV_INSN
el1_fiq_sp1:
    b    el1_fiq_sp1
    check_vector_size el1_fiq_sp1

    .align    7, INV_INSN
el1_serror_sp1:
    b    el1_serror_sp1
    check_vector_size el1_serror_sp1

    /* -----------------------------------------------------
     * Lower EL using AArch64 : 0x400 - 0x580
     * -----------------------------------------------------
     */
    .align    7, INV_INSN
el0_sync_a64:
    restore_mapping

    mrs    x2, esr_el1
    mrs    x3, sp_el0
    lsr    x2, x2, #ESR_EC_SHIFT
    cmp    x2, #ESR_EC_AARCH64_SVC
    b.eq    el0_svc
    b    el0_sync_abort
    check_vector_size el0_sync_a64

    .align    7, INV_INSN
el0_irq_a64:
    restore_mapping

    b    elx_irq
    check_vector_size el0_irq_a64

    .align    7, INV_INSN
el0_fiq_a64:
    restore_mapping

    b    elx_fiq
    check_vector_size el0_fiq_a64

    .align    7, INV_INSN
el0_serror_a64:
    b       el0_serror_a64
    check_vector_size el0_serror_a64

    /* -----------------------------------------------------
     * Lower EL using AArch32 : 0x0 - 0x180
     * -----------------------------------------------------
     */
    .align    7, INV_INSN
el0_sync_a32:
    restore_mapping

    mrs    x2, esr_el1
    mrs    x3, sp_el0
    lsr    x2, x2, #ESR_EC_SHIFT
    cmp    x2, #ESR_EC_AARCH32_SVC
    b.eq    el0_svc
    b    el0_sync_abort
    check_vector_size el0_sync_a32

    .align    7, INV_INSN
el0_irq_a32:
    restore_mapping

    b    elx_irq
    check_vector_size el0_irq_a32

    .align    7, INV_INSN
el0_fiq_a32:
    restore_mapping

    b    elx_fiq
    check_vector_size el0_fiq_a32

    .align    7, INV_INSN
el0_serror_a32:
    b    el0_serror_a32
    check_vector_size el0_serror_a32

3、在ATF中的异常向量表

(1)、同步异常向量表-(smc)

smc同步异常调用的都是handle_sync_exception

sync_exception_aarch64:
    /* -----------------------------------------------------
     * This exception vector will be the entry point for
     * SMCs and traps that are unhandled at lower ELs most
     * commonly. SP_EL3 should point to a valid cpu context
     * where the general purpose and system register state
     * can be saved.
     * -----------------------------------------------------
     */
    handle_sync_exception
    check_vector_size sync_exception_aarch64
sync_exception_aarch32:
    /* -----------------------------------------------------
     * This exception vector will be the entry point for
     * SMCs and traps that are unhandled at lower ELs most
     * commonly. SP_EL3 should point to a valid cpu context
     * where the general purpose and system register state
     * can be saved.
     * -----------------------------------------------------
     */
    handle_sync_exception
    check_vector_size sync_exception_aarch32
handle_sync_exception调用smc_handler64处理同步异常
.macro    handle_sync_exception
/* Enable the SError interrupt */
msr    daifclr, #DAIF_ABT_BIT

str    x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
mrs    x30, esr_el3
ubfx    x30, x30, #ESR_EC_SHIFT, #ESR_EC_LENGTH

cmp    x30, #EC_AARCH32_SMC
b.eq    smc_handler32

cmp    x30, #EC_AARCH64_SMC
b.eq    smc_handler64

/* -----------------------------------------------------
 * The following code handles any synchronous exception
 * that is not an SMC.
 * -----------------------------------------------------
 */

bl    report_unhandled_exception
.endm
(2)、异类步异常向量表-(irq,fiq...)

irq/fiq异步异常调用的是handle_interrupt_exception

irq_aarch64:
    handle_interrupt_exception irq_aarch64
    check_vector_size irq_aarch64

    .align    7
fiq_aarch64:
    handle_interrupt_exception fiq_aarch64
    check_vector_size fiq_aarch64
get_interrupt_type_handler获取ATF注册的中断处理函数
interrupt_type_handler_t get_interrupt_type_handler(uint32_t type)
{
    if (validate_interrupt_type(type))
        return NULL;

    return intr_type_descs[type].handler;
}
handle_interrupt_exception调用ATF中注册的handler函数
    .macro    handle_interrupt_exception label
    /* Enable the SError interrupt */
    msr    daifclr, #DAIF_ABT_BIT

    str    x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
    bl    save_gp_registers

    /*
     * Save the EL3 system registers needed to return from
     * this exception.
     */
    mrs    x0, spsr_el3
    mrs    x1, elr_el3
    stp    x0, x1, [sp, #CTX_EL3STATE_OFFSET + CTX_SPSR_EL3]

    /* Switch to the runtime stack i.e. SP_EL0 */
    ldr    x2, [sp, #CTX_EL3STATE_OFFSET + CTX_RUNTIME_SP]
    mov    x20, sp
    msr    spsel, #0
    mov    sp, x2

    /*
     * Find out whether this is a valid interrupt type. If the
     * interrupt controller reports a spurious interrupt then
     * return to where we came from.
     */
    bl    plat_ic_get_pending_interrupt_type
    cmp    x0, #INTR_TYPE_INVAL
    b.eq    interrupt_exit_\label

    /*
     * Get the registered handler for this interrupt type. A
     * NULL return value could be 'cause of the following
     * conditions:
     *
     * a. An interrupt of a type was routed correctly but a
     *    handler for its type was not registered.
     *
     * b. An interrupt of a type was not routed correctly so
     *    a handler for its type was not registered.
     *
     * c. An interrupt of a type was routed correctly to EL3,
     *    but was deasserted before its pending state could
     *    be read. Another interrupt of a different type pended
     *    at the same time and its type was reported as pending
     *    instead. However, a handler for this type was not
     *    registered.
     *
     * a. and b. can only happen due to a programming error.
     * The occurrence of c. could be beyond the control of
     * Trusted Firmware. It makes sense to return from this
     * exception instead of reporting an error.
     */
    bl    get_interrupt_type_handler
    cbz    x0, interrupt_exit_\label
    mov    x21, x0

    mov    x0, #INTR_ID_UNAVAILABLE

    /* Set the current security state in the 'flags' parameter */
    mrs    x2, scr_el3
    ubfx    x1, x2, #0, #1

    /* Restore the reference to the 'handle' i.e. SP_EL3 */
    mov    x2, x20

    /*  x3 will point to a cookie (not used now) */
    mov    x3, xzr

    /* Call the interrupt type handler */
    blr    x21

interrupt_exit_\label:
    /* Return from exception, possibly in a different security state */
    b    el3_exit

    .endm

剖析该段汇编的关键代码:

bl    get_interrupt_type_handler   //获取注册的中断处理函数, 返回函数地址,保存在X0中
cbz    x0, interrupt_exit_\label
mov    x21, x0  //X0保存到了X21中
.....
blr    x21  //跳转到X21,就是跳转到ATF中的中断处理函数

在这里插入图片描述
《ARMv8/ARMv9架构学习系列课程》全系列,共计51节课,超15h的视频课程


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

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