ARM 电源管理

从汇编指令 WFI/WFE 出发,沿着 Standby → Retention → Power Down 的空闲状态谱系,经 DVFS 动态调节与 Hotplug 核心下线,最终收敛到 PSCI 接口在多特权级系统中的协调机制——本文覆盖 ARMv7-A 电源管理的完整技术栈。

1. 动态功耗与静态功耗

对于 ARM Cortex-A 处理器而言,提升性能并不是唯一目标,如何降低功耗同样重要。无论是智能手机、平板电脑还是可穿戴设备,都受到电池容量和散热能力的限制,因此处理器需要在保证性能的同时尽可能减少能耗。

处理器功耗主要由两部分组成:

  • 动态功耗(Dynamic Power):晶体管开关翻转产生的功耗,与工作电压、时钟频率以及电路活动程度有关。CPU 工作越繁忙、频率越高,动态功耗越大。
  • 静态功耗(Static Power):即使处理器没有执行任何指令,只要保持上电状态,晶体管仍会产生漏电流,从而持续消耗能量。随着制造工艺不断演进,静态功耗在总功耗中的占比越来越高。

因此,现代处理器不仅需要在工作时提高性能,还需要在空闲时尽快进入低功耗状态,并根据系统负载动态调整运行性能。为此,ARMv7-A 提供了一系列电源管理机制,操作系统需要回答以下几个问题:

  1. CPU 空闲时如何降低功耗? —— Idle Management(空闲管理)
  2. 系统负载变化时如何平衡性能与功耗? —— DVFS(动态电压频率调节)
  3. 多个软件实体如何协调 CPU 的电源状态? —— PSCI(Power State Coordination Interface,电源状态协调接口)

本文将围绕这三个问题,介绍 ARMv7-A 平台上的电源管理机制及其软件实现。


2. 三大机制:Idle、Hotplug 与 DVFS

ARMv7-A 的电源管理主要围绕三个方面展开,它们分别对应不同的使用场景:

  • Idle Management:CPU 没有工作时,如何进入低功耗状态。
  • Hotplug:系统负载长期较低时,如何将整个 CPU 核心下线。
  • DVFS:CPU 仍在工作时,如何在性能和功耗之间取得平衡。

三者并不是互相替代,而是针对不同场景协同工作。

2.1 Idle Management(空闲管理)

当某个核心暂时没有线程可调度时,OSPM 会将其置于低功耗状态。根据预计空闲时间的长短,可以进入不同深度的 Idle State:状态越深,功耗越低,但唤醒延迟也越高。

空闲管理不仅作用于 CPU 核心,还可能影响更大的硬件范围。例如:

  • 一个 CPU 空闲,可以关闭该 CPU。
  • 一个 Cluster 中所有 CPU 都空闲,可以关闭整个 Cluster。
  • 整个 SoC 都空闲,可以让 DRAM 进入 Self-refresh 等更深层的低功耗状态。

因此,Idle Management 关注的是**”暂时没有工作”时如何尽可能降低功耗,并在需要时快速恢复运行。**

2.2 Hotplug(热插拔)

Hotplug 用于长期不需要某个 CPU 核心的场景。

与 Idle 不同,Hotplug 会将 CPU 从操作系统的调度域中移除,不再参与线程调度,也不会响应普通调度请求。只有当系统再次需要更多计算能力时,操作系统才会重新将该 CPU 上线。

除了电源管理外,Hotplug 也常用于多核启动过程:主核完成系统初始化后,再依次启动其余 CPU。

2.3 DVFS(动态电压频率调节)

DVFS 用于 CPU 仍在运行,但不需要最高性能的场景。

处理器的动态功耗近似满足:

P = C × V² × f

其中:

  • P:动态功耗
  • C:等效开关电容
  • V:工作电压
  • f:工作频率

DVFS 根据系统负载动态调整 CPU 的工作频率和电压:负载较低时降低频率,同时降低供电电压,从而显著减少动态功耗;负载升高时再恢复到较高性能状态。


3. 空闲管理的层次体系:四种核心电源状态

ARM 核心支持的电源状态构成了一个由浅入深的层次体系。理解它们的区别,是理解整个空闲管理子系统的基础。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
Standby

├─ Clock Gating
├─ CPU 完全上电
├─ 数个 CPU 周期恢复
└─ WFI/WFE



Retention

├─ CPU 状态保持供电
├─ 自动恢复
├─ μs 级恢复
└─ 调试状态不可保持



