linux 中 ACPI 电源管理 G 状态、S 状态、D 状态、C 状态、P 状态

ACPI 高级电源管理

ACPI 中定义了 G、D、S、C、P 这 5 个大的电力状态。

G 状态 Global system state

G 状态表示的是用户看到的整个系统的电力状态。

  • G0 运行模式。向硬件提供电源,软件可以运行的状态。

  • G1 停止模式。所谓的待机或休眠状态。

  • G2 软件为关闭状态,应将消耗若干电力状态。

  • G3 系统完全关闭,电源关闭的状态。

S 状态

  • S0 运行模式,与 G0 相同。

  • S1 到恢复为止的延迟时间较少的停止模式。 CPU 的上下文不会丢失。

  • S2 丢失 CPU 和系统缓存上下文。这些上下文需要在系统唤醒时进行恢复。在 Linux 中与 S3 相同。

  • S3 丢失除软件以外的系统上下文。这些上下文需要在操作系统唤醒时进行恢复。

  • S4 最省电。到恢复为止花费时间最多的停止模式。停止向所有设备提供电源

  • S5 除了不保存上下文以外,其它与 S4 相同。 S5 在恢复时进行的处理与普通的操作系统相同。与 G2 含义相同。

D 状态

Device Power State 定义的是各个设备的电力状态,设备的状态有如下内容:

  • 耗电量
  • 保存设备内寄存器上下文的状态
  • 直到设备驱动程序可使用为止必须进行的操作量
  • 直到设备可使用为止需要的时间

不同的子状态描述如下:

  • D0 设备可以完全运行的状态。所有上下文全部有效,最耗电。

  • D1 对于每个设备的意义不同。一般来说,耗电量比 D0 少,丢失的上下文比 D2 更少

  • D2 对于每个设备类型的意义也不同。一般来说,耗电量比 D1 更少,丢失的上下文比 D1 更多。

  • D3hot 对于每个设备类型的意义不同。D3hot 状态的设备主电源开启,可以从软件访问设备。但上下文是否能保留取决于实际安装的设备。D3 设备电源完全断开的状态。设备的上下文全部丢失,到恢复为止花的时间最长。在 PCI 用语中称为 D3cold。PCI 中常常将 D3hot 与 D3cold 统称为 D3

C 状态

Processor Power State 是 G0 中 CPU 空闲时进行的省电模式。

  • C0 运行中的状态。通常的运行模式。

  • C1 CPU 停止状态。使用 hlt 命令停止 CPU 的时钟,到恢复为止几乎没有延迟时间,软件不需进行特殊处理。

  • C2 总线的时钟也停止。恢复所花费的最长延时时间传递给 ACPI 的固件,操作系统基于这个延时时间判断使用 C1 还是 C2。

  • C3 将花费时间最长的延迟传递给 ACPI 固件,操作系统使用这个延迟时间判断使用 C2 还是 C3。操作系统需要考虑缓存的同步。

使用 C 状态时要注意,C 状态的程度越深,恢复到 C0 状态所需的时间越长。

P 状态

全称为 Device and Processor Performance State

P 状态是以控制电量消耗来降低设备或 CPU 的性能,对 D0 状态的设备、C0 状态的 CPU 进行了更细致的划分。

  • P0 通常的模式。以最高性能、最大耗电量运行。

  • P1 运行在低于最高性能、最大耗电量的模式 Pn n 的值越大,性能和耗电量越低。

ACPI 的结构

  1. ACPI 系统描述表
  2. ACPI 寄存器
  3. ACPI BIOS

ACPI 描述表在 ACPI 的接口中是核心的组件,提供 ACPI 寄存器等信息。ACPI BIOS 可以 提供 ACPI 系统描述表以及启动、停止、唤醒等功能。

两个编程模型

ACPI 的硬件模型有下面两种:

固定硬件编程模型

使用 ACPI 中定义的寄存器来访问 ACPI 的功能。

