BIOS/EFI 配置

BIOS 和 EFI 主要負責配置裝置的靜態資訊(或潛在的未來裝置),以便 Linux 可以構建這些裝置的適當邏輯表示。

從高層次來看,這是配置階段發生的事情。

  • 引導載入程式啟動 BIOS/EFI。

  • BIOS/EFI 執行早期裝置探測以確定靜態配置

  • BIOS/EFI 建立 ACPI 表,描述作業系統的靜態配置

  • BIOS/EFI 建立系統記憶體對映(EFI 記憶體對映、E820 等)

  • BIOS/EFI 呼叫 start_kernel 並開始 Linux 早期引導過程。

本節主要關注 ACPI 表的生成和靜態記憶體對映配置。有關這些表的更多詳細資訊,請參見 ACPI 表

注意

平臺供應商應仔細閱讀,因為本節包含有關物理記憶體區域大小和對齊方式、記憶體空洞、HDM 交錯以及 Linux 對試圖使用這些功能的 HDM 解碼器的期望的建議。

UEFI 設定

如果您的平臺支援,可以使用 uefisettings 命令來讀取/寫入 EFI 設定。更改將在下次重新啟動時生效。Kexec 不是一個充分的重新啟動。

這裡一個值得注意的配置是 EFI_MEMORY_SP(特定目的)位。啟用此位時,它告訴 Linux 將記憶體區域的管理推遲給驅動程式(在本例中,為 CXL 驅動程式)。否則,該記憶體將被視為“正常記憶體”,並在 __init 期間暴露給頁面分配器。

uefisettings 示例

uefisettings identify

uefisettings identify

bios_vendor: xxx
bios_version: xxx
bios_release: xxx
bios_date: xxx
product_name: xxx
product_family: xxx
product_version: xxx

在某些 AMD 平臺上,EFI_MEMORY_SP 位透過 CXL Memory Attribute 欄位設定。這在您的平臺上可能有不同的名稱。

uefisettings get "CXL Memory Attribute"

selector: xxx
...
question: Question {
    name: "CXL Memory Attribute",
    answer: "Enabled",
    ...
}

物理記憶體對映

物理地址區域對齊

從 Linux v6.14 開始,熱插拔記憶體系統要求記憶體區域的大小和對齊方式一致。雖然 CXL 規範允許小至 256MB 的記憶體區域,但熱插拔記憶體的受支援記憶體塊大小和對齊方式由架構定義。

Linux 記憶體塊可能小至 128MB,並以 2 的冪增加。

  • 在 ARM 上,預設塊大小和對齊方式為 128MB 或 256MB。

  • 在 x86 上,預設塊大小為 256MB,並且隨著系統容量增加到 64GB,增加到 2GB。

為了獲得跨版本的最佳支援,平臺供應商應將 CXL 記憶體放置在 2GB 對齊的基址上,並且區域應為 2GB 對齊。這也有助於防止建立數千個記憶體裝置(每個塊一個)。

記憶體空洞

記憶體對映中的空洞很棘手。考慮一個位於基址 0x100000000 的 4GB 裝置,但具有以下記憶體對映

---------------------
|    0x100000000    |
|        CXL        |
|    0x1BFFFFFFF    |
---------------------
|    0x1C0000000    |
|    MEMORY HOLE    |
|    0x1FFFFFFFF    |
---------------------
|    0x200000000    |
|     CXL CONT.     |
|    0x23FFFFFFF    |
---------------------

有兩個問題需要考慮

  • 解碼器程式設計,以及

  • 記憶體塊對齊。

如果您的架構需要 2GB 統一大小和對齊的記憶體塊,則 Linux 能夠對映的唯一容量(從 v6.14 開始)將是來自 0x100000000-0x180000000 的容量。剩餘容量將被滯留,因為它們不是 2GB 對齊的長度。

假設您的架構和記憶體配置允許 1GB 記憶體塊,則支援此記憶體對映,並且應在 CEDT 中將其表示為多個 CFMWS,分別描述記憶體空洞的每一側 - 以及匹配的解碼器。

可以使用(並且應該使用)多個解碼器來管理這樣的記憶體空洞(見下文),但是記憶體空洞的每個塊都應該對齊到合理的大小(更大的對齊方式總是更好)。如果您打算在記憶體對映中存在記憶體空洞,則預期每個連續的主機物理記憶體塊使用一個解碼器。

從 v6.14 開始,Linux 確實為由單個 HDM 解碼器描述的、被記憶體空洞分隔的多個物理記憶體區域的記憶體熱插拔提供支援。

解碼器程式設計

