3. 中断控制器基础:GIC v2/v3/v4 架构与中断路由
在 ARM 多核系统中,通用中断控制器(GIC)是连接外设中断源与 CPU 核心的硬件中枢。GIC 负责中断的优先级仲裁、分发、亲和性路由以及虚拟化支持。理解 GIC 架构是适配 PREEMPT_RT 中断线程化与 CPU 亲和性绑定的前提。
3.1 GIC 架构演进与核心组件
GIC 从 v2 发展到 v4,主要变化在于对多核、虚拟化以及大规模中断的支持。其核心组件始终包含两个逻辑单元:Distributor(分发器)和CPU Interface(CPU 接口)。
| 特性 | GIC v2 | GIC v3 | GIC v4 |
|---|---|---|---|
| 中断线数量 | 最多 1020 个 SPI | 几乎无限(通过 ITS) | 同 v3,增强虚拟中断 |
| CPU 接口访问 | 内存映射(MMIO) | 系统寄存器(ICC_*) | 同 v3 |
| 虚拟化支持 | 基础(虚拟 CPU 接口) | 增强(vLPI) | 直接注入虚拟中断(doorbell) |
| 亲和性路由 | 8 位 CPU ID | 16 位亲和性(Aff3/Aff2/Aff1/Aff0) | 同 v3 |
| 典型应用 | Cortex-A7/A9/A15 | Cortex-A53/A72/A76 | 虚拟化场景(KVM) |
3.2 中断类型:SPI / PPI / SGI / LPI
GIC 将中断源划分为四种类型,每种类型在路由、亲和性和使用场景上存在显著差异。
- SPI(Shared Peripheral Interrupt,共享外设中断):中断号范围 32~1019(v2)或 32~4095(v3)。可路由到任意一个或一组 CPU 核心,常用于外设(如网卡、USB 控制器)。
- PPI(Private Peripheral Interrupt,私有外设中断):中断号范围 16~31。每个 CPU 核心独享,用于本地定时器、性能监视单元等。
- SGI(Software Generated Interrupt,软件生成中断):中断号范围 0~15。通过写 GICD_SGIR 或 ICC_SGI1R 寄存器触发,用于核间通信(IPI)。
- LPI(Locality-specific Peripheral Interrupt,局部外设中断):GIC v3/v4 引入,中断号从 8192 开始。基于消息的中断,通过 ITS(中断翻译服务)路由,支持大量中断源。
| 类型 | 中断号范围 | 路由目标 | 触发方式 | 典型用途 |
|---|---|---|---|---|
| SPI | 32 ~ 1019 (v2) / 32 ~ 4095 (v3) | 任意 CPU 或 CPU 组 | 电平/边沿 | 外设中断 |
| PPI | 16 ~ 31 | 固定的私有 CPU | 电平/边沿 | 本地定时器、PMU |
| SGI | 0 ~ 15 | 指定 CPU 或所有 CPU | 边沿(软件触发) | 核间通信(IPI) |
| LPI | ≥ 8192 | 通过 ITS 路由 | 消息(电平) | PCIe MSI/MSI-X |
3.3 中断亲和性与路由机制
中断亲和性(Affinity)决定了中断由哪个 CPU 核心处理。合理的亲和性配置可以避免缓存抖动、提高实时任务的确定性。
3.3.1 GIC v2 亲和性路由
GIC v2 通过 GICD_ITARGETSRn 寄存器设置 SPI 的目标 CPU。每个寄存器对应 4 个中断,每个中断使用 8 位位图表示目标 CPU(bit0~bit7 对应 CPU0~CPU7)。
/* GIC v2 SPI 亲和性设置示例 */
#define GICD_ITARGETSR(n) (0x1800 + (n) * 4)
/* 将中断 42 路由到 CPU0 和 CPU2 */
uint32_t target = 0x05; /* bit0=CPU0, bit2=CPU2 */
writel(target, GICD_ITARGETSR(42 / 4));
3.3.2 GIC v3/v4 亲和性路由
GIC v3 使用 GICD_IROUTERn 寄存器,支持 16 位亲和性值(Aff3:Aff2:Aff1:Aff0),可以精确路由到特定物理 CPU 或 CPU 组。路由模式包括:
- 指定 CPU:写入目标 CPU 的 MPIDR 值。
- 任意 CPU:写入
0xFFFFFFFF,由 GIC 自动选择。 - 中断组:通过
GICD_ICFGRn配置组 0(安全)或组 1(非安全)。
/* GIC v3 SPI 亲和性设置示例 */
#define GICD_IROUTER(n) (0x6000 + (n) * 8)
/* 将中断 100 路由到 CPU1 (Aff0=1) */
uint64_t aff = 0x00000001; /* MPIDR: Aff0=1 */
writeq(aff, GICD_IROUTER(100));
3.4 中断优先级与抢占
GIC 支持 16~256 级中断优先级(v2 为 16 级,v3/v4 为 256 级)。优先级数值越小,优先级越高。PREEMPT_RT 内核依赖优先级机制实现中断线程化后的实时调度。
/* 设置 CPU 接口优先级掩码(GIC v3 系统寄存器) */
asm volatile("msr ICC_PMR_EL1, %0" : : "r" (0xF0));
/* 读取当前优先级掩码 */
uint32_t pmr;
asm volatile("mrs %0, ICC_PMR_EL1" : "=r" (pmr));
3.5 中断虚拟化:GIC v4 的 Direct Virtual Interrupt
GIC v4 引入了 直接虚拟中断注入 机制,允许物理外设直接向虚拟机注入中断,无需 VMM 介入。其核心是 Doorbell 机制:
- 物理中断到达时,ITS 将中断转换为虚拟中断(vLPI)。
- 通过 Doorbell 机制通知虚拟机 CPU 接口。
- 虚拟机直接读取中断信息,减少 VM-Exit 次数。
| 特性 | GIC v3 虚拟化 | GIC v4 虚拟化 |
|---|---|---|
| 中断注入方式 | VMM 写 List 寄存器 | 硬件直接注入(Doorbell) |
| VM-Exit 次数 | 每次中断至少 1 次 | 0 次(理想情况) |
| 中断延迟 | 较高(VMM 调度影响) | 接近物理中断 |
| 适用场景 | 通用虚拟化 | 实时虚拟化、NFV |
3.6 本章小结
GIC v2/v3/v4 架构为 ARM 多核系统提供了灵活的中断管理能力。理解 SPI/PPI/SGI/LPI 四种中断类型的路由特性,掌握亲和性寄存器的配置方法,是后续实现 PREEMPT_RT 中断线程化与 CPU 隔离的基础。在下一阶段,我们将深入分析中断控制器与 PREEMPT_RT 线程化模型的适配细节。