通用硬件编程模型

各厂商可以使用 ACPI Machine Language 将硬件固有的处理安装到 BIOS 中。操作系统可 以通过分析 BIOS 提供的 AML 代码,来理解就餐器的地址和访问方法等。

AML 是二进制码,通过编译 ACPI Source language 来生成。操作系统分析 AML 将 AML中 所写的内容按照解释器来执行。

ACPI 系统描述表

可以通过 pmtools 与 iasl 相关的命令来查看。执行如下命令安装这两个程序:

sudo apt-get install pmtools sudo apt-get install iasl

运行示例如下:

root@debian:~# acpidump -b -o dsdt.dat 
root@debian:~# ls apic.dat boot.dat dsdt.dat facp.dat facs.dat hpet.dat mcfg.dat srat.dat waet.dat 
root@debian:~# ls apic.dat boot.dat dsdt.dat facp.dat facs.dat hpet.dat mcfg.dat srat.dat waet.dat root@debian:~#
root@debian:~# iasl -d dsdt.dat

Intel ACPI Component Architecture
ASL+ Optimizing Compiler/Disassembler version 20181213
Copyright (c) 2000 - 2018 Intel Corporation

Input file dsdt.dat, Length 0x1368A (79498) bytes
ACPI: DSDT 0x0000000000000000 01368A (v01 PTLTD  Custom   06040000 MSFT 03000001)
Pass 1 parse of [DSDT]
Pass 2 parse of [DSDT]
Parsing Deferred Opcodes (Methods/Buffers/Packages/Regions)

Parsing completed
Disassembly completed
ASL Output:    dsdt.dsl - 729339 bytes
root@debian:~# head -n 30 dsdt.dsl
/*
 * Intel ACPI Component Architecture
 * AML/ASL+ Disassembler version 20181213 (64-bit version)
 * Copyright (c) 2000 - 2018 Intel Corporation
 *
 * Disassembling to symbolic ASL+ operators
 *
 * Disassembly of dsdt.dat, Mon Aug 10 12:43:44 2020
 *
 * Original Table Header:
 *     Signature        "DSDT"
 *     Length           0x0001368A (79498)
 *     Revision         0x01 **** 32-bit table (V1), no 64-bit math support
 *     Checksum         0x63
 *     OEM ID           "PTLTD "
 *     OEM Table ID     "Custom  "
 *     OEM Revision     0x06040000 (100925440)
 *     Compiler ID      "MSFT"
 *     Compiler Version 0x03000001 (50331649)
 */