如果 BIOS/EFI 打算對解碼器進行程式設計以進行靜態配置,則需要考慮一些事項,以避免妨礙 Linux 相容性的重大缺陷。其中一些建議不是“按照規範”要求的,但 Linux 不保證以其他方式提供支援。

轉換點

根據規範,唯一 **轉換** 主機物理地址 (HPA) 到裝置物理地址 (DPA) 的解碼器是 **端點解碼器**。結構中的所有其他解碼器都旨在路由訪問,而不轉換地址。

該規範強烈暗示了這一點,請參見

CXL Specification 3.1
8.2.4.20: CXL HDM Decoder Capability Structure
- Implementation Note: CXL Host Bridge and Upstream Switch Port Decoder Flow
- Implementation Note: Device Decoder Logic

鑑於此,Linux 強烈假設 CPU 和端點之間的解碼器都將使用其父解碼器的地址範圍的子集進行程式設計。

由於架構、ACPI、PCI 和 CXL 規範如何在域之間“移交”責任方面存在一些模糊性,因此一些早期採用平臺嘗試在原始記憶體控制器或主機橋上進行轉換。此配置需要平臺特定的驅動程式擴充套件,並且儘管受到支援,但並未獲得正式認可。

強烈建議 **不要** 這樣做;否則,您將需要自己為您的平臺實現驅動程式支援。

交錯和配置靈活性

如果提供跨主機橋交錯,則必須在 CEDT 中提供 CFMWS 條目,併為交錯裝置集提供目標主機橋(每個主機橋後面可能存在多個)。

如果提供主機橋內交錯,則如果它覆蓋主機橋後面的裝置的整個容量,則只需要在該主機橋的 CEDT 中提供 1 個 CFMWS 條目。

如果打算為使用者提供在根之外程式設計解碼器的靈活性,您可能希望在 CEDT 中提供多個用於不同目的的 CFMWS 條目。例如,您可能需要考慮新增

  1. 一個 CFMWS 條目,以覆蓋所有可交錯的主機橋。

  2. 一個 CFMWS 條目,以覆蓋單個主機橋上的所有裝置。

  3. 一個 CFMWS 條目,以覆蓋每個裝置。

平臺可以選擇新增所有這些,或者根據 BIOS 設定更改模式。對於每個 CFMWS 條目,Linux 期望在 SRAT 中描述所述記憶體區域,以確定它在早期引導/初始化期間應保留的 NUMA 節點數。

從 v6.14 開始,Linux 將為每個 CEDT CFMWS 條目建立一個 NUMA 節點,即使不存在匹配的 SRAT 條目也是如此;但是,這在未來無法保證,應避免這種配置。

記憶體空洞

如果您的平臺在 CXL 記憶體之間包含記憶體空洞,建議使用多個解碼器來覆蓋這些記憶體區域,而不是嘗試對解碼器進行程式設計以接受整個範圍並期望 Linux 管理重疊。

例如,考慮上面描述的記憶體空洞

---------------------
|    0x100000000    |
|        CXL        |
|    0x1BFFFFFFF    |
---------------------
|    0x1C0000000    |
|    MEMORY HOLE    |
|    0x1FFFFFFFF    |
---------------------
|    0x200000000    |
|     CXL CONT.     |
|    0x23FFFFFFF    |
---------------------

假設這是由直接連線到主機橋的單個裝置提供的,則 Linux 期望以下解碼器程式設計

-----------------------   -----------------------
| root-decoder-0      |   | root-decoder-1      |
|   base: 0x100000000 |   |   base: 0x200000000 |
|   size:  0xC0000000 |   |   size:  0x40000000 |
-----------------------   -----------------------
           |                         |
-----------------------   -----------------------
| HB-decoder-0        |   | HB-decoder-1        |
|   base: 0x100000000 |   |   base: 0x200000000 |
|   size:  0xC0000000 |   |   size:  0x40000000 |
-----------------------   -----------------------
           |                         |
-----------------------   -----------------------
| ep-decoder-0        |   | ep-decoder-1        |
|   base: 0x100000000 |   |   base: 0x200000000 |
|   size:  0xC0000000 |   |   size:  0x40000000 |
-----------------------   -----------------------

使用 CEDT 配置,其中兩個 CFMWS 描述了上述根解碼器。

Linux 不保證對奇怪的記憶體空洞情況提供支援。

多媒體裝置

CEDT 的 CFMWS 欄位具有特殊的限制位,用於描述所述記憶體區域是否允許易失性或永續性記憶體(或兩者)。如果平臺打算支援

  1. 具有多種介質的裝置,或

  2. 將永續性記憶體裝置用作普通記憶體

平臺可能希望建立多個 CEDT CFMWS 條目來描述相同的記憶體,目的是允許終端使用者靈活地配置該記憶體。Linux 目前在這方面沒有嚴格的要求。