中断控制器驱动
由于linux支持中断控制器的级联,因此多个中断控制器就可能包含相同的硬件中断号。为了可以通过中断号唯一地标识一个中断,linux引入了irq domain机制以实现将硬件中断号映射为全局唯一的逻辑中断号。
Hwirq映射到irq
- 每个中断控制器都对应一个IRQ Domain;
- 中断控制器驱动通过irq_domain_add_*()接口来创建IRQ Domain;
- IRQ Domain支持三种映射方式:linear map(线性映射),tree map(树映射),no map(不映射);
- linear map:维护固定大小的表,索引是硬件中断号,如果硬件中断最大数量固定,并且数值不大,可以选择线性映射;
- tree map:硬件中断号很大时,可以选择树映射;
- no map:硬件中断号直接就是Linux的中断号;
说明:
- 每个中断控制器对应一个irq_domain,使用链表将多个irq域组织起来。
- 每个irq对应一个irq_desc结构体
- hwirq_max:该 irq_domain 支持的中断最大数量
- revmap_size:映射表的大小
- revmap_direct_max_irq:此中断控制器支持的直接映射的最大中断数量
- revmap_tree:树映射的映射表
- linear_revmap[]:hwirq->virq 映射的线性表。索引是硬件中断号
通过这三种方式将硬件中断号映射成全局唯一的中断号。
但目前hwirq和irq直接的关系还没有完全建立起来,因此我们还不能用irq来注册中断
建立双向联系irq < --- > hwirq
说明:
- irq_data:包含中断控制器的硬件数据。在domain里面利用linear_revmap(线性)或者revmap_tree(radix tree)来保存irq_data结构。因此可以以hwirq为key值从revmap_tree或者linear_revmap当中获取到irq_data数据结构
irq_desc是一个irq对应的描述结构体,每个irq对应一个该结构,在irq_desc结构体里面有irq_data
Arch-specific code
这部分与具体的CPU架构相关,不同的架构有不同的执行方式。以ARMv8为例,具体见下面的Arch-specific中断处理流程源码分析。大概流程是:
enable_da_f:开启PSTATE的A/D/S(SError中断/调试异常/FIQ),保持irq关闭,防止中断嵌套
diable_daif: 关闭中断
恢复中断:
第一个关中断是硬件自动实现的,然后保存现场后将高优先级的中断打开,之后恢复现场前再次关中断,恢复之后才开中断。三次开关操作,如上所示