Dormant

├─ CPU Logic 断电
├─ Cache RAM 保持供电
├─ Cache 退出一致性域
├─ 恢复需重新建立一致性
└─ 通常用于 Cluster 级低功耗



Power Down

├─ CPU 完全断电
├─ Cache/寄存器全部丢失
├─ 从 Reset Vector 启动
├─ OSPM 恢复上下文
└─ 唤醒时间最长

3.1 Standby(待机模式)

Standby 是最浅的低功耗状态。核心保持上电,但大部分逻辑的时钟被门控(Clock Gating),停止执行指令;只有负责检测唤醒事件的少量逻辑继续接收时钟,因此能够快速响应唤醒请求。

进入方式:执行 WFI(Wait For Interrupt)或 WFE(Wait For Event)指令。需要注意的是,WFI/WFE 只是向硬件发出”可以进入低功耗状态”的提示,最终进入哪种低功耗状态由平台电源管理逻辑决定。

ARM 建议在执行 WFI/WFE 前插入 DSB(Data Synchronization Barrier)指令,确保此前发起的内存访问已经完成,再进入低功耗状态。

唤醒条件:

  • WFI:IRQ/FIQ、中断、异步 Abort、调试请求等。
  • WFE:除上述事件外,还可由其他核心执行 SEV(Send Event)指令唤醒。

关键特性: 无需保存或恢复处理器上下文,因此进入和退出通常只需几个 CPU 时钟周期,是响应延迟最低的低功耗状态。

3.2 Retention(保持模式)

Retention 比 Standby 更深一级。进入该状态后,CPU 的执行状态(如寄存器等)保存在保持供电(Retention)的存储结构中,而大部分逻辑可以停止工作,从而进一步降低功耗。

与 Standby 不同,Retention 的恢复时间更长(通常为微秒级),但仍无需重新复位处理器。唤醒后,硬件会自动恢复此前保存的处理器状态,并从休眠前的位置继续执行程序。

由于 CPU 的调试逻辑所在电源域可能已关闭,Retention 期间外部调试请求通常会被挂起,待处理器恢复后再继续处理。

与stand by的区别:stand by的时候,cpu还上电,只是clock gating;retention的时候,cpu的部分逻辑关闭。

3.3 Power Down(断电模式)

这是最深的空闲状态。核心被完全断电,所有上下文丢失。进入此状态前,软件必须保存全部核心状态;退出时必须经历完整的复位→恢复流程。

上下文破坏的范围取决于具体状态中哪些组件被断电——可能包括核心本身、GIC(通用中断控制器),甚至平台特定 IP。调试和跟踪上下文是否丢失,也取决于它们的电源域组织方式。

Power Down 的唤醒路径非常特殊。由于核心被完全断电,唤醒后从复位向量开始执行,通常在 Secure 模式下。Secure Firmware 首先恢复自身的上下文(寄存器、页表等),然后执行必要的硬件初始化,最后将执行权交还给发起 Power Down 请求的 OS,跳转到指定的返回地址继续执行。

1

Power Down 前需要保存 CPU 上下文、系统控制寄存器、设备状态以及必要的内存状态;唤醒后由 Firmware/OSPM 重新初始化硬件环境并恢复执行现场。相比 Retention,Power Down 的恢复成本更高,但可以获得最低功耗。

这一流程在多特权级系统(如同时运行 Rich OS + Hypervisor + Secure Firmware 的设备)中引入了一个关键问题:谁来负责保存和恢复哪个层次的上下文?这正是 PSCI 接口要解决的核心问题——我们将在第7节详细展开。

3.4 Dormant Mode(休眠模式)

Dormant Mode 是一种特殊的折中方案:核心逻辑被断电,但 Cache RAM 保持供电——通常 RAM 处于低功耗保持状态,内容保留但不可被功能访问。

理论上,这提供了比完整关机快得多的重启速度——因为热数据和代码仍在缓存中。但在多核系统中,Dormant Mode 面临一个根本性限制:

一个核心进入 Dormant Mode 前必须:

  1. 清理所有脏数据(clean dirty data)
  2. 退出一致性域(coherence domain)
  3. 被唤醒后重新加入一致性域

由于内存状态可能在休眠期间已被其他核心改变,唤醒后可能仍需失效(invalidate)缓存。因此,在 Cluster 中,Dormant Mode 通常只在最后一个核心(其他核心已关机)的场景下有意义。

