Commit 73795cea authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/awilliam/tags/vfio-pci-for-qemu-20140226.0' into staging



Updates include:
 - Coverify fixes for vfio & pci-assign (Markus)
 - VFIO blacklisting support for known brokwn PCI option ROMs (Bandan)

# gpg: Signature made Wed 26 Feb 2014 18:15:28 GMT using RSA key ID 3BB08B22
# gpg: Can't check signature: public key not found

* remotes/awilliam/tags/vfio-pci-for-qemu-20140226.0:
  vfio: blacklist loading of unstable roms
  qdev-monitor: set DeviceState opts before calling realize
  pci-assign: Fix potential read beyond buffer on -EBUSY
  vfio: Fix overrun after readlink() fills buffer completely

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 2ce5868c 4b943029
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -743,6 +743,7 @@ static void assign_failed_examine(AssignedDevice *dev)
        goto fail;
    }

    driver[r] = 0;
    ns = strrchr(driver, '/');
    if (!ns) {
        goto fail;
+76 −3
Original line number Diff line number Diff line
@@ -209,6 +209,29 @@ typedef struct VFIOGroup {
    QLIST_ENTRY(VFIOGroup) container_next;
} VFIOGroup;

typedef struct VFIORomBlacklistEntry {
    uint16_t vendor_id;
    uint16_t device_id;
} VFIORomBlacklistEntry;

/*
 * List of device ids/vendor ids for which to disable
 * option rom loading. This avoids the guest hangs during rom
 * execution as noticed with the BCM 57810 card for lack of a
 * more better way to handle such issues.
 * The  user can still override by specifying a romfile or
 * rombar=1.
 * Please see https://bugs.launchpad.net/qemu/+bug/1284874
 * for an analysis of the 57810 card hang. When adding
 * a new vendor id/device id combination below, please also add
 * your card/environment details and information that could
 * help in debugging to the bug tracking this issue
 */
static const VFIORomBlacklistEntry romblacklist[] = {
    /* Broadcom BCM 57810 */
    { 0x14e4, 0x168e }
};

#define MSIX_CAP_LENGTH 12

static QLIST_HEAD(, VFIOContainer)
@@ -1197,13 +1220,43 @@ static const MemoryRegionOps vfio_rom_ops = {
    .endianness = DEVICE_LITTLE_ENDIAN,
};

static bool vfio_blacklist_opt_rom(VFIODevice *vdev)
{
    PCIDevice *pdev = &vdev->pdev;
    uint16_t vendor_id, device_id;
    int count = 0;

    vendor_id = pci_get_word(pdev->config + PCI_VENDOR_ID);
    device_id = pci_get_word(pdev->config + PCI_DEVICE_ID);

    while (count < ARRAY_SIZE(romblacklist)) {
        if (romblacklist[count].vendor_id == vendor_id &&
            romblacklist[count].device_id == device_id) {
                return true;
        }
        count++;
    }

    return false;
}

static void vfio_pci_size_rom(VFIODevice *vdev)
{
    uint32_t orig, size = cpu_to_le32((uint32_t)PCI_ROM_ADDRESS_MASK);
    off_t offset = vdev->config_offset + PCI_ROM_ADDRESS;
    DeviceState *dev = DEVICE(vdev);
    char name[32];

    if (vdev->pdev.romfile || !vdev->pdev.rom_bar) {
        /* Since pci handles romfile, just print a message and return */
        if (vfio_blacklist_opt_rom(vdev) && vdev->pdev.romfile) {
            error_printf("Warning : Device at %04x:%02x:%02x.%x "
                         "is known to cause system instability issues during "
                         "option rom execution. "
                         "Proceeding anyway since user specified romfile\n",
                         vdev->host.domain, vdev->host.bus, vdev->host.slot,
                         vdev->host.function);
        }
        return;
    }

@@ -1227,6 +1280,26 @@ static void vfio_pci_size_rom(VFIODevice *vdev)
        return;
    }

    if (vfio_blacklist_opt_rom(vdev)) {
        if (dev->opts && qemu_opt_get(dev->opts, "rombar")) {
            error_printf("Warning : Device at %04x:%02x:%02x.%x "
                         "is known to cause system instability issues during "
                         "option rom execution. "
                         "Proceeding anyway since user specified non zero value for "
                         "rombar\n",
                         vdev->host.domain, vdev->host.bus, vdev->host.slot,
                         vdev->host.function);
        } else {
            error_printf("Warning : Rom loading for device at "
                         "%04x:%02x:%02x.%x has been disabled due to "
                         "system instability issues. "
                         "Specify rombar=1 or romfile to force\n",
                         vdev->host.domain, vdev->host.bus, vdev->host.slot,
                         vdev->host.function);
            return;
        }
    }

    DPRINTF("%04x:%02x:%02x.%x ROM size 0x%x\n", vdev->host.domain,
            vdev->host.bus, vdev->host.slot, vdev->host.function, size);

@@ -3681,10 +3754,10 @@ static int vfio_initfn(PCIDevice *pdev)

    strncat(path, "iommu_group", sizeof(path) - strlen(path) - 1);

    len = readlink(path, iommu_group_path, PATH_MAX);
    if (len <= 0) {
    len = readlink(path, iommu_group_path, sizeof(path));
    if (len <= 0 || len >= sizeof(path)) {
        error_report("vfio: error no iommu_group for device");
        return -errno;
        return len < 0 ? -errno : ENAMETOOLONG;
    }

    iommu_group_path[len] = 0;
+3 −1
Original line number Diff line number Diff line
@@ -548,16 +548,18 @@ DeviceState *qdev_device_add(QemuOpts *opts)
                                  OBJECT(dev), NULL);
        g_free(name);
    }

    dev->opts = opts;
    object_property_set_bool(OBJECT(dev), true, "realized", &err);
    if (err != NULL) {
        qerror_report_err(err);
        error_free(err);
        dev->opts = NULL;
        object_unparent(OBJECT(dev));
        object_unref(OBJECT(dev));
        qerror_report(QERR_DEVICE_INIT_FAILED, driver);
        return NULL;
    }
    dev->opts = opts;
    return dev;
}