内存热插拔

将 CXL 内存呈现给内核页面分配器的最后阶段是让 DAX 驱动程序通过内存热插拔组件呈现 驱动程序管理 内存区域。

需要考虑四个主要配置

  1. 默认在线行为(开/关和区域)

  2. 热插拔内存块大小

  3. 内存映射资源位置

  4. 驱动程序管理的内存指定

默认在线行为

热插拔内存的默认在线行为由以下因素决定,按优先级排序

  • CONFIG_MHP_DEFAULT_ONLINE_TYPE 构建配置

  • memhp_default_state 启动参数

  • /sys/devices/system/memory/auto_online_blocks

这些决定了热插拔内存块到达以下三种状态之一

  1. 离线

  2. 在线,位于 ZONE_NORMAL

  3. 在线,位于 ZONE_MOVABLE

ZONE_NORMAL 表示此容量可用于几乎任何分配,而 ZONE_MOVABLE 表示此容量仅应用于可迁移的分配。

ZONE_MOVABLE 尝试保留内存块的热插拔能力,以便稍后可以热拔出整个区域。 任何上线到 ZONE_NORMAL 的容量都应被视为永久附加到页面分配器。

热插拔内存块大小

默认情况下,在大多数架构上,热插拔内存块大小为 128MB 或 256MB。 在 x86 上,随着总内存容量超过 64GB,块大小会增加到 2GB。 从 v6.15 开始,Linux 在确定热插拔内存块大小时,不会考虑 ACPI CEDT CFMWS 区域的大小和对齐方式(请参阅早期启动文档)。

内存映射

用于表示热插拔内存容量的 struct folio 分配的位置由以下系统设置决定

  • /sys_module/memory_hotplug/parameters/memmap_on_memory

  • /sys/bus/dax/devices/daxN.Y/memmap_on_memory

如果这两个参数都设置为 true,则此容量的 struct folio 将从正在上线的内存块中划分出来。 如果内存的延迟特别高且其 struct folio 变得竞争激烈,则这会产生性能影响。

如果任一参数设置为 false,则此容量的 struct folio 将从运行热插拔过程的处理器的本地节点分配。 此容量将从该节点上的 ZONE_NORMAL 分配,因为它是一个 GFP_KERNEL 分配。

具有极大量 ZONE_MOVABLE 内存(例如 CXL 内存池)的系统必须确保有足够的本地 ZONE_NORMAL 容量来托管热插拔容量的内存映射。

驱动程序管理的内存

DAX 驱动程序将此内存作为“驱动程序管理”呈现给内存热插拔。 这不是一个可配置的设置,但需要注意的是,驱动程序管理的内存被明确排除在 kexec 期间使用。 这是必需的,以确保 CXL 设备在功能系统重启期间可能受到的任何重置或带外操作(例如 probe 时重置)不会导致 kexec 内核的部分被覆盖。