当将 CXL Type3 设备内部存储空间 DPA,并映射到系统物理地址空间形成 HPA 区域,CXL 使用 CXL REGION 为系统屏蔽了 HPA 到 DPA 映射的细节,操作系统可以将 HPA 当做正常的物理区域使用. 为了方便操作系统对 HPA 的使用,操作系统可以将 CXL REGION 切换成不同的模式,以此以不同的形态展现在系统硬件层面,主要包括三种模式: SYSTEM-RAM、DEVDAX 和 FSDAX.

DEVDAX 模式 是 CXL REGION 的一种高性能配置模式,通过将 CXL 内存直接映射为字符设备(如 /dev/daxX.Y),允许应用程序绕过文件系统和页缓存,以极低延迟直接访问内存, 此模式专为需要裸机级内存操作的场景设计,尤其适合持久化内存(Persistent Memory)和高性能计算任务, 其核心特点包括:

  • 直接内存访问: 通过 mmap 系统调用将设备内存映射到用户空间,实现接近本地 DRAM 的访问性能.
  • 持久化支持: 若 CXL 设备支持非易失性内存(如 CXL.mem 协议),数据可在断电后保留
  • 原子操作与内存语义: 支持原子读写和内存持久性原语(如 pmem_persist),确保数据一致性
  • 任意位置访问: 该模式可以访问 CXL REGION 里指定的内存

DEVDAX 模式 是 CXL Region 中性能最优的配置方式,专为需要极致延迟和直接内存访问的场景设计, 常见的应用场景包括:

  • 高性能计算(HPC): 科学仿真(如流体动力学)需频繁读写大规模数据集, 通过 DEVDAX 直接访问 CXL 内存,避免文件系统开销,提升计算吞吐量
  • 持久内存数据库: MongoDB、Redis 等数据库需低延迟持久化存储, 将数据库日志或热数据存储在 DEVDAX 内存中,通过 libpmem 确保崩溃一致性
  • 加速器直接内存访问: GPU 或 FPGA 需高速访问共享内存,减少 CPU 干预, 映射 DEVDAX 内存到 GPU/FPGA 地址空间,实现零拷贝数据传输

CXL Type3 设备可以是 PMEM,也可以是 SRAM, 当 CXL Type3 设备的 CXL REGION 创建完毕之后,可以借助 cxl-ctrl、ndctl 和 daxctl 工具设置 CXL REGION 的模式为 DEVDAX, 接下来边实践边进行讲解, 实践案例在 BiscuitOS 上的部署逻辑如下:

# 切换到 BiscuitOS 项目目录
cd BiscuitOS
# 通过 Kbuild 选择需要部署的应用程序
make menuconfig

  [*] DIY BiscuitOS/Broiler Hardware  --->
      <*> Intel Q35
      [*] CXL: Compute Express Link
            CXL Hardware Topology (CXL2.0: x1 VCS + x1 Type DDR)  --->
  [*] package --->
      [*] HETEROGENEOUS MEMORY MANAGEMENT  --->
          [*] CXL REGION: DEVDAX MODE  --->


# 配置完毕保存,然后进行部署
make
# 安装必备工具
cd BiscuitOS/output/linux-6.10-x86_64/package/BiscuitOS-CXL-REGION-DEVDAX-default
# 第一次执行如下命令
make prepare
make download
make tar
make configure
# 运行 BiscuitOS
make build

当 BiscuitOS 运行之后,直接运行 RunBiscuitOS.sh, 该脚本包含了实践所需的全部命令, 在运行实践案例之前,查看 /dev/ 目录下并未存在 daxX.Y 字符设备. 接着运行脚本,可以看到脚本创建了一个 CXL REGION,并将 CXL REGION 的模式设置为 DEVDAX 模式,接着可以看到实践案例从 CXL REGION 的内存里读到数据,最后确认新增 /dev/dax0.0 字符设备. 接下来查看一下实践案例源码:

实践案例由一个应用程序构成,其在 25 行调用 open 函数打开了 “/dev/dax0.0” 字符设备,然后在 30 行调用 mmap 函数分配一段虚拟内存映射到 CXL 内存上,接着在 39-40 行对 CXL 内存进行读写操作,最后在 43-44 行回收资源. 对 CXL REGION DEVDAX 模式的使用需要进行定制修改,接下来看一下 CXL REGION DEVDAX 创建过程:

# 清空所有的 CXL REGION
cxl destroy-region -f all
# 创建一个新的 CXL REGION
#   大小为 512M, 交织粒度为 4096, 来自一个 CXL Type3 设备 mem0
cxl create-region -d decoder0.0 -m mem0 -s 512M -t ram -w 1 -g 4096 -u
# 使能 CXL REGION
cxl enable-region region0

# 将 CXL REGION 设置为 DEVDAX 模式
daxctl reconfigure-device --mode=devdax dax0.0 --force

