4. FADT详解:电源管理寄存器与中断配置
FADT(Fixed ACPI Description Table)是 ACPI 启动流程中仅次于 RSDP 的核心表。它承载了硬件平台与 OSPM(操作系统电源管理)之间的关键握手信息,包括电源管理寄存器的物理地址、SCI 中断路由策略以及 SMI 命令端口。本章将深入解析 FADT 中与电源性能调优直接相关的字段。
4.1 FADT 表头与核心结构
FADT 的起始部分遵循标准 ACPI 表头,随后是长度可变的固定布局字段。下表列出了与电源管理直接相关的关键字段及其偏移量:
| 偏移(字节) | 字段名称 | 长度(字节) | 描述 |
|---|---|---|---|
| 0 | Signature | 4 | 固定为 "FACP" |
| 4 | Length | 4 | 表总长度,>= 244(ACPI 6.5) |
| 40 | SCI_INT | 2 | SCI 中断号(通常为 9) |
| 44 | SMI_CMD | 4 | SMI 命令端口 I/O 地址 |
| 48 | ACPI_ENABLE | 1 | 写入 SMI_CMD 以启用 ACPI 的值 |
| 49 | ACPI_DISABLE | 1 | 写入 SMI_CMD 以禁用 ACPI 的值 |
| 64 | PM1a_EVT_BLK | 4 | PM1a 事件寄存器块基地址 |
| 68 | PM1b_EVT_BLK | 4 | PM1b 事件寄存器块基地址(0 表示不存在) |
| 72 | PM1a_CNT_BLK | 4 | PM1a 控制寄存器块基地址 |
| 76 | PM1b_CNT_BLK | 4 | PM1b 控制寄存器块基地址(0 表示不存在) |
| 80 | PM2_CNT_BLK | 4 | PM2 控制寄存器块基地址(0 表示不存在) |
| 84 | PM_TMR_BLK | 4 | PM 定时器寄存器块基地址 |
| 88 | GPE0_BLK | 4 | GPE0 寄存器块基地址 |
| 92 | GPE1_BLK | 4 | GPE1 寄存器块基地址(0 表示不存在) |
acpidump 和 iasl 解析 FADT 时,重点关注 SCI_INT 是否与 IRQ 路由表匹配,以及 PM1a_EVT_BLK 的地址是否在 ACPI 驱动 IO 资源范围内。
4.2 电源管理寄存器详解
FADT 描述的电源管理寄存器块是 OSPM 直接操作硬件电源状态的窗口。这些寄存器通过 I/O 空间或内存映射空间访问,具体由 X_PM1a_EVT_BLK 等扩展地址字段中的地址空间 ID 决定。
4.2.1 PM1 事件与状态寄存器(PM1_EVT)
PM1_EVT 块包含两组寄存器:状态寄存器(PM1_STS)和使能寄存器(PM1_EN)。每组长度为 2 字节(16 位)。PM1a 是必须存在的,PM1b 为可选。当 PM1b 存在时,其寄存器与 PM1a 的对应寄存器在逻辑上拼接为 32 位宽。
- PM1_STS(偏移 0x00): 记录电源管理事件,如电源按钮按下、唤醒事件、RTC 闹钟等。写 1 清零。
- PM1_EN(偏移 0x02): 控制哪些事件可以触发 SCI。写 1 使能对应事件的中断。
4.2.2 PM1 控制寄存器(PM1_CNT)
PM1_CNT 块长度为 2 字节,用于控制系统睡眠状态转换(Sleep/ Wake)和 CPU 时钟调节。关键位域包括:
- SCI_EN(Bit 0): ACPI 硬件使能标志。OSPM 通过写入 SMI_CMD 使能 ACPI 后,此位由硬件置 1。
- SLP_TYPx(Bits 10-12): 睡眠类型,定义要进入的 S 状态(S1/S3/S4/S5)。
- SLP_EN(Bit 13): 睡眠使能位。OSPM 写入此位后,硬件立即开始睡眠序列。
4.2.3 PM2 控制寄存器(PM2_CNT)
PM2_CNT 块长度为 1 字节,主要用于处理器性能状态(P-State)的硬件协调。其核心位域为:
- ARB_DIS(Bit 0): 总线仲裁禁用位。在某些多处理器系统中,用于控制处理器对系统总线的访问优先级,以配合 P-State 切换。
4.2.4 GPE 寄存器块
GPE(General Purpose Event)寄存器块用于处理非固定功能的电源管理事件,例如设备唤醒、热插拔、电池状态变化等。每个 GPE 块包含状态寄存器和使能寄存器,长度由 FADT 中的 GPE0_BLK_LEN 和 GPE1_BLK_LEN 字段定义。
X_PM1a_EVT_BLK 等扩展字段确认寄存器是否映射到 MMIO 空间,MMIO 通常比 IO 空间具有更低的访问延迟。
4.3 SCI 中断配置
SCI(System Control Interrupt)是 ACPI 硬件向 OSPM 发送事件通知的主要机制。FADT 中的 SCI_INT 字段定义了 SCI 使用的 IRQ 号。在 x86 平台上,这个值通常为 9,但也可以由平台固件配置为其他值。
4.3.1 SCI 中断路由
SCI 必须被配置为高电平触发(Level-Triggered, High Active)。OSPM 在启动阶段通过解析 MADT(Multiple APIC Description Table)和 FADT 来建立 SCI 的中断路由。如果 SCI_INT 与某个设备的中断号冲突,会导致中断风暴或功能异常。
SCI_INT = 0,这表示 SCI 未使用或通过其他方式配置。OSPM 在这种情况下应回退到默认 IRQ 9,并验证中断控制器是否已正确配置。
4.3.2 SCI 与 SMI 的协同
在系统从 SMM(System Management Mode)过渡到 ACPI 模式时,SCI 和 SMI 的切换是关键步骤。FADT 中的 SMI_CMD、ACPI_ENABLE 和 ACPI_DISABLE 字段定义了 OSPM 如何通过写入 I/O 端口来请求固件切换中断模式。
4.4 SMI 命令端口
SMI_CMD 字段定义了 OSPM 用于与 SMM 通信的 I/O 端口地址。OSPM 通过向此端口写入 ACPI_ENABLE 或 ACPI_DISABLE 值,请求固件在 SMM 中执行 ACPI 模式的切换。
4.4.1 命令端口使用规范
- ACPI_ENABLE: OSPM 写入此值后,固件应设置 SCI_EN 位,并将 SCI 中断路由到操作系统。
- ACPI_DISABLE: OSPM 写入此值后,固件应清除 SCI_EN 位,并将控制权交还给 SMM。
- 端口宽度: 通常为 8 位 I/O 端口,但 FADT 也支持通过
X_SMI_CMD扩展字段定义 32 位或 64 位地址。
cat /sys/firmware/acpi/tables/FACP 查看原始 FADT 内容。使用 iasl -d FACP.dat 反编译后,重点关注 SMI_CMD 和 ACPI_ENABLE 字段。如果系统无法进入 ACPI 模式,检查 SMI_CMD 端口是否被其他设备占用。
4.5 实战:解析 FADT 并验证电源管理配置
以下步骤演示了如何在 Linux 环境下解析 FADT 并验证关键电源管理配置:
- 获取 FADT 原始数据:
acpidump > acpi.dat && acpixtract -a acpi.dat - 反编译 FADT:
iasl -d FACP.dat - 查看反编译输出: 打开
FACP.dsl,定位到以下字段:
// FACP.dsl 关键字段示例
[0x02C] SCI_INT : 9
[0x030] SMI_CMD : 000000B2
[0x034] ACPI_ENABLE : 01
[0x035] ACPI_DISABLE : 00
[0x040] PM1a_EVT_BLK : 00001000
[0x044] PM1b_EVT_BLK : 00000000
[0x048] PM1a_CNT_BLK : 00001004
[0x04C] PM1b_CNT_BLK : 00000000
[0x050] PM2_CNT_BLK : 00001050
[0x054] PM_TMR_BLK : 00001008
[0x058] GPE0_BLK : 00001020
[0x05C] GPE1_BLK : 00000000
- 验证寄存器地址范围: 使用
cat /proc/ioports检查上述 I/O 地址是否被正确声明。 - 检查 SCI 中断:
cat /proc/interrupts | grep acpi确认 SCI 中断号与 FADT 中的SCI_INT一致。
X_PM1a_EVT_BLK 等 64 位扩展地址字段。这些字段允许寄存器映射到 MMIO 空间,从而减少 IO 指令的开销,提升电源管理事件的响应速度。
4.6 本章小结
FADT 是 ACPI 电源管理的硬件接口手册。通过本章的学习,你应该掌握:
- PM1a/PM1b、PM2、GPE 寄存器块的布局与功能。
- SCI 中断的配置方法及其与 SMI 的切换流程。
- SMI 命令端口的使用规范与调试要点。
- 如何通过 Linux 工具解析 FADT 并验证硬件配置的正确性。