[PATCH v5 23/27] vfio/cxl: Describe the CXL device and decoder geometry to userspace
From: mhonap
Date: Wed Sep 16 2026 - 14:56:46 EST
From: Manish Honap <mhonap@xxxxxxxxxx>
Advertise the assignment with a device-info flag so a VMM can tell a CXL
Type-2 device apart from a plain vfio-pci one. On the trapped decoder
register region, add a capability carrying the BAR and offset of the HDM
decoder block so the VMM can place the trapped window where the guest
expects to find it and size the guest's fixed memory window.
Assisted-by: LLM
Signed-off-by: Manish Honap <mhonap@xxxxxxxxxx>
---
drivers/vfio/pci/cxl/vfio_cxl_core.c | 16 ++++++++++++++++
drivers/vfio/pci/vfio_pci_core.c | 3 +++
include/uapi/linux/vfio.h | 18 ++++++++++++++++++
3 files changed, 37 insertions(+)
diff --git a/drivers/vfio/pci/cxl/vfio_cxl_core.c b/drivers/vfio/pci/cxl/vfio_cxl_core.c
index 395b4a5b0956..5fe8e35c63c4 100644
--- a/drivers/vfio/pci/cxl/vfio_cxl_core.c
+++ b/drivers/vfio/pci/cxl/vfio_cxl_core.c
@@ -261,9 +261,25 @@ static ssize_t vfio_cxl_comp_rw(struct vfio_pci_core_device *vdev,
return count;
}
+static int vfio_cxl_comp_add_capability(struct vfio_pci_core_device *vdev,
+ struct vfio_pci_region *region,
+ struct vfio_info_cap *caps)
+{
+ struct cxl_hdm_info *hdm = vdev->pdev->hdm;
+ struct vfio_region_info_cap_cxl_comp_regs cap = {
+ .header.id = VFIO_REGION_INFO_CAP_CXL_COMP_REGS,
+ .header.version = 1,
+ .bar = hdm->hdm_bar,
+ .offset = hdm->hdm_offset,
+ };
+
+ return vfio_info_add_capability(caps, &cap.header, sizeof(cap));
+}
+
static const struct vfio_pci_regops vfio_cxl_comp_regops = {
.rw = vfio_cxl_comp_rw,
.release = vfio_cxl_region_release,
+ .add_capability = vfio_cxl_comp_add_capability,
};
static void vfio_cxl_release_hpa(void *data)
diff --git a/drivers/vfio/pci/vfio_pci_core.c b/drivers/vfio/pci/vfio_pci_core.c
index 8913a9e24302..f02a5240aa71 100644
--- a/drivers/vfio/pci/vfio_pci_core.c
+++ b/drivers/vfio/pci/vfio_pci_core.c
@@ -1364,6 +1364,9 @@ static int vfio_pci_ioctl_get_info(struct vfio_pci_core_device *vdev,
if (vdev->reset_works)
info.flags |= VFIO_DEVICE_FLAGS_RESET;
+ if (vdev->cxl_ops)
+ info.flags |= VFIO_DEVICE_FLAGS_CXL;
+
info.num_regions = VFIO_PCI_NUM_REGIONS + vdev->num_regions;
info.num_irqs = VFIO_PCI_NUM_IRQS;
diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h
index 8927a7a4e8e4..8f9518f09bd0 100644
--- a/include/uapi/linux/vfio.h
+++ b/include/uapi/linux/vfio.h
@@ -215,6 +215,7 @@ struct vfio_device_info {
#define VFIO_DEVICE_FLAGS_FSL_MC (1 << 6) /* vfio-fsl-mc device */
#define VFIO_DEVICE_FLAGS_CAPS (1 << 7) /* Info supports caps */
#define VFIO_DEVICE_FLAGS_CDX (1 << 8) /* vfio-cdx device */
+#define VFIO_DEVICE_FLAGS_CXL (1 << 9) /* vfio-cxl device */
__u32 num_regions; /* Max region index + 1 */
__u32 num_irqs; /* Max IRQ index + 1 */
__u32 cap_offset; /* Offset within info struct of first cap */
@@ -503,6 +504,23 @@ struct vfio_region_info_cap_nvlink2_lnkspd {
__u32 __pad;
};
+/*
+ * Geometry of a CXL Type-2 device's HDM decoder registers, so a VMM can place
+ * the trapped component register window where the guest expects it. The trapped
+ * region spans the whole HDM decoder block (every decoder), not just decoder 0:
+ * a VMM reads the decoder count and each decoder's committed base from the block
+ * itself. Additional trapped component capabilities, such as CXL RAS, are
+ * exposed as their own region subtypes rather than by extending this cap.
+ */
+#define VFIO_REGION_INFO_CAP_CXL_COMP_REGS 6
+
+struct vfio_region_info_cap_cxl_comp_regs {
+ struct vfio_info_cap_header header;
+ __u32 bar;
+ __u32 __resv;
+ __aligned_u64 offset;
+};
+
/**
* VFIO_DEVICE_GET_IRQ_INFO - _IOWR(VFIO_TYPE, VFIO_BASE + 9,
* struct vfio_irq_info)
--
2.25.1