1、GIC
GIC(Generic Interrupt Controller,通用中断控制器)是ARM架构中用于管理、优先级排序和分发中断的标准组件。
它作为CPU与外设之间的"交通警察",接收来自各种外设的中断请求,进行优先级判断和路由决策,再将高优先级中断送达合适的处理器核心处理,从而提升系统效率并支持虚拟化。
GIC的核心功能与作用
- 中断管理:集中管理所有外设(如键盘、传感器、网络模块)产生的中断信号。
- 优先级排序:为不同中断分配优先级,确保紧急任务(如系统错误)能被及时响应。
- 中断分发:将中断精准路由到指定的CPU核心,尤其在多核系统中实现负载均衡。
- 支持虚拟化:在虚拟机环境中,GIC可高效分发虚拟中断,提升虚拟化性能。
GIC在系统中的结构组成
- **Distributor(分发器)**:管理共享外设中断(SPI),控制中断使能、优先级和路由。
- **Redistributor(重分发器)**:处理私有外设中断(PPI)、软件生成中断(SGI)和LPI,连接到CPU接口。
- CPU Interface:每个处理器核心都有一个接口,负责接收并响应中断。
- **ITS(中断转换服务)**:用于复杂系统中实现中断的间接映射与虚拟化支持。
2、SPI、PPI 、SGI 和 LPI
在 ARM 架构的通用中断控制器(GIC,Generic Interrupt Controller)中,SPI 、PPI 、SGI 和 LPI 是四种主要的中断类型。它们根据来源、作用范围以及配置方式的不同,服务于不同的系统需求。
以下是这四种中断类型的详细解析:
1. SGI (Software Generated Interrupt) - 软件生成中断
- 定义:由软件通过写入 GIC 寄存器主动触发的中断,不依赖外部硬件信号。
- 中断 ID 范围:0 -- 15(共 16 个)。
- 主要用途 :核间通信(IPI, Inter-Processor Interrupt) 。
- 用于多核系统中 CPU 核心之间的协调与同步。
- 常见场景包括:进程调度迁移、TLB(页表缓冲)刷新、远程函数调用、CPU 停机或唤醒等。
- 特点 :
- 完全由软件控制,无物理连线。
- 可以发送给指定的一个或多个目标 CPU 核心。
- 在 Linux 内核中,SGI 常被映射为 IPI 消息(如
IPI_RESCHEDULE,IPI_CALL_FUNC等)。
2. PPI (Private Peripheral Interrupt) - 私有外设中断
- 定义:连接到特定 CPU 核心的本地外设产生的中断。每个核心拥有自己独立的 PPI 线路,其他核心无法接收该中断。
- 中断 ID 范围 :16 -- 31(共 16 个)。
- 注:GICv3.1 及更高版本支持扩展 PPI,ID 范围可延伸至 1056--1119。
- 主要用途 :处理核心本地的硬件事件。
- 典型来源:通用定时器(Generic Timer)、看门狗定时器(Watchdog)、本地错误中断等。核心本地外设 (Timer, WDT)
- 特点 :
- 非共享:虽然不同核心的 PPI ID 可能相同(例如 ID 30 都是定时器中断),但它们在物理上是隔离的,属于各自核心的"私有财产"。
- 配置简单,通常直接绑定到产生中断的那个核心。
3. SPI (Shared Peripheral Interrupt) - 共享外设中断
- 定义由系统级共享外设产生的中断,可以通过 GIC 的分发器(Distributor)路由到任何一个或多个 CPU 核心。
- 中断 ID 范围 :32 -- 1019(最多约 988 个)。
- 注:GICv3.1 及更高版本支持扩展 SPI,ID 范围可延伸至 4096--5119。
- 主要用途 :处理大多数外部设备的中断请求。
- 典型来源:UART、GPIO、USB、以太网控制器、PCIe 控制器(传统 INTx 模式)、触摸屏、按键等。系统共享外设 (UART, USB, GPIO)
- 特点 :
- 共享性:GIC 可以根据负载均衡策略或固定绑定规则,将中断分发给指定的核心。
- 全局配置 :由 GIC Distributor统一管理使能、优先级、触发方式(电平/边沿)和目标核心列表。
- 是嵌入式系统和服务器中最常见的中断类型。
4. LPI (Locality-specific Peripheral Interrupt) - 局部特定外设中断
- 定义:GICv3 引入的一种新型中断机制,专门针对基于消息的中断(Message Signaled Interrupts, MSI/MSI-X)。
- 中断 ID 范围:8192 及以上(数量巨大,理论上可达数百万,取决于实现)。
- 主要用途 :高性能 PCIe 设备中断。
- 典型来源:NVMe SSD、高速网卡(100G+)、GPU、AI 加速器等支持 MSI/MSI-X 的设备。PCIe MSI/MSI-X 设备
- 特点 :
- 动态分配 :与传统 SPI 不同,LPI 的配置信息(如优先级、目标核心)不存储在 GIC 的寄存器中,而是存储在内存中的配置表里。
- ITS 支持 :需要配合 **ITS (Interrupt Translation Service)** 模块使用。ITS 负责将 PCIe 设备发出的 MSI 事务包转换为 GIC 能够识别的 LPI 事件。
- 高扩展性:解决了 SPI 数量有限(~1000 个)的问题,适合现代数据中心和高性能计算场景中大量外设同时产生中断的需求。
- 低功耗优化:由于配置在内存中,未使用的 LPI 不需要占用 GIC 内部寄存器资源,有助于降低功耗。
3、WFI、WFE
WFI(Wait For Interrupt)和 WFE(Wait For Event)是 ARM 架构中用于实现低功耗管理的两条关键指令。它们允许处理器核心在空闲时进入低功耗待机状态,从而显著降低系统功耗,同时保持对特定事件的快速响应能力。
以下是关于这两条指令的详细解析:
1. 基本定义与共同点
- WFI (Wait For Interrupt) :等待中断。当执行该指令时,处理器暂停执行并进入低功耗模式,直到发生一个中断请求。
- **WFE (Wait For Event)**:等待事件。当执行该指令时,处理器暂停执行并进入低功耗模式,直到发生一个"事件"(Event)。
- 共同机制 :
- 低功耗状态:两者都会让处理器核心进入低功耗待机模式(Low-power standby state)。具体的实现方式由硬件决定,通常表现为关闭核心时钟(Clock Gating),但保持核心供电,仅消耗静态漏电流。
- 流水线清空:在执行 WFI/WFE 之前,处理器会等待所有之前的指令(包括内存访问)完成或提交,以确保系统状态的一致性,避免死锁。
- 唤醒后执行:被唤醒后,处理器会从 WFI/WFE 指令的下一条指令继续执行。
2. 核心区别:唤醒机制与行为逻辑
虽然两者都用于低功耗等待,但在进入条件和唤醒源上有显著不同:
A. 进入低功耗的条件
-
WFI:
- 执行 WFI 指令后,处理器立即进入低功耗模式。
- 它不检查任何内部标志位,无条件挂起。
-
WFE:
- WFE 的行为依赖于一个内部的单比特**事件寄存器(Event Register)**。
- 如果事件寄存器为 1 :WFE 指令会将该位清零,然后立即返回 ,不进入低功耗模式。这被称为"虚假唤醒"保护或快速路径。
- 如果事件寄存器为 0:处理器进入低功耗模式,直到有事件发生。
B. 唤醒源
-
WFI 的唤醒源:
- 主要由**中断(Interrupt)**唤醒。任何使能或未屏蔽的中断请求(IRQ/FIQ)到达时,处理器都会退出 WFI 状态。
- 复位(Reset)也可以唤醒。
-
WFE 的唤醒源:
- 中断:与 WFI 类似,中断也可以唤醒 WFE。
- 事件(Event) :这是 WFE 独有的唤醒方式。事件可以通过以下途径产生:
- SEV 指令 :其他核心执行
SEV(Send Event) 指令,会通过硬件信号线触发当前核心的事件寄存器置位,从而唤醒处于 WFE 状态的核心。 - 外部事件输入 :某些处理器支持专用的
EVENTI引脚信号。 - 特定硬件事件:如独占访问监视器(Exclusive Access Monitor)的状态改变(例如在自旋锁释放时)。
- SEV 指令 :其他核心执行
3. 典型应用场景
WFI:CPU 空闲管理 (Idle Loop)
- 场景:操作系统调度器发现当前 CPU 没有任务可执行时。
- 用法 :调用
WFI让 CPU 进入深度睡眠,直到下一个定时器中断、外设中断或 IPI(核间中断)到来。 - 优势:简单直接,适用于大多数通用的空闲等待场景。
WFE:多核同步与自旋锁优化 (Spinlock)
- 场景:在多核系统中,当一个核心试图获取已被另一个核心占用的锁(Spinlock)时。
- 传统做法:忙等待(Busy Wait),即不断循环检查锁状态。这会浪费大量功耗并占用总线带宽。
- WFE 优化做法 :
- 尝试获取锁:核心尝试原子操作获取锁。
- 失败则等待 :如果获取失败,执行
WFE进入低功耗模式。 - 释放锁并通知 :持有锁的核心在完成临界区操作后,释放锁,并执行
SEV指令(或利用释放锁时的存储操作触发事件)。 - 唤醒 :
SEV或相关硬件事件将唤醒等待中的核心,使其重新尝试获取锁。
- 优势:在等待锁期间大幅降低功耗,减少总线流量,提高多核系统的能效比。
4. 技术细节与注意事项
- 内存一致性:在进入 WFI/WFE 之前,软件通常需要使用数据同步屏障(DSB, Data Synchronization Barrier)来确保所有之前的内存访问已完成。这防止了因内存操作未完成而导致的潜在死锁或数据不一致。
- 中断优先级 :对于 WFE,如果唤醒源是一个被屏蔽或优先级不足的中断,处理器可能会唤醒但不会立即进入中断服务程序(ISR),而是继续执行 WFE 后的代码。具体行为取决于处理器的配置(如
SEVONPEND位)。 - 多核事件广播 :
SEV指令通常会向系统中的所有处理器核心广播事件。如果只需要唤醒特定核心,可能需要结合其他机制或使用SEVL(Send Event Local,仅影响本地核心,具体支持情况视架构版本而定)。 - Cortex-M 系列的特殊性 :在 Cortex-M 微控制器中,WFI/WFE 进入的具体低功耗模式(Sleep 或 Deep Sleep)还受系统控制寄存器(SCR)中的
SLEEPDEEP位控制,并由芯片厂商的电源管理单元(PMU)具体实现
**Gating Clocks(门控时钟)**
- 作用:通过关闭空闲模块的时钟信号,减少不必要的电平翻转,从而降低动态功耗。
- 实现方式 :
- 使用使能信号(Enable)与逻辑门(如AND门)控制时钟通断。
- 推荐采用基于锁存器或触发器的门控结构,避免毛刺影响时序。
- 应用场景:FPGA、ASIC等低功耗集成电路设计中广泛使用。
**Flushing Caches(刷新缓存)**
- 目的 :确保缓存中的"脏数据"写回主存,维持数据一致性,防止DMA、多核访问时读取到过期数据。
- 触发时机 :
- 系统休眠(如进入S3状态)前。
- 上下文切换、中断处理时。
- 设备驱动中DMA传输前后。
- 实现方法 :
- 硬件层面:执行
WBINVD(x86)或dmb sy+ 清缓存指令(ARM)。 - 软件层面:调用
sync()、fsync()或编译器内置函数。
- 硬件层面:执行
**Disabling Coherency(禁用一致性)**
- 含义:关闭缓存一致性协议(如MESI),通常在多核系统中某个核心即将关闭或复位时执行。
- 原因:避免该核心继续参与缓存监听(snooping),防止一致性协议异常。
- 操作流程 :
- 先刷新本地缓存。
- 停止参与总线监听。
- 进入非一致性状态,等待电源控制器统一调度。
这三项操作常在处理器进入低功耗状态(如WFI、power down)前由硬件自动或软件协同完成,确保系统安全过渡。