一颗SOC集成了大量的外设,如何有序的控制和响应这些中断呢?
不同体系结构对中断控制器有着不同的设计理念,但是其设计方法基本相同。ARM公司提供了一个通用中断控制器GIC(Generic Interrupt Controller)。目前最新版本的GIC规范是version 3/4,支持Armv8-A,Armv8-R,Armv9-A架构,version 2通常在ARMv7处理器中使用。
gic v2
中断状态
gic为每个中断维护着4个状态,inac
tive、pending、active、active and pending。
中断类型
gic支持的中断类型有外设中断、软件中断。其中外设中断源来自于硬件,软件中断是通过软件写gic寄存器产生的。
gic v2架构划分
gic从逻辑上分为Distributor和CPU interface。Distributor是中断的统一入口,负责分发中断给具体的CPU。每个CPU都有一个CPU interface负责本CPU的中断屏蔽和抢占的。
Distributor的编程接口主要有:
中断ID
中断处理流程
其中第五步,CPU读取GICC_IAR寄存器来响应该中断(一般是linux内核程序来读取寄存器),寄存器返回硬件中断号;第六步,CPU处理完中断后写GICC_EOIR寄存器来通知CPU interface。
硬件中断号与Linux软件中断号的映射
每一款ARM SOC在芯片设计阶段时,就会把各种中断和外设分配情况固定下来,因此对于底层软件来说,需要查询SOC的芯片手册来确定的外设的中断号。
随着芯片硬件的发展,使用直接映射的方式难以应对多个中断控制器级联的情况,Linux引入了irq domain的管理框架,irq domain框架可支持多个中断控制器并且完美地支持device tree机制。git_init_of->gic_init_bases->__irq_domain_add(),添加到全局变量irq_domain_list。
注册中断的API函数request_irq()/requeset_threaded_irq()是使用内核软件中断号,而不是硬件中断号,那它们是如何映射的呢?
一般通过调用核心函数irq_of_parse_and_map来解析DTS中的硬件中断号,返回内核使用的IRQ中断号。
它初始化时在位图中寻找空闲的bit来分配描述符。
irq_of_parse_and_map()->irq_domain_alloc_irqs()->__irq_alloc_descs()->bitmap_find_next_zero_area()
在内核中有两种方式来分配struct irq_desc数据结构,一是内核配置了CONFIG_SPARSE_IRQ使用radix tree树结构来存储;二是采用数组的方式,定义一个全局的数组struct irq_desc irq_desc[NR_IRQS],每个中断对应一个元素。
struct irq_desc包含struct irq_data,其中irq是软件中断号,hwirq是硬件中断号,当这两个成员填写完成,即完成了硬件中断的注册。struct irq_data包含struct irq_chip,struct irq_chip是硬件中断控制器操作的抽象接口,如使能/去使能、响应、完成等接口。
gic v3
gic V3变化点
扩展性
v2架构最多支持8个PE,v3架构通过redistributor组件来引入affinity routing机制可以支持更多的PE。
中断分组
Group 0 physical interrupts are expected to be handled at the highest implemented Exceptionlevel.
Secure Group 1 physical interrupts are expected to be handled at Secure EL1 or Secure EL2.
Non-secure Group 1 physical interrupts are excepted to be handled at Non-secure EL1 or Non-secure EL2.
将cpu interface独立出来,用户可以将其设计在core内部
增加了LPI(Locality-specific Peripheral Interrupt),使用ITS(Interrupt Translation Service)来解析
v3逻辑架构图
The Distributor provides the routing configuration for SPIs, and holds all the associated routing and priority
information.
The Redistributor provides the configuration settings for PPIs and SGIs.
A Redistributor always presents the pending interrupt with the highest priority to the CPU interface in finite time.
v3架构支持affinity routing,在MPIDR_EL1寄存器中,Aff3.Aff2.Aff1.Aff0。
寄存器前缀