Dormant Power Down
CPU Logic 断电 断电
Cache RAM 保持供电 通常断电
寄存器状态 丢失,需要恢复 丢失,需要恢复
Cache 内容 保留 丢失
唤醒方式 Resume Reset/Boot Resume
软件参与 需要 需要更多
恢复速度 较快 最慢
功耗 较低 最低

4. WFI/WFE 与 SEV:汇编指令级别的功耗控制

ARM 架构在汇编语言层面直接暴露了功耗控制接口。WFIWFESEV 这三个指令构成了 Standby 模式的硬件入口。

4.1 WFI:等待中断

WFI 指令使核心暂停执行,直到被以下任何一个条件唤醒:

  • IRQ 中断(即使 CPSR 的 I 位被设置——即中断被屏蔽时仍会唤醒)
  • FIQ 中断(同理,即使 F 位被设置)
  • 异步中止(Asynchronous Abort)
  • 调试入口请求(即使 JTAG Debug 被禁用)

一个值得注意的细节:当核心被中断唤醒,而 CPSR 中对应的中断屏蔽位被设置时,核心会执行 WFI 之后的下一条指令,而不是跳转到中断处理程序。这是因为中断在 CPSR 层面被屏蔽了——它只充当了唤醒信号的角色,而不会触发异常处理流程。

架构演进:在旧版 ARM 架构中,进入待机模式需要通过 CP15 协处理器操作实现;ARMv7-A 将其提升为专用指令,体现了电源管理在架构层面的重要性提升。

4.2 WFE 与 SEV:核间事件同步

WFE(Wait For Event)的唤醒条件比 WFI 更丰富。除了中断、中止和调试请求之外,它还可以被其他核心通过 SEV 指令唤醒。

WFE/SEV 的同步机制依赖于每个核心内部的 Event Register(1-bit 锁存器):

  • SEV:将一致性域内所有核心的 Event Register 置位。

  • WFE :检查本核心的 Event Register:

  • 如果已经置位,则将其清零并立即返回;

    • 如果未置位,则进入待机状态。

因此,WFESEV 构成了一个轻量级的核间同步原语——无需中断控制器参与即可完成线程间通知。

典型使用场景:核心 A 在等待核心 B 完成某项工作,核心 A 执行 WFE 进入待机;核心 B 完成后执行 SEV 唤醒核心 A。

SCU 唤醒:在多核系统中,Snoop Control Unit 也可以通过唤醒时钟来请求一个处于 Standby 状态的核心执行缓存一致性操作。这意味着处于 Standby 的核心,其缓存仍然与其他核心保持一致。

4.3 DSB 屏障:WFI 前置同步的必要性

ARM 明确建议在 WFIWFE 之前执行 DSB 指令:

1
2
DSB    @ 确保所有待处理的内存访问完成
WFI @ 进入待机模式

DSB 保证在核心停止执行之前,所有之前发起的内存事务(包括缓存操作、外部内存写入)都已经完成。如果缺少这个屏障,可能发生以下问题:

  • 某个 Store 操作尚未到达最终目的地,核心就进入了待机状态
  • 其他核心或 DMA 设备看到的数据与预期不一致
  • 恢复执行后,内存访问顺序可能出现意料之外的结果

5. Power Down 与 Hotplug:深度状态下的上下文管理

Power Down 和 Hotplug 虽然在功耗目标上不同,但在技术实现上共享同一个核心挑战:上下文的保存与恢复

5.1 Power Down 的上下文生命周期

进入 Power Down 状态的典型流程如下:

1
2
3
4
5
1. OSPM 保存恢复运行所需的状态(CPU 上下文、系统寄存器等)
2. 根据平台要求完成 Cache 维护(通常包括 clean,并在需要时 invalidate)
3. 调用 PSCI CPU_SUSPEND 接口
4. Secure Firmware 执行平台特定的断电操作
5. 核心断电 → CPU 硬件状态丢失

唤醒流程:

1
2
3
4
5
6
1. 唤醒事件触发 → 硬件恢复供电
2. 核心从复位入口开始执行平台固件
3. Secure Firmware 初始化必要的硬件环境
4. 跳转到 OSPM 指定的恢复入口
5. OSPM 恢复此前保存的状态
6. 继续执行原来的程序

5.2 Hotplug 与 Idle 的语义差异

