Merge remote-tracking branch 'luiz/queue/qmp' into staging
# By Michael Roth (1) and Zhangleiqiang (1)
# Via Luiz Capitulino
* luiz/queue/qmp:
qapi: fix leak in unit tests
qmp: fix handling of cmd with Equals in qmp-shell
Message-id: 1368625179-27962-1-git-send-email-lcapitulino@redhat.com
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
diff --git a/configure b/configure
index cab6332..5ae7e4a 100755
--- a/configure
+++ b/configure
@@ -1346,6 +1346,7 @@
int main(void)
{
int val = 42;
+ val = __sync_val_compare_and_swap(&val, 0, 1);
sfaa(&val);
return val;
}
@@ -1948,6 +1949,8 @@
##########################################
# uuid_generate() probe, used for vdi block driver
+# Note that on some systems (notably MacOSX) no extra library
+# need be linked to get the uuid functions.
if test "$uuid" != "no" ; then
uuid_libs="-luuid"
cat > $TMPC << EOF
@@ -1959,7 +1962,9 @@
return 0;
}
EOF
- if compile_prog "" "$uuid_libs" ; then
+ if compile_prog "" "" ; then
+ uuid="yes"
+ elif compile_prog "" "$uuid_libs" ; then
uuid="yes"
libs_softmmu="$uuid_libs $libs_softmmu"
libs_tools="$uuid_libs $libs_tools"
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 9f18d6a..bed0822 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -1275,6 +1275,29 @@
n->config_size = config_size;
}
+void virtio_net_set_netclient_name(VirtIONet *n, const char *name,
+ const char *type)
+{
+ /*
+ * The name can be NULL, the netclient name will be type.x.
+ */
+ assert(type != NULL);
+
+ if (n->netclient_name) {
+ g_free(n->netclient_name);
+ n->netclient_name = NULL;
+ }
+ if (n->netclient_type) {
+ g_free(n->netclient_type);
+ n->netclient_type = NULL;
+ }
+
+ if (name != NULL) {
+ n->netclient_name = g_strdup(name);
+ }
+ n->netclient_type = g_strdup(type);
+}
+
static int virtio_net_device_init(VirtIODevice *vdev)
{
int i;
@@ -1315,8 +1338,17 @@
memcpy(&n->mac[0], &n->nic_conf.macaddr, sizeof(n->mac));
n->status = VIRTIO_NET_S_LINK_UP;
- n->nic = qemu_new_nic(&net_virtio_info, &n->nic_conf,
- object_get_typename(OBJECT(qdev)), qdev->id, n);
+ if (n->netclient_type) {
+ /*
+ * Happen when virtio_net_set_netclient_name has been called.
+ */
+ n->nic = qemu_new_nic(&net_virtio_info, &n->nic_conf,
+ n->netclient_type, n->netclient_name, n);
+ } else {
+ n->nic = qemu_new_nic(&net_virtio_info, &n->nic_conf,
+ object_get_typename(OBJECT(qdev)), qdev->id, n);
+ }
+
peer_test_vnet_hdr(n);
if (peer_has_vnet_hdr(n)) {
for (i = 0; i < n->max_queues; i++) {
@@ -1357,6 +1389,15 @@
unregister_savevm(qdev, "virtio-net", n);
+ if (n->netclient_name) {
+ g_free(n->netclient_name);
+ n->netclient_name = NULL;
+ }
+ if (n->netclient_type) {
+ g_free(n->netclient_type);
+ n->netclient_type = NULL;
+ }
+
g_free(n->mac_table.macs);
g_free(n->vlans);
diff --git a/hw/pci-host/versatile.c b/hw/pci-host/versatile.c
index 540daf7..2f996d9 100644
--- a/hw/pci-host/versatile.c
+++ b/hw/pci-host/versatile.c
@@ -28,6 +28,36 @@
* this allows a newer kernel to use the INTERRUPT_LINE
* registers arbitrarily once it has indicated that it isn't
* broken in its init code somewhere.
+ *
+ * Unfortunately we have to cope with multiple different
+ * variants on the broken kernel behaviour:
+ * phase I (before kernel commit 1bc39ac5d) kernels assume old
+ * QEMU behaviour, so they use IRQ 27 for all slots
+ * phase II (1bc39ac5d and later, but before e3e92a7be6) kernels
+ * swizzle IRQs between slots, but do it wrongly, so they
+ * work only for every fourth PCI card, and only if (like old
+ * QEMU) the PCI host device is at slot 0 rather than where
+ * the h/w actually puts it
+ * phase III (e3e92a7be6 and later) kernels still swizzle IRQs between
+ * slots wrongly, but add a fixed offset of 64 to everything
+ * they write to PCI_INTERRUPT_LINE.
+ *
+ * We live in hope of a mythical phase IV kernel which might
+ * actually behave in ways that work on the hardware. Such a
+ * kernel should probably start off by writing some value neither
+ * 27 nor 91 to slot zero's PCI_INTERRUPT_LINE register to
+ * disable the autodetection. After that it can do what it likes.
+ *
+ * Slot % 4 | hw | I | II | III
+ * -------------------------------
+ * 0 | 29 | 27 | 27 | 91
+ * 1 | 30 | 27 | 28 | 92
+ * 2 | 27 | 27 | 29 | 93
+ * 3 | 28 | 27 | 30 | 94
+ *
+ * Since our autodetection is not perfect we also provide a
+ * property so the user can make us start in BROKEN or FORCE_OK
+ * on reset if they know they have a bad or good kernel.
*/
enum {
PCI_VPB_IRQMAP_ASSUME_OK,
@@ -56,6 +86,7 @@
/* Constant for life of device: */
int realview;
uint32_t mem_win_size[3];
+ uint8_t irq_mapping_prop;
/* Variable state: */
uint32_t imap[3];
@@ -214,6 +245,41 @@
},
};
+static int pci_vpb_broken_irq(int slot, int irq)
+{
+ /* Determine whether this IRQ value for this slot represents a
+ * known broken Linux kernel behaviour for this slot.
+ * Return one of the PCI_VPB_IRQMAP_ constants:
+ * BROKEN : if this definitely looks like a broken kernel
+ * FORCE_OK : if this definitely looks good
+ * ASSUME_OK : if we can't tell
+ */
+ slot %= PCI_NUM_PINS;
+
+ if (irq == 27) {
+ if (slot == 2) {
+ /* Might be a Phase I kernel, or might be a fixed kernel,
+ * since slot 2 is where we expect this IRQ.
+ */
+ return PCI_VPB_IRQMAP_ASSUME_OK;
+ }
+ /* Phase I kernel */
+ return PCI_VPB_IRQMAP_BROKEN;
+ }
+ if (irq == slot + 27) {
+ /* Phase II kernel */
+ return PCI_VPB_IRQMAP_BROKEN;
+ }
+ if (irq == slot + 27 + 64) {
+ /* Phase III kernel */
+ return PCI_VPB_IRQMAP_BROKEN;
+ }
+ /* Anything else must be a fixed kernel, possibly using an
+ * arbitrary irq map.
+ */
+ return PCI_VPB_IRQMAP_FORCE_OK;
+}
+
static void pci_vpb_config_write(void *opaque, hwaddr addr,
uint64_t val, unsigned size)
{
@@ -221,13 +287,7 @@
if (!s->realview && (addr & 0xff) == PCI_INTERRUPT_LINE
&& s->irq_mapping == PCI_VPB_IRQMAP_ASSUME_OK) {
uint8_t devfn = addr >> 8;
- if ((PCI_SLOT(devfn) % PCI_NUM_PINS) != 2) {
- if (val == 27) {
- s->irq_mapping = PCI_VPB_IRQMAP_BROKEN;
- } else {
- s->irq_mapping = PCI_VPB_IRQMAP_FORCE_OK;
- }
- }
+ s->irq_mapping = pci_vpb_broken_irq(PCI_SLOT(devfn), val);
}
pci_data_write(&s->pci_bus, addr, val, size);
}
@@ -311,7 +371,7 @@
s->smap[2] = 0;
s->selfid = 0;
s->flags = 0;
- s->irq_mapping = PCI_VPB_IRQMAP_ASSUME_OK;
+ s->irq_mapping = s->irq_mapping_prop;
pci_vpb_update_all_windows(s);
}
@@ -331,8 +391,6 @@
object_initialize(&s->pci_dev, TYPE_VERSATILE_PCI_HOST);
qdev_set_parent_bus(DEVICE(&s->pci_dev), BUS(&s->pci_bus));
- object_property_set_int(OBJECT(&s->pci_dev), PCI_DEVFN(29, 0), "addr",
- NULL);
/* Window sizes for VersatilePB; realview_pci's init will override */
s->mem_win_size[0] = 0x0c000000;
@@ -423,6 +481,12 @@
.class_init = versatile_pci_host_class_init,
};
+static Property pci_vpb_properties[] = {
+ DEFINE_PROP_UINT8("broken-irq-mapping", PCIVPBState, irq_mapping_prop,
+ PCI_VPB_IRQMAP_ASSUME_OK),
+ DEFINE_PROP_END_OF_LIST()
+};
+
static void pci_vpb_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
@@ -430,6 +494,7 @@
dc->realize = pci_vpb_realize;
dc->reset = pci_vpb_reset;
dc->vmsd = &pci_vpb_vmstate;
+ dc->props = pci_vpb_properties;
}
static const TypeInfo pci_vpb_info = {
diff --git a/hw/s390x/s390-virtio-bus.c b/hw/s390x/s390-virtio-bus.c
index 5a3d97c..a1cdfb0 100644
--- a/hw/s390x/s390-virtio-bus.c
+++ b/hw/s390x/s390-virtio-bus.c
@@ -152,10 +152,13 @@
static int s390_virtio_net_init(VirtIOS390Device *s390_dev)
{
+ DeviceState *qdev = DEVICE(s390_dev);
VirtIONetS390 *dev = VIRTIO_NET_S390(s390_dev);
DeviceState *vdev = DEVICE(&dev->vdev);
virtio_net_set_config_size(&dev->vdev, s390_dev->host_features);
+ virtio_net_set_netclient_name(&dev->vdev, qdev->id,
+ object_get_typename(OBJECT(qdev)));
qdev_set_parent_bus(vdev, BUS(&s390_dev->bus));
if (qdev_init(vdev) < 0) {
return -1;
diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index 76e6d32..5f5e267 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -550,10 +550,13 @@
static int virtio_ccw_net_init(VirtioCcwDevice *ccw_dev)
{
+ DeviceState *qdev = DEVICE(ccw_dev);
VirtIONetCcw *dev = VIRTIO_NET_CCW(ccw_dev);
DeviceState *vdev = DEVICE(&dev->vdev);
virtio_net_set_config_size(&dev->vdev, ccw_dev->host_features[0]);
+ virtio_net_set_netclient_name(&dev->vdev, qdev->id,
+ object_get_typename(OBJECT(qdev)));
qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus));
if (qdev_init(vdev) < 0) {
return -1;
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index 113fbd9..70d2c6b 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -1398,10 +1398,13 @@
static int virtio_net_pci_init(VirtIOPCIProxy *vpci_dev)
{
+ DeviceState *qdev = DEVICE(vpci_dev);
VirtIONetPCI *dev = VIRTIO_NET_PCI(vpci_dev);
DeviceState *vdev = DEVICE(&dev->vdev);
virtio_net_set_config_size(&dev->vdev, vpci_dev->host_features);
+ virtio_net_set_netclient_name(&dev->vdev, qdev->id,
+ object_get_typename(OBJECT(qdev)));
qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
if (qdev_init(vdev) < 0) {
return -1;
diff --git a/include/hw/virtio/virtio-net.h b/include/hw/virtio/virtio-net.h
index ce4ab50..beeead7 100644
--- a/include/hw/virtio/virtio-net.h
+++ b/include/hw/virtio/virtio-net.h
@@ -188,6 +188,8 @@
uint16_t max_queues;
uint16_t curr_queues;
size_t config_size;
+ char *netclient_name;
+ char *netclient_type;
} VirtIONet;
#define VIRTIO_NET_CTRL_MAC 1
@@ -255,5 +257,7 @@
DEFINE_PROP_STRING("tx", _state, _field.tx)
void virtio_net_set_config_size(VirtIONet *n, uint32_t host_features);
+void virtio_net_set_netclient_name(VirtIONet *n, const char *name,
+ const char *type);
#endif
diff --git a/include/qemu-common.h b/include/qemu-common.h
index af769f5..7f18b8e 100644
--- a/include/qemu-common.h
+++ b/include/qemu-common.h
@@ -448,12 +448,18 @@
/* vector definitions */
#ifdef __ALTIVEC__
#include <altivec.h>
-#define VECTYPE vector unsigned char
+/* The altivec.h header says we're allowed to undef these for
+ * C++ compatibility. Here we don't care about C++, but we
+ * undef them anyway to avoid namespace pollution.
+ */
+#undef vector
+#undef pixel
+#undef bool
+#define VECTYPE __vector unsigned char
#define SPLAT(p) vec_splat(vec_ld(0, p), 0)
#define ALL_EQ(v1, v2) vec_all_eq(v1, v2)
/* altivec.h may redefine the bool macro as vector type.
* Reset it to POSIX semantics. */
-#undef bool
#define bool _Bool
#elif defined __SSE2__
#include <emmintrin.h>
diff --git a/tests/ide-test.c b/tests/ide-test.c
index bdc1da7..365e995 100644
--- a/tests/ide-test.c
+++ b/tests/ide-test.c
@@ -252,7 +252,10 @@
uintptr_t guest_buf = guest_alloc(guest_malloc, len);
PrdtEntry prdt[] = {
- { .addr = guest_buf, .size = len | PRDT_EOT },
+ {
+ .addr = cpu_to_le32(guest_buf),
+ .size = cpu_to_le32(len | PRDT_EOT),
+ },
};
buf = g_malloc(len);
@@ -304,7 +307,10 @@
uint8_t status;
PrdtEntry prdt[] = {
- { .addr = 0, .size = 0x10 | PRDT_EOT },
+ {
+ .addr = 0,
+ .size = cpu_to_le32(0x10 | PRDT_EOT),
+ },
};
/* Normal request */
@@ -325,7 +331,10 @@
uint8_t status;
PrdtEntry prdt[] = {
- { .addr = 0, .size = 0x1000 | PRDT_EOT },
+ {
+ .addr = 0,
+ .size = cpu_to_le32(0x1000 | PRDT_EOT),
+ },
};
/* Normal request */
@@ -355,6 +364,17 @@
ide_test_quit();
}
+static void string_cpu_to_be16(uint16_t *s, size_t bytes)
+{
+ g_assert((bytes & 1) == 0);
+ bytes /= 2;
+
+ while (bytes--) {
+ *s = cpu_to_be16(*s);
+ s++;
+ }
+}
+
static void test_identify(void)
{
uint8_t data;
@@ -389,10 +409,12 @@
assert_bit_clear(data, BSY | DF | ERR | DRQ);
/* Check serial number/version in the buffer */
- ret = memcmp(&buf[10], "ettsidks ", 20);
+ string_cpu_to_be16(&buf[10], 20);
+ ret = memcmp(&buf[10], "testdisk ", 20);
g_assert(ret == 0);
- ret = memcmp(&buf[23], "evsroi n", 8);
+ string_cpu_to_be16(&buf[23], 8);
+ ret = memcmp(&buf[23], "version ", 8);
g_assert(ret == 0);
/* Write cache enabled bit */
diff --git a/ui/vnc.c b/ui/vnc.c
index 89108de..dfc7459 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -1601,6 +1601,7 @@
{
VncState *vs = opaque;
int caps, num, scr;
+ bool has_changed = (ledstate != current_led_state(vs));
caps = ledstate & QEMU_CAPS_LOCK_LED ? 1 : 0;
num = ledstate & QEMU_NUM_LOCK_LED ? 1 : 0;
@@ -1617,7 +1618,7 @@
}
/* Sending the current led state message to the client */
- if (ledstate != current_led_state(vs)) {
+ if (has_changed) {
vnc_led_state_change(vs);
}
}