一、gic V2
①、中断状态:
gic为每个中断维护着4个状态,inactive、pending、active、active and pending
The following states apply at each interface between the GIC and a connected processor:
Inactive: An interrupt that is not active or pending.
Pending: An interrupt from a source to the GIC that is recognized at asserted in hardware,or generated by software,and is waitting to be serviced by a target processor.
Active: An interrupt from a source to the GIC thar has been acknowledeged by a processor, and is beging serviced but has not completed.
Active and pending: A processor is servicing the interrupt and the GIC has a pending interrupt from the same source.
②、中断类型
gic支持的中断类型有外设中断、软件中断。其中外设中断源来自于硬件,软件中断通过软件写gic寄存器产生的。
Peripheral interrupt This ia an interrupt asserted by a signal to th GIC.The GIC architecture defines the following types of perpheral interrupt:
Private Peripheral Interrupt(PPI):This is a peripheral interrupt that is specific to a single processor.
Shared Peripheral Interrupt(SPI): This is a peripheral interrunpt that the Distributor can route to any o a specified combination of processors.
Each peripheral interrupt is either:
Edge-triggered
This is an interrupt that is asserted on detection of a rising edeg of an interruptt signal and then,regardless of the state of the signal,remains asserted until it is cleared by by the conditions defined by this specification.
Level-sensitive
This is an interrupt that is asserted whenever the interrupt signal level is active,and deasserted whenever the level is not active.
Software-generated interrupt(SGI)
This is an interrupt generated by software writing to a GICD_SGIR register in the GIC.The system uses SGIs for interprocessor communication.
An SGI has edge-triggered properties. The software triggering of the interrupt is equivalent to the edge transition of the interrupt requeset signal.
When an SIG occurs in a multiprocessor implementation, the CPUID field in the Interrupt Acknowledeg Register,GICC_IAR, or the Aliased Interrupt Acknowledeg Register, GICC_AIAR,identifies the processor that requested the interrupt.
In an implementaion that includes the GIC Virtualization Extensions:
- when an SGI occurs, management registers in the GIC virtualization Extensions enable the requesting processor to be reported to the Guest OS
- by writing to the management registers in the GIC Virtualization Extensions, a hypervisor can generate a virtual interrupt that appears to a virtual machine as an SGI.
③、gic v2架构划分
gic从逻辑上分为Distributor和CPU interface。Distributor是中断的统一入口,负责分发中断给具体的CPU。每个CPU都有一个CPU interface负责本CPU的中断屏蔽和抢占。
Distributor The Distributor block performs interrupt prioritization and distribution on the CPU interface blocks that connect to the processors in the system.
The Distributor block regisgers are identified by the GICD_prefix.
CPU Interfaces Each CPU interface block performs priority masking and prempting handling for a connected processor in the system
CPU interface block register are identified by the GICC_prefix.
When describing a GIC that includes the GIC Virtualization Extensions, a CPU interface is sometimes called a physical CPU interface, to avoid possibel confusion with cpu interface.
Distributor的编程接口主要有:
The Distributor provides a programming interface for:
- Globally enabling the forwarding of interrupts to the CPU interfaces.
- Enabling or disabling each interrupt.
- Setting the priority level if each interrupt.
- Setting the target processor list of each interrupt.
- Setting each peripheral interrupt to be level-sensitive or edge-triggered.
- Setting each interrupt as either Group 0 or Group 1.
参考连接:https://www.cnblogs.com/lvzh/p/15058027.html
④、中断ID和中断处理流程
Interrupt IDs
Interrupts from sources are identifiled usring ID numbers.Each CPU interface can set up to 1020 interrupts.The banking of SPIs and PPIs increase the total number of interrupts supported by the Distributor.
The GIC assigns interrupt ID numbers ID0-ID1019 as follows:
- Interrupt numbers ID32-ID1019 are used for SPIs.
- Interrupt numbers ID0-ID31 are used for interrupts that are private to a CPU interface. These interrupts are banked in the Distributor.
A banked interrupt is one where the Distributor can have multiple interrupts with the same ID.A banked interrupt is identified uniquely by its ID number and its associated CPU interface number. Of the banked interrupt IDS:
ID0-ID15 are used for SGIs
ID16-ID31 are used for PPIs
中断处理流程
When the GIC recognizes an interrupt request, it marks its state as pending.Regenerating a pending interrupt does not affect the state of the interrupt.
The GIC interrupt handling sequence is
- The GIC determines the interrupts that are enabled.
- For each pending interrupt, the GIC determines the targeted processor or processors.
- For each CPU interface, The Distributor forwards the highest priority pending interrupt that targets that interface.
- Each CPU interface determnes whether to signal an interrupt request to its processor,and if required,does so.
- The processor acknoeledeg the interrupt,and the GIC returns the interrupt ID and updated the interrupt state.
- After processiong the interrupt, the processor signals End of Interrupt(EOI) to the GIC.
其中第五步,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
是硬件中断控制器操作的抽象接口,如使能/去使能、响应、完成等接口。
struct irq_data {unsigned int irq;unsigned long hwirq;struct irq_chip *chip;...
};
struct irq_chip {const char *name;unsigned int (*irq_startup)(struct irq_data *data);void (*irq_shutdown)(struct irq_data *data);void (*irq_enable)(struct irq_data *data);void (*irq_disable)(struct irq_data *data);void (*irq_ack)(struct irq_data *data);void (*irq_mask)(struct irq_data *data);void (*irq_mask_ack)(struct irq_data *data);void (*irq_unmask)(struct irq_data *data);void (*irq_eoi)(struct irq_data *data);...
};
参考:zhuanlan.zhihu.com/p/85353687
二、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 handled at Secure EL1 or Secure EL2.
Non-secure Group 1 physical interrupts are excepted to handled at Non-secure EL1 or Non-secure EL2.
- 将cpu interface独立出来,用户可以将其设计再core内部
- 增加了LPI(Locality-specific Peripyeral Intertupt),使用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。
③、中断路由
GICv3 使用 hierarchy 来标识一个具体的 core, 如下图是一个四层的结构(aarch64):
用 <affinity level 3>.<affinity level 2>.<affinity level 1>.<affinity level 0> 的形式组成一个 PE 的路由。每一个 core 的 affnity 值可以通过 MPDIR_EL1 寄存器获取, 每一个 affinity 占用8bit。配置对应 core 的 MPIDR 值,可以将中断路由到该 core 上。
https://oss-emcsprod-public.modb.pro/wechatSpider/modb_20210802_1251295a-f365-11eb-a003-00163e068ecd.png
各个 affinity 的定义是根据 SOC 自己的定义,比如:
<group of groups>. <group of processors>.<processor>.<core>
<group of processors>.<processor>.<core>.<thread>