Notify the PCI subsystem about devices vfio-pci is preserving across Live Update by registering the vfio-pci liveupdate file handler with the PCI subsystem's FLB handler.
Notably this will ensure that devices preserved through vfio-pci do not go through auto-probing in the next kernel (i.e. preventing them from being bound to a different driver).
This also enables VFIO to detect that a device was preserved before userspace first retrieves the file from it, which will be used in subsequent commits.
Signed-off-by: David Matlack dmatlack@google.com --- drivers/vfio/pci/vfio_pci_liveupdate.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-)
diff --git a/drivers/vfio/pci/vfio_pci_liveupdate.c b/drivers/vfio/pci/vfio_pci_liveupdate.c index b7451007fca4..7669c65bde17 100644 --- a/drivers/vfio/pci/vfio_pci_liveupdate.c +++ b/drivers/vfio/pci/vfio_pci_liveupdate.c @@ -64,6 +64,7 @@ static int vfio_pci_liveupdate_preserve(struct liveupdate_file_op_args *args) if (err) goto error;
+ pci_liveupdate_outgoing_preserve(pdev); args->serialized_data = virt_to_phys(ser); return 0;
@@ -75,8 +76,10 @@ static int vfio_pci_liveupdate_preserve(struct liveupdate_file_op_args *args) static void vfio_pci_liveupdate_unpreserve(struct liveupdate_file_op_args *args) { struct vfio_pci_core_device_ser *ser = phys_to_virt(args->serialized_data); + struct vfio_device *device = vfio_device_from_file(args->file); struct folio *folio = virt_to_folio(ser);
+ pci_liveupdate_outgoing_unpreserve(to_pci_dev(device->dev)); kho_unpreserve_folio(folio); folio_put(folio); } @@ -199,8 +202,11 @@ static bool vfio_pci_liveupdate_can_finish(struct liveupdate_file_op_args *args)
static void vfio_pci_liveupdate_finish(struct liveupdate_file_op_args *args) { + struct vfio_device *device = vfio_device_from_file(args->file); struct folio *folio;
+ pci_liveupdate_incoming_finish(to_pci_dev(device->dev)); + folio = virt_to_folio(phys_to_virt(args->serialized_data)); folio_put(folio); } @@ -223,10 +229,24 @@ static struct liveupdate_file_handler vfio_pci_liveupdate_fh = {
int __init vfio_pci_liveupdate_init(void) { + int ret; + if (!liveupdate_enabled()) return 0;
- return liveupdate_register_file_handler(&vfio_pci_liveupdate_fh); + ret = liveupdate_register_file_handler(&vfio_pci_liveupdate_fh); + if (ret) + return ret; + + ret = pci_liveupdate_register_fh(&vfio_pci_liveupdate_fh); + if (ret) + goto error; + + return 0; + +error: + liveupdate_unregister_file_handler(&vfio_pci_liveupdate_fh); + return ret; }
void vfio_pci_liveupdate_cleanup(void) @@ -234,5 +254,6 @@ void vfio_pci_liveupdate_cleanup(void) if (!liveupdate_enabled()) return;
+ WARN_ON_ONCE(pci_liveupdate_unregister_fh(&vfio_pci_liveupdate_fh)); liveupdate_unregister_file_handler(&vfio_pci_liveupdate_fh); }