요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
.. SPDX-License-Identifier: GPL-2.0
====================
CXL Driver Operation
====================
The devices described in this section are present in ::
/sys/bus/cxl/devices/
/dev/cxl/
The :code:`cxl-cli` library, maintained as part of the NDTCL project, may
be used to script interactions with these devices.
Drivers
=======
The CXL driver is split into a number of drivers.
* cxl_core - fundamental init interface and core object creation
* cxl_port - initializes root and provides port enumeration interface.
* cxl_acpi - initializes root decoders and interacts with ACPI data.
* cxl_p/mem - initializes memory devices
* cxl_pci - uses cxl_port to enumerate the actual fabric hierarchy.
Driver Devices
==============
Here is an example from a single-socket system with 4 host bridges. Two host
bridges have a single memory device attached, and the devices are interleaved
into a single memory region. The memory region has been converted to dax. ::
# ls /sys/bus/cxl/devices/
dax_region0 decoder3.0 decoder6.0 mem0 port3
decoder0.0 decoder4.0 decoder6.1 mem1 port4
decoder1.0 decoder5.0 endpoint5 port1 region0
decoder2.0 decoder5.1 endpoint6 port2 root0
.. kernel-render:: DOT
:alt: Digraph of CXL fabric describing host-bridge interleaving
:caption: Diagraph of CXL fabric with a host-bridge interleave memory region
digraph foo {
"root0" -> "port1";
"root0" -> "port3";
"root0" -> "decoder0.0";
"port1" -> "endpoint5";
"port3" -> "endpoint6";
"port1" -> "decoder1.0";
"port3" -> "decoder3.0";
"endpoint5" -> "decoder5.0";
"endpoint6" -> "decoder6.0";
"decoder0.0" -> "region0";
"decoder0.0" -> "decoder1.0";
"decoder0.0" -> "decoder3.0";
"decoder1.0" -> "decoder5.0";
"decoder3.0" -> "decoder6.0";
"decoder5.0" -> "region0";
"decoder6.0" -> "region0";
"region0" -> "dax_region0";
"dax_region0" -> "dax0.0";
}
For this section we'll explore the devices present in this configuration, but
we'll explore more configurations in-depth in example configurations below.
Base Devices
------------
Most devices in a CXL fabric are a `port` of some kind (because each
device mostly routes request from one device to the next, rather than
provide a direct service).
Root
~~~~
The `CXL Root` is logical object created by the `cxl_acpi` driver during
:code:`cxl_acpi_probe` - if the :code:`ACPI0017` `Compute Express Link
Root Object` Device Class is found.
The Root contains links to:
* `Host Bridge Ports` defined by CHBS in the :doc:`CEDT<../platform/acpi/cedt>`
* `Downstream Ports` typically connected to `Host Bridge Ports`.
* `Root Decoders` defined by CFMWS the :doc:`CEDT<../platform/acpi/cedt>`
::
# ls /sys/bus/cxl/devices/root0
decoder0.0 dport0 dport5 port2 subsystem
decoders_committed dport1 modalias port3 uevent
devtype dport4 port1 port4 uport
# cat /sys/bus/cxl/devices/root0/devtype
cxl_port
# cat port1/devtype
cxl_port
# cat decoder0.0/devtype
cxl_decoder_root
The root is first `logical port` in the CXL fabric, as presented by the Linux
CXL driver. The `CXL root` is a special type of `switch port`, in that it
only has downstream port connections.
Port
~~~~
A `port` object is better described as a `switch port`. It may represent a
host bridge to the root or an actual switch port on a switch. A `switch port`
contains one or more decoders used to route memory requests downstream ports,
which may be connected to another `switch port` or an `endpoint port`.
::
# ls /sys/bus/cxl/devices/port1
decoder1.0 dport0 driver parent_dport uport
decoders_committed dport113 endpoint5 subsystem
devtype dport2 modalias uevent
# cat devtype
cxl_port
# cat decoder1.0/devtype
cxl_decoder_switch
# cat endpoint5/devtype
cxl_port
CXL `Host Bridges` in the fabric are probed during :code:`cxl_acpi_probe` at
the time the `CXL Root` is probed. The allows for the immediate logical
connection to between the root and host bridge.
* The root has a downstream port connection to a host bridge
* The host bridge has an upstream port connection to the root.
* The host bridge has one or more downstream port connections to switch
or endpoint ports.
A `Host Bridge` is a special type of CXL `switch port`. It is explicitly
defined in the ACPI specification via `ACPI0016` ID. `Host Bridge` ports
will be probed at `acpi_probe` time, while similar ports on an actual switch
will be probed later. Otherwise, switch and host bridge ports look very
similar - the both contain switch decoders which route accesses between
upstream and downstream ports.
Endpoint
~~~~~~~~
An `endpoint` is a terminal port in the fabric. This is a `logical device`,
and may be one of many `logical devices` presented by a memory device. It
is still considered a type of `port` in the fabric.
An `endpoint` contains `endpoint decoders` and the device's Coherent Device
Attribute Table (which describes the device's capabilities). ::
# ls /sys/bus/cxl/devices/endpoint5
CDAT decoders_committed modalias uevent
decoder5.0 devtype parent_dport uport
decoder5.1 driver subsystem
# cat /sys/bus/cxl/devices/endpoint5/devtype
cxl_port
# cat /sys/bus/cxl/devices/endpoint5/decoder5.0/devtype
cxl_decoder_endpoint
Memory Device (memdev)
~~~~~~~~~~~~~~~~~~~~~~
A `memdev` is probed and added by the `cxl_pci` driver in :code:`cxl_pci_probe`
and is managed by the `cxl_mem` driver. It primarily provides the `IOCTL`
interface to a memory device, via :code:`/dev/cxl/memN`, and exposes various
device configuration data. ::
# ls /sys/bus/cxl/devices/mem0
dev firmware_version payload_max security uevent
driver label_storage_size pmem serial
firmware numa_node ram subsystem
A Memory Device is a discrete base object that is not a port. While the
physical device it belongs to may also host an `endpoint`, the relationship
between an `endpoint` and a `memdev` is not captured in sysfs.
Port Relationships
~~~~~~~~~~~~~~~~~~
In our example described above, there are four host bridges attached to the
root, and two of the host bridges have one endpoint attached.
.. kernel-render:: DOT
:alt: Digraph of CXL fabric describing host-bridge interleaving
:caption: Diagraph of CXL fabric with a host-bridge interleave memory region
digraph foo {
"root0" -> "port1";
"root0" -> "port2";
"root0" -> "port3";
"root0" -> "port4";
"port1" -> "endpoint5";
"port3" -> "endpoint6";
}
Decoders
--------
A `Decoder` is short for a CXL Host-Managed Device Memory (HDM) Decoder. It is
a device that routes accesses through the CXL fabric to an endpoint, and at
the endpoint translates a `Host Physical` to `Device Physical` Addressing.
The CXL 3.1 specification heavily implies that only endpoint decoders should
engage in translation of `Host Physical Address` to `Device Physical Address`.
::
8.2.4.20 CXL HDM Decoder Capability Structure
IMPLEMENTATION NOTE
CXL Host Bridge and Upstream Switch Port Decode Flow
IMPLEMENTATION NOTE
Device Decode Logic
These notes imply that there are two logical groups of decoders.
* Routing Decoder - a decoder which routes accesses but does not translate
addresses from HPA to DPA.
* Translating Decoder - a decoder which translates accesses from HPA to DPA
for an endpoint to service.
The CXL drivers distinguish 3 decoder types: root, switch, and endpoint. Only
endpoint decoders are Translating Decoders, all others are Routing Decoders.
.. note:: PLATFORM VENDORS BE AWARE
Linux makes a strong assumption that endpoint decoders are the only decoder
in the fabric that actively translates HPA to DPA. Linux assumes routing
decoders pass the HPA unchanged to the next decoder in the fabric.
It is therefore assumed that any given decoder in the fabric will have an
address range that is a subset of its upstream port decoder. Any deviation
from this scheme undefined per the specification. Linux prioritizes
spec-defined / architectural behavior.
Decoders may have one or more `Downstream Targets` if configured to interleave
memory accesses. This will be presented in sysfs via the :code:`target_list`
parameter.
Root Decoder
~~~~~~~~~~~~
A `Root Decoder` is logical construct of the physical address and interleave
configurations present in the CFMWS field of the :doc:`CEDT
<../platform/acpi/cedt>`.
Linux presents this information as a decoder present in the `CXL Root`. We
consider this a `Root Decoder`, though technically it exists on the boundary
of the CXL specification and platform-specific CXL root implementations.
Linux considers these logical decoders a type of `Routing Decoder`, and is the
first decoder in the CXL fabric to receive a memory access from the platform's
memory controllers.
`Root Decoders` are created during :code:`cxl_acpi_probe`. One root decoder
is created per CFMWS entry in the :doc:`CEDT <../platform/acpi/cedt>`.
The :code:`target_list` parameter is filled by the CFMWS target fields. Targets
of a root decoder are `Host Bridges`, which means interleave done at the root
decoder level is an `Inter-Host-Bridge Interleave`.
Only root decoders are capable of `Inter-Host-Bridge Interleave`.
Such interleaves must be configured by the platform and described in the ACPI
CEDT CFMWS, as the target CXL host bridge UIDs in the CFMWS must match the CXL
host bridge UIDs in the CHBS field of the :doc:`CEDT
<../platform/acpi/cedt>` and the UID field of CXL Host Bridges defined in
the :doc:`DSDT <../platform/acpi/dsdt>`.
Interleave settings in a root decoder describe how to interleave accesses among
the *immediate downstream targets*, not the entire interleave set.
The memory range described in the root decoder is used to
1) Create a memory region (:code:`region0` in this example), and
2) Associate the region with an IO Memory Resource (:code:`kernel/resource.c`)
::
# ls /sys/bus/cxl/devices/decoder0.0/
cap_pmem devtype region0
cap_ram interleave_granularity size
cap_type2 interleave_ways start
cap_type3 locked subsystem
create_ram_region modalias target_list
delete_region qos_class uevent
# cat /sys/bus/cxl/devices/decoder0.0/region0/resource
0xc050000000
The IO Memory Resource is created during early boot when the CFMWS region is
identified in the EFI Memory Map or E820 table (on x86).
Root decoders are defined as a separate devtype, but are also a type
of `Switch Decoder` due to having downstream targets. ::
# cat /sys/bus/cxl/devices/decoder0.0/devtype
cxl_decoder_root
Switch Decoder
~~~~~~~~~~~~~~
Any non-root, translating decoder is considered a `Switch Decoder`, and will
present with the type :code:`cxl_decoder_switch`. Both `Host Bridge` and `CXL
Switch` (device) decoders are of type :code:`cxl_decoder_switch`. ::
# ls /sys/bus/cxl/devices/decoder1.0/
devtype locked size target_list
interleave_granularity modalias start target_type
interleave_ways region subsystem uevent
# cat /sys/bus/cxl/devices/decoder1.0/devtype
cxl_decoder_switch
# cat /sys/bus/cxl/devices/decoder1.0/region
region0
A `Switch Decoder` has associations between a region defined by a root
decoder and downstream target ports. Interleaving done within a switch decoder
is a multi-downstream-port interleave (or `Intra-Host-Bridge Interleave` for
host bridges).
Interleave settings in a switch decoder describe how to interleave accesses
among the *immediate downstream targets*, not the entire interleave set.
Switch decoders are created during :code:`cxl_switch_port_probe` in the
:code:`cxl_port` driver, and is created based on a PCI device's DVSEC
registers.
Switch decoder programming is validated during probe if the platform programs
them during boot (See `Auto Decoders` below), or on commit if programmed at
runtime (See `Runtime Programming` below).
Endpoint Decoder
~~~~~~~~~~~~~~~~
Any decoder attached to a *terminal* point in the CXL fabric (`An Endpoint`) is
considered an `Endpoint Decoder`. Endpoint decoders are of type
:code:`cxl_decoder_endpoint`. ::
# ls /sys/bus/cxl/devices/decoder5.0
devtype locked start
dpa_resource modalias subsystem
dpa_size mode target_type
interleave_granularity region uevent
interleave_ways size
# cat /sys/bus/cxl/devices/decoder5.0/devtype
cxl_decoder_endpoint
# cat /sys/bus/cxl/devices/decoder5.0/region
region0
An `Endpoint Decoder` has an association with a region defined by a root
decoder and describes the device-local resource associated with this region.
Unlike root and switch decoders, endpoint decoders translate `Host Physical` to
`Device Physical` address ranges. The interleave settings on an endpoint
therefore describe the entire *interleave set*.
`Device Physical Address` regions must be committed in-order. For example, the
DPA region starting at 0x80000000 cannot be committed before the DPA region
starting at 0x0.
As of Linux v6.15, Linux does not support *imbalanced* interleave setups, all
endpoints in an interleave set are expected to have the same interleave
settings (granularity and ways must be the same).
Endpoint decoders are created during :code:`cxl_endpoint_port_probe` in the
:code:`cxl_port` driver, and is created based on a PCI device's DVSEC registers.
Decoder Relationships
~~~~~~~~~~~~~~~~~~~~~
In our example described above, there is one root decoder which routes memory
accesses over two host bridges. Each host bridge has a decoder which routes
access to their singular endpoint targets. Each endpoint has a decoder which
translates HPA to DPA and services the memory request.
The driver validates relationships between ports by decoder programming, so
we can think of decoders being related in a similarly hierarchical fashion to
ports.
.. kernel-render:: DOT
:alt: Digraph of hierarchical relationship between root, switch, and endpoint decoders.
:caption: Diagraph of CXL root, switch, and endpoint decoders.
digraph foo {
"root0" -> "decoder0.0";
"decoder0.0" -> "decoder1.0";
"decoder0.0" -> "decoder3.0";
"decoder1.0" -> "decoder5.0";
"decoder3.0" -> "decoder6.0";
}
Regions
-------
Memory Region
~~~~~~~~~~~~~
A `Memory Region` is a logical construct that connects a set of CXL ports in
the fabric to an IO Memory Resource. It is ultimately used to expose the memory
on these devices to the DAX subsystem via a `DAX Region`.
An example RAM region: ::
# ls /sys/bus/cxl/devices/region0/
access0 devtype modalias subsystem uuid
access1 driver mode target0
commit interleave_granularity resource target1
dax_region0 interleave_ways size uevent
A memory region can be constructed during endpoint probe, if decoders were
programmed by BIOS/EFI (see `Auto Decoders`), or by creating a region manually
via a `Root Decoder`'s :code:`create_ram_region` or :code:`create_pmem_region`
interfaces.
The interleave settings in a `Memory Region` describe the configuration of the
`Interleave Set` - and are what can be expected to be seen in the endpoint
interleave settings.
.. kernel-render:: DOT
:alt: Digraph of CXL memory region relationships between root and endpoint decoders.
:caption: Regions are created based on root decoder configurations. Endpoint decoders
must be programmed with the same interleave settings as the region.
digraph foo {
"root0" -> "decoder0.0";
"decoder0.0" -> "region0";
"region0" -> "decoder5.0";
"region0" -> "decoder6.0";
}
DAX Region
~~~~~~~~~~
A `DAX Region` is used to convert a CXL `Memory Region` to a DAX device. A
DAX device may then be accessed directly via a file descriptor interface, or
converted to System RAM via the DAX kmem driver. See the DAX driver section
for more details. ::
# ls /sys/bus/cxl/devices/dax_region0/
dax0.0 devtype modalias uevent
dax_region driver subsystem
Mailbox Interfaces
------------------
A mailbox command interface for each device is exposed in ::
/dev/cxl/mem0
/dev/cxl/mem1
These mailboxes may receive any specification-defined command. Raw commands
(custom commands) can only be sent to these interfaces if the build config
:code:`CXL_MEM_RAW_COMMANDS` is set. This is considered a debug and/or
development interface, not an officially supported mechanism for creation
of vendor-specific commands (see the `fwctl` subsystem for that).
Decoder Programming
===================
Runtime Programming
-------------------
During probe, the only decoders *required* to be programmed are `Root Decoders`.
In reality, `Root Decoders` are a logical construct to describe the memory
region and interleave configuration at the host bridge level - as described
in the ACPI CEDT CFMWS.
All other `Switch` and `Endpoint` decoders may be programmed by the user
at runtime - if the platform supports such configurations.
This interaction is what creates a `Software Defined Memory` environment.
See the :code:`cxl-cli` documentation for more information about how to
configure CXL decoders at runtime.
Auto Decoders
-------------
Auto Decoders are decoders programmed by BIOS/EFI at boot time, and are
almost always locked (cannot be changed). This is done by a platform
which may have a static configuration - or certain quirks which may prevent
dynamic runtime changes to the decoders (such as requiring additional
controller programming within the CPU complex outside the scope of CXL).
Auto Decoders are probed automatically as long as the devices and memory
regions they are associated with probe without issue. When probing Auto
Decoders, the driver's primary responsibility is to ensure the fabric is
sane - as-if validating runtime programmed regions and decoders.
If Linux cannot validate auto-decoder configuration, the memory will not
be surfaced as a DAX device - and therefore not be exposed to the page
allocator - effectively stranding it.
Interleave
----------
The Linux CXL driver supports `Cross-Link First` interleave. This dictates
how interleave is programmed at each decoder step, as the driver validates
the relationships between a decoder and it's parent.
For example, in a `Cross-Link First` interleave setup with 16 endpoints
attached to 4 host bridges, linux expects the following ways/granularity
across the root, host bridge, and endpoints respectively.
.. flat-table:: 4x4 cross-link first interleave settings
* - decoder
- ways
- granularity
* - root
- 4
- 256
* - host bridge
- 4
- 1024
* - endpoint
- 16
- 256
At the root, every a given access will be routed to the
:code:`((HPA / 256) % 4)th` target host bridge. Within a host bridge, every
:code:`((HPA / 1024) % 4)th` target endpoint. Each endpoint translates based
on the entire 16 device interleave set.
Unbalanced interleave sets are not supported - decoders at a similar point
in the hierarchy (e.g. all host bridge decoders) must have the same ways and
granularity configuration.
At Root
~~~~~~~
Root decoder interleave is defined by CFMWS field of the :doc:`CEDT
<../platform/acpi/cedt>`. The CEDT may actually define multiple CFMWS
configurations to describe the same physical capacity, with the intent to allow
users to decide at runtime whether to online memory as interleaved or
non-interleaved. ::
Subtable Type : 01 [CXL Fixed Memory Window Structure]
Window base address : 0000000100000000
Window size : 0000000100000000
Interleave Members (2^n) : 00
Interleave Arithmetic : 00
First Target : 00000007
Subtable Type : 01 [CXL Fixed Memory Window Structure]
Window base address : 0000000200000000
Window size : 0000000100000000
Interleave Members (2^n) : 00
Interleave Arithmetic : 00
First Target : 00000006
Subtable Type : 01 [CXL Fixed Memory Window Structure]
Window base address : 0000000300000000
Window size : 0000000200000000
Interleave Members (2^n) : 01
Interleave Arithmetic : 00
First Target : 00000007
Next Target : 00000006
In this example, the CFMWS defines two discrete non-interleaved 4GB regions
for each host bridge, and one interleaved 8GB region that targets both. This
would result in 3 root decoders presenting in the root. ::
# ls /sys/bus/cxl/devices/root0/decoder*
decoder0.0 decoder0.1 decoder0.2
# cat /sys/bus/cxl/devices/decoder0.0/target_list start size
7
0x100000000
0x100000000
# cat /sys/bus/cxl/devices/decoder0.1/target_list start size
6
0x200000000
0x100000000
# cat /sys/bus/cxl/devices/decoder0.2/target_list start size
7,6
0x300000000
0x200000000
These decoders are not runtime programmable. They are used to generate a
`Memory Region` to bring this memory online with runtime programmed settings
at the `Switch` and `Endpoint` decoders.
At Host Bridge or Switch
~~~~~~~~~~~~~~~~~~~~~~~~
`Host Bridge` and `Switch` decoders are programmable via the following fields:
- :code:`start` - the HPA region associated with the memory region
- :code:`size` - the size of the region
- :code:`target_list` - the list of downstream ports
- :code:`interleave_ways` - the number downstream ports to interleave across
- :code:`interleave_granularity` - the granularity to interleave at.
Linux expects the :code:`interleave_granularity` of switch decoders to be
derived from their upstream port connections. In `Cross-Link First` interleave
configurations, the :code:`interleave_granularity` of a decoder is equal to
:code:`parent_interleave_granularity * parent_interleave_ways`.
At Endpoint
~~~~~~~~~~~
`Endpoint Decoders` are programmed similar to Host Bridge and Switch decoders,
with the exception that the ways and granularity are defined by the interleave
set (e.g. the interleave settings defined by the associated `Memory Region`).
- :code:`start` - the HPA region associated with the memory region
- :code:`size` - the size of the region
- :code:`interleave_ways` - the number endpoints in the interleave set
- :code:`interleave_granularity` - the granularity to interleave at.
These settings are used by endpoint decoders to *Translate* memory requests
from HPA to DPA. This is why they must be aware of the entire interleave set.
Linux does not support unbalanced interleave configurations. As a result, all
endpoints in an interleave set must have the same ways and granularity.
Example Configurations
======================
.. toctree::
:maxdepth: 1
example-configurations/single-device.rst
example-configurations/hb-interleave.rst
example-configurations/intra-hb-interleave.rst
example-configurations/multi-interleave.rst
3. 한국어 전문 번역
영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.
CXL driver 장치 경로
1-14.. SPDX-License-Identifier: GPL-2.0
이 문서에서 설명하는 장치는 다음 경로에 있습니다.
/sys/bus/cxl/devices/
/dev/cxl/
NDTCL 프로젝트의 일부로 관리되는 `cxl-cli` library를 사용하면 이 장치들과의 상호작용을 script로 자동화할 수 있습니다.
CXL driver 구성 모듈
15-24CXL driver는 여러 driver로 나뉩니다.
- `cxl_core`: 기본 초기화 interface와 core object 생성을 담당합니다.
- `cxl_port`: root를 초기화하고 port enumeration interface를 제공합니다.
- `cxl_acpi`: root decoder를 초기화하고 ACPI data와 상호작용합니다.
- `cxl_p/mem`: memory device를 초기화합니다.
- `cxl_pci`: `cxl_port`를 이용해 실제 fabric 계층을 열거합니다.
Host Bridge interleave 예제
25-65다음은 Host Bridge가 4개인 single-socket 시스템 예입니다. 두 Host Bridge에 memory device가 하나씩 연결되고, 두 장치는 하나의 memory region으로 interleave돼 있습니다. 이 memory region은 DAX로 변환됐습니다.
# ls /sys/bus/cxl/devices/
dax_region0 decoder3.0 decoder6.0 mem0 port3
decoder0.0 decoder4.0 decoder6.1 mem1 port4
decoder1.0 decoder5.0 endpoint5 port1 region0
decoder2.0 decoder5.1 endpoint6 port2 root0
.. kernel-render:: DOT
:alt: Digraph of CXL fabric describing host-bridge interleaving
:caption: Diagraph of CXL fabric with a host-bridge interleave memory region
digraph foo {
"root0" -> "port1";
"root0" -> "port3";
"root0" -> "decoder0.0";
"port1" -> "endpoint5";
"port3" -> "endpoint6";
"port1" -> "decoder1.0";
"port3" -> "decoder3.0";
"endpoint5" -> "decoder5.0";
"endpoint6" -> "decoder6.0";
"decoder0.0" -> "region0";
"decoder0.0" -> "decoder1.0";
"decoder0.0" -> "decoder3.0";
"decoder1.0" -> "decoder5.0";
"decoder3.0" -> "decoder6.0";
"decoder5.0" -> "region0";
"decoder6.0" -> "region0";
"region0" -> "dax_region0";
"dax_region0" -> "dax0.0";
}
두 Endpoint의 decoder가 region0에 결합되고 DAX Region을 거쳐 dax0.0으로 노출되는 fabric 관계입니다.
이 절에서는 이 구성에 나타나는 장치를 살펴봅니다. 더 다양한 구성은 뒤의 example configuration 문서에서 자세히 다룹니다.
Base Device와 CXL Root
66-105CXL fabric의 대부분 장치는 어떤 종류의 `port`입니다. 각 장치가 직접 서비스를 제공하기보다는 한 장치의 요청을 다음 장치로 routing하는 역할을 주로 하기 때문입니다.
`CXL Root`는 `ACPI0017` Compute Express Link Root Object Device Class를 찾았을 때 `cxl_acpi` driver가 `cxl_acpi_probe` 중 생성하는 logical object입니다.
Root에는 다음 항목을 향한 link가 있습니다.
- CEDT의 CHBS가 정의한 Host Bridge Port
- 보통 Host Bridge Port에 연결되는 Downstream Port
- CEDT의 CFMWS가 정의한 Root Decoder
# ls /sys/bus/cxl/devices/root0
decoder0.0 dport0 dport5 port2 subsystem
decoders_committed dport1 modalias port3 uevent
devtype dport4 port1 port4 uport
# cat /sys/bus/cxl/devices/root0/devtype
cxl_port
# cat port1/devtype
cxl_port
# cat decoder0.0/devtype
cxl_decoder_root
Linux CXL driver가 보여 주는 fabric에서 root는 첫 logical port입니다. CXL root는 downstream port 연결만 가진다는 점에서 특별한 switch port입니다.
Port와 Host Bridge
106-146`port` object는 `switch port`라고 설명하는 편이 정확합니다. root에 연결된 Host Bridge를 나타낼 수도 있고 실제 switch의 port를 나타낼 수도 있습니다.
switch port에는 memory 요청을 downstream port로 routing하는 decoder가 하나 이상 있습니다. downstream은 다른 switch port나 endpoint port에 연결될 수 있습니다.
# ls /sys/bus/cxl/devices/port1
decoder1.0 dport0 driver parent_dport uport
decoders_committed dport113 endpoint5 subsystem
devtype dport2 modalias uevent
# cat devtype
cxl_port
# cat decoder1.0/devtype
cxl_decoder_switch
# cat endpoint5/devtype
cxl_port
fabric의 CXL Host Bridge는 CXL Root를 probe하는 `cxl_acpi_probe` 중 함께 probe되므로 root와 Host Bridge 사이의 logical 연결을 즉시 만들 수 있습니다.
- root는 Host Bridge를 향하는 downstream port 연결을 가집니다.
- Host Bridge는 root를 향하는 upstream port 연결을 가집니다.
- Host Bridge는 switch 또는 endpoint port를 향하는 downstream port 연결을 하나 이상 가집니다.
Host Bridge는 특별한 CXL switch port이며 ACPI 사양의 `ACPI0016` ID로 명시됩니다. Host Bridge port는 `acpi_probe` 때 probe되고 실제 switch의 비슷한 port는 나중에 probe됩니다. 두 유형 모두 upstream과 downstream 사이의 접근을 routing하는 switch decoder를 포함하므로 그 밖의 모습은 매우 비슷합니다.
Endpoint port
147-167endpoint는 fabric의 terminal port입니다. memory device가 제시하는 여러 logical device 중 하나일 수 있는 logical device이며, fabric에서는 여전히 port의 한 유형입니다.
endpoint는 endpoint decoder와 장치 capability를 설명하는 Coherent Device Attribute Table(CDAT)을 포함합니다.
# ls /sys/bus/cxl/devices/endpoint5
CDAT decoders_committed modalias uevent
decoder5.0 devtype parent_dport uport
decoder5.1 driver subsystem
# cat /sys/bus/cxl/devices/endpoint5/devtype
cxl_port
# cat /sys/bus/cxl/devices/endpoint5/decoder5.0/devtype
cxl_decoder_endpoint
Memory Device(memdev)
168-183`memdev`는 `cxl_pci` driver가 `cxl_pci_probe`에서 probe해 추가하고 `cxl_mem` driver가 관리합니다. 주로 `/dev/cxl/memN`을 통한 memory device IOCTL interface를 제공하고 여러 장치 구성 data를 노출합니다.
# ls /sys/bus/cxl/devices/mem0
dev firmware_version payload_max security uevent
driver label_storage_size pmem serial
firmware numa_node ram subsystem
Memory Device는 port가 아닌 별도의 base object입니다. 물리 장치가 endpoint도 함께 가질 수 있지만 endpoint와 memdev의 관계는 sysfs에 표현되지 않습니다.
Port 관계
184-201예제에는 root에 연결된 Host Bridge가 네 개 있고, 그중 두 Host Bridge에 endpoint가 하나씩 연결돼 있습니다.
.. kernel-render:: DOT
:alt: Digraph of CXL fabric describing host-bridge interleaving
:caption: Diagraph of CXL fabric with a host-bridge interleave memory region
digraph foo {
"root0" -> "port1";
"root0" -> "port2";
"root0" -> "port3";
"root0" -> "port4";
"port1" -> "endpoint5";
"port3" -> "endpoint6";
}
root0 아래 네 Host Bridge port가 있고 port1과 port3에 각각 Endpoint가 연결된 구조입니다.
HDM Decoder의 역할
202-245Decoder는 CXL Host-Managed Device Memory(HDM) Decoder를 줄인 말입니다. fabric을 통해 endpoint로 접근을 routing하고, endpoint에서는 Host Physical Address를 Device Physical Address로 변환합니다.
CXL 3.1 사양은 endpoint decoder만 Host Physical Address(HPA)를 Device Physical Address(DPA)로 변환해야 한다는 점을 강하게 시사합니다.
8.2.4.20 CXL HDM Decoder Capability Structure
IMPLEMENTATION NOTE
CXL Host Bridge and Upstream Switch Port Decode Flow
IMPLEMENTATION NOTE
Device Decode Logic
이 구현 참고 사항은 decoder를 두 logical group으로 나눕니다.
- Routing Decoder: 접근을 routing하지만 HPA를 DPA로 변환하지 않습니다.
- Translating Decoder: endpoint가 처리할 수 있도록 접근 주소를 HPA에서 DPA로 변환합니다.
CXL driver는 root, switch, endpoint의 세 decoder 유형을 구별합니다. Endpoint Decoder만 Translating Decoder이고 나머지는 모두 Routing Decoder입니다.
플랫폼 공급자는 Linux가 endpoint decoder만 fabric에서 HPA를 DPA로 실제 변환한다고 강하게 가정한다는 점에 유의해야 합니다. Routing Decoder는 변경하지 않은 HPA를 다음 decoder에 전달한다고 가정합니다.
따라서 fabric의 각 decoder 주소 범위는 upstream port decoder 범위의 부분집합이어야 합니다. 이 방식에서 벗어난 동작은 사양상 정의되지 않았으며 Linux는 사양에 정의된 architecture 동작을 우선합니다.
memory 접근을 interleave하도록 구성한 decoder는 Downstream Target을 하나 이상 가질 수 있고 sysfs의 `target_list` parameter에 표시됩니다.
Root Decoder
246-304Root Decoder는 CEDT의 CFMWS field에 있는 물리 주소와 interleave 구성을 표현하는 logical construct입니다. Linux는 이를 CXL Root에 있는 decoder로 제시합니다. 기술적으로는 CXL 사양과 플랫폼별 CXL root 구현의 경계에 존재하지만 이 문서에서는 Root Decoder라고 부릅니다.
Linux는 이를 Routing Decoder로 간주하며 플랫폼 memory controller에서 온 접근을 처음 받는 CXL fabric decoder입니다.
`cxl_acpi_probe` 중 CEDT CFMWS entry마다 Root Decoder 하나를 만듭니다. `target_list`는 CFMWS target field로 채우며 target은 Host Bridge입니다. 따라서 root decoder 수준의 interleave는 Inter-Host-Bridge Interleave이고 이 기능은 Root Decoder만 수행할 수 있습니다.
이 interleave는 플랫폼이 구성하고 ACPI CEDT CFMWS에 기술해야 합니다. CFMWS의 target CXL Host Bridge UID는 CEDT CHBS와 DSDT에 정의된 CXL Host Bridge UID와 일치해야 합니다.
Root Decoder의 interleave 설정은 전체 interleave set이 아니라 바로 아래 downstream target 사이에서 접근을 interleave하는 방법을 설명합니다.
Root Decoder가 설명하는 memory 범위는 memory region을 만들고, 그 region을 `kernel/resource.c`의 IO Memory Resource와 연결하는 데 사용합니다.
# ls /sys/bus/cxl/devices/decoder0.0/
cap_pmem devtype region0
cap_ram interleave_granularity size
cap_type2 interleave_ways start
cap_type3 locked subsystem
create_ram_region modalias target_list
delete_region qos_class uevent
# cat /sys/bus/cxl/devices/decoder0.0/region0/resource
0xc050000000
IO Memory Resource는 초기 부팅 중 CFMWS region을 EFI Memory Map 또는 x86의 E820 table에서 찾을 때 생성됩니다.
Root Decoder는 별도 `devtype`으로 정의되지만 downstream target이 있으므로 Switch Decoder의 한 유형이기도 합니다.
# cat /sys/bus/cxl/devices/decoder0.0/devtype
cxl_decoder_root
Switch Decoder
305-338root가 아닌 routing decoder는 Switch Decoder이며 `cxl_decoder_switch` 유형으로 표시됩니다. Host Bridge와 실제 CXL Switch의 decoder가 모두 이 유형입니다.
# ls /sys/bus/cxl/devices/decoder1.0/
devtype locked size target_list
interleave_granularity modalias start target_type
interleave_ways region subsystem uevent
# cat /sys/bus/cxl/devices/decoder1.0/devtype
cxl_decoder_switch
# cat /sys/bus/cxl/devices/decoder1.0/region
region0
Switch Decoder는 Root Decoder가 정의한 region과 downstream target port 사이의 연관을 가집니다. Switch Decoder 안에서의 interleave는 multi-downstream-port interleave이며, Host Bridge에서는 Intra-Host-Bridge Interleave라고도 부릅니다.
Switch Decoder의 interleave 설정도 전체 interleave set이 아니라 바로 아래 downstream target 사이의 분배를 설명합니다.
Switch Decoder는 `cxl_port` driver의 `cxl_switch_port_probe` 중 PCI 장치 DVSEC register를 바탕으로 생성됩니다. 플랫폼이 부팅 중 프로그래밍한 경우 probe 때 검증하고, 실행 중 프로그래밍한 경우 commit 때 검증합니다.
Endpoint Decoder
339-375CXL fabric의 terminal 지점인 Endpoint에 연결된 decoder는 Endpoint Decoder이며 `cxl_decoder_endpoint` 유형입니다.
# ls /sys/bus/cxl/devices/decoder5.0
devtype locked start
dpa_resource modalias subsystem
dpa_size mode target_type
interleave_granularity region uevent
interleave_ways size
# cat /sys/bus/cxl/devices/decoder5.0/devtype
cxl_decoder_endpoint
# cat /sys/bus/cxl/devices/decoder5.0/region
region0
Endpoint Decoder는 Root Decoder가 정의한 region과 연관되며 이 region에 연결된 device-local resource를 설명합니다.
Root 및 Switch Decoder와 달리 Endpoint Decoder는 Host Physical Address 범위를 Device Physical Address 범위로 변환합니다. 따라서 Endpoint Decoder의 interleave 설정은 전체 interleave set을 설명합니다.
Device Physical Address region은 순서대로 commit해야 합니다. 예를 들어 `0x80000000`에서 시작하는 DPA region을 `0x0`에서 시작하는 region보다 먼저 commit할 수 없습니다.
Linux v6.15 기준으로 불균형 interleave 구성을 지원하지 않습니다. 한 interleave set의 모든 endpoint는 granularity와 ways가 같은 설정을 가져야 합니다.
Endpoint Decoder는 `cxl_port` driver의 `cxl_endpoint_port_probe` 중 PCI 장치 DVSEC register를 바탕으로 생성됩니다.
Decoder 계층 관계
376-398예제의 Root Decoder 하나는 두 Host Bridge에 memory 접근을 routing합니다. 각 Host Bridge decoder는 단일 endpoint target으로 접근을 routing하고, 각 Endpoint Decoder는 HPA를 DPA로 변환해 memory 요청을 처리합니다.
driver는 decoder programming으로 port 사이의 관계를 검증하므로 decoder도 port와 비슷한 계층 관계로 생각할 수 있습니다.
.. kernel-render:: DOT
:alt: Digraph of hierarchical relationship between root, switch, and endpoint decoders.
:caption: Diagraph of CXL root, switch, and endpoint decoders.
digraph foo {
"root0" -> "decoder0.0";
"decoder0.0" -> "decoder1.0";
"decoder0.0" -> "decoder3.0";
"decoder1.0" -> "decoder5.0";
"decoder3.0" -> "decoder6.0";
}
Root Decoder에서 두 Host Bridge Switch Decoder를 거쳐 각각의 Endpoint Decoder로 이어지는 관계입니다.
Memory Region과 DAX Region
399-447Memory Region은 fabric의 CXL port 집합을 IO Memory Resource와 연결하는 logical construct입니다. 최종적으로 이 장치의 memory를 DAX Region을 통해 DAX subsystem에 노출하는 데 사용합니다.
# ls /sys/bus/cxl/devices/region0/
access0 devtype modalias subsystem uuid
access1 driver mode target0
commit interleave_granularity resource target1
dax_region0 interleave_ways size uevent
BIOS/EFI가 decoder를 프로그래밍했다면 endpoint probe 중 memory region을 만들 수 있습니다. 또는 Root Decoder의 `create_ram_region`이나 `create_pmem_region` interface를 통해 수동으로 만들 수 있습니다.
Memory Region의 interleave 설정은 Interleave Set의 구성을 설명하며 Endpoint Decoder의 interleave 설정에서도 같은 값을 볼 수 있어야 합니다.
.. kernel-render:: DOT
:alt: Digraph of CXL memory region relationships between root and endpoint decoders.
:caption: Regions are created based on root decoder configurations. Endpoint decoders
must be programmed with the same interleave settings as the region.
digraph foo {
"root0" -> "decoder0.0";
"decoder0.0" -> "region0";
"region0" -> "decoder5.0";
"region0" -> "decoder6.0";
}
Root Decoder 구성으로 만든 region0이 같은 interleave 설정의 두 Endpoint Decoder와 연결되는 구조입니다.
DAX Region은 CXL Memory Region을 DAX 장치로 변환합니다. DAX 장치는 file descriptor interface로 직접 접근하거나 DAX kmem driver를 통해 System RAM으로 변환할 수 있습니다.
# ls /sys/bus/cxl/devices/dax_region0/
dax0.0 devtype modalias uevent
dax_region driver subsystem
Mailbox interface
448-460각 장치의 mailbox command interface는 다음 경로에 노출됩니다.
/dev/cxl/mem0
/dev/cxl/mem1
이 mailbox는 사양에 정의된 모든 command를 받을 수 있습니다. raw 또는 custom command는 build 설정 `CXL_MEM_RAW_COMMANDS`가 켜진 경우에만 보낼 수 있습니다.
이 기능은 debug·개발 interface이며 vendor-specific command를 만드는 공식 지원 수단이 아닙니다. 그런 용도에는 `fwctl` subsystem을 사용합니다.
Runtime Programming과 Auto Decoder
461-495probe 중 반드시 프로그래밍돼 있어야 하는 decoder는 Root Decoder뿐입니다. 실제로 Root Decoder는 ACPI CEDT CFMWS가 설명하는 Host Bridge 수준의 memory region과 interleave 구성을 나타내는 logical construct입니다.
플랫폼이 허용한다면 나머지 Switch 및 Endpoint Decoder는 사용자가 실행 중 프로그래밍할 수 있습니다. 이 상호작용이 Software Defined Memory 환경을 만듭니다. 실행 중 구성 방법은 `cxl-cli` 문서를 참고하십시오.
Auto Decoder는 BIOS/EFI가 부팅 때 프로그래밍한 decoder이며 거의 항상 잠겨 있어 변경할 수 없습니다. 플랫폼이 정적 구성을 사용하거나 CPU complex 안에서 CXL 범위를 벗어난 추가 controller programming이 필요해 동적 변경을 막는 경우에 사용합니다.
연결된 장치와 memory region이 문제없이 probe되면 Auto Decoder도 자동으로 probe됩니다. driver의 주된 책임은 실행 중 프로그래밍된 region과 decoder를 검증할 때처럼 fabric 구성이 타당한지 확인하는 것입니다.
Linux가 auto-decoder 구성을 검증하지 못하면 memory를 DAX 장치로 노출하지 않으며 page allocator에도 제공하지 못해 사실상 사용할 수 없게 됩니다.
Cross-Link First interleave
496-533Linux CXL driver는 Cross-Link First interleave를 지원합니다. driver가 decoder와 parent의 관계를 검증하므로 이 방식은 각 decoder 단계에서 interleave를 프로그래밍하는 방법을 정합니다.
Host Bridge 4개에 Endpoint 16개가 연결된 4x4 Cross-Link First 구성에서 root, Host Bridge, Endpoint의 ways와 granularity는 다음과 같습니다.
.. flat-table:: 4x4 cross-link first interleave settings
* - decoder
- ways
- granularity
* - root
- 4
- 256
* - host bridge
- 4
- 1024
* - endpoint
- 16
- 256
| decoder | ways | granularity |
|---|---|---|
| root | 4 | 256 |
| host bridge | 4 | 1024 |
| endpoint | 16 | 256 |
root에서는 각 접근을 `((HPA / 256) % 4)`번째 target Host Bridge로 routing합니다. Host Bridge 안에서는 `((HPA / 1024) % 4)`번째 target Endpoint로 보냅니다. 각 Endpoint는 장치 16개 전체 interleave set을 기준으로 변환합니다.
불균형 interleave set은 지원하지 않습니다. 계층에서 같은 위치에 있는 decoder, 예를 들어 모든 Host Bridge Decoder는 ways와 granularity가 같아야 합니다.
Root 수준 interleave
534-589Root Decoder interleave는 CEDT의 CFMWS field가 정의합니다. CEDT는 사용자가 실행 중 memory를 interleave 또는 non-interleave로 online할지 선택하게 하려는 목적으로 같은 물리 용량을 설명하는 CFMWS 구성을 여러 개 정의할 수 있습니다.
Subtable Type : 01 [CXL Fixed Memory Window Structure]
Window base address : 0000000100000000
Window size : 0000000100000000
Interleave Members (2^n) : 00
Interleave Arithmetic : 00
First Target : 00000007
Subtable Type : 01 [CXL Fixed Memory Window Structure]
Window base address : 0000000200000000
Window size : 0000000100000000
Interleave Members (2^n) : 00
Interleave Arithmetic : 00
First Target : 00000006
Subtable Type : 01 [CXL Fixed Memory Window Structure]
Window base address : 0000000300000000
Window size : 0000000200000000
Interleave Members (2^n) : 01
Interleave Arithmetic : 00
First Target : 00000007
Next Target : 00000006
이 예에서 CFMWS는 각 Host Bridge에 대한 서로 분리된 non-interleave 4 GiB region 두 개와 두 Host Bridge 모두를 target으로 하는 interleave 8 GiB region 하나를 정의합니다. 결과적으로 root에는 Root Decoder 세 개가 나타납니다.
# ls /sys/bus/cxl/devices/root0/decoder*
decoder0.0 decoder0.1 decoder0.2
# cat /sys/bus/cxl/devices/decoder0.0/target_list start size
7
0x100000000
0x100000000
# cat /sys/bus/cxl/devices/decoder0.1/target_list start size
6
0x200000000
0x100000000
# cat /sys/bus/cxl/devices/decoder0.2/target_list start size
7,6
0x300000000
0x200000000
이 decoder들은 실행 중 프로그래밍할 수 없습니다. Memory Region을 생성해 Switch 및 Endpoint Decoder에 실행 중 설정을 프로그래밍하고 이 memory를 online하는 데 사용합니다.
Host Bridge와 Switch 프로그래밍
590-604Host Bridge와 Switch Decoder는 다음 field로 프로그래밍합니다.
- `start`: memory region에 연결된 HPA region
- `size`: region 크기
- `target_list`: downstream port 목록
- `interleave_ways`: interleave할 downstream port 수
- `interleave_granularity`: interleave granularity
Linux는 Switch Decoder의 `interleave_granularity`가 upstream port 연결에서 유도되기를 기대합니다. Cross-Link First 구성에서는 decoder의 granularity가 `parent_interleave_granularity * parent_interleave_ways`와 같습니다.
Endpoint 프로그래밍
605-621Endpoint Decoder도 Host Bridge 및 Switch Decoder와 비슷하게 프로그래밍하지만 ways와 granularity는 연결된 Memory Region이 정의한 전체 interleave set을 따릅니다.
- `start`: memory region에 연결된 HPA region
- `size`: region 크기
- `interleave_ways`: interleave set의 Endpoint 수
- `interleave_granularity`: interleave granularity
Endpoint Decoder는 이 설정을 사용해 memory 요청을 HPA에서 DPA로 변환하므로 전체 interleave set을 알아야 합니다.
Linux는 불균형 interleave 구성을 지원하지 않으므로 한 set의 모든 Endpoint는 ways와 granularity가 같아야 합니다.
예제 구성 문서
622-630하위 문서는 single device, Host Bridge interleave, Host Bridge 내부 interleave와 다중 interleave 예제를 제공합니다.
.. toctree::
:maxdepth: 1
example-configurations/single-device.rst
example-configurations/hb-interleave.rst
example-configurations/intra-hb-interleave.rst
example-configurations/multi-interleave.rst
요약과 해설
cxl-driver.rst:1-630이 문서는 Linux CXL driver가 sysfs와 `/dev/cxl/`에 제시하는 fabric object의 관계를 따라갑니다. Root, Host Bridge, Endpoint와 memdev에서 HDM Decoder, Memory Region, DAX Region으로 이어지는 구성과 Cross-Link First interleave 프로그래밍 규칙을 설명합니다. 영어 원문 전체와 한국어 전문 번역을 함께 제공하며 DOT 원문, 구조화 도식, 표, 명령, symbol, source path와 원문 줄 좌표를 보존합니다.