GICv2与GICv3中断架构对比与LPI中断机制分析
往期内容
本文章相关专栏往期内容,PCI/PCIe子系统专栏:
- 嵌入式系统的内存访问和总线通信机制解析、PCI/PCIe引入
- 深入解析非桥PCI设备的访问和配置方法
- PCI桥设备的访问方法、软件角度讲解PCIe设备的硬件结构
- 深入解析PCIe设备事务层与配置过程
- PCIe的三种路由方式
- PCI驱动与AXI总线框架解析(RK3399)
- 深入解析PCIe地址空间与寄存器机制:从地址映射到TLP生成的完整流程
- PCIe_Host驱动分析_地址映射
- PCIe_Host驱动分析_设备枚举
- PCI/PCIe设备INTx中断机制和MSI中断机制
- MSI-X中断机制、MSI/MSI-X操作流程详解
- RK3399 PCIe 中断处理与映射分析(INTx中断机制源码分析)
Uart子系统专栏:
- 专栏地址:Uart子系统
- Linux内核早期打印机制与RS485通信技术
– 末片,有专栏内容观看顺序interrupt子系统专栏:
- 专栏地址:interrupt子系统
- Linux 链式与层级中断控制器讲解:原理与驱动开发
– 末片,有专栏内容观看顺序pinctrl和gpio子系统专栏:
专栏地址:pinctrl和gpio子系统
编写虚拟的GPIO控制器的驱动程序:和pinctrl的交互使用
– 末片,有专栏内容观看顺序
input子系统专栏:
- 专栏地址:input子系统
- input角度:I2C触摸屏驱动分析和编写一个简单的I2C驱动程序
– 末片,有专栏内容观看顺序I2C子系统专栏:
- 专栏地址:IIC子系统
- 具体芯片的IIC控制器驱动程序分析:i2c-imx.c-CSDN博客
– 末篇,有专栏内容观看顺序总线和设备树专栏:
- 专栏地址:总线和设备树
- 设备树与 Linux 内核设备驱动模型的整合-CSDN博客
– 末篇,有专栏内容观看顺序
目录
- 往期内容
- 1.资料
- 2.GICv2
- 3.GICv3
- 3.1 SPI触发
- 3.2 LPI触发
- 3.3 GICv3所有的中断号
- 4.LPI的触发方式
- 4.1 第一种触发方式
- 4.2 第二种触发方式(常用)
- 5.提问
1.资料
- 《ARM® Generic Interrupt Controller Architecture Specification Architecture version 2.0(IHI0048B_b_gic_architecture_specification_v2).pdf》📎ARM® Generic Interrupt Controller Architecture Specification Architecture version 2.0(IHI0048B_b_gic_architecture_specification_v2).pdf
- 《IHI0069G_gic_architecture_specification.pdf》第5章📎IHI0069G_gic_architecture_specification.pdf
- 《GICv3_Software_Overview_Official_Release_B.pdf》📎GICv3_Software_Overview_Official_Release_B.pdf
- ARM GIC(六)gicv3架构-LPI
2.GICv2
GICv2的三种中断类型
-
软件触发中断(SGI):
- 由软件生成,主要用于不同CPU核之间的通信。每个CPU核可以通过写入SGI寄存器(如
ICDSGIR
)触发中断,并将其发送给所有核或指定的核。 - SGI的中断号为0-15,这些号位于固定的中断号范围内。软件可以决定使用哪些号来通信。
- 由软件生成,主要用于不同CPU核之间的通信。每个CPU核可以通过写入SGI寄存器(如
-
私有外设中断(PPI):
- 由特定CPU核私有的外设生成。这些中断源只针对单个CPU核,因此每个核独立处理自己的PPI。
- PPI的中断号为16-31,典型的例子包括每个CPU核的定时器。
-
共享外设中断(SPI):
- 由系统中共享的外设(即非核私有设备)生成。SPI可以路由到一个或多个CPU核,以处理来自系统级设备的中断请求。
- SPI的中断号为32-1020,它们用于系统中广泛的外设,比如I/O控制器等。
这些中断类型在GICv2中构成了中断处理的基础框架,在GICv3中进一步增强了对更复杂中断场景的支持。
在GICv2里,设备向中断控制器发出中断,必须使用物理上的线路:
之前提到过,就像INTx#,这种采用传统的中断信号线传递中断信号的方式,如果有很多个外设的时候就需要有对应数量的信号线,这是不理想的,因此就引入了像MSI/MSI-X这种采用TPL包触发发送中断信息的方式,设备往某个地址写入数值,即可触发中断。
3.GICv3
MSI如何触发中断在之前的章节就讲过了,往特定的寄存器传值写入触发中断,那这个寄存器的地址???写什么值??? 继续往下看。
3.1 SPI触发
在GICv3中,SPI可以通过MSI的方式触发中断。通常情况下,传统的SPI由外围设备通过硬件信号产生,但通过MSI方式,设备可以直接通过写入消息的方式在GIC中触发中断。要产生或清除SPI中断时,涉及的寄存器操作如下:
产生中断:
-
写寄存器
**GICD_SETSPI_NSR**
(Non-Secure Sets SPI Register)或**GICD_SETSPI_SR**
(Secure Sets SPI Register):- 写入这些寄存器可以触发一个SPI中断。设备或软件可以使用这些寄存器来通知GIC某个中断已被请求。
- 选择
NSR
或SR
取决于中断是在安全世界还是非安全世界触发的。
清除中断:
-
写寄存器
**GICD_CLRSPI_NSR**
(Non-Secure Clear SPI Register)或**GICD_CLRSPI_SR**
(Secure Clear SPI Register):- 在中断处理完成后,清除这些寄存器可以停止对应的SPI中断。
3.2 LPI触发
而GIC V3里新增加了一类中断:LPI(Locality-specific Peripheral Interrupts)框图如下:
在GICv3中,LPI(Locality-specific Peripheral Interrupt)是一种特别为MSI设计的低延迟中断。LPI专门用于大量MSI的场景,比如虚拟化环境中为每个虚拟设备提供独立的中断号。LPI的触发方式与传统的SPI不同。
触发方式1:写寄存器**GICR_SETLPIR**
- GICR_SETLPIR寄存器用于直接触发某个特定的LPI中断。
- 设备或软件可以通过写入该寄存器触发LPI,而不是依赖于
GITS_TRANSLATER
机制。这种方式更直接。
触发方式2:写寄存器**GITS_TRANSLATER**
- GITS_TRANSLATER寄存器是GICv3中的一部分,位于ITS(Interrupt Translation Service)中。
- 当设备触发MSI时,它会将数据写入
GITS_TRANSLATER
,其中的数据(称为EventID)与LPI的映射表关联,进而触发相应的LPI中断。 - EventID可以看作是LPI的标识符。通过ITS,GIC能够将MSI消息转换为对应的LPI,并将其路由到适当的CPU。
3.3 GICv3所有的中断号
0~1023跟GICv2保存一致。
INTID | 中断类型 | 描述 |
---|---|---|
0~15 | SGI | |
16~31 | PPI | |
32~1019 | SPI | 设备发出的中断 |
1020~1023 | SPI | 用于特殊目的 |
1024~1055 | - | 保留 |
1056~1119 | PPI | 扩展的PPI,GICv3.1才支持 |
1120~4095 | - | 保留 |
4096~5119 | SPI | 扩展的SPI,GICv3.1才支持 |
5120~8191 | - | 保留 |
8192~芯片实现 | LPI |
4.LPI的触发方式
在上文中提到过两种触发方式,都是往寄存器写值,寄存器长啥样?写入什么类型的值?
4.1 第一种触发方式
直接写入GICR_SETLPIR寄存器
把LPI的中断号(INT ID)写入这个寄存器即可触发中断。
4.2 第二种触发方式(常用)
-
外设发送中断消息到ITS
-
当外设产生中断时,它会通过写入
GITS_TRANSLATER
(上图)寄存器发送一个中断消息。这个消息中包含两个重要的标识符: -
DeviceID:标识哪个设备发出了中断。这是外设的唯一ID。
-
EventID:标识同一个设备上哪个具体事件发生了中断。一个设备可以触发多个中断,每个中断对应不同的EventID。
-
外设并不需要知道如何将这些ID转换成中断号(INTID)或路由到哪个处理器,这些都由GICv3的ITS模块处理。
-
ITS查找Device Table
-
当ITS接收到包含
DeviceID
和EventID
的消息后,它会首先根据DeviceID在Device Table中查找该设备的记录。- Device Table 是一个全局表,每个能够产生MSI中断的设备在这个表中有一项记录。
- 这项记录指向该设备的Interrupt Translation Table(ITT, 中断转换表)。每个设备都有自己的ITT,用于将EventID映射到GIC中的中断ID(INTID)。
-
-
ITS查找Interrupt Translation Table(ITT)
-
ITS使用EventID在设备的ITT中查找一项记录。
-
ITT 中的每一项记录包含:
- INTID:这是最终传递到GIC中的中断标识符。GIC使用INTID来识别和处理这个中断。
- Collection ID:用于标识该中断应该被路由到哪个处理器上的Redistributor。
-
-
-
ITS查找Collection Table
-
ITS根据从ITT中找到的Collection ID在Collection Table中查找。
-
Collection Table保存每个中断目标的信息。它包含将中断路由到哪个CPU核上的信息,即"Target Redistributor"。
-
-
中断路由到目标Redistributor
- ITS查找完Collection Table后,找到中断应发送的目标处理器(Redistributor)。
- 然后,它会将中断消息发往目标Redistributor,GIC最终将中断投递到对应的CPU核,完成中断处理。
总的大概就是:
- 外设发送中断消息(DeviceID + EventID) → ITS接收消息
- ITS使用DeviceID查找Device Table → 找到设备的ITT
- ITS使用EventID查找ITT → 找到INTID和Collection ID
- ITS使用Collection ID查找Collection Table → 找到目标Redistributor(处理器)
- 中断消息发送到目标Redistributor → 投递到CPU,处理中断
Device Table、Interrupt Translation Table、Collection Table都是在内存里,但是我们不能直接去设置内存。而是通过发送ITS命令来设置这些表格。
5.提问
回到之前的提问,MSI如何触发中断在之前的章节就讲过了,往特定的寄存器传值写入触发中断,那这个寄存器的地址???写什么值???
看完上面就知道的差不多了,只不过需要注意的是寄存器的地址,外设在使用的时候是经过映射的pci_addr