9ae3a8
From aa757665c90914e69db3f16b11753c6d936b9bf0 Mon Sep 17 00:00:00 2001
9ae3a8
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
9ae3a8
Date: Thu, 17 Aug 2017 09:45:36 +0200
9ae3a8
Subject: [PATCH 3/4] Workaround rhel6 ctrl_guest_offloads machine type
9ae3a8
 mismatch
9ae3a8
9ae3a8
RH-Author: Dr. David Alan Gilbert <dgilbert@redhat.com>
9ae3a8
Message-id: <20170817094536.12740-3-dgilbert@redhat.com>
9ae3a8
Patchwork-id: 76022
9ae3a8
O-Subject: [RHEL-7.5/7.4.z/7.3.z/7.2.z qemu-kvm PATCH v2 2/2] Workaround rhel6 ctrl_guest_offloads machine type mismatch
9ae3a8
Bugzilla: 1480428
9ae3a8
RH-Acked-by: Eduardo Habkost <ehabkost@redhat.com>
9ae3a8
RH-Acked-by: Michael S. Tsirkin <mst@redhat.com>
9ae3a8
RH-Acked-by: Thomas Huth <thuth@redhat.com>
9ae3a8
9ae3a8
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
9ae3a8
9ae3a8
RHEL6's 6.5 and 6.6 machine types enable the ctrl_guest_offloads
9ae3a8
feature on virtio-net-pci, unfortunately RHEL7's definition of the
9ae3a8
6.5 and 6.6 machine types are missing that flag.
9ae3a8
9ae3a8
This works around it by allowing an incoming migration with the
9ae3a8
guest flag set (for the bad machine types).
9ae3a8
9ae3a8
Fixing the machine type definitions would break migration from this
9ae3a8
version to an earlier 7.x.
9ae3a8
9ae3a8
Note: Restarting the VM after this import will still keep the old
9ae3a8
(broken) machine type and turn the feature off.
9ae3a8
9ae3a8
(cherry picked from commit 73fe1f6ffd03f49f4be4b0482fdd2611aa9a17ca)
9ae3a8
9ae3a8
          Heavy conflicts from backport, mostly around structure
9ae3a8
          of properties
9ae3a8
9ae3a8
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
9ae3a8
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
9ae3a8
---
9ae3a8
 hw/i386/pc_piix.c          |  9 +++++++++
9ae3a8
 hw/virtio/virtio.c         | 26 +++++++++++++++++++++++++-
9ae3a8
 include/hw/virtio/virtio.h |  1 +
9ae3a8
 3 files changed, 35 insertions(+), 1 deletion(-)
9ae3a8
9ae3a8
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
9ae3a8
index f4cf2b5..b043124 100644
9ae3a8
--- a/hw/i386/pc_piix.c
9ae3a8
+++ b/hw/i386/pc_piix.c
9ae3a8
@@ -908,8 +908,13 @@ static QEMUMachine pc_machine_rhel700 = {
9ae3a8
         .driver   = "virtio-net-pci",\
9ae3a8
         .property = "any_layout",\
9ae3a8
         .value    = "off",\
9ae3a8
+    },{\
9ae3a8
+        .driver = "virtio-net-device",\
9ae3a8
+        .property = "__com.redhat_rhel6_ctrl_guest_workaround", \
9ae3a8
+        .value = "on",\
9ae3a8
     }
9ae3a8
 
9ae3a8
+
9ae3a8
 static void pc_compat_rhel660(QEMUMachineInitArgs *args)
