Skip to the content.

6. ACPI considerations for PCI host bridges

一般规则是 ACPI 命名空间应该描述操作系统可能使用的所有内容,除非操作系统有其他方法可以找到它 [1, 2]。

例如,没有用于枚举 PCI 主桥的标准硬件机制,因此 ACPI 命名空间必须描述每个主桥、访问其下面的 PCI 配置空间的方法、主桥转发到 PCI 的地址空间窗口(使用 _CRS)以及 传统 INTx 中断的路由(使用 _PRT)。

PCI 设备位于主桥下方,一般不需要通过 ACPI 进行描述。 操作系统可以通过标准 PCI 枚举机制发现它们,使用配置访问来发现和识别设备并读取其 BAR 并调整其大小。 但是,如果 ACPI 为 PCI 设备提供电源管理或热插拔功能,或者设备具有由平台中断控制器连接的 INTx 中断,并且需要 _PRT 来描述这些连接,则 ACPI 可以描述 PCI 设备。

ACPI 资源描述是通过 ACPI 命名空间中设备的 _CRS 对象完成的 [2]。 _CRS 就像一个通用的 PCI BAR:操作系统可以读取 _CRS 并找出正在消耗的资源,即使它没有设备的驱动程序 [3]。 这很重要,因为这意味着旧操作系统即使在操作系统未知的新设备的系统上也可以正常工作。 新设备可能不会做任何事情,但操作系统至少可以确保不会与它们发生资源冲突。

MCFG、HPET、ECDT 等静态表不是保留地址空间的机制。 静态表用于操作系统在启动早期需要了解的内容,然后才能解析 ACPI 命名空间。 如果定义了新表,则旧操作系统即使忽略该表也需要正确运行。 _CRS 允许这样做,因为它是通用的并且可以被旧操作系统理解; 静态表则不然。

如果操作系统需要管理通过 ACPI 描述的不可发现的设备,则该设备将具有特定的 _HID/_CID,告诉操作系统要绑定到它的驱动程序,并且 _CRS 告诉操作系统和驱动程序设备寄存器的位置 。

PCI 主桥是 PNP0A03 或 PNP0A08 设备。 它们的 _CRS 应该描述它们消耗的所有地址空间。 这包括它们向下转发到 PCI 总线的所有窗口,以及主桥本身未转发到 PCI 的寄存器。 主桥寄存器包括诸如辅助/从属总线寄存器之类的东西,这些寄存器确定桥下方的总线范围,描述孔径的窗口寄存器等。这些都是特定于设备的、非架构的东西,因此 PNP0A03/PNP0A08 的唯一方法 驱动程序可以通过 _PRS/_CRS/_SRS 管理它们,其中包含设备特定的详细信息。 主桥寄存器还包括 ECAM 空间,因为它被主桥消耗。

ACPI 定义了消费者/生产者位来区分桥寄存器(“消费者”)和桥孔径(“生产者”)[4, 5],但早期的 BIOS 没有正确使用该位。 结果是当前的 ACPI 规范仅针对扩展地址空间描述符定义了消费者/生产者; 在较旧的 QWord/DWord/Word 地址空间描述符中应忽略该位。 因此,操作系统必须假设所有 QWord/DWord/Word 描述符都是窗口。

在添加扩展地址空间描述符之前,消费者/生产者的故障意味着无法描述 PNP0A03/PNP0A08 设备本身中的桥寄存器。 解决方法是描述 PNP0C02 catch-all 器件中的桥寄存器(包括 ECAM 空间)[6]。 除了 ECAM 之外,桥寄存器空间无论如何都是特定于设备的,因此通用 PNP0A03/PNP0A08 驱动程序 (pci_root.c) 无需了解它。

新架构应该能够在 PNP0A03 器件中使用桥寄存器(包括 ECAM)中的“消费者”扩展地址空间描述符,尽管 [6] 的严格解释可能会禁止这样做。 旧的 x86 和 ia64 内核假定所有地址空间描述符(包括“消费者”扩展地址空间描述符)都是 Windows,因此在这些体系结构上以这种方式描述桥寄存器是不安全的。

PNP0C02“主板”设备基本上是包罗万象的。 除了“不要将这些资源用于其他用途”之外,没有其他编程模型。 因此,PNP0C02 _CRS 应该声明 (1) ACPI 命名空间中任何其他设备对象下的 _CRS 未声明的任何地址空间,以及 (2) 不应由操作系统分配给其他内容。

PCIe 规范需要增强配置访问方法 (ECAM),除非有用于配置访问的标准固件接口,例如 ia64 SAL 接口 [7]。 主桥占用 ECAM 内存地址空间并将内存访问转换为 PCI 配置访问。 该规范定义了 ECAM 地址空间布局和功能; 只有地址空间的基址是特定于设备的。 ACPI 操作系统从静态 MCFG 表或 PNP0A03 设备中的 _CBA 方法学习基地址。