虽然 Hotplug 的下线操作(CPU_OFF)在底层可能使用与 Power Down 相同的硬件机制,但在操作系统语义层面有根本差异:

  • Power Down(Idle):核心仍属于操作系统的调度域,OS 认为它仍是可用 CPU。当中断等唤醒事件到来后,核心恢复运行并继续参与任务调度。
  • Hotplug(CPU_OFF):核心被彻底移出操作系统的可用资源池。调度器不会向它分派任何线程,中断也不会被路由给它。要将核心重新投入使用,必须显式调用 CPU_ON 接口。

5.3 辅助核启动与 Hotplug 的关联

操作系统通常在主核心上完成大部分内核启动流程,辅助核心稍后上线。辅助核启动的行为与 Hotplug 十分相似——两者在技术流程上几乎一致。

也就是说,在多核 ARM 系统中,辅助核的首次上线在实现上与”热插入一个核心”非常接近。区别在于:辅助核是首次启动,而 Hotplug 是已经运行过的核心重新加入系统,因此需要完成离线与重新上线相关的管理流程。

至此,我们讨论了核心在”不运行时”的功耗管理——从浅层时钟门控到完全断电。但 ARM 核心在”运行时”还有另一条优化路径:如果不需要全速运行,能否动态降低频率和电压来节省功耗?这正是 DVFS 的切入点。


6. DVFS:P = C × V² × f 的工程实现

DVFS 的理论基础——P = C × V² × f——已在第2章介绍,但其工程实现涉及硬件和软件两方面的复杂挑战。

6.1 Operating Performance Point (OPP)

对于给定的电路,工作电压和可安全运行的频率范围之间存在实现特定的对应关系。一个经过芯片厂商验证、能够稳定工作的(频率,电压)组合被称为一个 **Operating Performance Point (OPP)**。系统中所有可用的 OPP 集合构成了 DVFS Curve

例如,一个典型的 DVFS Curve 可能包含:

OPP 频率 电压 相对功耗 (P ∝ V² × f) 适用场景
OPP0 200 MHz 0.85V 基准 (1.0×) 待机/后台任务
OPP1 500 MHz 0.95V 3.2× 轻度交互
OPP2 800 MHz 1.05V 6.3× 网页浏览
OPP3 1.2 GHz 1.15V 11.3× 游戏/视频

(以上为基于 DVFS 公式的典型推算值,实际值取决于具体芯片设计)

6.2 硬件层面的挑战

实现 DVFS 不仅需要软件支持,还依赖 SoC 在硬件上的配合,例如独立供电域、电压调节电路以及跨电压域通信等。

这些硬件设计增加了芯片面积和设计复杂度,但为动态调节电压和频率提供了基础。

6.3 软件层面的挑战:负载预测

硬件提供了调节能力,但决定何时调节、调节到什么程度是软件的责任。

OS 的 DVFS Governor(如 Linux 中的 ondemandconservativeschedutil 等)需要根据系统负载历史做出决策。同样重要的是软件对未来工作负载的准确预测能力——根据预测结果调整电压和时钟频率。

这本质上是一个预测问题,而且需要在两个矛盾的目标之间取得平衡:

  • **高性能策略 (Performance Policy)**:选择更高的频率/电压,确保应用不卡顿,但功耗更高。
  • **节能策略 (Power-Saving Policy)**:选择更低的频率/电压,牺牲部分性能以换取更长的电池续航。

调频过慢 → 应用感知到延迟;调频过快 → 无法有效节能。这是每一代 DVFS Governor 持续优化的方向。

DVFS 和 Hotplug 解决了单个 OS 实例内部的功耗管理问题。但在 ARMv7-A 的多特权级架构中,一个设备上可能同时运行着来自不同供应商的多层软件。当 Rich OS 希望核心进入低功耗状态时,Hypervisor 和 Secure Firmware 如何知晓并协同?这引出了 ARM 电源管理的最后一块拼图——跨特权级协调。


7. PSCI:跨越特权级的电源管理协调接口

ARMv7-A 架构通过特权级(PL0/PL1/PL2)以及 Security Extensions 和 Virtualization Extensions 将软件栈分为多个层次。这种分层带来了一个在单层 OS 中不存在的问题:如何协调不同特权级 OS 的电源决策?

7.1 问题场景

在一个典型的 ARM 移动设备上,可能同时运行着来自不同供应商的软件:

