ACPI电源按钮唤醒S3切换到S0流程(附流程图)

ACPI电源按钮唤醒S3切换到S0流程(附流程图)

本文属于《 ACPI规范基础系列教程》之一,欢迎查看其它文章。

在 ‌S3(挂起到内存 / Suspend to RAM)‌ 状态下,系统仅保留内存供电,其余硬件(如CPU、硬盘、外设等)断电。唤醒S3并恢复到 ‌S0(工作状态)‌ 的主要方式如下:

常见唤醒途径

  • 按下电源按钮‌:这是最常见且广泛支持的方式,适用于绝大多数支持S3的设备 。
  • 外接键盘或鼠标输入‌:若系统BIOS/UEFI和驱动配置允许,按任意键或移动鼠标可触发唤醒 。
  • 网络唤醒(WOL, Wake-on-LAN)‌:
    • 需主板和网卡支持;
    • 路由器需配置端口转发(通常UDP 7或9端口);
    • 客户端发送"Magic Packet"唤醒包 。
  • USB设备唤醒‌:部分USB设备(如键盘、鼠标)在S3下仍可发送唤醒信号,前提是其在设备管理器中启用了"允许此设备唤醒计算机"选项 。
  • 定时器唤醒‌:通过操作系统设置唤醒定时器(如计划任务),可在指定时间自动唤醒。

与休眠流程(S0->S3)类似,唤醒流程也分为固定硬件 和通用事件 两种路径,下面以更标准的固定硬件方案为主线进行说明。

1 完整软硬件流程(S3 → S0)

第一阶段:硬件触发唤醒(物理层 → 芯片组 → 寄存器)

此时系统处于S3状态,CPU停止执行,内存自刷新,但芯片组的唤醒逻辑和部分待机电源仍在工作。

  1. 用户按下电源按钮:产生物理信号。
  2. EC捕获并转发 :嵌入式控制器检测到按钮按下,向芯片组的PWRBTN#专用引脚发送一个低脉冲。
  3. 芯片组唤醒逻辑启动 :
    • 芯片组检测到PWRBTN#信号。
    • 寄存器操作: 芯片组硬件将PM1状态寄存器 中的 PWRBTN_STS(电源按钮状态)位 置为 1,记录唤醒事件源。
    • 寄存器操作: 芯片组硬件将PM1状态寄存器 中的 WAK_STS(唤醒状态)位 置为 1,表示系统从睡眠状态唤醒。
  4. 硬件恢复电源 :
    • 芯片组解除SLP_S3#信号的断言(assertion),主电源轨恢复供电。
    • CPU接收POWER GOOD信号,从重置向量开始执行。

第二阶段:固件早期恢复(BIOS/UEFI)

此时CPU开始在实模式下执行固件代码。

  1. BIOS早期初始化 :快速初始化内存控制器、芯片组等必要部分,但不破坏内存中的内容。
  2. 检测唤醒源(固件视角) :
    • BIOS读取PM1状态寄存器,发现 WAK_STS位 为1,确认是从S3唤醒,而非冷启动。
    • (可选)BIOS可以读取PWRBTN_STS位,确认具体的唤醒原因。
  3. 查找OS唤醒向量 :
    • BIOS读取FACS 表中的FIRMWARE_WAKING_VECTOR,这个地址是操作系统在休眠前写入的,指向OS唤醒代码的入口。
  4. 跳转到OS:BIOS执行远跳转,进入OS的实模式唤醒代码。

第三阶段:OS内核重入(恢复执行上下文)

此时CPU进入OS的实模式唤醒代码,准备恢复执行。

  1. OS唤醒代码开始执行 :入口点通常是wakeup.S,CPU处于实模式。
  2. 恢复CPU运行环境 :
    • 代码通过ljmpl指令切换回保护模式。
    • 恢复休眠前保存的GDT、IDT和寄存器状态。
  3. 从休眠函数返回 :
    • 当CPU状态完全恢复后,代码从do_suspend_lowlevel()返回,看起来就像是从acpi_enter_sleep_state()函数正常返回一样。
    • 重新获取内核锁,恢复中断处理。

第四阶段:AML执行与设备恢复

