vfio: unplug failover primary device before migration

As usual block all vfio-pci devices from being migrated, but make an
exception for failover primary devices. This is achieved by setting
unmigratable to 0 but also add a migration blocker for all vfio-pci
devices except failover primary devices. These will be unplugged before
migration happens by the migration handler of the corresponding
virtio-net standby device.

Signed-off-by: Jens Freimann <jfreimann@redhat.com>
Acked-by: Alex Williamson <alex.williamson@redhat.com>
Message-Id: <20191029114905.6856-12-jfreimann@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
Jens Freimann 2019-10-29 12:49:05 +01:00 committed by Michael S. Tsirkin
parent 9711cd0dfc
commit f045a0104c
2 changed files with 21 additions and 6 deletions

View File

@ -40,6 +40,7 @@
#include "pci.h" #include "pci.h"
#include "trace.h" #include "trace.h"
#include "qapi/error.h" #include "qapi/error.h"
#include "migration/blocker.h"
#define TYPE_VFIO_PCI "vfio-pci" #define TYPE_VFIO_PCI "vfio-pci"
#define PCI_VFIO(obj) OBJECT_CHECK(VFIOPCIDevice, obj, TYPE_VFIO_PCI) #define PCI_VFIO(obj) OBJECT_CHECK(VFIOPCIDevice, obj, TYPE_VFIO_PCI)
@ -2732,6 +2733,17 @@ static void vfio_realize(PCIDevice *pdev, Error **errp)
return; return;
} }
if (!pdev->failover_pair_id) {
error_setg(&vdev->migration_blocker,
"VFIO device doesn't support migration");
ret = migrate_add_blocker(vdev->migration_blocker, &err);
if (err) {
error_propagate(errp, err);
error_free(vdev->migration_blocker);
return;
}
}
vdev->vbasedev.name = g_path_get_basename(vdev->vbasedev.sysfsdev); vdev->vbasedev.name = g_path_get_basename(vdev->vbasedev.sysfsdev);
vdev->vbasedev.ops = &vfio_pci_ops; vdev->vbasedev.ops = &vfio_pci_ops;
vdev->vbasedev.type = VFIO_DEVICE_TYPE_PCI; vdev->vbasedev.type = VFIO_DEVICE_TYPE_PCI;
@ -3008,6 +3020,10 @@ out_teardown:
vfio_bars_exit(vdev); vfio_bars_exit(vdev);
error: error:
error_prepend(errp, VFIO_MSG_PREFIX, vdev->vbasedev.name); error_prepend(errp, VFIO_MSG_PREFIX, vdev->vbasedev.name);
if (vdev->migration_blocker) {
migrate_del_blocker(vdev->migration_blocker);
error_free(vdev->migration_blocker);
}
} }
static void vfio_instance_finalize(Object *obj) static void vfio_instance_finalize(Object *obj)
@ -3019,6 +3035,10 @@ static void vfio_instance_finalize(Object *obj)
vfio_bars_finalize(vdev); vfio_bars_finalize(vdev);
g_free(vdev->emulated_config_bits); g_free(vdev->emulated_config_bits);
g_free(vdev->rom); g_free(vdev->rom);
if (vdev->migration_blocker) {
migrate_del_blocker(vdev->migration_blocker);
error_free(vdev->migration_blocker);
}
/* /*
* XXX Leaking igd_opregion is not an oversight, we can't remove the * XXX Leaking igd_opregion is not an oversight, we can't remove the
* fw_cfg entry therefore leaking this allocation seems like the safest * fw_cfg entry therefore leaking this allocation seems like the safest
@ -3151,11 +3171,6 @@ static Property vfio_pci_dev_properties[] = {
DEFINE_PROP_END_OF_LIST(), DEFINE_PROP_END_OF_LIST(),
}; };
static const VMStateDescription vfio_pci_vmstate = {
.name = "vfio-pci",
.unmigratable = 1,
};
static void vfio_pci_dev_class_init(ObjectClass *klass, void *data) static void vfio_pci_dev_class_init(ObjectClass *klass, void *data)
{ {
DeviceClass *dc = DEVICE_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass);
@ -3163,7 +3178,6 @@ static void vfio_pci_dev_class_init(ObjectClass *klass, void *data)
dc->reset = vfio_pci_reset; dc->reset = vfio_pci_reset;
dc->props = vfio_pci_dev_properties; dc->props = vfio_pci_dev_properties;
dc->vmsd = &vfio_pci_vmstate;
dc->desc = "VFIO-based PCI device assignment"; dc->desc = "VFIO-based PCI device assignment";
set_bit(DEVICE_CATEGORY_MISC, dc->categories); set_bit(DEVICE_CATEGORY_MISC, dc->categories);
pdc->realize = vfio_realize; pdc->realize = vfio_realize;

View File

@ -168,6 +168,7 @@ typedef struct VFIOPCIDevice {
bool no_vfio_ioeventfd; bool no_vfio_ioeventfd;
bool enable_ramfb; bool enable_ramfb;
VFIODisplay *dpy; VFIODisplay *dpy;
Error *migration_blocker;
} VFIOPCIDevice; } VFIOPCIDevice;
uint32_t vfio_pci_read_config(PCIDevice *pdev, uint32_t addr, int len); uint32_t vfio_pci_read_config(PCIDevice *pdev, uint32_t addr, int len);