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