mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v5 00/27] vfio/pci: Add CXL Type-2 device passthrough support
@ 2026-09-16 18:35 mhonap
  2026-09-16 18:35 ` [PATCH v5 01/27] cxl/regs: Split the BAR block request and ioremap helpers mhonap
                   ` (26 more replies)
  0 siblings, 27 replies; 33+ messages in thread
From: mhonap @ 2026-09-16 18:35 UTC (permalink / raw)
  To: alex, jgg, ankita, jic23, dave.jiang, alejandro.lucero-palau,
	smadhavan, corbet, skhan, dave, alison.schofield, vishal.l.verma,
	iweiny, ming.li, yishaih, skolothumtho, kevin.tian, bhelgaas,
	dmatlack, kees, gustavoars
  Cc: cjia, kjaju, vsethi, zhiw, mhonap, linux-doc, linux-kernel, kvm,
	linux-cxl, linux-pci, linux-kselftest, linux-hardening

From: Manish Honap <mhonap@nvidia.com>

This series adds VFIO passthrough for CXL Type-2 accelerators. The guest
drives its own virtual HDM decoder and can reset the device. The host
owns the physical decoder and the host physical address the memory lands
at. The guest only picks a guest physical address. This series targets a
single, non-interleaved, firmware-committed endpoint decoder.


Base and dependencies
---------------------

  Base: Linux 7.3-rc1 (cee9395acd80), plus the cxl-reset dependency:
  - CXL reset core from Srirangan's cxl_reset series (v12) [1], which
    caches the endpoint decoder settings in pdev->hdm and keeps the HDM
    decoder and reset helpers in drivers/cxl/core.
  - This series adds a function-scoped reset entry
    (cxl_reset_dvsec_sequence) on top and drives it at the vfio reset
    points.
  - Prerequisite commits from Alejandro's type-2 device support and
    Dan's devm_cxl_probe_mem are already upstreamed in this kernel
    release and those series are not listed as dependencies now.


Changes since v4
----------------

v4 [2] introduced the vfio-cxl provider: the register emulation lives in
a separate module that vfio-pci-core loads on demand, and cxl-core keeps
only the reset entry and a few enabling helpers. v5 keeps that model and
folds the v4 review, reshaping the region and reset handling. The patch
count is unchanged at 27; several patches were split, a few were dropped,
and the composition changed.

Structural
  - The v4 "expose the HDM memory and trap the decoder registers" patch is
    split into three: the mmap-able HDM memory region, memory-failure
    containment for that struct-page-less range, and the read-only
    decoder-register region.
  - "Guard HDM access on device state" is split into two: excluding the
    decoder block from the direct BAR, and clearing the HDM access gate
    after a secondary bus reset.
  - The decoder register block is read live; the static decoder snapshot
    and its refresh-after-reset patch are gone.
  - The CXL DVSEC is virtualized through the config-space permission hooks
    in vfio_pci_config.c; the separate DVSEC-shadow patch is gone.
  - The cxl-core media-readiness patch is dropped; a mailbox-less Type-2
    memdev sets media ready in the provider at bind (mirrors efx_cxl).
  - The cxl-core register-map rework is split into request/ioremap helpers
    plus an owned-resource record, replacing the v4 bar_owned flag.
  - The v4 resource.c include/export patch is dropped; the include ships in
    the cxl_reset base and the disputed re-export no longer exists.

Behavioral
  - The HDM decoder registers are served by live reads with guest writes
    absorbed; the host committed and locked the physical decoder, so the
    guest never drives it.
  - fd read/write of the HDM memory region is serviced by a device-state
    guarded write-back copy (Memory-Space enabled, decoder known-good, and
    media ready) and refused only while that gate is closed, rather than
    unconditionally.
  - The coherent CXL.mem range is exported as a dma-buf and mapped into the
    guest IOAS with IOMMU_IOAS_MAP_FILE, replacing the out-of-tree PFNMAP
    workaround v4 needed for device-side ATS.
  - Reset is wired through the pci_error_handlers .reset_prepare and
    .reset_done callbacks and the CXL reset method rather than open-coded;
    a bus hot reset no longer rejects sibling functions.
  - The excluded-range facility is generic (a list of bar/start/size/flags)
    and the existing MSI-X exclusion is migrated onto it.


Reviewer feedback addressed
---------------------------

The v4 [2] thread has the full discussion; this is where each objection
landed.

