This allows a device to migrate if it meet a few requirements. Signed-off-by: Eugenio Pérez <eperezma@xxxxxxxxxx> --- hw/virtio/vhost.c | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index cf000b979f..44a51ccf5e 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -1529,6 +1529,37 @@ static void vhost_virtqueue_cleanup(struct vhost_virtqueue *vq) event_notifier_cleanup(&vq->masked_notifier); } +static bool vhost_hdev_can_sw_lm(struct vhost_dev *hdev) +{ + const char *cause = NULL; + + if (hdev->features & (VIRTIO_F_IOMMU_PLATFORM)) { + cause = "have iommu"; + } else if (hdev->features & VIRTIO_F_RING_PACKED) { + cause = "is packed"; + } else if (hdev->features & VIRTIO_RING_F_EVENT_IDX) { + cause = "Have event idx"; + } else if (hdev->features & VIRTIO_RING_F_INDIRECT_DESC) { + cause = "Supports indirect descriptors"; + } else if (hdev->nvqs != 2) { + cause = "!= 2 #vq supported"; + } else if (!hdev->vhost_ops->vhost_net_set_backend) { + cause = "cannot pause device"; + } + + if (cause) { + if (!hdev->migration_blocker) { + error_setg(&hdev->migration_blocker, + "Migration disabled: vhost lacks VHOST_F_LOG_ALL feature and %s.", + cause); + } + + return false; + } + + return true; +} + int vhost_dev_init(struct vhost_dev *hdev, void *opaque, VhostBackendType backend_type, uint32_t busyloop_timeout) { @@ -1604,7 +1635,8 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque, }; if (hdev->migration_blocker == NULL) { - if (!vhost_dev_can_log(hdev)) { + if (!vhost_dev_can_log(hdev) && !vhost_hdev_can_sw_lm(hdev) + && hdev->migration_blocker == NULL) { error_setg(&hdev->migration_blocker, "Migration disabled: vhost lacks VHOST_F_LOG_ALL feature."); } else if (vhost_dev_log_is_shared(hdev) && !qemu_memfd_alloc_check()) { -- 2.18.4