diff --git a/hw/core/machine.c b/hw/core/machine.c index 9b02fb2f5e..d7f4a0d259 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -44,6 +44,7 @@ GlobalProperty hw_compat_5_0[] = { { "vmport", "x-signal-unsupported-cmd", "off" }, { "vmport", "x-report-vmx-type", "off" }, { "vmport", "x-cmds-v2", "off" }, + { "virtio-device", "x-disable-legacy-check", "true" }, }; const size_t hw_compat_5_0_len = G_N_ELEMENTS(hw_compat_5_0); diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c index 8d140dc50f..4582e94ae7 100644 --- a/hw/s390x/virtio-ccw.c +++ b/hw/s390x/virtio-ccw.c @@ -1122,9 +1122,18 @@ static void virtio_ccw_device_plugged(DeviceState *d, Error **errp) } if (!virtio_ccw_rev_max(dev) && !virtio_legacy_allowed(vdev)) { - error_setg(errp, "Invalid value of property max_rev " - "(is %d expected >= 1)", virtio_ccw_rev_max(dev)); - return; + /* + * To avoid migration issues, we allow legacy mode when legacy + * check is disabled in the old machine types (< 5.1). + */ + if (virtio_legacy_check_disabled(vdev)) { + warn_report("device requires revision >= 1, but for backward " + "compatibility max_revision=0 is allowed"); + } else { + error_setg(errp, "Invalid value of property max_rev " + "(is %d expected >= 1)", virtio_ccw_rev_max(dev)); + return; + } } if (virtio_get_num_queues(vdev) > VIRTIO_QUEUE_MAX) { diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index 02790e3237..36524a5728 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -1597,8 +1597,18 @@ static void virtio_pci_device_plugged(DeviceState *d, Error **errp) if (legacy) { if (!virtio_legacy_allowed(vdev)) { - error_setg(errp, "device is modern-only, use disable-legacy=on"); - return; + /* + * To avoid migration issues, we allow legacy mode when legacy + * check is disabled in the old machine types (< 5.1). + */ + if (virtio_legacy_check_disabled(vdev)) { + warn_report("device is modern-only, but for backward " + "compatibility legacy is allowed"); + } else { + error_setg(errp, + "device is modern-only, use disable-legacy=on"); + return; + } } if (virtio_host_has_feature(vdev, VIRTIO_F_IOMMU_PLATFORM)) { error_setg(errp, "VIRTIO_F_IOMMU_PLATFORM was supported by" diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index 3a3d012d9f..a2edb4f386 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -3304,6 +3304,11 @@ bool virtio_legacy_allowed(VirtIODevice *vdev) } } +bool virtio_legacy_check_disabled(VirtIODevice *vdev) +{ + return vdev->disable_legacy_check; +} + hwaddr virtio_queue_get_desc_addr(VirtIODevice *vdev, int n) { return vdev->vq[n].vring.desc; @@ -3713,6 +3718,8 @@ static Property virtio_properties[] = { DEFINE_VIRTIO_COMMON_FEATURES(VirtIODevice, host_features), DEFINE_PROP_BOOL("use-started", VirtIODevice, use_started, true), DEFINE_PROP_BOOL("use-disabled-flag", VirtIODevice, use_disabled_flag, true), + DEFINE_PROP_BOOL("x-disable-legacy-check", VirtIODevice, + disable_legacy_check, false), DEFINE_PROP_END_OF_LIST(), }; diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h index 28cf3b9120..b7ece7a6a8 100644 --- a/include/hw/virtio/virtio.h +++ b/include/hw/virtio/virtio.h @@ -101,6 +101,7 @@ struct VirtIODevice bool use_started; bool started; bool start_on_kick; /* when virtio 1.0 feature has not been negotiated */ + bool disable_legacy_check; VMChangeStateEntry *vmstate; char *bus_name; uint8_t device_endian; @@ -394,5 +395,6 @@ static inline bool virtio_device_disabled(VirtIODevice *vdev) } bool virtio_legacy_allowed(VirtIODevice *vdev); +bool virtio_legacy_check_disabled(VirtIODevice *vdev); #endif