Alex Williamson
  - A generic excluded-range list replaces the CXL one-off; MSI-X is
    migrated onto it; an intersecting host read fills -1 and a write is
    dropped rather than erroring.
  - The component-register block is exposed as a live read-only view, not a
    static shadow; the refresh-after-reset patch is eliminated.
  - The HDM memory fd read/write is device-state guarded rather than a bare
    -EIO.
  - Error containment and the decoder-register region are their own patches.
  - Reset uses .reset_prepare/.reset_done; the multifunction/sibling
    hot-reset rejection is dropped; the VM-centric framing is removed.
  - CXL init failure is non-fatal and falls back to plain vfio-pci;
    disable_cxl is a convenience opt-out, not the failure path.
  - The DVSEC virtualization lives in vfio_pci_config.c as an ecap perm map;
    the config path takes no CXL module dependency.
  - Both regions use VFIO_REGION_TYPE_PCI_VENDOR_TYPE with the CXL vendor id.
  - Kconfig/Makefile ordering fixed; the .open_device/.close_device hook
    names are kept to mirror vfio_device_ops; the bind-time rejects log
    consistently.

Dave Jiang
  - Component-register ownership uses the owned-resource API, not a
    bar_owned flag.
  - Media readiness is set in the provider at bind (efx_cxl precedent); the
    cxl-core media-readiness change is dropped.
  - The component register defines live in uapi/cxl/cxl_regs.h and the
    message names the selftest as the consumer.
  - The cheap topology rejects are grouped before the range computation.

Jonathan Cameron
  - The v4 resource.c include/export patch is gone: the include arrives with
    the cxl_reset base and the re-export it objected to no longer exists.

Shuai Xue
  - The selftest maps the HDM range through the dma-buf + IOMMU_IOAS_MAP_FILE
    path instead of failing a VA-based IOAS map.
  - The guest cache write-back-invalidate doorbell completes in the shadow;
    the host runs the real WBI inside the reset sequence.


Patch order
-----------

The patches are ordered so the tree builds at every commit and each change
sits next to the code it depends on. Five groups:

  Part 1  CXL core (patches 1-4)
    - Split the BAR block request and ioremap helpers, and let a BAR-owning
      driver own the component register block, so the HDM/RAS sub-blocks are
      left unclaimed for vfio-cxl.
    - Move the component register defines to include/uapi/cxl/cxl_regs.h so a
      VMM (and the selftest) can consume them.
    - Add the function-scoped cxl_reset_dvsec_sequence() for vfio-pci.

  Part 2  vfio-pci-core enabling (patches 5-14)
    - The CXL provider ops registration interface, on-demand provider load,
      -EPROBE_DEFER handling for the built-in case, and the non-fatal
      fallback to plain vfio-pci when CXL init fails.
    - A generic excluded-range list and the MSI-X migration onto it.
    - The CXL DVSEC virtualization in config space, the open/close hooks, the
      reset brackets, and the disable_cxl opt-out.

  Part 3  vfio-cxl provider and HDM regions (patches 15-24)
    - The vfio-cxl module, the CXL memdev created at bind, and ownership of
      the whole component BAR.
    - The mmap-able HDM memory region, memory-failure containment for it, and
      the read-only decoder-register region.
    - Excluding the decoder block from the direct BAR, the hot-reset access
      gate, the device/decoder geometry cap, and the dma-buf export.

  Part 4  vfio-cxl reset (patch 25)
    - Run the CXL DVSEC reset at every vfio reset point.

  Part 5  Documentation and selftests (patches 26-27)


Subsystem boundary
------------------

vfio-pci-core does not implement CXL registers. vfio-cxl is a separate
module that registers a struct vfio_cxl_ops at init. vfio-pci-core loads it
on demand for a CXL device (request_module plus pcie_is_cxl) and pins it
per bound device. If a modular provider is missing or fails to load, the
device is driven as plain vfio-pci. The bind only defers for the built-in
initcall-order case, where request_module cannot help.

The core exposes only the primitives that have to live in core (memory_lock,
mapping revoke, dma-buf quiesce, and the BAR sub-range exclusion). The
CXL-specific work stays behind the ops.


Memory ownership
----------------

The host resolves the host physical address once, at bind, through
devm_cxl_probe_mem(). The memdev is owned for the bind lifetime and torn
down at unbind. The HPA range is claimed IORESOURCE_EXCLUSIVE so no
mismatched cacheable alias can form, including one mapped through /dev/mem.

The guest programs a guest physical address into a trapped virtual decoder
and polls a shadow for commit. It never reaches the physical decoder
registers: those are served only through the live-read trap and are
excluded from the direct BAR mapping, so the guest cannot move the host
physical window.


HDM region access
-----------------

