ARM GIC 学习专栏 --> 点击这里 <—
1. GICv2
ARM的 cpu,特别是 cortex-A 系列的 CPU,都是多 core 的 cpu,因此对于多 core 的 cpu 的中断管理,就不能像单 core 那样简单去管理,由此 arm定义了GICv2 架构,来支持多核 cpu 的中断管理。GICv2,支持最大 8个 core。其框图如下图所示:
Fiture 1-1 ARM GICv2
GICv2 中断类型
Fiture 1-2 ARM GICv2 内部实现
GICV2有3种中断:
- 软件触发中断(SGI,SoftwareGenerated Interrupt)
这是由软件通过写入专用仲裁单元的寄存器即软件触发中断寄存器(ICDSGIR)显式生成的。它最常用于CPU核间通信。SGI既可以发
给所有的核,也可以发送给系统中选定的一组核心。中断号0-15保留用于SGI的中断号。用于通信的确切中断号由软件决定。 - 私有外设中断(PPI,Private Peripheral Interrupt)
这是由单个CPU核私有的外设生成的。PPI的中断号为16-31。它们标识CPU核私有的中断源,并且独立于另一个内核上的相同中源,
比如,每个核的计时器。 - 共享外设中断(SPI,Shared Peripheral Interrupt)
这是由外设生成的,中断控制器可以将其路由到多个核。中断号为32-1020。SPI用于从整个系统可访问的各种外围设备发出中断信号
在GICv2里, 设备向中断控制器发出中断,必须使用物理上的线路:
Fiture 1-3 Dedicated interrupt signal
在复杂系统中有成本上千的中断时, 就需要成本上千的中断信号线这太复杂了。
于是在GICv3中引入 MSI(“message-based interrupts”), 设备往某个地址写入数值,即可触发中断
2. GICv3
2.1 MSI
在GICv3里,添加了 MSI(“message-based interrupts”), 设备往某个地地址写入数值, 即可触发中断:
使用消息来发送中断, 好处是可以省略硬件线路。在大型系统中有成百上千个中断,使用MSI可以省下很多线路。
Fiture 1-4 GIC MSI
2.2 GICv3 内部结构
GICV3里新增加了一类中断: IPI(Locality-specific Peripheral Interrupts)
GICv3 框图如下:
Fiture 1-4 GIC logical partitioning with an ITS
1. 设备写 GITS_TRANSLATER 触发中断
2. 设备写 GICR_SETLPIR 触发中断
对于原来的 SPI, 它也是可以使用MSI的方式传递的,这个功能是可选的。如果GICV3支持MSI方式的SPI,要产生/清除中断时, 操乍如下
GIC寄存器:
- 产生中断:写寄存器 GICD_SETSPI_NSR或 GICD_SETSPI_SR
- 清除中断:写寄存器 GICD_CLRSPI_NSR 或 GICD_CLRSPI_SR
对于LPI中断,有两种触发方式:
- 写寄存器 GITS_TRANSLATER
- 设备把数据写入GITS_TRANSLATER寄存器,写入的值被称为EventlD
- 写寄存器 GICR_SETLPIR
2.3 中断号
0~1023跟GICv2保存一致。
3. LPI 的触发方式
LPI有两种触发中断的方式:
- 把INTID直接写入GICR_SETLPIR寄存器
- 使用 ITS把 EventID 转换为 LPI INTID, 会用到 “GITS_TRANSLATER” 寄存器
这两种方法只能支持一种。
3.1 使用 GICR_SETPIR
这个寄存器格式如下:
把LPI的中断号写入这个寄存器即可触发中断。
使用 ITS
ITS 的意思是:Interrupt Translation Service,中断转换服务。
能产生 MSI 中断的设备, 都有一个 DeviceID (设备ID), 它产生的每一个MSI中断都有一个EventID(事件ID)。"DevicelD+EventlD"组合被传入ITS,IDS会把它们转换为INTID。
过程如下:
- 外设发生中断消息(Interrupt Message)到ITS
- 外设只要写
GITS_TRANSLATER
就可以发送消息, 这个寄存器格式如下:
- 消息里包含有: DevicelD(哪一个设备)、EventlD(这个设备的哪一个中断)
- 外设只要写
- ITS 使用 DevicelD 在 Device Table 中找到 一项
- 只有一个Device Table
- 每一个能发生MSI中断的设备在里面都有一项,它指向这个设备的Interrupt Translation Table(中断转换表,简称ITT)
- 每一个能发生MSI中断的设备,都有一个ITT
- ITS使用EventID在ITT中找到一项,从中返回INTID和Collection |D
- ITS使用Collection ID在Collection Table中找到一项,从中返回"Target Redistributor",即:中断发给哪个CPU
- ITS把INTID发给Redistributor
假设有N个设备可以发出 LPI 中断,或者可以发出基于消息的中断,这N个设备都会有ID,Device1, Device2,Device3… 。每个设备都会有一个中断转换表 interrupt Translation Table,这些表都是放在内存里面的,那么怎么找到这个表呢?在 Device Table 中都会有一项,存放的是 interrupt Translation Table 的首地址。设备把消息发给 ITS 之后,消息里面含有设备ID 和 EventID,
设备 ID 表示 这个中断是有这个设备发出的,EventID 表示我这个设备发出的时哪个中断,比如某个设备可以发出多个中断。N个设备里面第一个设备它可以发出M个事件,每个事件都会有个ID, 首先会根据 Interrupt Message 中的 Device ID 在 Device Table 里面找打一项,从这项里面就可以找到这个设备的中断转换表格 interrupt Translation Table 在哪里,这个表格就是用来为这个设备服务的,每个设备都会有个表格,这个表格里面会含有 M 项,每一项里面会含有 INTID 和 Collection ID , 这个 INTID 要发给哪个 Redistributor 是由 Collection ID 决定的, 根据 Collection ID 在 Collection Table 中找到某一项,这一项里面会含有发给哪一个 Redistributor , 也就是发给哪个CPU,