0a122b
From 8c54fd61fa0c98d6e543923badfd174160acedd0 Mon Sep 17 00:00:00 2001
0a122b
From: Bandan Das <bsd@redhat.com>
0a122b
Date: Thu, 27 Feb 2014 18:31:17 +0100
0a122b
Subject: [PATCH 5/6] vfio: blacklist loading of unstable roms
0a122b
0a122b
RH-Author: Bandan Das <bsd@redhat.com>
0a122b
Message-id: <1393525877-32262-3-git-send-email-bsd@redhat.com>
0a122b
Patchwork-id: 57933
0a122b
O-Subject: [PATCH RHEL-7.0 qemu-kvm v2 2/2] vfio: blacklist loading of unstable roms
0a122b
Bugzilla: 1037956
0a122b
RH-Acked-by: Alex Williamson <alex.williamson@redhat.com>
0a122b
RH-Acked-by: Michael S. Tsirkin <mst@redhat.com>
0a122b
RH-Acked-by: Marcel Apfelbaum <marcel.a@redhat.com>
0a122b
0a122b
Certain cards such as the Broadcom BCM57810 have rom quirks
0a122b
that exhibit unstable system behavior duing device assignment. In
0a122b
the particular case of 57810, rom execution hangs and if a FLR
0a122b
follows, the device becomes inoperable until a power cycle. This
0a122b
change blacklists loading of rom for such cards unless the user
0a122b
specifies a romfile or rombar=1 on the cmd line
0a122b
0a122b
Signed-off-by: Bandan Das <bsd@redhat.com>
0a122b
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
0a122b
(cherry picked from commit 4b9430294ed406a00f045d825ada146aecf32309)
0a122b
---
0a122b
 hw/misc/vfio.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
0a122b
 1 file changed, 73 insertions(+)
0a122b
0a122b
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
0a122b
---
0a122b
 hw/misc/vfio.c |   73 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
0a122b
 1 files changed, 73 insertions(+), 0 deletions(-)
0a122b
0a122b
diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c
0a122b
index e1f30a2..b04170e 100644
0a122b
--- a/hw/misc/vfio.c
0a122b
+++ b/hw/misc/vfio.c
0a122b
@@ -206,6 +206,29 @@ typedef struct VFIOGroup {
0a122b
     QLIST_ENTRY(VFIOGroup) container_next;
0a122b
 } VFIOGroup;
0a122b
 
0a122b
+typedef struct VFIORomBlacklistEntry {
0a122b
+    uint16_t vendor_id;
0a122b
+    uint16_t device_id;
0a122b
+} VFIORomBlacklistEntry;
0a122b
+
0a122b
+/*
0a122b
+ * List of device ids/vendor ids for which to disable
0a122b
+ * option rom loading. This avoids the guest hangs during rom
0a122b
+ * execution as noticed with the BCM 57810 card for lack of a
0a122b
+ * more better way to handle such issues.
0a122b
+ * The  user can still override by specifying a romfile or
0a122b
+ * rombar=1.
0a122b
+ * Please see https://bugs.launchpad.net/qemu/+bug/1284874
0a122b
+ * for an analysis of the 57810 card hang. When adding
0a122b
+ * a new vendor id/device id combination below, please also add
0a122b
+ * your card/environment details and information that could
0a122b
+ * help in debugging to the bug tracking this issue
0a122b
+ */
0a122b
+static const VFIORomBlacklistEntry romblacklist[] = {
0a122b
+    /* Broadcom BCM 57810 */
0a122b
+    { 0x14e4, 0x168e }
0a122b
+};
0a122b
+
0a122b
 #define MSIX_CAP_LENGTH 12
0a122b
 #define MAX_DEV_ASSIGN_CMDLINE 32
0a122b
 
0a122b
@@ -1167,13 +1190,43 @@ static const MemoryRegionOps vfio_rom_ops = {
0a122b
     .endianness = DEVICE_LITTLE_ENDIAN,
0a122b
 };
0a122b
 
0a122b
+static bool vfio_blacklist_opt_rom(VFIODevice *vdev)
0a122b
+{
0a122b
+    PCIDevice *pdev = &vdev->pdev;
0a122b
+    uint16_t vendor_id, device_id;
0a122b
+    int count = 0;
0a122b
+
0a122b
+    vendor_id = pci_get_word(pdev->config + PCI_VENDOR_ID);
0a122b
+    device_id = pci_get_word(pdev->config + PCI_DEVICE_ID);
0a122b
+
0a122b
+    while (count < ARRAY_SIZE(romblacklist)) {
0a122b
+        if (romblacklist[count].vendor_id == vendor_id &&
0a122b
+            romblacklist[count].device_id == device_id) {
0a122b
+                return true;
0a122b
+        }
0a122b
+        count++;
0a122b
+    }
0a122b
+
0a122b
+    return false;
0a122b
+}
0a122b
+
0a122b
 static void vfio_pci_size_rom(VFIODevice *vdev)
0a122b
 {
0a122b
     uint32_t orig, size = cpu_to_le32((uint32_t)PCI_ROM_ADDRESS_MASK);
0a122b
     off_t offset = vdev->config_offset + PCI_ROM_ADDRESS;
0a122b
+    DeviceState *dev = DEVICE(vdev);
0a122b
     char name[32];
0a122b
 
0a122b
     if (vdev->pdev.romfile || !vdev->pdev.rom_bar) {
0a122b
+        /* Since pci handles romfile, just print a message and return */
0a122b
+        if (vfio_blacklist_opt_rom(vdev) && vdev->pdev.romfile) {
0a122b
+            error_printf("Warning : Device at %04x:%02x:%02x.%x "
0a122b
+                         "is known to cause system instability issues during "
0a122b
+                         "option rom execution. "
0a122b
+                         "Proceeding anyway since user specified romfile\n",
0a122b
+                         vdev->host.domain, vdev->host.bus, vdev->host.slot,
0a122b
+                         vdev->host.function);
0a122b
+        }
0a122b
         return;
0a122b
     }
0a122b
 
0a122b
@@ -1197,6 +1250,26 @@ static void vfio_pci_size_rom(VFIODevice *vdev)
0a122b
         return;
0a122b
     }
0a122b
 
0a122b
+    if (vfio_blacklist_opt_rom(vdev)) {
0a122b
+        if (dev->opts && qemu_opt_get(dev->opts, "rombar")) {
0a122b
+            error_printf("Warning : Device at %04x:%02x:%02x.%x "
0a122b
+                         "is known to cause system instability issues during "
0a122b
+                         "option rom execution. "
0a122b
+                         "Proceeding anyway since user specified non zero value for "
0a122b
+                         "rombar\n",
0a122b
+                         vdev->host.domain, vdev->host.bus, vdev->host.slot,
0a122b
+                         vdev->host.function);
0a122b
+        } else {
0a122b
+            error_printf("Warning : Rom loading for device at "
0a122b
+                         "%04x:%02x:%02x.%x has been disabled due to "
0a122b
+                         "system instability issues. "
0a122b
+                         "Specify rombar=1 or romfile to force\n",
0a122b
+                         vdev->host.domain, vdev->host.bus, vdev->host.slot,
0a122b
+                         vdev->host.function);
0a122b
+            return;
0a122b
+        }
0a122b
+    }
0a122b
+
0a122b
     DPRINTF("%04x:%02x:%02x.%x ROM size 0x%x\n", vdev->host.domain,
0a122b
             vdev->host.bus, vdev->host.slot, vdev->host.function, size);
0a122b
 
0a122b
-- 
0a122b
1.7.1
0a122b