diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2014-09-30 13:09:39 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2014-09-30 13:09:40 +0100 |
commit | 2e456b2b606aef488de27f8212e22382141fa022 (patch) | |
tree | 39184cd190bedef458e5d9c698e9915ea49932b0 /hw | |
parent | 45c270b1ea7987ab93e41ab095dd77370523e6b3 (diff) | |
parent | 28d16f38d0d5881f95b074cc802dae8cacc1bf58 (diff) | |
download | hqemu-2e456b2b606aef488de27f8212e22382141fa022.zip hqemu-2e456b2b606aef488de27f8212e22382141fa022.tar.gz |
Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging
pci, pc, virtio, misc bugfixes
A bunch of bugfixes.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
# gpg: Signature made Mon 29 Sep 2014 17:59:57 BST using RSA key ID D28D5469
# gpg: Good signature from "Michael S. Tsirkin <mst@kernel.org>"
# gpg: aka "Michael S. Tsirkin <mst@redhat.com>"
* remotes/mst/tags/for_upstream:
vl: Adjust the place of calling mlockall to speedup VM's startup
pc-dimm: Don't check dimm->node when there is non-NUMA config
pci-hotplug-old: avoid losing error message
Revert "virtio-pci: fix migration for pci bus master"
loader: g_realloc(p, 0) frees and returns NULL, simplify
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw')
-rw-r--r-- | hw/mem/pc-dimm.c | 2 | ||||
-rw-r--r-- | hw/pci/pci-hotplug-old.c | 5 | ||||
-rw-r--r-- | hw/virtio/virtio-pci.c | 39 |
3 files changed, 24 insertions, 22 deletions
diff --git a/hw/mem/pc-dimm.c b/hw/mem/pc-dimm.c index 5bfc5b7..a800ea7 100644 --- a/hw/mem/pc-dimm.c +++ b/hw/mem/pc-dimm.c @@ -252,7 +252,7 @@ static void pc_dimm_realize(DeviceState *dev, Error **errp) error_setg(errp, "'" PC_DIMM_MEMDEV_PROP "' property is not set"); return; } - if (dimm->node >= nb_numa_nodes) { + if ((nb_numa_nodes > 0) && (dimm->node >= nb_numa_nodes)) { error_setg(errp, "'DIMM property " PC_DIMM_NODE_PROP " has value %" PRIu32 "' which exceeds the number of numa nodes: %d", dimm->node, nb_numa_nodes); diff --git a/hw/pci/pci-hotplug-old.c b/hw/pci/pci-hotplug-old.c index cf2caeb..d87c469 100644 --- a/hw/pci/pci-hotplug-old.c +++ b/hw/pci/pci-hotplug-old.c @@ -107,6 +107,7 @@ static int scsi_hot_add(Monitor *mon, DeviceState *adapter, { SCSIBus *scsibus; SCSIDevice *scsidev; + Error *local_err = NULL; scsibus = (SCSIBus *) object_dynamic_cast(OBJECT(QLIST_FIRST(&adapter->child_bus)), @@ -127,8 +128,10 @@ static int scsi_hot_add(Monitor *mon, DeviceState *adapter, dinfo->unit = qemu_opt_get_number(dinfo->opts, "unit", -1); dinfo->bus = scsibus->busnr; scsidev = scsi_bus_legacy_add_drive(scsibus, dinfo->bdrv, dinfo->unit, - false, -1, NULL, NULL); + false, -1, NULL, &local_err); if (!scsidev) { + error_report("%s", error_get_pretty(local_err)); + error_free(local_err); return -1; } dinfo->unit = scsidev->id; diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index f560814..a827cd4 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -86,6 +86,9 @@ * 12 is historical, and due to x86 page size. */ #define VIRTIO_PCI_QUEUE_ADDR_SHIFT 12 +/* Flags track per-device state like workarounds for quirks in older guests. */ +#define VIRTIO_PCI_FLAG_BUS_MASTER_BUG (1 << 0) + static void virtio_pci_bus_new(VirtioBusState *bus, size_t bus_size, VirtIOPCIProxy *dev); @@ -320,6 +323,14 @@ static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val) proxy->pci_dev.config[PCI_COMMAND] | PCI_COMMAND_MASTER, 1); } + + /* Linux before 2.6.34 sets the device as OK without enabling + the PCI device bus master bit. In this case we need to disable + some safety checks. */ + if ((val & VIRTIO_CONFIG_S_DRIVER_OK) && + !(proxy->pci_dev.config[PCI_COMMAND] & PCI_COMMAND_MASTER)) { + proxy->flags |= VIRTIO_PCI_FLAG_BUS_MASTER_BUG; + } break; case VIRTIO_MSI_CONFIG_VECTOR: msix_vector_unuse(&proxy->pci_dev, vdev->config_vector); @@ -469,18 +480,13 @@ static void virtio_write_config(PCIDevice *pci_dev, uint32_t address, VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev); VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); - uint8_t cmd = proxy->pci_dev.config[PCI_COMMAND]; - pci_default_write_config(pci_dev, address, val, len); if (range_covers_byte(address, len, PCI_COMMAND) && !(pci_dev->config[PCI_COMMAND] & PCI_COMMAND_MASTER) && - (cmd & PCI_COMMAND_MASTER)) { - /* Bus driver disables bus mastering - make it act - * as a kind of reset to render the device quiescent. */ + !(proxy->flags & VIRTIO_PCI_FLAG_BUS_MASTER_BUG)) { virtio_pci_stop_ioeventfd(proxy); - virtio_reset(vdev); - msix_unuse_all_vectors(&proxy->pci_dev); + virtio_set_status(vdev, vdev->status & ~VIRTIO_CONFIG_S_DRIVER_OK); } } @@ -889,19 +895,11 @@ static void virtio_pci_vmstate_change(DeviceState *d, bool running) VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); if (running) { - /* Linux before 2.6.34 drives the device without enabling - the PCI device bus master bit. Enable it automatically - for the guest. This is a PCI spec violation but so is - initiating DMA with bus master bit clear. - Note: this only makes a difference when migrating - across QEMU versions from an old QEMU, as for new QEMU - bus master and driver bits are always in sync. - TODO: consider enabling conditionally for compat machine types. */ - if (vdev->status & (VIRTIO_CONFIG_S_ACKNOWLEDGE | - VIRTIO_CONFIG_S_DRIVER)) { - pci_default_write_config(&proxy->pci_dev, PCI_COMMAND, - proxy->pci_dev.config[PCI_COMMAND] | - PCI_COMMAND_MASTER, 1); + /* Try to find out if the guest has bus master disabled, but is + in ready state. Then we have a buggy guest OS. */ + if ((vdev->status & VIRTIO_CONFIG_S_DRIVER_OK) && + !(proxy->pci_dev.config[PCI_COMMAND] & PCI_COMMAND_MASTER)) { + proxy->flags |= VIRTIO_PCI_FLAG_BUS_MASTER_BUG; } virtio_pci_start_ioeventfd(proxy); } else { @@ -1042,6 +1040,7 @@ static void virtio_pci_reset(DeviceState *qdev) virtio_pci_stop_ioeventfd(proxy); virtio_bus_reset(bus); msix_unuse_all_vectors(&proxy->pci_dev); + proxy->flags &= ~VIRTIO_PCI_FLAG_BUS_MASTER_BUG; } static Property virtio_pci_properties[] = { |