From: Vipin Sharma vipinsh@google.com
Do not reset the device when a Live Update preserved vfio-pci device is retrieved and first enabled. vfio_pci_liveupdate_freeze() guarantees the device is reset prior to Live Update, so there's no reason to reset it again after Live Update.
Since VFIO normally uses the initial reset to detect if the device supports function resets, pass that from the previous kernel via struct vfio_pci_core_dev_ser.
Signed-off-by: Vipin Sharma vipinsh@google.com Signed-off-by: David Matlack dmatlack@google.com --- drivers/vfio/pci/vfio_pci_core.c | 22 +++++++++++++++++----- drivers/vfio/pci/vfio_pci_liveupdate.c | 1 + include/linux/kho/abi/vfio_pci.h | 2 ++ include/linux/vfio_pci_core.h | 1 + 4 files changed, 21 insertions(+), 5 deletions(-)
diff --git a/drivers/vfio/pci/vfio_pci_core.c b/drivers/vfio/pci/vfio_pci_core.c index b09fe0993e04..c3b30f08a788 100644 --- a/drivers/vfio/pci/vfio_pci_core.c +++ b/drivers/vfio/pci/vfio_pci_core.c @@ -482,12 +482,24 @@ int vfio_pci_core_enable(struct vfio_pci_core_device *vdev) if (ret) goto out_power;
- /* If reset fails because of the device lock, fail this path entirely */ - ret = pci_try_reset_function(pdev); - if (ret == -EAGAIN) - goto out_disable_device; + if (vdev->liveupdate_state) { + /* + * This device was handed off by vfio-pci from a previous kernel + * via Live Update, so it does not need to be reset. + */ + vdev->reset_works = vdev->liveupdate_state->reset_works; + } else { + /* + * If reset fails because of the device lock, fail this path + * entirely. + */ + ret = pci_try_reset_function(pdev); + if (ret == -EAGAIN) + goto out_disable_device; + + vdev->reset_works = !ret; + }
- vdev->reset_works = !ret; pci_save_state(pdev); vdev->pci_saved_state = pci_store_saved_state(pdev); if (!vdev->pci_saved_state) diff --git a/drivers/vfio/pci/vfio_pci_liveupdate.c b/drivers/vfio/pci/vfio_pci_liveupdate.c index 0fb29bd3ae3b..bcaf9de8a823 100644 --- a/drivers/vfio/pci/vfio_pci_liveupdate.c +++ b/drivers/vfio/pci/vfio_pci_liveupdate.c @@ -59,6 +59,7 @@ static int vfio_pci_liveupdate_preserve(struct liveupdate_file_op_args *args)
ser->bdf = pci_dev_id(pdev); ser->domain = pci_domain_nr(pdev->bus); + ser->reset_works = vdev->reset_works;
err = kho_preserve_folio(folio); if (err) diff --git a/include/linux/kho/abi/vfio_pci.h b/include/linux/kho/abi/vfio_pci.h index 9bf58a2f3820..6c3d3c6dfc09 100644 --- a/include/linux/kho/abi/vfio_pci.h +++ b/include/linux/kho/abi/vfio_pci.h @@ -34,10 +34,12 @@ * * @bdf: The device's PCI bus, device, and function number. * @domain: The device's PCI domain number (segment). + * @reset_works: Non-zero if the device supports function resets. */ struct vfio_pci_core_device_ser { u16 bdf; u16 domain; + u8 reset_works; } __packed;
#endif /* _LINUX_LIVEUPDATE_ABI_VFIO_PCI_H */ diff --git a/include/linux/vfio_pci_core.h b/include/linux/vfio_pci_core.h index 56ff6452562d..3421721a1615 100644 --- a/include/linux/vfio_pci_core.h +++ b/include/linux/vfio_pci_core.h @@ -15,6 +15,7 @@ #include <linux/types.h> #include <linux/uuid.h> #include <linux/notifier.h> +#include <linux/kho/abi/vfio_pci.h>
#ifndef VFIO_PCI_CORE_H #define VFIO_PCI_CORE_H