[PATCH v5 05/27] vfio/pci: Add the CXL provider ops registration interface
From: mhonap
Date: Wed Sep 16 2026 - 16:32:52 EST
From: Manish Honap <mhonap@xxxxxxxxxx>
vfio-pci-core must stay free of any CXL header dependency, so CXL Type-2
handling lives in a separate vfio-cxl module that plugs in a set of
callbacks.
Add the registration interface:
- vfio-cxl registers a single struct vfio_cxl_ops at module_init
- vfio-pci-core stores it under an rwsem.
A second registration is refused with -EBUSY.
The owner field will be used to pin vfio-cxl for the lifetime of each
bound CXL device.
Assisted-by: LLM
Signed-off-by: Manish Honap <mhonap@xxxxxxxxxx>
---
drivers/vfio/pci/vfio_pci_core.c | 24 ++++++++++++++++++++++++
include/linux/vfio_pci_core.h | 10 ++++++++++
2 files changed, 34 insertions(+)
diff --git a/drivers/vfio/pci/vfio_pci_core.c b/drivers/vfio/pci/vfio_pci_core.c
index 6757054e9d87..2cc5dd20396c 100644
--- a/drivers/vfio/pci/vfio_pci_core.c
+++ b/drivers/vfio/pci/vfio_pci_core.c
@@ -2178,6 +2178,30 @@ static void vfio_pci_vga_uninit(struct vfio_pci_core_device *vdev)
VGA_RSRC_LEGACY_MEM);
}
+static const struct vfio_cxl_ops *vfio_pci_cxl_ops;
+static DECLARE_RWSEM(vfio_pci_cxl_ops_rwsem);
+
+int vfio_pci_core_register_cxl_ops(const struct vfio_cxl_ops *ops)
+{
+ guard(rwsem_write)(&vfio_pci_cxl_ops_rwsem);
+
+ if (vfio_pci_cxl_ops)
+ return -EBUSY;
+
+ vfio_pci_cxl_ops = ops;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(vfio_pci_core_register_cxl_ops);
+
+void vfio_pci_core_unregister_cxl_ops(const struct vfio_cxl_ops *ops)
+{
+ guard(rwsem_write)(&vfio_pci_cxl_ops_rwsem);
+
+ if (vfio_pci_cxl_ops == ops)
+ vfio_pci_cxl_ops = NULL;
+}
+EXPORT_SYMBOL_GPL(vfio_pci_core_unregister_cxl_ops);
+
int vfio_pci_core_init_dev(struct vfio_device *core_vdev)
{
struct vfio_pci_core_device *vdev =
diff --git a/include/linux/vfio_pci_core.h b/include/linux/vfio_pci_core.h
index 9a1674c152aa..9fe0d1a3a370 100644
--- a/include/linux/vfio_pci_core.h
+++ b/include/linux/vfio_pci_core.h
@@ -66,6 +66,16 @@ struct vfio_pci_device_ops {
size_t nr_ranges);
};
+struct vfio_cxl_ops {
+ int (*init)(struct vfio_pci_core_device *vdev);
+ void (*release)(struct vfio_pci_core_device *vdev);
+ /* Pinned per bound CXL device so vfio-cxl cannot unload under usage */
+ struct module *owner;
+};
+
+int vfio_pci_core_register_cxl_ops(const struct vfio_cxl_ops *ops);
+void vfio_pci_core_unregister_cxl_ops(const struct vfio_cxl_ops *ops);
+
#if IS_ENABLED(CONFIG_VFIO_PCI_DMABUF)
int vfio_pci_core_fill_phys_vec(struct phys_vec *phys_vec,
struct vfio_region_dma_range *dma_ranges,
--
2.25.1