2. ARM GIC中断控制器:GIC v3/v4架构、中断类型(SPI、PPI、SGI)、中断亲和性
2.1 GIC v3/v4 架构概览
ARM通用中断控制器(Generic Interrupt Controller, GIC)是ARM架构中管理中断的核心硬件单元。从GIC v3开始,架构引入了对大型多核系统(如ARMv8服务器和高端移动SoC)的原生支持,解决了v2版本在可扩展性和虚拟化方面的瓶颈。GIC v4则在v3基础上进一步优化了虚拟中断的直接注入能力。
GIC v3/v4的逻辑架构分为两大组件:Distributor(分发器)和Redistributor(重分发器),每个CPU核心(PE)拥有独立的Redistributor实例。
2.2 中断类型:SPI、PPI、SGI
GIC v3/v4定义了三种核心中断类型,它们在触发源、路由方式和配置属性上存在显著差异。理解这些差异是进行中断亲和性配置和延迟优化的基础。
| 中断类型 | 全称 | 中断ID范围 | 目标 | 典型用途 |
|---|---|---|---|---|
| SPI | Shared Peripheral Interrupt | 32 ~ 1019 | 可路由至任意一个或多个PE | 外设中断(UART、I2C、DMA、GPU等) |
| PPI | Private Peripheral Interrupt | 16 ~ 31 | 仅路由至指定的单个PE | 本地定时器、PMU、Watchdog |
| SGI | Software Generated Interrupt | 0 ~ 15 | 由软件写入触发,可路由至自身或其他PE | 核间通信(IPI)、任务调度、TLB刷新 |
2.3 中断亲和性(Interrupt Affinity)
中断亲和性是指将特定中断源绑定到指定CPU核心(或核心组)上处理的能力。在GIC v3/v4中,亲和性通过Interrupt Routing和Affinity Routing机制实现,支持将中断精确路由到单个PE、一组PE或所有PE。
亲和性配置的核心寄存器是GICD_IROUTER(Distributor中的中断路由寄存器),每个SPI都有一个对应的IROUTER寄存器,用于指定该中断的目标PE。对于PPI和SGI,其路由由Redistributor和软件控制。
亲和性配置方式
- 静态亲和性: 在系统启动时通过固件(如ATF)或设备树配置,中断固定路由到指定核心。
- 动态亲和性: 在运行时通过内核接口(如
irq_set_affinity)修改中断路由,实现负载均衡。 - 默认亲和性: 若未显式配置,中断通常路由到所有在线核心,由硬件或内核调度决定处理核心。
2.4 亲和性在Android BSP中的实战应用
在Android设备上,合理配置中断亲和性可以显著降低关键中断的响应延迟,避免中断在多个核心间迁移导致的缓存抖动。以下是常见的优化场景:
| 场景 | 中断类型 | 推荐亲和性策略 | 优化目标 |
|---|---|---|---|
| 触摸屏中断 | SPI | 绑定到小核(LITTLE core) | 降低功耗,避免唤醒大核 |
| 音频DMA中断 | SPI | 绑定到特定大核(big core) | 保证音频无卡顿,低延迟 |
| 核间通信(IPI) | SGI | 默认路由,由内核调度 | 保证核间同步效率 |
| 本地定时器 | PPI | 固定绑定到所属PE | 硬件强制,无需配置 |
irqbalance服务或手动配置亲和性,将中断分散到不同核心。
2.5 GIC v3/v4 关键寄存器与编程接口
驱动开发者需要了解以下关键寄存器,以便在内核代码或设备树中配置中断属性:
- GICD_CTLR:Distributor控制寄存器,启用/禁用中断组。
- GICD_ISENABLERn:中断使能寄存器组,按位使能中断。
- GICD_ICENABLERn:中断禁能寄存器组。
- GICD_ICPENDRn:中断挂起状态清除寄存器。
- GICD_IROUTERn:中断路由寄存器,配置SPI的亲和性目标PE。
- ICC_PMR_EL1:CPU接口优先级掩码寄存器,设置当前PE的中断优先级阈值。
- ICC_IAR0_EL1 / ICC_IAR1_EL1:中断确认寄存器,读取当前中断ID。
- ICC_EOIR0_EL1 / ICC_EOIR1_EL1:中断结束寄存器,通知GIC中断处理完成。
在Linux内核中,GIC v3/v4的驱动代码位于drivers/irqchip/irq-gic-v3.c,提供了标准的中断控制器操作接口。驱动开发者通常通过request_irq()、devm_request_irq()或irq_set_affinity()等内核API与GIC交互,无需直接操作硬件寄存器。
#include <linux/irq.h>
#include <linux/irqdomain.h>
int set_irq_affinity_to_cpu0(unsigned int irq)
{
struct cpumask mask;
cpumask_clear(&mask);
cpumask_set_cpu(0, &mask); // 绑定到CPU0
return irq_set_affinity(irq, &mask);
}
2.6 本章小结
GIC v3/v4是ARMv8-A架构下中断管理的核心,其Distributor + Redistributor的分布式架构为大型多核系统提供了灵活的中断路由和亲和性配置能力。SPI、PPI、SGI三种中断类型分别对应外设、本地和软件触发场景,驱动开发者需要根据中断特性选择合适的亲和性策略。在Android BSP开发中,合理配置中断亲和性是优化驱动响应延迟、降低功耗和提升系统稳定性的关键手段。