From: Yukiya Takaki <fj2110jc@fujitsu.com>
To: qemu-devel@nongnu.org
Cc: Yukiya Takaki <fj2110jc@fujitsu.com>,
"Michael S. Tsirkin" <mst@redhat.com>,
Ani Sinha <anisinha@redhat.com>, Anisa Su <anisa.su@samsung.com>,
Igor Mammedov <imammedo@redhat.com>,
Jonathan Cameron <jic23@kernel.org>,
Junjie Cao <junjie.cao@intel.com>,
Paolo Bonzini <pbonzini@redhat.com>,
Peter Maydell <peter.maydell@linaro.org>,
Richard Henderson <richard.henderson@linaro.org>,
linux-cxl@vger.kernel.org, qemu-arm@nongnu.org, "Wolski,
Tomasz" <tomasz.wolski@fujitsu.com>,
lizhijian@fujitsu.com, y-goto@fujitsu.com,
yukiya.takaki@gmail.com
Subject: [PATCH RFC 0/7] QEMU/hw/cxl: Allow CXL Type 3 memory regions to be initialized at guest boot
Date: Mon, 26 Oct 2026 19:03:21 +0900 [thread overview]
Message-ID: <cover.1793003983.git.fj2110jc@fujitsu.com> (raw)
Hello everyone,
I’m a student intern, and this is my first time sending patches to an open source mailing list.
This patch series configures QEMU’s CXL Type 3 devices so that guest operating systems can automatically discover
and create CXL regions during boot, aligning QEMU’s behavior with real hardware.
Background and motivation
Currently, during guest boot QEMU does not provide the information or register programming needed for the guest OS
to initialize CXL Type 3 memory, so using it still requires an explicit action in the guest (for example, running the cxl create-region command).
By contrast, on some physical systems the firmware automatically allocates CXL memory ranges and exposes them to the OS,
allowing the Linux CXL driver to discover and create regions during boot.
This patch series is a first, experimental attempt to reproduce that behavior in QEMU.
Some parts of this implementation are based on Li, Zhijian’s work in:
https://github.com/zhijianli88/qemu/tree/program-decoder-v2
I would like to ask for feedback on whether this approach makes sense and whether I should continue to enhance it.
Approach
This patch first adds a program_hdm_decoder option to cxl-type3.
When program-hdm-decoder is enabled on cxl-type3, QEMU will:
1) program endpoint/host-bridge HDM decoder state,
2) expose Type 3 ranges as E820_SOFT_RESERVED on x86,
3) create memory-only NUMA nodes for those ranges,
4) emit SRAT memory-affinity entries mapping each Type 3 HPA range to its node ID
On real hardware, HDM decoder programming and memory layout are typically handled by firmware, so they would ideally be managed by SeaBIOS.
However, in the current QEMU/SeaBIOS model, E820 and SRAT are built on the QEMU side, and pushing HDM decoder programming
into SeaBIOS would introduce additional complexity and risk inconsistencies.
Testing
We ran tests in the following environment and confirmed that CXL regions were created at boot, NUMA nodes were set up,
and E820_SOFT_RESERVED entries appeared in the E820 table:
- BIOS: SeaBIOS c2a33ad9ad1452e23b41c4ac44a3bc6be8ebc4cf
- CXL memory: 4 GB
- CFMWS: 4 GB
- Host bridge: 1
The following is the startup script.
sudo /path/to/qemu/build/qemu-system-x86_64 \
-name guest=cxl \
-nographic \
-machine q35,accel=tcg,nvdimm=on,cxl=on \
-cpu max -smp 4,sockets=4,cores=1,threads=1 \
-m size=4G,slots=10,maxmem=20G \
-drive file=/path/to/image.qcow2,format=qcow2,index=0,media=disk,id=hd \
-bios /path/to/seabios/out/bios.bin \
-nic bridge,br=virbr0,model=e1000e,mac=52:54:00:b5:4e:7c \
-object memory-backend-ram,size=2G,id=m0 \
-object memory-backend-ram,size=2G,id=m1 \
-numa node,nodeid=0,cpus=0-1,memdev=m0 \
-numa node,nodeid=1,cpus=2-3,memdev=m1 \
-device pcie-root-port,id=pci-root,slot=4,bus=pcie.0,chassis=0 \
-device pxb-cxl,bus_nr=12,bus=pcie.0,id=cxl.1,hdm_for_passthrough=true \
-device cxl-rp,port=0,id=root_port13,bus=cxl.1,chassis=0,slot=2 \
-object memory-backend-ram,size=4G,share=on,id=vmem0 \
-device cxl-type3,bus=root_port13,volatile-memdev=vmem0,id=cxl-vmem0,program-hdm-decoder=true \
-M cxl-fmw.0.targets.0=cxl.1,cxl-fmw.0.size=4G,cxl-fmw.0.interleave-granularity=4k
Furthermore, we conducted the experiment in which we added two CXL Type3.
- CXL memory: 4 GB × 2
- CFMWS: 4 GB × 2
The following is the startup script.
sudo /path/to/qemu/build/qemu-system-x86_64 \
-name guest=cxl \
-nographic \
-machine q35,accel=tcg,nvdimm=on,cxl=on,hmat=on \
-cpu max -smp 4,sockets=4,cores=1,threads=1 \
-m size=4G,slots=10,maxmem=20G \
-drive file=/path/to/image.qcow2,format=qcow2,index=0,media=disk,id=hd \
-bios /path/to/seabios/out/bios.bin \
-nic bridge,br=virbr0,model=e1000e,mac=52:54:00:b5:4e:7c \
-object memory-backend-ram,size=2G,id=m0 \
-object memory-backend-ram,size=2G,id=m1 \
-numa node,nodeid=0,cpus=0-1,memdev=m0 \
-numa node,nodeid=1,cpus=2-3,memdev=m1 \
-device pcie-root-port,id=pci-root,slot=4,bus=pcie.0,chassis=0 \
-device pcie-root-port,id=pci-root-net,chassis=5,slot=5,bus=pcie.0 \
-device pxb-cxl,bus_nr=12,bus=pcie.0,id=cxl.1,hdm_for_passthrough=true \
-device cxl-rp,port=0,id=root_port13,bus=cxl.1,chassis=0,slot=2 \
-device cxl-rp,port=3,id=root_port14,bus=cxl.1,chassis=2,slot=4 \
-object memory-backend-ram,size=4G,share=on,id=vmem0 \
-object memory-backend-ram,size=4G,share=on,id=vmem1 \
-device cxl-type3,bus=root_port13,volatile-memdev=vmem0,id=cxl-vmem0,program-hdm-decoder=true \
-device cxl-type3,bus=root_port14,volatile-memdev=vmem1,id=cxl-vmem1,program-hdm-decoder=true \
-M cxl-fmw.0.targets.0=cxl.1,cxl-fmw.0.size=4G,cxl-fmw.0.interleave-granularity=4k,cxl-fmw.1.targets.0=cxl.1,cxl-fmw.1.size=4G,cxl-fmw.1.interleave-granularity=4k
How to use
Specify the following parameters when starting QEMU:
- bios <SeaBIOS binary that includes commit c2a33ad9ad1452e23b41c4ac44a3bc6be8ebc4cf> to ensure that E820_SOFT_RESERVED entries are exposed
- Add hmat=on to the -machine option [1]
- Add program-hdm-decoder=true to each -device cxl-type3 option
[1] On Linux, the kernel first checks E820_SOFT_RESERVED ranges. When multiple CXL Type 3 devices share a contiguous HPA range,
these ranges tend to be merged into a single region, so the CXL driver cannot reliably initialize per‑device regions based on E820 alone.
SRAT entries for CXL memory are therefore needed, and the guest seems to discard SRAT when `hmat=on` is not specified,
so HMAT must be enabled.
QEMU base commit: bddb785e791e415db38884848d068457e226f5e3
TODO
With the current implementation of this patch, the following configurations are either not supported or have not been sufficiently tested.
As a result, automatic creation of CXL regions in the guest OS may fail:
- A CXL persistent memory device is included
- Interleaved configurations
- Cases where the memory size specified by CFMWS does not match the size of the CXL Type 3 backend memory
- Configurations where CXL memory is attached via a switch
- Multi-target CFMWS environments
- ARM environments
- HMAT does not yet include information about CXL memory devices
The following behaviors are also provisional implementations and may need further refinement:
- A new NUMA node ID is assigned to each CXL memory device. This should be improved either to reflect more accurate NUMA distances for CXL memory,
or to allow the NUMA node IDs to be specified by the user.
- Assignment of CXL Type 3 devices to CFMWS address ranges. On physical systems, platform firmware typically generates CFMWS entries
based on the detected CXL topology and its address-space allocation. In QEMU, however, CFMWS entries are configured explicitly
through machine options. The current implementation therefore has to infer which CFMWS range should be used for each Type 3 device.
This selection logic may need further refinement. Possible approaches include improving the selection and validation logic,
adding an explicit option to associate each Type 3 device with a CFMWS entry,
or generating CFMWS entries automatically from the configured CXL topology and devices.
- HDM decoder reset sequencing and state reconstruction.
The current implementation prevents the host bridge HDM decoder configuration from being overwritten later in the same reset
by moving the common initialization of the host bridge component registers from the reset path to the realization path.
However, ideally, after the registers have been restored to their reset values, the host bridge HDM decoder configuration
automatically programmed by QEMU should be reconstructed as part of reset processing.
Thanks,
------
Yukiya Takaki (7):
QEMU/hw/cxl: add program-hdm-decoder option for CXL Type 3 devices
QEMU/hw/cxl:add HPA offset tracking for CXL Type 3 devices
QEMU: hw/cxl: add helper to get HPA range for CXL Type 3
QEMU/hw/cxl: auto‑program HDM decoders for CXL Type 3
QEMU/hw/cxl: expose CXL Type 3 ranges as E820_SOFT_RESERVED on x86
QEMU/hw/cxl: Create NUMA nodes for CXL Type 3 memory
add CXL Type 3 memory ranges to SRAT
hw/acpi/cxl_type3.c | 30 +++++
hw/acpi/meson.build | 1 +
hw/arm/cxl.c | 10 ++
hw/arm/meson.build | 2 +
hw/cxl/cxl-host.c | 63 ++++++++++
hw/i386/acpi-build.c | 7 ++
hw/i386/cxl.c | 11 ++
hw/i386/meson.build | 1 +
hw/i386/pc.c | 2 +
hw/mem/cxl_type3.c | 177 ++++++++++++++++++++++++++++
hw/pci-bridge/pci_expander_bridge.c | 13 +-
include/hw/cxl/cxl.h | 2 +
include/hw/cxl/cxl_device.h | 6 +
include/hw/cxl/cxl_host.h | 3 +
include/hw/mem/cxl_type3.h | 8 ++
15 files changed, 334 insertions(+), 2 deletions(-)
create mode 100644 hw/acpi/cxl_type3.c
create mode 100644 hw/arm/cxl.c
create mode 100644 hw/i386/cxl.c
create mode 100644 include/hw/mem/cxl_type3.h
--
2.52.0
WARNING: multiple messages have this Message-ID (diff)
From: Yukiya Takaki via qemu development <qemu-devel@nongnu.org>
To: qemu-devel@nongnu.org
Cc: Yukiya Takaki <fj2110jc@fujitsu.com>,
"Michael S. Tsirkin" <mst@redhat.com>,
Ani Sinha <anisinha@redhat.com>, Anisa Su <anisa.su@samsung.com>,
Igor Mammedov <imammedo@redhat.com>,
Jonathan Cameron <jic23@kernel.org>,
Junjie Cao <junjie.cao@intel.com>,
Paolo Bonzini <pbonzini@redhat.com>,
Peter Maydell <peter.maydell@linaro.org>,
Richard Henderson <richard.henderson@linaro.org>,
linux-cxl@vger.kernel.org, qemu-arm@nongnu.org, "Wolski,
Tomasz" <tomasz.wolski@fujitsu.com>,
lizhijian@fujitsu.com, y-goto@fujitsu.com,
yukiya.takaki@gmail.com
Subject: [PATCH RFC 0/7] QEMU/hw/cxl: Allow CXL Type 3 memory regions to be initialized at guest boot
Date: Mon, 26 Oct 2026 19:03:21 +0900 [thread overview]
Message-ID: <cover.1793003983.git.fj2110jc@fujitsu.com> (raw)
Hello everyone,
I’m a student intern, and this is my first time sending patches to an open source mailing list.
This patch series configures QEMU’s CXL Type 3 devices so that guest operating systems can automatically discover
and create CXL regions during boot, aligning QEMU’s behavior with real hardware.
Background and motivation
Currently, during guest boot QEMU does not provide the information or register programming needed for the guest OS
to initialize CXL Type 3 memory, so using it still requires an explicit action in the guest (for example, running the cxl create-region command).
By contrast, on some physical systems the firmware automatically allocates CXL memory ranges and exposes them to the OS,
allowing the Linux CXL driver to discover and create regions during boot.
This patch series is a first, experimental attempt to reproduce that behavior in QEMU.
Some parts of this implementation are based on Li, Zhijian’s work in:
https://github.com/zhijianli88/qemu/tree/program-decoder-v2
I would like to ask for feedback on whether this approach makes sense and whether I should continue to enhance it.
Approach
This patch first adds a program_hdm_decoder option to cxl-type3.
When program-hdm-decoder is enabled on cxl-type3, QEMU will:
1) program endpoint/host-bridge HDM decoder state,
2) expose Type 3 ranges as E820_SOFT_RESERVED on x86,
3) create memory-only NUMA nodes for those ranges,
4) emit SRAT memory-affinity entries mapping each Type 3 HPA range to its node ID
On real hardware, HDM decoder programming and memory layout are typically handled by firmware, so they would ideally be managed by SeaBIOS.
However, in the current QEMU/SeaBIOS model, E820 and SRAT are built on the QEMU side, and pushing HDM decoder programming
into SeaBIOS would introduce additional complexity and risk inconsistencies.
Testing
We ran tests in the following environment and confirmed that CXL regions were created at boot, NUMA nodes were set up,
and E820_SOFT_RESERVED entries appeared in the E820 table:
- BIOS: SeaBIOS c2a33ad9ad1452e23b41c4ac44a3bc6be8ebc4cf
- CXL memory: 4 GB
- CFMWS: 4 GB
- Host bridge: 1
The following is the startup script.
sudo /path/to/qemu/build/qemu-system-x86_64 \
-name guest=cxl \
-nographic \
-machine q35,accel=tcg,nvdimm=on,cxl=on \
-cpu max -smp 4,sockets=4,cores=1,threads=1 \
-m size=4G,slots=10,maxmem=20G \
-drive file=/path/to/image.qcow2,format=qcow2,index=0,media=disk,id=hd \
-bios /path/to/seabios/out/bios.bin \
-nic bridge,br=virbr0,model=e1000e,mac=52:54:00:b5:4e:7c \
-object memory-backend-ram,size=2G,id=m0 \
-object memory-backend-ram,size=2G,id=m1 \
-numa node,nodeid=0,cpus=0-1,memdev=m0 \
-numa node,nodeid=1,cpus=2-3,memdev=m1 \
-device pcie-root-port,id=pci-root,slot=4,bus=pcie.0,chassis=0 \
-device pxb-cxl,bus_nr=12,bus=pcie.0,id=cxl.1,hdm_for_passthrough=true \
-device cxl-rp,port=0,id=root_port13,bus=cxl.1,chassis=0,slot=2 \
-object memory-backend-ram,size=4G,share=on,id=vmem0 \
-device cxl-type3,bus=root_port13,volatile-memdev=vmem0,id=cxl-vmem0,program-hdm-decoder=true \
-M cxl-fmw.0.targets.0=cxl.1,cxl-fmw.0.size=4G,cxl-fmw.0.interleave-granularity=4k
Furthermore, we conducted the experiment in which we added two CXL Type3.
- CXL memory: 4 GB × 2
- CFMWS: 4 GB × 2
The following is the startup script.
sudo /path/to/qemu/build/qemu-system-x86_64 \
-name guest=cxl \
-nographic \
-machine q35,accel=tcg,nvdimm=on,cxl=on,hmat=on \
-cpu max -smp 4,sockets=4,cores=1,threads=1 \
-m size=4G,slots=10,maxmem=20G \
-drive file=/path/to/image.qcow2,format=qcow2,index=0,media=disk,id=hd \
-bios /path/to/seabios/out/bios.bin \
-nic bridge,br=virbr0,model=e1000e,mac=52:54:00:b5:4e:7c \
-object memory-backend-ram,size=2G,id=m0 \
-object memory-backend-ram,size=2G,id=m1 \
-numa node,nodeid=0,cpus=0-1,memdev=m0 \
-numa node,nodeid=1,cpus=2-3,memdev=m1 \
-device pcie-root-port,id=pci-root,slot=4,bus=pcie.0,chassis=0 \
-device pcie-root-port,id=pci-root-net,chassis=5,slot=5,bus=pcie.0 \
-device pxb-cxl,bus_nr=12,bus=pcie.0,id=cxl.1,hdm_for_passthrough=true \
-device cxl-rp,port=0,id=root_port13,bus=cxl.1,chassis=0,slot=2 \
-device cxl-rp,port=3,id=root_port14,bus=cxl.1,chassis=2,slot=4 \
-object memory-backend-ram,size=4G,share=on,id=vmem0 \
-object memory-backend-ram,size=4G,share=on,id=vmem1 \
-device cxl-type3,bus=root_port13,volatile-memdev=vmem0,id=cxl-vmem0,program-hdm-decoder=true \
-device cxl-type3,bus=root_port14,volatile-memdev=vmem1,id=cxl-vmem1,program-hdm-decoder=true \
-M cxl-fmw.0.targets.0=cxl.1,cxl-fmw.0.size=4G,cxl-fmw.0.interleave-granularity=4k,cxl-fmw.1.targets.0=cxl.1,cxl-fmw.1.size=4G,cxl-fmw.1.interleave-granularity=4k
How to use
Specify the following parameters when starting QEMU:
- bios <SeaBIOS binary that includes commit c2a33ad9ad1452e23b41c4ac44a3bc6be8ebc4cf> to ensure that E820_SOFT_RESERVED entries are exposed
- Add hmat=on to the -machine option [1]
- Add program-hdm-decoder=true to each -device cxl-type3 option
[1] On Linux, the kernel first checks E820_SOFT_RESERVED ranges. When multiple CXL Type 3 devices share a contiguous HPA range,
these ranges tend to be merged into a single region, so the CXL driver cannot reliably initialize per‑device regions based on E820 alone.
SRAT entries for CXL memory are therefore needed, and the guest seems to discard SRAT when `hmat=on` is not specified,
so HMAT must be enabled.
QEMU base commit: bddb785e791e415db38884848d068457e226f5e3
TODO
With the current implementation of this patch, the following configurations are either not supported or have not been sufficiently tested.
As a result, automatic creation of CXL regions in the guest OS may fail:
- A CXL persistent memory device is included
- Interleaved configurations
- Cases where the memory size specified by CFMWS does not match the size of the CXL Type 3 backend memory
- Configurations where CXL memory is attached via a switch
- Multi-target CFMWS environments
- ARM environments
- HMAT does not yet include information about CXL memory devices
The following behaviors are also provisional implementations and may need further refinement:
- A new NUMA node ID is assigned to each CXL memory device. This should be improved either to reflect more accurate NUMA distances for CXL memory,
or to allow the NUMA node IDs to be specified by the user.
- Assignment of CXL Type 3 devices to CFMWS address ranges. On physical systems, platform firmware typically generates CFMWS entries
based on the detected CXL topology and its address-space allocation. In QEMU, however, CFMWS entries are configured explicitly
through machine options. The current implementation therefore has to infer which CFMWS range should be used for each Type 3 device.
This selection logic may need further refinement. Possible approaches include improving the selection and validation logic,
adding an explicit option to associate each Type 3 device with a CFMWS entry,
or generating CFMWS entries automatically from the configured CXL topology and devices.
- HDM decoder reset sequencing and state reconstruction.
The current implementation prevents the host bridge HDM decoder configuration from being overwritten later in the same reset
by moving the common initialization of the host bridge component registers from the reset path to the realization path.
However, ideally, after the registers have been restored to their reset values, the host bridge HDM decoder configuration
automatically programmed by QEMU should be reconstructed as part of reset processing.
Thanks,
------
Yukiya Takaki (7):
QEMU/hw/cxl: add program-hdm-decoder option for CXL Type 3 devices
QEMU/hw/cxl:add HPA offset tracking for CXL Type 3 devices
QEMU: hw/cxl: add helper to get HPA range for CXL Type 3
QEMU/hw/cxl: auto‑program HDM decoders for CXL Type 3
QEMU/hw/cxl: expose CXL Type 3 ranges as E820_SOFT_RESERVED on x86
QEMU/hw/cxl: Create NUMA nodes for CXL Type 3 memory
add CXL Type 3 memory ranges to SRAT
hw/acpi/cxl_type3.c | 30 +++++
hw/acpi/meson.build | 1 +
hw/arm/cxl.c | 10 ++
hw/arm/meson.build | 2 +
hw/cxl/cxl-host.c | 63 ++++++++++
hw/i386/acpi-build.c | 7 ++
hw/i386/cxl.c | 11 ++
hw/i386/meson.build | 1 +
hw/i386/pc.c | 2 +
hw/mem/cxl_type3.c | 177 ++++++++++++++++++++++++++++
hw/pci-bridge/pci_expander_bridge.c | 13 +-
include/hw/cxl/cxl.h | 2 +
include/hw/cxl/cxl_device.h | 6 +
include/hw/cxl/cxl_host.h | 3 +
include/hw/mem/cxl_type3.h | 8 ++
15 files changed, 334 insertions(+), 2 deletions(-)
create mode 100644 hw/acpi/cxl_type3.c
create mode 100644 hw/arm/cxl.c
create mode 100644 hw/i386/cxl.c
create mode 100644 include/hw/mem/cxl_type3.h
--
2.52.0
WARNING: multiple messages have this Message-ID (diff)
From: Yukiya Takaki via <qemu-arm@nongnu.org>
To: qemu-devel@nongnu.org
Cc: Yukiya Takaki <fj2110jc@fujitsu.com>,
"Michael S. Tsirkin" <mst@redhat.com>,
Ani Sinha <anisinha@redhat.com>, Anisa Su <anisa.su@samsung.com>,
Igor Mammedov <imammedo@redhat.com>,
Jonathan Cameron <jic23@kernel.org>,
Junjie Cao <junjie.cao@intel.com>,
Paolo Bonzini <pbonzini@redhat.com>,
Peter Maydell <peter.maydell@linaro.org>,
Richard Henderson <richard.henderson@linaro.org>,
linux-cxl@vger.kernel.org, qemu-arm@nongnu.org, "Wolski,
Tomasz" <tomasz.wolski@fujitsu.com>,
lizhijian@fujitsu.com, y-goto@fujitsu.com,
yukiya.takaki@gmail.com
Subject: [PATCH RFC 0/7] QEMU/hw/cxl: Allow CXL Type 3 memory regions to be initialized at guest boot
Date: Mon, 26 Oct 2026 19:03:21 +0900 [thread overview]
Message-ID: <cover.1793003983.git.fj2110jc@fujitsu.com> (raw)
Hello everyone,
I’m a student intern, and this is my first time sending patches to an open source mailing list.
This patch series configures QEMU’s CXL Type 3 devices so that guest operating systems can automatically discover
and create CXL regions during boot, aligning QEMU’s behavior with real hardware.
Background and motivation
Currently, during guest boot QEMU does not provide the information or register programming needed for the guest OS
to initialize CXL Type 3 memory, so using it still requires an explicit action in the guest (for example, running the cxl create-region command).
By contrast, on some physical systems the firmware automatically allocates CXL memory ranges and exposes them to the OS,
allowing the Linux CXL driver to discover and create regions during boot.
This patch series is a first, experimental attempt to reproduce that behavior in QEMU.
Some parts of this implementation are based on Li, Zhijian’s work in:
https://github.com/zhijianli88/qemu/tree/program-decoder-v2
I would like to ask for feedback on whether this approach makes sense and whether I should continue to enhance it.
Approach
This patch first adds a program_hdm_decoder option to cxl-type3.
When program-hdm-decoder is enabled on cxl-type3, QEMU will:
1) program endpoint/host-bridge HDM decoder state,
2) expose Type 3 ranges as E820_SOFT_RESERVED on x86,
3) create memory-only NUMA nodes for those ranges,
4) emit SRAT memory-affinity entries mapping each Type 3 HPA range to its node ID
On real hardware, HDM decoder programming and memory layout are typically handled by firmware, so they would ideally be managed by SeaBIOS.
However, in the current QEMU/SeaBIOS model, E820 and SRAT are built on the QEMU side, and pushing HDM decoder programming
into SeaBIOS would introduce additional complexity and risk inconsistencies.
Testing
We ran tests in the following environment and confirmed that CXL regions were created at boot, NUMA nodes were set up,
and E820_SOFT_RESERVED entries appeared in the E820 table:
- BIOS: SeaBIOS c2a33ad9ad1452e23b41c4ac44a3bc6be8ebc4cf
- CXL memory: 4 GB
- CFMWS: 4 GB
- Host bridge: 1
The following is the startup script.
sudo /path/to/qemu/build/qemu-system-x86_64 \
-name guest=cxl \
-nographic \
-machine q35,accel=tcg,nvdimm=on,cxl=on \
-cpu max -smp 4,sockets=4,cores=1,threads=1 \
-m size=4G,slots=10,maxmem=20G \
-drive file=/path/to/image.qcow2,format=qcow2,index=0,media=disk,id=hd \
-bios /path/to/seabios/out/bios.bin \
-nic bridge,br=virbr0,model=e1000e,mac=52:54:00:b5:4e:7c \
-object memory-backend-ram,size=2G,id=m0 \
-object memory-backend-ram,size=2G,id=m1 \
-numa node,nodeid=0,cpus=0-1,memdev=m0 \
-numa node,nodeid=1,cpus=2-3,memdev=m1 \
-device pcie-root-port,id=pci-root,slot=4,bus=pcie.0,chassis=0 \
-device pxb-cxl,bus_nr=12,bus=pcie.0,id=cxl.1,hdm_for_passthrough=true \
-device cxl-rp,port=0,id=root_port13,bus=cxl.1,chassis=0,slot=2 \
-object memory-backend-ram,size=4G,share=on,id=vmem0 \
-device cxl-type3,bus=root_port13,volatile-memdev=vmem0,id=cxl-vmem0,program-hdm-decoder=true \
-M cxl-fmw.0.targets.0=cxl.1,cxl-fmw.0.size=4G,cxl-fmw.0.interleave-granularity=4k
Furthermore, we conducted the experiment in which we added two CXL Type3.
- CXL memory: 4 GB × 2
- CFMWS: 4 GB × 2
The following is the startup script.
sudo /path/to/qemu/build/qemu-system-x86_64 \
-name guest=cxl \
-nographic \
-machine q35,accel=tcg,nvdimm=on,cxl=on,hmat=on \
-cpu max -smp 4,sockets=4,cores=1,threads=1 \
-m size=4G,slots=10,maxmem=20G \
-drive file=/path/to/image.qcow2,format=qcow2,index=0,media=disk,id=hd \
-bios /path/to/seabios/out/bios.bin \
-nic bridge,br=virbr0,model=e1000e,mac=52:54:00:b5:4e:7c \
-object memory-backend-ram,size=2G,id=m0 \
-object memory-backend-ram,size=2G,id=m1 \
-numa node,nodeid=0,cpus=0-1,memdev=m0 \
-numa node,nodeid=1,cpus=2-3,memdev=m1 \
-device pcie-root-port,id=pci-root,slot=4,bus=pcie.0,chassis=0 \
-device pcie-root-port,id=pci-root-net,chassis=5,slot=5,bus=pcie.0 \
-device pxb-cxl,bus_nr=12,bus=pcie.0,id=cxl.1,hdm_for_passthrough=true \
-device cxl-rp,port=0,id=root_port13,bus=cxl.1,chassis=0,slot=2 \
-device cxl-rp,port=3,id=root_port14,bus=cxl.1,chassis=2,slot=4 \
-object memory-backend-ram,size=4G,share=on,id=vmem0 \
-object memory-backend-ram,size=4G,share=on,id=vmem1 \
-device cxl-type3,bus=root_port13,volatile-memdev=vmem0,id=cxl-vmem0,program-hdm-decoder=true \
-device cxl-type3,bus=root_port14,volatile-memdev=vmem1,id=cxl-vmem1,program-hdm-decoder=true \
-M cxl-fmw.0.targets.0=cxl.1,cxl-fmw.0.size=4G,cxl-fmw.0.interleave-granularity=4k,cxl-fmw.1.targets.0=cxl.1,cxl-fmw.1.size=4G,cxl-fmw.1.interleave-granularity=4k
How to use
Specify the following parameters when starting QEMU:
- bios <SeaBIOS binary that includes commit c2a33ad9ad1452e23b41c4ac44a3bc6be8ebc4cf> to ensure that E820_SOFT_RESERVED entries are exposed
- Add hmat=on to the -machine option [1]
- Add program-hdm-decoder=true to each -device cxl-type3 option
[1] On Linux, the kernel first checks E820_SOFT_RESERVED ranges. When multiple CXL Type 3 devices share a contiguous HPA range,
these ranges tend to be merged into a single region, so the CXL driver cannot reliably initialize per‑device regions based on E820 alone.
SRAT entries for CXL memory are therefore needed, and the guest seems to discard SRAT when `hmat=on` is not specified,
so HMAT must be enabled.
QEMU base commit: bddb785e791e415db38884848d068457e226f5e3
TODO
With the current implementation of this patch, the following configurations are either not supported or have not been sufficiently tested.
As a result, automatic creation of CXL regions in the guest OS may fail:
- A CXL persistent memory device is included
- Interleaved configurations
- Cases where the memory size specified by CFMWS does not match the size of the CXL Type 3 backend memory
- Configurations where CXL memory is attached via a switch
- Multi-target CFMWS environments
- ARM environments
- HMAT does not yet include information about CXL memory devices
The following behaviors are also provisional implementations and may need further refinement:
- A new NUMA node ID is assigned to each CXL memory device. This should be improved either to reflect more accurate NUMA distances for CXL memory,
or to allow the NUMA node IDs to be specified by the user.
- Assignment of CXL Type 3 devices to CFMWS address ranges. On physical systems, platform firmware typically generates CFMWS entries
based on the detected CXL topology and its address-space allocation. In QEMU, however, CFMWS entries are configured explicitly
through machine options. The current implementation therefore has to infer which CFMWS range should be used for each Type 3 device.
This selection logic may need further refinement. Possible approaches include improving the selection and validation logic,
adding an explicit option to associate each Type 3 device with a CFMWS entry,
or generating CFMWS entries automatically from the configured CXL topology and devices.
- HDM decoder reset sequencing and state reconstruction.
The current implementation prevents the host bridge HDM decoder configuration from being overwritten later in the same reset
by moving the common initialization of the host bridge component registers from the reset path to the realization path.
However, ideally, after the registers have been restored to their reset values, the host bridge HDM decoder configuration
automatically programmed by QEMU should be reconstructed as part of reset processing.
Thanks,
------
Yukiya Takaki (7):
QEMU/hw/cxl: add program-hdm-decoder option for CXL Type 3 devices
QEMU/hw/cxl:add HPA offset tracking for CXL Type 3 devices
QEMU: hw/cxl: add helper to get HPA range for CXL Type 3
QEMU/hw/cxl: auto‑program HDM decoders for CXL Type 3
QEMU/hw/cxl: expose CXL Type 3 ranges as E820_SOFT_RESERVED on x86
QEMU/hw/cxl: Create NUMA nodes for CXL Type 3 memory
add CXL Type 3 memory ranges to SRAT
hw/acpi/cxl_type3.c | 30 +++++
hw/acpi/meson.build | 1 +
hw/arm/cxl.c | 10 ++
hw/arm/meson.build | 2 +
hw/cxl/cxl-host.c | 63 ++++++++++
hw/i386/acpi-build.c | 7 ++
hw/i386/cxl.c | 11 ++
hw/i386/meson.build | 1 +
hw/i386/pc.c | 2 +
hw/mem/cxl_type3.c | 177 ++++++++++++++++++++++++++++
hw/pci-bridge/pci_expander_bridge.c | 13 +-
include/hw/cxl/cxl.h | 2 +
include/hw/cxl/cxl_device.h | 6 +
include/hw/cxl/cxl_host.h | 3 +
include/hw/mem/cxl_type3.h | 8 ++
15 files changed, 334 insertions(+), 2 deletions(-)
create mode 100644 hw/acpi/cxl_type3.c
create mode 100644 hw/arm/cxl.c
create mode 100644 hw/i386/cxl.c
create mode 100644 include/hw/mem/cxl_type3.h
--
2.52.0
next reply other threads:[~2026-10-26 9:54 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-26 10:03 Yukiya Takaki [this message]
2026-10-26 10:03 ` [PATCH RFC 0/7] QEMU/hw/cxl: Allow CXL Type 3 memory regions to be initialized at guest boot Yukiya Takaki via
2026-10-26 10:03 ` Yukiya Takaki via qemu development
2026-10-26 10:03 ` [PATCH RFC 1/7] QEMU/hw/cxl: add program-hdm-decoder option for CXL Type 3 devices Yukiya Takaki
2026-10-26 10:03 ` Yukiya Takaki via qemu development
2026-10-26 10:03 ` [PATCH RFC 2/7] QEMU/hw/cxl:add HPA offset tracking " Yukiya Takaki
2026-10-26 10:03 ` Yukiya Takaki via qemu development
2026-10-26 10:03 ` [PATCH RFC 3/7] QEMU: hw/cxl: add helper to get HPA range for CXL Type 3 Yukiya Takaki
2026-10-26 10:03 ` Yukiya Takaki via qemu development
2026-10-28 1:09 ` Anisa Su
2026-10-29 0:17 ` Yukiya Takaki (Fujitsu)
2026-10-26 10:03 ` [PATCH RFC 4/7] QEMU/hw/cxl: auto‑program HDM decoders " Yukiya Takaki
2026-10-26 10:03 ` Yukiya Takaki via qemu development
2026-10-26 10:03 ` [PATCH RFC 5/7] QEMU/hw/cxl: expose CXL Type 3 ranges as E820_SOFT_RESERVED on x86 Yukiya Takaki
2026-10-26 10:03 ` Yukiya Takaki via
2026-10-26 10:03 ` Yukiya Takaki via qemu development
2026-10-26 10:03 ` [PATCH RFC 6/7] QEMU/hw/cxl: Create NUMA nodes for CXL Type 3 memory Yukiya Takaki
2026-10-26 10:03 ` Yukiya Takaki via qemu development
2026-10-26 10:03 ` [PATCH RFC 7/7] add CXL Type 3 memory ranges to SRAT Yukiya Takaki via qemu development
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=cover.1793003983.git.fj2110jc@fujitsu.com \
--to=fj2110jc@fujitsu.com \
--cc=anisa.su@samsung.com \
--cc=anisinha@redhat.com \
--cc=imammedo@redhat.com \
--cc=jic23@kernel.org \
--cc=junjie.cao@intel.com \
--cc=linux-cxl@vger.kernel.org \
--cc=lizhijian@fujitsu.com \
--cc=mst@redhat.com \
--cc=pbonzini@redhat.com \
--cc=peter.maydell@linaro.org \
--cc=qemu-arm@nongnu.org \
--cc=qemu-devel@nongnu.org \
--cc=richard.henderson@linaro.org \
--cc=tomasz.wolski@fujitsu.com \
--cc=y-goto@fujitsu.com \
--cc=yukiya.takaki@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.