翼度科技»论坛 云主机 LINUX 查看内容

GICV3中断控制器调用流程

8

主题

8

帖子

24

积分

新手上路

Rank: 1

积分
24
GICV3中断控制器初始化调用链

  1. /kernel/irq/handle.c:
  2. #ifdef CONFIG_GENERIC_IRQ_MULTI_HANDLER
  3. int __init set_handle_irq(void (*handle_irq)(struct pt_regs *))
  4. {
  5.     if (handle_arch_irq)
  6.         return -EBUSY;
  7.     handle_arch_irq = handle_irq;
  8.     return 0;
  9. }
  10. #endif
复制代码
  1. /drivers/irqchip/irq-gic-v3.c:
  2. static int __init gic_init_bases(void __iomem *dist_base,
  3.                  struct redist_region *rdist_regs,
  4.                  u32 nr_redist_regions,
  5.                  u64 redist_stride,
  6.                  struct fwnode_handle *handle)
  7. {
  8. ... ...
  9.     set_handle_irq(gic_handle_irq);
  10. ... ...
  11. }
复制代码
  1. /drivers/irqchip/irq-gic-v3.c:
  2. IRQCHIP_DECLARE(gic_v3, "arm,gic-v3", gic_of_init);
  3. static int __init gic_of_init(struct device_node *node, struct device_node *parent)
  4. {
  5. ... ...
  6.     err = gic_init_bases(dist_base, rdist_regs, nr_redist_regions,
  7.                  redist_stride, &node->fwnode);
  8. ... ....
  9. }
