3、GICv2架构详解:GICv2的组成模块、中断类型、中断优先级与亲和性

GICv2(Generic Interrupt Controller version 2)是ARM Cortex-A系列处理器在ARMv7-A及部分早期ARMv8-A平台上广泛使用的中断控制器标准。理解GICv2的组成模块、中断类型、优先级与亲和性机制,是掌握Linux内核中断子系统初始化的基础。本节将从硬件架构层面深入剖析GICv2的核心设计。

3.1 GICv2的组成模块

GICv2由两大逻辑模块构成:Distributor(分发器)和CPU Interface(CPU接口)。这两个模块通过专用总线连接,共同完成中断的收集、优先级仲裁、分发和CPU核交付。

架构要点: Distributor负责全局中断管理和优先级决策,CPU Interface负责将中断信号实际传递到指定的CPU核。两者缺一不可。

3.1.1 Distributor(分发器)

Distributor是GICv2的控制中心,主要职责包括:

  • 中断使能与屏蔽: 控制每个中断源的使能/禁止状态。
  • 优先级管理: 为每个中断分配优先级值,并基于优先级进行仲裁。
  • 中断目标选择: 决定每个中断可以发送到哪个或哪些CPU核(亲和性)。
  • 中断触发方式配置: 设置中断为电平触发或边沿触发。
  • 中断分组: 将中断分为Group 0(安全中断)和Group 1(非安全中断),支持TrustZone。
  • 软件触发中断(SGI): 提供寄存器用于软件生成SGI。

3.1.2 CPU Interface(CPU接口)

每个CPU核拥有一个独立的CPU Interface模块,负责:

  • 中断优先级掩码: 设置当前CPU核能响应的最低优先级阈值。
  • 中断抢占逻辑: 管理高优先级中断对低优先级中断的抢占。
  • 中断应答(ACK): CPU读取GICC_IAR寄存器获取中断ID。
  • 中断结束(EOI): CPU写入GICC_EOIR寄存器通知中断处理完成。
  • 运行优先级跟踪: 维护当前CPU核的运行优先级状态。
编程提示: 在Linux内核中,Distributor对应的内存映射基地址通常为 0x2C001000(以某平台为例),CPU Interface基地址为 0x2C002000。驱动通过访问这些寄存器完成初始化配置。
GICv2 架构组成模块 Distributor(分发器) 中断使能/屏蔽控制 优先级仲裁与分组 中断目标(亲和性)选择 触发方式配置(电平/边沿) SGI软件触发寄存器 CPU Interface(CPU接口) 优先级掩码阈值设置 中断抢占逻辑 中断应答(ACK) 中断结束(EOI) 运行优先级跟踪 中断仲裁结果 每个CPU核拥有独立的CPU Interface,Distributor为全局共享模块

3.2 中断类型

GICv2定义了四种中断类型,每种类型在中断ID范围、触发方式、目标CPU等方面有明确区分。

中断类型 中断ID范围 触发方式 目标CPU 典型用途
SGI(Software Generated Interrupt) ID 0 ~ 15 边沿触发(软件写入) 可指定一个或多个CPU 核间通信(IPI)、CPU唤醒
PPI(Private Peripheral Interrupt) ID 16 ~ 31 电平或边沿触发 仅绑定到特定CPU核 本地定时器、性能监视单元(PMU)
SPI(Shared Peripheral Interrupt) ID 32 ~ 1019 电平或边沿触发 可路由到任意CPU核 外设中断(UART、I2C、DMA等)
LPI(Locality-specific Peripheral Interrupt) ID 8192 ~ 65535 消息中断(基于写操作) 可路由到任意CPU核 GICv3/v4引入,GICv2不支持
注意: LPI是GICv3/v4引入的新中断类型,GICv2原生不支持LPI。在GICv2系统中,SPI是主要的外设中断来源,SGI用于核间通信,PPI用于CPU私有外设。

3.2.1 SGI(软件生成中断)

SGI通过Distributor的GICD_SGIR寄存器触发。Linux内核使用SGI实现IPI(Inter-Processor Interrupt),例如:

  • IPI_RESCHEDULE: 触发CPU重新调度(SGI ID 0)。
  • IPI_CALL_FUNC: 让目标CPU执行指定函数(SGI ID 1)。
  • IPI_CPU_STOP: 停止目标CPU(SGI ID 2)。

3.2.2 PPI(私有外设中断)

PPI是每个CPU核私有的中断,不同CPU核的同ID PPI互不干扰。典型PPI包括:

  • ARM Generic Timer: 物理定时器(PPI ID 29)、虚拟定时器(PPI ID 27)。
  • Performance Monitors: PMU溢出中断(PPI ID 23)。

3.2.3 SPI(共享外设中断)

SPI是系统中所有外设共享的中断类型,通过Distributor路由到指定CPU核。SPI ID从32开始,每个外设占用一个唯一ID。例如:

  • UART0中断通常映射为SPI ID 32 ~ 39(具体取决于SoC设计)。
  • I2C控制器中断映射为SPI ID 40 ~ 47。
