ACPI设备树 - ACPI命名空间的表示¶
- 版权所有:
© 2013, 英特尔公司
- 作者:
郑律 <lv.zheng@intel.com>
- 鸣谢:
感谢张锐 <rui.zhang@intel.com> 和 Rafael J.Wysocki <rafael.j.wysocki@intel.com> 的帮助。
摘要¶
Linux ACPI子系统将ACPI命名空间对象转换为位于 /sys/devices/LNXSYSTM:00 下的Linux设备树,并在收到ACPI热插拔通知事件时对其进行更新。此层次结构中的每个设备对象在 /sys/bus/acpi/devices 中都有一个相应的符号链接。
本文档阐述了ACPI设备树的结构。
ACPI定义块¶
ACPI固件在系统内存地址空间中设置RSDP(根系统描述指针),指向XSDT(扩展系统描述表)。XSDT始终使用其第一个条目指向FADT(固定ACPI描述表),FADT中的数据包含描述硬件固定ACPI功能的各种固定长度条目。FADT包含指向DSDT(差分系统描述表)的指针。XSDT还包含指向可能多个SSDT(辅助系统描述表)的条目。
DSDT和SSDT数据以称为定义块的数据结构组织,这些定义块包含各种对象的定义,包括以AML(ACPI机器语言)编码的ACPI控制方法。DSDT的数据块以及SSDT的内容共同构成了一个称为ACPI命名空间的分层数据结构,其拓扑结构反映了底层硬件平台的结构。
上述ACPI系统定义表之间的关系在以下图表中进行了说明
+---------+ +-------+ +--------+ +------------------------+
| RSDP | +->| XSDT | +->| FADT | | +-------------------+ |
+---------+ | +-------+ | +--------+ +-|->| DSDT | |
| Pointer | | | Entry |-+ | ...... | | | +-------------------+ |
+---------+ | +-------+ | X_DSDT |--+ | | Definition Blocks | |
| Pointer |-+ | ..... | | ...... | | +-------------------+ |
+---------+ +-------+ +--------+ | +-------------------+ |
| Entry |------------------|->| SSDT | |
+- - - -+ | +-------------------| |
| Entry | - - - - - - - -+ | | Definition Blocks | |
+- - - -+ | | +-------------------+ |
| | +- - - - - - - - - -+ |
+-|->| SSDT | |
| +-------------------+ |
| | Definition Blocks | |
| +- - - - - - - - - -+ |
+------------------------+
|
OSPM Loading |
\|/
+----------------+
| ACPI Namespace |
+----------------+
Figure 1. ACPI Definition Blocks
注意
RSDP还可以包含指向RSDT(根系统描述表)的指针。平台提供RSDT是为了实现与ACPI 1.0操作系统的兼容性。如果XSDT存在,操作系统应使用XSDT。
ACPI命名空间示例¶
所有定义块都加载到一个单一的命名空间中。该命名空间是一个由名称和路径标识的对象层次结构。以下命名约定适用于ACPI命名空间中的对象名称
所有名称均为32位长。
名称的第一个字节必须是‘A’ - ‘Z’中的一个,或者‘_’。
名称的其余每个字节必须是‘A’ - ‘Z’、‘0’ - ‘9’中的一个,或者‘_’。
以‘_’开头的名称由ACPI规范保留。
符号‘\’表示命名空间的根(即,以‘\’为前缀的名称是相对于命名空间根的)。
符号‘^’表示当前命名空间节点的父级(即,以‘^’为前缀的名称是相对于当前命名空间节点父级的)。
下图显示了一个ACPI命名空间示例
+------+
| \ | Root
+------+
|
| +------+
+-| _PR | Scope(_PR): the processor namespace
| +------+
| |
| | +------+
| +-| CPU0 | Processor(CPU0): the first processor
| +------+
|
| +------+
+-| _SB | Scope(_SB): the system bus namespace
| +------+
| |
| | +------+
| +-| LID0 | Device(LID0); the lid device
| | +------+
| | |
| | | +------+
| | +-| _HID | Name(_HID, "PNP0C0D"): the hardware ID
| | | +------+
| | |
| | | +------+
| | +-| _STA | Method(_STA): the status control method
| | +------+
| |
| | +------+
| +-| PCI0 | Device(PCI0); the PCI root bridge
| +------+
| |
| | +------+
| +-| _HID | Name(_HID, "PNP0A08"): the hardware ID
| | +------+
| |
| | +------+
| +-| _CID | Name(_CID, "PNP0A03"): the compatible ID
| | +------+
| |
| | +------+
| +-| RP03 | Scope(RP03): the PCI0 power scope
| | +------+
| | |
| | | +------+
| | +-| PXP3 | PowerResource(PXP3): the PCI0 power resource
| | +------+
| |
| | +------+
| +-| GFX0 | Device(GFX0): the graphics adapter
| +------+
| |
| | +------+
| +-| _ADR | Name(_ADR, 0x00020000): the PCI bus address
| | +------+
| |
| | +------+
| +-| DD01 | Device(DD01): the LCD output device
| +------+
| |
| | +------+
| +-| _BCL | Method(_BCL): the backlight control method
| +------+
|
| +------+
+-| _TZ | Scope(_TZ): the thermal zone namespace
| +------+
| |
| | +------+
| +-| FN00 | PowerResource(FN00): the FAN0 power resource
| | +------+
| |
| | +------+
| +-| FAN0 | Device(FAN0): the FAN0 cooling device
| | +------+
| | |
| | | +------+
| | +-| _HID | Name(_HID, "PNP0A0B"): the hardware ID
| | +------+
| |
| | +------+
| +-| TZ00 | ThermalZone(TZ00); the FAN thermal zone
| +------+
|
| +------+
+-| _GPE | Scope(_GPE): the GPE namespace
+------+
Figure 2. Example ACPI Namespace
Linux ACPI设备对象¶
Linux内核的核心ACPI子系统为表示设备、电源资源处理器、热区的ACPI命名空间对象创建 struct acpi_device 对象。这些对象通过sysfs以目录形式导出到用户空间,位于 /sys/devices/LNXSYSTM:00 子树下。它们的名称格式为 <bus_id:instance>,其中‘bus_id’指代给定对象的ACPI命名空间表示,而‘instance’用于区分相同‘bus_id’的不同对象(它是无符号整数的两位十进制表示)。
‘bus_id’的值取决于其所属对象的类型,如下表所示
+---+-----------------+-------+----------+
| | Object/Feature | Table | bus_id |
+---+-----------------+-------+----------+
| N | Root | xSDT | LNXSYSTM |
+---+-----------------+-------+----------+
| N | Device | xSDT | _HID |
+---+-----------------+-------+----------+
| N | Processor | xSDT | LNXCPU |
+---+-----------------+-------+----------+
| N | ThermalZone | xSDT | LNXTHERM |
+---+-----------------+-------+----------+
| N | PowerResource | xSDT | LNXPOWER |
+---+-----------------+-------+----------+
| N | Other Devices | xSDT | device |
+---+-----------------+-------+----------+
| F | PWR_BUTTON | FADT | LNXPWRBN |
+---+-----------------+-------+----------+
| F | SLP_BUTTON | FADT | LNXSLPBN |
+---+-----------------+-------+----------+
| M | Video Extension | xSDT | LNXVIDEO |
+---+-----------------+-------+----------+
| M | ATA Controller | xSDT | LNXIOBAY |
+---+-----------------+-------+----------+
| M | Docking Station | xSDT | LNXDOCK |
+---+-----------------+-------+----------+
Table 1. ACPI Namespace Objects Mapping
根据ACPI系统描述表的内容创建 struct acpi_device 对象时,适用以下规则(如上表第一列的字母和第二列的符号所示)
- N
对象的来源是ACPI命名空间节点(如第二列中命名对象的类型所示)。在这种情况下,对象在sysfs中的目录将包含‘path’属性,其值为从命名空间根到该节点的完整路径。
- F
struct acpi_device 对象是为固定硬件功能创建的(如第二列中固定功能标志的名称所示),因此其sysfs目录将不包含‘path’属性。
- M
struct acpi_device 对象是为具有特定控制方法的ACPI命名空间节点创建的(如第二列中ACPI定义设备的类型所示)。包含其命名空间路径的‘path’属性将存在于其sysfs目录中。例如,如果ACPI命名空间节点存在 _BCL 方法,将为其创建一个‘bus_id’为LNXVIDEO的 struct acpi_device 对象。
上表的第三列指出了哪些ACPI系统描述表包含了用于创建由给定行表示的 struct acpi_device 对象的信息(xSDT表示DSDT或SSDT)。
上表的第四列指出了 struct acpi_device 对象的‘bus_id’生成规则
- _HID
表格最后一列中的 _HID 表示对象的 bus_id 来源于对应ACPI命名空间节点下存在的 _HID/_CID 标识对象。然后,对象的sysfs目录将包含‘hid’和‘modalias’属性,可用于检索该对象的 _HID 和 _CIDs。
- LNXxxxxx
对于 bus_id 为“LNXxxxxx”形式(伪设备)的 struct acpi_device 对象,也存在‘modalias’属性,在这种情况下它包含 bus_id 字符串本身。
- device
表格最后一列中的‘device’表示对象的 bus_id 无法从对应ACPI命名空间节点的 _HID/_CID 中确定,尽管该对象代表一个设备(例如,它可能是一个定义了 _ADR 但没有 _HID 或 _CID 的PCI设备)。在这种情况下,字符串‘device’将用作对象的 bus_id。
Linux ACPI物理设备粘合层¶
ACPI设备(即 struct acpi_device)对象可以链接到Linux设备层次结构中表示“物理”设备(例如,PCI总线上的设备)的其他对象。如果发生这种情况,意味着ACPI设备对象是某个以其他方式表示的设备的“伴侣”,并用于 (1) 提供无法通过其他方式获取的该设备的配置信息,以及 (2) 借助其ACPI控制方法对设备执行特定操作。一个ACPI设备对象可以以这种方式链接到多个“物理”设备。
如果ACPI设备对象链接到“物理”设备,其sysfs目录将包含指向目标设备对象sysfs目录的“physical_node”符号链接。反过来,目标设备的sysfs目录将包含指向伴侣ACPI设备对象sysfs目录的“firmware_node”符号链接。链接机制依赖于ACPI命名空间提供的设备标识。例如,如果有一个表示PCI设备的ACPI命名空间对象(即,在表示PCI桥的ACPI命名空间对象下的一个设备对象),其 _ADR 返回 0x00020000 且父PCI桥的总线号为0,则为该ACPI命名空间对象创建的 struct acpi_device 对象所代表的sysfs目录将包含指向相应PCI设备的 /sys/devices/pci0000:00/0000:00:02:0/ sysfs 目录的‘physical_node’符号链接。
链接机制通常是总线特定的。其实现的核心位于 drivers/acpi/glue.c 文件中,但根据涉及的总线类型,在其他地方也有补充部分。例如,其PCI特定部分位于 drivers/pci/pci-acpi.c。
Linux ACPI设备树示例¶
对应于图2所示ACPI命名空间示例(并增加了固定的PWR_BUTTON/SLP_BUTTON设备)的 struct acpi_device 对象sysfs层次结构如下所示
+--------------+---+-----------------+
| LNXSYSTM:00 | \ | acpi:LNXSYSTM: |
+--------------+---+-----------------+
|
| +-------------+-----+----------------+
+-| LNXPWRBN:00 | N/A | acpi:LNXPWRBN: |
| +-------------+-----+----------------+
|
| +-------------+-----+----------------+
+-| LNXSLPBN:00 | N/A | acpi:LNXSLPBN: |
| +-------------+-----+----------------+
|
| +-----------+------------+--------------+
+-| LNXCPU:00 | \_PR_.CPU0 | acpi:LNXCPU: |
| +-----------+------------+--------------+
|
| +-------------+-------+----------------+
+-| LNXSYBUS:00 | \_SB_ | acpi:LNXSYBUS: |
| +-------------+-------+----------------+
| |
| | +- - - - - - - +- - - - - - +- - - - - - - -+
| +-| PNP0C0D:00 | \_SB_.LID0 | acpi:PNP0C0D: |
| | +- - - - - - - +- - - - - - +- - - - - - - -+
| |
| | +------------+------------+-----------------------+
| +-| PNP0A08:00 | \_SB_.PCI0 | acpi:PNP0A08:PNP0A03: |
| +------------+------------+-----------------------+
| |
| | +-----------+-----------------+-----+
| +-| device:00 | \_SB_.PCI0.RP03 | N/A |
| | +-----------+-----------------+-----+
| | |
| | | +-------------+----------------------+----------------+
| | +-| LNXPOWER:00 | \_SB_.PCI0.RP03.PXP3 | acpi:LNXPOWER: |
| | +-------------+----------------------+----------------+
| |
| | +-------------+-----------------+----------------+
| +-| LNXVIDEO:00 | \_SB_.PCI0.GFX0 | acpi:LNXVIDEO: |
| +-------------+-----------------+----------------+
| |
| | +-----------+-----------------+-----+
| +-| device:01 | \_SB_.PCI0.DD01 | N/A |
| +-----------+-----------------+-----+
|
| +-------------+-------+----------------+
+-| LNXSYBUS:01 | \_TZ_ | acpi:LNXSYBUS: |
+-------------+-------+----------------+
|
| +-------------+------------+----------------+
+-| LNXPOWER:0a | \_TZ_.FN00 | acpi:LNXPOWER: |
| +-------------+------------+----------------+
|
| +------------+------------+---------------+
+-| PNP0C0B:00 | \_TZ_.FAN0 | acpi:PNP0C0B: |
| +------------+------------+---------------+
|
| +-------------+------------+----------------+
+-| LNXTHERM:00 | \_TZ_.TZ00 | acpi:LNXTHERM: |
+-------------+------------+----------------+
Figure 3. Example Linux ACPI Device Tree
注意
每个节点表示为“object/path/modalias”,其中
‘object’是对象在sysfs中的目录名称。
‘path’是相应ACPI命名空间对象的ACPI命名空间路径,其值由对象的‘path’sysfs属性返回。
‘modalias’是对象的‘modalias’sysfs属性的值(如本文档前面所述)。
注意
N/A 表示设备对象不具有‘path’或‘modalias’属性。