mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00

This patch corrects several typographical issues and improves phrasing in memory-devices.rst: - Fixes duplicate word ("1 one") and adjusts phrasing for clarity. - Adds missing hyphen in "on-device". - Corrects "a give memory device" to "a given memory device". - fix singular/plural "decoder resource" -> "decoder resources". - Clarifies "spans to Host Bridges" -> "spans two Host Bridges". - change "at a" -> "a" These changes improve readability and accuracy of the documentation. Signed-off-by: Alok Tiwari <alok.a.tiwari@oracle.com> Reviewed-by: Randy Dunlap <rdunlap@infradead.org> Reviewed-by: Gregory Price <gourry@gourry.net> Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com> Link: https://patch.msgid.link/20250609171130.2375901-1-alok.a.tiwari@oracle.com Signed-off-by: Dave Jiang <dave.jiang@intel.com>
415 lines
13 KiB
ReStructuredText
415 lines
13 KiB
ReStructuredText
.. SPDX-License-Identifier: GPL-2.0
|
|
.. include:: <isonum.txt>
|
|
|
|
===============================================
|
|
Compute Express Link Driver Theory of Operation
|
|
===============================================
|
|
|
|
A Compute Express Link Memory Device is a CXL component that implements the
|
|
CXL.mem protocol. It contains some amount of volatile memory, persistent memory,
|
|
or both. It is enumerated as a PCI device for configuration and passing
|
|
messages over an MMIO mailbox. Its contribution to the System Physical
|
|
Address space is handled via HDM (Host Managed Device Memory) decoders
|
|
that optionally define a device's contribution to an interleaved address
|
|
range across multiple devices underneath a host-bridge or interleaved
|
|
across host-bridges.
|
|
|
|
The CXL Bus
|
|
===========
|
|
Similar to how a RAID driver takes disk objects and assembles them into a new
|
|
logical device, the CXL subsystem is tasked to take PCIe and ACPI objects and
|
|
assemble them into a CXL.mem decode topology. The need for runtime configuration
|
|
of the CXL.mem topology is also similar to RAID in that different environments
|
|
with the same hardware configuration may decide to assemble the topology in
|
|
contrasting ways. One may choose performance (RAID0) striping memory across
|
|
multiple Host Bridges and endpoints while another may opt for fault tolerance
|
|
and disable any striping in the CXL.mem topology.
|
|
|
|
Platform firmware enumerates a menu of interleave options at the "CXL root port"
|
|
(Linux term for the top of the CXL decode topology). From there, PCIe topology
|
|
dictates which endpoints can participate in which Host Bridge decode regimes.
|
|
Each PCIe Switch in the path between the root and an endpoint introduces a point
|
|
at which the interleave can be split. For example, platform firmware may say a
|
|
given range only decodes to one Host Bridge, but that Host Bridge may in turn
|
|
interleave cycles across multiple Root Ports. An intervening Switch between a
|
|
port and an endpoint may interleave cycles across multiple Downstream Switch
|
|
Ports, etc.
|
|
|
|
Here is a sample listing of a CXL topology defined by 'cxl_test'. The 'cxl_test'
|
|
module generates an emulated CXL topology of 2 Host Bridges each with 2 Root
|
|
Ports. Each of those Root Ports are connected to 2-way switches with endpoints
|
|
connected to those downstream ports for a total of 8 endpoints::
|
|
|
|
# cxl list -BEMPu -b cxl_test
|
|
{
|
|
"bus":"root3",
|
|
"provider":"cxl_test",
|
|
"ports:root3":[
|
|
{
|
|
"port":"port5",
|
|
"host":"cxl_host_bridge.1",
|
|
"ports:port5":[
|
|
{
|
|
"port":"port8",
|
|
"host":"cxl_switch_uport.1",
|
|
"endpoints:port8":[
|
|
{
|
|
"endpoint":"endpoint9",
|
|
"host":"mem2",
|
|
"memdev":{
|
|
"memdev":"mem2",
|
|
"pmem_size":"256.00 MiB (268.44 MB)",
|
|
"ram_size":"256.00 MiB (268.44 MB)",
|
|
"serial":"0x1",
|
|
"numa_node":1,
|
|
"host":"cxl_mem.1"
|
|
}
|
|
},
|
|
{
|
|
"endpoint":"endpoint15",
|
|
"host":"mem6",
|
|
"memdev":{
|
|
"memdev":"mem6",
|
|
"pmem_size":"256.00 MiB (268.44 MB)",
|
|
"ram_size":"256.00 MiB (268.44 MB)",
|
|
"serial":"0x5",
|
|
"numa_node":1,
|
|
"host":"cxl_mem.5"
|
|
}
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"port":"port12",
|
|
"host":"cxl_switch_uport.3",
|
|
"endpoints:port12":[
|
|
{
|
|
"endpoint":"endpoint17",
|
|
"host":"mem8",
|
|
"memdev":{
|
|
"memdev":"mem8",
|
|
"pmem_size":"256.00 MiB (268.44 MB)",
|
|
"ram_size":"256.00 MiB (268.44 MB)",
|
|
"serial":"0x7",
|
|
"numa_node":1,
|
|
"host":"cxl_mem.7"
|
|
}
|
|
},
|
|
{
|
|
"endpoint":"endpoint13",
|
|
"host":"mem4",
|
|
"memdev":{
|
|
"memdev":"mem4",
|
|
"pmem_size":"256.00 MiB (268.44 MB)",
|
|
"ram_size":"256.00 MiB (268.44 MB)",
|
|
"serial":"0x3",
|
|
"numa_node":1,
|
|
"host":"cxl_mem.3"
|
|
}
|
|
}
|
|
]
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"port":"port4",
|
|
"host":"cxl_host_bridge.0",
|
|
"ports:port4":[
|
|
{
|
|
"port":"port6",
|
|
"host":"cxl_switch_uport.0",
|
|
"endpoints:port6":[
|
|
{
|
|
"endpoint":"endpoint7",
|
|
"host":"mem1",
|
|
"memdev":{
|
|
"memdev":"mem1",
|
|
"pmem_size":"256.00 MiB (268.44 MB)",
|
|
"ram_size":"256.00 MiB (268.44 MB)",
|
|
"serial":"0",
|
|
"numa_node":0,
|
|
"host":"cxl_mem.0"
|
|
}
|
|
},
|
|
{
|
|
"endpoint":"endpoint14",
|
|
"host":"mem5",
|
|
"memdev":{
|
|
"memdev":"mem5",
|
|
"pmem_size":"256.00 MiB (268.44 MB)",
|
|
"ram_size":"256.00 MiB (268.44 MB)",
|
|
"serial":"0x4",
|
|
"numa_node":0,
|
|
"host":"cxl_mem.4"
|
|
}
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"port":"port10",
|
|
"host":"cxl_switch_uport.2",
|
|
"endpoints:port10":[
|
|
{
|
|
"endpoint":"endpoint16",
|
|
"host":"mem7",
|
|
"memdev":{
|
|
"memdev":"mem7",
|
|
"pmem_size":"256.00 MiB (268.44 MB)",
|
|
"ram_size":"256.00 MiB (268.44 MB)",
|
|
"serial":"0x6",
|
|
"numa_node":0,
|
|
"host":"cxl_mem.6"
|
|
}
|
|
},
|
|
{
|
|
"endpoint":"endpoint11",
|
|
"host":"mem3",
|
|
"memdev":{
|
|
"memdev":"mem3",
|
|
"pmem_size":"256.00 MiB (268.44 MB)",
|
|
"ram_size":"256.00 MiB (268.44 MB)",
|
|
"serial":"0x2",
|
|
"numa_node":0,
|
|
"host":"cxl_mem.2"
|
|
}
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
|
|
In that listing each "root", "port", and "endpoint" object correspond a kernel
|
|
'struct cxl_port' object. A 'cxl_port' is a device that can decode CXL.mem to
|
|
its descendants. So "root" claims non-PCIe enumerable platform decode ranges and
|
|
decodes them to "ports", "ports" decode to "endpoints", and "endpoints"
|
|
represent the decode from SPA (System Physical Address) to DPA (Device Physical
|
|
Address).
|
|
|
|
Continuing the RAID analogy, disks have both topology metadata and on-device
|
|
metadata that determine RAID set assembly. CXL Port topology and CXL Port link
|
|
status is metadata for CXL.mem set assembly. The CXL Port topology is enumerated
|
|
by the arrival of a CXL.mem device. I.e. unless and until the PCIe core attaches
|
|
the cxl_pci driver to a CXL Memory Expander there is no role for CXL Port
|
|
objects. Conversely for hot-unplug / removal scenarios, there is no need for
|
|
the Linux PCI core to tear down switch-level CXL resources because the endpoint
|
|
->remove() event cleans up the port data that was established to support that
|
|
Memory Expander.
|
|
|
|
The port metadata and potential decode schemes that a given memory device may
|
|
participate can be determined via a command like::
|
|
|
|
# cxl list -BDMu -d root -m mem3
|
|
{
|
|
"bus":"root3",
|
|
"provider":"cxl_test",
|
|
"decoders:root3":[
|
|
{
|
|
"decoder":"decoder3.1",
|
|
"resource":"0x8030000000",
|
|
"size":"512.00 MiB (536.87 MB)",
|
|
"volatile_capable":true,
|
|
"nr_targets":2
|
|
},
|
|
{
|
|
"decoder":"decoder3.3",
|
|
"resource":"0x8060000000",
|
|
"size":"512.00 MiB (536.87 MB)",
|
|
"pmem_capable":true,
|
|
"nr_targets":2
|
|
},
|
|
{
|
|
"decoder":"decoder3.0",
|
|
"resource":"0x8020000000",
|
|
"size":"256.00 MiB (268.44 MB)",
|
|
"volatile_capable":true,
|
|
"nr_targets":1
|
|
},
|
|
{
|
|
"decoder":"decoder3.2",
|
|
"resource":"0x8050000000",
|
|
"size":"256.00 MiB (268.44 MB)",
|
|
"pmem_capable":true,
|
|
"nr_targets":1
|
|
}
|
|
],
|
|
"memdevs:root3":[
|
|
{
|
|
"memdev":"mem3",
|
|
"pmem_size":"256.00 MiB (268.44 MB)",
|
|
"ram_size":"256.00 MiB (268.44 MB)",
|
|
"serial":"0x2",
|
|
"numa_node":0,
|
|
"host":"cxl_mem.2"
|
|
}
|
|
]
|
|
}
|
|
|
|
...which queries the CXL topology to ask "given CXL Memory Expander with a kernel
|
|
device name of 'mem3' which platform level decode ranges may this device
|
|
participate". A given expander can participate in multiple CXL.mem interleave
|
|
sets simultaneously depending on how many decoder resources it has. In this
|
|
example mem3 can participate in one or more of a PMEM interleave that spans two
|
|
Host Bridges, a PMEM interleave that targets a single Host Bridge, a Volatile
|
|
memory interleave that spans 2 Host Bridges, and a Volatile memory interleave
|
|
that only targets a single Host Bridge.
|
|
|
|
Conversely the memory devices that can participate in a given platform level
|
|
decode scheme can be determined via a command like the following::
|
|
|
|
# cxl list -MDu -d 3.2
|
|
[
|
|
{
|
|
"memdevs":[
|
|
{
|
|
"memdev":"mem1",
|
|
"pmem_size":"256.00 MiB (268.44 MB)",
|
|
"ram_size":"256.00 MiB (268.44 MB)",
|
|
"serial":"0",
|
|
"numa_node":0,
|
|
"host":"cxl_mem.0"
|
|
},
|
|
{
|
|
"memdev":"mem5",
|
|
"pmem_size":"256.00 MiB (268.44 MB)",
|
|
"ram_size":"256.00 MiB (268.44 MB)",
|
|
"serial":"0x4",
|
|
"numa_node":0,
|
|
"host":"cxl_mem.4"
|
|
},
|
|
{
|
|
"memdev":"mem7",
|
|
"pmem_size":"256.00 MiB (268.44 MB)",
|
|
"ram_size":"256.00 MiB (268.44 MB)",
|
|
"serial":"0x6",
|
|
"numa_node":0,
|
|
"host":"cxl_mem.6"
|
|
},
|
|
{
|
|
"memdev":"mem3",
|
|
"pmem_size":"256.00 MiB (268.44 MB)",
|
|
"ram_size":"256.00 MiB (268.44 MB)",
|
|
"serial":"0x2",
|
|
"numa_node":0,
|
|
"host":"cxl_mem.2"
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"root decoders":[
|
|
{
|
|
"decoder":"decoder3.2",
|
|
"resource":"0x8050000000",
|
|
"size":"256.00 MiB (268.44 MB)",
|
|
"pmem_capable":true,
|
|
"nr_targets":1
|
|
}
|
|
]
|
|
}
|
|
]
|
|
|
|
...where the naming scheme for decoders is "decoder<port_id>.<instance_id>".
|
|
|
|
Driver Infrastructure
|
|
=====================
|
|
|
|
This section covers the driver infrastructure for a CXL memory device.
|
|
|
|
CXL Memory Device
|
|
-----------------
|
|
|
|
.. kernel-doc:: drivers/cxl/pci.c
|
|
:doc: cxl pci
|
|
|
|
.. kernel-doc:: drivers/cxl/pci.c
|
|
:internal:
|
|
|
|
.. kernel-doc:: drivers/cxl/mem.c
|
|
:doc: cxl mem
|
|
|
|
.. kernel-doc:: drivers/cxl/cxlmem.h
|
|
:internal:
|
|
|
|
.. kernel-doc:: drivers/cxl/core/memdev.c
|
|
:identifiers:
|
|
|
|
CXL Port
|
|
--------
|
|
.. kernel-doc:: drivers/cxl/port.c
|
|
:doc: cxl port
|
|
|
|
CXL Core
|
|
--------
|
|
.. kernel-doc:: drivers/cxl/cxl.h
|
|
:doc: cxl objects
|
|
|
|
.. kernel-doc:: drivers/cxl/cxl.h
|
|
:internal:
|
|
|
|
.. kernel-doc:: drivers/cxl/acpi.c
|
|
:identifiers: add_cxl_resources
|
|
|
|
.. kernel-doc:: drivers/cxl/core/hdm.c
|
|
:doc: cxl core hdm
|
|
|
|
.. kernel-doc:: drivers/cxl/core/hdm.c
|
|
:identifiers:
|
|
|
|
.. kernel-doc:: drivers/cxl/core/cdat.c
|
|
:identifiers:
|
|
|
|
.. kernel-doc:: drivers/cxl/core/port.c
|
|
:doc: cxl core
|
|
|
|
.. kernel-doc:: drivers/cxl/core/port.c
|
|
:identifiers:
|
|
|
|
.. kernel-doc:: drivers/cxl/core/pci.c
|
|
:doc: cxl core pci
|
|
|
|
.. kernel-doc:: drivers/cxl/core/pci.c
|
|
:identifiers:
|
|
|
|
.. kernel-doc:: drivers/cxl/core/pmem.c
|
|
:doc: cxl pmem
|
|
|
|
.. kernel-doc:: drivers/cxl/core/pmem.c
|
|
:identifiers:
|
|
|
|
.. kernel-doc:: drivers/cxl/core/regs.c
|
|
:doc: cxl registers
|
|
|
|
.. kernel-doc:: drivers/cxl/core/regs.c
|
|
:identifiers:
|
|
|
|
.. kernel-doc:: drivers/cxl/core/mbox.c
|
|
:doc: cxl mbox
|
|
|
|
.. kernel-doc:: drivers/cxl/core/mbox.c
|
|
:identifiers:
|
|
|
|
.. kernel-doc:: drivers/cxl/core/features.c
|
|
:doc: cxl features
|
|
|
|
See :c:func:`devm_cxl_setup_features` for API details.
|
|
|
|
CXL Regions
|
|
-----------
|
|
.. kernel-doc:: drivers/cxl/core/region.c
|
|
:doc: cxl core region
|
|
|
|
.. kernel-doc:: drivers/cxl/core/region.c
|
|
:identifiers:
|
|
|
|
External Interfaces
|
|
===================
|
|
|
|
CXL IOCTL Interface
|
|
-------------------
|
|
|
|
.. kernel-doc:: include/uapi/linux/cxl_mem.h
|
|
:doc: UAPI
|
|
|
|
.. kernel-doc:: include/uapi/linux/cxl_mem.h
|
|
:internal:
|