kernel/power 内核电源管理与休眠机制与原理详解

kernel/power 内核电源管理与休眠机制与原理详解

源码路径rk3588/kernel-6.1/kernel/power/
内核版本:Linux 6.1(RK3588 平台)
平台:RK3588(4×Cortex-A76 + 4×Cortex-A55 big.LITTLE,ARM64)

该目录实现 Linux 系统级睡眠(System Sleep)电源管理基础设施:Suspend-to-RAM(STR)、Suspend-to-Idle(S2Idle)、Hibernation(STD/swsusp)、进程冻结、PM QoS、Energy Model,以及 /sys/power 用户接口。设备运行时 PM(runtime suspend)的核心逻辑在 drivers/base/power/,但系统休眠路径通过 DPM(Device Power Management) 与本目录紧密协作。

定位:协调「整机睡眠/唤醒」的框架层;平台相关休眠入口由 arch/arm64/drivers/soc/rockchip/ 通过 suspend_set_ops() 注册。


目录


一、源码目录结构

1.1 编译依赖(Makefile)

1
2
3
4
5
6
7
8
9
10
11
12
13
obj-y += qos.o

obj-$(CONFIG_PM) += main.o
obj-$(CONFIG_FREEZER) += process.o
obj-$(CONFIG_SUSPEND) += suspend.o
obj-$(CONFIG_PM_TEST_SUSPEND) += suspend_test.o
obj-$(CONFIG_HIBERNATION) += hibernate.o snapshot.o swap.o
obj-$(CONFIG_HIBERNATION_SNAPSHOT_DEV) += user.o
obj-$(CONFIG_PM_AUTOSLEEP) += autosleep.o
obj-$(CONFIG_PM_WAKELOCKS) += wakelock.o
obj-$(CONFIG_ENERGY_MODEL) += energy_model.o
obj-$(CONFIG_VT_CONSOLE_SLEEP) += console.o
obj-$(CONFIG_MAGIC_SYSRQ) += poweroff.o
配置项 说明
CONFIG_PM 设备 PM 核心(本目录 main.c 部分功能)
CONFIG_PM_SLEEP 系统睡眠(依赖 SUSPEND 或 HIBERNATE_CALLBACKS)
CONFIG_SUSPEND Suspend-to-RAM / Standby / S2Idle
CONFIG_HIBERNATION 休眠到磁盘(swsusp)
CONFIG_FREEZER 睡眠前冻结用户态/内核线程
CONFIG_PM_AUTOSLEEP 无 wakeup source 时自动睡眠
CONFIG_PM_WAKELOCKS 用户态 wakelock 接口
CONFIG_ENERGY_MODEL DVFS 设备能耗模型(调度/thermal 用)
CONFIG_SUSPEND_FREEZER STR 前冻结进程(默认 y)

Kconfig 位于 kernel/power/Kconfig(由 arch/arm64/Kconfig source)。

1.2 源文件

文件 行数 功能
snapshot.c 2756 内存快照:PBE、页面备份/恢复、镜像读写
hibernate.c 1367 休眠流程编排、平台回调、resume 参数
swap.c 1619 快照镜像读写 swap 分区
main.c 940 PM 核心:sysfs、notifier、state 入口、统计
qos.c 678 PM QoS 约束聚合(latency、flags)
suspend.c 648 STR/S2Idle 状态机、platform ops
energy_model.c 438 CPU/GPU 等平台能耗表注册
user.c 466 uswsusp 用户态快照设备
wakelock.c 285 用户态 wakelock(Android 兼容)
process.c 235 睡眠前 freeze/thaw 进程
suspend_test.c 219 启动时 test_suspend 自检
console.c 152 VT 控制台 suspend/resume
autosleep.c 129 opportunistic sleep
poweroff.c 45 SysRq 关机辅助
power.h 328 内部 API、swsusp 结构

相关目录(目录外)

