Linux 初始化 (早期启动)

Linux 配置分为两个主要步骤:早期启动和其余部分。

在早期启动期间,Linux 设置不可变的资源(例如 numa 节点),而后续操作包括驱动程序探测和内存热插拔等。 Linux 可能会在此过程中读取 EFI 和 ACPI 信息,以配置设备的逻辑表示。

在 Linux 早期启动阶段(内核中带有 __init 修饰符的函数),系统会获取 EFI/BIOS 创建的资源 (ACPI 表格) 并将其转换为内核可以使用的资源。

BIOS、构建和启动选项

在内核构建期间需要考虑 4 个预启动选项,这些选项决定了 Linux 在早期启动期间如何管理内存。

  • EFI_MEMORY_SP

    • BIOS/EFI 选项,用于指示内存是 SystemRAM 还是特定用途。 特定用途内存将被推迟到驱动程序管理,而不是立即作为系统 RAM 公开。

  • CONFIG_EFI_SOFT_RESERVE

    • Linux 构建配置选项,用于指示内核是否支持特定用途内存。

  • CONFIG_MHP_DEFAULT_ONLINE_TYPE

    • Linux 构建配置,用于指示应如何管理转换为 dax 设备的特定用途内存(保留为 DAX,还是作为 SystemRAM 在 ZONE_NORMAL 或 ZONE_MOVABLE 中联机)。

  • nosoftreserve

    • Linux 内核启动选项,用于指示是否应支持软保留。 类似于 CONFIG_EFI_SOFT_RESERVE。

内存映射创建

当内核解析 EFI 内存映射时,如果支持并检测到 Specific Purpose 内存,它将把此区域设置为 SOFT_RESERVED

如果 EFI_MEMORY_SP=0CONFIG_EFI_SOFT_RESERVE=nnosoftreserve=y - Linux 会将 CXL 设备内存区域默认设置为 SystemRAM。 这会将内存公开给 ZONE_NORMAL 中的内核页面分配器,使其可用于大多数分配(包括 struct page 和页表)。

如果设置并支持了 特定用途,则 CONFIG_MHP_DEFAULT_ONLINE_TYPE_* 指示默认情况下是否联机内存 (_OFFLINE_ONLINE_*),以及如果联机,默认情况下将该内存联机到哪个区域 (_NORMAL_MOVABLE)。

如果放置在 ZONE_MOVABLE 中,则该内存将不可用于大多数内核分配(例如 struct page 或页表)。 这可能会严重影响性能,具体取决于系统的内存容量。

NUMA 节点保留

Linux 引用 SRAT 中定义的邻近域 (PXM) 以在 acpi_numa_init 中创建 NUMA 节点。 通常,PXM 和 NUMA 节点 ID 之间存在 1:1 关系。

SRAT 是 ACPI 定义的定义邻近域的唯一方法。 Linux 选择最多将这些域与 NUMA 节点 1:1 映射。 CEDT 添加了 SPA 范围的描述,Linux 可以将这些范围映射到一个或多个 NUMA 节点。

如果 CFMWS 中存在 CXL 范围,但 SRAT 中不存在,则会创建一个伪 PXM(截至 v6.15)。 将来,由于邻近域关联的模糊性,Linux 可能会拒绝 SRAT 未描述的 CFMWS。

重要的是要注意,NUMA 节点创建不能在运行时完成。 所有可能的 NUMA 节点都在 __init 时识别,更具体地说是 mm_init 期间。 CEDT 和 SRAT 必须包含足够的 PXM 数据,以便 Linux 识别 NUMA 节点及其关联的内存区域。

相关代码存在于: linux/drivers/acpi/numa/srat.c 中。

有关更多信息,请参见 示例平台配置

内存层创建

内存层是按性能特征分组的 NUMA 节点的集合。 在 __init 期间,Linux 使用包含所有标记为 N_MEMORY 的节点的默认内存层初始化系统。

memory_tier_init 在启动时为默认联机的所有内存节点调用。 memory_tier_late_init 在 late-init 期间为驱动程序配置期间设置的节点调用。

只有当节点具有在线内存时,才会标记为 N_MEMORY

层成员资格可以在

/sys/devices/virtual/memory_tiering/memory_tierN/nodelist
0-1

中检查如果分组的节点在性能上有明显的差异,请检查 CXL 节点的 HMAT 和 CDAT 信息。 除非通过 access_coordinates 将 HMAT/CDAT 信息报告给 memory_tier 组件,否则所有节点都默认为 DRAM 层。

有关更多信息,请参见 CXL 访问坐标文档

连续内存分配

连续内存分配器 (CMA) 允许在早期启动期间在 NUMA 节点上保留连续的内存区域。 但是,CMA 无法在早期启动期间未联机的 NUMA 节点上保留内存。

void __init hugetlb_cma_reserve(int order) {
  if (!node_online(nid))
    /* do not allow reservations */
}

这意味着如果用户打算将 CXL 内存的管理推迟到驱动程序,则 CMA 不能用于保证巨页分配。 如果在早期启动期间将 CXL 内存作为 ZONE_NORMAL 中的 SystemRAM 启用,则可以使用 cma_pernumanuma_cma 内核命令行参数进行每个节点的 CMA 预留。