9ae3a8
 {
9ae3a8
     pc_compat_rhel700(args);
9ae3a8
@@ -1031,6 +1036,10 @@ static QEMUMachine pc_machine_rhel650 = {
9ae3a8
         .driver   = "virtio-net-pci",\
9ae3a8
         .property = "ctrl_mac_addr",\
9ae3a8
         .value    = "off",\
9ae3a8
+    },{\
9ae3a8
+        .driver   = "virtio-net-device",\
9ae3a8
+        .property = "__com.redhat_rhel6_ctrl_guest_workaround", \
9ae3a8
+        .value    = "off",\
9ae3a8
     }
9ae3a8
 
9ae3a8
 static void pc_compat_rhel640(QEMUMachineInitArgs *args)
9ae3a8
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
9ae3a8
index fe6b032..e3af5ae 100644
9ae3a8
--- a/hw/virtio/virtio.c
9ae3a8
+++ b/hw/virtio/virtio.c
9ae3a8
@@ -18,6 +18,7 @@
9ae3a8
 #include "hw/virtio/virtio.h"
9ae3a8
 #include "qemu/atomic.h"
9ae3a8
 #include "hw/virtio/virtio-bus.h"
9ae3a8
+#include "include/hw/virtio/virtio-net.h"
9ae3a8
 
9ae3a8
 /* The alignment to use between consumer and producer parts of vring.
9ae3a8
  * x86 pagesize again. */
9ae3a8
@@ -888,8 +889,24 @@ int virtio_set_features(VirtIODevice *vdev, uint32_t val)
9ae3a8
     VirtioBusClass *vbusk = VIRTIO_BUS_GET_CLASS(qbus);
9ae3a8
     VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
9ae3a8
     uint32_t supported_features = vbusk->get_features(qbus->parent);
9ae3a8
-    bool bad = (val & ~supported_features) != 0;
9ae3a8
+    bool bad;
9ae3a8
+    uint64_t ctrl_guest_mask = 1ull << VIRTIO_NET_F_CTRL_GUEST_OFFLOADS;
9ae3a8
+
9ae3a8
+    if (vdev->rhel6_ctrl_guest_workaround && (val & ctrl_guest_mask) &&
9ae3a8
+          !(supported_features & ctrl_guest_mask)) {
9ae3a8
+        /*
9ae3a8
+         * This works around a mistake in the definition of the rhel6.[56].0
9ae3a8
+         * machinetypes, ctrl-guest-offload was not set in qemu-kvm for
9ae3a8
+         * those machine types, but is set on the rhel6 qemu-kvm-rhev build.
9ae3a8
+         * If an incoming rhel6 guest uses it then we need to allow it.
9ae3a8
+         * Note: There's a small race where a guest read the flag but didn't
9ae3a8
+         * declare it's useage yet.
9ae3a8
+         */
9ae3a8
+        fprintf(stderr, "RHEL6 ctrl_guest_offload workaround\n");
9ae3a8
+        supported_features |= ctrl_guest_mask;
9ae3a8
+    }
9ae3a8
 
9ae3a8
+    bad = (val & ~supported_features) != 0;
9ae3a8
     val &= supported_features;
9ae3a8
     if (k->set_features) {
9ae3a8
         k->set_features(vdev, val);
9ae3a8
@@ -1223,6 +1240,12 @@ static int virtio_device_exit(DeviceState *qdev)
9ae3a8
     return 0;
9ae3a8
 }
9ae3a8
 
9ae3a8
+static Property virtio_properties[] = {
9ae3a8
+    DEFINE_PROP_BOOL("__com.redhat_rhel6_ctrl_guest_workaround", VirtIODevice,
9ae3a8
+                     rhel6_ctrl_guest_workaround, false),
9ae3a8
+    DEFINE_PROP_END_OF_LIST(),
9ae3a8
+};
9ae3a8
+
9ae3a8
 static void virtio_device_class_init(ObjectClass *klass, void *data)
9ae3a8
 {
9ae3a8
     /* Set the default value here. */
9ae3a8
@@ -1230,6 +1253,7 @@ static void virtio_device_class_init(ObjectClass *klass, void *data)
9ae3a8
     dc->init = virtio_device_init;
9ae3a8
     dc->exit = virtio_device_exit;
9ae3a8
     dc->bus_type = TYPE_VIRTIO_BUS;
9ae3a8
+    dc->props = virtio_properties;
9ae3a8
 }
9ae3a8
 
9ae3a8
 static const TypeInfo virtio_device_info = {
9ae3a8
diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
9ae3a8
index d9bfe4c..0c4e963 100644
9ae3a8
--- a/include/hw/virtio/virtio.h
9ae3a8
+++ b/include/hw/virtio/virtio.h
9ae3a8
@@ -121,6 +121,7 @@ struct VirtIODevice
9ae3a8
     bool vm_running;
9ae3a8
     VMChangeStateEntry *vmstate;
9ae3a8
     char *bus_name;
9ae3a8
+    bool rhel6_ctrl_guest_workaround;
9ae3a8
 };
9ae3a8
 
9ae3a8
 typedef struct VirtioDeviceClass {
9ae3a8
-- 
9ae3a8
1.8.3.1
9ae3a8