The HDM region carries the coherent device memory. A VMM mmaps it and maps
it into the guest through stage-2; that is the primary access path. The
region advertises READ and WRITE so a VMM can derive an accessible (non
PROT_NONE) mmap protection. fd read/write is serviced by a write-back copy
gated on the same device state as the fault path, and refused while that
gate is closed.

The fault path inserts the pfn only while the decoder is in a known-good
restored state, the device has PCI Memory-Space enabled, and the media is
ready, so a host access cannot reach a revoked or disabled decoder. The
fault inserts the HPA pfn at the largest aligned order, including 2 MB PMDs.
The struct-page-less range is registered with the memory-failure machinery
so a memory error is contained to unmapping the range and a SIGBUS rather
than a host SError.


DMA and iommufd
---------------

A Type-2 accelerator issues ATS-translated DMA to addresses inside its own
HDM window, so that range must be present in the guest IOAS. The HDM range
is struct-page-less coherent memory that a userspace-VA IOMMU_IOAS_MAP
cannot pin, so the HDM memory region is exportable as a dma-buf:
VFIO_DEVICE_FEATURE_DMA_BUF returns an fd that iommufd maps with
IOMMU_IOAS_MAP_FILE, without a VA or a page pin. The dma-buf is revoked
whenever the mapping is torn down, so a stale stage-2 mapping cannot outlive
the HDM window.


Reset
-----

A CXL Type-2 device is reset through its DVSEC sequence at every path that
can reset it, not through an FLR (an FLR would corrupt CXL.mem). The reset
runs at every vfio reset point through one shared helper: VM enable and
close, the VFIO_DEVICE_RESET ioctl, a config-space FLR, and a guest write of
Initiate_CXL_Reset in the CXL DVSEC. Under memory_lock, with the HDM mapping
and the dma-buf revoked, the host runs cxl_reset_dvsec_sequence(), which
always clears device memory on the v12 base and restores and re-samples the
firmware-committed decoder. The guest's cache write-back-invalidate doorbell
completes in the shadow and the real invalidate runs inside that sequence;
the reset outcome comes back through DVSEC STATUS2 for the guest to poll.

A CXL port masks Secondary Bus Reset by default, so a
VFIO_DEVICE_PCI_HOT_RESET does not reach the endpoint and the HDM state is
untouched; a hot reset no longer rejects sibling functions. If the port has
SBR unmasked the reset can decommit the decoder without restoring it, so the
reset_done handler gates HDM access; a later VFIO_DEVICE_RESET runs the CXL
reset sequence and restores it.

A bound CXL Type-2 device is kept out of idle D3. Powering a Type-2 function
down and back up reinitializes it and discards its coherent memory, which
only the accelerator's own driver re-initializes, so vfio-cxl sets
disable_idle_d3 to keep the device in D0 while it is bound.


Validation
----------

  - Each patch builds (drivers/cxl and drivers/vfio) and passes
    scripts/checkpatch.pl --codespell --strict with no errors, warnings, or
    checks.
  - The series applies in sequence on the stated base and dependencies.
  - The coherent CXL.mem range is mapped into the guest IOAS through the
    in-series dma-buf export (IOMMU_IOAS_MAP_FILE); the out-of-tree PFNMAP
    workaround v4 required for device-side ATS is no longer needed.
  - A selftest, tools/testing/selftests/vfio/vfio_cxl_type2_test.c,
    exercises region discovery, the sparse mmap, the huge-page fault, the
    dma-buf IOAS map, the live decoder reads, aligned/range access rejects,
    the commit/lock FSM, the DVSEC virtualization, and a real device reset.
  - Built and functionally tested against a CXL Type-2 device: guest boot,
    decoder commit and mapping, and guest-triggered CXL reset.


Follow-on UAPI
--------------

- The trapped component-register region spans the whole HDM decoder block,
  so a multi-decoder device needs no new region or cap: a VMM reads the
  decoder count and each committed base from every decoder in the block.
- The COMP_REGS geometry cap keeps a reserved field as a versioning anchor.
- Further trapped surfaces such as CXL RAS are planned as new CXL region
  subtypes rather than by extending this cap.
- The single committed, non-interleaved decoder is a bind-time policy in one
  place, not an ABI assumption, so multi-decoder and switched topologies
  relax only there.


Deferred
--------

  - Topology reach. Switched, multi-decoder, and interleaved decoders stay
    rejected at bind.
  - Non firmware-committed decoder support.


AI assistance disclosure
------------------------

