每个中断控制器都对应一个IRQ Domain;
中断控制器驱动通过irq_domain_add_*()接口来创建IRQ Domain;
IRQ Domain支持三种映射方式:linear map(线性映射),tree map(树映射),no map(不映射);
linear map:维护固定大小的表,索引是硬件中断号,如果硬件中断最大数量固定,并且数值不大,可以选择线性映射;
tree map:硬件中断号可能很大,可以选择树映射;
no map:硬件中断号直接就是Linux的中断号;
三种映射的方式如下图:
图中描述了三个中断控制器,对应到三种不同的映射方式;
各个控制器的硬件中断号可以一样,最终在Linux内核中映射的中断号是唯一的;
4. Arch-speicific代码分析中断也是异常模式的一种,当外设触发中断时,处理器会切换到特定的异常模式进行处理,而这部分代码都是架构相关的;ARM64的代码位于arch/arm64/kernel/entry.S。
ARM64处理器有四个异常级别Exception Level:0~3,EL0级对应用户态程序,EL1级对应操作系统内核态,EL2级对应Hypervisor,EL3级对应Secure Monitor;
异常触发时,处理器进行切换,并且跳转到异常向量表开始执行,针对中断异常,最终会跳转到irq_handler中;
代码比较简单,如下:
/* * Interrupt handling. */ .macro irq_handler ldr_l x1, handle_arch_irq mov x0, sp irq_stack_entry blr x1 irq_stack_exit .endm来张图:
中断触发,处理器去异常向量表找到对应的入口,比如EL0的中断跳转到el0_irq处,EL1则跳转到el1_irq处;
在GIC驱动中,会调用set_handle_irq接口来设置handle_arch_irq的函数指针,让它指向gic_handle_irq,因此中断触发的时候会跳转到gic_handle_irq处执行;
gic_handle_irq函数处理时,分为两种情况,一种是外设触发的中断,硬件中断号在16 ~ 1020之间,一种是软件触发的中断,用于处理器之间的交互,硬件中断号在16以内;
外设触发中断后,根据irq domain去查找对应的Linux IRQ中断号,进而得到中断描述符irq_desc,最终也就能调用到外设的中断处理函数了;
GIC和Arch相关的介绍就此打住,下一篇文章会接着介绍通用的中断处理框架,敬请期待。
参考ARM Generic Interrupt Controller Architecture version 2.0
欢迎关注公众号,不定期更新Linux内核机制相关文章,谢谢。