From 9e0a86718c5c91e964eb4b2a87375926bd3a36cf Mon Sep 17 00:00:00 2001 From: Cole Robinson Date: Sep 03 2013 18:49:39 +0000 Subject: Fix qmp capabilities calls on i686 (bz #1003162) Fix crash with -M isapc -cpu Haswell (bz #986790) Fix crash in lsi_soft_reset (bz #1000947) Fix initial /dev/kvm permissions (bz #993491) --- diff --git a/0002-qapi-types.py-Fix-enum-struct-sizes-on-i686.patch b/0002-qapi-types.py-Fix-enum-struct-sizes-on-i686.patch new file mode 100644 index 0000000..607826c --- /dev/null +++ b/0002-qapi-types.py-Fix-enum-struct-sizes-on-i686.patch @@ -0,0 +1,38 @@ +From f3e59ce7c471d3f0f1f293ecd0ef3e1797ce411f Mon Sep 17 00:00:00 2001 +From: Cole Robinson +Date: Sat, 31 Aug 2013 18:25:01 -0400 +Subject: [PATCH] qapi-types.py: Fix enum struct sizes on i686 + +Unlike other list types, enum wasn't adding any padding, which caused +a mismatch between the generated struct size and GenericList struct +size. More details in a678e26cbe89f7a27cbce794c2c2784571ee9d21 + +This crashed qemu if calling qmp query-tpm-types for example, which +upsets libvirt capabilities probing. Reproducer on i686: + +(sleep 5; printf '{"execute":"qmp_capabilities"}\n{"execute":"query-tpm-types"}\n') | ./i386-softmmu/qemu-system-i386 -S -nodefaults -nographic -M none -qmp stdio + +https://bugs.launchpad.net/qemu/+bug/1219207 + +Cc: qemu-stable@nongnu.org +(cherry picked from commit a9d960fb0b1bc104294ab965116a2d53038b4692) +--- + scripts/qapi-types.py | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py +index 5ee46ea..5d31b06 100644 +--- a/scripts/qapi-types.py ++++ b/scripts/qapi-types.py +@@ -51,7 +51,10 @@ def generate_fwd_enum_struct(name, members): + return mcgen(''' + typedef struct %(name)sList + { +- %(name)s value; ++ union { ++ %(name)s value; ++ uint64_t padding; ++ }; + struct %(name)sList *next; + } %(name)sList; + ''', diff --git a/0003-isapc-disable-kvmvapic.patch b/0003-isapc-disable-kvmvapic.patch new file mode 100644 index 0000000..1fd2899 --- /dev/null +++ b/0003-isapc-disable-kvmvapic.patch @@ -0,0 +1,36 @@ +From 56cee96f3c71ffee457d8fbdf427c47824a12e05 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Tue, 13 Aug 2013 00:02:18 +0200 +Subject: [PATCH] isapc: disable kvmvapic + +vapic requires the VAPIC ROM to be mapped into RAM. This is not +possible without PAM hardware. This fixes a segmentation fault +running with -M isapc. + +Cc: qemu-stable@nongnu.org +Signed-off-by: Paolo Bonzini + +(crobinso: s/kvmvapic/vapic/g) + +Signed-off-by: Cole Robinson +--- + hw/i386/pc_piix.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c +index 4fd5b6d..462d991 100644 +--- a/hw/i386/pc_piix.c ++++ b/hw/i386/pc_piix.c +@@ -795,7 +795,11 @@ static QEMUMachine isapc_machine = { + .init = pc_init_isa, + .max_cpus = 1, + .compat_props = (GlobalProperty[]) { +- { /* end of list */ } ++ { ++ .driver = "apic-common", ++ .property = "vapic", ++ .value = "off", ++ }, + }, + DEFAULT_MACHINE_OPTIONS, + }; diff --git a/0004-pci-do-not-export-pci_bus_reset.patch b/0004-pci-do-not-export-pci_bus_reset.patch new file mode 100644 index 0000000..a7fb21d --- /dev/null +++ b/0004-pci-do-not-export-pci_bus_reset.patch @@ -0,0 +1,72 @@ +From b8decc166db51601a6ad6f1df1752e9a9dc4544c Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Thu, 2 May 2013 11:38:37 +0200 +Subject: [PATCH] pci: do not export pci_bus_reset + +qbus_reset_all can be used instead. There is no semantic change +because pcibus_reset returns 1 and takes care of the device +tree traversal. + +This will be necessary once the traversal is done always in +qbus_reset_all *before* invoking pcibus_reset itself. + +Tested-by: Claudio Bley +Signed-off-by: Paolo Bonzini +--- + hw/pci/pci.c | 8 ++------ + hw/pci/pci_bridge.c | 2 +- + include/hw/pci/pci.h | 1 - + 3 files changed, 3 insertions(+), 8 deletions(-) + +diff --git a/hw/pci/pci.c b/hw/pci/pci.c +index 4c004f5..0389375 100644 +--- a/hw/pci/pci.c ++++ b/hw/pci/pci.c +@@ -210,8 +210,9 @@ void pci_device_reset(PCIDevice *dev) + * Trigger pci bus reset under a given bus. + * To be called on RST# assert. + */ +-void pci_bus_reset(PCIBus *bus) ++static int pcibus_reset(BusState *qbus) + { ++ PCIBus *bus = DO_UPCAST(PCIBus, qbus, qbus); + int i; + + for (i = 0; i < bus->nirq; i++) { +@@ -222,11 +223,6 @@ void pci_bus_reset(PCIBus *bus) + pci_device_reset(bus->devices[i]); + } + } +-} +- +-static int pcibus_reset(BusState *qbus) +-{ +- pci_bus_reset(DO_UPCAST(PCIBus, qbus, qbus)); + + /* topology traverse is done by pci_bus_reset(). + Tell qbus/qdev walker not to traverse the tree */ +diff --git a/hw/pci/pci_bridge.c b/hw/pci/pci_bridge.c +index a90671d..5d0e5ff 100644 +--- a/hw/pci/pci_bridge.c ++++ b/hw/pci/pci_bridge.c +@@ -268,7 +268,7 @@ void pci_bridge_write_config(PCIDevice *d, + newctl = pci_get_word(d->config + PCI_BRIDGE_CONTROL); + if (~oldctl & newctl & PCI_BRIDGE_CTL_BUS_RESET) { + /* Trigger hot reset on 0->1 transition. */ +- pci_bus_reset(&s->sec_bus); ++ qbus_reset_all(&s->sec_bus.qbus); + } + } + +diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h +index ccec2ba..32f1419 100644 +--- a/include/hw/pci/pci.h ++++ b/include/hw/pci/pci.h +@@ -376,7 +376,6 @@ void pci_bus_fire_intx_routing_notifier(PCIBus *bus); + void pci_device_set_intx_routing_notifier(PCIDevice *dev, + PCIINTxRoutingNotifier notifier); + void pci_device_reset(PCIDevice *dev); +-void pci_bus_reset(PCIBus *bus); + + PCIDevice *pci_nic_init(NICInfo *nd, PCIBus *rootbus, + const char *default_model, diff --git a/0005-qdev-allow-both-pre-and-post-order-vists-in-qdev-wal.patch b/0005-qdev-allow-both-pre-and-post-order-vists-in-qdev-wal.patch new file mode 100644 index 0000000..a418e80 --- /dev/null +++ b/0005-qdev-allow-both-pre-and-post-order-vists-in-qdev-wal.patch @@ -0,0 +1,141 @@ +From 7dbd6881f10537bf586f1eedf5a3bda2e50174ca Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Thu, 2 May 2013 11:38:38 +0200 +Subject: [PATCH] qdev: allow both pre- and post-order vists in qdev walking + functions + +Resetting should be done in post-order, not pre-order. However, +qdev_walk_children and qbus_walk_children do not allow this. Fix +it by adding two extra arguments to the functions. + +Tested-by: Claudio Bley +Signed-off-by: Paolo Bonzini +--- + hw/core/qdev.c | 45 +++++++++++++++++++++++++++++++++------------ + include/hw/qdev-core.h | 13 +++++++++---- + 2 files changed, 42 insertions(+), 16 deletions(-) + +diff --git a/hw/core/qdev.c b/hw/core/qdev.c +index 9190a7e..842804f 100644 +--- a/hw/core/qdev.c ++++ b/hw/core/qdev.c +@@ -240,12 +240,12 @@ static int qbus_reset_one(BusState *bus, void *opaque) + + void qdev_reset_all(DeviceState *dev) + { +- qdev_walk_children(dev, qdev_reset_one, qbus_reset_one, NULL); ++ qdev_walk_children(dev, qdev_reset_one, qbus_reset_one, NULL, NULL, NULL); + } + + void qbus_reset_all(BusState *bus) + { +- qbus_walk_children(bus, qdev_reset_one, qbus_reset_one, NULL); ++ qbus_walk_children(bus, qdev_reset_one, qbus_reset_one, NULL, NULL, NULL); + } + + void qbus_reset_all_fn(void *opaque) +@@ -343,49 +343,70 @@ BusState *qdev_get_child_bus(DeviceState *dev, const char *name) + return NULL; + } + +-int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn, +- qbus_walkerfn *busfn, void *opaque) ++int qbus_walk_children(BusState *bus, ++ qdev_walkerfn *pre_devfn, qbus_walkerfn *pre_busfn, ++ qdev_walkerfn *post_devfn, qbus_walkerfn *post_busfn, ++ void *opaque) + { + BusChild *kid; + int err; + +- if (busfn) { +- err = busfn(bus, opaque); ++ if (pre_busfn) { ++ err = pre_busfn(bus, opaque); + if (err) { + return err; + } + } + + QTAILQ_FOREACH(kid, &bus->children, sibling) { +- err = qdev_walk_children(kid->child, devfn, busfn, opaque); ++ err = qdev_walk_children(kid->child, ++ pre_devfn, pre_busfn, ++ post_devfn, post_busfn, opaque); + if (err < 0) { + return err; + } + } + ++ if (post_busfn) { ++ err = post_busfn(bus, opaque); ++ if (err) { ++ return err; ++ } ++ } ++ + return 0; + } + +-int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn, +- qbus_walkerfn *busfn, void *opaque) ++int qdev_walk_children(DeviceState *dev, ++ qdev_walkerfn *pre_devfn, qbus_walkerfn *pre_busfn, ++ qdev_walkerfn *post_devfn, qbus_walkerfn *post_busfn, ++ void *opaque) + { + BusState *bus; + int err; + +- if (devfn) { +- err = devfn(dev, opaque); ++ if (pre_devfn) { ++ err = pre_devfn(dev, opaque); + if (err) { + return err; + } + } + + QLIST_FOREACH(bus, &dev->child_bus, sibling) { +- err = qbus_walk_children(bus, devfn, busfn, opaque); ++ err = qbus_walk_children(bus, pre_devfn, pre_busfn, ++ post_devfn, post_busfn, opaque); + if (err < 0) { + return err; + } + } + ++ if (post_devfn) { ++ err = post_devfn(dev, opaque); ++ if (err) { ++ return err; ++ } ++ } ++ + return 0; + } + +diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h +index 46972f4..c6c9b14 100644 +--- a/include/hw/qdev-core.h ++++ b/include/hw/qdev-core.h +@@ -270,10 +270,15 @@ BusState *qbus_create(const char *typename, DeviceState *parent, const char *nam + /* Returns > 0 if either devfn or busfn skip walk somewhere in cursion, + * < 0 if either devfn or busfn terminate walk somewhere in cursion, + * 0 otherwise. */ +-int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn, +- qbus_walkerfn *busfn, void *opaque); +-int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn, +- qbus_walkerfn *busfn, void *opaque); ++int qbus_walk_children(BusState *bus, ++ qdev_walkerfn *pre_devfn, qbus_walkerfn *pre_busfn, ++ qdev_walkerfn *post_devfn, qbus_walkerfn *post_busfn, ++ void *opaque); ++int qdev_walk_children(DeviceState *dev, ++ qdev_walkerfn *pre_devfn, qbus_walkerfn *pre_busfn, ++ qdev_walkerfn *post_devfn, qbus_walkerfn *post_busfn, ++ void *opaque); ++ + void qdev_reset_all(DeviceState *dev); + + /** diff --git a/0006-qdev-switch-reset-to-post-order.patch b/0006-qdev-switch-reset-to-post-order.patch new file mode 100644 index 0000000..4679fc5 --- /dev/null +++ b/0006-qdev-switch-reset-to-post-order.patch @@ -0,0 +1,143 @@ +From 59164410b2f021d53be2ce45630647e952ccf9c2 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Thu, 2 May 2013 11:38:39 +0200 +Subject: [PATCH] qdev: switch reset to post-order + +Post-order is the only sensible direction for the reset signals. +For example, suppose pre-order is used and the parent has some data +structures that cache children state (for example a list of active +requests). When the reset method is invoked on the parent, these caches +could be in any state. + +If post-order is used, on the other hand, these will be in a known state +when the reset method is invoked on the parent. + +This change means that it is no longer possible to block the visit of +the devices, so the callback is changed to return void. This is not +a problem, because PCI was returning 1 exactly in order to achieve the +same ordering that this patch implements. + +PCI can then rely on the qdev core having sent a "reset signal" +(whatever that means) to the device, and only do the PCI-specific +initialization with the new function pci_do_device_reset, extracted +from pci_device_reset. There is no change in the operation of FLR, +which used and still uses pci_device_reset. + +Tested-by: Claudio Bley +Signed-off-by: Paolo Bonzini +--- + hw/core/qdev.c | 6 +++--- + hw/pci/pci.c | 31 ++++++++++++++++--------------- + include/hw/qdev-core.h | 2 +- + 3 files changed, 20 insertions(+), 19 deletions(-) + +diff --git a/hw/core/qdev.c b/hw/core/qdev.c +index 842804f..87d7e1e 100644 +--- a/hw/core/qdev.c ++++ b/hw/core/qdev.c +@@ -233,19 +233,19 @@ static int qbus_reset_one(BusState *bus, void *opaque) + { + BusClass *bc = BUS_GET_CLASS(bus); + if (bc->reset) { +- return bc->reset(bus); ++ bc->reset(bus); + } + return 0; + } + + void qdev_reset_all(DeviceState *dev) + { +- qdev_walk_children(dev, qdev_reset_one, qbus_reset_one, NULL, NULL, NULL); ++ qdev_walk_children(dev, NULL, NULL, qdev_reset_one, qbus_reset_one, NULL); + } + + void qbus_reset_all(BusState *bus) + { +- qbus_walk_children(bus, qdev_reset_one, qbus_reset_one, NULL, NULL, NULL); ++ qbus_walk_children(bus, NULL, NULL, qdev_reset_one, qbus_reset_one, NULL); + } + + void qbus_reset_all_fn(void *opaque) +diff --git a/hw/pci/pci.c b/hw/pci/pci.c +index 0389375..bbca696 100644 +--- a/hw/pci/pci.c ++++ b/hw/pci/pci.c +@@ -46,7 +46,7 @@ + static void pcibus_dev_print(Monitor *mon, DeviceState *dev, int indent); + static char *pcibus_get_dev_path(DeviceState *dev); + static char *pcibus_get_fw_dev_path(DeviceState *dev); +-static int pcibus_reset(BusState *qbus); ++static void pcibus_reset(BusState *qbus); + + static Property pci_props[] = { + DEFINE_PROP_PCI_DEVFN("addr", PCIDevice, devfn, -1), +@@ -165,16 +165,10 @@ void pci_device_deassert_intx(PCIDevice *dev) + } + } + +-/* +- * This function is called on #RST and FLR. +- * FLR if PCI_EXP_DEVCTL_BCR_FLR is set +- */ +-void pci_device_reset(PCIDevice *dev) ++static void pci_do_device_reset(PCIDevice *dev) + { + int r; + +- qdev_reset_all(&dev->qdev); +- + dev->irq_state = 0; + pci_update_irq_status(dev); + pci_device_deassert_intx(dev); +@@ -207,10 +201,21 @@ void pci_device_reset(PCIDevice *dev) + } + + /* ++ * This function is called on #RST and FLR. ++ * FLR if PCI_EXP_DEVCTL_BCR_FLR is set ++ */ ++void pci_device_reset(PCIDevice *dev) ++{ ++ qdev_reset_all(&dev->qdev); ++ pci_do_device_reset(dev); ++} ++ ++/* + * Trigger pci bus reset under a given bus. +- * To be called on RST# assert. ++ * Called via qbus_reset_all on RST# assert, after the devices ++ * have been reset qdev_reset_all-ed already. + */ +-static int pcibus_reset(BusState *qbus) ++static void pcibus_reset(BusState *qbus) + { + PCIBus *bus = DO_UPCAST(PCIBus, qbus, qbus); + int i; +@@ -220,13 +225,9 @@ static int pcibus_reset(BusState *qbus) + } + for (i = 0; i < ARRAY_SIZE(bus->devices); ++i) { + if (bus->devices[i]) { +- pci_device_reset(bus->devices[i]); ++ pci_do_device_reset(bus->devices[i]); + } + } +- +- /* topology traverse is done by pci_bus_reset(). +- Tell qbus/qdev walker not to traverse the tree */ +- return 1; + } + + static void pci_host_bus_register(PCIBus *bus, DeviceState *parent) +diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h +index c6c9b14..89dcbad 100644 +--- a/include/hw/qdev-core.h ++++ b/include/hw/qdev-core.h +@@ -174,7 +174,7 @@ struct BusClass { + * bindings can be found at http://playground.sun.com/1275/bindings/. + */ + char *(*get_fw_dev_path)(DeviceState *dev); +- int (*reset)(BusState *bus); ++ void (*reset)(BusState *bus); + /* maximum devices allowed on the bus, 0: no limit. */ + int max_dev; + }; diff --git a/qemu.spec b/qemu.spec index 1f226f1..2b2147c 100644 --- a/qemu.spec +++ b/qemu.spec @@ -140,7 +140,7 @@ Summary: QEMU is a FAST! processor emulator Name: qemu Version: 1.6.0 -Release: 5%{?dist} +Release: 6%{?dist} Epoch: 2 License: GPLv2+ and LGPLv2+ and BSD Group: Development/Tools @@ -183,6 +183,16 @@ Source13: qemu-kvm.sh # qemu-kvm migration compat (not for upstream, drop by Fedora 21?) Patch0001: 0001-Fix-migration-from-qemu-kvm.patch +# Fix qmp capabilities calls on i686 (bz #1003162) +# Patch posted upstream +Patch0002: 0002-qapi-types.py-Fix-enum-struct-sizes-on-i686.patch +# Fix crash with -M isapc -cpu Haswell (bz #986790) +Patch0003: 0003-isapc-disable-kvmvapic.patch +# Fix crash in lsi_soft_reset (bz #1000947) +# Patches posted upstream +Patch0004: 0004-pci-do-not-export-pci_bus_reset.patch +Patch0005: 0005-qdev-allow-both-pre-and-post-order-vists-in-qdev-wal.patch +Patch0006: 0006-qdev-switch-reset-to-post-order.patch BuildRequires: SDL-devel BuildRequires: zlib-devel @@ -695,6 +705,16 @@ CAC emulation development files. # qemu-kvm migration compat (not for upstream, drop by Fedora 21?) %patch0001 -p1 +# Fix qmp capabilities calls on i686 (bz #1003162) +# Patch posted upstream +%patch0002 -p1 +# Fix crash with -M isapc -cpu Haswell (bz #986790) +%patch0003 -p1 +# Fix crash in lsi_soft_reset (bz #1000947) +# Patches posted upstream +%patch0004 -p1 +%patch0005 -p1 +%patch0006 -p1 %build @@ -1003,6 +1023,7 @@ qemu-sanity-check --qemu=x86_64-softmmu/qemu-system-x86_64 || : # load kvm modules now, so we can make sure no reboot is needed. # If there's already a kvm module installed, we don't mess with it sh %{_sysconfdir}/sysconfig/modules/kvm.modules &> /dev/null || : +setfacl --remove-all /dev/kvm &> /dev/null || : udevadm trigger --subsystem-match=misc --sysname-match=kvm --action=add || : %endif @@ -1399,6 +1420,12 @@ getent passwd qemu >/dev/null || \ %endif %changelog +* Tue Sep 03 2013 Cole Robinson - 2:1.6.0-6 +- Fix qmp capabilities calls on i686 (bz #1003162) +- Fix crash with -M isapc -cpu Haswell (bz #986790) +- Fix crash in lsi_soft_reset (bz #1000947) +- Fix initial /dev/kvm permissions (bz #993491) + * Wed Aug 28 2013 Richard W.M. Jones - 2:1.6.0-5 - Enable qemu-sanity-check, however do not fail the build if it fails.