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=0、CONFIG_EFI_SOFT_RESERVE=n 或 nosoftreserve=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_pernuma 或 numa_cma 核心命令列引數進行每個節點的 CMA 預留。