render / rpms / qemu

Forked from rpms/qemu 9 months ago
Clone

Blame 0007-virtio-pci-fix-migration-for-pci-bus-master.patch

46f3a5
From 2c8d6826ebaf1bf846edd213f8fe8f95c0c300cb Mon Sep 17 00:00:00 2001
e84b90
From: "Michael S. Tsirkin" <mst@redhat.com>
e84b90
Date: Thu, 11 Sep 2014 18:34:29 +0300
e84b90
Subject: [PATCH] virtio-pci: fix migration for pci bus master
e84b90
e84b90
Current support for bus master (clearing OK bit)
e84b90
together with the need to support guests which do not
e84b90
enable PCI bus mastering, leads to extra state in
e84b90
VIRTIO_PCI_FLAG_BUS_MASTER_BUG bit, which isn't robust
e84b90
in case of cross-version migration for the case when
e84b90
guests use the device before setting DRIVER_OK.
e84b90
e84b90
Rip out VIRTIO_PCI_FLAG_BUS_MASTER_BUG and implement a simpler
e84b90
work-around: treat clearing of PCI_COMMAND as a virtio reset.  Old
e84b90
guests never touch this bit so they will work.
e84b90
e84b90
As reset clears device status, DRIVER and MASTER bits are
e84b90
now in sync, so we can fix up cross-version migration simply
e84b90
by synchronising them, without need to detect a buggy guest
e84b90
explicitly.
e84b90
e84b90
Drop tracking VIRTIO_PCI_FLAG_BUS_MASTER_BUG completely.
e84b90
e84b90
As reset makes the device quiescent, in the future we'll be able to drop
e84b90
checking OK bit in a bunch of places.
e84b90
e84b90
Cc: Jason Wang <jasowang@redhat.com>
e84b90
Cc: Greg Kurz <gkurz@linux.vnet.ibm.com>
e84b90
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
e84b90
(cherry picked from commit 4d43d3f3c8147ade184df9a1e9e82826edd39e19)
e84b90
---
e84b90
 hw/virtio/virtio-pci.c | 39 ++++++++++++++++++++-------------------
e84b90
 1 file changed, 20 insertions(+), 19 deletions(-)
e84b90
e84b90
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
e84b90
index 58ebbcf..c19c4d6 100644
e84b90
--- a/hw/virtio/virtio-pci.c
e84b90
+++ b/hw/virtio/virtio-pci.c
e84b90
@@ -86,9 +86,6 @@
e84b90
  * 12 is historical, and due to x86 page size. */
e84b90
 #define VIRTIO_PCI_QUEUE_ADDR_SHIFT    12
e84b90
 
e84b90
-/* Flags track per-device state like workarounds for quirks in older guests. */
e84b90
-#define VIRTIO_PCI_FLAG_BUS_MASTER_BUG  (1 << 0)
e84b90
-
e84b90
 static void virtio_pci_bus_new(VirtioBusState *bus, size_t bus_size,
e84b90
                                VirtIOPCIProxy *dev);
e84b90
 
e84b90
@@ -323,14 +320,6 @@ static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val)
e84b90
                                      proxy->pci_dev.config[PCI_COMMAND] |
e84b90
                                      PCI_COMMAND_MASTER, 1);
e84b90
         }
e84b90
-
e84b90
-        /* Linux before 2.6.34 sets the device as OK without enabling
e84b90
-           the PCI device bus master bit. In this case we need to disable
e84b90
-           some safety checks. */
e84b90
-        if ((val & VIRTIO_CONFIG_S_DRIVER_OK) &&
e84b90
-            !(proxy->pci_dev.config[PCI_COMMAND] & PCI_COMMAND_MASTER)) {
e84b90
-            proxy->flags |= VIRTIO_PCI_FLAG_BUS_MASTER_BUG;
e84b90
-        }
e84b90
         break;
e84b90
     case VIRTIO_MSI_CONFIG_VECTOR:
e84b90
         msix_vector_unuse(&proxy->pci_dev, vdev->config_vector);
e84b90
@@ -480,13 +469,18 @@ static void virtio_write_config(PCIDevice *pci_dev, uint32_t address,
e84b90
     VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
e84b90
     VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
e84b90
 
e84b90
+    uint8_t cmd = proxy->pci_dev.config[PCI_COMMAND];
e84b90
+
e84b90
     pci_default_write_config(pci_dev, address, val, len);
e84b90
 
e84b90
     if (range_covers_byte(address, len, PCI_COMMAND) &&
e84b90
         !(pci_dev->config[PCI_COMMAND] & PCI_COMMAND_MASTER) &&
e84b90
-        !(proxy->flags & VIRTIO_PCI_FLAG_BUS_MASTER_BUG)) {
e84b90
+        (cmd & PCI_COMMAND_MASTER)) {
e84b90
+        /* Bus driver disables bus mastering - make it act
e84b90
+         * as a kind of reset to render the device quiescent. */
e84b90
         virtio_pci_stop_ioeventfd(proxy);
e84b90
-        virtio_set_status(vdev, vdev->status & ~VIRTIO_CONFIG_S_DRIVER_OK);
e84b90
+        virtio_reset(vdev);
e84b90
+        msix_unuse_all_vectors(&proxy->pci_dev);
e84b90
     }
e84b90
 }
e84b90
 
e84b90
@@ -895,11 +889,19 @@ static void virtio_pci_vmstate_change(DeviceState *d, bool running)
e84b90
     VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
e84b90
 
e84b90
     if (running) {
e84b90
-        /* Try to find out if the guest has bus master disabled, but is
e84b90
-           in ready state. Then we have a buggy guest OS. */
e84b90
-        if ((vdev->status & VIRTIO_CONFIG_S_DRIVER_OK) &&
e84b90
-            !(proxy->pci_dev.config[PCI_COMMAND] & PCI_COMMAND_MASTER)) {
e84b90
-            proxy->flags |= VIRTIO_PCI_FLAG_BUS_MASTER_BUG;
e84b90
+        /* Linux before 2.6.34 drives the device without enabling
e84b90
+           the PCI device bus master bit. Enable it automatically
e84b90
+           for the guest. This is a PCI spec violation but so is
e84b90
+           initiating DMA with bus master bit clear.
e84b90
+           Note: this only makes a difference when migrating
e84b90
+           across QEMU versions from an old QEMU, as for new QEMU
e84b90
+           bus master and driver bits are always in sync.
e84b90
+           TODO: consider enabling conditionally for compat machine types. */
e84b90
+        if (vdev->status & (VIRTIO_CONFIG_S_ACKNOWLEDGE |
e84b90
+                            VIRTIO_CONFIG_S_DRIVER)) {
e84b90
+            pci_default_write_config(&proxy->pci_dev, PCI_COMMAND,
e84b90
+                                     proxy->pci_dev.config[PCI_COMMAND] |
e84b90
+                                     PCI_COMMAND_MASTER, 1);
e84b90
         }
e84b90
         virtio_pci_start_ioeventfd(proxy);
e84b90
     } else {
e84b90
@@ -1043,7 +1045,6 @@ static void virtio_pci_reset(DeviceState *qdev)
e84b90
     virtio_pci_stop_ioeventfd(proxy);
e84b90
     virtio_bus_reset(bus);
e84b90
     msix_unuse_all_vectors(&proxy->pci_dev);
e84b90
-    proxy->flags &= ~VIRTIO_PCI_FLAG_BUS_MASTER_BUG;
e84b90
 }
e84b90
 
e84b90
 static Property virtio_pci_properties[] = {