@@ -177,6 +177,7 @@ struct VFIOPCIDevice {
OnOffAuto ramfb_migrate;
bool defer_kvm_irq_routing;
bool clear_parent_atomics_on_exit;
+ bool skip_vsc_check;
VFIODisplay *dpy;
Notifier irqchip_change_notifier;
};
@@ -35,6 +35,7 @@
GlobalProperty hw_compat_9_0[] = {
{"arm-cpu", "backcompat-cntfrq", "true" },
+ {"vfio-pci", "skip-vsc-check", "false" },
};
const size_t hw_compat_9_0_len = G_N_ELEMENTS(hw_compat_9_0);
@@ -2134,6 +2134,28 @@ static void vfio_check_af_flr(VFIOPCIDevice *vdev, uint8_t pos)
}
}
+static int vfio_add_vendor_specific_cap(VFIOPCIDevice *vdev, int pos,
+ uint8_t size, Error **errp)
+{
+ PCIDevice *pdev = &vdev->pdev;
+
+ pos = pci_add_capability(pdev, PCI_CAP_ID_VNDR, pos, size, errp);
+ if (pos < 0) {
+ return pos;
+ }
+
+ /*
+ * Exempt config space check for Vendor Specific Information during
+ * restore/load.
+ * Config space check is still enforced for 3 byte VSC header.
+ */
+ if (vdev->skip_vsc_check && size > 3) {
+ memset(pdev->cmask + pos + 3, 0, size - 3);
+ }
+
+ return pos;
+}
+
static int vfio_add_std_cap(VFIOPCIDevice *vdev, uint8_t pos, Error **errp)
{
ERRP_GUARD();
@@ -2202,6 +2224,9 @@ static int vfio_add_std_cap(VFIOPCIDevice *vdev, uint8_t pos, Error **errp)
vfio_check_af_flr(vdev, pos);
ret = pci_add_capability(pdev, cap_id, pos, size, errp);
break;
+ case PCI_CAP_ID_VNDR:
+ ret = vfio_add_vendor_specific_cap(vdev, pos, size, errp);
+ break;
default:
ret = pci_add_capability(pdev, cap_id, pos, size, errp);
break;
@@ -3391,6 +3416,7 @@ static Property vfio_pci_dev_properties[] = {
DEFINE_PROP_LINK("iommufd", VFIOPCIDevice, vbasedev.iommufd,
TYPE_IOMMUFD_BACKEND, IOMMUFDBackend *),
#endif
+ DEFINE_PROP_BOOL("skip-vsc-check", VFIOPCIDevice, skip_vsc_check, true),
DEFINE_PROP_END_OF_LIST(),
};