此时内核已恢复基本运行,开始与ACPI固件交互并恢复设备。

  1. 调用_WAK方法 :
    • 内核调用ACPI控制方法_WAK,将唤醒状态作为参数传入。
    • _WAK方法由BIOS提供,执行平台特定的唤醒后操作(如重新配置EC、恢复某些GPIO状态)。
  2. OS确定唤醒源(OSPM视角) :
    • 寄存器操作: OS读取PM1状态寄存器,发现 PWRBTN_STS位 为1,确认是电源按钮唤醒了系统。
    • 寄存器操作: OS软件向PM1状态寄存器PWRBTN_STS位写入1,清除该状态位,表示事件已处理。
    • 寄存器操作: OS软件向PM1状态寄存器WAK_STS位写入1,清除唤醒状态标志。
  3. 恢复设备驱动 :
    • 内核遍历设备树,为每个设备调用注册的resume回调函数。
    • 设备驱动恢复硬件状态,重新初始化寄存器。
  4. 恢复控制台和中断:重新启用控制台输出,恢复所有中断。

第五阶段:软件恢复完成

  1. 解冻用户空间:内核解冻之前冻结的用户进程和内核线程。
  2. 返回用户空间:系统完全恢复到S0工作状态,看起来就像系统只是"暂停"了一下。

2 完整流程图

下面是根据上述流程,绘制的完整流程图:

3 关键寄存器与控制方法速查

为方便理解软硬件,以下是流程中涉及的寄存器/方法及其作用:

名称 类型 作用 所在位置
SLP_S3# 硬件信号 S3期间有效(低电平),唤醒时解除 芯片组引脚
FACS ACPI表 包含Firmware Waking Vector 内存中,由FADT指向
FIRMWARE_WAKING_VECTOR FACS字段 BIOS跳转到OS唤醒代码的地址 FACS偏移12
X_FIRMWARE_WAKING_VECTOR FACS字段 64位版本的唤醒向量 FACS偏移24
_WAK 控制方法 唤醒后执行的AML代码 DSDT
PWRBTN_STS 寄存器位 电源按钮事件状态位。硬件在电源按钮按下时自动置1;OS处理完成后写1清除。 PM1状态寄存器(PM1_STS)
WAK_STS 寄存器位 唤醒状态位。硬件在系统从S3唤醒时自动置1;OS处理完成后写1清除。 PM1状态寄存器(PM1_STS)
SLP_EN 寄存器位 睡眠使能位。OS在准备进入睡眠状态时将此位置1,触发硬件执行睡眠时序。 PM1控制寄存器(PM1_CNT)
SLP_TYP 寄存器字段 睡眠类型字段。OS写入目标S状态对应的编码值,指定睡眠深度。 PM1控制寄存器(PM1_CNT)
相关推荐
分布式存储与RustFS1 小时前
你的网站备份只存一块盘?把 1Panel 的备份目标换成 RustFS
运维·开源·备份·对象存储·1panel·s3·rustfs
分布式存储与RustFS4 小时前
十分钟在自己机器上跑通一个 S3 兼容对象存储(RustFS + Docker)
云原生·开源·对象存储·分布式存储·s3·rustfs·性能基准
分布式存储与RustFS1 天前
在 1Panel 应用商店部署 RustFS:安装、配置与验证步骤
云原生·开源·对象存储·分布式存储·s3·rustfs·性能基准
分布式存储与RustFS2 天前
GPU 在空转等数据?PyTorch 训练集进 RustFS 的三种接法
云原生·开源·对象存储·分布式存储·s3·rustfs·性能基准
分布式存储与RustFS3 天前
把 LSM 引擎直接架在对象存储上:slatedb 能不能跑在 RustFS 上?
运维·云原生·开源·对象存储·分布式存储·s3·性能基准
分布式存储与RustFS4 天前
机器要下线,数据先线上搬家:RustFS 存储池退役实操
运维·云原生·开源·对象存储·分布式存储·s3·性能基准
分布式存储与RustFS10 天前
RustFS 该跟 stable 还是 nightly?两条版本线的分工、风险与回退,一张表说清
运维·云原生·开源·对象存储·分布式存储·s3·性能基准
分布式存储与RustFS12 天前
训练集放在 RustFS 上,怎么像本地盘一样快?用 Curvine 加一层 POSIX 缓存
运维·云原生·开源·对象存储·分布式存储·s3·性能基准
分布式存储与RustFS14 天前
指标、日志、链路进同一个桶:GreptimeDB 存算分离解读与 RustFS 接入配置
运维·云原生·开源·对象存储·分布式存储·s3·性能基准
分布式存储与RustFS14 天前
RustFS 上生产第一步:从单机到 4 节点多盘集群(MNMD)部署实操
运维·云原生·开源·对象存储·分布式存储·s3·性能基准