路径 功能
drivers/base/power/ 设备 runtime PM、wakeup source、DPM
kernel/freezer.c 任务 refrigerator 机制
arch/arm64/kernel/suspend.c CPU 级 suspend/resume(cpu_suspend
drivers/soc/rockchip/ RK 平台 suspend 模式、lite/ultra

二、整体架构

2.1 子系统分层

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
用户空间
echo mem > /sys/power/state
/sys/power/autosleep, wakeup_count, mem_sleep


kernel/power/ ← 本目录(系统睡眠框架)
main.c — sysfs、pm_notifier、pm_suspend 入口
suspend.c — STR/S2Idle 流程
hibernate.c + snapshot.c + swap.c — STD
process.c — freezer
qos.c / energy_model.c — 约束与能耗

├── dpm_suspend_* / dpm_resume_* → drivers/base/power/
├── syscore_suspend / syscore_resume
└── suspend_ops->enter() → 平台(Rockchip ATF/PSCI)


arch/arm64/kernel/suspend.c — cpu_suspend / __cpu_suspend_enter
drivers/soc/rockchip/ — ROCKCHIP_SUSPEND_MODE 等

2.2 与 Runtime PM 的区别

维度 System Sleep(本目录) Runtime PM(drivers/base/power)
粒度 整机 单个 device
触发 /sys/power/state、autosleep pm_runtime_suspend()
进程 通常 freeze 全部用户进程 不 freeze
状态 PM_SUSPEND_MEM runtime_status

两者通过 DPM 在系统休眠时统一 suspend 所有设备。


三、睡眠状态与术语

3.1 suspend_state_t

枚举 pm_labels(state) mem_sleep_labels 含义
PM_SUSPEND_TO_IDLE freeze s2idle 冻结进程+设备,CPU 进 idle
PM_SUSPEND_STANDBY standby shallow 浅睡(平台相关)
PM_SUSPEND_MEM mem deep 深睡 STR(内存保持)
PM_SUSPEND_MAX 写入 “disk” 触发 hibernate

RK 平台扩展(CONFIG_ROCKCHIP_LITE_ULTRA_SUSPEND):

状态 mem_sleep 说明
PM_SUSPEND_MEM_LITE lite 电子书等场景的轻量 mem 睡眠
PM_SUSPEND_MEM_ULTRA ultra 更深度的 ultra 睡眠

写入 mem_sleep 时选择实际 mem_sleep_currentpm_suspend() 会将 lite/ultra 映射为 PM_SUSPEND_MEM 再进入平台代码。

3.2 全局变量

1
2
3
suspend_state_t mem_sleep_current;      /* 当前 mem 睡眠深度 */
suspend_state_t pm_suspend_target_state;
struct mutex system_transition_mutex; /* 睡眠转换互斥 */

四、核心入口与 Sysfs(main.c)

4.1 /sys/power/ 主要属性

属性 读写 功能
state RW 写入 mem/freeze/disk 触发睡眠
mem_sleep RW 选择 s2idle/shallow/deep(及 lite/ultra)
sync_on_suspend RW 睡眠前是否 sync() 文件系统
wakeup_count RW 与 wakeup event 配合避免竞态
pm_async RW 设备异步 suspend/resume
pm_test RW 调试:在指定阶段停止(freezer/devices/platform…)
pm_print_times RW 打印各设备 suspend/resume 耗时
autosleep RW opportunistic sleep 目标状态
wake_lock / wake_unlock WO 用户态 wakelock(CONFIG_PM_WAKELOCKS)

4.2 state_store 流程

1
2
3
4
state = decode_state(buf, n);   /* "mem" → PM_SUSPEND_MEM, "disk" → hibernate */
if (state == PM_SUSPEND_MEM)
state = mem_sleep_current;
error = pm_suspend(state); /* 或 hibernate() */

4.3 PM Notifier

1
2
static BLOCKING_NOTIFIER_HEAD(pm_chain_head);
register_pm_notifier() / pm_notifier_call_chain()

通知阶段包括 PM_SUSPEND_PREPAREPM_POST_SUSPENDPM_HIBERNATION_PREPARE 等,供子系统(如 CPUFreq)在睡眠前后调整状态。

4.4 lock_system_sleep()

1
2
current->flags |= PF_NOFREEZE;
mutex_lock(&system_transition_mutex);

防止睡眠线程自身被 freezer 冻结;与 hibernation 的 snapshot 读写路径配合。


五、Suspend-to-RAM(suspend.c)

5.1 平台操作表

1
2
3
static const struct platform_suspend_ops *suspend_ops;

void suspend_set_ops(const struct platform_suspend_ops *ops);

典型回调:

回调 时机
valid(state) 检查平台是否支持该睡眠状态
prepare() 设备 suspend 之前
prepare_late() dpm_suspend_late 前后
enter(state) 关中断、停从核、进硬件睡眠
wake() 唤醒后早期处理

S2Idle 另有 platform_s2idle_opsprepare/check/wake)。

