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实例。

关键架构变化: GIC v3/v4废弃了v2中基于单一Distributor的全局中断路由,采用Distributor + 每个PE独立的Redistributor架构,实现了中断亲和性的灵活配置和中断负载的分布式处理。
GIC v3/v4 架构框图 GIC v3/v4 架构框图 Distributor 中断配置、优先级、路由 Redistributor 0 CPU Interface 0 Redistributor 1 CPU Interface 1 PE 0 (CPU Core 0) 中断处理 PE 1 (CPU Core 1) 中断处理 外设中断 (SPI) 软件中断 (SGI) 说明: 每个PE拥有独立的Redistributor,负责管理该PE的PPI、SGI以及从Distributor路由来的SPI。Distributor负责全局中断配置和路由决策。

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刷新
实战提示: 在Android BSP开发中,SPI是驱动开发者最常打交道的类型。例如,触摸屏、传感器、音频编解码器等外设的中断通常配置为SPI,并可通过设备树(Device Tree)中的interrupts属性指定中断号和触发类型。

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)修改中断路由,实现负载均衡。
  • 默认亲和性: 若未显式配置,中断通常路由到所有在线核心,由硬件或内核调度决定处理核心。
中断亲和性路由示意图 中断亲和性路由示意图 外设中断 (SPI) Distributor GICD_IROUTER 亲和性路由决策 PE 0 (CPU0) 亲和性: 目标 PE 1 (CPU1) 亲和性: 目标 PE 2 (CPU2) 亲和性: 非目标 通过配置GICD_IROUTER寄存器,可以将SPI中断精确路由到指定的PE(如CPU0或CPU1),实现中断负载的定向分配。

2.4 亲和性在Android BSP中的实战应用

在Android设备上,合理配置中断亲和性可以显著降低关键中断的响应延迟,避免中断在多个核心间迁移导致的缓存抖动。以下是常见的优化场景:

场景 中断类型 推荐亲和性策略 优化目标
触摸屏中断 SPI 绑定到小核(LITTLE core) 降低功耗,避免唤醒大核
音频DMA中断 SPI 绑定到特定大核(big core) 保证音频无卡顿,低延迟
核间通信(IPI) SGI 默认路由,由内核调度 保证核间同步效率
本地定时器 PPI 固定绑定到所属PE 硬件强制,无需配置
避坑指南: 在Android系统中,不要将高频率的中断(如GPU渲染完成中断)绑定到所有核心,这会导致中断风暴和严重的性能下降。建议使用内核的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交互,无需直接操作硬件寄存器。

内核API示例: 设置中断亲和性到CPU0
#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开发中,合理配置中断亲和性是优化驱动响应延迟、降低功耗和提升系统稳定性的关键手段。