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);
     }
 }