5.2.10. 固件 ACPI 控制结构 (FACS)
固件 ACPI 控制结构(FACS)是读/写存储器中的一个结构,平台启动固件保留该结构供ACPI使用。当且仅当设置了FADT中的HARDWARE_REDUCED_ACPI标志时,该结构才是可选的。使用FADT将FACS传递到ACPI兼容的OS。有关 FADT FIRMWARE_CTRL 字段的更多信息,请参阅第 5.2.9 节
平台引导固件将FACS对齐到系统内存地址空间内任何位置的 64 字节边界上。 FACS结构所在的内存不得在系统地址映射中报告为系统AddressRangeMemory。例如,E820地址映射报告界面会将区域报告为“AddressRangeReserved”。有关更多信息,请参阅第 15 节。
| 表 5.13 固件ACPI 控制结构 (FACS) 字段 | 字节长度 | 字节偏移 | 描述 |
|---|---|---|---|
| 签名 | 4 | 0 | ‘FACS’ |
| 长度 | 4 | 4 | 整个固件 ACPI 控制结构的长度(以字节为单位)。该值是 64 字节或更大。 |
| 硬件签名 | 4 | 8 | 上次启动时系统“硬件签名”的值。该值由平台引导固件尽力计算以指示系统的基本硬件配置,使得不同的基本硬件配置可以具有不同的硬件签名值。尽管在S4期间,OS不会保存/恢复使用 EfiPersistentMemory 描述的内存,但对影响任何OS可见固件接口的持久内存的任何更改都必须更改硬件签名(请参阅表 15.6)。对持久内存本身数据的任何更改不应包含在计算硬件签名中。通过将当前硬件签名与非易失性睡眠映像中保存的签名值进行比较,OSPM使用此信息从S4状态唤醒。如果值不同,OSPM假定保存的非易失性映像来自不同的硬件配置,并且无法恢复。 |
| 固件唤醒矢量 | 4 | 12 | 12该字段被X_Firmware_Waking_Vector字段取代。 OSPM 放置其唤醒向量的 32 位地址字段。在将系统转换为全局睡眠状态之前,OSPM用OS特定唤醒功能的物理内存地址填充此字段。在POST期间,平台固件首先检查X_Firmware_Waking_Vector字段的值是否非零,如果是,则将控制转移到OSPM,如下面X_Firmware_Waking_vector字段说明中所述。如果X_Firmware_Waking_Vector字段为零,则平台固件检查该字段的值,如果不为零,则将控制权转移到指定地址。在 PC 上,唤醒功能地址位于内存中低于 1MB 的位置,并且控制权在实模式下传输。 OSPM的唤醒功能可恢复处理器的上下文。对于IA-PC平台,以下示例显示了固件唤醒向量中的物理地址与BIOS跳转到的实模式地址之间的关系。例如,如果物理地址是 0x12345,则BIOS必须跳转到实模式地址 0x1234:0x0005。一般来说,这种关系是实模式地址 = 物理地址>>4:物理地址和 0x000F 请注意,在IA-PC平台上,当BIOS跳转到从存储在固件唤醒向量中的物理地址派生的实模式地址时,必须启用A20。 |
全局锁定| 4 | 16 | 16该字段包含全局锁,用于同步OSPM环境和外部控制器环境(例如SMI环境)之间对共享硬件资源的访问。该锁在任何时候均由OSPM或固件独占。当尝试获得锁的所有权时,它可能很忙,在这种情况下,请求环境退出并等待锁已被释放的信号。例如,全局锁可用于保护嵌入式控制器接口,以便在任何时候只有OSPM或固件才能访问嵌入式控制器接口。有关获取和释放全局锁的更多信息,请参阅第 5.2.10.1 节。 旗帜| 4 | 20 |表 5.14 X 固件唤醒矢量| 8 | 24 | OSPM 唤醒向量的 64 位物理地址。在将系统转换为全局睡眠状态之前,OSPM填充此字段和OSPM标志字段以描述唤醒向量。 OSPM用OS特定唤醒功能的物理内存地址填充该字段。在POST期间,平台固件检查该字段的值是否非零,如果是,则在创建适当的执行环境后跳转到该地址,将控制权转移到OSPM,必须按如下方式配置: 对于基于64位安腾™处理器系列(IPF)的平台:必须禁用中断 处理器必须将psr.i设置为0。请参阅Intel®有关详细信息,请参阅 ItaniumTM 架构软件开发人员手册。必须禁用内存地址转换 处理器必须将 psr.it、psr.dt 和 psr.rt 设置为 0。有关详细信息,请参阅英特尔® 安腾™ 架构软件开发人员手册。对于IA32 和 x64 平台,平台固件需要支持 32 位执行环境。平台固件还可以支持 64 位执行环境。如果平台固件支持 64 位执行环境,则固件会在POST期间检查OSPM标志。如果设置了64BIT_WAKE_F标志,平台固件将创建一个 64 位执行环境。否则,平台固件将创建 32 位执行环境。对于 64 位执行环境: 必须禁用中断 EFLAGS.IF 设置为 0 启用长模式 启用分页模式,并且唤醒向量的物理内存是恒等映射的(虚拟地址等于物理地址) 唤醒向量必须包含在一个物理页内 选择器设置为平面,否则不使用 对于 32 位执行环境: 必须禁用中断EFLAGS.IF 设置为 0 必须禁用内存地址转换/分页 4 GB 所有段寄存器的平面地址空间 版本 | 1 | 32 | 32 2-该表的版本 保留 | 3 | 33 | 33该值为零。 OSPM 旗帜 | 4 | 36 | 36 OSPM 启用固件控制结构标志。平台固件必须将该字段初始化为零。详细信息请参见表 5.15。 保留 | 24 | 40|该值为零。
| 表 5.14 固件控制结构功能标志 FACS - 标志 | 位长度 | 位偏移 | 描述 |
|---|---|---|---|
| S4BIOS_F | 1 | 0 | 指示平台是否支持S4BIOS_REQ。如果不支持S4BIOS_REQ,则OSPM必须能够保存和恢复内存状态才能使用S4状态。 |
64BIT_WAKE_SUPPORTED_F | 1 | 1 |表示平台固件支持唤醒向量的 64 位执行环境。当设置并且OSPM另外设置64BIT_WAKE_F时,平台固件将在将控制权转移到X_Firmware_Waking_Vector之前创建一个 64 位执行环境。 保留 | 30| 2 |该值为零。
| 表 5.15 OSPM 启用的固件控制结构功能标志 FACS - 标志 | 位长度 | 位偏移 | 描述 |
|---|---|---|---|
| 64BIT_WAKE_F | 1 | 0 | OSPM设置该位以向平台固件指示X_Firmware_Waking_Vector需要 64 位执行环境。仅当平台固件在FACS标志字段中设置64BIT_WAKE_SUPPORTED_F时,才能设置此标志。该位字段对基于 Itanium™ 处理器系列 (IPF) 的平台没有影响,该平台需要 64 位执行环境。 |
| 保留 | 31 | 1 | 该值为零。 |
5.2.10.1. 全局锁定
ACPI全局锁的目的是在主机OS和平台运行时固件之间提供互斥。全局锁是位于FACS内的读/写存储器中的 32 位 (DWORD) 值,并由OS环境和SMI环境以定义的方式访问和更新,以提供独占锁。注意:这不是指向全局锁的指针,而是锁的实际内存位置。 FACS和全局锁可以位于物理内存中的任何位置。
按照惯例,此锁用于确保当一个环境正在访问某些硬件时,另一环境则不能。根据此约定,当锁的所有权因其他环境拥有该锁而失败时,请求环境会在该锁内设置“挂起”状态,退出获取该锁的尝试,并等待拥有该锁的环境发出该锁已被释放的信号,然后再尝试再次获取该锁。释放锁时,如果锁释放后设置了锁中的挂起位,则通过中断机制向对方环境发送信号,通知其锁已被释放。在相应环境内的“锁释放”事件的中断处理期间,如果仍然需要锁所有权,则将尝试获取锁。如果未获取所有权,则环境必须再次设置“挂起”并等待另一个“锁定释放”信号。
下表显示了全局锁DWORD在内存中的编码。
| 表 5.16 FACS 字段内的全局锁结构 | 位长度 | 位偏移 | 描述 |
|---|---|---|---|
| 待定 | 1 | 0 | 非零表示全局锁所有权请求正在等待处理。 |
| 拥有 | 1 | 1 | 非零表示拥有全局锁。 |
| 保留 | 30 | 2 | 保留以供将来使用。 |
OSPM和固件使用以下代码序列来获取全局锁的所有权。如果函数返回非零,则调用者已被授予全局锁的所有权并可以继续。如果函数返回零,则表示调用者尚未被授予全局锁的所有权,“挂起”位已被设置,并且调用者必须等待,直到中断事件发出该锁可用的信号,然后再尝试再次获取访问权限。
注意事项
在下面的示例中,“GlobalLock”变量是一个指针,之前已初始化为指向FACS内的 32 位全局锁位置。
获取全局锁: mov ecx, GlobalLock ; ecx = Address of Global Lock in FACS acq10: mov eax, [ecx] ; Get current value of Global Lock
mov edx, eax
and edx, not 1 ; Clear pending bit
bts edx, 1 ; Check and set owner bit
adc edx, 0 ; If owned, set pending bit
lock cmpxchg dword ptr[ecx], edx ; Attempt to set new value
jnz short acq10 ; If not set, try again
cmp dl, 3 ; Was it acquired or marked pending?
sbb eax, eax ; acquired = -1, pending = 0
ret
OSPM和固件使用以下代码序列来释放全局锁的所有权。如果返回非零,则调用者必须向其他环境引发适当的事件,以表明全局锁现在已释放。根据环境,此信号是通过在各自的硬件寄存器空间内设置GBL_RLS或BIOS_RLS来完成的。仅当其他环境在拥有锁的情况下尝试获取所有权时,才会出现此信号。
ReleaseGlobalLock:
mov ecx, GlobalLock ; ecx = Address of Global Lock in FACS
rel10: mov eax, [ecx] ; Get current value of Global Lock
mov edx, eax
and edx, not 03h ; Clear owner and pending field
lock cmpxchg dword ptr[ecx], edx ; Attempt to set it
jnz short rel10 ; If not set, try again
and eax, 1 ; Was pending set?
; if one is returned (we were pending) the caller must signal that the
; lock has been released using either GBL_RLS or BIOS_RLS as appropriate
ret
尽管使用全局锁允许共享各种硬件资源,但值得注意的是,在存在所有权争用时使用它可能会带来大量的系统开销以及等待不确定的时间来获取全局锁的所有权。因此,实现应尝试设计硬件以将全局锁所需的使用量保持在最低限度。
每当硬件中的逻辑寄存器被共享时,就需要全局锁。例如,如果 ACPI (OSPM) 使用同一寄存器的位 0,而 SMI 使用同一寄存器的位 1,则需要在全局锁下保护对该寄存器的访问,以确保在另一个环境对其进行更改时,该寄存器的内容不会从一个环境下发生更改。类似地,如果整个寄存器是共享的(嵌入式控制器接口可能是这种情况),则需要在全局锁下保护对寄存器的访问。