baron · 3月28日 · 四川

optee中的中断处理详解

快速连接

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


 title=

1、注册一个中断

注册中断很简单,itr_add和itr_enable就可以了

struct itr_handler temp_irq = {
    50,    //中断号
    0,    //flag
    temp_itr_handler,  //handler
    &temp_data[0],   //paramaters
    {NULL}   //link
};

itr_add(&temp_irq);
itr_enable(50);

2、调用到中断处理函数

在secure中断产生后,PE跳转到optee的中断向量表中的irq offset:

el1_irq_sp0:
    store_xregs sp, THREAD_CORE_LOCAL_X0, 0, 3
    b    elx_irq
    check_vector_size el1_irq_sp0

调用native_intr_handler函数

LOCAL_FUNC elx_irq , :
#if defined(CFG_ARM_GICV3)
    native_intr_handler    irq
#else
    foreign_intr_handler    irq
#endif
END_FUNC elx_irq

native_intr_handler调用thread_nintr_handler_ptr,也就是在平台中注册的handler函数

/* The handler of native interrupt. */
.macro native_intr_handler mode:req
    /*
     * Update core local flags
     */
    ldr    w1, [sp, #THREAD_CORE_LOCAL_FLAGS]
    lsl    w1, w1, #THREAD_CLF_SAVED_SHIFT
    .ifc    \mode\(),fiq
    orr    w1, w1, #THREAD_CLF_FIQ
    .else
    orr    w1, w1, #THREAD_CLF_IRQ
    .endif
    orr    w1, w1, #THREAD_CLF_TMP
    str    w1, [sp, #THREAD_CORE_LOCAL_FLAGS]

    /* load tmp_stack_va_end */
    ldr    x1, [sp, #THREAD_CORE_LOCAL_TMP_STACK_VA_END]
    /* Keep original SP_EL0 */
    mrs    x2, sp_el0
    /* Switch to SP_EL0 */
    msr    spsel, #0
    mov    sp, x1

    /*
     * Save registers on stack that can be corrupted by a call to
     * a C function
     */
    /* Make room for struct elx_nintr_rec */
    sub    sp, sp, #ELX_NINTR_REC_SIZE
    /* Store x4..x18 */
    store_xregs sp, ELX_NINTR_REC_X(4), 4, 18
    /* Store lr and original sp_el0 */
    stp    x30, x2, [sp, #ELX_NINTR_REC_LR]

    bl    thread_check_canaries
    adr    x16, thread_nintr_handler_ptr
    ldr    x16, [x16]
    blr    x16

    /*
     * Restore registers
     */
    /* Restore x4..x18 */
    load_xregs sp, ELX_NINTR_REC_X(4), 4, 18
    /* Load  lr and original sp_el0 */
    ldp    x30, x2, [sp, #ELX_NINTR_REC_LR]
    /* Restore SP_El0 */
    mov    sp, x2
    /* Switch back to SP_EL1 */
    msr    spsel, #1

    /* Update core local flags */
    ldr    w0, [sp, #THREAD_CORE_LOCAL_FLAGS]
    lsr    w0, w0, #THREAD_CLF_SAVED_SHIFT
    str    w0, [sp, #THREAD_CORE_LOCAL_FLAGS]

    mrs    x0, spsr_el1
    /* Restore x2..x3 */
    load_xregs sp, THREAD_CORE_LOCAL_X2, 2, 3
    b_if_spsr_is_el0 w0, 1f

    /* Restore x0..x1 */
    load_xregs sp, THREAD_CORE_LOCAL_X0, 0, 1

    /* Return from exception */
    eret
1:    b    eret_to_el0
.endm

平台的gic中段函数注册,在arch/arm/plat-xxx/main.c中

static const struct thread_handlers handlers = {
    .std_smc = tee_entry_std,
    .fast_smc = tee_entry_fast,
    .nintr = main_fiq,
#if defined(CFG_WITH_ARM_TRUSTED_FW)
    .cpu_on = cpu_on_handler,
    .cpu_off = pm_do_nothing,
    .cpu_suspend = pm_do_nothing,
    .cpu_resume = pm_do_nothing,
    .system_off = pm_do_nothing,
    .system_reset = pm_do_nothing,
#else
    .cpu_on = pm_panic,
    .cpu_off = pm_panic,
    .cpu_suspend = pm_panic,
    .cpu_resume = pm_panic,
    .system_off = pm_panic,
    .system_reset = pm_panic,
#endif
};

如果使用的是gic,在平台的handler函数中,会直接调用gic中的gic_it_handle

static void main_fiq(void)
{
    gic_it_handle(&gic_data);
}

我们在看gic_it_handle函数,也是非常的简单,

void gic_it_handle(struct gic_data *gd)
{
    uint32_t iar;
    uint32_t id;

    iar = gic_read_iar(gd);  //------------------------从gic中读取中断号
    id = iar & GICC_IAR_IT_ID_MASK;

    if (id < gd->max_it)
        itr_handle(id);    //--------------------调用itr_add注册的中断处理函数
    else
        DMSG("ignoring interrupt %" PRIu32, id);

    gic_write_eoir(gd, iar);   //--------------------取消中断active(或者叫清除gic中的中断标记)
}

调用gic_it_add注册的中断处理函数

void itr_handle(size_t it)
{
    struct itr_handler *h = find_handler(it);    //----------------------- 找到itr_add注册时添加的handler

    if (!h) {
        EMSG("Disabling unhandled interrupt %zu", it);
        itr_chip->ops->disable(itr_chip, it);
        return;
    }

    if (h->handler(h) != ITRR_HANDLED) {    //-----------------------执行handler
        EMSG("Disabling interrupt %zu not handled by handler", it);
        itr_chip->ops->disable(itr_chip, it);
    }
}

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

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