[RFC PATCH 3/5] vfio/pci: Refuse to reset an SR-IOV PF with enabled VFs

Alex Williamson <[email protected]>
Newsgroups org.kernel.vger.linux-pci,org.kernel.vger.kvm,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
The vfio-pci hot-reset interface VFIO_DEVICE_PCI_HOT_RESET does not
take into account whether an SR-IOV PF has active VFs.  The VFs appear
on a virtual bus, which is not enumerated in collecting affected
devices.

Move the burden to the user when active VFs are present, require that
there are no VFs present on SR-IOV capable PFs in order to conduct a
hot reset.

Fixes: 137e5531351d ("vfio/pci: Add sriov_configure support")
Cc: [email protected]
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Alex Williamson <[email protected]>
---
 drivers/vfio/pci/vfio_pci_core.c | 15 +++++++++++++--
 include/uapi/linux/vfio.h        |  3 +++
 2 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/drivers/vfio/pci/vfio_pci_core.c b/drivers/vfio/pci/vfio_pci_core.c
index 9757b171791c..956a05ca12e5 100644
--- a/drivers/vfio/pci/vfio_pci_core.c
+++ b/drivers/vfio/pci/vfio_pci_core.c
@@ -894,6 +894,17 @@ static int vfio_pci_count_devs(struct pci_dev *pdev, void *data)
 	return 0;
 }
 
+/*
+ * PCI walk callback to check for SR-IOV PFs with active VFs.  VFs are not
+ * enumerated when determining affected devices and may be owned by separate
+ * userspace processes from the PF.  It's therefore the user's responsibility
+ * to teardown VFs for any affected PF before performing a hot-reset.
+ */
+static int vfio_pci_dev_has_vfs(struct pci_dev *pdev, void *data)
+{
+	return pci_num_vf(pdev) ? -EBUSY : 0;
+}
+
 struct vfio_pci_fill_info {
 	struct vfio_device *vdev;
 	struct vfio_pci_dependent_device *devices;
@@ -2598,7 +2609,7 @@ static int vfio_pci_dev_set_hot_reset(struct vfio_device_set *dev_set,
 	list_for_each_entry(vdev, &dev_set->device_list, vdev.dev_set_list)
 		vfio_pci_set_power_state(vdev, PCI_D0);
 
-	ret = pci_reset_bus(pdev);
+	ret = pci_reset_bus_cond(pdev, vfio_pci_dev_has_vfs, NULL);
 
 	vdev = list_last_entry(&dev_set->device_list,
 			       struct vfio_pci_core_device, vdev.dev_set_list);
@@ -2661,7 +2672,7 @@ static void vfio_pci_dev_set_try_reset(struct vfio_device_set *dev_set)
 	if (vfio_pci_dev_set_pm_runtime_get(dev_set))
 		return;
 
-	if (!pci_reset_bus(pdev))
+	if (!pci_reset_bus_cond(pdev, vfio_pci_dev_has_vfs, NULL))
 		reset_done = true;
 
 	list_for_each_entry(cur, &dev_set->device_list, vdev.dev_set_list) {
diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h
index 5de618a3a5ee..8603959f1735 100644
--- a/include/uapi/linux/vfio.h
+++ b/include/uapi/linux/vfio.h
@@ -772,6 +772,9 @@ struct vfio_pci_hot_reset_info {
  * Mixed usage of legacy groups and cdevs across the set of affected
  * devices is not supported.
  *
+ * Hot reset of SR-IOV PFs with active VFs is not supported, SR-IOV
+ * should first be disabled on any affected PF.
+ *
  * Return: 0 on success, -errno on failure.
  */
 struct vfio_pci_hot_reset {
-- 
2.53.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.