2. 中断控制器(GIC):GIC v2/v3/v4 架构演进、中断分发机制、中断路由表
通用中断控制器(Generic Interrupt Controller, GIC)是 ARM 架构中管理中断的核心硬件单元,负责中断的检测、优先级排序、分发与路由。随着多核处理器、虚拟化及大规模 SoC 的发展,GIC 从 v2 演进至 v4,每一代都在中断分发机制与路由表结构上做出了关键改进。理解 GIC 的演进是配置中断负载均衡与 CPU 亲和性的硬件基础。
2.1 GIC 架构演进概览
GIC 的每一代都对应着 ARM 处理器架构与系统规模的需求变化。下表总结了三代 GIC 的核心差异:
| 特性 | GIC v2 | GIC v3 | GIC v4 |
|---|---|---|---|
| CPU 接口 | 内存映射寄存器(CPU 接口) | 系统寄存器(ICC_*_ELn) | 系统寄存器 + 虚拟化扩展 |
| 最大 PE 数 | 最多 8 个 PE | 最多 2^16 个 PE | 最多 2^16 个 PE |
| 中断路由 | 固定路由(SPI 路由到指定 PE) | 可编程路由表(支持亲和性路由) | 支持直接注入虚拟中断(vLPI) |
| 虚拟化支持 | 基本虚拟中断(通过 LR) | 支持虚拟 CPU 接口(GICv3) | 原生支持直接虚拟中断(Doorbell) |
| 中断类型 | SGI/PPI/SPI/LPI | SGI/PPI/SPI/LPI | SGI/PPI/SPI/LPI + vLPI |
| 中断标识符范围 | ID0~ID1019 | ID0~ID65535 | ID0~ID65535 |
2.2 GIC v2 架构与中断分发
GIC v2 是经典的分布式中断控制器架构,由 Distributor 和 CPU Interface 两部分组成。Distributor 负责全局中断管理,CPU Interface 负责将中断信号传递给具体的处理器核心。
GIC v2 中断分发机制
- SGI (Software Generated Interrupt):通过写入 Distributor 的 SGIR 寄存器触发,目标由寄存器中的 CPU Target List 字段指定,用于核间通信(IPI)。
- PPI (Private Peripheral Interrupt):每个 CPU 核私有,直接路由到对应的 CPU Interface,无需 Distributor 路由。
- SPI (Shared Peripheral Interrupt):由 Distributor 根据
ITARGETSR寄存器(每 SPI 占用 8 位,每位对应一个 CPU)路由到指定的一个或多个 CPU Interface。 - LPI (Locality-specific Peripheral Interrupt):GIC v2 中 LPI 支持有限,通常通过外部 ITS(Interrupt Translation Service)实现。
2.3 GIC v3 架构与中断路由表
GIC v3 引入了革命性的变化:CPU 接口从内存映射寄存器迁移到系统寄存器(ICC_*_ELn),并增加了 Redistributor 组件。每个 CPU 核关联一个 Redistributor,负责管理该核的 PPI、SGI 和 LPI 中断。Distributor 不再直接与 CPU Interface 通信,而是通过 Redistributor 进行。
GIC v3 中断路由表(GICD_IROUTER)
GIC v3 为每个 SPI 中断提供了一个独立的 64 位路由寄存器 GICD_IROUTER<n>,取代了 GIC v2 的位掩码方式。该寄存器支持两种路由模式:
- 亲和性路由(Affinity Routing):通过
Aff3.Aff2.Aff1.Aff0字段指定目标 PE(Processing Element),支持层次化的路由拓扑。 - 1-of-N 路由:将中断路由到当前处于最低优先级或最空闲的 PE,实现硬件级的负载均衡。
irq_set_affinity 接口设置 GICD_IROUTER 寄存器,将中断绑定到指定 CPU。
/* 伪代码:设置 SPI 中断 42 路由到 CPU1 (Aff0=1) */
gicd_irouter[42] = 0x00000001; /* 仅设置 Aff0 字段 */
/* 设置 SPI 中断 43 使用 1-of-N 路由 */
gicd_irouter[43] = 0x00000000 | (1ULL << 31); /* Interrupt_Routing_Mode 位 */
2.4 GIC v4 架构与虚拟中断直接注入
GIC v4 在 v3 的基础上,主要增强了虚拟化支持。它引入了 vLPI (Virtual LPI) 和 Doorbell 机制,允许虚拟机直接接收物理中断,而无需 VMM(虚拟机监视器)的介入。
GIC v4 关键特性
- vLPI (Virtual LPI):每个虚拟 CPU (vCPU) 拥有独立的虚拟 LPI 配置表,由 ITS(Interrupt Translation Service)管理。
- Doorbell:当物理中断到达时,ITS 通过 Doorbell 机制直接通知对应的 vCPU,无需 VMM 模拟。
- 中断路由表扩展:GIC v4 的路由表支持将中断直接路由到虚拟 PE(vPE),通过
GICR_VPENDBASER寄存器维护物理 PE 与虚拟 PE 的映射。
CONFIG_ARM_GIC_V4 配置选项,并且 QEMU/KVM 需要提供相应的 GIC v4 设备模型。
2.5 中断分发机制对比总结
| 中断类型 | GIC v2 分发方式 | GIC v3/v4 分发方式 | 路由粒度 |
|---|---|---|---|
| SGI | Distributor 根据 SGIR 的 Target List 广播 | Redistributor 直接处理,通过系统寄存器触发 | 按 PE 位掩码 (v2) / 亲和性 (v3) |
| PPI | 直接路由到私有 CPU Interface | 由关联的 Redistributor 管理 | 固定到单个 PE |
| SPI | Distributor 根据 ITARGETSR 位掩码路由 | Distributor 根据 GICD_IROUTER 亲和性路由 | 按 PE 位掩码 (v2) / 亲和性或 1-of-N (v3) |
| LPI | 通过外部 ITS(可选) | ITS 翻译后路由到 Redistributor | 按设备 ID 和事件 ID 翻译 |
| vLPI (v4) | 不支持 | ITS 直接注入到 vPE 的虚拟 LPI 表 | 按 vPE 亲和性 |
2.6 中断路由表在 Linux 内核中的体现
Linux 内核通过 struct irq_chip 和 struct irq_domain 抽象 GIC 的路由能力。对于 GIC v3/v4,关键的数据结构包括:
- GIC 芯片(gic_chip):提供
.irq_set_affinity回调,用于设置GICD_IROUTER寄存器。 - 中断域(irq_domain):管理硬件中断号到 Linux IRQ 号的映射,以及路由表的初始化。
- ITS 设备(its_device):管理 LPI 中断的翻译表,包括设备 ID 与事件 ID 的映射。
/proc/irq/<IRQ>/smp_affinity 文件动态调整中断的 CPU 亲和性。内核会调用 gic_set_affinity 更新 GICD_IROUTER 寄存器,实现中断的负载均衡。