RE: [PATCH v3 00/11] vfio/pci: Add CXL Type-2 device passthrough support

Manish Honap <[email protected]>
Newsgroups org.kernel.vger.linux-cxl,org.kernel.vger.kvm,org.kernel.vger.linux-doc,org.kernel.vger.linux-kernel,org.kernel.vger.linux-kselftest
Message-ID <IA1PR12MB903093E02EB1C21A8596EEAABDC22@IA1PR12MB9030.namprd12.prod.outlook.com>
Thank you all for review suggestions. Closing the loop on v3. I will rework
patch series v4 as per the review feedback.

Current understanding of what changes in v4:

- Create v4 on top of cxl_reset v9 from Srirangan. Move the patch series to
  Linus's RC tree and apply Srirangan's cxl-reset support patch v9 on it.
- Patch 01 is dropped; vfio-cxl reads pdev->hdm directly.
- The memdev is created at bind via devm_cxl_probe_mem() and is removed on
  unbind. Probe takes no action that outlives it.
- Volatile state (DVSEC shadow, CM snapshot, ecap handlers) is acquired at
  open_device() and released at close_device(). Nothing volatile is read at bind.
- HDM mmap will make use of huge pfnmap as seen in vfio mmap routine.
- DVSEC is handled through ecap_perms readfn/writefn with a range check against
  the CXL DVSEC body; other DVSECs pass through unchanged.
- UAPI: the flag is VFIO_DEVICE_FLAGS_CXL; region index fields are removed from
  the device cap; component-register geometry moves to a region info cap; there
  is no firmware-committed flag.
- The CM capability snapshot uses readq() throughout; the lock-on-commit state
  machine is corrected so COMMIT is read-only while locked.
- The file moves to drivers/vfio/pci/cxl/ with a private header; duplicate
  register defines are dropped for the upstream ones; devres uses
  devm_add_action_or_reset().
- vfio-pci loads vfio-cxl through request_module() only when it finds a CXL
  device; vfio-cxl registers its ops at module_init; each bound device holds a
  module reference from probe to release.
- vfio-cxl owns the whole component BAR via pci_request_selected_regions(). A
  cxl_register_map flag (skip_sub_bar_request) lets cxl-core skip its HDM/RAS
  sub-block claim for an owning driver; cxl_pci is unchanged.
- The HPA is resolved before the guest sees the device; the guest only relocates
  CXL memory in GPA space. Range readiness happens at enumeration in cxl-core, so
  vfio-cxl waits on nothing and consumes a ready resource (No await_range_active
  exported)
--

Device lifecycle in v4

cxl-pci discovery / enumeration
- pdev->hdm is populated (decoder settings, count, base and size) via cxl_reset v9.
- No memdev here; a passthrough device binds to vfio-pci, not cxl_pci.

vfio-pci probe / vfio-cxl bind (reversible)
- Read hdm_hpa and hdm_size from pdev->hdm as u64 on vfio_pci_core_device.
- Walk the PCIe ecap for the CXL DVSEC body range; record offset and size.
- Record the component-register BAR index.
- request_module("vfio-cxl"); take one module reference, held until release.
- Create the memdev via devm_cxl_probe_mem(); devm removes it on unbind.
- Register pfn_address_space over the HDM range for error containment.
- Request the whole component BAR; cxl-core skips its sub-block claim.

vfio-pci open_device (volatile state, device-open lifetime)
- Read the DVSEC body into a shadow; read the CM array with readq().
- Validate pdev->hdm against the hardware.
- Install the ecap_perms DVSEC handler (range check, fall through for others).
- Allocate cxl_vfio_state and set vdev->cxl.

vfio-pci close_device
- Remove the DVSEC handler; free the shadow and snapshot; clear vdev->cxl.

vfio-pci remove / unbind
- Release the component BAR; unregister pfn_address_space; drop the module
  reference.
- The memdev is auto-removed by devm.

I will post v4 on this basis.

Thanks,
Manish