This series was developed with substantial AI assistance (Anthropic Claude,
via the Claude Code CLI), used for design exploration and trade-off
analysis, multi-agent regression and adversarial review against the v4
feedback, and drafting the selftests and the documentation. Following
Documentation/process/coding-assistants.rst, each patch carries an
Assisted-by: LLM tag. Build, checkpatch, and on-hardware functional
testing were done by me, not the assistant. I have reviewed every change
and take full DCO responsibility for the series.


References
----------

[1] [PATCH v12 00/12] PCI/CXL: Add CXL reset support for Type 2 devices
https://lore.kernel.org/linux-cxl/20260910070808.1444264-1-smadhavan@nvidia.com/

[2] [PATCH v4 00/27] vfio/pci: Add CXL Type-2 device passthrough support
https://lore.kernel.org/linux-cxl/20260813093631.2288172-1-mhonap@nvidia.com


Manish Honap (27):
  cxl/regs: Split the BAR block request and ioremap helpers
  cxl/regs: Let a BAR-owning driver own the component register block
  cxl: Move component register defines to uapi/cxl/cxl_regs.h
  cxl: Add cxl_reset_dvsec_sequence() for vfio-pci
  vfio/pci: Add the CXL provider ops registration interface
  vfio/pci: Detect CXL devices and load the CXL provider on demand
  vfio/pci: Honor -EPROBE_DEFER from CXL provider probe
  vfio/pci: Fall back to plain vfio-pci when CXL init fails
  vfio/pci: Add a generic excluded-range list
  vfio/pci: Migrate MSI-X exclusion onto the generic excluded-range list
  vfio/pci: Virtualize the CXL DVSEC in vfio_pci_config.c
  vfio/pci: Call the CXL open and close hooks around device use
  vfio/pci: Bracket PCI resets with the CXL reset hooks
  vfio/pci: Provide an opt-out for the CXL Type-2 extensions
  vfio/cxl: Add the vfio-cxl provider module skeleton
  vfio/cxl: Create the CXL memdev and set media ready at bind
  vfio/cxl: Own the whole component register BAR
  vfio/cxl: Expose the HDM memory region to the guest
  vfio/cxl: Contain HDM memory errors with memory_failure()
  vfio/cxl: Expose the HDM decoder registers read-only to the guest
  vfio/cxl: Exclude the HDM decoder registers from direct BAR access
  vfio/cxl: Clear the HDM access gate after a hot reset
  vfio/cxl: Describe the CXL device and decoder geometry to userspace
  vfio/cxl: Export the HDM memory region as a dma-buf
  vfio/cxl: Run the CXL reset at the vfio reset points
  Documentation: vfio-pci: Document CXL Type-2 device passthrough
  selftests/vfio: Add CXL Type-2 passthrough tests

 Documentation/driver-api/index.rst            |   1 +
 Documentation/driver-api/vfio-pci-cxl.rst     | 188 +++++
 MAINTAINERS                                   |  10 +
 drivers/cxl/core/regs.c                       |  35 +-
 drivers/cxl/core/resource.c                   |  53 ++
 drivers/cxl/cxl.h                             |  47 +-
 drivers/vfio/pci/Kconfig                      |   2 +
 drivers/vfio/pci/Makefile                     |   2 +
 drivers/vfio/pci/cxl/Kconfig                  |  11 +
 drivers/vfio/pci/cxl/Makefile                 |   3 +
 drivers/vfio/pci/cxl/vfio_cxl_core.c          | 704 ++++++++++++++++
 drivers/vfio/pci/vfio_pci.c                   |  13 +
 drivers/vfio/pci/vfio_pci_config.c            | 177 +++-
 drivers/vfio/pci/vfio_pci_core.c              | 544 +++++++++++-
 drivers/vfio/pci/vfio_pci_dmabuf.c            |  27 +-
 drivers/vfio/pci/vfio_pci_priv.h              |  10 +
 drivers/vfio/pci/vfio_pci_rdwr.c              |  50 +-
 include/cxl/cxl.h                             |  14 +
 include/cxl/pci.h                             |   3 +
 include/linux/vfio_pci_core.h                 |  40 +
 include/uapi/cxl/cxl_regs.h                   |  53 ++
 include/uapi/linux/vfio.h                     |  24 +
 tools/testing/selftests/vfio/Makefile         |   1 +
 .../vfio/lib/include/libvfio/iommu.h          |   3 +
 tools/testing/selftests/vfio/lib/iommu.c      |  29 +
 .../selftests/vfio/lib/vfio_pci_device.c      |  57 +-
 .../selftests/vfio/vfio_cxl_type2_test.c      | 780 ++++++++++++++++++
 27 files changed, 2789 insertions(+), 92 deletions(-)
 create mode 100644 Documentation/driver-api/vfio-pci-cxl.rst
 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 include/uapi/cxl/cxl_regs.h
 create mode 100644 tools/testing/selftests/vfio/vfio_cxl_type2_test.c