特权级 运行软件 供应商
PL0 用户应用(App) 应用开发者
PL1 Rich OS(Linux Kernel / Android) OS 供应商
PL2 Hypervisor 虚拟化方案供应商
Secure PL0 Trusted OS 应用 Trusted OS 供应商
Secure PL1 Trusted OS + Secure Firmware OEM / 芯片厂商

当 Rich OS 需要将一个核心置于低功耗状态时,Hypervisor 需要知道这件事(以便管理自己的虚拟化状态),Secure Firmware 也需要知道(以便执行实际的硬件操作)。如果各层之间没有统一的接口,就会出现消息传递断裂——每层都可能在错误的时机做出错误的假设。

7.2 PSCI 的消息传递链

ARM 提供的答案就是 **Power State Coordination Interface (PSCI)**。它不是一个硬件接口,而是一套软件约定,定义了电源管理请求如何跨特权级传递。

消息传递链:

2

7.3 PSCI 四大核心调用

PSCI 定义了四个核心函数,覆盖了从 Idle 到 Hotplug 到 big.LITTLE 迁移的全部场景:

CPU_SUSPEND
挂起核心执行,用于空闲子系统——核心预期通过唤醒事件恢复执行。

用于空闲管理场景。核心被挂起后,会通过硬件唤醒事件恢复执行。这是 Idle 子系统的主要接口。

CPU_OFF
关闭核心电源,用于 Hotplug 场景。CPU_OFF 后的核心只能通过 CPU_ON 重新上线。

用于 Hotplug 场景。CPU_OFF 后的核心只能通过 CPU_ON 重新上线——唤醒事件不会自动恢复它。这是与 CPU_SUSPEND 的语义边界:Suspend 是”暂时睡一会”,OFF 是”正式下线”。

CPU_ON
激活一个核心,用于辅助核首次启动或此前 CPU_OFF 下线核心的重新上线。

覆盖两个场景:辅助核的首次启动,以及此前 CPU_OFF 下线核心的重新上线。

MIGRATE
请求将某个核心上 Trusted OS 的上下文迁移到指定的目标核心,用于 big.LITTLE 系统中的上下文迁移。

用于 big.LITTLE 系统中的上下文迁移。当 OSPM 决定将任务从 big 核心迁移到 LITTLE 核心(或反向)时,Trusted OS 的上下文也需要随之移动。

7.4 PSCI 的设计哲学

PSCI 的设计体现了 ARM 对多供应商软件生态的深刻理解。它不规定每层具体做什么(那是各供应商的实现细节),只规定了:

  1. 统一的请求格式:所有 OS 层使用相同的调用规范
  2. 逐层传递义务:每层收到消息后必须决定自己需要做什么,然后将消息传递给下一层(或直接处理)
  3. 最终执行权在 Secure Firmware:因为只有 Secure Firmware 有权操作硬件电源控制器

这种设计使得来自不同供应商的 OS 组件可以在不相互了解内部实现的情况下,协同完成电源管理任务。


8. 总结与关键要点

ARMv7-A 的电源管理是一个从硬件指令到软件接口的完整分层体系。以下是在系统设计和调试中值得牢记的要点:

  1. 功耗来源决定优化方向:动态功耗通过降频降压控制,静态功耗通过断电(power gating)控制。130nm 以下工艺中,漏电流占比不可忽视。
  2. 空闲状态的层次是深度-延迟的权衡谱系:Standby(两周期延迟,功耗降低有限)→ Retention → Power Down(需复位恢复,功耗接近零)→ Dormant(Cache 保留的折中)。
  3. WFI/WFE 是 Standby 的唯一入口:WFI 前必须执行 DSB 屏障;WFE 配合 SEV 实现轻量级核间同步。
  4. Power Down 与 Hotplug 共享底层机制但语义不同:前者核心仍被视为在线(中断可自动唤醒),后者核心被移出调度域(需显式 CPU_ON)。
  5. DVFS 的物理红利来自 V² 项:降频仅带来线性收益,降频同时降压才能获得叠加红利。硬件需要电平转换器和跨域同步器支持。
  6. **PSCI 是多特权级系统的”翻译层”**:它不定义策略,只定义消息格式和传递路径,让 Rich OS / Hypervisor / Secure Firmware 各司其职。
  7. 调试电源管理代码时需注意:在 Retention 和 Power Down 状态下,调试寄存器可能不可访问,调试请求可能挂起——这不是 bug,是设计行为