요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
.. SPDX-License-Identifier: GPL-2.0
======================
BIOS/EFI Configuration
======================
BIOS and EFI are largely responsible for configuring static information about
devices (or potential future devices) such that Linux can build the appropriate
logical representations of these devices.
At a high level, this is what occurs during this phase of configuration.
* The bootloader starts the BIOS/EFI.
* BIOS/EFI do early device probe to determine static configuration
* BIOS/EFI creates ACPI Tables that describe static config for the OS
* BIOS/EFI create the system memory map (EFI Memory Map, E820, etc)
* BIOS/EFI calls :code:`start_kernel` and begins the Linux Early Boot process.
Much of what this section is concerned with is ACPI Table production and
static memory map configuration. More detail on these tables can be found
at :doc:`ACPI Tables <acpi>`.
.. note::
Platform Vendors should read carefully, as this sections has recommendations
on physical memory region size and alignment, memory holes, HDM interleave,
and what linux expects of HDM decoders trying to work with these features.
UEFI Settings
=============
If your platform supports it, the :code:`uefisettings` command can be used to
read/write EFI settings. Changes will be reflected on the next reboot. Kexec
is not a sufficient reboot.
One notable configuration here is the EFI_MEMORY_SP (Specific Purpose) bit.
When this is enabled, this bit tells linux to defer management of a memory
region to a driver (in this case, the CXL driver). Otherwise, the memory is
treated as "normal memory", and is exposed to the page allocator during
:code:`__init`.
uefisettings examples
---------------------
:code:`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
On some AMD platforms, the :code:`EFI_MEMORY_SP` bit is set via the :code:`CXL
Memory Attribute` field. This may be called something else on your platform.
:code:`uefisettings get "CXL Memory Attribute"` ::
selector: xxx
...
question: Question {
name: "CXL Memory Attribute",
answer: "Enabled",
...
}
Physical Memory Map
===================
Physical Address Region Alignment
---------------------------------
As of Linux v6.14, the hotplug memory system requires memory regions to be
uniform in size and alignment. While the CXL specification allows for memory
regions as small as 256MB, the supported memory block size and alignment for
hotplugged memory is architecture-defined.
A Linux memory blocks may be as small as 128MB and increase in powers of two.
* On ARM, the default block size and alignment is either 128MB or 256MB.
* On x86, the default block size is 256MB, and increases to 2GB as the
capacity of the system increases up to 64GB.
For best support across versions, platform vendors should place CXL memory at
a 2GB aligned base address, and regions should be 2GB aligned. This also helps
prevent the creating thousands of memory devices (one per block).
Memory Holes
------------
Holes in the memory map are tricky. Consider a 4GB device located at base
address 0x100000000, but with the following memory map ::
---------------------
| 0x100000000 |
| CXL |
| 0x1BFFFFFFF |
---------------------
| 0x1C0000000 |
| MEMORY HOLE |
| 0x1FFFFFFFF |
---------------------
| 0x200000000 |
| CXL CONT. |
| 0x23FFFFFFF |
---------------------
There are two issues to consider:
* decoder programming, and
* memory block alignment.
If your architecture requires 2GB uniform size and aligned memory blocks, the
only capacity Linux is capable of mapping (as of v6.14) would be the capacity
from `0x100000000-0x180000000`. The remaining capacity will be stranded, as
they are not of 2GB aligned length.
Assuming your architecture and memory configuration allows 1GB memory blocks,
this memory map is supported and this should be presented as multiple CFMWS
in the CEDT that describe each side of the memory hole separately - along with
matching decoders.
Multiple decoders can (and should) be used to manage such a memory hole (see
below), but each chunk of a memory hole should be aligned to a reasonable block
size (larger alignment is always better). If you intend to have memory holes
in the memory map, expect to use one decoder per contiguous chunk of host
physical memory.
As of v6.14, Linux does provide support for memory hotplug of multiple
physical memory regions separated by a memory hole described by a single
HDM decoder.
Decoder Programming
===================
If BIOS/EFI intends to program the decoders to be statically configured,
there are a few things to consider to avoid major pitfalls that will
prevent Linux compatibility. Some of these recommendations are not
required "per the specification", but Linux makes no guarantees of support
otherwise.
Translation Point
-----------------
Per the specification, the only decoders which **TRANSLATE** Host Physical
Address (HPA) to Device Physical Address (DPA) are the **Endpoint Decoders**.
All other decoders in the fabric are intended to route accesses without
translating the addresses.
This is heavily implied by the specification, see: ::
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
Given this, Linux makes a strong assumption that decoders between CPU and
endpoint will all be programmed with addresses ranges that are subsets of
their parent decoder.
Due to some ambiguity in how Architecture, ACPI, PCI, and CXL specifications
"hand off" responsibility between domains, some early adopting platforms
attempted to do translation at the originating memory controller or host
bridge. This configuration requires a platform specific extension to the
driver and is not officially endorsed - despite being supported.
It is *highly recommended* **NOT** to do this; otherwise, you are on your own
to implement driver support for your platform.
Interleave and Configuration Flexibility
----------------------------------------
If providing cross-host-bridge interleave, a CFMWS entry in the :doc:`CEDT
<acpi/cedt>` must be presented with target host-bridges for the interleaved
device sets (there may be multiple behind each host bridge).
If providing intra-host-bridge interleaving, only 1 CFMWS entry in the CEDT is
required for that host bridge - if it covers the entire capacity of the devices
behind the host bridge.
If intending to provide users flexibility in programming decoders beyond the
root, you may want to provide multiple CFMWS entries in the CEDT intended for
different purposes. For example, you may want to consider adding:
1) A CFMWS entry to cover all interleavable host bridges.
2) A CFMWS entry to cover all devices on a single host bridge.
3) A CFMWS entry to cover each device.
A platform may choose to add all of these, or change the mode based on a BIOS
setting. For each CFMWS entry, Linux expects descriptions of the described
memory regions in the :doc:`SRAT <acpi/srat>` to determine the number of
NUMA nodes it should reserve during early boot / init.
As of v6.14, Linux will create a NUMA node for each CEDT CFMWS entry, even if
a matching SRAT entry does not exist; however, this is not guaranteed in the
future and such a configuration should be avoided.
Memory Holes
------------
If your platform includes memory holes interspersed between your CXL memory, it
is recommended to utilize multiple decoders to cover these regions of memory,
rather than try to program the decoders to accept the entire range and expect
Linux to manage the overlap.
For example, consider the Memory Hole described above ::
---------------------
| 0x100000000 |
| CXL |
| 0x1BFFFFFFF |
---------------------
| 0x1C0000000 |
| MEMORY HOLE |
| 0x1FFFFFFFF |
---------------------
| 0x200000000 |
| CXL CONT. |
| 0x23FFFFFFF |
---------------------
Assuming this is provided by a single device attached directly to a host bridge,
Linux would expect the following decoder programming ::
----------------------- -----------------------
| 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 |
----------------------- -----------------------
With a CEDT configuration with two CFMWS describing the above root decoders.
Linux makes no guarantee of support for strange memory hole situations.
Multi-Media Devices
-------------------
The CFMWS field of the CEDT has special restriction bits which describe whether
the described memory region allows volatile or persistent memory (or both). If
the platform intends to support either:
1) A device with multiple medias, or
2) Using a persistent memory device as normal memory
A platform may wish to create multiple CEDT CFMWS entries to describe the same
memory, with the intent of allowing the end user flexibility in how that memory
is configured. Linux does not presently have strong requirements in this area.
3. 한국어 전문 번역
영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.
BIOS/EFI 구성 단계
1-31.. SPDX-License-Identifier: GPL-2.0
BIOS와 EFI는 Linux가 device 또는 향후 장착될 수 있는 device의 적절한 logical representation을 만들 수 있도록 정적 정보를 구성하는 일을 주로 담당합니다.
이 구성 단계에서는 상위 수준에서 다음 작업이 일어납니다.
- bootloader가 BIOS/EFI를 시작합니다.
- BIOS/EFI가 early device probe를 수행해 정적 구성을 파악합니다.
- BIOS/EFI가 OS에 정적 구성을 설명하는 ACPI Table을 만듭니다.
- BIOS/EFI가 EFI Memory Map, E820 등의 system memory map을 만듭니다.
- BIOS/EFI가 `start_kernel`을 호출하고 Linux Early Boot 과정을 시작합니다.
이 절은 주로 ACPI Table 생성과 정적 memory map 구성에 초점을 둡니다. table의 자세한 내용은 `ACPI Tables` 문서를 참조하십시오.
Platform vendor는 physical memory region의 크기와 alignment, memory hole, HDM interleave, 그리고 이 기능을 사용하는 HDM decoder에 Linux가 기대하는 조건에 관한 권고를 주의 깊게 읽어야 합니다.
UEFI 설정과 EFI_MEMORY_SP
32-71platform이 지원한다면 `uefisettings` command로 EFI setting을 읽고 쓸 수 있습니다. 변경 사항은 다음 reboot에 반영되며 kexec는 충분한 reboot가 아닙니다.
중요한 설정 중 하나는 `EFI_MEMORY_SP`(Specific Purpose) bit입니다. 이 bit를 enable하면 Linux는 memory region 관리를 driver, 여기서는 CXL driver에 맡깁니다. 그렇지 않으면 해당 memory는 `normal memory`로 처리되어 `__init` 중 page allocator에 노출됩니다.
`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 platform에서는 `CXL Memory Attribute` field를 통해 `EFI_MEMORY_SP` bit를 설정합니다. 다른 platform에서는 이름이 다를 수 있습니다.
`uefisettings get "CXL Memory Attribute"` 예시는 다음과 같습니다.
selector: xxx
...
question: Question {
name: "CXL Memory Attribute",
answer: "Enabled",
...
}
Physical Address Region Alignment
72-93Linux v6.14 기준 memory hotplug system은 memory region의 크기와 alignment가 균일하기를 요구합니다. CXL specification은 256MB만큼 작은 region을 허용하지만 hotplug memory가 지원하는 block size와 alignment는 architecture가 정의합니다.
Linux memory block은 128MB까지 작을 수 있으며 이후 2의 거듭제곱으로 증가합니다.
- ARM의 기본 block size와 alignment는 128MB 또는 256MB입니다.
- x86의 기본 block size는 256MB이며 system capacity가 64GB까지 커짐에 따라 2GB까지 증가합니다.
여러 Linux version에서 가장 잘 지원되도록 platform vendor는 CXL memory를 2GB aligned base address에 배치하고 region도 2GB 단위로 align해야 합니다. 이렇게 하면 block마다 하나씩 수천 개의 memory device가 만들어지는 문제도 줄어듭니다.
Physical Memory Map의 memory hole
94-139memory map의 hole은 처리하기 까다롭습니다. base address `0x100000000`에 놓인 4GB device가 다음과 같은 memory map을 가진다고 가정합니다.
---------------------
| 0x100000000 |
| CXL |
| 0x1BFFFFFFF |
---------------------
| 0x1C0000000 |
| MEMORY HOLE |
| 0x1FFFFFFFF |
---------------------
| 0x200000000 |
| CXL CONT. |
| 0x23FFFFFFF |
---------------------
4GB CXL device의 address range가 중간 memory hole 때문에 두 개의 연속 구간으로 나뉘는 구조입니다.
검토해야 할 문제는 decoder programming과 memory block alignment 두 가지입니다.
architecture가 균일한 2GB 크기와 alignment의 memory block을 요구한다면 Linux v6.14가 mapping할 수 있는 capacity는 `0x100000000-0x180000000`뿐입니다. 나머지는 길이가 2GB 단위로 align되지 않아 사용할 수 없는 capacity로 남습니다.
architecture와 memory 구성이 1GB memory block을 허용한다면 이 memory map은 지원됩니다. CEDT에는 memory hole 양쪽을 따로 설명하는 여러 CFMWS와 이에 대응하는 decoder를 제시해야 합니다.
이런 memory hole을 관리하려면 여러 decoder를 사용할 수 있고 사용해야 합니다. hole의 각 연속 chunk는 합리적인 block size로 align해야 하며 큰 alignment일수록 좋습니다. memory map에 hole을 둘 계획이라면 연속된 host physical memory chunk마다 decoder 하나를 사용해야 합니다.
Linux v6.14는 하나의 HDM decoder가 설명하는 memory hole로 분리된 여러 physical memory region의 memory hotplug를 지원합니다.
Decoder Programming과 translation point
140-175BIOS/EFI가 decoder를 정적으로 구성하도록 programming하려면 Linux 호환성을 막는 중대한 함정을 피하기 위해 몇 가지 사항을 고려해야 합니다. 일부 권고는 specification의 필수 조건이 아니지만, 따르지 않는 구성에 Linux는 지원을 보장하지 않습니다.
specification에 따르면 Host Physical Address(HPA)를 Device Physical Address(DPA)로 실제 `TRANSLATE`하는 decoder는 `Endpoint Decoder`뿐입니다. fabric의 다른 모든 decoder는 address를 변환하지 않고 access를 route해야 합니다.
CXL Specification 3.1의 관련 근거는 다음과 같습니다.
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와 endpoint 사이의 모든 decoder가 parent decoder address range의 subset으로 programming된다고 강하게 가정합니다.
Architecture, ACPI, PCI, CXL specification 사이의 책임 인계가 다소 모호해 일부 초기 platform은 시작 memory controller 또는 host bridge에서 translation을 시도했습니다. 이 구성은 platform별 driver extension이 필요하고 지원 사례가 있더라도 공식적으로 권장되지 않습니다.
이 방식을 사용하지 않는 것이 강력히 권장됩니다. 사용한다면 해당 platform의 driver 지원을 직접 구현해야 합니다.
Interleave와 구성 유연성
176-202host bridge를 가로지르는 `cross-host-bridge` interleave를 제공한다면 CEDT의 CFMWS entry가 interleave된 device set의 target host bridge를 제시해야 합니다. 각 host bridge 뒤에는 여러 device가 있을 수 있습니다.
host bridge 내부 `intra-host-bridge` interleave를 제공한다면 그 host bridge 뒤의 device 전체 capacity를 덮는 경우 CEDT에는 해당 host bridge용 CFMWS entry 하나만 필요합니다.
root 이후 decoder programming을 사용자에게 유연하게 제공하려면 서로 다른 목적의 CFMWS entry를 여러 개 둘 수 있습니다.
- interleave 가능한 모든 host bridge를 덮는 CFMWS entry
- 단일 host bridge의 모든 device를 덮는 CFMWS entry
- 각 device를 덮는 CFMWS entry
platform은 이 entry를 모두 추가하거나 BIOS setting에 따라 mode를 바꿀 수 있습니다. 각 CFMWS entry에 대해 Linux는 early boot/init 중 예약할 NUMA node 수를 결정할 수 있도록 SRAT에 해당 memory region 설명이 있기를 기대합니다.
Linux v6.14는 일치하는 SRAT entry가 없어도 각 CEDT CFMWS entry에 NUMA node를 만들지만, 향후에는 보장되지 않으므로 그런 구성은 피해야 합니다.
Memory hole을 위한 decoder 구성
203-250CXL memory 사이에 memory hole이 있다면 decoder가 전체 range를 받아들이게 한 뒤 Linux가 overlap을 관리하기를 기대하는 대신, 여러 decoder로 각 memory region을 덮는 것이 권장됩니다.
앞서 설명한 memory hole은 다음과 같습니다.
---------------------
| 0x100000000 |
| CXL |
| 0x1BFFFFFFF |
---------------------
| 0x1C0000000 |
| MEMORY HOLE |
| 0x1FFFFFFFF |
---------------------
| 0x200000000 |
| CXL CONT. |
| 0x23FFFFFFF |
---------------------
4GB CXL device의 address range가 중간 memory hole 때문에 두 개의 연속 구간으로 나뉘는 구조입니다.
이 memory가 host bridge에 직접 연결된 단일 device에서 제공된다고 가정하면 Linux는 다음 decoder programming을 기대합니다.
----------------------- -----------------------
| 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 |
----------------------- -----------------------
각 연속 HPA chunk는 root, host bridge, endpoint의 대응 decoder를 따라 독립적으로 route됩니다.
CEDT에는 위의 두 root decoder를 설명하는 두 CFMWS가 있어야 합니다. Linux는 특이한 memory hole 구성에 대한 지원을 보장하지 않습니다.
Multi-Media Device
251-262CEDT의 CFMWS field에는 해당 memory region이 volatile memory, persistent memory 또는 둘 다를 허용하는지 설명하는 특별한 restriction bit가 있습니다.
platform이 다음 중 하나를 지원하려 한다고 가정합니다.
- 여러 media를 가진 device
- persistent memory device를 normal memory로 사용
이 경우 end user가 memory 구성 방식을 유연하게 선택할 수 있도록 동일한 memory를 설명하는 CEDT CFMWS entry를 여러 개 만들 수 있습니다. 현재 Linux는 이 영역에 강한 요구 조건을 두지 않습니다.
요약과 해설
bios-and-efi.rst:1-262CXL의 정적 구성은 BIOS/EFI가 만든 ACPI table과 physical memory map에서 시작됩니다. `EFI_MEMORY_SP`는 memory 관리를 CXL driver에 맡기고, 2GB alignment는 여러 architecture와 kernel version의 hotplug 호환성을 높입니다. HPA-to-DPA translation은 endpoint decoder에서만 수행해야 하며, memory hole은 연속 HPA chunk마다 root·host bridge·endpoint decoder chain과 CFMWS를 나누는 구성이 가장 안전합니다.