-- 
2.25.1


^ permalink raw reply	[flat|nested] 33+ messages in thread

end of thread, other threads:[~2026-09-17  8:48 UTC | newest]

Thread overview: 33+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-16 18:35 [PATCH v5 00/27] vfio/pci: Add CXL Type-2 device passthrough support mhonap
2026-09-16 18:35 ` [PATCH v5 01/27] cxl/regs: Split the BAR block request and ioremap helpers mhonap
2026-09-16 18:35 ` [PATCH v5 02/27] cxl/regs: Let a BAR-owning driver own the component register block mhonap
2026-09-16 18:35 ` [PATCH v5 03/27] cxl: Move component register defines to uapi/cxl/cxl_regs.h mhonap
2026-09-16 18:35 ` [PATCH v5 04/27] cxl: Add cxl_reset_dvsec_sequence() for vfio-pci mhonap
2026-09-16 18:35 ` [PATCH v5 05/27] vfio/pci: Add the CXL provider ops registration interface mhonap
2026-09-16 18:35 ` [PATCH v5 06/27] vfio/pci: Detect CXL devices and load the CXL provider on demand mhonap
2026-09-17  8:48   ` Richard Cheng
2026-09-16 18:35 ` [PATCH v5 07/27] vfio/pci: Honor -EPROBE_DEFER from CXL provider probe mhonap
2026-09-16 18:35 ` [PATCH v5 08/27] vfio/pci: Fall back to plain vfio-pci when CXL init fails mhonap
2026-09-16 18:35 ` [PATCH v5 09/27] vfio/pci: Add a generic excluded-range list mhonap
2026-09-16 18:35 ` [PATCH v5 10/27] vfio/pci: Migrate MSI-X exclusion onto the " mhonap
2026-09-16 18:35 ` [PATCH v5 11/27] vfio/pci: Virtualize the CXL DVSEC in vfio_pci_config.c mhonap
2026-09-16 18:35 ` [PATCH v5 12/27] vfio/pci: Call the CXL open and close hooks around device use mhonap
2026-09-16 18:35 ` [PATCH v5 13/27] vfio/pci: Bracket PCI resets with the CXL reset hooks mhonap
2026-09-16 18:35 ` [PATCH v5 14/27] vfio/pci: Provide an opt-out for the CXL Type-2 extensions mhonap
2026-09-16 18:35 ` [PATCH v5 15/27] vfio/cxl: Add the vfio-cxl provider module skeleton mhonap
2026-09-16 18:35 ` [PATCH v5 16/27] vfio/cxl: Create the CXL memdev and set media ready at bind mhonap
2026-09-16 18:35 ` [PATCH v5 17/27] vfio/cxl: Own the whole component register BAR mhonap
2026-09-16 18:35 ` [PATCH v5 18/27] vfio/cxl: Expose the HDM memory region to the guest mhonap
2026-09-16 18:35 ` [PATCH v5 19/27] vfio/cxl: Contain HDM memory errors with memory_failure() mhonap
2026-09-16 18:35 ` [PATCH v5 20/27] vfio/cxl: Expose the HDM decoder registers read-only to the guest mhonap
2026-09-16 18:35 ` [PATCH v5 21/27] vfio/cxl: Exclude the HDM decoder registers from direct BAR access mhonap
2026-09-17  7:28   ` Richard Cheng
2026-09-16 18:35 ` [PATCH v5 22/27] vfio/cxl: Clear the HDM access gate after a hot reset mhonap
2026-09-16 18:35 ` [PATCH v5 23/27] vfio/cxl: Describe the CXL device and decoder geometry to userspace mhonap
2026-09-16 18:35 ` [PATCH v5 24/27] vfio/cxl: Export the HDM memory region as a dma-buf mhonap
2026-09-17  7:55   ` Richard Cheng
2026-09-16 18:35 ` [PATCH v5 25/27] vfio/cxl: Run the CXL reset at the vfio reset points mhonap
2026-09-17  8:11   ` Richard Cheng
2026-09-16 18:35 ` [PATCH v5 26/27] Documentation: vfio-pci: Document CXL Type-2 device passthrough mhonap
2026-09-16 19:33   ` Gregory Price
2026-09-16 18:35 ` [PATCH v5 27/27] selftests/vfio: Add CXL Type-2 passthrough tests mhonap

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®