5.2 enter_state() — 顶层流程

1
2
3
4
5
6
7
8
9
10
11
12
mutex_trylock(system_transition_mutex)
sync_on_suspend → ksys_sync_helper()(可选)
suspend_prepare(state)
├── pm_notifier PM_SUSPEND_PREPARE
├── suspend_freeze_processes() ← process.c
├── dpm_suspend_start(PMSG_SUSPEND)
└── platform prepare
suspend_devices_and_enter(state)
suspend_finish()
├── thaw_processes()
└── pm_notifier PM_POST_SUSPEND
mutex_unlock(system_transition_mutex)

5.3 suspend_devices_and_enter()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
suspend_console()
dpm_suspend_start(PMSG_SUSPEND) /* 设备 early suspend */
suspend_enter(state)
├── dpm_suspend_late()
├── dpm_suspend_noirq()
├── [S2Idle] s2idle_loop()
├── [STR] pm_sleep_disable_secondary_cpus()
│ syscore_suspend()
│ suspend_ops->enter(state) ← 平台进睡眠
│ syscore_resume()
│ pm_sleep_enable_secondary_cpus()
└── dpm_resume_noirq / early / finish
dpm_resume_end(PMSG_RESUME)
resume_console()

5.4 Suspend-to-Idle(S2Idle)

不调用 suspend_ops->enter(),而是:

1
2
3
s2idle_loop():
wake_up_all_idle_cpus() /* 所有 CPU 进 idle */
swait_event(s2idle_wait_head) /* 等待 wakeup */

等价于:冻结进程 + 设备 suspend + CPU idle,功耗低于运行态但通常高于 STR。

5.5 suspend 统计

1
struct suspend_stats suspend_stats;  /* success/fail、failed_dev、errno、step */

可通过 debugfs suspend_stats 或 sysfs suspend_stats/ 查看。


六、进程冻结(process.c)

睡眠前须冻结用户态与可冻结内核线程,防止持有锁或 DMA 的进程在设备已 suspend 后继续运行。

6.1 freeze_processes()

1
2
3
4
5
__usermodehelper_disable(UMH_FREEZING)
current->flags |= PF_SUSPEND_TASK
pm_freezing = true
try_to_freeze_tasks(user_only=true) /* 对每个 task freeze_task() */
oom_killer_disable()

6.2 freeze_kernel_threads()

1
2
pm_nosig_freezing = true
try_to_freeze_tasks(user_only=false) /* 含 workqueue */

6.3 thaw_processes()

1
2
3
4
oom_killer_enable()
thaw_workqueues()
__thaw_task() 对所有进程
usermodehelper_enable()

超时默认 freeze_timeout_msecs = 20s;失败时打印 refusing-to-freeze 任务栈。


七、Hibernation 休眠到磁盘(hibernate.c / snapshot.c / swap.c)

7.1 原理(swsusp)

  1. 冻结进程、quiesce 设备
  2. snapshot.c:将内存页写入 PBE(Page Backup Entry) 链表,生成连续镜像
  3. swap.c:镜像压缩(LZO 等)写入 swap 分区
  4. 关机或重启
  5. 下次启动带 resume=/dev/swap:从 swap 读镜像、snapshot 恢复内存、跳回原内核上下文

7.2 关键结构(power.h)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
struct swsusp_info {
struct new_utsname uts;
u32 version_code;
unsigned long num_physpages;
int cpus;
unsigned long image_pages;
...
};

struct snapshot_handle {
unsigned int cur;
void *buffer;
int sync_read;
};

镜像通过 snapshot_read_next() / snapshot_write_next() 以 PAGE_SIZE 块流式读写。

