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 固件在系统内存地址空间中设置指向 XSDT(扩展系统描述表)的 RSDP(根系统描述指针)。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。

ACPI 命名空间示例

所有定义块都加载到单个命名空间中。命名空间是按名称和路径标识的对象层次结构。以下命名约定适用于 ACPI 命名空间中的对象名称

  1. 所有名称均为 32 位长。

  2. 名称的第一个字节必须是 'A' - 'Z'、'_' 之一。

  3. 名称的其余字节中的每一个都必须是 'A' - 'Z'、'0' - '9'、'_' 之一。

  4. 以 '_' 开头的名称由 ACPI 规范保留。

  5. 符号 '' 代表命名空间的根(即,以 '' 开头的名称相对于命名空间根)。

  6. 符号 '^' 代表当前命名空间节点的父节点(即,以 '^' 开头的名称相对于当前命名空间节点的父节点)。

下图显示了 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

为具有特定控制方法的 ACPI 命名空间节点创建 struct acpi_device 对象(如第二列中 ACPI 定义的设备类型所示)。包含其命名空间路径的 'path' 属性将存在于其 sysfs 目录中。例如,如果 ACPI 命名空间节点存在 _BCL 方法,则将为其创建具有 LNXVIDEO 'bus_id' 的 struct acpi_device 对象。

上表的第三列指示哪些 ACPI 系统描述表包含用于创建由给定行表示的 struct acpi_device 对象的信息(xSDT 表示 DSDT 或 SSDT)。

上表的第四列指示 struct acpi_device 对象的 'bus_id' 生成规则

_HID

表最后一列中的 _HID 表示对象的 bus_id 来自相应 ACPI 命名空间节点下的 _HID/_CID 标识对象。然后,对象的 sysfs 目录将包含可用于检索该对象的 _HID 和 _CID 的 'hid' 和 'modalias' 属性。

LNXxxxxx

对于具有 “LNXxxxxx” 形式(伪设备)的 bus_id 的 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 命名空间提供的设备标识。例如,如果存在一个 ACPI 命名空间对象,该对象表示一个 PCI 设备(即,一个 ACPI 命名空间对象下的设备对象,该对象表示一个 PCI 桥),其 _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 命名空间对应的 struct acpi_device 对象的 sysfs 层次结构,其中添加了固定的 PWR_BUTTON/SLP_BUTTON 设备

+--------------+---+-----------------+
| 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

注意

每个节点表示为 “对象/路径/modalias”,其中

  1. “对象” 是 sysfs 中对象目录的名称。

  2. “路径” 是相应 ACPI 命名空间对象的 ACPI 命名空间路径,由对象的 “path” sysfs 属性返回。

  3. “modalias” 是对象的 “modalias” sysfs 属性的值(如本文档前面所述)。

注意

N/A 表示设备对象没有 “path” 或 “modalias” 属性。