MCFG 表必须描述非热插拔主桥的 ECAM 空间 [8]。 由于MCFG是静态表并且不能通过热插拔更新,因此PNP0A03器件中的_CBA方法描述了可热插拔主桥的ECAM空间[9]。 请注意,对于 MCFG 和 _CBA,基地址始终对应于总线 0,即使桥下方的总线范围(通过 _CRS 报告)不从 0 开始。

[1] ACPI 6.2, sec 6.1:

 对于位于不可枚举类型总线(例如 ISA 总线)上的任何设备,OSPM 会枚举设备的标识符,并且 ACPI 系统固件必须为每个设备提供 _HID 对象以启用 OSPM 要做到这一点。

[2] ACPI 6.2, sec 3.7:

 操作系统只需读取 ACPI 命名空间并查找具有硬件 ID 的设备即可枚举主板设备。

 ACPI 枚举的每个设备都包含 ACPI 命名空间中 ACPI 定义的对象,这些对象报告设备可能占用的硬件资源 [_PRS]、报告设备当前使用的资源的对象 [_CRS] 以及用于配置这些资源的对象 [_SRS]。 即插即用操作系统 (OSPM) 使用该信息来配置设备。

[3] ACPI 6.2, sec 6.2:

 OSPM 使用设备配置对象为通过 ACPI 枚举的设备配置硬件资源。 设备配置对象提供有关当前和可能的资源需求、共享资源之间的关系以及配置硬件资源的方法的信息。

 当 OSPM 枚举设备时,它会调用 _PRS 来确定设备的资源需求。 它还可以调用 _CRS 来查找设备的当前资源设置。 使用此信息,即插即用系统确定设备应消耗哪些资源,并通过调用设备的 _SRS 控制方法来设置这些资源。

 在 ACPI 中,设备可以消耗资源(例如,传统键盘)、提供资源(例如,专有 PCI 桥),或两者兼而有之。 除非另有说明,否则假定设备的资源取自设备层次结构中该设备上方最近的匹配资源。

[4] ACPI 6.2, sec 6.4.3.5.1, 2, 3, 4:

 QWord/DWord/Word 地址空间描述符(.1、.2、.3)

  通用标志:位 [0] 被忽略

 扩展地址空间描述符 (.4)

  通用标志:位 [0] 消费者/生产者:

   1 – 该设备消耗该资源

   0 – 该设备生产并消耗该资源

[5] ACPI 6.2, sec 19.6.43:

 ResourceUsage 指定内存范围是由该设备消耗(ResourceConsumer)还是传递给子设备(ResourceProducer)。 如果未指定任何内容,则假定为 ResourceConsumer。

[6] PCI Firmware 3.2, sec 4.1.2:

 如果操作系统本身不支持保留 MMCFG 区域,则必须由固件保留 MMCFG 区域。 MCFG 表或 _CBA 方法(参见第 4.1.3 节)报告的地址范围必须通过声明主板资源来保留。 对于大多数系统,主板资源将出现在 _HID 为 EISAID (PNP0C02) 的节点中 ACPI 命名空间的根部(在 _SB 下),并且这种情况下的资源不应在根 PCI 总线的 _CRS 中声明。 这些资源可以选择在 Int15 E820 或 EFIGetMemoryMap 中作为保留内存返回,但必须始终通过 ACPI 作为主板资源进行报告。

[7] PCI Express 4.0, sec 7.2.2:

 对于 PC 兼容的系统,或者未实现允许访问配置空间的处理器架构特定固件接口标准的系统,需要 ECAM(如本节中所定义)。

[8] PCI Firmware 3.2, sec 4.1.2:

 MCFG表是ACPI表,用于传送与操作系统在引导时可用的PCI段组内的非热可移除PCI段组范围相对应的基地址。 这是 PC 兼容系统所必需的。

 MCFG 表仅用于传达与系统启动时可用的 PCI 段组相对应的基地址。

[9] PCI Firmware 3.2, sec 4.1.3:

 _CBA(内存映射配置基地址)控制方法是一个可选的 ACPI 对象,它返回支持热插拔的主机桥的 64 位内存映射配置基地址。 _CBA 返回的基地址是处理器相对地址。 _CBA 控制方法计算结果为 Integer.

 该控制方法出现在主机桥对象下。 当 _CBA 方法出现在活动主机桥对象下时,操作系统会评估此结构,以识别与 _CRS 方法中指定的总线编号范围的 PCI 段组相对应的内存映射配置基地址。 包含 _CBA 方法的 ACPI 命名空间对象还必须包含相应的 _SEG 方法。