Linux CXL 驱动中的 DSDT 表解析:CXL 主机桥 UID 一致性机制与 ACPI0016 设备定义
2026/9/17 6:32:23 网站建设 项目流程

Linux CXL 驱动中的 DSDT 表解析:CXL 主机桥 UID 一致性机制与 ACPI0016 设备定义

【免费下载链接】linuxLinux kernel source tree项目地址: https://gitcode.com/GitHub_Trending/li/linux

导读

本文基于 Linux 内核 CXL 子系统文档 Documentation/driver-api/cxl/platform/acpi/dsdt.rst,深入讲解 ACPI DSDT(Differentiated System Description Table)在 CXL(Compute Express Link)平台发现流程中的作用:DSDT 以ACPI0016硬件 ID 声明 CXL 主机桥,并通过_UID唯一标识每台主机桥。文章将结合内核源码drivers/cxl/acpi.c与测试代码,说明 DSDT 中的主机桥 UID 必须与 CEDT(CXL Early Discovery Table)保持一致的底层原因、驱动如何校验这一约束,以及平台固件开发者如何正确编写与排查相关 ACPI 表。读完本文,你将掌握 DSDT 中 CXL 主机桥设备的 ASL 编写规范、UID 一致性校验的完整调用链,以及常见的固件配置故障定位方法。

DSDT 在 CXL 平台发现中的角色

ACPI(Advanced Configuration and Power Interface)是定义平台与操作系统之间电源管理与硬件配置协作方式的标准。对 Linux CXL 驱动而言,所谓"ACPI"通常特指 ACPI 表——即平台固件(BIOS/EFI)向操作系统传递静态配置信息的载体。如 Documentation/driver-api/cxl/platform/acpi.rst 所述,CXL 相关的静态配置与性能数据分布于多张 ACPI 表:

  • DSDT:描述机器具备哪些外设(本文核心);
  • CEDT:CXL Early Discovery Table,描述 BIOS 在启动时配置好的 CXL 内存区域与主机桥;
  • SRAT / HMAT / SLIT:分别描述 NUMA 亲和性、内存性能属性与节点间距离。

DSDT 本身是 ACPI 体系中一张通用的"差异化系统描述表",其作用是描述机器上存在的外设。CXL 驱动关注的要点只有一个:DSDT 中 CXL 主机桥(CXL Host Bridge)的 UID 必须与 CEDT 中的内容保持一致,否则 CXL 驱动将无法正确探测(probe)设备。

CXL 主机桥在 DSDT 中的标准定义

原文档给出了一个完整的 CXL 主机桥 ASL 示例(Scope (_SB)下的S0D0设备)。下面逐字段解读:

Scope (_SB) { Device (S0D0) { Name (_HID, "ACPI0016" /* Compute Express Link Host Bridge */) // _HID: Hardware ID Name (_CID, Package (0x02) // _CID: Compatible ID { EisaId ("PNP0A08") /* PCI Express Bus */, EisaId ("PNP0A03") /* PCI Bus */ }) ... Name (_UID, 0x05) // _UID: Unique ID ... } }

各字段的作用:

ASL 字段取值含义
_HID"ACPI0016"硬件 ID,标识这是一个 CXL 主机桥设备(Compute Express Link Host Bridge)
_CIDPNP0A08/PNP0A03兼容 ID,声明该设备同时兼容 PCI Express 总线与 PCI 总线,从而纳入既有的 PCI 根桥枚举体系
_UID0x05唯一 ID,用于在系统中唯一标识该主机桥,必须与 CEDT 中对应主机桥的 UID 一致

从源码结构看,ACPI0016是驱动识别 CXL 主机桥的唯一依据:在 drivers/cxl/acpi.c 的to_cxl_host_bridge()中,驱动通过acpi_device_hid(adev)获取设备的_HID,并严格比较字符串是否为"ACPI0016",同时要求该设备能够通过acpi_pci_find_root()找到对应的 PCI 根。只有同时满足这两个条件的 ACPI 设备才会被认定为 CXL 主机桥:

if (strcmp(acpi_device_hid(adev), "ACPI0016") == 0) return adev;

_CID中声明的PNP0A08(PCI Express Bus)与PNP0A03(PCI Bus)使主机桥在操作系统眼中同时是一个标准 PCI 根桥,这是 CXL 主机桥天然作为 PCIe 层次结构根节点的体现。而_UID则承担着跨表关联的重任,详见下文。

为什么 UID 一致性如此关键:跨表关联的探针链路

DSDT 中的_UID并非孤立存在,它是把三张 ACPI 表"缝"在一起的纽带。参考 Documentation/driver-api/cxl/platform/acpi/cedt.rst 与 Documentation/driver-api/cxl/linux/cxl-driver.rst,CXL 平台发现的完整数据流如下:

  1. CEDT CHBS(CXL Host Bridge Structure):描述每个 CXL 主机桥的组件寄存器信息,并报告该主机桥的 UID(如示例中的Associated host bridge : 00000007);
  2. CEDT CFMWS(CXL Fixed Memory Window Structure):描述与一个或多个主机桥关联的内存窗口,其First Target/Next Target字段以主机桥 UID 引用目标(如示例中的0000000700000006);
  3. DSDT_UID:在 ACPI 设备对象层面为主机桥提供最终的身份。

驱动在 cxl_acpi_probe() 中的探针顺序决定了这种一致性的必要性:

  • 先通过bus_for_each_dev()遍历 ACPI 总线上的设备,用to_cxl_host_bridge()筛选出ACPI0016设备;
  • 对每个主机桥调用cxl_get_chbs()(drivers/cxl/acpi.c):该函数通过acpi_evaluate_integer(hb->handle, METHOD_NAME__UID, ...)读出 DSDT 中的_UID值,再调用acpi_table_parse_cedt(ACPI_CEDT_TYPE_CHBS, ...)遍历 CEDT 中所有 CHBS 条目,用ctx->uid != chbs->uid逐一比对,只有 UID 匹配的 CHBS 才会被采纳,从而得到该主机桥的寄存器基址(CHBCR)与 CXL 版本;
  • 随后解析 CFMWS 构建根解码器(Root Decoder),其target_list由 CFMWS 的目标 UID 列表填充,最终这些目标需要落到具体的主机桥 dport 上。

也就是说,从 CFMWS 目标 UID → CHBS UID → DSDT_UID整条链路靠 UID 这一个整数串起来。任一处不一致(例如 DSDT 写0x05而 CHBS 写7),驱动就无法把 CFMWS 内存窗口映射到正确的主机桥,最终表现为 CXL 内存设备探测失败。正因如此,原文档将"DSDT UID 与 CEDT 一致"列为硬性约束,并明确指出否则"CXL 驱动将无法正确探测"。

UID 一致性在测试代码中的印证

仓库的 CXL 测试基础设施直接验证了"UID 必须跨表一致"这一设计。在 tools/testing/cxl/test/cxl.c 中,模拟的 CEDT 表为 4 台主机桥各配置了一个 CHBS 条目,UID 依次为 0、1、2、3,且版本分别标记为ACPI_CEDT_CHBS_VERSION_CXL20(VH 模式)与ACPI_CEDT_CHBS_VERSION_CXL11(RCH 模式):

.chbs[0] = { .header = { .type = ACPI_CEDT_TYPE_CHBS, .length = sizeof(mock_cedt.chbs[0]), }, .uid = 0, .cxl_version = ACPI_CEDT_CHBS_VERSION_CXL20, },

而 tools/testing/cxl/mock_acpi.c 中模拟的to_cxl_host_bridge()与真实实现保持同一判定逻辑(ACPI0016+acpi_pci_find_root()),确保模拟环境下的主机桥识别路径与真实平台一致。测试驱动的探针流程会以这些 CHBS 的 UID 为准去匹配主机桥,任何 UID 偏差都会在测试中暴露出来。这从侧面说明:UID 一致性是驱动正常运行的前置条件,而不是可选项

固件侧常见错误与排查方法

若 DSDT 的 UID 与其他表不匹配,症状往往极具迷惑性——用户看到的是"CXL 驱动不支持内存设备",而实际根源是平台固件配置错误。参考 Documentation/driver-api/cxl/platform/acpi.rst 的 "Common Issues" 清单,与 DSDT 直接相关的典型故障包括:

  • CEDT CFMWS 目标 UID 与 DSDT 主机桥 UID 不匹配
  • CEDT CHBS UID 与 DSDT 主机桥 UID 不匹配

两者都会导致驱动无法把 CFMWS 描述的内存窗口与 DSDT 中的主机桥设备对上号,从而无法将 CXL 内存以 DAX 设备或kmem形式呈现给用户空间。其余常见问题(如 CFMWS 限制位错误、内存区域未 256MB 对齐、SRAT/HMAT 缺失对应区域等)也大多表现为"驱动探测失败",需要从 ACPI 表源头排查。

内核文档推荐的排查手段是 ACPI 表转储与反汇编:

acpidump -b && iasl -d cedt.dat
  • acpidump -b:将系统当前 ACPI 表以二进制形式导出(包括dsdt.datcedt.dat等);
  • iasl -d:将二进制表反汇编为可读的 ASL/AML 文本。

之后对照检查:dsdt中每个ACPI0016设备的_UID是否与cedt中 CHBS 的 UID 完全一致,且 CFMWS 的目标列表是否都落在这些 UID 集合内。

总结

DSDT 对 Linux CXL 驱动而言是一张"身份表":它以ACPI0016声明 CXL 主机桥设备,以_CIDPNP0A08/PNP0A03)保持 PCI 兼容性,并通过_UID与 CEDT 的 CHBS、CFMWS 建立一一对应的关联。驱动在cxl_acpi_probe()中正是依赖这条 UID 链完成主机桥识别、寄存器定位与内存窗口绑定。因此,平台固件开发者在编写或修改 DSDT 时,务必保证_UID与 CEDT 中 CHBS/CFMWS 的 UID 严格一致;排查 CXL 内存无法识别的问题时,也应首先用acpidump -b+iasl -d检查这几张表的 UID 是否对齐。相关配套文档可继续阅读 CEDT 详解、SRAT 亲和性说明 以及 CXL 驱动总览。

【免费下载链接】linuxLinux kernel source tree项目地址: https://gitcode.com/GitHub_Trending/li/linux

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询