复制代码
  1. /include/linux/irqchip.h:
  2. #define IRQCHIP_DECLARE(name, compat, fn) OF_DECLARE_2(irqchip, name, compat, fn)
  3. /include/linux/of.h:
  4. #define OF_DECLARE_2(table, name, compat, fn) \
  5.         _OF_DECLARE(table, name, compat, fn, of_init_fn_2)
  6.         
  7. #define _OF_DECLARE(table, name, compat, fn, fn_type)            \
  8.     static const struct of_device_id __of_table_##name        \
  9.         __used __section(__##table##_of_table)            \
  10.          = { .compatible = compat,                \
  11.              .data = (fn == (fn_type)NULL) ? fn : fn  }
复制代码
  1. /arch/arm64/kernel/vmlinux.lds:
  2. .init.data : {
  3. ... ...
  4. . = ALIGN(8); __irqchip_of_table = .; KEEP(*(__irqchip_of_table)) KEEP(*(__irqchip_of_table_end)) . = ALIGN(8);
  5. ... ...
  6. }
复制代码
  1. /drivers/irqchip/irqchip.c:
  2. void __init irqchip_init(void)
  3. {
  4.     of_irq_init(__irqchip_of_table);
  5.     acpi_probe_device_table(irqchip);
  6. }
复制代码
  1. /arch/arm64/kernel/irq.c:
  2. void __init init_IRQ(void)
  3. {
  4.     init_irq_stacks();
  5.     irqchip_init();
  6. ... ...
  7. }
复制代码
  1. asmlinkage __visible void __init start_kernel(void)
  2. {
  3. ... ...
  4. init_IRQ();
  5. ... ...
  6. }
复制代码
中断的处理过程


异常向量表vectors
  1. /arch/arm64/kernel/entry.S:
  2. ENTRY(vectors)
  3.     kernel_ventry    1, sync_invalid            // Synchronous EL1t
  4.     kernel_ventry    1, irq_invalid            // IRQ EL1t
  5.     kernel_ventry    1, fiq_invalid            // FIQ EL1t
  6.     kernel_ventry    1, error_invalid        // Error EL1t
  7.     kernel_ventry    1, sync                // Synchronous EL1h
  8.     kernel_ventry    1, irq                // IRQ EL1h
  9.     kernel_ventry    1, fiq_invalid            // FIQ EL1h
  10.     kernel_ventry    1, error            // Error EL1h
  11.     kernel_ventry    0, sync                // Synchronous 64-bit EL0
  12.     kernel_ventry    0, irq                // IRQ 64-bit EL0
  13.     kernel_ventry    0, fiq_invalid            // FIQ 64-bit EL0
  14.     kernel_ventry    0, error            // Error 64-bit EL0
  15. #ifdef CONFIG_COMPAT
  16.     kernel_ventry    0, sync_compat, 32        // Synchronous 32-bit EL0
  17.     kernel_ventry    0, irq_compat, 32        // IRQ 32-bit EL0
  18.     kernel_ventry    0, fiq_invalid_compat, 32    // FIQ 32-bit EL0
  19.     kernel_ventry    0, error_compat, 32        // Error 32-bit EL0
  20. #else
  21.     kernel_ventry    0, sync_invalid, 32        // Synchronous 32-bit EL0
  22.     kernel_ventry    0, irq_invalid, 32        // IRQ 32-bit EL0
  23.     kernel_ventry    0, fiq_invalid, 32        // FIQ 32-bit EL0
  24.     kernel_ventry    0, error_invalid, 32        // Error 32-bit EL0
  25. #endif
  26. END(vectors)
复制代码
el1_irq
  1. /arch/arm64/kernel/entry.S:
  2.     .align    6
  3. el1_irq:
  4.     kernel_entry 1
  5.     gic_prio_irq_setup pmr=x20, tmp=x1
  6.     enable_da_f
  7. #ifdef CONFIG_ARM64_PSEUDO_NMI
  8.     test_irqs_unmasked    res=x0, pmr=x20
  9.     cbz    x0, 1f
  10.     bl    asm_nmi_enter
  11. 1:
  12. #endif
  13. #ifdef CONFIG_TRACE_IRQFLAGS
  14.     bl    trace_hardirqs_off
  15. #endif
  16.     irq_handler
  17. #ifdef CONFIG_PREEMPT
  18.     ldr    x24, [tsk, #TSK_TI_PREEMPT]    // get preempt count
  19. alternative_if ARM64_HAS_IRQ_PRIO_MASKING
  20.     /*
  21.      * DA_F were cleared at start of handling. If anything is set in DAIF,
  22.      * we come back from an NMI, so skip preemption
  23.      */
  24.     mrs    x0, daif
  25.     orr    x24, x24, x0
  26. alternative_else_nop_endif
  27.     cbnz    x24, 1f                // preempt count != 0 || NMI return path
  28.     bl    arm64_preempt_schedule_irq    // irq en/disable is done inside
  29. 1:
  30. #endif
  31. #ifdef CONFIG_ARM64_PSEUDO_NMI
  32.     /*
  33.      * When using IRQ priority masking, we can get spurious interrupts while
  34.      * PMR is set to GIC_PRIO_IRQOFF. An NMI might also have occurred in a
  35.      * section with interrupts disabled. Skip tracing in those cases.
  36.      */
  37.     test_irqs_unmasked    res=x0, pmr=x20
  38.     cbz    x0, 1f
  39.     bl    asm_nmi_exit
  40. 1:
  41. #endif
  42. #ifdef CONFIG_TRACE_IRQFLAGS
  43. #ifdef CONFIG_ARM64_PSEUDO_NMI
  44.     test_irqs_unmasked    res=x0, pmr=x20
  45.     cbnz    x0, 1f
  46. #endif
  47.     bl    trace_hardirqs_on
  48. 1:
  49. #endif
  50.     kernel_exit 1
  51. ENDPROC(el1_irq)
复制代码
el0_irq
  1.     .align    6
  2. el0_irq:
  3.     kernel_entry 0
  4. el0_irq_naked:
  5.     gic_prio_irq_setup pmr=x20, tmp=x0
  6.     ct_user_exit_irqoff
  7.     enable_da_f
  8. #ifdef CONFIG_TRACE_IRQFLAGS
  9.     bl    trace_hardirqs_off
  10. #endif
  11. #ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
  12.     tbz    x22, #55, 1f
  13.     bl    do_el0_irq_bp_hardening
  14. 1:
  15. #endif
  16.     irq_handler
  17. #ifdef CONFIG_TRACE_IRQFLAGS
  18.     bl    trace_hardirqs_on
  19. #endif
  20.     b    ret_to_user
  21. ENDPROC(el0_irq)
复制代码
irq_handler
  1. /arch/arm64/kernel/entry.S:
  2. /*
  3. * Interrupt handling.
  4. */
  5.     .macro    irq_handler
  6.     ldr_l    x1, handle_arch_irq
  7.     mov    x0, sp
  8.     irq_stack_entry
  9.     blr    x1
  10.     irq_stack_exit
  11.     .endm
复制代码
gic_handle_irq
  1. /drivers/irqchip/irq-gic-v3.c:
  2. static asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs)
  3. {
  4.     u32 irqnr;
  5.     irqnr = gic_read_iar();
  6. ... ...
  7.     /* Check for special IDs first */
  8.     if ((irqnr >= 1020 && irqnr <= 1023))
  9.         return;
  10.     /* Treat anything but SGIs in a uniform way */
  11.     if (likely(irqnr > 15)) {
  12. ... ...
  13.         err = handle_domain_irq(gic_data.domain, irqnr, regs);
  14. ... ...
  15.     }
  16.     if (irqnr < 16) {
  17.         gic_write_eoir(irqnr);
  18.         if (static_branch_likely(&supports_deactivate_key))
  19.             gic_write_dir(irqnr);
  20. #ifdef CONFIG_SMP
  21.         /*
  22.          * Unlike GICv2, we don't need an smp_rmb() here.
  23.          * The control dependency from gic_read_iar to
  24.          * the ISB in gic_write_eoir is enough to ensure
  25.          * that any shared data read by handle_IPI will
  26.          * be read after the ACK.
  27.          */
  28.         handle_IPI(irqnr, regs);
  29. #else
  30.         WARN_ONCE(true, "Unexpected SGI received!\n");
  31. #endif
  32.     }
  33. }
复制代码
中断状态



  • 硬件触发中断信号,中断assert,GIC标记中断为PENDING状态。
  • GIC中distributor选择优先级最高的PENDING中断,发送给CPU interface, CPU interface对优先级进行判定,然后GIC发送中断请求信号给CPU, CPU进入中断异常后,通过GICC_IAR读取硬中断号,中断进入ACTIVE状态。
  • 硬件触发新的中断信号,中断assert, GIC标记中断为ACTIVE_AND_PENDING状态
  • CPU完成中断处理,发送EIO信号到GIC(写EOIR寄存器)
需要注意的是,INACTIVE PENDING ACTIVE ACTIVE_AND_PENDING,在此例中均属于GIC硬件所标记的中断状态,另外当GIC中断信号处于PENDING状态时,硬件外设无法发送新的中断信号给GIC中断控制器。事实上中断属异步通知并且没有排队的概念。

来源:https://www.cnblogs.com/forwards/p/18310037
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具