GICv2 中断类型与ID映射 SGI ID 0 ~ 15 软件触发 核间通信 边沿触发 PPI ID 16 ~ 31 私有外设 CPU本地 电平/边沿 SPI ID 32 ~ 1019 共享外设 可路由 电平/边沿 LPI ID 8192+ 消息中断 GICv3/v4 GICv2不支持 GICv2支持SGI、PPI、SPI三种中断类型,LPI为GICv3/v4新增特性

3.3 中断优先级

GICv2使用8位优先级值(实际实现可能只使用高4位或高5位),数值越小优先级越高。优先级管理涉及两个关键寄存器:

  • GICD_IPRIORITYR(Distributor优先级寄存器): 每个中断源占用一个字节,设置该中断的优先级。
  • GICC_PMR(CPU Interface优先级掩码寄存器): 设置当前CPU核能响应的最低优先级阈值。只有优先级高于PMR值的中断才能被CPU处理。
优先级仲裁流程:
  1. Distributor收集所有挂起的中断,比较它们的优先级。
  2. 选择优先级最高的中断,将其发送到目标CPU Interface。
  3. CPU Interface检查该中断优先级是否高于当前运行优先级(由GICC_RPR寄存器维护)。
  4. 如果高于运行优先级,则触发CPU中断异常;否则等待。

3.3.1 优先级配置示例

Linux内核通常将优先级分为几个等级,例如:

优先级值(高4位) 优先级等级 典型用途
0x00 最高 紧急错误中断(如硬件故障)
0x10 ~ 0x20 高 定时器、DMA传输完成
0x40 ~ 0x60 中 网络、存储控制器
0x80 ~ 0xA0 低 UART、I2C等慢速外设
0xFF 最低 空闲中断或屏蔽

3.4 中断亲和性(Affinity)

中断亲和性是指将中断路由到特定CPU核的能力。GICv2通过Distributor中的GICD_ITARGETSR寄存器实现亲和性配置。每个中断源占用一个字节,每个bit对应一个CPU核(bit0对应CPU0,bit1对应CPU1,以此类推)。

亲和性配置示例:
  • 将SPI中断路由到CPU0:写入 0x01 到对应的GICD_ITARGETSR字节。
  • 将SPI中断路由到CPU0和CPU1:写入 0x03。
  • 将SPI中断路由到所有CPU:写入 0xFF(最多8个CPU)。

3.4.1 亲和性在Linux内核中的应用

Linux内核通过irq_set_affinity接口动态调整中断亲和性,实现负载均衡:

/* 将IRQ 42(假设为网卡中断)绑定到CPU2 */
struct cpumask mask;
cpumask_clear(&mask);
cpumask_set_cpu(2, &mask);
irq_set_affinity(42, &mask);

内核的irqbalance守护进程会周期性地重新分配中断亲和性,以均衡各CPU核的中断处理负载。

GICv2 中断亲和性路由示意图 Distributor GICD_ITARGETSR UART0 (SPI 32) I2C0 (SPI 40) CPU0 CPU1 CPU2 CPU3 UART0 → CPU0 I2C0 → CPU1 通过GICD_ITARGETSR寄存器,Distributor将不同SPI路由到指定CPU核

3.5 中断生命周期与状态机

GICv2中的每个中断源在硬件层面维护一个状态机,包含以下状态:

状态 描述 触发条件
Inactive 中断未触发 初始状态或EOI后
Pending 中断已触发,等待CPU响应 外设触发中断信号
Active CPU已应答中断,正在处理 CPU读取GICC_IAR
Active and Pending 中断处理中,又有新触发 处理期间中断再次到达
中断处理流程(硬件视角):
  1. 外设触发中断信号,Distributor将对应中断状态置为Pending。
  2. Distributor进行优先级仲裁,选择最高优先级中断。
  3. Distributor将中断发送到目标CPU的CPU Interface。
  4. CPU Interface检查优先级掩码,若允许则向CPU核发送IRQ/FIQ信号。
  5. CPU核响应异常,读取GICC_IAR寄存器获取中断ID,状态变为Active。
  6. CPU执行中断服务程序(ISR)。
  7. ISR完成后,CPU写入GICC_EOIR寄存器,状态回到Inactive。

3.6 本章小结

GICv2架构通过Distributor和CPU Interface的分工协作,实现了灵活的中断管理。Distributor负责全局中断收集、优先级仲裁和亲和性路由,CPU Interface负责与CPU核的直接交互和优先级掩码控制。四种中断类型(SGI、PPI、SPI、LPI)覆盖了核间通信、私有外设和共享外设的不同需求。优先级和亲和性机制为Linux内核实现中断负载均衡和实时性保障提供了硬件基础。理解这些概念,是后续分析GIC初始化代码和中断处理流程的关键前提。