当 CXL REGION 的模式设置为 DEVDAX 模式之后,系统会为 CXL REGION 创建一个 DAX 字符设备,该字符设备可以跨过 PAGE CACHE,直接访问 CXL MEMORY,也就是 DAX 机制. DEVDAX 的好处是多个使用者可以同时通过 DAX 字符设备访问 CXL MEMORY 的指定位置,这在 CXL POOLING 里很有用,另外使用者可以根据需求访问 CXL MEMORY 的指定位置, 以上的特点提升了裸 CXL MEMORY 的访问效率. 那么接下来实践案例介绍内核线程或内核态如何使用 DEVDAX 模式下的 CXL REGION, 实践案例在 BiscuitOS 上的部署逻辑如下:

# 切换到 BiscuitOS 项目目录
cd BiscuitOS
# 通过 Kbuild 选择需要部署的应用程序
make menuconfig

  [*] DIY BiscuitOS/Broiler Hardware  --->
      <*> Intel Q35
      [*] CXL: Compute Express Link
            CXL Hardware Topology (CXL2.0: x1 VCS + x1 Type DDR)  --->
  [*] package --->
      [*] HETEROGENEOUS MEMORY MANAGEMENT  --->
          [*] CXL DEVDAX: ACCESS ON KERNEL  --->


# 配置完毕保存,然后进行部署
make
# 安装必备工具
cd BiscuitOS/output/linux-6.10-x86_64/package/BiscuitOS-CXL-SYSRAM-KERNEL-default
# 第一次执行如下命令
make prepare
make download
make tar
make configure
# 运行 BiscuitOS
make build

当 BiscuitOS 运行之后,直接运行 RunBiscuitOS.sh, 该脚本包含了实践所需的全部命令, 在运行实践案例之前,使用 free 和 numactl 命令查看当前内存信息,接着运行脚本,可以看到脚本创建了一个 CXL REGION,并将 CXL REGION 的模式设置为 SYSTEM-RAM 模式,接着可以看到实践案例从 CXL REGION 的内存里读到数据,并打印了物理页所在的 ZONE 信息. 最后通过 free 和 numactl 命令可以看到系统物理内存数量增加,并且新增加了一个 NUMA NODE. 接下来查看一下实践案例源码:

实践案例由一个内核模块构成,其在 24 行调用 filp_open 函数打开 “/dev/dax0.0” 文件,然后在 31 行从打开文件的 private_data 获得 struct dev_dax 数据结构,然后在 34 行从 dev_dax 里获得对应的 dev_pagemap, 里面包含了 ZONE_DEVICE 里的 struct page,接着在 39 行通过 __va 函数获得物理地址对应的线性映射区虚拟地址,然后在 42-43 行对这段内存进行读写操作,最后在 46 行调用 filp_close 函数关闭文件. 以上便是内核线程或者内核态使用 CXL REGION DEVDAX 的案例. 接下来分析用户进程如何使用 CXL REGION DEVDAX 模式,实践案例在 BiscuitOS 上的部署逻辑如下:

# 切换到 BiscuitOS 项目目录
cd BiscuitOS
# 通过 Kbuild 选择需要部署的应用程序
make menuconfig

  [*] DIY BiscuitOS/Broiler Hardware  --->
      <*> Intel Q35
      [*] CXL: Compute Express Link
            CXL Hardware Topology (CXL2.0: x1 VCS + x1 Type DDR)  --->
  [*] package --->
      [*] HETEROGENEOUS MEMORY MANAGEMENT  --->
          [*] CXL DEVAX: ACCESS ON USERSPACE  --->


# 配置完毕保存,然后进行部署
make
# 安装必备工具
cd BiscuitOS/output/linux-6.10-x86_64/package/BiscuitOS-CXL-DEVDAX-USERSPACE-default
# 第一次执行如下命令
make prepare
make download
make tar
make configure
# 运行 BiscuitOS
make build

当 BiscuitOS 运行之后,直接运行 RunBiscuitOS.sh, 该脚本包含了实践所需的全部命令, 在运行实践案例之前,使用 free 和 numactl 命令查看 当前内存信息,接着运行脚本,可以看到脚本创建了一个 CXL REGION,并将 CXL REGION 的模式设置为 SYSTEM-RAM 模式,接着可以看到实践案例>从 CXL REGION 的内存里读到数据,最后通过 free 和 numactl 命令可以看到系统物理内存数量增加,并且新增加了一个 NUMA NODE. 接下来查看>一下实践案例源码:

实践案例由一个应用程序构成,其在 25 行调用 open 函数打开了 “/dev/dax0.0” 字符设备,然后在 30 行调用 mmap 函数分配一段虚拟内存映射到 CXL 内存上,接着在 39-40 行对 CXL 内存进行读写操作,最后在 43-44 行回收资源. 对 CXL REGION DEVDAX 模式的使用需要进行定制修改,接下来看一下 CXL REGION DEVDAX 创建过程:

图片无法显示,请右键点击新窗口打开图片