前两篇文章我们介绍了GIC的基础知识,涵盖了功能组件、中断类型及其他相关特性。本篇作为系列第三部分,将深入探讨GIC在实际使用中所需的软件配置细节。
1. GIC Distributor (GICD) 配置
GICD的配置可分为全局配置和针对单个PE(Processor Element)的私有配置。
a. 全局配置
此部分主要涉及对GICD_CTLR寄存器中特定功能域的设置,以决定是否启用相应特性:
- 使能 Affinity Routing。
- 使能中断分组功能。
b. 私有PE配置
这部分配置作用于每个独立的处理核心。
1. 唤醒 GIC (GICR)
- 设置
gicr_waker.ProccessorSleep = 0。
- 轮询
gicr_waker.childrenAsleep,直到其值变为 0。
2. 配置 CPU Interface
配置 ICC_* 系列寄存器与配置其对应的 GICC_* 寄存器效果一致。
- 使能 CPU Interface: 设置
ICC_SRE_ELN.SRE=0。
- 设置优先级与分组:
- 设置 Priority Mask 寄存器 (
ICC_PME_EL1),用于判断哪些优先级的中断可以发送给CPU。
- 设置 Binary Point 寄存器 (
ICC_BPRn_EL1),用于优先级分组和判断抢占。
- 设置 EOI 模式: 通过配置
ICC_CTLR_EL1/3.EOImode 来控制中断结束(EOI)是单步还是分步操作。
- 使能分组中断: 分别设置
ICC_IGRPEN1_EL1 和 ICC_IGRPEN0_EL1 来使能 Group1 和 Group0 中断。对于EL3,则需设置 ICC_IGRPEN1_EL3。
3. PE (Processing Element) 核心配置
此为处理器核心内部的配置,以下仅列出基本项,实际配置可能更为复杂。
- 路由控制 (Routing Control): 配置
CR_EL3/HCR_EL2 寄存器,以设定中断可在哪个异常等级 (EL) 被响应。
- 中断掩码 (Interrupt Mask): 清除PE内部的中断掩码位。
- 向量表 (Vector Table): 设置指向对应中断服务程序 (ISR) 的向量表基地址。
2. 中断源的软件配置
中断源的配置主要分为两类:SPI/SGI/PPI 的配置和 LPI 的配置。
a. SPI/SGI/PPI 配置
- 使能 (Enable): 通过写
GICD/R_ISENABLER<n> 寄存器来使能特定中断。只有被使能的中断才会被分发给CPU核心;未使能的中断若产生,则会保持为 pending 状态。
- 优先级 (Priority): 每个中断在
GICD/R_IPRIORITY<n> 寄存器中有一个8位的优先级字段。数值 0x0 代表最高优先级。
- 配置 (CFG): 通过
GICD/R_ICFG<n> 寄存器配置每个中断的触发模式(边沿触发或电平触发)。注意,SGI(软件生成中断)只能配置为边沿触发。
- 路由 (Routing): 仅 SPI 中断支持特殊的 1/N 路由模式(即一个中断可以路由到一组CPU中的某一个),该功能由
GICD_IROUTER<n> 寄存器控制。
- 安全域与分组 (Security/Group):
gicd_ctlr.ds 位可以全局关闭安全模式。当安全模式开启时,每个中断可以通过 GICD/R_IGROUPR<n> 和 GICD/R_IGRPMODER<n> 寄存器进行分组配置。
b. LPI (Locality-specific Peripheral Interrupt) 配置
- 使能 (Enable):
- 使能 LPI 功能: 设置
GICR_CTLR.EnableLPIs = 1。
- 当
GICD_CTLR.DS=0 (安全模式开启) 时:LPI 仅在 Non-secure affinity routing 使能后才被支持。
- 当
GICD_CTLR.DS=1 (安全模式关闭) 时:LPI 总是属于 Group1 中断。
- 配置 (CFG):
- ITS 配置: 需要初始化 Interrupt Translation Service (ITS) 相关的表项。一旦使能,对应的基地址寄存器将变为可读。
- GICR 配置:
- 初始化 LPI 配置表 (Configuration Table) 和 Pending 表。
- 重新配置 LPI 的基表项,以刷新相关缓存中的信息。
3. 中断响应 (Acknowledge Interrupt)
当中断被 CPU 响应后,软件需要在中断服务程序 (ISR) 中读取中断应答寄存器 (Interrupt Acknowledge Register)。硬件会返回该中断的 INTID,并更新其内部状态。
- 中断应答寄存器:不同中断组使用不同的寄存器。
- Group0 中断: 读取
ICC_IAR0_EL1。
- Group1 中断: 读取
ICC_IAR1_EL1。
- 被响应中断的优先级会成为 CPU 当前的 运行优先级 (Running Priority)。
- 运行优先级机制为中断抢占提供了条件:当有新中断的优先级高于当前运行优先级时,就会发生抢占。
4. 中断结束 (End of Interrupt, EOI)
中断处理完成后,软件需要完成两件事:
- 优先级下降 (Priority Drop): 将 CPU 的运行优先级恢复为触发此中断之前的值。
- 失效化 (Deactivation): 将对应 INTID 的中断状态机置为 Inactive。
这两步操作是分开执行还是合并为一步,取决于 EOI 模式是否开启:
- EOI 模式开启 (分步执行):
- 写
ICC_EOIRn_EL1 寄存器触发 Priority Drop。
- 写
ICC_DIR_EL1 寄存器触发 Deactivation。
- EOI 模式关闭 (单步执行):
- 写
ICC_EOIRn_EL1 寄存器会同时完成上述两步操作。
5. 虚拟化支持
为了支持 ARMv8 架构的虚拟化特性,GICv3 引入了相应的虚拟化功能。
- 虚拟 CPU Interface:
- 新增了
ICV_* 系列私有寄存器来控制虚拟中断,其位域定义与物理的 ICC_* 寄存器保持一致。
- 在 Non-secure EL1 下,对这些寄存器的访问权限由
HCR_EL2 控制;在安全态下访问则不受限制。
- 虚拟中断:
- 运行在 EL2 的 Hypervisor 使用
ICH_LRn_EL2 寄存器列表来管理虚拟中断,包括其分组、优先级以及与物理中断的映射关系。
- 维护中断 (Maintenance Interrupt):
- 这是一种新增的中断类型,用于 vPE (Virtual PE) 与物理 PE 之间的交互。
- 使能: 由
ICH_HCR_EL2 寄存器控制。
- 触发机制: 当
ICH_HCR_EL2.LRENPIE == 1 且 ICH_HCR_EL2.EOIcount != 0 时产生。
- 监控: 可通过
ICH_MISR_EL2 寄存器检测是否有维护中断产生。
- 上下文切换:
- 当 vPE 之间发生上下文切换时,需要保存和恢复 vPE 的状态信息,其中就包括虚拟 CPU Interface 的寄存器内容。
在 GICv4 中,进一步增加了对虚拟 LPI (Virtual LPI) 的支持:
- 触发方式: 仍然采用 ITS 翻译表机制,但将 Collection Table 替换为 vPE Table 来实现虚拟中断到物理 vPE 的映射。
理解这些配置原理是进行底层计算机基础开发,尤其是操作系统与驱动开发的关键。希望这篇关于 ARM GIC 软件配置的解析能对你的学习或工作有所帮助。如果你想查看更多技术讨论或分享,欢迎访问我们的云栈社区。
|