7.3 hibernation_snapshot() 概要

1
2
3
4
5
6
platform_begin()
dpm_suspend_start(PMSG_FREEZE)
create_basic_memory_bitmaps()
swsusp_alloc() / swsusp_save() ← snapshot.c,保存 CPU/内存状态
swsusp_write(flags) ← swap.c,写 swap
platform_finish()

7.4 恢复路径

1
2
3
4
swsusp_check() — 检测 swap 上有效镜像
swsusp_read() — 读入镜像
restore_highmem() / resume_target_kernel()
arch 相关:swsusp_arch_resume、enable_restore_image_protection

7.5 平台模式

1
2
enum { HIBERNATION_PLATFORM, HIBERNATION_SHUTDOWN, HIBERNATION_REBOOT, ... };
hibernation_set_ops(platform_hibernation_ops);

ARM64 支持 ARCH_HIBERNATION_POSSIBLE + ARCH_HIBERNATION_HEADER


八、PM QoS(qos.c)

Quality of Service 约束框架:多个请求者注册 latency/flags 需求,内核聚合为 target_value

1
2
3
int pm_qos_update_target(struct pm_qos_constraints *c,
struct plist_node *node,
enum pm_qos_req_action action, int value);
聚合类型 规则
PM_QOS_MIN 取 plist 最小值(最严格 latency 要求)
PM_QOS_MAX 取最大值

变更时通过 blocking_notifier_call_chain(c->notifiers) 通知 CPUIdle/CPUFreq 等子系统。

常见约束:CPU latency QoS、freq QoS、device PM QoS flags(dev_pm_qos_* 在 drivers/base/power)。


九、Energy Model(energy_model.c)

DVFS 设备(主要是 CPU)注册 性能状态 → 功耗/成本 表,供调度器(EAS)、thermal 使用。

1
2
3
4
5
struct em_perf_domain {
struct em_perf_state *table; /* frequency, power, cost */
unsigned int nr_perf_states;
struct cpumask *cpus;
};

驱动通过 em_dev_register_perf_domain() 注册;debugfs 位于 /sys/kernel/debug/energy_model/

RK3588 big.LITTLE 场景下,A76/A55 各 cluster 可注册独立 perf domain,调度器据此做能效感知选核。


十、Autosleep 与 Wakelock

10.1 autosleep.c

1
2
3
4
5
/* /sys/power/autosleep 写入 "mem" 后 */
try_to_suspend(work):
pm_save_wakeup_count()
pm_suspend(autosleep_state) 或 hibernate()
queue_up_suspend_work() /* 循环尝试 */

仅当 无 active wakeup source 时进入睡眠;与 Android 式 power manager 类似。

10.2 wakelock.c

用户态通过 /sys/power/wake_lockwake_unlock 创建 wakeup_source

1
2
3
4
struct wakelock {
struct rb_node node;
struct wakeup_source *ws;
};

__pm_stay_awake() / __pm_relax() 阻止 autosleep;可选 GC(PM_WAKELOCKS_GC)回收长期未用 wakelock。


十一、辅助组件

文件 功能
console.c VT 控制台在睡眠前后 save/restore
user.c /dev/snapshot 字符设备,uswsusp 用户态休眠
suspend_test.c 内核参数 test_suspend=mem 启动时自动测 suspend
poweroff.c Magic SysRq 触发 orderly poweroff
tracking.c 记录已卸载 taint 模块(debugfs)

十二、RK3588/ARM64 平台说明

12.1 ARM64 架构支持

配置 说明
ARCH_SUSPEND_POSSIBLE y 支持 STR
ARCH_HIBERNATION_POSSIBLE y 依赖 CPU_PM
ARCH_HIBERNATION_HEADER y 休眠镜像含 arch 头
CPU_PM select if SUSPEND CPU 电源管理

arch/arm64/kernel/suspend.c 提供 cpu_suspend()

1
2
3
4
5
6
7
8
int cpu_suspend(unsigned long arg, int (*fn)(unsigned long))
{
/* 保存 GPR、FP、debug、MMU 等到 sleep_stack_data */
if (__cpu_suspend_enter(&state))
ret = fn(arg); /* 平台 finisher,通常不再返回 */
else
__cpu_suspend_exit(); /* 唤醒恢复路径 */
}

