aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2014-09-18 20:02:00 +0100
committerPeter Maydell <peter.maydell@linaro.org>2014-09-18 20:02:01 +0100
commit10e11f4d2bf171f99c6b13883a510acfbc5dd585 (patch)
tree4a82db961f4f11df98d071450eb8b2bd47bd39fa /hw
parentbb26a1e80b5639d71119ff58e0ef598708993fc0 (diff)
parent438f92ee9f6a4f78f8adcc399809e252b6da72a2 (diff)
Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging
pci, pc, virtio, misc bugfixes A bunch of bugfixes - some of these will make sense for 2.1.2 I put Cc: qemu-stable included where appropriate. Signed-off-by: Michael S. Tsirkin <mst@redhat.com> # gpg: Signature made Thu 18 Sep 2014 19:52:18 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: pc: leave more space for BIOS allocations virtio-pci: fix migration for pci bus master vhost-user: fix VIRTIO_NET_F_MRG_RXBUF negotiation virtio-pci: enable bus master for old guests Revert "virtio: don't call device on !vm_running" virtio-net: drop assert on vm stop Revert "rng-egd: remove redundant free" qdev: Move global validation to a single function qdev: Rename qdev_prop_check_global() to qdev_prop_check_globals() test-qdev-global-props: Test handling of hotpluggable and non-device types test-qdev-global-props: Initialize not_used=true for all props test-qdev-global-props: Run tests on subprocess tests: disable global props test for old glib test-qdev-global-props: Trivial comment fix hw/machine: Free old values of string properties Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw')
-rw-r--r--hw/core/machine.c8
-rw-r--r--hw/core/qdev-properties-system.c18
-rw-r--r--hw/core/qdev-properties.c30
-rw-r--r--hw/i386/pc.c6
-rw-r--r--hw/net/vhost_net.c8
-rw-r--r--hw/net/virtio-net.c2
-rw-r--r--hw/virtio/virtio-pci.c45
-rw-r--r--hw/virtio/virtio.c9
8 files changed, 69 insertions, 57 deletions
diff --git a/hw/core/machine.c b/hw/core/machine.c
index f0046d6de3..7f3418c5af 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -24,6 +24,7 @@ static void machine_set_accel(Object *obj, const char *value, Error **errp)
{
MachineState *ms = MACHINE(obj);
+ g_free(ms->accel);
ms->accel = g_strdup(value);
}
@@ -79,6 +80,7 @@ static void machine_set_kernel(Object *obj, const char *value, Error **errp)
{
MachineState *ms = MACHINE(obj);
+ g_free(ms->kernel_filename);
ms->kernel_filename = g_strdup(value);
}
@@ -93,6 +95,7 @@ static void machine_set_initrd(Object *obj, const char *value, Error **errp)
{
MachineState *ms = MACHINE(obj);
+ g_free(ms->initrd_filename);
ms->initrd_filename = g_strdup(value);
}
@@ -107,6 +110,7 @@ static void machine_set_append(Object *obj, const char *value, Error **errp)
{
MachineState *ms = MACHINE(obj);
+ g_free(ms->kernel_cmdline);
ms->kernel_cmdline = g_strdup(value);
}
@@ -121,6 +125,7 @@ static void machine_set_dtb(Object *obj, const char *value, Error **errp)
{
MachineState *ms = MACHINE(obj);
+ g_free(ms->dtb);
ms->dtb = g_strdup(value);
}
@@ -135,6 +140,7 @@ static void machine_set_dumpdtb(Object *obj, const char *value, Error **errp)
{
MachineState *ms = MACHINE(obj);
+ g_free(ms->dumpdtb);
ms->dumpdtb = g_strdup(value);
}
@@ -176,6 +182,7 @@ static void machine_set_dt_compatible(Object *obj, const char *value, Error **er
{
MachineState *ms = MACHINE(obj);
+ g_free(ms->dt_compatible);
ms->dt_compatible = g_strdup(value);
}
@@ -232,6 +239,7 @@ static void machine_set_firmware(Object *obj, const char *value, Error **errp)
{
MachineState *ms = MACHINE(obj);
+ g_free(ms->firmware);
ms->firmware = g_strdup(value);
}
diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c
index ae0900f651..84caa1d694 100644
--- a/hw/core/qdev-properties-system.c
+++ b/hw/core/qdev-properties-system.c
@@ -388,28 +388,12 @@ void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
static int qdev_add_one_global(QemuOpts *opts, void *opaque)
{
GlobalProperty *g;
- ObjectClass *oc;
g = g_malloc0(sizeof(*g));
g->driver = qemu_opt_get(opts, "driver");
g->property = qemu_opt_get(opts, "property");
g->value = qemu_opt_get(opts, "value");
- oc = object_class_dynamic_cast(object_class_by_name(g->driver),
- TYPE_DEVICE);
- if (oc) {
- DeviceClass *dc = DEVICE_CLASS(oc);
-
- if (dc->hotpluggable) {
- /* If hotpluggable then skip not_used checking. */
- g->not_used = false;
- } else {
- /* Maybe a typo. */
- g->not_used = true;
- }
- } else {
- /* Maybe a typo. */
- g->not_used = true;
- }
+ g->user_provided = true;
qdev_prop_register_global(g);
return 0;
}
diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c
index 3d12560f43..66556d3bf9 100644
--- a/hw/core/qdev-properties.c
+++ b/hw/core/qdev-properties.c
@@ -955,19 +955,35 @@ void qdev_prop_register_global_list(GlobalProperty *props)
}
}
-int qdev_prop_check_global(void)
+int qdev_prop_check_globals(void)
{
GlobalProperty *prop;
int ret = 0;
QTAILQ_FOREACH(prop, &global_props, next) {
- if (!prop->not_used) {
+ ObjectClass *oc;
+ DeviceClass *dc;
+ if (prop->used) {
+ continue;
+ }
+ if (!prop->user_provided) {
+ continue;
+ }
+ oc = object_class_by_name(prop->driver);
+ oc = object_class_dynamic_cast(oc, TYPE_DEVICE);
+ if (!oc) {
+ error_report("Warning: global %s.%s has invalid class name",
+ prop->driver, prop->property);
+ ret = 1;
+ continue;
+ }
+ dc = DEVICE_CLASS(oc);
+ if (!dc->hotpluggable && !prop->used) {
+ error_report("Warning: global %s.%s=%s not used",
+ prop->driver, prop->property, prop->value);
+ ret = 1;
continue;
}
- ret = 1;
- error_report("Warning: \"-global %s.%s=%s\" not used",
- prop->driver, prop->property, prop->value);
-
}
return ret;
}
@@ -983,7 +999,7 @@ void qdev_prop_set_globals_for_type(DeviceState *dev, const char *typename,
if (strcmp(typename, prop->driver) != 0) {
continue;
}
- prop->not_used = false;
+ prop->used = true;
object_property_parse(OBJECT(dev), prop->value, prop->property, &err);
if (err != NULL) {
error_propagate(errp, err);
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 77b6782fed..2c2e9dcbf4 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -72,8 +72,10 @@
#define DPRINTF(fmt, ...)
#endif
-/* Leave a chunk of memory at the top of RAM for the BIOS ACPI tables. */
-unsigned acpi_data_size = 0x20000;
+/* Leave a chunk of memory at the top of RAM for the BIOS ACPI tables
+ * (128K) and other BIOS datastructures (less than 4K reported to be used at
+ * the moment, 32K should be enough for a while). */
+unsigned acpi_data_size = 0x20000 + 0x8000;
void pc_set_legacy_acpi_data_size(void)
{
acpi_data_size = 0x10000;
diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
index b21e7a434f..77bb93e4d7 100644
--- a/hw/net/vhost_net.c
+++ b/hw/net/vhost_net.c
@@ -163,11 +163,11 @@ struct vhost_net *vhost_net_init(VhostNetOptions *options)
if (r < 0) {
goto fail;
}
- if (!qemu_has_vnet_hdr_len(options->net_backend,
- sizeof(struct virtio_net_hdr_mrg_rxbuf))) {
- net->dev.features &= ~(1 << VIRTIO_NET_F_MRG_RXBUF);
- }
if (backend_kernel) {
+ if (!qemu_has_vnet_hdr_len(options->net_backend,
+ sizeof(struct virtio_net_hdr_mrg_rxbuf))) {
+ net->dev.features &= ~(1 << VIRTIO_NET_F_MRG_RXBUF);
+ }
if (~net->dev.features & net->dev.backend_features) {
fprintf(stderr, "vhost lacks feature mask %" PRIu64
" for backend\n",
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 826a2a5fca..2040eac9a1 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -1125,8 +1125,6 @@ static int32_t virtio_net_flush_tx(VirtIONetQueue *q)
return num_packets;
}
- assert(vdev->vm_running);
-
if (q->async_tx.elem.out_num) {
virtio_queue_set_notification(q->tx_vq, 0);
return num_packets;
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index ddb5da181c..f5608140f9 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -86,9 +86,6 @@
* 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);
@@ -314,12 +311,14 @@ static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val)
msix_unuse_all_vectors(&proxy->pci_dev);
}
- /* 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;
+ /* 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. */
+ if (val == (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);
}
break;
case VIRTIO_MSI_CONFIG_VECTOR:
@@ -470,13 +469,18 @@ 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) &&
- !(proxy->flags & VIRTIO_PCI_FLAG_BUS_MASTER_BUG)) {
+ (cmd & PCI_COMMAND_MASTER)) {
+ /* Bus driver disables bus mastering - make it act
+ * as a kind of reset to render the device quiescent. */
virtio_pci_stop_ioeventfd(proxy);
- virtio_set_status(vdev, vdev->status & ~VIRTIO_CONFIG_S_DRIVER_OK);
+ virtio_reset(vdev);
+ msix_unuse_all_vectors(&proxy->pci_dev);
}
}
@@ -885,11 +889,19 @@ static void virtio_pci_vmstate_change(DeviceState *d, bool running)
VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
if (running) {
- /* 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;
+ /* 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);
}
virtio_pci_start_ioeventfd(proxy);
} else {
@@ -1030,7 +1042,6 @@ 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[] = {
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index ac222385d6..5c981801f3 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -1108,10 +1108,7 @@ static void virtio_vmstate_change(void *opaque, int running, RunState state)
BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
bool backend_run = running && (vdev->status & VIRTIO_CONFIG_S_DRIVER_OK);
-
- if (running) {
- vdev->vm_running = running;
- }
+ vdev->vm_running = running;
if (backend_run) {
virtio_set_status(vdev, vdev->status);
@@ -1124,10 +1121,6 @@ static void virtio_vmstate_change(void *opaque, int running, RunState state)
if (!backend_run) {
virtio_set_status(vdev, vdev->status);
}
-
- if (!running) {
- vdev->vm_running = running;
- }
}
void virtio_init(VirtIODevice *vdev, const char *name,