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 条目。例如,您可能需要考虑添加
一个 CFMWS 条目,以覆盖所有可交错的主机桥。
一个 CFMWS 条目,以覆盖单个主机桥上的所有设备。
一个 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 字段具有特殊的限制位,用于描述所述内存区域是否允许易失性或持久性内存(或两者)。如果平台打算支持
具有多种介质的设备,或
将持久性内存设备用作普通内存
平台可能希望创建多个 CEDT CFMWS 条目来描述相同的内存,目的是允许最终用户灵活地配置该内存。Linux 目前在这方面没有严格的要求。