12.2 Rockchip 平台扩展

配置 说明
ROCKCHIP_SUSPEND_MODE 通过 ATF 配置 suspend 模式
ROCKCHIP_LITE_ULTRA_SUSPEND mem_sleep 增加 lite/ultra(电子书等)
ROCKCHIP_SUSPEND_DEBUG suspend 调试
ROCKCHIP_SYSTEM_MONITOR 系统 monitor、early suspend

平台驱动在 init 时调用 suspend_set_ops(&rockchip_suspend_ops).enter() 最终通过 PSCI SYSTEM_SUSPEND 或 Rockchip ATF 进入硬件低功耗。

12.3 RK3588 常用操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 查看可用睡眠状态
cat /sys/power/state # freeze mem disk

# 选择 deep sleep 深度
cat /sys/power/mem_sleep # [s2idle] shallow deep (lite ultra)

# 进入 STR
echo mem > /sys/power/state

# S2Idle(仅 freeze,不进硬件 deep sleep)
echo freeze > /sys/power/state

# 唤醒源计数(避免睡眠竞态)
read /sys/power/wakeup_count
echo mem > /sys/power/state

12.4 big.LITTLE 注意点

  • STR 时 非 boot CPU 离线,boot CPU 在 suspend_ops->enter() 中最后进入 WFI/平台睡眠
  • 唤醒后 secondary CPU 重新 online;cpuidle 在 pm_sleep_disable/enable_secondary_cpus() 中 pause/resume
  • Energy Model 与 EAS 调度器配合,影响 睡眠前选核唤醒后负载迁移(逻辑在 kernel/sched/drivers/cpufreq/

十三、完整 Suspend 时序

platform/ATFdrivers/base/powerprocess.csuspend.cmain.c用户空间platform/ATFdrivers/base/powerprocess.csuspend.cmain.c用户空间CPU WFI / PSCI suspendecho mem > /sys/power/statepm_suspend(PM_SUSPEND_MEM)enter_state()suspend_freeze_processes()dpm_suspend_start()suspend_devices_and_enter()dpm_suspend_late/noirq()suspend_ops->enter()唤醒中断dpm_resume_*suspend_thaw_processes()返回用户空间

十四、总结

组件 职责
main.c /sys/power 接口、PM notifier、睡眠入口协调
suspend.c STR/S2Idle 状态机、DPM 与 platform ops 编排
process.c 睡眠前 freezer
hibernate.c + snapshot.c + swap.c 休眠到磁盘完整实现
qos.c PM QoS 约束聚合
energy_model.c DVFS 能耗表(EAS/thermal)
autosleep.c / wakelock.c opportunistic sleep 与 Android 式唤醒锁

kernel/power/ 是 Linux 系统级电源管理 的中枢;RK3588 实际进深睡依赖 Rockchip 平台驱动与 ATF/PSCI,本目录提供标准流程与 sysfs 接口。设备级 runtime PM 请结合 drivers/base/power/ 与具体驱动 dev_pm_ops 一并理解。


附录:源文件清单

文件 行数
kernel/power/snapshot.c 2756
kernel/power/hibernate.c 1367
kernel/power/swap.c 1619
kernel/power/main.c 940
kernel/power/qos.c 678
kernel/power/suspend.c 648
kernel/power/energy_model.c 438
kernel/power/user.c 466
kernel/power/wakelock.c 285
kernel/power/process.c 235
kernel/power/suspend_test.c 219
kernel/power/console.c 152
kernel/power/autosleep.c 129
kernel/power/poweroff.c 45
kernel/power/power.h 328
kernel/power/Kconfig 354
kernel/power/Makefile 24
合计 ~10305

关联源码(目录外)

文件 说明
drivers/base/power/main.c 设备 PM 核心
kernel/freezer.c 任务 refrigerator
arch/arm64/kernel/suspend.c CPU suspend 汇编入口
drivers/soc/rockchip/ RK3588 平台 suspend 配置

文章互动

阅读 --

留言

0 条留言

正在加载留言…