2. GIC(Generic Interrupt Controller)简介
通用中断控制器(GIC)是 ARM 架构中用于管理中断的核心硬件单元。它负责接收来自外设、软件和处理器内部的中断请求,进行优先级仲裁、分发和路由,最终将中断信号传递给对应的 CPU 核心。在 Linux 内核启动流程中,GIC 的初始化是中断子系统建立的基础,直接影响系统的实时性和响应能力。
2.1 GIC 的版本演进(GICv1/v2/v3/v4)
ARM GIC 经历了多个版本的迭代,每个版本在中断数量、分发机制、虚拟化支持和安全扩展方面都有显著提升。下表总结了各版本的核心差异:
| 特性 | GICv1 | GICv2 | GICv3 | GICv4 |
|---|---|---|---|---|
| 中断线数量 | 最多 1020 个 SPI | 最多 1020 个 SPI | 最多 1020 个 SPI + 扩展 SPI | 同 GICv3 |
| CPU 接口 | 内存映射寄存器 | 内存映射寄存器 | 系统寄存器(ICC_*) | 同 GICv3 |
| 亲和性路由 | 不支持 | 不支持 | 支持(Affinity Routing) | 同 GICv3 |
| 虚拟化支持 | 无 | 基本虚拟化(vGIC) | 增强虚拟化(LPI 支持) | 直接注入虚拟中断(Direct Injection) |
| LPI(Locality-specific Peripheral Interrupt) | 不支持 | 不支持 | 支持 | 支持 |
| 典型应用 | Cortex-A9 等早期多核 | Cortex-A15/A7 大小核 | Cortex-A53/A72 及服务器 | 虚拟化场景(如 KVM) |
版本选择提示: 在嵌入式 Linux 开发中,GICv2 和 GICv3 最为常见。GICv2 适用于传统多核 SoC,而 GICv3 在 64 位 ARMv8 平台上已成为标准配置,其系统寄存器接口减少了内存映射访问的开销。
下图展示了 GIC 版本演进的关键里程碑和主要新增特性:
2.2 GIC 在 ARM 架构中的地位
GIC 是 ARM 架构中中断子系统的核心组件,位于外设和 CPU 核心之间。它承担着中断信号的汇聚、优先级排序和分发任务。在 ARM 多核系统中,GIC 的地位可以概括为以下几点:
- 中断汇聚中心: 所有外设中断(SPI、PPI、SGI)和软件触发中断都通过 GIC 进行统一管理。
- 优先级仲裁器: GIC 根据配置的优先级字段,决定哪个中断优先被处理,支持抢占和嵌套。
- 分发与路由: 在 GICv3 及以上版本中,支持将中断路由到指定的 CPU 核心或核心组(Cluster)。
- 虚拟化桥接: 在虚拟化环境中,GIC 负责将物理中断转换为虚拟中断,并注入到 Guest OS。
下图展示了 GIC 在 ARM 系统架构中的位置和连接关系:
2.3 GIC 与 CPU 接口的关系
GIC 与 CPU 之间的接口是中断传递的关键通道。不同版本的 GIC 采用了不同的接口方式,直接影响中断延迟和软件访问方式。
2.3.1 接口类型对比
| 接口类型 | GIC 版本 | 访问方式 | 典型寄存器 | 延迟特点 |
|---|---|---|---|---|
| 内存映射接口 | GICv1 / GICv2 | 通过 CPU 内存总线访问 | GICC_*(CPU Interface) | 较高,依赖总线仲裁 |
| 系统寄存器接口 | GICv3 / GICv4 | 通过 MSR/MRS 指令访问 | ICC_*(系统寄存器) | 较低,直接访问 |
2.3.2 中断信号传递流程
当外设产生中断时,信号经过以下路径到达 CPU:
- 外设触发: 外设将中断信号发送到 GIC 的 Distributor 单元。
- 优先级仲裁: Distributor 根据中断优先级和当前运行状态,选择最高优先级的中断。
- 路由决策: 根据亲和性配置(GICv3+),将中断路由到目标 Redistributor。
- CPU 接口通知: Redistributor 通过 CPU 接口(内存映射或系统寄存器)向目标 CPU 发送 IRQ 或 FIQ 信号。
- CPU 响应: CPU 在异常向量表中跳转到中断处理程序,读取 GICC_IAR(GICv2)或 ICC_IAR0_EL1(GICv3)获取中断 ID。
关键区别: 在 GICv2 中,CPU 通过读取内存映射寄存器
GICC_IAR 获取中断 ID;而在 GICv3 中,CPU 通过系统寄存器 ICC_IAR0_EL1 或 ICC_IAR1_EL1 读取,无需经过内存总线,延迟更低。
下图展示了 GICv2 和 GICv3 在 CPU 接口访问路径上的差异:
2.3.3 中断类型与 CPU 接口的对应关系
GIC 支持多种中断类型,每种类型与 CPU 接口的交互方式略有不同:
- SGI(Software Generated Interrupt): 由软件通过写入 GICD_SGIR(GICv2)或 ICC_SGI0R_EL1(GICv3)触发,用于核间通信(IPI)。
- PPI(Private Peripheral Interrupt): 每个 CPU 核心私有的外设中断,如本地定时器,通过 Redistributor 直接路由到对应核心。
- SPI(Shared Peripheral Interrupt): 共享外设中断,由 Distributor 根据配置路由到指定核心或核心组。
- LPI(Locality-specific Peripheral Interrupt): GICv3 引入,基于消息的中断,通过 ITS(Interrupt Translation Service)进行路由,适合大量外设场景。
注意事项: 在 GICv3 中,LPI 中断不支持通过内存映射寄存器直接访问,必须通过 ITS 和系统寄存器配合使用。Linux 内核中,LPI 的配置涉及
its_alloc_tables() 和 its_alloc_collections() 等复杂流程。