1. Linux Kernel CXL 驱动
硬件架构看,CXL 设备物理上挂在 PCIe 总线上。CPU 通过 PCIe Root Complex 访问外设,CXL Host Bridge 作为 PCIe 和 CXL 协议的桥接点,位于 Root Complex 和 CXL Switch 之间。Switch 下挂载各类 CXL Device——可能是 Type-3 内存设备,也可能是支持 CXL.cache/CXL.mem 的加速器。Linux 将 CXL 驱动定位为连接多个已有子系统的中间层。PCI subsystem 负责设备发现和基础枚举,ACPI firmware interface 通过 CEDT/CFMWS 表描述 CXL 拓扑和内存资源,Memory subsystem 管理系统内存视图,而 CXL subsystem 则在这些子系统之间协调,将 CXL 硬件能力正确地暴露给内核其他部分。
2. Linux Kernel drivers/cxl 目录框架分析
drivers/cxl/ 目录下的模块划分体现了 CXL 系统复杂性的分层抽象思路。
cxl_core 是整个框架的基石。它定义了 CXL 设备的核心抽象——port、decoder、region、memdev 等数据结构都在这里定义。cxl_core 不绑定任何特定传输层,提供了 CXL 拓扑管理的公共基础设施和总线注册机制。所有其他 CXL 模块都依赖 cxl_core 提供的公共服务。
cxl_pci 是 PCIe 物理层的适配层。它的职责是处理 CXL 设备与 PCI subsystem 的衔接——识别具有 CXL capability 的 PCIe 设备,解析 DVSEC 中的 CXL 特定配置,将 PCI 层的设备信息转换为 CXL 层可以理解的抽象。
cxl_port 管理 CXL 拓扑结构。CXL 协议支持复杂的树形拓扑:Root Port、Switch Upstream Port、Switch Downstream Port、Endpoint Port。cxl_port 模块负责在软件层面重建这棵物理拓扑树,维护 port 之间的父子关系,为后续的地址路由配置提供基础。
cxl_mem 针对 Type-3 内存设备提供专门支持。这类设备没有本地 CPU,完全由主机管理。cxl_mem 实现了内存设备的特定逻辑——HDM decoder 配置、memory region 管理、设备到 Linux memory subsystem 的注册等。
cxl_acpi 桥接固件和内核。ACPI 规范定义了 CEDT(CXL Early Discovery Table)和 CFMWS(CXL Fixed Memory Window Structured)来描述系统中的 CXL 资源。cxl_acpi 解析这些表格,将固件层的描述转换为内核可以使用的设备对象。
3. CXL Kernel 核心对象模型
Linux kernel 通过一组核心数据结构描述 CXL 硬件拓扑。
struct cxl_port 对应 CXL 拓扑中的端口节点。它可以是 Root Port(连接 Host Bridge)、Switch Port(连接交换芯片)、或 Endpoint Port(连接最终设备)。Port 对象维护父子关系,形成内核中的 CXL 设备树。Port 的关键职责是管理挂载其下的 decoder。
struct cxl_decoder 对应地址路由硬件。Decoder 配置决定了哪些 CPU 物理地址被路由到 CXL 总线。Linux 区分 Root Decoder、Switch Decoder、Endpoint Decoder,分别对应拓扑中不同位置的路由单元。Decoder 关联到 Port——每个 Port 下可以挂载多个 Decoder。
struct cxl_memdev 对应实际的 CXL 内存设备。它是内核暴露给用户空间的抽象,代表一个可以被系统使用的 CXL 内存资源。Memdev 对象关联到对应的 Endpoint Port,并通过 decoder 了解自己被映射到的地址范围。
struct cxl_dev_state 是每个 CXL 设备维护的运行时状态。它包含设备的 MMIO 基址、mailbox 句柄、命令接口等运行时信息。Dev_state 将设备抽象(struct device)和 CXL 特定的状态关联起来。
4. CXL 驱动初始化
系统启动时,Linux 初始化各个子系统。ACPI subsystem 解析固件,PCI subsystem 完成总线扫描。当 PCI 总线探测到带有 CXL capability 的设备时,cxl_pci driver 的 probe 函数被调用。
register_cxl_bus() 建立 CXL 虚拟总线,所有 CXL 设备都挂在这条总线上。register_cxl_pci_driver() 将 cxl_pci 注册为 PCI driver,使其能够与 CXL 设备匹配。cxl_acpi_init() 则解析固件表格,建立初始拓扑。
设备匹配后,cxl_pci probe 函数执行。它解析设备 DVSEC,创建对应的 port 对象,配置 decoder,注册 memdev。整个过程中,cxl_port 负责建立拓扑关系,cxl_mem 处理设备特定逻辑,最终在 /sys/bus/cxl/devices/ 下生成可见的设备节点。
这种分层初始化的好处是依赖关系清晰。ACPI 信息在 PCI 扫描前准备好,PCI driver 注册在 CXL bus 注册之后,设备创建在 driver 和 bus 都就绪之后。每一步都建立在前一步的成果之上。