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 預留。