DefinitionBlock ("", "DSDT", 1, "PTLTD ", "Custom  ", 0x06040000)
{
    External (_SB_.L1M0.L0MX, IntObj)
    External (_SB_.L1M1.L0MX, IntObj)
    External (_SB_.L1M2.L0MX, IntObj)
    External (_SB_.L1M3.L0MX, IntObj)
    External (_SB_.L1M4.L0MX, IntObj)
    External (_SB_.L1M5.L0MX, IntObj)
    External (_SB_.L1M6.L0MX, IntObj)
    External (_SB_.L1M7.L0MX, IntObj)

使用 ACPI 的 S 状态

查看支持的 S 状态:

root@debian:~# cat /sys/power/state
freeze standby mem disk
standby S1 mem S3 disk S4

切换状态:

echo "状态字符串" > /sys/power/state

执行示例:

root@debian:~# echo "mem" > /sys/power/state

按下电源键就可以恢复。

S3 状态的结构

使用 S3 状态时,不同系统的反应不同,大致操作如下:

  • 停止进程
  • 停止设备运行
  • 将唤醒时的开始地址作为 Wakeup vector 登录到 BIOS
  • 停止 BSP (Boot Strap Processor) 以外的 CPU 运行
  • 停止系统设备运行
  • 保存内核和 CPU 的状态
  • 将获取到的 ACPI 的 _S3 对象得到的值写入 FADT 的 PM1 寄存器,进入待机模式。
  • 系统恢复时,从登录到 wakeup vector 的地址启动,按下列方式恢复到待机前的状态
  • 启用 ACPI
  • 恢复系统设备
  • 启用 CPU
  • 清除 wakeup vector
  • 恢复停止的设备
  • 恢复进程

S4 状态的使用方法

linux 中 S4 称为 swap 待机,有内核的 S4 处理通过将内存上的所有数据保存在交换区磁盘来停止电源,恢复时由 bootloader 启动内核,在内核初始化时,把之前保存到交换区磁盘的数据读入内存来快速回复到原来的状态。

使用方法如下:

echo "platform" > /sys/power/disk 
echo "disk" > /sys/power/state

休眠要使用交换区磁盘,一般需要准备内存的 1.5 ~ 2 倍的磁盘容量。这应该就是 swap 要设置为 2 倍内存大小的原因。

在我的系统中,默认保存在交换区磁盘的内存大小如下:

longyu@debian:~$ cat /sys/power/image_size 814505984

执行如下命令来取消限制。

echo "0" > /sys/power/image_size

执行一次休眠后按电源键重新启动系统后查看 dmesg 信息,有如下相关信息:

[  759.283304] PM: hibernation entry
[  759.285989] PM: Syncing filesystems ...
[  759.289551] PM: done.
[  759.289552] Freezing user space processes ... (elapsed 0.001 seconds) done.
[  759.291357] OOM killer disabled.
[  759.291465] PM: Marking nosave pages: [mem 0x00000000-0x00000fff]
[  759.291466] PM: Marking nosave pages: [mem 0x0009e000-0x000fffff]
[  759.291467] PM: Marking nosave pages: [mem 0x7fee0000-0x7fefffff]
[  759.291468] PM: Basic memory bitmaps created
[  759.291505] PM: Preallocating image memory... done (allocated 95921 pages)
[  759.339329] PM: Allocated 383684 kbytes in 0.04 seconds (9592.10 MB/s)
[  759.339330] Freezing remaining freezable tasks ... (elapsed 0.002 seconds) done.
[  759.342363] Suspending console(s) (use no_console_suspend to debug)
[  759.343092] serial 00:05: disabled
[  759.376353] mptbase: ioc0: pci-suspend: pdev=0x0000000010a726cd, slot=0000:00:10.0, Entering operating state [D0]
[  759.457082] ACPI: Preparing to enter system sleep state S4
[  759.457366] PM: Saving platform NVS memory
[  759.457368] Disabling non-boot CPUs ...
[  759.494741] smpboot: CPU 1 is now offline
[  759.522630] smpboot: CPU 2 is now offline
[  759.550458] smpboot: CPU 3 is now offline
[  759.583388] smpboot: CPU 4 is now offline
[  759.606987] smpboot: CPU 5 is now offline
[  759.625346] smpboot: CPU 6 is now offline
[  759.653837] smpboot: CPU 7 is now offline
[  759.655801] PM: Creating hibernation image:
[  759.682494] PM: Need to copy 90196 pages
[  759.682497] PM: Normal pages needed: 90196 + 1024, available pages: 433921
[18446744073.256268] PM: Restoring platform NVS memory
[18446744073.257563] Enabling non-boot CPUs ...
[18446744073.257640] x86: Booting SMP configuration:
[18446744073.257640] smpboot: Booting Node 0 Processor 1 APIC 0x1
[18446744073.258291] Disabled fast string operations
[18446744073.258509]  cache: parent cpu1 should not be sleeping
[18446744073.258972] CPU1 is up
[18446744073.258998] smpboot: Booting Node 0 Processor 2 APIC 0x2
[18446744073.259670] Disabled fast string operations
[18446744073.259845]  cache: parent cpu2 should not be sleeping
[18446744073.260236] CPU2 is up
[18446744073.260272] smpboot: Booting Node 0 Processor 3 APIC 0x3
[18446744073.260877] Disabled fast string operations
[18446744073.261022]  cache: parent cpu3 should not be sleeping
[18446744073.261423] CPU3 is up
[18446744073.261443] smpboot: Booting Node 0 Processor 4 APIC 0x4
[18446744073.262117] Disabled fast string operations
[18446744073.262547]  cache: parent cpu4 should not be sleeping
[18446744073.263934] CPU4 is up
[18446744073.263991] smpboot: Booting Node 0 Processor 5 APIC 0x5
[18446744073.264913] Disabled fast string operations
[18446744073.265184]  cache: parent cpu5 should not be sleeping
[18446744073.265796] CPU5 is up
[18446744073.265821] smpboot: Booting Node 0 Processor 6 APIC 0x6
[18446744073.266459] Disabled fast string operations
[18446744073.266673]  cache: parent cpu6 should not be sleeping
[18446744073.267193] CPU6 is up
[18446744073.267219] smpboot: Booting Node 0 Processor 7 APIC 0x7
[18446744073.267894] Disabled fast string operations
[18446744073.268043]  cache: parent cpu7 should not be sleeping
[18446744073.268521] CPU7 is up
[18446744073.269975] ACPI: Waking up from system sleep state S4
[18446744073.325536] mptbase: ioc0: pci-resume: pdev=0x0000000010a726cd, slot=0000:00:10.0, Previous operating state [D0]
[18446744073.325631] mptbase: ioc0: pci-resume: ioc-state=0x1,doorbell=0x14000000
[18446744073.325631] mptbase: ioc0: Sending mpt_do_ioc_recovery
[18446744073.325632] mptbase: ioc0: Initiating bringup
[18446744073.325634] [drm] width 640
[18446744073.325639] [drm] height 480
[18446744073.325643] [drm] bpp 32
[18446744073.327033] [drm] Fifo max 0x00040000 min 0x00001000 cap 0x0000077f
[18446744073.327785] [drm] Using command buffers with DMA pool.
[18446744073.328515] usb usb2: root hub lost power or was reset
[18446744073.330434] serial 00:05: activated
[18446744073.331200] usb usb1: root hub lost power or was reset
[18446744073.331518] ehci-pci 0000:02:03.0: cache line size of 64 is not supported
[18446744073.389402] e1000: ens38 NIC Link is Up 1000 Mbps Full Duplex, Flow Control: None
[18446744073.423015] ioc0: LSI53C1030 B0: Capabilities={Initiator}
[18446744073.662087] mptbase: ioc0: pci-resume: success
[18446744073.696571] usb 2-2: reset full-speed USB device number 3 using uhci_hcd
[    0.267194] usb 2-1: reset full-speed USB device number 2 using uhci_hcd
[    0.433369] PM: Basic memory bitmaps freed
[    0.433370] OOM killer enabled.
[    0.433370] Restarting tasks ... done.
[    0.436577] PM: hibernation exit

PM: hibernation entry 与 PM: hibernation exit 之间就是休眠过程的处理。

有的 PC 上可能出现 BIOS 无法顺利运行,休眠失败的情况,这时可以尝试如下方法:

  1. 编辑 grub.cfg 内核启动参数中添加用于恢复系统的交换设备 “resume=<交换设备名称>” 如 resume=/dev/sda1

  2. 执行如下敏玲将休眠设置为 shutdown 模式

	echo shutdown > /sys/power/disk
  1. 进行休眠
	echo disk > /sys/power/state

如果恢复系统后系统运行状态有所不同,有时会通过将交换区的数据强制读入内存来改善性能,这可以通过执行如下命令来完成:

swapoff -a
swapon -a

如果休眠失败,可以查看 /var/log/messages 文件来寻找原因。

你可能感兴趣的:(Linux,电源管理,ACPI,linux,系统休眠)