> -----Original Message-----
> From: Manish Honap <[email protected]>
> Sent: 13 July 2026 22:14
> To: Dave Jiang <[email protected]>; [email protected];
> [email protected]; [email protected]; [email protected]; Ankit Agrawal
> <[email protected]>; [email protected];
> [email protected]; [email protected]; [email protected];
> [email protected]; [email protected]
> Cc: Neo Jia <[email protected]>; Krishnakant Jaju <[email protected]>;
> Vikram Sethi <[email protected]>; Zhi Wang <[email protected]>;
> [email protected]; [email protected]; linux-
> [email protected]; [email protected]; linux-
> [email protected]; Manish Honap <[email protected]>
> Subject: RE: [PATCH v3 00/11] vfio/pci: Add CXL Type-2 device
> passthrough support
> 
> > -----Original Message-----
> > From: Dave Jiang <[email protected]>
> > Sent: 10 July 2026 21:57
> > To: Manish Honap <[email protected]>; [email protected];
> > [email protected]; [email protected]; [email protected]; Ankit Agrawal
> > <[email protected]>; [email protected];
> > [email protected]; [email protected]; [email protected];
> > [email protected]; [email protected]
> > Cc: Neo Jia <[email protected]>; Krishnakant Jaju <[email protected]>;
> > Vikram Sethi <[email protected]>; Zhi Wang <[email protected]>;
> > [email protected]; [email protected]; linux-
> > [email protected]; [email protected]; linux-
> > [email protected]
> > Subject: Re: [PATCH v3 00/11] vfio/pci: Add CXL Type-2 device
> > passthrough support
> >
> > External email: Use caution opening links or attachments
> >
> >
> > On 6/25/26 9:53 AM, [email protected] wrote:
> > > From: Manish Honap <[email protected]>
> > >
> > > CXL Type-2 accelerators (CXL.mem-capable GPUs and similar) cannot be
> > > passed through to virtual machines with stock vfio-pci because the
> > > driver has no concept of HDM decoder management, HDM region
> > > exposure, or component register virtualization.  This series adds
> > > those three pieces, sufficient for a guest to use the device's
> > > firmware-committed coherent memory under UVM / ATS.
> > >
> > > v3 is a rewrite of the v2 framework form, responding to Dan's
> > > request in the v2 review for "less emulation, narrower interfaces,
> > > and a closer mapping to the spec language."
> > > In this release, cxl-core exposes four EXPORT_SYMBOL_GPL helpers
> > > behind an opaque handle.  vfio-pci becomes a thin transport on top
> > > of
> > those.
> > > Please see "Changes since v2" and "Reviewer feedback addressed"
> > > below for the per-area summary.
> > >
> > > Motivation
> > > ==========
> > >
> > > A CXL Type-2 device exposes its HDM-mapped device memory through HDM
> > > decoders that BIOS programs and commits at boot.  To pass such a
> > > device to a guest, vfio-pci has to do three things at once:
> > >
> > >   1. Surface the firmware-committed HDM-mapped HPA range as a guest-
> > >      mmappable region.
> > >
> > >   2. Surface a CXL-spec-compliant view of the CXL Device DVSEC body,
> > >      the HDM Decoder Capability block, and the CXL.cache/mem cap-
> array
> > >      prefix, so the guest's CXL driver enumerates the same topology
> > >      the host saw.
> > >
> > >   3. Keep the host's committed decoder configuration intact (the
> > >      physical decoder is never reprogrammed) while letting the guest
> > >      observe and manage a shadow that follows the per-field write
> > >      semantics in the spec.
> > >
> > > The series builds on Alejandro Lucero-Palau's v28 work applied on
> > > for-7.3/cxl-type2-enabling [1] (sfc is the in-tree consumer today).
> > > vfio-pci becomes the second consumer.
> > >
> > > Architecture
> > > ============
> > >
> > > cxl-core owns the CXL semantics.  A new file
> > > drivers/cxl/core/passthrough.c (gated by hidden Kconfig
> > > CXL_VFIO_PASSTHROUGH) provides four exported symbols:
> > >
> > >     struct cxl_passthrough *
> > >     devm_cxl_passthrough_create(struct device *dev,
> > >                                 struct cxl_dev_state *cxlds);
> > >
> > >     int cxl_passthrough_dvsec_rw(p, off, val, sz, write);
> > >     int cxl_passthrough_hdm_rw  (p, off, val,      write);
> > >     int cxl_passthrough_cm_rw   (p, off, val,      write);
> > >
> > > cxl_passthrough is an opaque handle; vfio-pci sees no cxl-internal
> > > struct pointers.  The shadows are snapshotted at create time: the
> > > DVSEC body from PCI config space dword by dword, the CM cap-array
> > > and HDM block from the cxl-core MMIO mapping at cxlds->reg_map.base.
> > > Per-field write semantics follow below:
> > > CXL r4.0 8.1.3 DVSEC:
> > > - LOCK is RWO,
> > > - CONTROL/CONTROL2 are RWL gated on CONFIG_LOCK,
> > > - STATUS/STATUS2 are RW1C,
> > > - RANGE1 is HwInit, RANGE2 is RsvdZ
> > > CXL r4.0 8.2.4.20 HDM:
> > > - GLOBAL_CTRL RW,
> > > - decoder CTRL implements COMMIT/COMMITTED,
> > > - decoder BASE/SIZE RWL gated on COMMITTED or LOCK_ON_COMMIT,
> > > - cap header HwInit).
> > >
> > > vfio-pci becomes a thin transport.  The new module
> > > drivers/vfio/pci/cxl/ exposes two VFIO regions.
> > >
> > >   VFIO_REGION_SUBTYPE_CXL (HDM region): mmappable view of the
> > >   HDM-mapped HPA. The mmap fault handler calls vmf_insert_pfn() from
> > >   the physical HPA. pread/pwrite go through the memremap_wb() kva
> > >   captured at bind time.
> > >
> > >   VFIO_REGION_SUBTYPE_CXL_COMP_REGS (component register shadow):
> > >   pread/pwrite only, dword-aligned (-EINVAL on misalignment).
> > >   Each dword dispatches by offset to cxl_passthrough_cm_rw() or
> > >   cxl_passthrough_hdm_rw(). No shadow state on the vfio side; cxl-
> core
> > >   enforces the spec.
> > >
> > > CXL DVSEC config-space accesses use a clipping shim in
> > > vfio_pci_config_rw_single(). A config-space chunk that crosses the
> > > DVSEC body boundary is split: header bytes go through the generic
> > > perm-bits path, body bytes go through cxl_passthrough_dvsec_rw().
> > > The shim replaces v2's approach of repointing ecap_perms[]
> > >
> > > Sparse-mmap is exposed on the component BAR so userspace can mmap
> > > the non-component portions directly; only the CXL component register
> > > sub-range goes through pread/pwrite emulation. The CXL sub-range is
> > > also skipped from vfio_pci-core's request_selected_regions() set
> > > because cxl-core's devm_cxl_probe_mem() already holds a
> > > request_mem_region() on it; the asymmetric skip is matched by an
> > > asymmetric release on disable().
> > >
> > > Scope and out-of-scope
> > > ======================
> > >
> > > In scope (rejected at create time with -EOPNOTSUPP otherwise):
> > >
> > >   - Firmware-committed devices (HOST_FIRMWARE_COMMITTED set).
> > >   - Single HDM decoder (hdm_count == 1).
> > >   - No interleave (IW == 0).
> > >
> > > Out of scope, deferred for follow-on work:
> > >
> > >   - Multi-decoder devices and interleave.
> > >   - Guest-driven (non-firmware-committed) HDM commit.
> > >   - Hotplug, FLR, and sibling-function reset of CXL Type-2 devices.
> > >
> > > Changes since v2
> > > ================
> > >
> > > This is a rewrite, not an incremental update.  The structure of the
> > > series changed (20 patches in v2 to 11 in v3) because v3 collapses
> > > v2 patches 9-15 (detection, HDM emulation, media readiness, region
> > > management, HDM region, DVSEC emulation) into one cxl-core helper
> > > file and one vfio-pci consumer.
> > >
> > > Framework replaced by narrow opaque-handle helpers (patches 6, 8)
> > >
> > >   v2 carried a generic register-emulation framework split across
> four
> > >   state-machine files in cxl-core.
> > >   v3 collapses it into one file: drivers/cxl/core/passthrough.c
> > >   exposing the four EXPORT_SYMBOL_GPL helpers above behind a struct
> > >   cxl_passthrough opaque handle.
> > >
> > > Shadow ownership moved into cxl-core (patches 6, 8)
> > >
> > >   vfio-pci no longer keeps any per-field state. It forwards
> > >   (offset, value) into cxl-core, and cxl-core enforces the spec
> > >   (RWO, RWL, RW1C, HwInit, RsvdZ) with explicit CXL r4.0 section
> > >   references in the switch arms.
> > >
> > > DVSEC config-space clipping shim (patch 8)
> > >
> > >   v2 repointed ecap_perms[] to redirect CXL DVSEC reads and writes.
> > >   v3 keeps ecap_perms[] untouched and clips per-config-access chunks
> > >   at the DVSEC body boundary in vfio_pci_config_rw_single(); header
> > bytes
> > >   go through the generic perm-bits path, body bytes go through
> > >   cxl_passthrough_dvsec_rw(). The shim is local to the per-device
> > >   path.
> > >
> > > CONFIG_VFIO_PCI_CXL gates the new module (patch 7)
> > >
> > >   v2 had a CONFIG_VFIO_CXL_CORE Kconfig stub; v3 renames it to
> > >   CONFIG_VFIO_PCI_CXL to match the vfio-pci naming convention.
> > >   The hidden CXL_VFIO_PASSTHROUGH selects the cxl-core helper file
> > >   on demand. With both disabled, the cxl-core size is unchanged.
> > >
> > > UAPI rewritten with named fields (patch 5)
> > >
> > >   vfio_device_info_cap_cxl in v3 carries:
> > >     flags + HOST_FIRMWARE_COMMITTED bit
> > >     hdm_region_idx
> > >     comp_reg_region_idx
> > >     comp_reg_bar
> > >     comp_reg_offset
> > >     comp_reg_size
> > >   The DPA terminology is renamed to HDM region throughout.
> > >   CACHE_CAPABLE (HDM-DB indicator) is dropped;
> > >   it was informational only in v2 with no caller, and re-adding it
> > >   for an active CXL.cache plumbing series later.
> > >
> > > Selftests trimmed (patch 9)
> > >
> > >   v2 carried selftests for device detection, capability parsing,
> > >   region enumeration, HDM register emulation, HDM mmap with
> > >   page-fault insertion, FLR invalidation, and DVSEC register
> > >   emulation. v3 keeps a smoke-test set of six focused tests:
> > >
> > >     device_is_cxl                  GET_INFO advertises FLAGS_CXL
> > >                                    and a populated CAP_CXL.
> > >     hdm_region_mmap_rw             mmap one page, write+read back.
> > >     component_bar_sparse_mmap      SPARSE_MMAP cap excludes the
> > >                                    CXL component register sub-range.
> > >     comp_regs_cm_cap_array_read    pread of the CM cap-array
> > >                                    header at CXL_CM_OFFSET succeeds
> > >                                    (CAP_ID == 1).
> > >     dvsec_lock_byte_read           pread of the DVSEC CONFIG_LOCK
> > >                                    byte through the clipping shim
> > >                                    succeeds.
> > >     hdm_decoder_commit_fsm         COMMIT / COMMITTED state machine
> > >                                    and LOCK_ON_COMMIT behaviour.
> > >
> > >   FLR invalidation, page-fault insertion under load, and full
> > >   DVSEC field-by-field write coverage are deferred to a follow-on
> > >   selftest series. The current six are the minimal set that
> > >   exercises the kernel-side contract end-to-end.
> > >
> > > cxl-core prep patches split (patches 1-4)
> > >
> > >   v3 keeps the cxl-side enablers from v2 patches 1-4 but each as
> > >   a standalone change so the cxl maintainer can review the helper
> > >   API independently of the vfio consumer:
> > >
> > >     [1/11] cxl_get_hdm_info()
> > >     [2/11] cxl_await_range_active() split from media-ready wait
> > >     [3/11] cxl_register_map records BIR + BAR offset
> > >     [4/11] component/HDM register defines moved to
> > > uapi/cxl/cxl_regs.h
> > >
> > > Reviewer feedback addressed
> > > ===========================
> > >
> > > Dan
> > > ---
> > >
> > > - VFIO exposes HDM/host-visible region, not raw DPA; docs/UAPI say
> HDM
> > >   region, DPA only inside cxl-core where appropriate.
> > > - One vfio-pci device = one HDM region / one decoder, no interleave;
> > >   hdm_count != 1 → -EOPNOTSUPP.
> > > - Global HDM on DVSEC Range Base treated as legacy; RANGE1/RANGE2
> > >   read-only snapshot, guest writes dropped.
> > > - No guest/kernel lock games; DVSEC LOCK and HDM LOCK_ON_COMMIT RWO,
> > >   fixed at create from firmware snapshot.
> > > - Opaque cxl_passthrough handle only; vfio gets HPA via memdev probe
> +
> > >   layout via cxl_get_hdm_info(), rw via helpers.
> > > - No multi-region accelerator case in v3; single region enforced,
> > >   multi-region deferred.
> > > - cxl_await_range_active stays in cxl-core probe; not exported, vfio
> > does
> > >   not call it.
> > > - No guest LOCK→0 reprogram; guest cannot clear LOCK to remap host
> > HPA;
> > >   kernel uncommit tied to COMMIT, not LOCK alone.
> > >
> > > Jason / Gregory / Dan
> > > ---------------------
> > >
> > > - memremap(WB) + request_mem_region on HPA; conflicting
> > > direct-map/EFI
> > use
> > >   fails probe with -EBUSY.
> > >
> > > Jonathan
> > > --------
> > >
> > > - uapi/cxl/cxl_regs.h for register defines so VMMs need no private
> > >   kernel headers.
> > > - __free() locals on cxl-core/passthrough error paths instead of
> > >   struct-owned temporaries.
> > > - No "precommitted at probe" assumption; acquire checks COMMITTED in
> > >   HDM shadow and refuses if missing.
> > >
> > > Dave
> > > ----
> > >
> > > - memremap(MEMREMAP_WB) for HDM host mapping (not ioremap_cache).
> > > - Renamed cap flag to VFIO_CXL_CAP_HOST_FIRMWARE_COMMITTED for
> > clarity.
> > > - __free() / DEFINE_FREE() cleanup in new passthrough.c create path.
> > >
> > > Patch series
> > > ============
> > >
> > >  [1/11] cxl: Add cxl_get_hdm_info() helper for HDM decoder metadata
> > > [2/11] cxl: Split cxl_await_range_active() from media-ready wait
> > > [3/11] cxl: Record BIR and BAR offset in cxl_register_map  [4/11]
> cxl:
> > > Move component/HDM register defines to
> > >         uapi/cxl/cxl_regs.h
> > >  [5/11] vfio: UAPI for CXL Type-2 device passthrough  [6/11] cxl:
> > > Add register-virtualization helpers for vfio Type-2
> > >         passthrough
> > >  [7/11] vfio/pci: Add CONFIG_VFIO_PCI_CXL with bind-time CXL Type-2
> > >         acquisition
> > >  [8/11] vfio/pci/cxl: Add HDM + COMP_REGS regions and DVSEC clipping
> > >         shim
> > >  [9/11] selftests/vfio: Add CXL Type-2 device passthrough smoke test
> > > [10/11] docs: vfio-pci: Document CXL Type-2 device passthrough
> > > [11/11]
> > > vfio/pci: Provide opt-out for CXL Type-2 extensions
> > >
> > > Dependencies
> > > ============
> > >
> > > [1] [PATCH v28 0/5] Type2 device basic support
> > > https://lore.kernel.org/linux-cxl/20260618181806.118745-1-alejandro.
> > > lu
> > > [email protected]/
> > >
> > > [2] Previous version of this patch series [PATCH v2 00/20] vfio/pci:
> > > Add CXL Type-2 device passthrough support
> > > https://lore.kernel.org/linux-cxl/20260401143917.108413-1-mhonap@nvi
> > > di
> > > a.com/
> > >
> > > [3] Companion QEMU series
> > > [RFC 0/9] QEMU: CXL Type-2 device passthrough via vfio-pci
> > > https://lore.kernel.org/linux-cxl/20260427181235.3003865-1-mhonap@nv
> > > id
> > > ia.com/
> > >
> > > Manish Honap (11):
> > >   cxl: Add cxl_get_hdm_info() helper for HDM decoder metadata
> > >   cxl: Split cxl_await_range_active() from media-ready wait
> > >   cxl: Record BIR and BAR offset in cxl_register_map
> > >   cxl: Move component/HDM register defines to uapi/cxl/cxl_regs.h
> > >   vfio: UAPI for CXL Type-2 device passthrough
> > >   cxl: Add register-virtualization helpers for vfio Type-2
> passthrough
> > >   vfio/pci: Add CONFIG_VFIO_PCI_CXL with bind-time CXL Type-2
> > >     acquisition
> > >   vfio/pci/cxl: Add HDM + COMP_REGS regions and DVSEC clipping shim
> > >   selftests/vfio: Add CXL Type-2 device passthrough smoke test
> > >   docs: vfio-pci: Document CXL Type-2 device passthrough
> > >   vfio/pci: Provide opt-out for CXL Type-2 extensions
> > >
> > >  Documentation/driver-api/index.rst            |   1 +
> > >  Documentation/driver-api/vfio-pci-cxl.rst     | 282 ++++++
> > >  drivers/cxl/Kconfig                           |   7 +
> > >  drivers/cxl/core/Makefile                     |   1 +
> > >  drivers/cxl/core/passthrough.c                | 590 ++++++++++++
> > >  drivers/cxl/core/pci.c                        |  70 +-
> > >  drivers/cxl/core/regs.c                       |  35 +
> > >  drivers/cxl/cxl.h                             |  52 +-
> > >  drivers/vfio/pci/Kconfig                      |   2 +
> > >  drivers/vfio/pci/Makefile                     |   1 +
> > >  drivers/vfio/pci/cxl/Kconfig                  |  34 +
> > >  drivers/vfio/pci/cxl/Makefile                 |   2 +
> > >  drivers/vfio/pci/cxl/vfio_cxl_core.c          | 889
> > ++++++++++++++++++
> > >  drivers/vfio/pci/cxl/vfio_cxl_priv.h          |  71 ++
> > >  drivers/vfio/pci/vfio_pci.c                   |   9 +
> > >  drivers/vfio/pci/vfio_pci_config.c            |  31 +
> > >  drivers/vfio/pci/vfio_pci_core.c              |  68 +-
> > >  drivers/vfio/pci/vfio_pci_priv.h              |  93 ++
> > >  drivers/vfio/pci/vfio_pci_rdwr.c              |  17 +
> > >  include/cxl/cxl.h                             |  18 +
> > >  include/cxl/passthrough.h                     | 121 +++
> > >  include/linux/vfio_pci_core.h                 |   8 +
> > >  include/uapi/cxl/cxl_regs.h                   |  63 ++
> > >  include/uapi/linux/vfio.h                     |  46 +
> > >  tools/testing/selftests/vfio/Makefile         |   1 +
> > >  .../selftests/vfio/lib/vfio_pci_device.c      |  11 +-
> > >  .../selftests/vfio/vfio_cxl_type2_test.c      | 350 +++++++
> > >  27 files changed, 2821 insertions(+), 52 deletions(-)  create mode
> > > 100644 Documentation/driver-api/vfio-pci-cxl.rst
> > >  create mode 100644 drivers/cxl/core/passthrough.c  create mode
> > > 100644 drivers/vfio/pci/cxl/Kconfig  create mode 100644
> > > drivers/vfio/pci/cxl/Makefile  create mode 100644
> > > drivers/vfio/pci/cxl/vfio_cxl_core.c
> > >  create mode 100644 drivers/vfio/pci/cxl/vfio_cxl_priv.h
> > >  create mode 100644 include/cxl/passthrough.h  create mode 100644
> > > include/uapi/cxl/cxl_regs.h  create mode 100644
> > > tools/testing/selftests/vfio/vfio_cxl_type2_test.c
> > >
> > > base-commit: 90cf2e0d702c8a132ccbe72e7687f33c04c14658
> >
> > Hi Manish,
> > b4 seems to be failing with applying on top of this base-commit.
> >
> 
> Sorry about this; The series does not apply against a plain mainline
> tree because it depends on Alejandro's v28 "Type2 device basic support"
> 
> I created this patchseries on `origin/for-7.3/cxl-type2-enabling' with
> base commit as 90cf2e0d702c and applied Alejandro's patch-v28. on this
> tree, I see the patches can be applied correctly.
> 
> I see Srirangan has based his reset series on Linus's tree. I will
> follow similar guidelines for v4.
>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.