RE: [PATCH v3 08/11] vfio/pci/cxl: Add HDM + COMP_REGS regions and DVSEC clipping shim
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 | <IA1PR12MB90302564411A6FAE9FB5A97EBDFA2@IA1PR12MB9030.namprd12.prod.outlook.com> |
> -----Original Message----- > From: Alex Williamson <[email protected]> > Sent: 11 July 2026 03:53 > To: Manish Honap <[email protected]> > Cc: [email protected]; [email protected]; [email protected]; > [email protected]; Ankit Agrawal <[email protected]>; > [email protected]; [email protected]; > [email protected]; [email protected]; [email protected]; > [email protected]; Neo Jia <[email protected]>; Krishnakant Jaju > <[email protected]>; Vikram Sethi <[email protected]>; Zhi Wang > <[email protected]>; [email protected]; [email protected]; > [email protected]; [email protected]; linux- > [email protected]; [email protected] > Subject: Re: [PATCH v3 08/11] vfio/pci/cxl: Add HDM + COMP_REGS regions > and DVSEC clipping shim > > External email: Use caution opening links or attachments > > > On Thu, 25 Jun 2026 22:24:04 +0530 > <[email protected]> wrote: > > diff --git a/drivers/vfio/pci/vfio_pci_config.c > > b/drivers/vfio/pci/vfio_pci_config.c > > index a10ed733f0e3..b9f30a33515a 100644 > > --- a/drivers/vfio/pci/vfio_pci_config.c > > +++ b/drivers/vfio/pci/vfio_pci_config.c > > @@ -1898,8 +1898,15 @@ ssize_t vfio_pci_config_rw_single(struct > vfio_pci_core_device *vdev, > > /* > > * Chop accesses into aligned chunks containing no more than a > > * single capability. Caller increments to the next chunk. > > + * > > + * For CXL Type-2 devices also clip at the CXL Device DVSEC body > > + * boundary so the generic perm-bits path handles the DVSEC > > + * header bytes and the CXL hook handles the body bytes; without > > + * this clip a 32-bit access at dvsec + 0x08 would span the > > + * generic Header2 word and the CXL CAPABILITY word. > > */ > > count = min(count, vfio_pci_cap_remaining_dword(vdev, *ppos)); > > + count = min(count, vfio_pci_cxl_config_boundary(vdev, *ppos)); > > if (count >= 4 && !(*ppos % 4)) > > count = 4; > > else if (count >= 2 && !(*ppos % 2)) @@ -1909,6 +1916,30 @@ > > ssize_t vfio_pci_config_rw_single(struct vfio_pci_core_device *vdev, > > > > ret = count; > > > > + /* > > + * Give the CXL Type-2 hook first claim on this access: if the > > + * range lies inside the CXL Device DVSEC body, forward it to > > + * cxl-core's register-virtualization helpers instead of the > > + * standard perm-bits path. -ENOENT means "not for me; use the > > + * default path"; any other negative value is a hard error. > > + */ > > + if (vdev->cxl) { > > + __le32 le_val = 0; > > + ssize_t cxl_ret; > > + > > + if (iswrite && copy_from_user(&le_val, buf, count)) > > + return -EFAULT; > > + cxl_ret = vfio_pci_cxl_config_rw(vdev, *ppos, count, > &le_val, > > + iswrite); > > + if (cxl_ret >= 0) { > > + if (!iswrite && copy_to_user(buf, &le_val, > count)) > > + return -EFAULT; > > + return cxl_ret; > > + } > > + if (cxl_ret != -ENOENT) > > + return cxl_ret; > > + } > > + > > I think the solution here is just to set the .readfn and .writefn for > PCI_EXT_CAP_ID_DVSEC to dvsec specific handlers, rather than the raw > write and direct read handlers. The new handlers would detect whether > the reference is to the CXL DVSEC body, possibly via ranges stored in > vdev->cxl, and either call through to CXL handlers via cxl_ops > (previously suggested), or fall through to the raw/direct handlers. okay, I will have handling for this in v4. > > > cap_id = vdev->pci_config_map[*ppos]; > > > > if (cap_id == PCI_CAP_ID_INVALID) { diff --git > > a/drivers/vfio/pci/vfio_pci_core.c b/drivers/vfio/pci/vfio_pci_core.c > > index 05ab4ae59157..2d2dae278d1e 100644 > > --- a/drivers/vfio/pci/vfio_pci_core.c > > +++ b/drivers/vfio/pci/vfio_pci_core.c > > @@ -501,6 +501,23 @@ static void vfio_pci_core_map_bars(struct > vfio_pci_core_device *vdev) > > if (!pci_resource_len(pdev, i)) > > continue; > > > > + /* > > + * cxl-core already holds request_mem_region() on the > CXL > > + * component register sub-range of this BAR. Skip the > > + * full-BAR request so we do not collide with that > > + * sub-region; vfio still owns the BAR via the driver > > + * binding and the iomap below succeeds without a region > > + * claim. > > + */ > > + if (vdev->cxl && bar == > vfio_pci_cxl_get_component_reg_bar(vdev)) { > > + vdev->barmap[bar] = pci_iomap(pdev, bar, 0); > > + if (!vdev->barmap[bar]) { > > + pci_dbg(pdev, "Failed to iomap region > %d\n", bar); > > + vdev->barmap[bar] = IOMEM_ERR_PTR(- > ENOMEM); > > + } > > + continue; > > + } > > + > > if (pci_request_selected_regions(pdev, 1 << bar, > "vfio")) { > > pci_dbg(pdev, "Failed to reserve region %d\n", > bar); > > vdev->barmap[bar] = IOMEM_ERR_PTR(-EBUSY); @@ > > -701,7 +718,10 @@ void vfio_pci_core_disable(struct > vfio_pci_core_device *vdev) > > if (IS_ERR_OR_NULL(vdev->barmap[bar])) > > continue; > > pci_iounmap(pdev, vdev->barmap[bar]); > > - pci_release_selected_regions(pdev, 1 << bar); > > + /* Mirror the asymmetric setup-time skip in map_bars(). > */ > > + if (!(vdev->cxl && > > + i == vfio_pci_cxl_get_component_reg_bar(vdev))) > > + pci_release_selected_regions(pdev, 1 << bar); > > It would be much less ugly to create > vfio_pci_{request,release}_selected_region() wrappers that mask whether > the region is actually requested or released than to disrupt the code > flow like this. Likewise below, think about creating wrappers that do > the right thing for cxl and are no-ops otherwise. For example, embed > the vdev->cxl test into the function to cleanup the callers. Thanks, > Agreed. I will add helper routines for this as suggested. > Alex > > > vdev->barmap[bar] = NULL; > > } > > > > @@ -1051,6 +1071,16 @@ static int vfio_pci_ioctl_get_info(struct > vfio_pci_core_device *vdev, > > info.num_regions = VFIO_PCI_NUM_REGIONS + vdev->num_regions; > > info.num_irqs = VFIO_PCI_NUM_IRQS; > > > > + if (vdev->cxl) { > > + ret = vfio_pci_cxl_get_info(vdev, &caps); > > + if (ret) { > > + pci_warn(vdev->pdev, > > + "Failed to add CXL info capability\n"); > > + return ret; > > + } > > + info.flags |= VFIO_DEVICE_FLAGS_CXL; > > + } > > + > > ret = vfio_pci_info_zdev_add_caps(vdev, &caps); > > if (ret && ret != -ENODEV) { > > pci_warn(vdev->pdev, > > @@ -1093,6 +1123,12 @@ int vfio_pci_ioctl_get_region_info(struct > vfio_device *core_vdev, > > struct pci_dev *pdev = vdev->pdev; > > int i, ret; > > > > + if (vdev->cxl) { > > + ret = vfio_pci_cxl_get_region_info(vdev, info, caps); > > + if (ret != -ENOTTY) > > + return ret; > > + } > > + > > switch (info->index) { > > case VFIO_PCI_CONFIG_REGION_INDEX: > > info->offset = VFIO_PCI_INDEX_TO_OFFSET(info->index);