[Spice-commits] 57 commits - VERSION block/curl.c configure docs/tracing.txt hmp-commands.hx hmp.c hmp.h hw/9pfs hw/acpi_piix4.c hw/e1000.c hw/pxa2xx.c hw/s390x hw/virtio-net.c hw/virtio-net.h hw/virtio-pci.c hw/virtio.h hw/xilinx_zynq.c include/qemu include/qemu-common.h linux-user/qemu.h linux-user/strace.c linux-user/syscall.c net/net.c pc-bios/README pc-bios/bios.bin pc-bios/openbios-ppc pc-bios/openbios-sparc32 pc-bios/openbios-sparc64 qapi-schema.json qemu-char.c qemu-nbd.texi qemu-options.hx qmp-commands.hx roms/openbios target-cris/op_helper.c target-m68k/translate.c target-s390x/helper.c tests/Makefile tests/test-cutils.c trace/simple.c ui/vnc_keysym.h util/cutils.c util/iov.c vl.c

Gerd Hoffmann kraxel at kemper.freedesktop.org
Mon Feb 11 05:14:37 PST 2013


 VERSION                    |    2 
 block/curl.c               |   11 +
 configure                  |    2 
 docs/tracing.txt           |    4 
 hmp-commands.hx            |  102 +++++++++---------
 hmp.c                      |   30 +++--
 hmp.h                      |    4 
 hw/9pfs/virtio-9p.c        |   12 +-
 hw/acpi_piix4.c            |    4 
 hw/e1000.c                 |   42 ++++++-
 hw/pxa2xx.c                |   16 +-
 hw/s390x/s390-virtio-bus.c |    3 
 hw/s390x/virtio-ccw.c      |    3 
 hw/virtio-net.c            |   43 ++++++-
 hw/virtio-net.h            |    2 
 hw/virtio-pci.c            |    3 
 hw/virtio.h                |    3 
 hw/xilinx_zynq.c           |    2 
 include/qemu-common.h      |    4 
 include/qemu/bswap.h       |   12 +-
 linux-user/qemu.h          |    4 
 linux-user/strace.c        |    2 
 linux-user/syscall.c       |   48 ++++++--
 net/net.c                  |    2 
 pc-bios/README             |    2 
 pc-bios/bios.bin           |binary
 pc-bios/openbios-ppc       |binary
 pc-bios/openbios-sparc32   |binary
 pc-bios/openbios-sparc64   |binary
 qapi-schema.json           |   71 +++++-------
 qemu-char.c                |  140 +++++++++++--------------
 qemu-nbd.texi              |    7 +
 qemu-options.hx            |   13 --
 qmp-commands.hx            |   61 +++++-----
 roms/openbios              |    2 
 target-cris/op_helper.c    |    2 
 target-m68k/translate.c    |    2 
 target-s390x/helper.c      |    4 
 tests/Makefile             |    3 
 tests/test-cutils.c        |  251 +++++++++++++++++++++++++++++++++++++++++++++
 trace/simple.c             |   39 ++----
 ui/vnc_keysym.h            |    4 
 util/cutils.c              |   99 +++++++++++++++++
 util/iov.c                 |    4 
 vl.c                       |   93 ++++++++++++----
 45 files changed, 828 insertions(+), 329 deletions(-)

New commits:
commit 10442558ab1797bfbb01285b909e34c5cf038f12
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sat Feb 9 13:39:45 2013 +0000

    Update OpenBIOS images
    
    Update OpenBIOS images to SVN r1097 built from submodule.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/pc-bios/README b/pc-bios/README
index eff3de7..bb182dc 100644
--- a/pc-bios/README
+++ b/pc-bios/README
@@ -12,7 +12,7 @@
   1275-1994 (referred to as Open Firmware) compliant firmware.
   The included images for PowerPC (for 32 and 64 bit PPC CPUs),
   Sparc32 and Sparc64 are built from OpenBIOS SVN revision
-  1063.
+  1097.
 
 - SLOF (Slimline Open Firmware) is a free IEEE 1275 Open Firmware
   implementation for certain IBM POWER hardware.  The sources are at
diff --git a/pc-bios/openbios-ppc b/pc-bios/openbios-ppc
index 5311eca..c37c258 100644
Binary files a/pc-bios/openbios-ppc and b/pc-bios/openbios-ppc differ
diff --git a/pc-bios/openbios-sparc32 b/pc-bios/openbios-sparc32
index 6bd8e45..79e816e 100644
Binary files a/pc-bios/openbios-sparc32 and b/pc-bios/openbios-sparc32 differ
diff --git a/pc-bios/openbios-sparc64 b/pc-bios/openbios-sparc64
index 7c06fcc..14624e9 100644
Binary files a/pc-bios/openbios-sparc64 and b/pc-bios/openbios-sparc64 differ
diff --git a/roms/openbios b/roms/openbios
index f095c85..a5af2b3 160000
--- a/roms/openbios
+++ b/roms/openbios
@@ -1 +1 @@
-Subproject commit f095c858136896d236931357b8d597f407286f71
+Subproject commit a5af2b322e54104f1b095c8c156ffd03bf6ca3e9
commit 70ef6a5b7121cb54d7f9713d6315fb8547761bfc
Author: Liming Wang <walimisdev at gmail.com>
Date:   Thu Feb 7 16:58:15 2013 +1000

    xilinx_zynq: Fix wrong IRQ number of the second EHCI controller
    
    The IRQ number of the second EHCI controller should be 76, not 75.
    
    Signed-off-by: Liming Wang <walimisdev at gmail.com>
    Tested-by: Peter Crosthwaite <peter.crosthwaite at petalogix.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/xilinx_zynq.c b/hw/xilinx_zynq.c
index 0ac33b5..311f791 100644
--- a/hw/xilinx_zynq.c
+++ b/hw/xilinx_zynq.c
@@ -168,7 +168,7 @@ static void zynq_init(QEMUMachineInitArgs *args)
     zynq_init_spi_flashes(0xE000D000, pic[51-IRQ_OFFSET], true);
 
     sysbus_create_simple("xlnx,ps7-usb", 0xE0002000, pic[53-IRQ_OFFSET]);
-    sysbus_create_simple("xlnx,ps7-usb", 0xE0003000, pic[75-IRQ_OFFSET]);
+    sysbus_create_simple("xlnx,ps7-usb", 0xE0003000, pic[76-IRQ_OFFSET]);
 
     sysbus_create_simple("cadence_uart", 0xE0000000, pic[59-IRQ_OFFSET]);
     sysbus_create_simple("cadence_uart", 0xE0001000, pic[82-IRQ_OFFSET]);
commit fb6d1bbd246c7a57ef53d3847ef225cd1349d602
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Fri Feb 8 08:49:10 2013 +0100

    block/curl: disable extra protocols to prevent CVE-2013-0249
    
    There is a buffer overflow in libcurl POP3/SMTP/IMAP.  The workaround is
    simple: disable extra protocols so that they cannot be exploited.  Full
    details here:
    
      http://curl.haxx.se/docs/adv_20130206.html
    
    QEMU only cares about HTTP, HTTPS, FTP, FTPS, and TFTP.  I have tested
    that this fix prevents the exploit on my host with
    libcurl-7.27.0-5.fc18.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/block/curl.c b/block/curl.c
index 47df952..f6226b3 100644
--- a/block/curl.c
+++ b/block/curl.c
@@ -34,6 +34,10 @@
 #define DPRINTF(fmt, ...) do { } while (0)
 #endif
 
+#define PROTOCOLS (CURLPROTO_HTTP | CURLPROTO_HTTPS | \
+                   CURLPROTO_FTP | CURLPROTO_FTPS | \
+                   CURLPROTO_TFTP)
+
 #define CURL_NUM_STATES 8
 #define CURL_NUM_ACB    8
 #define SECTOR_SIZE     512
@@ -302,6 +306,13 @@ static CURLState *curl_init_state(BDRVCURLState *s)
     curl_easy_setopt(state->curl, CURLOPT_ERRORBUFFER, state->errmsg);
     curl_easy_setopt(state->curl, CURLOPT_FAILONERROR, 1);
 
+    /* Restrict supported protocols to avoid security issues in the more
+     * obscure protocols.  For example, do not allow POP3/SMTP/IMAP see
+     * CVE-2013-0249.
+     */
+    curl_easy_setopt(state->curl, CURLOPT_PROTOCOLS, PROTOCOLS);
+    curl_easy_setopt(state->curl, CURLOPT_REDIR_PROTOCOLS, PROTOCOLS);
+
 #ifdef DEBUG_VERBOSE
     curl_easy_setopt(state->curl, CURLOPT_VERBOSE, 1);
 #endif
commit 0eb256a2173d35c64696189adcd3599be61922ef
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Feb 8 13:19:07 2013 +0100

    qemu-nbd: document --cache and --aio options
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-nbd.texi b/qemu-nbd.texi
index 6955d90..3e57200 100644
--- a/qemu-nbd.texi
+++ b/qemu-nbd.texi
@@ -29,7 +29,12 @@ Export QEMU disk image using NBD protocol.
 @item -s, --snapshot
   use snapshot file
 @item -n, --nocache
-  disable host cache
+ at itemx --cache=@var{cache}
+  set cache mode to be used with the file.  See the documentation of
+  the emulator's @code{-drive cache=...} option for allowed values.
+ at item --aio=@var{aio}
+  choose asynchronous I/O mode between @samp{threads} (the default)
+  and @samp{native} (Linux only).
 @item -c, --connect=@var{dev}
   connect @var{filename} to NBD device @var{dev}
 @item -d, --disconnect
commit 32ab06bcf1352848eec42629a85e20efa4e105dc
Author: Jesse Larrew <jlarrew at linux.vnet.ibm.com>
Date:   Tue Feb 5 17:47:17 2013 -0600

    hw/virtio-net: disable multiqueue by default
    
    The new multiqueue feature adds fields to the virtio device config, which
    breaks Windows guests. Disable the feature by default until the Windows
    drivers are fixed.
    
    Signed-off-by: Jesse Larrew <jlarrew at linux.vnet.ibm.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-net.h b/hw/virtio-net.h
index f5fea6e..e654c13 100644
--- a/hw/virtio-net.h
+++ b/hw/virtio-net.h
@@ -191,6 +191,6 @@ struct virtio_net_ctrl_mq {
         DEFINE_PROP_BIT("ctrl_vlan", _state, _field, VIRTIO_NET_F_CTRL_VLAN, true), \
         DEFINE_PROP_BIT("ctrl_rx_extra", _state, _field, VIRTIO_NET_F_CTRL_RX_EXTRA, true), \
         DEFINE_PROP_BIT("ctrl_mac_addr", _state, _field, VIRTIO_NET_F_CTRL_MAC_ADDR, true), \
-        DEFINE_PROP_BIT("mq", _state, _field, VIRTIO_NET_F_MQ, true)
+        DEFINE_PROP_BIT("mq", _state, _field, VIRTIO_NET_F_MQ, false)
 
 #endif
commit 14f9b664b34bbd37a488cb5c762aa278c60e1fb6
Author: Jesse Larrew <jlarrew at linux.vnet.ibm.com>
Date:   Tue Feb 5 17:47:16 2013 -0600

    hw/virtio-net.c: set config size using host features
    
    Currently, the config size for virtio devices is hard coded. When a new
    feature is added that changes the config size, drivers that assume a static
    config size will break. For purposes of backward compatibility, there needs
    to be a way to inform drivers of the config size needed to accommodate the
    set of features enabled.
    
    aliguori: merged in
     - hw/virtio-net: use existing macros to implement endof
     - hw/virtio-net: fix config_size data type
    
    Signed-off-by: Jesse Larrew <jlarrew at linux.vnet.ibm.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-net.c b/hw/virtio-net.c
index f1c2884..573c669 100644
--- a/hw/virtio-net.c
+++ b/hw/virtio-net.c
@@ -73,8 +73,31 @@ typedef struct VirtIONet
     int multiqueue;
     uint16_t max_queues;
     uint16_t curr_queues;
+    size_t config_size;
 } VirtIONet;
 
+/*
+ * Calculate the number of bytes up to and including the given 'field' of
+ * 'container'.
+ */
+#define endof(container, field) \
+    (offsetof(container, field) + sizeof(((container *)0)->field))
+
+typedef struct VirtIOFeature {
+    uint32_t flags;
+    size_t end;
+} VirtIOFeature;
+
+static VirtIOFeature feature_sizes[] = {
+    {.flags = 1 << VIRTIO_NET_F_MAC,
+     .end = endof(struct virtio_net_config, mac)},
+    {.flags = 1 << VIRTIO_NET_F_STATUS,
+     .end = endof(struct virtio_net_config, status)},
+    {.flags = 1 << VIRTIO_NET_F_MQ,
+     .end = endof(struct virtio_net_config, max_virtqueue_pairs)},
+    {}
+};
+
 static VirtIONetQueue *virtio_net_get_subqueue(NetClientState *nc)
 {
     VirtIONet *n = qemu_get_nic_opaque(nc);
@@ -104,15 +127,15 @@ static void virtio_net_get_config(VirtIODevice *vdev, uint8_t *config)
     stw_p(&netcfg.status, n->status);
     stw_p(&netcfg.max_virtqueue_pairs, n->max_queues);
     memcpy(netcfg.mac, n->mac, ETH_ALEN);
-    memcpy(config, &netcfg, sizeof(netcfg));
+    memcpy(config, &netcfg, n->config_size);
 }
 
 static void virtio_net_set_config(VirtIODevice *vdev, const uint8_t *config)
 {
     VirtIONet *n = to_virtio_net(vdev);
-    struct virtio_net_config netcfg;
+    struct virtio_net_config netcfg = {};
 
-    memcpy(&netcfg, config, sizeof(netcfg));
+    memcpy(&netcfg, config, n->config_size);
 
     if (!(n->vdev.guest_features >> VIRTIO_NET_F_CTRL_MAC_ADDR & 1) &&
         memcmp(netcfg.mac, n->mac, ETH_ALEN)) {
@@ -1279,16 +1302,21 @@ static void virtio_net_guest_notifier_mask(VirtIODevice *vdev, int idx,
 }
 
 VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf,
-                              virtio_net_conf *net,
-                              uint32_t host_features)
+                              virtio_net_conf *net, uint32_t host_features)
 {
     VirtIONet *n;
-    int i;
+    int i, config_size = 0;
+
+    for (i = 0; feature_sizes[i].flags != 0; i++) {
+        if (host_features & feature_sizes[i].flags) {
+            config_size = MAX(feature_sizes[i].end, config_size);
+        }
+    }
 
     n = (VirtIONet *)virtio_common_init("virtio-net", VIRTIO_ID_NET,
-                                        sizeof(struct virtio_net_config),
-                                        sizeof(VirtIONet));
+                                        config_size, sizeof(VirtIONet));
 
+    n->config_size = config_size;
     n->vdev.get_config = virtio_net_get_config;
     n->vdev.set_config = virtio_net_set_config;
     n->vdev.get_features = virtio_net_get_features;
commit 1e89ad5b00ba0426d4e949c9e6ce2926c15b81b7
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Feb 5 17:47:15 2013 -0600

    virtio-net: pass host features to virtio_net_init
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/s390x/s390-virtio-bus.c b/hw/s390x/s390-virtio-bus.c
index d467781..089ed92 100644
--- a/hw/s390x/s390-virtio-bus.c
+++ b/hw/s390x/s390-virtio-bus.c
@@ -153,7 +153,8 @@ static int s390_virtio_net_init(VirtIOS390Device *dev)
 {
     VirtIODevice *vdev;
 
-    vdev = virtio_net_init((DeviceState *)dev, &dev->nic, &dev->net);
+    vdev = virtio_net_init((DeviceState *)dev, &dev->nic, &dev->net,
+                           dev->host_features);
     if (!vdev) {
         return -1;
     }
diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index 231f81e..d92e427 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -555,7 +555,8 @@ static int virtio_ccw_net_init(VirtioCcwDevice *dev)
 {
     VirtIODevice *vdev;
 
-    vdev = virtio_net_init((DeviceState *)dev, &dev->nic, &dev->net);
+    vdev = virtio_net_init((DeviceState *)dev, &dev->nic, &dev->net,
+                           dev->host_features[0]);
     if (!vdev) {
         return -1;
     }
diff --git a/hw/virtio-net.c b/hw/virtio-net.c
index e37358a..f1c2884 100644
--- a/hw/virtio-net.c
+++ b/hw/virtio-net.c
@@ -1279,7 +1279,8 @@ static void virtio_net_guest_notifier_mask(VirtIODevice *vdev, int idx,
 }
 
 VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf,
-                              virtio_net_conf *net)
+                              virtio_net_conf *net,
+                              uint32_t host_features)
 {
     VirtIONet *n;
     int i;
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index 9abbcdf..a869f53 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -997,7 +997,8 @@ static int virtio_net_init_pci(PCIDevice *pci_dev)
     VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
     VirtIODevice *vdev;
 
-    vdev = virtio_net_init(&pci_dev->qdev, &proxy->nic, &proxy->net);
+    vdev = virtio_net_init(&pci_dev->qdev, &proxy->nic, &proxy->net,
+                           proxy->host_features);
 
     vdev->nvectors = proxy->nvectors;
     virtio_init_pci(proxy, vdev);
diff --git a/hw/virtio.h b/hw/virtio.h
index a29a54d..1e206b8 100644
--- a/hw/virtio.h
+++ b/hw/virtio.h
@@ -243,7 +243,8 @@ typedef struct VirtIOBlkConf VirtIOBlkConf;
 VirtIODevice *virtio_blk_init(DeviceState *dev, VirtIOBlkConf *blk);
 struct virtio_net_conf;
 VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf,
-                              struct virtio_net_conf *net);
+                              struct virtio_net_conf *net,
+                              uint32_t host_features);
 typedef struct virtio_serial_conf virtio_serial_conf;
 VirtIODevice *virtio_serial_init(DeviceState *dev, virtio_serial_conf *serial);
 VirtIODevice *virtio_balloon_init(DeviceState *dev);
commit b890492110ccdc943554231d40b67d29fef6af82
Author: Michael Roth <mdroth at linux.vnet.ibm.com>
Date:   Wed Feb 6 18:25:48 2013 -0600

    net: fix infinite loop on exit
    
    1ceef9f27359cbe92ef124bf74de6f792e71f6fb added handling for cleaning
    up multiple queues in qemu_del_nic() for cases where multiqueue is in
    use. To determine the number of queues it looks at nic->conf->queues,
    then iterates through all the queues to cleanup the associated
    NetClientStates. If no queues are found, no NetClientStates are deleted.
    
    However, nic->conf->queues is only set when a peer is created via
    -netdev or netdev_add, and is otherwise 0. This causes us to spin in
    net_cleanup() if we attempt to shut down qemu before adding a host
    device.
    
    Since qemu_new_nic() unconditionally creates at least 1
    queue/NetClientState at queue idx 0, make qemu_del_nic() always attempt
    to clean it up.
    
    Signed-off-by: Michael Roth <mdroth at linux.vnet.ibm.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/net/net.c b/net/net.c
index 9806862..f9e7136 100644
--- a/net/net.c
+++ b/net/net.c
@@ -351,7 +351,7 @@ void qemu_del_net_client(NetClientState *nc)
 
 void qemu_del_nic(NICState *nic)
 {
-    int i, queues = nic->conf->queues;
+    int i, queues = MAX(nic->conf->queues, 1);
 
     /* If this is a peer NIC and peer has already been deleted, free it now. */
     if (nic->peer_deleted) {
commit ecd8d4715ea33aa2c146a5047bacb031e86af599
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Wed Feb 6 18:33:47 2013 -0600

    Update version for release
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/VERSION b/VERSION
index 619d9ea..aa6058d 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.3.90
+1.3.91
commit bd4bd24ed3e33f4f0ffa9dde23b8b85430592dc6
Merge: 0bc8ce9 c07ecc6
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Wed Feb 6 16:39:04 2013 -0600

    Merge branch 'for-linux-user' of https://git.gitorious.org/qemu-m68k/qemu-m68k into staging
    
    * 'for-linux-user' of https://git.gitorious.org/qemu-m68k/qemu-m68k:
      linux-user: correct reboot()
      linux-user: correct setsockopt()
      linux-user: correct print_timeval() swap tv_sec and tv_usec
      linux-user: correct msgrcv()
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

commit 0bc8ce9460c1f51211e797a825432e55327b70c6
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Thu Jan 31 12:50:40 2013 +0000

    linux-user: Restore cast to target type in get_user()
    
    Commit 658f2dc97 accidentally dropped the cast to the target type of
    the value loaded by get_user().  The most visible effect of this would
    be that the sequence "uint64_t v; get_user_u32(v, addr)" would sign
    extend the 32 bit loaded value into v rather than zero extending as
    would be expected for a _u32 accessor.  Put the cast back again to
    restore the old behaviour.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index 31a220a..b10e957 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -306,12 +306,12 @@ static inline int access_ok(int type, abi_ulong addr, abi_ulong size)
      ((hptr), (x)), 0)
 
 #define __get_user_e(x, hptr, e)                                        \
-  ((x) =                                                                \
+  ((x) = (typeof(*hptr))(                                               \
    __builtin_choose_expr(sizeof(*(hptr)) == 1, ldub_p,                  \
    __builtin_choose_expr(sizeof(*(hptr)) == 2, lduw_##e##_p,            \
    __builtin_choose_expr(sizeof(*(hptr)) == 4, ldl_##e##_p,             \
    __builtin_choose_expr(sizeof(*(hptr)) == 8, ldq_##e##_p, abort))))   \
-     (hptr), 0)
+     (hptr)), 0)
 
 #ifdef TARGET_WORDS_BIGENDIAN
 # define __put_user(x, hptr)  __put_user_e(x, hptr, be)
commit f565235b71b7be66f3f6b385a5377969f5ed26f7
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Sat Feb 2 15:13:02 2013 +0000

    hw/pxa2xx: Fix transposed crn/crm values for pxa2xx cp14 perf regs
    
    When the pxa2xx performance counter related cp14 registers were converted
    from a switch-statement implementation to the new table driven cpregs
    format in commit dc2a9045c, the crn and crm values for all these
    registers were accidentally transposed. Fix this mistake, which was
    causing OpenBSD for Zaurus to fail to boot.
    
    Reported-by: Jonathan Gray <jsg at jsg.id.au>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
index 373d061..d303320 100644
--- a/hw/pxa2xx.c
+++ b/hw/pxa2xx.c
@@ -343,23 +343,23 @@ static int pxa2xx_cpccnt_read(CPUARMState *env, const ARMCPRegInfo *ri,
 }
 
 static const ARMCPRegInfo pxa_cp_reginfo[] = {
-    /* cp14 crn==1: perf registers */
-    { .name = "CPPMNC", .cp = 14, .crn = 1, .crm = 0, .opc1 = 0, .opc2 = 0,
+    /* cp14 crm==1: perf registers */
+    { .name = "CPPMNC", .cp = 14, .crn = 0, .crm = 1, .opc1 = 0, .opc2 = 0,
       .access = PL1_RW,
       .readfn = pxa2xx_cppmnc_read, .writefn = pxa2xx_cppmnc_write },
     { .name = "CPCCNT", .cp = 14, .crn = 1, .crm = 1, .opc1 = 0, .opc2 = 0,
       .access = PL1_RW,
       .readfn = pxa2xx_cpccnt_read, .writefn = arm_cp_write_ignore },
-    { .name = "CPINTEN", .cp = 14, .crn = 1, .crm = 4, .opc1 = 0, .opc2 = 0,
+    { .name = "CPINTEN", .cp = 14, .crn = 4, .crm = 1, .opc1 = 0, .opc2 = 0,
       .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
-    { .name = "CPFLAG", .cp = 14, .crn = 1, .crm = 5, .opc1 = 0, .opc2 = 0,
+    { .name = "CPFLAG", .cp = 14, .crn = 5, .crm = 1, .opc1 = 0, .opc2 = 0,
       .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
-    { .name = "CPEVTSEL", .cp = 14, .crn = 1, .crm = 8, .opc1 = 0, .opc2 = 0,
+    { .name = "CPEVTSEL", .cp = 14, .crn = 8, .crm = 1, .opc1 = 0, .opc2 = 0,
       .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
-    /* cp14 crn==2: performance count registers */
-    { .name = "CPPMN0", .cp = 14, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 0,
+    /* cp14 crm==2: performance count registers */
+    { .name = "CPPMN0", .cp = 14, .crn = 0, .crm = 2, .opc1 = 0, .opc2 = 0,
       .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
-    { .name = "CPPMN1", .cp = 14, .crn = 2, .crm = 1, .opc1 = 0, .opc2 = 0,
+    { .name = "CPPMN1", .cp = 14, .crn = 1, .crm = 2, .opc1 = 0, .opc2 = 0,
       .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
     { .name = "CPPMN2", .cp = 14, .crn = 2, .crm = 2, .opc1 = 0, .opc2 = 0,
       .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
commit 5b2cd9857d945cc1e9b6f596c757f70e25aed60c
Merge: 3f23624 8f44015
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Wed Feb 6 16:36:16 2013 -0600

    Merge remote-tracking branch 'stefanha/tracing' into staging
    
    # By Markus Armbruster
    # Via Stefan Hajnoczi
    * stefanha/tracing:
      trace: Fix location of simpletrace.py in docs
      trace: Clean up the "try to update atomic until it worked" loops
      trace: Direct access of atomics is verboten, use the API
      trace: Fix simple trace dropped event record for big endian

commit 3f23624c848b8f1c88e4305fe01e19b2520bfd3d
Merge: 8a14952 2a0e1ad
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Wed Feb 6 16:36:11 2013 -0600

    Merge remote-tracking branch 'stefanha/trivial-patches' into staging
    
    # By Michael Tokarev (1) and Stefan Weil (1)
    # Via Stefan Hajnoczi
    * stefanha/trivial-patches:
      vnc: recognize Hungarian doubleacutes
      target-m68k: Fix comment

commit 8a14952c9d2f5fa2b3caa6dc286b62ed5d26bca7
Author: Markus Armbruster <armbru at redhat.com>
Date:   Wed Feb 6 17:07:46 2013 +0100

    hmp: Disable chardev-add and chardev-remove
    
    As a general rule, HMP commands must be built on top of the QMP API.
    Luiz and others have worked long & hard to make HMP conform to this
    rule.
    
    Commit f1088908 added chardev-add, in violation of this rule.  QMP
    command chardev-add was added right before, with minimal features, and
    the idea to complete it step by step, then switch over the HMP command
    to use it.
    
    Unfortunately, we're not there, yet, and we don't want to release with
    chardev-add in a "HMP is more powerful than QMP" state.
    
    Disable the HMP command for now, along with its chardev-remove buddy.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hmp-commands.hx b/hmp-commands.hx
index 4c100d7..64008a9 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1522,37 +1522,38 @@ passed since 1970, i.e. unix epoch.
 @end table
 ETEXI
 
-    {
-        .name       = "chardev-add",
-        .args_type  = "args:s",
-        .params     = "args",
-        .help       = "add chardev",
-        .mhandler.cmd = hmp_chardev_add,
-    },
-
-STEXI
- at item chardev_add args
- at findex chardev_add
-
-chardev_add accepts the same parameters as the -chardev command line switch.
-
-ETEXI
-
-    {
-        .name       = "chardev-remove",
-        .args_type  = "id:s",
-        .params     = "id",
-        .help       = "remove chardev",
-        .mhandler.cmd = hmp_chardev_remove,
-    },
-
-STEXI
- at item chardev_remove id
- at findex chardev_remove
-
-Removes the chardev @var{id}.
-
-ETEXI
+HXCOMM Disabled for now, because it isn't built on top of QMP's chardev-add
+HXCOMM     {
+HXCOMM         .name       = "chardev-add",
+HXCOMM         .args_type  = "args:s",
+HXCOMM         .params     = "args",
+HXCOMM         .help       = "add chardev",
+HXCOMM         .mhandler.cmd = hmp_chardev_add,
+HXCOMM     },
+HXCOMM
+HXCOMM STEXI
+HXCOMM @item chardev_add args
+HXCOMM @findex chardev_add
+HXCOMM
+HXCOMM chardev_add accepts the same parameters as the -chardev command line switch.
+HXCOMM
+HXCOMM ETEXI
+HXCOMM
+HXCOMM     {
+HXCOMM         .name       = "chardev-remove",
+HXCOMM         .args_type  = "id:s",
+HXCOMM         .params     = "id",
+HXCOMM         .help       = "remove chardev",
+HXCOMM         .mhandler.cmd = hmp_chardev_remove,
+HXCOMM     },
+HXCOMM
+HXCOMM STEXI
+HXCOMM @item chardev_remove id
+HXCOMM @findex chardev_remove
+HXCOMM
+HXCOMM Removes the chardev @var{id}.
+HXCOMM
+HXCOMM ETEXI
 
     {
         .name       = "info",
commit 543f34126b7bfc85b05d0e371e3ce0695444f433
Author: Markus Armbruster <armbru at redhat.com>
Date:   Wed Feb 6 21:27:26 2013 +0100

    hmp: make memchar-read escape ASCII control chars except \n and \t
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hmp-commands.hx b/hmp-commands.hx
index 66ec716..4c100d7 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -869,6 +869,8 @@ STEXI
 @findex ringbuf_read
 Read and print up to @var{size} bytes from ring buffer character
 device @var{device}.
+Certain non-printable characters are printed \uXXXX, where XXXX is the
+character code in hexadecimal.  Character \ is printed \\.
 Bug: can screw up when the buffer contains invalid UTF-8 sequences,
 NUL characters, after the ring buffer lost data, and when reading
 stops because the size limit is reached.
diff --git a/hmp.c b/hmp.c
index cbd5727..420d48b 100644
--- a/hmp.c
+++ b/hmp.c
@@ -679,6 +679,7 @@ void hmp_ringbuf_read(Monitor *mon, const QDict *qdict)
     const char *chardev = qdict_get_str(qdict, "device");
     char *data;
     Error *errp = NULL;
+    int i;
 
     data = qmp_ringbuf_read(chardev, size, false, 0, &errp);
     if (errp) {
@@ -687,7 +688,19 @@ void hmp_ringbuf_read(Monitor *mon, const QDict *qdict)
         return;
     }
 
-    monitor_printf(mon, "%s\n", data);
+    for (i = 0; data[i]; i++) {
+        unsigned char ch = data[i];
+
+        if (ch == '\\') {
+            monitor_printf(mon, "\\\\");
+        } else if ((ch < 0x20 && ch != '\n' && ch != '\t') || ch == 0x7F) {
+            monitor_printf(mon, "\\u%04X", ch);
+        } else {
+            monitor_printf(mon, "%c", ch);
+        }
+
+    }
+    monitor_printf(mon, "\n");
     g_free(data);
 }
 
commit de1cc36e1039faf65b1739d28bef9f2a4e230eb6
Author: Markus Armbruster <armbru at redhat.com>
Date:   Wed Feb 6 21:27:25 2013 +0100

    qemu-char: Support suffixed ringbuf size arguments like "size=64K"
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-char.c b/qemu-char.c
index 8a35403..a3ba021 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -98,7 +98,6 @@
 #include "ui/qemu-spice.h"
 
 #define READ_BUF_LEN 4096
-#define CBUFF_SIZE 65536
 
 /***********************************************************/
 /* character device */
@@ -2709,9 +2708,9 @@ static CharDriverState *qemu_chr_open_ringbuf(QemuOpts *opts)
     chr = g_malloc0(sizeof(CharDriverState));
     d = g_malloc(sizeof(*d));
 
-    d->size = qemu_opt_get_number(opts, "size", 0);
+    d->size = qemu_opt_get_size(opts, "size", 0);
     if (d->size == 0) {
-        d->size = CBUFF_SIZE;
+        d->size = 65536;
     }
 
     /* The size must be power of 2 */
@@ -3244,7 +3243,7 @@ QemuOptsList qemu_chardev_opts = {
             .type = QEMU_OPT_NUMBER,
         },{
             .name = "size",
-            .type = QEMU_OPT_NUMBER,
+            .type = QEMU_OPT_SIZE,
         },
         { /* end of list */ }
     },
commit 3949e59414fccefadc50ae65650d676cc734048c
Author: Markus Armbruster <armbru at redhat.com>
Date:   Wed Feb 6 21:27:24 2013 +0100

    qemu-char: Saner naming of memchar stuff & doc fixes
    
    New device, has never been released, so we can still improve things
    without worrying about compatibility.
    
    Naming is a mess.  The code calls the device driver CirMemCharDriver,
    the public API calls it "memory", "memchardev", or "memchar", and the
    special commands are named like "memchar-FOO".  "memory" is a
    particularly unfortunate choice, because there's another character
    device driver called MemoryDriver.  Moreover, the device's distinctive
    property is that it's a ring buffer, not that's in memory.  Therefore:
    
    * Rename CirMemCharDriver to RingBufCharDriver, and call the thing a
      "ringbuf" in the API.
    
    * Rename QMP and HMP commands from memchar-FOO to ringbuf-FOO.
    
    * Rename device parameter from maxcapacity to size (simple words are
      good for you).
    
    * Clearly mark the parameter as optional in documentation.
    
    * Fix error reporting so that chardev-add reports to current monitor,
      not stderr.
    
    * Replace cirmem in C identifiers by ringbuf.
    
    * Rework documentation.  Document the impact of our crappy UTF-8
      handling on reading.
    
    * QMP examples that even work.
    
    I could split this up into multiple commits, but they'd change the
    same documentation lines multiple times.  Not worth it.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hmp-commands.hx b/hmp-commands.hx
index bdd48f3..66ec716 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -841,40 +841,37 @@ Inject an NMI on the given CPU (x86 only).
 ETEXI
 
     {
-        .name       = "memchar_write",
+        .name       = "ringbuf_write",
         .args_type  = "device:s,data:s",
         .params     = "device data",
-        .help       = "Provide writing interface for CirMemCharDriver. Write"
-                      "'data' to it.",
-        .mhandler.cmd = hmp_memchar_write,
+        .help       = "Write to a ring buffer character device",
+        .mhandler.cmd = hmp_ringbuf_write,
     },
 
 STEXI
- at item memchar_write @var{device} @var{data}
- at findex memchar_write
-Provide writing interface for CirMemCharDriver. Write @var{data}
-to char device 'memory'.
+ at item ringbuf_write @var{device} @var{data}
+ at findex ringbuf_write
+Write @var{data} to ring buffer character device @var{device}.
+ at var{data} must be a UTF-8 string.
 
 ETEXI
 
     {
-        .name       = "memchar_read",
+        .name       = "ringbuf_read",
         .args_type  = "device:s,size:i",
         .params     = "device size",
-        .help       = "Provide read interface for CirMemCharDriver. Read from"
-                      "it and return the data with size.",
-        .mhandler.cmd = hmp_memchar_read,
+        .help       = "Read from a ring buffer character device",
+        .mhandler.cmd = hmp_ringbuf_read,
     },
 
 STEXI
- at item memchar_read @var{device}
- at findex memchar_read
-Provide read interface for CirMemCharDriver. Read from char device
-'memory' and return the data.
-
- at var{size} is the size of data want to read from. Refer to unencoded
-size of the raw data, would adjust to the init size of the memchar
-if the requested size is larger than it.
+ at item ringbuf_read @var{device}
+ at findex ringbuf_read
+Read and print up to @var{size} bytes from ring buffer character
+device @var{device}.
+Bug: can screw up when the buffer contains invalid UTF-8 sequences,
+NUL characters, after the ring buffer lost data, and when reading
+stops because the size limit is reached.
 
 ETEXI
 
diff --git a/hmp.c b/hmp.c
index f6bb767..cbd5727 100644
--- a/hmp.c
+++ b/hmp.c
@@ -662,25 +662,25 @@ void hmp_pmemsave(Monitor *mon, const QDict *qdict)
     hmp_handle_error(mon, &errp);
 }
 
-void hmp_memchar_write(Monitor *mon, const QDict *qdict)
+void hmp_ringbuf_write(Monitor *mon, const QDict *qdict)
 {
     const char *chardev = qdict_get_str(qdict, "device");
     const char *data = qdict_get_str(qdict, "data");
     Error *errp = NULL;
 
-    qmp_memchar_write(chardev, data, false, 0, &errp);
+    qmp_ringbuf_write(chardev, data, false, 0, &errp);
 
     hmp_handle_error(mon, &errp);
 }
 
-void hmp_memchar_read(Monitor *mon, const QDict *qdict)
+void hmp_ringbuf_read(Monitor *mon, const QDict *qdict)
 {
     uint32_t size = qdict_get_int(qdict, "size");
     const char *chardev = qdict_get_str(qdict, "device");
     char *data;
     Error *errp = NULL;
 
-    data = qmp_memchar_read(chardev, size, false, 0, &errp);
+    data = qmp_ringbuf_read(chardev, size, false, 0, &errp);
     if (errp) {
         monitor_printf(mon, "%s\n", error_get_pretty(errp));
         error_free(errp);
diff --git a/hmp.h b/hmp.h
index 076d8cf..30b3c20 100644
--- a/hmp.h
+++ b/hmp.h
@@ -43,8 +43,8 @@ void hmp_system_powerdown(Monitor *mon, const QDict *qdict);
 void hmp_cpu(Monitor *mon, const QDict *qdict);
 void hmp_memsave(Monitor *mon, const QDict *qdict);
 void hmp_pmemsave(Monitor *mon, const QDict *qdict);
-void hmp_memchar_write(Monitor *mon, const QDict *qdict);
-void hmp_memchar_read(Monitor *mon, const QDict *qdict);
+void hmp_ringbuf_write(Monitor *mon, const QDict *qdict);
+void hmp_ringbuf_read(Monitor *mon, const QDict *qdict);
 void hmp_cont(Monitor *mon, const QDict *qdict);
 void hmp_system_wakeup(Monitor *mon, const QDict *qdict);
 void hmp_inject_nmi(Monitor *mon, const QDict *qdict);
diff --git a/qapi-schema.json b/qapi-schema.json
index 6f63791..736f881 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -329,9 +329,9 @@
 #
 # An enumeration of data format.
 #
-# @utf8: The data format is 'utf8'.
+# @utf8: Data is a UTF-8 string (RFC 3629)
 #
-# @base64: The data format is 'base64'.
+# @base64: Data is Base64 encoded binary (RFC 3548)
 #
 # Since: 1.4
 ##
@@ -339,44 +339,55 @@
   'data': [ 'utf8', 'base64' ] }
 
 ##
-# @memchar-write:
+# @ringbuf-write:
 #
-# Provide writing interface for memchardev. Write data to char
-# device 'memory'.
+# Write to a ring buffer character device.
 #
-# @device: the name of the memory char device.
+# @device: the ring buffer character device name
 #
-# @data: the source data write to memchar.
+# @data: data to write
 #
-# @format: #optional the format of the data write to chardev 'memory',
-#          by default is 'utf8'.
+# @format: #optional data encoding (default 'utf8').
+#          - base64: data must be base64 encoded text.  Its binary
+#            decoding gets written.
+#            Bug: invalid base64 is currently not rejected.
+#            Whitespace *is* invalid.
+#          - utf8: data's UTF-8 encoding is written
+#          - data itself is always Unicode regardless of format, like
+#            any other string.
 #
 # Returns: Nothing on success
 #
 # Since: 1.4
 ##
-{ 'command': 'memchar-write',
+{ 'command': 'ringbuf-write',
   'data': {'device': 'str', 'data': 'str',
            '*format': 'DataFormat'} }
 
 ##
-# @memchar-read:
+# @ringbuf-read:
 #
-# Provide read interface for memchardev. Read from the char
-# device 'memory' and return the data.
+# Read from a ring buffer character device.
 #
-# @device: the name of the memory char device.
+# @device: the ring buffer character device name
 #
-# @size: the size to read in bytes.
+# @size: how many bytes to read at most
 #
-# @format: #optional the format of the data want to read from
-#          memchardev, by default is 'utf8'.
+# @format: #optional data encoding (default 'utf8').
+#          - base64: the data read is returned in base64 encoding.
+#          - utf8: the data read is interpreted as UTF-8.
+#            Bug: can screw up when the buffer contains invalid UTF-8
+#            sequences, NUL characters, after the ring buffer lost
+#            data, and when reading stops because the size limit is
+#            reached.
+#          - The return value is always Unicode regardless of format,
+#            like any other string.
 #
 # Returns: data read from the device
 #
 # Since: 1.4
 ##
-{ 'command': 'memchar-read',
+{ 'command': 'ringbuf-read',
   'data': {'device': 'str', 'size': 'int', '*format': 'DataFormat'},
   'returns': 'str' }
 
diff --git a/qemu-char.c b/qemu-char.c
index 831d564..8a35403 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -2645,25 +2645,25 @@ size_t qemu_chr_mem_osize(const CharDriverState *chr)
 }
 
 /*********************************************************/
-/* CircularMemory chardev */
+/* Ring buffer chardev */
 
 typedef struct {
     size_t size;
     size_t prod;
     size_t cons;
     uint8_t *cbuf;
-} CirMemCharDriver;
+} RingBufCharDriver;
 
-static size_t cirmem_count(const CharDriverState *chr)
+static size_t ringbuf_count(const CharDriverState *chr)
 {
-    const CirMemCharDriver *d = chr->opaque;
+    const RingBufCharDriver *d = chr->opaque;
 
     return d->prod - d->cons;
 }
 
-static int cirmem_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
+static int ringbuf_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
 {
-    CirMemCharDriver *d = chr->opaque;
+    RingBufCharDriver *d = chr->opaque;
     int i;
 
     if (!buf || (len < 0)) {
@@ -2680,9 +2680,9 @@ static int cirmem_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
     return 0;
 }
 
-static int cirmem_chr_read(CharDriverState *chr, uint8_t *buf, int len)
+static int ringbuf_chr_read(CharDriverState *chr, uint8_t *buf, int len)
 {
-    CirMemCharDriver *d = chr->opaque;
+    RingBufCharDriver *d = chr->opaque;
     int i;
 
     for (i = 0; i < len && d->cons != d->prod; i++) {
@@ -2692,31 +2692,31 @@ static int cirmem_chr_read(CharDriverState *chr, uint8_t *buf, int len)
     return i;
 }
 
-static void cirmem_chr_close(struct CharDriverState *chr)
+static void ringbuf_chr_close(struct CharDriverState *chr)
 {
-    CirMemCharDriver *d = chr->opaque;
+    RingBufCharDriver *d = chr->opaque;
 
     g_free(d->cbuf);
     g_free(d);
     chr->opaque = NULL;
 }
 
-static CharDriverState *qemu_chr_open_cirmemchr(QemuOpts *opts)
+static CharDriverState *qemu_chr_open_ringbuf(QemuOpts *opts)
 {
     CharDriverState *chr;
-    CirMemCharDriver *d;
+    RingBufCharDriver *d;
 
     chr = g_malloc0(sizeof(CharDriverState));
     d = g_malloc(sizeof(*d));
 
-    d->size = qemu_opt_get_number(opts, "maxcapacity", 0);
+    d->size = qemu_opt_get_number(opts, "size", 0);
     if (d->size == 0) {
         d->size = CBUFF_SIZE;
     }
 
     /* The size must be power of 2 */
     if (d->size & (d->size - 1)) {
-        fprintf(stderr, "chardev: size of memory device must be power of 2\n");
+        error_report("size of ringbuf device must be power of two");
         goto fail;
     }
 
@@ -2725,8 +2725,8 @@ static CharDriverState *qemu_chr_open_cirmemchr(QemuOpts *opts)
     d->cbuf = g_malloc0(d->size);
 
     chr->opaque = d;
-    chr->chr_write = cirmem_chr_write;
-    chr->chr_close = cirmem_chr_close;
+    chr->chr_write = ringbuf_chr_write;
+    chr->chr_close = ringbuf_chr_close;
 
     return chr;
 
@@ -2736,12 +2736,12 @@ fail:
     return NULL;
 }
 
-static bool chr_is_cirmem(const CharDriverState *chr)
+static bool chr_is_ringbuf(const CharDriverState *chr)
 {
-    return chr->chr_write == cirmem_chr_write;
+    return chr->chr_write == ringbuf_chr_write;
 }
 
-void qmp_memchar_write(const char *device, const char *data,
+void qmp_ringbuf_write(const char *device, const char *data,
                        bool has_format, enum DataFormat format,
                        Error **errp)
 {
@@ -2756,8 +2756,8 @@ void qmp_memchar_write(const char *device, const char *data,
         return;
     }
 
-    if (!chr_is_cirmem(chr)) {
-        error_setg(errp,"%s is not memory char device", device);
+    if (!chr_is_ringbuf(chr)) {
+        error_setg(errp,"%s is not a ringbuf device", device);
         return;
     }
 
@@ -2768,7 +2768,7 @@ void qmp_memchar_write(const char *device, const char *data,
         write_count = strlen(data);
     }
 
-    ret = cirmem_chr_write(chr, write_data, write_count);
+    ret = ringbuf_chr_write(chr, write_data, write_count);
 
     if (write_data != (uint8_t *)data) {
         g_free((void *)write_data);
@@ -2780,7 +2780,7 @@ void qmp_memchar_write(const char *device, const char *data,
     }
 }
 
-char *qmp_memchar_read(const char *device, int64_t size,
+char *qmp_ringbuf_read(const char *device, int64_t size,
                        bool has_format, enum DataFormat format,
                        Error **errp)
 {
@@ -2795,8 +2795,8 @@ char *qmp_memchar_read(const char *device, int64_t size,
         return NULL;
     }
 
-    if (!chr_is_cirmem(chr)) {
-        error_setg(errp,"%s is not memory char device", device);
+    if (!chr_is_ringbuf(chr)) {
+        error_setg(errp,"%s is not a ringbuf device", device);
         return NULL;
     }
 
@@ -2805,16 +2805,23 @@ char *qmp_memchar_read(const char *device, int64_t size,
         return NULL;
     }
 
-    count = cirmem_count(chr);
+    count = ringbuf_count(chr);
     size = size > count ? count : size;
     read_data = g_malloc(size + 1);
 
-    cirmem_chr_read(chr, read_data, size);
+    ringbuf_chr_read(chr, read_data, size);
 
     if (has_format && (format == DATA_FORMAT_BASE64)) {
         data = g_base64_encode(read_data, size);
         g_free(read_data);
     } else {
+        /*
+         * FIXME should read only complete, valid UTF-8 characters up
+         * to @size bytes.  Invalid sequences should be replaced by a
+         * suitable replacement character.  Except when (and only
+         * when) ring buffer lost characters since last read, initial
+         * continuation characters should be dropped.
+         */
         read_data[size] = 0;
         data = (char *)read_data;
     }
@@ -2975,7 +2982,7 @@ static const struct {
     { .name = "udp",       .open = qemu_chr_open_udp },
     { .name = "msmouse",   .open = qemu_chr_open_msmouse },
     { .name = "vc",        .open = text_console_init },
-    { .name = "memory",    .open = qemu_chr_open_cirmemchr },
+    { .name = "memory",    .open = qemu_chr_open_ringbuf },
 #ifdef _WIN32
     { .name = "file",      .open = qemu_chr_open_win_file_out },
     { .name = "pipe",      .open = qemu_chr_open_win_pipe },
@@ -3236,7 +3243,7 @@ QemuOptsList qemu_chardev_opts = {
             .name = "debug",
             .type = QEMU_OPT_NUMBER,
         },{
-            .name = "maxcapacity",
+            .name = "size",
             .type = QEMU_OPT_NUMBER,
         },
         { /* end of list */ }
diff --git a/qemu-options.hx b/qemu-options.hx
index 2d44137..046bdc0 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -1736,7 +1736,7 @@ DEF("chardev", HAS_ARG, QEMU_OPTION_chardev,
     "-chardev msmouse,id=id[,mux=on|off]\n"
     "-chardev vc,id=id[[,width=width][,height=height]][[,cols=cols][,rows=rows]]\n"
     "         [,mux=on|off]\n"
-    "-chardev memory,id=id,maxcapacity=maxcapacity\n"
+    "-chardev ringbuf,id=id[,size=size]\n"
     "-chardev file,id=id,path=path[,mux=on|off]\n"
     "-chardev pipe,id=id,path=path[,mux=on|off]\n"
 #ifdef _WIN32
@@ -1778,7 +1778,7 @@ Backend is one of:
 @option{udp},
 @option{msmouse},
 @option{vc},
- at option{memory},
+ at option{ringbuf},
 @option{file},
 @option{pipe},
 @option{console},
@@ -1887,13 +1887,10 @@ the console, in pixels.
 @option{cols} and @option{rows} specify that the console be sized to fit a text
 console with the given dimensions.
 
- at item -chardev memory ,id=@var{id} ,maxcapacity=@var{maxcapacity}
+ at item -chardev ringbuf ,id=@var{id} [,size=@var{size}]
 
-Create a circular buffer with fixed size indicated by optionally @option{maxcapacity}
-which will be default 64K if it is not given.
-
- at option{maxcapacity} specifies the max capacity of the size of circular buffer
-to create. Should be power of 2.
+Create a ring buffer with fixed size @option{size}.
+ at var{size} must be a power of two, and defaults to @code{64K}).
 
 @item -chardev file ,id=@var{id} ,path=@var{path}
 
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 51ce2e6..799adea 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -466,30 +466,30 @@ Note: inject-nmi fails when the guest doesn't support injecting.
 EQMP
 
     {
-        .name       = "memchar-write",
+        .name       = "ringbuf-write",
         .args_type  = "device:s,data:s,format:s?",
-        .mhandler.cmd_new = qmp_marshal_input_memchar_write,
+        .mhandler.cmd_new = qmp_marshal_input_ringbuf_write,
     },
 
 SQMP
-memchar-write
+ringbuf-write
 -------------
 
-Provide writing interface for CirMemCharDriver. Write data to memory
-char device.
+Write to a ring buffer character device.
 
 Arguments:
 
-- "device": the name of the char device, must be unique (json-string)
-- "data": the source data write to memory (json-string)
-- "format": the data format write to memory, default is
-            utf8. (json-string, optional)
-          - Possible values: "utf8", "base64"
+- "device": ring buffer character device name (json-string)
+- "data": data to write (json-string)
+- "format": data format (json-string, optional)
+          - Possible values: "utf8" (default), "base64"
+            Bug: invalid base64 is currently not rejected.
+            Whitespace *is* invalid.
 
 Example:
 
--> { "execute": "memchar-write",
-                "arguments": { "device": foo,
+-> { "execute": "ringbuf-write",
+                "arguments": { "device": "foo",
                                "data": "abcdefgh",
                                "format": "utf8" } }
 <- { "return": {} }
@@ -497,32 +497,35 @@ Example:
 EQMP
 
     {
-        .name       = "memchar-read",
+        .name       = "ringbuf-read",
         .args_type  = "device:s,size:i,format:s?",
-        .mhandler.cmd_new = qmp_marshal_input_memchar_read,
+        .mhandler.cmd_new = qmp_marshal_input_ringbuf_read,
     },
 
 SQMP
-memchar-read
+ringbuf-read
 -------------
 
-Provide read interface for CirMemCharDriver. Read from the char
-device memory and return the data with size.
+Read from a ring buffer character device.
 
 Arguments:
 
-- "device": the name of the char device, must be unique (json-string)
-- "size": the memory size wanted to read in bytes (refer to unencoded
-          size of the raw data), would adjust to the init size of the
-          memchar if the requested size is larger than it. (json-int)
-- "format": the data format write to memchardev, default is
-            utf8. (json-string, optional)
-          - Possible values: "utf8", "base64"
+- "device": ring buffer character device name (json-string)
+- "size": how many bytes to read at most (json-int)
+          - Number of data bytes, not number of characters in encoded data
+- "format": data format (json-string, optional)
+          - Possible values: "utf8" (default), "base64"
+          - Naturally, format "utf8" works only when the ring buffer
+            contains valid UTF-8 text.  Invalid UTF-8 sequences get
+            replaced.  Bug: replacement doesn't work.  Bug: can screw
+            up on encountering NUL characters, after the ring buffer
+            lost data, and when reading stops because the size limit
+            is reached.
 
 Example:
 
--> { "execute": "memchar-read",
-                "arguments": { "device": foo,
+-> { "execute": "ringbuf-read",
+                "arguments": { "device": "foo",
                                "size": 1000,
                                "format": "utf8" } }
 <- {"return": "abcdefgh"}
commit 5c230105cdea8ac9338bd5b4485c6ae80ec1fa18
Author: Markus Armbruster <armbru at redhat.com>
Date:   Wed Feb 6 21:27:23 2013 +0100

    qemu-char: General chardev "memory" code cleanup
    
    Inline trivial cirmem_chr_is_empty() into its only caller.
    
    Rename qemu_chr_cirmem_count() to cirmem_count().
    
    Fast ring buffer index wraparound.  Without this, there's no point in
    restricting size to a power two.
    
    qemu_is_chr(chr, "memory") returns *zero* when chr is a memory
    character device, which isn't what I'd expect.  Replace it by the
    saner and more obviously correct chr_is_cirmem().  Also avoids
    encouraging testing for specific character devices elsewhere.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-char.c b/qemu-char.c
index cdbbafe..831d564 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -2645,7 +2645,7 @@ size_t qemu_chr_mem_osize(const CharDriverState *chr)
 }
 
 /*********************************************************/
-/*CircularMemory chardev*/
+/* CircularMemory chardev */
 
 typedef struct {
     size_t size;
@@ -2654,18 +2654,11 @@ typedef struct {
     uint8_t *cbuf;
 } CirMemCharDriver;
 
-static bool cirmem_chr_is_empty(const CharDriverState *chr)
+static size_t cirmem_count(const CharDriverState *chr)
 {
     const CirMemCharDriver *d = chr->opaque;
 
-    return d->cons == d->prod;
-}
-
-static size_t qemu_chr_cirmem_count(const CharDriverState *chr)
-{
-    const CirMemCharDriver *d = chr->opaque;
-
-    return (d->prod - d->cons);
+    return d->prod - d->cons;
 }
 
 static int cirmem_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
@@ -2678,8 +2671,8 @@ static int cirmem_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
     }
 
     for (i = 0; i < len; i++ ) {
-        d->cbuf[d->prod++ % d->size] = buf[i];
-        if ((d->prod - d->cons) > d->size) {
+        d->cbuf[d->prod++ & (d->size - 1)] = buf[i];
+        if (d->prod - d->cons > d->size) {
             d->cons = d->prod - d->size;
         }
     }
@@ -2692,8 +2685,8 @@ static int cirmem_chr_read(CharDriverState *chr, uint8_t *buf, int len)
     CirMemCharDriver *d = chr->opaque;
     int i;
 
-    for (i = 0; i < len && !cirmem_chr_is_empty(chr); i++) {
-        buf[i] = d->cbuf[d->cons++ % d->size];
+    for (i = 0; i < len && d->cons != d->prod; i++) {
+        buf[i] = d->cbuf[d->cons++ & (d->size - 1)];
     }
 
     return i;
@@ -2743,9 +2736,9 @@ fail:
     return NULL;
 }
 
-static bool qemu_is_chr(const CharDriverState *chr, const char *filename)
+static bool chr_is_cirmem(const CharDriverState *chr)
 {
-    return strcmp(chr->filename, filename);
+    return chr->chr_write == cirmem_chr_write;
 }
 
 void qmp_memchar_write(const char *device, const char *data,
@@ -2763,7 +2756,7 @@ void qmp_memchar_write(const char *device, const char *data,
         return;
     }
 
-    if (qemu_is_chr(chr, "memory")) {
+    if (!chr_is_cirmem(chr)) {
         error_setg(errp,"%s is not memory char device", device);
         return;
     }
@@ -2802,7 +2795,7 @@ char *qmp_memchar_read(const char *device, int64_t size,
         return NULL;
     }
 
-    if (qemu_is_chr(chr, "memory")) {
+    if (!chr_is_cirmem(chr)) {
         error_setg(errp,"%s is not memory char device", device);
         return NULL;
     }
@@ -2812,7 +2805,7 @@ char *qmp_memchar_read(const char *device, int64_t size,
         return NULL;
     }
 
-    count = qemu_chr_cirmem_count(chr);
+    count = cirmem_count(chr);
     size = size > count ? count : size;
     read_data = g_malloc(size + 1);
 
commit 6fd5b66950fc5551d371ba5017d0e0858b7c800b
Author: Markus Armbruster <armbru at redhat.com>
Date:   Wed Feb 6 21:27:22 2013 +0100

    qemu-char: Drop undocumented chardev "memory" compatibility syntax
    
    This is a new device, so there's no compatibility to maintain, and its
    use case isn't common enough to justify shorthand syntax.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-char.c b/qemu-char.c
index 2f59a61..cdbbafe 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -2883,11 +2883,6 @@ QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename)
         qemu_opt_set(opts, "path", filename);
         return opts;
     }
-    if (strstart(filename, "memory", &p)) {
-        qemu_opt_set(opts, "backend", "memory");
-        qemu_opt_set(opts, "maxcapacity", p);
-        return opts;
-    }
     if (strstart(filename, "file:", &p)) {
         qemu_opt_set(opts, "backend", "file");
         qemu_opt_set(opts, "path", p);
commit 094c8c2c67c486bcbc03c5e6327edc6ad3e5e29a
Author: Markus Armbruster <armbru at redhat.com>
Date:   Wed Feb 6 21:27:21 2013 +0100

    qemu-char: Fix chardev "memory" not to drop IAC characters
    
    Undocumented misfeature, get rid of it while we can.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-char.c b/qemu-char.c
index b0e4b41..2f59a61 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -2678,11 +2678,6 @@ static int cirmem_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
     }
 
     for (i = 0; i < len; i++ ) {
-        /* Avoid writing the IAC information to the queue. */
-        if ((unsigned char)buf[i] == IAC) {
-            continue;
-        }
-
         d->cbuf[d->prod++ % d->size] = buf[i];
         if ((d->prod - d->cons) > d->size) {
             d->cons = d->prod - d->size;
commit 44f3bcd2c7991cc9d096e51e38864135543ea1ce
Author: Markus Armbruster <armbru at redhat.com>
Date:   Wed Feb 6 21:27:20 2013 +0100

    qmp: Drop wasteful zero-initialization in qmp_memchar_read()
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-char.c b/qemu-char.c
index 9d1c02c..b0e4b41 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -2819,7 +2819,7 @@ char *qmp_memchar_read(const char *device, int64_t size,
 
     count = qemu_chr_cirmem_count(chr);
     size = size > count ? count : size;
-    read_data = g_malloc0(size + 1);
+    read_data = g_malloc(size + 1);
 
     cirmem_chr_read(chr, read_data, size);
 
@@ -2827,6 +2827,7 @@ char *qmp_memchar_read(const char *device, int64_t size,
         data = g_base64_encode(read_data, size);
         g_free(read_data);
     } else {
+        read_data[size] = 0;
         data = (char *)read_data;
     }
 
commit c287e99fe47b179e6ef6b212139821b4d78934c1
Author: Markus Armbruster <armbru at redhat.com>
Date:   Wed Feb 6 21:27:19 2013 +0100

    qmp: Drop superfluous special case "empty" in qmp_memchar_read()
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-char.c b/qemu-char.c
index 4dd01e6..9d1c02c 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -2818,10 +2818,6 @@ char *qmp_memchar_read(const char *device, int64_t size,
     }
 
     count = qemu_chr_cirmem_count(chr);
-    if (count == 0) {
-        return g_strdup("");
-    }
-
     size = size > count ? count : size;
     read_data = g_malloc0(size + 1);
 
commit 13289fb5a716e06fb06febb880e5e116d485f82b
Author: Markus Armbruster <armbru at redhat.com>
Date:   Wed Feb 6 21:27:18 2013 +0100

    qmp: Plug memory leaks in memchar-write, memchar-read
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-char.c b/qemu-char.c
index b1c6132..4dd01e6 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -2782,6 +2782,10 @@ void qmp_memchar_write(const char *device, const char *data,
 
     ret = cirmem_chr_write(chr, write_data, write_count);
 
+    if (write_data != (uint8_t *)data) {
+        g_free((void *)write_data);
+    }
+
     if (ret < 0) {
         error_setg(errp, "Failed to write to device %s", device);
         return;
@@ -2825,6 +2829,7 @@ char *qmp_memchar_read(const char *device, int64_t size,
 
     if (has_format && (format == DATA_FORMAT_BASE64)) {
         data = g_base64_encode(read_data, size);
+        g_free(read_data);
     } else {
         data = (char *)read_data;
     }
commit c4f331b6b3b5fe260128f316ee9f01997f7c428d
Author: Markus Armbruster <armbru at redhat.com>
Date:   Wed Feb 6 21:27:17 2013 +0100

    qmp: Clean up type usage in qmp_memchar_write(), qmp_memchar_read()
    
    Const-correctness, consistently use standard C types instead of mixing
    them with GLib types.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-char.c b/qemu-char.c
index 2bdd1bb..b1c6132 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -2758,9 +2758,9 @@ void qmp_memchar_write(const char *device, const char *data,
                        Error **errp)
 {
     CharDriverState *chr;
-    guchar *write_data;
+    const uint8_t *write_data;
     int ret;
-    gsize write_count;
+    size_t write_count;
 
     chr = qemu_chr_find(device);
     if (!chr) {
@@ -2793,7 +2793,7 @@ char *qmp_memchar_read(const char *device, int64_t size,
                        Error **errp)
 {
     CharDriverState *chr;
-    guchar *read_data;
+    uint8_t *read_data;
     size_t count;
     char *data;
 
commit 1a69278e53a0e5060c8c6cc825449a122634ce3b
Author: Markus Armbruster <armbru at redhat.com>
Date:   Wed Feb 6 21:27:16 2013 +0100

    qmp: Use generic errors in memchar-read, memchar-write
    
    New errors should be generic unless there's a real use case for rich
    errors.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qapi-schema.json b/qapi-schema.json
index d8fa1c3..6f63791 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -352,7 +352,6 @@
 #          by default is 'utf8'.
 #
 # Returns: Nothing on success
-#          If @device is not a valid char device, DeviceNotFound
 #
 # Since: 1.4
 ##
@@ -374,7 +373,6 @@
 #          memchardev, by default is 'utf8'.
 #
 # Returns: data read from the device
-#          If @device is not a valid memchr device, DeviceNotFound
 #
 # Since: 1.4
 ##
diff --git a/qemu-char.c b/qemu-char.c
index b593c50..2bdd1bb 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -2764,7 +2764,7 @@ void qmp_memchar_write(const char *device, const char *data,
 
     chr = qemu_chr_find(device);
     if (!chr) {
-        error_set(errp, QERR_DEVICE_NOT_FOUND, device);
+        error_setg(errp, "Device '%s' not found", device);
         return;
     }
 
@@ -2799,7 +2799,7 @@ char *qmp_memchar_read(const char *device, int64_t size,
 
     chr = qemu_chr_find(device);
     if (!chr) {
-        error_set(errp, QERR_DEVICE_NOT_FOUND, device);
+        error_setg(errp, "Device '%s' not found", device);
         return NULL;
     }
 
commit 3ab651fc819178cf6a518af5860cc49f42cff455
Author: Markus Armbruster <armbru at redhat.com>
Date:   Wed Feb 6 21:27:15 2013 +0100

    qmp: Clean up design of memchar-read
    
    The data returned has a well-defined size, which makes the size
    returned along with it redundant at best.  Drop it.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hmp.c b/hmp.c
index 9fdf1ce..f6bb767 100644
--- a/hmp.c
+++ b/hmp.c
@@ -677,21 +677,18 @@ void hmp_memchar_read(Monitor *mon, const QDict *qdict)
 {
     uint32_t size = qdict_get_int(qdict, "size");
     const char *chardev = qdict_get_str(qdict, "device");
-    MemCharRead *meminfo;
+    char *data;
     Error *errp = NULL;
 
-    meminfo = qmp_memchar_read(chardev, size, false, 0, &errp);
+    data = qmp_memchar_read(chardev, size, false, 0, &errp);
     if (errp) {
         monitor_printf(mon, "%s\n", error_get_pretty(errp));
         error_free(errp);
         return;
     }
 
-    if (meminfo->count > 0) {
-        monitor_printf(mon, "%s\n", meminfo->data);
-    }
-
-    qapi_free_MemCharRead(meminfo);
+    monitor_printf(mon, "%s\n", data);
+    g_free(data);
 }
 
 static void hmp_cont_cb(void *opaque, int err)
diff --git a/qapi-schema.json b/qapi-schema.json
index 9e2cbbd..d8fa1c3 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -361,20 +361,6 @@
            '*format': 'DataFormat'} }
 
 ##
-# @MemCharRead
-#
-# Result of QMP command memchar-read.
-#
-# @data: The data read from memchar as string.
-#
-# @count: The numbers of bytes read from.
-#
-# Since: 1.4
-##
-{ 'type': 'MemCharRead',
-  'data': { 'data': 'str', 'count': 'int' } }
-
-##
 # @memchar-read:
 #
 # Provide read interface for memchardev. Read from the char
@@ -387,14 +373,14 @@
 # @format: #optional the format of the data want to read from
 #          memchardev, by default is 'utf8'.
 #
-# Returns: @MemCharRead
+# Returns: data read from the device
 #          If @device is not a valid memchr device, DeviceNotFound
 #
 # Since: 1.4
 ##
 { 'command': 'memchar-read',
   'data': {'device': 'str', 'size': 'int', '*format': 'DataFormat'},
-  'returns': 'MemCharRead' }
+  'returns': 'str' }
 
 ##
 # @CommandInfo:
diff --git a/qemu-char.c b/qemu-char.c
index 9c1dd13..b593c50 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -2788,14 +2788,14 @@ void qmp_memchar_write(const char *device, const char *data,
     }
 }
 
-MemCharRead *qmp_memchar_read(const char *device, int64_t size,
-                              bool has_format, enum DataFormat format,
-                              Error **errp)
+char *qmp_memchar_read(const char *device, int64_t size,
+                       bool has_format, enum DataFormat format,
+                       Error **errp)
 {
     CharDriverState *chr;
     guchar *read_data;
-    MemCharRead *meminfo;
     size_t count;
+    char *data;
 
     chr = qemu_chr_find(device);
     if (!chr) {
@@ -2813,26 +2813,23 @@ MemCharRead *qmp_memchar_read(const char *device, int64_t size,
         return NULL;
     }
 
-    meminfo = g_malloc0(sizeof(MemCharRead));
-
     count = qemu_chr_cirmem_count(chr);
     if (count == 0) {
-        meminfo->data = g_strdup("");
-        return meminfo;
+        return g_strdup("");
     }
 
     size = size > count ? count : size;
     read_data = g_malloc0(size + 1);
 
-    meminfo->count = cirmem_chr_read(chr, read_data, size);
+    cirmem_chr_read(chr, read_data, size);
 
     if (has_format && (format == DATA_FORMAT_BASE64)) {
-        meminfo->data = g_base64_encode(read_data, (size_t)meminfo->count);
+        data = g_base64_encode(read_data, size);
     } else {
-        meminfo->data = (char *)read_data;
+        data = (char *)read_data;
     }
 
-    return meminfo;
+    return data;
 }
 
 QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename)
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 8468f10..51ce2e6 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -525,7 +525,7 @@ Example:
                 "arguments": { "device": foo,
                                "size": 1000,
                                "format": "utf8" } }
-<- { "return": { "data": "data string...", "count": 1000 } }
+<- {"return": "abcdefgh"}
 
 EQMP
 
commit 82e59a676c01b3df3b53998d428d0a64a55f2439
Author: Markus Armbruster <armbru at redhat.com>
Date:   Wed Feb 6 21:27:14 2013 +0100

    qmp: Fix design bug and read beyond buffer in memchar-write
    
    Command memchar-write takes data and size parameter.  Begs the
    question what happens when data doesn't match size.
    
    With format base64, qmp_memchar_write() copies the full data argument,
    regardless of size argument.
    
    With format utf8, qmp_memchar_write() copies size bytes from data,
    happily reading beyond data.  Copies crap from the heap or even
    crashes.
    
    Drop the size parameter, and always copy the full data argument.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hmp.c b/hmp.c
index 1689e6f..9fdf1ce 100644
--- a/hmp.c
+++ b/hmp.c
@@ -664,13 +664,11 @@ void hmp_pmemsave(Monitor *mon, const QDict *qdict)
 
 void hmp_memchar_write(Monitor *mon, const QDict *qdict)
 {
-    uint32_t size;
     const char *chardev = qdict_get_str(qdict, "device");
     const char *data = qdict_get_str(qdict, "data");
     Error *errp = NULL;
 
-    size = strlen(data);
-    qmp_memchar_write(chardev, size, data, false, 0, &errp);
+    qmp_memchar_write(chardev, data, false, 0, &errp);
 
     hmp_handle_error(mon, &errp);
 }
diff --git a/qapi-schema.json b/qapi-schema.json
index cdd8384..9e2cbbd 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -346,8 +346,6 @@
 #
 # @device: the name of the memory char device.
 #
-# @size: the size to write in bytes.
-#
 # @data: the source data write to memchar.
 #
 # @format: #optional the format of the data write to chardev 'memory',
@@ -359,7 +357,7 @@
 # Since: 1.4
 ##
 { 'command': 'memchar-write',
-  'data': {'device': 'str', 'size': 'int', 'data': 'str',
+  'data': {'device': 'str', 'data': 'str',
            '*format': 'DataFormat'} }
 
 ##
diff --git a/qemu-char.c b/qemu-char.c
index ac5d62d..9c1dd13 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -2753,9 +2753,8 @@ static bool qemu_is_chr(const CharDriverState *chr, const char *filename)
     return strcmp(chr->filename, filename);
 }
 
-void qmp_memchar_write(const char *device, int64_t size,
-                       const char *data, bool has_format,
-                       enum DataFormat format,
+void qmp_memchar_write(const char *device, const char *data,
+                       bool has_format, enum DataFormat format,
                        Error **errp)
 {
     CharDriverState *chr;
@@ -2774,12 +2773,11 @@ void qmp_memchar_write(const char *device, int64_t size,
         return;
     }
 
-    write_count = (gsize)size;
-
     if (has_format && (format == DATA_FORMAT_BASE64)) {
         write_data = g_base64_decode(data, &write_count);
     } else {
         write_data = (uint8_t *)data;
+        write_count = strlen(data);
     }
 
     ret = cirmem_chr_write(chr, write_data, write_count);
diff --git a/qmp-commands.hx b/qmp-commands.hx
index bbb21f3..8468f10 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -467,7 +467,7 @@ EQMP
 
     {
         .name       = "memchar-write",
-        .args_type  = "device:s,size:i,data:s,format:s?",
+        .args_type  = "device:s,data:s,format:s?",
         .mhandler.cmd_new = qmp_marshal_input_memchar_write,
     },
 
@@ -481,7 +481,6 @@ char device.
 Arguments:
 
 - "device": the name of the char device, must be unique (json-string)
-- "size": the memory size, in bytes, should be power of 2 (json-int)
 - "data": the source data write to memory (json-string)
 - "format": the data format write to memory, default is
             utf8. (json-string, optional)
@@ -491,7 +490,6 @@ Example:
 
 -> { "execute": "memchar-write",
                 "arguments": { "device": foo,
-                               "size": 8,
                                "data": "abcdefgh",
                                "format": "utf8" } }
 <- { "return": {} }
commit 2a0e1ad66e4177dddc6c8fb7aeadc095aafac828
Author: Michael Tokarev <mjt at tls.msk.ru>
Date:   Mon Feb 4 00:36:25 2013 +0400

    vnc: recognize Hungarian doubleacutes
    
    As reported in http://bugs.debian.org/697641 , some Hungarian keys
    does not work with qemu when using vnc display.
    
    This is because while the Hungarian keymap mentions these symbols,
    qemu know nothing about them.  So add them.
    
    This patch is applicable to -stable for all previous releases.
    
    Signed-off-by: Michael Tokarev <mjt at tls.msk.ru>
    Reviewed-by: Laszlo Ersek <lersek at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/ui/vnc_keysym.h b/ui/vnc_keysym.h
index df33cfe..6250bec 100644
--- a/ui/vnc_keysym.h
+++ b/ui/vnc_keysym.h
@@ -215,10 +215,14 @@ static const name2keysym_t name2keysym[]={
 { "Zabovedot",            0x1af},
 { "zacute",               0x1bc},
 { "Zacute",               0x1ac},
+{ "Odoubleacute",         0x1d5},
+{ "Udoubleacute",         0x1db},
 { "cacute",               0x1e6},
 { "Cacute",               0x1c6},
 { "nacute",               0x1f1},
 { "Nacute",               0x1d1},
+{ "odoubleacute",         0x1f5},
+{ "udoubleacute",         0x1fb},
 
     /* modifiers */
 {"ISO_Level3_Shift", 0xfe03}, /* XK_ISO_Level3_Shift */
commit f38f7a847e316def8606d25441878d723de84b65
Author: Stefan Weil <sw at weilnetz.de>
Date:   Tue Feb 5 13:12:43 2013 +0100

    target-m68k: Fix comment
    
    * spelling fix ito -> into
    * reorder to match load/store
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index e763195..3f1478c 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -574,7 +574,7 @@ static inline TCGv gen_ea_once(CPUM68KState *env, DisasContext *s,
     return gen_ldst(s, opsize, tmp, val, what);
 }
 
-/* Generate code to load/store a value ito/from an EA.  If VAL > 0 this is
+/* Generate code to load/store a value from/into an EA.  If VAL > 0 this is
    a write otherwise it is a read (0 == sign extend, -1 == zero extend).
    ADDRP is non-null for readwrite operands.  */
 static TCGv gen_ea(CPUM68KState *env, DisasContext *s, uint16_t insn,
commit 15af6321f4d1f90d0ae1b5cb05093c48b41c4533
Author: Michael Tokarev <mjt at tls.msk.ru>
Date:   Mon Feb 4 00:36:25 2013 +0400

    vnc: recognize Hungarian doubleacutes
    
    As reported in http://bugs.debian.org/697641 , some Hungarian keys
    does not work with qemu when using vnc display.
    
    This is because while the Hungarian keymap mentions these symbols,
    qemu know nothing about them.  So add them.
    
    This patch is applicable to -stable for all previous releases.
    
    Signed-off-by: Michael Tokarev <mjt at tls.msk.ru>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/ui/vnc_keysym.h b/ui/vnc_keysym.h
index df33cfe..6250bec 100644
--- a/ui/vnc_keysym.h
+++ b/ui/vnc_keysym.h
@@ -215,10 +215,14 @@ static const name2keysym_t name2keysym[]={
 { "Zabovedot",            0x1af},
 { "zacute",               0x1bc},
 { "Zacute",               0x1ac},
+{ "Odoubleacute",         0x1d5},
+{ "Udoubleacute",         0x1db},
 { "cacute",               0x1e6},
 { "Cacute",               0x1c6},
 { "nacute",               0x1f1},
 { "Nacute",               0x1d1},
+{ "odoubleacute",         0x1f5},
+{ "udoubleacute",         0x1fb},
 
     /* modifiers */
 {"ISO_Level3_Shift", 0xfe03}, /* XK_ISO_Level3_Shift */
commit a911a182a6bfd3b0257b13f862b0d4fbd9392715
Author: Aneesh Kumar K.V <aneesh.kumar at linux.vnet.ibm.com>
Date:   Tue Feb 5 11:27:46 2013 +0530

    qemu/9p: Don't ignore error in fid clunk
    
    We use the clunk request to do the actual xattr operation. So don't
    ignore the error value for fid clunk.
    
    Security model "none" don't support posix acl. Without this patch
    guest won't get EOPNOTSUPP error on setxattr("system.posix_acl_access")
    
    Signed-off-by: Aneesh Kumar K.V <aneesh.kumar at linux.vnet.ibm.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c
index b795839..d3ea820 100644
--- a/hw/9pfs/virtio-9p.c
+++ b/hw/9pfs/virtio-9p.c
@@ -327,7 +327,7 @@ static int free_fid(V9fsPDU *pdu, V9fsFidState *fidp)
     return retval;
 }
 
-static void put_fid(V9fsPDU *pdu, V9fsFidState *fidp)
+static int put_fid(V9fsPDU *pdu, V9fsFidState *fidp)
 {
     BUG_ON(!fidp->ref);
     fidp->ref--;
@@ -348,8 +348,9 @@ static void put_fid(V9fsPDU *pdu, V9fsFidState *fidp)
                 pdu->s->migration_blocker = NULL;
             }
         }
-        free_fid(pdu, fidp);
+        return free_fid(pdu, fidp);
     }
+    return 0;
 }
 
 static V9fsFidState *clunk_fid(V9fsState *s, int32_t fid)
@@ -1537,9 +1538,10 @@ static void v9fs_clunk(void *opaque)
      * free the fid.
      */
     fidp->ref++;
-    err = offset;
-
-    put_fid(pdu, fidp);
+    err = put_fid(pdu, fidp);
+    if (!err) {
+        err = offset;
+    }
 out_nofid:
     complete_pdu(s, pdu, err);
 }
commit facf98ad987a38d97e12511f81375380b407a828
Author: Aneesh Kumar K.V <aneesh.kumar at linux.vnet.ibm.com>
Date:   Tue Feb 5 11:27:45 2013 +0530

    qemu/iovec: Don't assert if sbytes is zero
    
    Since these values can possibly be sent from guest (for hw/9pfs), do a sanity check
    on them. A 9p write request with 0 bytes caused qemu to abort without this patch
    
    Signed-off-by: Aneesh Kumar K.V <aneesh.kumar at linux.vnet.ibm.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/util/iov.c b/util/iov.c
index c0f5c56..fbe675d 100644
--- a/util/iov.c
+++ b/util/iov.c
@@ -304,6 +304,10 @@ void qemu_iovec_concat_iov(QEMUIOVector *dst,
 {
     int i;
     size_t done;
+
+    if (!sbytes) {
+        return;
+    }
     assert(dst->nalloc != -1);
     for (i = 0, done = 0; done < sbytes && i < src_cnt; i++) {
         if (soffset < src_iov[i].iov_len) {
commit ddcb73b7782cb6104479503faea04cc224f982b5
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Tue Feb 5 21:00:21 2013 +0200

    e1000: fix link down handling with auto negotiation
    
    Fixes a couple of regression bugs introduced by
    b9d03e352cb6b31a66545763f6a1e20c9abf0c2c and related to
    auto-negotiation:
    -   Auto-negotiation currently sets link up even if it was
        forced down from the monitor.
    -   If Auto-negotiation was in progress during migration,
        link will never come up.
    
    As a fix, don't touch NC link_down field at all,
    instead add code on receive path to check
    guest link status.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/e1000.c b/hw/e1000.c
index bb150c6..d6fe815 100644
--- a/hw/e1000.c
+++ b/hw/e1000.c
@@ -166,7 +166,6 @@ static void
 set_phy_ctrl(E1000State *s, int index, uint16_t val)
 {
     if ((val & MII_CR_AUTO_NEG_EN) && (val & MII_CR_RESTART_AUTO_NEG)) {
-        qemu_get_queue(s->nic)->link_down = true;
         e1000_link_down(s);
         s->phy_reg[PHY_STATUS] &= ~MII_SR_AUTONEG_COMPLETE;
         DBGOUT(PHY, "Start link auto negotiation\n");
@@ -178,8 +177,9 @@ static void
 e1000_autoneg_timer(void *opaque)
 {
     E1000State *s = opaque;
-    qemu_get_queue(s->nic)->link_down = false;
-    e1000_link_up(s);
+    if (!qemu_get_queue(s->nic)->link_down) {
+        e1000_link_up(s);
+    }
     s->phy_reg[PHY_STATUS] |= MII_SR_AUTONEG_COMPLETE;
     DBGOUT(PHY, "Auto negotiation is completed\n");
 }
@@ -784,7 +784,8 @@ e1000_can_receive(NetClientState *nc)
 {
     E1000State *s = qemu_get_nic_opaque(nc);
 
-    return (s->mac_reg[RCTL] & E1000_RCTL_EN) && e1000_has_rxbufs(s, 1);
+    return (s->mac_reg[STATUS] & E1000_STATUS_LU) &&
+        (s->mac_reg[RCTL] & E1000_RCTL_EN) && e1000_has_rxbufs(s, 1);
 }
 
 static uint64_t rx_desc_base(E1000State *s)
@@ -810,8 +811,13 @@ e1000_receive(NetClientState *nc, const uint8_t *buf, size_t size)
     size_t desc_size;
     size_t total_size;
 
-    if (!(s->mac_reg[RCTL] & E1000_RCTL_EN))
+    if (!(s->mac_reg[STATUS] & E1000_STATUS_LU)) {
+        return -1;
+    }
+
+    if (!(s->mac_reg[RCTL] & E1000_RCTL_EN)) {
         return -1;
+    }
 
     /* Pad to minimum Ethernet frame length */
     if (size < sizeof(min_buf)) {
@@ -1110,14 +1116,37 @@ static bool is_version_1(void *opaque, int version_id)
     return version_id == 1;
 }
 
+static void e1000_pre_save(void *opaque)
+{
+    E1000State *s = opaque;
+    NetClientState *nc = qemu_get_queue(s->nic);
+    /*
+     * If link is down and auto-negotiation is ongoing, complete
+     * auto-negotiation immediately.  This allows is to look at
+     * MII_SR_AUTONEG_COMPLETE to infer link status on load.
+     */
+    if (nc->link_down &&
+        s->phy_reg[PHY_CTRL] & MII_CR_AUTO_NEG_EN &&
+        s->phy_reg[PHY_CTRL] & MII_CR_RESTART_AUTO_NEG) {
+         s->phy_reg[PHY_STATUS] |= MII_SR_AUTONEG_COMPLETE;
+    }
+}
+
 static int e1000_post_load(void *opaque, int version_id)
 {
     E1000State *s = opaque;
     NetClientState *nc = qemu_get_queue(s->nic);
 
     /* nc.link_down can't be migrated, so infer link_down according
-     * to link status bit in mac_reg[STATUS] */
+     * to link status bit in mac_reg[STATUS].
+     * Alternatively, restart link negotiation if it was in progress. */
     nc->link_down = (s->mac_reg[STATUS] & E1000_STATUS_LU) == 0;
+    if (s->phy_reg[PHY_CTRL] & MII_CR_AUTO_NEG_EN &&
+        s->phy_reg[PHY_CTRL] & MII_CR_RESTART_AUTO_NEG &&
+        !(s->phy_reg[PHY_STATUS] & MII_SR_AUTONEG_COMPLETE)) {
+        nc->link_down = false;
+        qemu_mod_timer(s->autoneg_timer, qemu_get_clock_ms(vm_clock) + 500);
+    }
 
     return 0;
 }
@@ -1127,6 +1156,7 @@ static const VMStateDescription vmstate_e1000 = {
     .version_id = 2,
     .minimum_version_id = 1,
     .minimum_version_id_old = 1,
+    .pre_save = e1000_pre_save,
     .post_load = e1000_post_load,
     .fields      = (VMStateField []) {
         VMSTATE_PCI_DEVICE(dev, E1000State),
commit 84208085d357d95b84f6e281ec3aa028e988e5ff
Author: Richard Henderson <rth at twiddle.net>
Date:   Mon Feb 4 16:21:07 2013 -0800

    configure: Fix build with XFree
    
    The build is broken on ppc64-linux, possibly only with new binutils:
    
    ld: hw/lm32/../milkymist-tmu2.o: undefined reference to symbol 'XFree'
    ld: note: 'XFree' is defined in DSO /lib64/libX11.so.6 so try \
      adding it to the linker command line
    
    So let's follow the linker's advice.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/configure b/configure
index 0657b1a..8789324 100755
--- a/configure
+++ b/configure
@@ -2388,7 +2388,7 @@ fi
 ##########################################
 # opengl probe, used by milkymist-tmu2
 if test "$opengl" != "no" ; then
-  opengl_libs="-lGL"
+  opengl_libs="-lGL -lX11"
   cat > $TMPC << EOF
 #include <X11/Xlib.h>
 #include <GL/gl.h>
commit 91107fdf4443d2171e06840e87277bb7a047343b
Author: Richard Henderson <rth at twiddle.net>
Date:   Mon Feb 4 16:21:06 2013 -0800

    bswap: Fix width of swap in leul_to_cpu
    
    The misnamed HOST_LONG_BITS is really HOST_POINTER_BITS.  Here we're
    explicitly using an unsigned long, rather than uintptr_t, so it is
    more correct to select the swap size via ULONG_MAX.
    
    Acked-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/include/qemu/bswap.h b/include/qemu/bswap.h
index e6d4798..d3af35d 100644
--- a/include/qemu/bswap.h
+++ b/include/qemu/bswap.h
@@ -2,8 +2,8 @@
 #define BSWAP_H
 
 #include "config-host.h"
-
 #include <inttypes.h>
+#include <limits.h>
 #include "fpu/softfloat.h"
 
 #ifdef CONFIG_MACHINE_BSWAP_H
@@ -458,7 +458,15 @@ static inline void cpu_to_32wu(uint32_t *p, uint32_t v)
 
 static inline unsigned long leul_to_cpu(unsigned long v)
 {
-    return le_bswap(v, HOST_LONG_BITS);
+    /* In order to break an include loop between here and
+       qemu-common.h, don't rely on HOST_LONG_BITS.  */
+#if ULONG_MAX == UINT32_MAX
+    return le_bswap(v, 32);
+#elif ULONG_MAX == UINT64_MAX
+    return le_bswap(v, 64);
+#else
+# error Unknown sizeof long
+#endif
 }
 
 #undef le_bswap
commit 5f876756c57c15f5e14d4136fc432b74f05f082b
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Wed Feb 6 05:12:06 2013 -0600

    bios: recompile BIOS
    
    SeaBIOS is really close to spilling over to 256k.  Until we can better
    handle migration across RAM block size changes, recompile SeaBIOS with
    a compiler that causes the binary to still fit in 128k.
    
    This was built with:
    
    gcc version 4.7.2 20121109 (Red Hat 4.7.2-8) (GCC)
    
    On 64-bit Fedora 18.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/pc-bios/bios.bin b/pc-bios/bios.bin
index 924bee3..ab5dd9d 100644
Binary files a/pc-bios/bios.bin and b/pc-bios/bios.bin differ
commit 8f44015e4600041e200506720e39de7728c5cde9
Author: Markus Armbruster <armbru at redhat.com>
Date:   Fri Jan 25 16:43:40 2013 +0100

    trace: Fix location of simpletrace.py in docs
    
    Missed when commit 4c3b5a48 moved it.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Reviewed-by: Laszlo Ersek <lersek at redhat.com>
    Reviewed-by: Harsh Prateek Bora <harsh at linux.vnet.ibm.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/docs/tracing.txt b/docs/tracing.txt
index 453cc4a..14db3bf 100644
--- a/docs/tracing.txt
+++ b/docs/tracing.txt
@@ -23,7 +23,7 @@ for debugging, profiling, and observing execution.
 
 4. Pretty-print the binary trace file:
 
-    ./simpletrace.py trace-events trace-*
+    ./scripts/simpletrace.py trace-events trace-*
 
 == Trace events ==
 
@@ -198,7 +198,7 @@ The "simple" backend produces binary trace files that can be formatted with the
 simpletrace.py script.  The script takes the "trace-events" file and the binary
 trace:
 
-    ./simpletrace.py trace-events trace-12345
+    ./scripts/simpletrace.py trace-events trace-12345
 
 You must ensure that the same "trace-events" file was used to build QEMU,
 otherwise trace event declarations may have changed and output will not be
commit b6b2c9628084f1672b92393cf84039a075a95301
Author: Markus Armbruster <armbru at redhat.com>
Date:   Fri Jan 25 16:43:39 2013 +0100

    trace: Clean up the "try to update atomic until it worked" loops
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Reviewed-by: Laszlo Ersek <lersek at redhat.com>
    Reviewed-by: Harsh Prateek Bora <harsh at linux.vnet.ibm.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/trace/simple.c b/trace/simple.c
index 592ff48..74701e3 100644
--- a/trace/simple.c
+++ b/trace/simple.c
@@ -171,13 +171,10 @@ static gpointer writeout_thread(gpointer opaque)
             dropped.rec.timestamp_ns = get_clock();
             dropped.rec.length = sizeof(TraceRecord) + sizeof(uint64_t),
             dropped.rec.reserved = 0;
-            while (1) {
+            do {
                 dropped_count = g_atomic_int_get(&dropped_events);
-                if (g_atomic_int_compare_and_exchange(&dropped_events,
-                                                      dropped_count, 0)) {
-                    break;
-                }
-            }
+            } while (!g_atomic_int_compare_and_exchange(&dropped_events,
+                                                        dropped_count, 0));
             dropped.rec.arguments[0] = dropped_count;
             unused = fwrite(&dropped.rec, dropped.rec.length, 1, trace_fp);
         }
@@ -213,7 +210,7 @@ int trace_record_start(TraceBufferRecord *rec, TraceEventID event, size_t datasi
     uint32_t rec_len = sizeof(TraceRecord) + datasize;
     uint64_t timestamp_ns = get_clock();
 
-    while (1) {
+    do {
         old_idx = g_atomic_int_get(&trace_idx);
         smp_rmb();
         new_idx = old_idx + rec_len;
@@ -223,12 +220,7 @@ int trace_record_start(TraceBufferRecord *rec, TraceEventID event, size_t datasi
             g_atomic_int_inc(&dropped_events);
             return -ENOSPC;
         }
-
-        if (g_atomic_int_compare_and_exchange(&trace_idx,
-                                              old_idx, new_idx)) {
-            break;
-        }
-    }
+    } while (!g_atomic_int_compare_and_exchange(&trace_idx, old_idx, new_idx));
 
     idx = old_idx % TRACE_BUF_LEN;
 
commit e722d705ae7648a6bd94848319a11eb0afd58a17
Author: Markus Armbruster <armbru at redhat.com>
Date:   Fri Jan 25 16:43:38 2013 +0100

    trace: Direct access of atomics is verboten, use the API
    
    The GLib Reference Manual says:
    
        It is very important that all accesses to a particular integer or
        pointer be performed using only this API and that different sizes
        of operation are not mixed or used on overlapping memory
        regions. Never read or assign directly from or to a value --
        always use this API.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Reviewed-by: Laszlo Ersek <lersek at redhat.com>
    Reviewed-by: Harsh Prateek Bora <harsh at linux.vnet.ibm.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/trace/simple.c b/trace/simple.c
index ccbdb6a..592ff48 100644
--- a/trace/simple.c
+++ b/trace/simple.c
@@ -166,13 +166,13 @@ static gpointer writeout_thread(gpointer opaque)
     for (;;) {
         wait_for_trace_records_available();
 
-        if (dropped_events) {
+        if (g_atomic_int_get(&dropped_events)) {
             dropped.rec.event = DROPPED_EVENT_ID,
             dropped.rec.timestamp_ns = get_clock();
             dropped.rec.length = sizeof(TraceRecord) + sizeof(uint64_t),
             dropped.rec.reserved = 0;
             while (1) {
-                dropped_count = dropped_events;
+                dropped_count = g_atomic_int_get(&dropped_events);
                 if (g_atomic_int_compare_and_exchange(&dropped_events,
                                                       dropped_count, 0)) {
                     break;
@@ -214,7 +214,7 @@ int trace_record_start(TraceBufferRecord *rec, TraceEventID event, size_t datasi
     uint64_t timestamp_ns = get_clock();
 
     while (1) {
-        old_idx = trace_idx;
+        old_idx = g_atomic_int_get(&trace_idx);
         smp_rmb();
         new_idx = old_idx + rec_len;
 
@@ -275,7 +275,8 @@ void trace_record_finish(TraceBufferRecord *rec)
     record.event |= TRACE_RECORD_VALID;
     write_to_buffer(rec->tbuf_idx, &record, sizeof(TraceRecord));
 
-    if ((trace_idx - writeout_idx) > TRACE_BUF_FLUSH_THRESHOLD) {
+    if ((g_atomic_int_get(&trace_idx) - writeout_idx)
+        > TRACE_BUF_FLUSH_THRESHOLD) {
         flush_trace_file(false);
     }
 }
commit fb3a508531227bc7fb7eee22c51d30bf2ceb15f5
Author: Markus Armbruster <armbru at redhat.com>
Date:   Fri Jan 25 16:43:37 2013 +0100

    trace: Fix simple trace dropped event record for big endian
    
    We use atomic operations to keep track of dropped events.
    
    Inconveniently, GLib supports only int and void * atomics, but the
    counter dropped_events is uint64_t.  Can't stop commit 62bab732: a
    quick (gint *)&dropped_events bludgeons the compiler into submission.
    
    That cast is okay only when int is exactly 64 bits wide, which it
    commonly isn't.
    
    If int is even wider, we clobber whatever follows dropped_events.  Not
    worth worrying about, as none of the machines that interest us have
    such morbidly obese ints.
    
    That leaves the common case: int narrower than 64 bits.
    
    Harmless on little endian hosts: we just don't access the most
    significant bits of dropped_events.  They remain zero.
    
    On big endian hosts, we use only the most significant bits of
    dropped_events as counter.  The least significant bits remain zero.
    However, we write out the full value, which is the correct counter
    shifted left a bunch of places.
    
    Fix by changing the variables involved to int.
    
    There's another, equally suspicious-looking (gint *)&trace_idx
    argument to g_atomic_int_compare_and_exchange(), but that one casts
    unsigned *, so it's okay.  But it's also superfluous, because GLib's
    atomic int operations work just fine for unsigned.  Drop it.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Reviewed-by: Laszlo Ersek <lersek at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/trace/simple.c b/trace/simple.c
index ce17d64..ccbdb6a 100644
--- a/trace/simple.c
+++ b/trace/simple.c
@@ -53,7 +53,7 @@ enum {
 uint8_t trace_buf[TRACE_BUF_LEN];
 static unsigned int trace_idx;
 static unsigned int writeout_idx;
-static uint64_t dropped_events;
+static int dropped_events;
 static FILE *trace_fp;
 static char *trace_file_name;
 
@@ -63,7 +63,7 @@ typedef struct {
     uint64_t timestamp_ns;
     uint32_t length;   /*    in bytes */
     uint32_t reserved; /*    unused */
-    uint8_t arguments[];
+    uint64_t arguments[];
 } TraceRecord;
 
 typedef struct {
@@ -160,7 +160,7 @@ static gpointer writeout_thread(gpointer opaque)
         uint8_t bytes[sizeof(TraceRecord) + sizeof(uint64_t)];
     } dropped;
     unsigned int idx = 0;
-    uint64_t dropped_count;
+    int dropped_count;
     size_t unused __attribute__ ((unused));
 
     for (;;) {
@@ -169,16 +169,16 @@ static gpointer writeout_thread(gpointer opaque)
         if (dropped_events) {
             dropped.rec.event = DROPPED_EVENT_ID,
             dropped.rec.timestamp_ns = get_clock();
-            dropped.rec.length = sizeof(TraceRecord) + sizeof(dropped_events),
+            dropped.rec.length = sizeof(TraceRecord) + sizeof(uint64_t),
             dropped.rec.reserved = 0;
             while (1) {
                 dropped_count = dropped_events;
-                if (g_atomic_int_compare_and_exchange((gint *)&dropped_events,
+                if (g_atomic_int_compare_and_exchange(&dropped_events,
                                                       dropped_count, 0)) {
                     break;
                 }
             }
-            memcpy(dropped.rec.arguments, &dropped_count, sizeof(uint64_t));
+            dropped.rec.arguments[0] = dropped_count;
             unused = fwrite(&dropped.rec, dropped.rec.length, 1, trace_fp);
         }
 
@@ -220,11 +220,11 @@ int trace_record_start(TraceBufferRecord *rec, TraceEventID event, size_t datasi
 
         if (new_idx - writeout_idx > TRACE_BUF_LEN) {
             /* Trace Buffer Full, Event dropped ! */
-            g_atomic_int_inc((gint *)&dropped_events);
+            g_atomic_int_inc(&dropped_events);
             return -ENOSPC;
         }
 
-        if (g_atomic_int_compare_and_exchange((gint *)&trace_idx,
+        if (g_atomic_int_compare_and_exchange(&trace_idx,
                                               old_idx, new_idx)) {
             break;
         }
commit b22dd1243f38286263d40496ce5298a8a7d96eea
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sun Feb 3 21:33:16 2013 +0100

    target-s390x: Fix wrong comparison in interrupt handling
    
    gcc with -Wextra complains about an ordered pointer comparison:
    
    target-s390x/helper.c:660:27: warning:
     ordered comparison of pointer with integer zero [-Wextra]
    
    Obviously the index was missing in the code.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/target-s390x/helper.c b/target-s390x/helper.c
index 95f1ff5..043feb2 100644
--- a/target-s390x/helper.c
+++ b/target-s390x/helper.c
@@ -657,7 +657,7 @@ static void do_io_interrupt(CPUS390XState *env)
         cpu_unmap_lowcore(lowcore);
 
         env->io_index[isc]--;
-        if (env->io_index >= 0) {
+        if (env->io_index[isc] >= 0) {
             disable = 0;
         }
         break;
commit 0123c486367ab77c3c5ed349616a862eb474a03f
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Feb 4 15:22:08 2013 -0600

    s390x: silence warning from GCC on uninitialized values
    
    As best I can tell, this is a false positive.
    
      [aliguori at ccnode4 qemu-s390]$ make
        CC    s390x-softmmu/target-s390x/helper.o
      /home/aliguori/git/qemu/target-s390x/helper.c: In function ‘do_interrupt’:
      /home/aliguori/git/qemu/target-s390x/helper.c:673:17: error: ‘addr’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
      /home/aliguori/git/qemu/target-s390x/helper.c:620:20: note: ‘addr’ was declared here
      /home/aliguori/git/qemu/target-s390x/helper.c:673:17: error: ‘mask’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
      /home/aliguori/git/qemu/target-s390x/helper.c:620:14: note: ‘mask’ was declared here
      cc1: all warnings being treated as errors
      make[1]: *** [target-s390x/helper.o] Error 1
      make: *** [subdir-s390x-softmmu] Error 2
    
    Cc: Cornelia Huck <cornelia.huck at de.ibm.com>
    Cc: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/target-s390x/helper.c b/target-s390x/helper.c
index 3180b90..95f1ff5 100644
--- a/target-s390x/helper.c
+++ b/target-s390x/helper.c
@@ -617,7 +617,7 @@ static void do_ext_interrupt(CPUS390XState *env)
 
 static void do_io_interrupt(CPUS390XState *env)
 {
-    uint64_t mask, addr;
+    uint64_t mask = 0, addr = 0;
     LowCore *lowcore;
     IOIntQueue *q;
     uint8_t isc;
commit ded67782e6d06069873adce7f9074d273ae75760
Author: Michael Roth <mdroth at linux.vnet.ibm.com>
Date:   Mon Feb 4 10:07:51 2013 -0600

    acpi_piix4: fix segfault migrating from 1.2
    
    b0b873a07872f7ab7f66f259c73fb9dd42aa66a9 bumped the vmstate version and
    introduced an old-style load function to handle migration from prior
    (<= 1.2) versions.
    
    The load function passes the top-level PIIX4PMState pointer to
    vmstate_load_state() to handle nested structs for APMState and
    pci_status, which leads to corruption of the top-level PIIX4PMState,
    since pointers to the nested structs are expected.
    
    A segfault can be fairly reliably triggered by migrating from 1.2 and
    issuing a reset, which will trigger a number of QOM operations which
    rely on the now corrupted ObjectClass/Object members.
    
    Fix this by passing in the expected pointers for vmstate_load_state().
    
    Cc: qemu-stable at nongnu.org
    Signed-off-by: Michael Roth <mdroth at linux.vnet.ibm.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index 0d33849..65b2601 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -235,7 +235,7 @@ static int acpi_load_old(QEMUFile *f, void *opaque, int version_id)
     qemu_get_be16s(f, &s->ar.pm1.evt.en);
     qemu_get_be16s(f, &s->ar.pm1.cnt.cnt);
 
-    ret = vmstate_load_state(f, &vmstate_apm, opaque, 1);
+    ret = vmstate_load_state(f, &vmstate_apm, &s->apm, 1);
     if (ret) {
         return ret;
     }
@@ -253,7 +253,7 @@ static int acpi_load_old(QEMUFile *f, void *opaque, int version_id)
         qemu_get_be16s(f, &temp);
     }
 
-    ret = vmstate_load_state(f, &vmstate_pci_status, opaque, 1);
+    ret = vmstate_load_state(f, &vmstate_pci_status, &s->pci0_status, 1);
     return ret;
 }
 
commit c881e20eed4911ab6f8c674f2b1bf225a2cdde71
Author: Eduardo Habkost <ehabkost at redhat.com>
Date:   Mon Feb 4 16:27:52 2013 -0200

    vl.c: validate -numa "cpus" parameter properly
    
    - Accept empty strings without aborting
    - Use parse_uint*() to parse numbers
    - Abort if anything except '-' or end-of-string is found after the first
      number.
    - Check for endvalue < value
    
    Also change the MAX_CPUMASK_BITS warning message from "A max of %d CPUs
    are supported in a guest" to "qemu: NUMA: A max of %d VCPUs are
    supported".
    
    Signed-off-by: Eduardo Habkost <ehabkost at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/vl.c b/vl.c
index de164f8..a8dc73d 100644
--- a/vl.c
+++ b/vl.c
@@ -1249,21 +1249,43 @@ static void numa_node_parse_cpus(int nodenr, const char *cpus)
     char *endptr;
     unsigned long long value, endvalue;
 
-    value = strtoull(cpus, &endptr, 10);
+    /* Empty CPU range strings will be considered valid, they will simply
+     * not set any bit in the CPU bitmap.
+     */
+    if (!*cpus) {
+        return;
+    }
+
+    if (parse_uint(cpus, &value, &endptr, 10) < 0) {
+        goto error;
+    }
     if (*endptr == '-') {
-        endvalue = strtoull(endptr+1, &endptr, 10);
-    } else {
+        if (parse_uint_full(endptr + 1, &endvalue, 10) < 0) {
+            goto error;
+        }
+    } else if (*endptr == '\0') {
         endvalue = value;
+    } else {
+        goto error;
     }
 
-    if (!(endvalue < MAX_CPUMASK_BITS)) {
+    if (endvalue >= MAX_CPUMASK_BITS) {
         endvalue = MAX_CPUMASK_BITS - 1;
         fprintf(stderr,
-            "A max of %d CPUs are supported in a guest\n",
+            "qemu: NUMA: A max of %d VCPUs are supported\n",
              MAX_CPUMASK_BITS);
     }
 
+    if (endvalue < value) {
+        goto error;
+    }
+
     bitmap_set(node_cpumask[nodenr], value, endvalue-value+1);
+    return;
+
+error:
+    fprintf(stderr, "qemu: Invalid NUMA CPU range: %s\n", cpus);
+    exit(1);
 }
 
 static void numa_add(const char *optarg)
commit 845e5bf9cd49873c72f84796cabf107c3f520f37
Author: Eduardo Habkost <ehabkost at redhat.com>
Date:   Mon Feb 4 16:27:51 2013 -0200

    vl.c: Extract -numa "cpus" parsing to separate function
    
    This will make it easier to refactor that code later.
    
    Signed-off-by: Eduardo Habkost <ehabkost at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/vl.c b/vl.c
index d6f6422..de164f8 100644
--- a/vl.c
+++ b/vl.c
@@ -1244,15 +1244,34 @@ char *get_boot_devices_list(size_t *size)
     return list;
 }
 
+static void numa_node_parse_cpus(int nodenr, const char *cpus)
+{
+    char *endptr;
+    unsigned long long value, endvalue;
+
+    value = strtoull(cpus, &endptr, 10);
+    if (*endptr == '-') {
+        endvalue = strtoull(endptr+1, &endptr, 10);
+    } else {
+        endvalue = value;
+    }
+
+    if (!(endvalue < MAX_CPUMASK_BITS)) {
+        endvalue = MAX_CPUMASK_BITS - 1;
+        fprintf(stderr,
+            "A max of %d CPUs are supported in a guest\n",
+             MAX_CPUMASK_BITS);
+    }
+
+    bitmap_set(node_cpumask[nodenr], value, endvalue-value+1);
+}
+
 static void numa_add(const char *optarg)
 {
     char option[128];
     char *endptr;
-    unsigned long long value, endvalue;
     unsigned long long nodenr;
 
-    value = endvalue = 0ULL;
-
     optarg = get_opt_name(option, 128, optarg, ',');
     if (*optarg == ',') {
         optarg++;
@@ -1290,21 +1309,7 @@ static void numa_add(const char *optarg)
             node_mem[nodenr] = sval;
         }
         if (get_param_value(option, 128, "cpus", optarg) != 0) {
-            value = strtoull(option, &endptr, 10);
-            if (*endptr == '-') {
-                endvalue = strtoull(endptr+1, &endptr, 10);
-            } else {
-                endvalue = value;
-            }
-
-            if (!(endvalue < MAX_CPUMASK_BITS)) {
-                endvalue = MAX_CPUMASK_BITS - 1;
-                fprintf(stderr,
-                    "A max of %d CPUs are supported in a guest\n",
-                     MAX_CPUMASK_BITS);
-            }
-
-            bitmap_set(node_cpumask[nodenr], value, endvalue-value+1);
+            numa_node_parse_cpus(nodenr, option);
         }
         nb_numa_nodes++;
     } else {
commit 5f1399651eaab1b04e49107250d182968a227aa6
Author: Eduardo Habkost <ehabkost at redhat.com>
Date:   Mon Feb 4 16:27:50 2013 -0200

    vl.c: Use parse_uint_full() for NUMA nodeid
    
    This should catch many kinds of errors that the current code wasn't
    checking for:
    
     - Values that can't be parsed as a number
     - Negative values
     - Overflow
     - Empty string
    
    Signed-off-by: Eduardo Habkost <ehabkost at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/vl.c b/vl.c
index 4955c29..d6f6422 100644
--- a/vl.c
+++ b/vl.c
@@ -1267,7 +1267,10 @@ static void numa_add(const char *optarg)
         if (get_param_value(option, 128, "nodeid", optarg) == 0) {
             nodenr = nb_numa_nodes;
         } else {
-            nodenr = strtoull(option, NULL, 10);
+            if (parse_uint_full(option, &nodenr, 10) < 0) {
+                fprintf(stderr, "qemu: Invalid NUMA nodeid: %s\n", option);
+                exit(1);
+            }
         }
 
         if (nodenr >= MAX_NODES) {
commit e4ce85b25838694d2d7396b5e969eb4830329631
Author: Eduardo Habkost <ehabkost at redhat.com>
Date:   Mon Feb 4 16:27:49 2013 -0200

    vl.c: numa_add(): Validate nodeid before using it
    
    Without this check, QEMU will corrupt memory if a too-large nodeid is
    provided in the command-line. e.g.:
    
      -numa node,mem=...,cpus=...,nodeid=65
    
    This changes nodenr to unsigned long long, to avoid integer conversion
    issues when converting the strtoull() result to int.
    
    Signed-off-by: Eduardo Habkost <ehabkost at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/vl.c b/vl.c
index 89de003..4955c29 100644
--- a/vl.c
+++ b/vl.c
@@ -1249,7 +1249,7 @@ static void numa_add(const char *optarg)
     char option[128];
     char *endptr;
     unsigned long long value, endvalue;
-    int nodenr;
+    unsigned long long nodenr;
 
     value = endvalue = 0ULL;
 
@@ -1270,6 +1270,11 @@ static void numa_add(const char *optarg)
             nodenr = strtoull(option, NULL, 10);
         }
 
+        if (nodenr >= MAX_NODES) {
+            fprintf(stderr, "qemu: invalid NUMA nodeid: %llu\n", nodenr);
+            exit(1);
+        }
+
         if (get_param_value(option, 128, "mem", optarg) == 0) {
             node_mem[nodenr] = 0;
         } else {
commit ca4c6d363153f19abf3ffdf0ca1532daa581867d
Author: Eduardo Habkost <ehabkost at redhat.com>
Date:   Mon Feb 4 16:27:48 2013 -0200

    vl.c: Check for NUMA node limit inside numa_add()
    
    Instead of checking the limit before calling numa_add(), check the limit
    only when we already know we're going to add a new node.
    
    Signed-off-by: Eduardo Habkost <ehabkost at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/vl.c b/vl.c
index 586aa9a..89de003 100644
--- a/vl.c
+++ b/vl.c
@@ -1258,6 +1258,12 @@ static void numa_add(const char *optarg)
         optarg++;
     }
     if (!strcmp(option, "node")) {
+
+        if (nb_numa_nodes >= MAX_NODES) {
+            fprintf(stderr, "qemu: too many NUMA nodes\n");
+            exit(1);
+        }
+
         if (get_param_value(option, 128, "nodeid", optarg) == 0) {
             nodenr = nb_numa_nodes;
         } else {
@@ -3003,10 +3009,6 @@ int main(int argc, char **argv, char **envp)
                 }
                 break;
             case QEMU_OPTION_numa:
-                if (nb_numa_nodes >= MAX_NODES) {
-                    fprintf(stderr, "qemu: too many NUMA nodes\n");
-                    exit(1);
-                }
                 numa_add(optarg);
                 break;
             case QEMU_OPTION_display:
commit 12e53a9d59c8cb272a423e1db036324579a3c697
Author: Eduardo Habkost <ehabkost at redhat.com>
Date:   Mon Feb 4 16:27:47 2013 -0200

    vl.c: Abort on unknown -numa option type
    
    Abort in case an invalid -numa option is provided, instead of silently
    ignoring it.
    
    Signed-off-by: Eduardo Habkost <ehabkost at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/vl.c b/vl.c
index 0dae44c..586aa9a 100644
--- a/vl.c
+++ b/vl.c
@@ -1293,6 +1293,9 @@ static void numa_add(const char *optarg)
             bitmap_set(node_cpumask[nodenr], value, endvalue-value+1);
         }
         nb_numa_nodes++;
+    } else {
+        fprintf(stderr, "Invalid -numa option: %s\n", option);
+        exit(1);
     }
 }
 
commit 8f302cb0900ba7f38b62da5759f07b77483d6fb9
Author: Eduardo Habkost <ehabkost at redhat.com>
Date:   Mon Feb 4 16:27:46 2013 -0200

    vl.c: Fix off-by-one bug when handling "-numa node" argument
    
    The numa_add() code was unconditionally adding 1 to the get_opt_name()
    return value, making it point after the end of the string if no ','
    separator is present.
    
    Example of weird behavior caused by the bug:
    
      $ qemu-img create -f qcow2 this-file-image-has,cpus=5,mem=1000,in-its-name.qcow2 5G
      Formatting 'this-file-image-has,cpus=5,mem=1000,in-its-name.qcow2', fmt=qcow2 size=5368709120 encryption=off cluster_size=65536
      $ ./x86_64-softmmu/qemu-system-x86_64 -S -monitor stdio -numa node 'this-file-image-has,cpus=5,mem=1000,in-its-name.qcow2'
      QEMU 1.3.50 monitor - type 'help' for more information
      (qemu) info numa
      1 nodes
      node 0 cpus: 0
      node 0 size: 1000 MB
      (qemu)
    
    This changes the code to nove the pointer only if ',' is found.
    
    Signed-off-by: Eduardo Habkost <ehabkost at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/vl.c b/vl.c
index 3155989..0dae44c 100644
--- a/vl.c
+++ b/vl.c
@@ -1253,7 +1253,10 @@ static void numa_add(const char *optarg)
 
     value = endvalue = 0ULL;
 
-    optarg = get_opt_name(option, 128, optarg, ',') + 1;
+    optarg = get_opt_name(option, 128, optarg, ',');
+    if (*optarg == ',') {
+        optarg++;
+    }
     if (!strcmp(option, "node")) {
         if (get_param_value(option, 128, "nodeid", optarg) == 0) {
             nodenr = nb_numa_nodes;
commit e3f9fe2d404ca10153e95499ece111c077b6690a
Author: Eduardo Habkost <ehabkost at redhat.com>
Date:   Mon Feb 4 16:27:45 2013 -0200

    cutils: unsigned int parsing functions
    
    There are lots of duplicate parsing code using strto*() in QEMU, and
    most of that code is broken in one way or another. Even the visitors
    code have duplicate integer parsing code[1]. This introduces functions
    to help parsing unsigned int values: parse_uint() and parse_uint_full().
    
    Parsing functions for signed ints and floats will be submitted later.
    
    parse_uint_full() has all the checks made by opts_type_uint64() at
    opts-visitor.c:
    
     - Check for NULL (returns -EINVAL)
     - Check for negative numbers (returns -EINVAL)
     - Check for empty string (returns -EINVAL)
     - Check for overflow or other errno values set by strtoll() (returns
       -errno)
     - Check for end of string (reject invalid characters after number)
       (returns -EINVAL)
    
    parse_uint() does everything above except checking for the end of the
    string, so callers can continue parsing the remainder of string after
    the number.
    
    Unit tests included.
    
    [1] string-input-visitor.c:parse_int() could use the same parsing code
        used by opts-visitor.c:opts_type_int(), instead of duplicating that
        logic.
    
    Signed-off-by: Eduardo Habkost <ehabkost at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Reviewed-by: Laszlo Ersek <lersek at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/include/qemu-common.h b/include/qemu-common.h
index af2379f..80016ad 100644
--- a/include/qemu-common.h
+++ b/include/qemu-common.h
@@ -173,6 +173,10 @@ int qemu_fdatasync(int fd);
 int fcntl_setfl(int fd, int flag);
 int qemu_parse_fd(const char *param);
 
+int parse_uint(const char *s, unsigned long long *value, char **endptr,
+               int base);
+int parse_uint_full(const char *s, unsigned long long *value, int base);
+
 /*
  * strtosz() suffixes used to specify the default treatment of an
  * argument passed to strtosz() without an explicit suffix.
diff --git a/tests/Makefile b/tests/Makefile
index 83145f5..a2d62b8 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -52,6 +52,8 @@ check-unit-y += tests/test-x86-cpuid$(EXESUF)
 gcov-files-test-x86-cpuid-y =
 check-unit-y += tests/test-xbzrle$(EXESUF)
 gcov-files-test-xbzrle-y = xbzrle.c
+check-unit-y += tests/test-cutils$(EXESUF)
+gcov-files-test-cutils-y += util/cutils.c
 
 check-block-$(CONFIG_POSIX) += tests/qemu-iotests-quick.sh
 
@@ -101,6 +103,7 @@ tests/test-iov$(EXESUF): tests/test-iov.o libqemuutil.a
 tests/test-hbitmap$(EXESUF): tests/test-hbitmap.o libqemuutil.a libqemustub.a
 tests/test-x86-cpuid$(EXESUF): tests/test-x86-cpuid.o
 tests/test-xbzrle$(EXESUF): tests/test-xbzrle.o xbzrle.o page_cache.o libqemuutil.a
+tests/test-cutils$(EXESUF): tests/test-cutils.o util/cutils.o
 
 tests/test-qapi-types.c tests/test-qapi-types.h :\
 $(SRC_PATH)/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-types.py
diff --git a/tests/test-cutils.c b/tests/test-cutils.c
new file mode 100644
index 0000000..2a4556d
--- /dev/null
+++ b/tests/test-cutils.c
@@ -0,0 +1,251 @@
+/*
+ * cutils.c unit-tests
+ *
+ * Copyright (C) 2013 Red Hat Inc.
+ *
+ * Authors:
+ *  Eduardo Habkost <ehabkost at redhat.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <glib.h>
+#include <errno.h>
+#include <string.h>
+
+#include "qemu-common.h"
+
+
+static void test_parse_uint_null(void)
+{
+    unsigned long long i = 999;
+    char f = 'X';
+    char *endptr = &f;
+    int r;
+
+    r = parse_uint(NULL, &i, &endptr, 0);
+
+    g_assert_cmpint(r, ==, -EINVAL);
+    g_assert_cmpint(i, ==, 0);
+    g_assert(endptr == NULL);
+}
+
+static void test_parse_uint_empty(void)
+{
+    unsigned long long i = 999;
+    char f = 'X';
+    char *endptr = &f;
+    const char *str = "";
+    int r;
+
+    r = parse_uint(str, &i, &endptr, 0);
+
+    g_assert_cmpint(r, ==, -EINVAL);
+    g_assert_cmpint(i, ==, 0);
+    g_assert(endptr == str);
+}
+
+static void test_parse_uint_whitespace(void)
+{
+    unsigned long long i = 999;
+    char f = 'X';
+    char *endptr = &f;
+    const char *str = "   \t   ";
+    int r;
+
+    r = parse_uint(str, &i, &endptr, 0);
+
+    g_assert_cmpint(r, ==, -EINVAL);
+    g_assert_cmpint(i, ==, 0);
+    g_assert(endptr == str);
+}
+
+
+static void test_parse_uint_invalid(void)
+{
+    unsigned long long i = 999;
+    char f = 'X';
+    char *endptr = &f;
+    const char *str = " \t xxx";
+    int r;
+
+    r = parse_uint(str, &i, &endptr, 0);
+
+    g_assert_cmpint(r, ==, -EINVAL);
+    g_assert_cmpint(i, ==, 0);
+    g_assert(endptr == str);
+}
+
+
+static void test_parse_uint_trailing(void)
+{
+    unsigned long long i = 999;
+    char f = 'X';
+    char *endptr = &f;
+    const char *str = "123xxx";
+    int r;
+
+    r = parse_uint(str, &i, &endptr, 0);
+
+    g_assert_cmpint(r, ==, 0);
+    g_assert_cmpint(i, ==, 123);
+    g_assert(endptr == str + 3);
+}
+
+static void test_parse_uint_correct(void)
+{
+    unsigned long long i = 999;
+    char f = 'X';
+    char *endptr = &f;
+    const char *str = "123";
+    int r;
+
+    r = parse_uint(str, &i, &endptr, 0);
+
+    g_assert_cmpint(r, ==, 0);
+    g_assert_cmpint(i, ==, 123);
+    g_assert(endptr == str + strlen(str));
+}
+
+static void test_parse_uint_octal(void)
+{
+    unsigned long long i = 999;
+    char f = 'X';
+    char *endptr = &f;
+    const char *str = "0123";
+    int r;
+
+    r = parse_uint(str, &i, &endptr, 0);
+
+    g_assert_cmpint(r, ==, 0);
+    g_assert_cmpint(i, ==, 0123);
+    g_assert(endptr == str + strlen(str));
+}
+
+static void test_parse_uint_decimal(void)
+{
+    unsigned long long i = 999;
+    char f = 'X';
+    char *endptr = &f;
+    const char *str = "0123";
+    int r;
+
+    r = parse_uint(str, &i, &endptr, 10);
+
+    g_assert_cmpint(r, ==, 0);
+    g_assert_cmpint(i, ==, 123);
+    g_assert(endptr == str + strlen(str));
+}
+
+
+static void test_parse_uint_llong_max(void)
+{
+    unsigned long long i = 999;
+    char f = 'X';
+    char *endptr = &f;
+    char *str = g_strdup_printf("%llu", (unsigned long long)LLONG_MAX + 1);
+    int r;
+
+    r = parse_uint(str, &i, &endptr, 0);
+
+    g_assert_cmpint(r, ==, 0);
+    g_assert_cmpint(i, ==, (unsigned long long)LLONG_MAX + 1);
+    g_assert(endptr == str + strlen(str));
+
+    g_free(str);
+}
+
+static void test_parse_uint_overflow(void)
+{
+    unsigned long long i = 999;
+    char f = 'X';
+    char *endptr = &f;
+    const char *str = "99999999999999999999999999999999999999";
+    int r;
+
+    r = parse_uint(str, &i, &endptr, 0);
+
+    g_assert_cmpint(r, ==, -ERANGE);
+    g_assert_cmpint(i, ==, ULLONG_MAX);
+    g_assert(endptr == str + strlen(str));
+}
+
+static void test_parse_uint_negative(void)
+{
+    unsigned long long i = 999;
+    char f = 'X';
+    char *endptr = &f;
+    const char *str = " \t -321";
+    int r;
+
+    r = parse_uint(str, &i, &endptr, 0);
+
+    g_assert_cmpint(r, ==, -ERANGE);
+    g_assert_cmpint(i, ==, 0);
+    g_assert(endptr == str + strlen(str));
+}
+
+
+static void test_parse_uint_full_trailing(void)
+{
+    unsigned long long i = 999;
+    const char *str = "123xxx";
+    int r;
+
+    r = parse_uint_full(str, &i, 0);
+
+    g_assert_cmpint(r, ==, -EINVAL);
+    g_assert_cmpint(i, ==, 0);
+}
+
+static void test_parse_uint_full_correct(void)
+{
+    unsigned long long i = 999;
+    const char *str = "123";
+    int r;
+
+    r = parse_uint_full(str, &i, 0);
+
+    g_assert_cmpint(r, ==, 0);
+    g_assert_cmpint(i, ==, 123);
+}
+
+int main(int argc, char **argv)
+{
+    g_test_init(&argc, &argv, NULL);
+
+    g_test_add_func("/cutils/parse_uint/null", test_parse_uint_null);
+    g_test_add_func("/cutils/parse_uint/empty", test_parse_uint_empty);
+    g_test_add_func("/cutils/parse_uint/whitespace",
+                    test_parse_uint_whitespace);
+    g_test_add_func("/cutils/parse_uint/invalid", test_parse_uint_invalid);
+    g_test_add_func("/cutils/parse_uint/trailing", test_parse_uint_trailing);
+    g_test_add_func("/cutils/parse_uint/correct", test_parse_uint_correct);
+    g_test_add_func("/cutils/parse_uint/octal", test_parse_uint_octal);
+    g_test_add_func("/cutils/parse_uint/decimal", test_parse_uint_decimal);
+    g_test_add_func("/cutils/parse_uint/llong_max", test_parse_uint_llong_max);
+    g_test_add_func("/cutils/parse_uint/overflow", test_parse_uint_overflow);
+    g_test_add_func("/cutils/parse_uint/negative", test_parse_uint_negative);
+    g_test_add_func("/cutils/parse_uint_full/trailing",
+                    test_parse_uint_full_trailing);
+    g_test_add_func("/cutils/parse_uint_full/correct",
+                    test_parse_uint_full_correct);
+
+    return g_test_run();
+}
diff --git a/util/cutils.c b/util/cutils.c
index 80bb1dc..1439da4 100644
--- a/util/cutils.c
+++ b/util/cutils.c
@@ -270,6 +270,105 @@ int64_t strtosz(const char *nptr, char **end)
     return strtosz_suffix(nptr, end, STRTOSZ_DEFSUFFIX_MB);
 }
 
+/**
+ * parse_uint:
+ *
+ * @s: String to parse
+ * @value: Destination for parsed integer value
+ * @endptr: Destination for pointer to first character not consumed
+ * @base: integer base, between 2 and 36 inclusive, or 0
+ *
+ * Parse unsigned integer
+ *
+ * Parsed syntax is like strtoull()'s: arbitrary whitespace, a single optional
+ * '+' or '-', an optional "0x" if @base is 0 or 16, one or more digits.
+ *
+ * If @s is null, or @base is invalid, or @s doesn't start with an
+ * integer in the syntax above, set *@value to 0, *@endptr to @s, and
+ * return -EINVAL.
+ *
+ * Set *@endptr to point right beyond the parsed integer (even if the integer
+ * overflows or is negative, all digits will be parsed and *@endptr will
+ * point right beyond them).
+ *
+ * If the integer is negative, set *@value to 0, and return -ERANGE.
+ *
+ * If the integer overflows unsigned long long, set *@value to
+ * ULLONG_MAX, and return -ERANGE.
+ *
+ * Else, set *@value to the parsed integer, and return 0.
+ */
+int parse_uint(const char *s, unsigned long long *value, char **endptr,
+               int base)
+{
+    int r = 0;
+    char *endp = (char *)s;
+    unsigned long long val = 0;
+
+    if (!s) {
+        r = -EINVAL;
+        goto out;
+    }
+
+    errno = 0;
+    val = strtoull(s, &endp, base);
+    if (errno) {
+        r = -errno;
+        goto out;
+    }
+
+    if (endp == s) {
+        r = -EINVAL;
+        goto out;
+    }
+
+    /* make sure we reject negative numbers: */
+    while (isspace((unsigned char)*s)) {
+        s++;
+    }
+    if (*s == '-') {
+        val = 0;
+        r = -ERANGE;
+        goto out;
+    }
+
+out:
+    *value = val;
+    *endptr = endp;
+    return r;
+}
+
+/**
+ * parse_uint_full:
+ *
+ * @s: String to parse
+ * @value: Destination for parsed integer value
+ * @base: integer base, between 2 and 36 inclusive, or 0
+ *
+ * Parse unsigned integer from entire string
+ *
+ * Have the same behavior of parse_uint(), but with an additional check
+ * for additional data after the parsed number. If extra characters are present
+ * after the parsed number, the function will return -EINVAL, and *@v will
+ * be set to 0.
+ */
+int parse_uint_full(const char *s, unsigned long long *value, int base)
+{
+    char *endp;
+    int r;
+
+    r = parse_uint(s, value, &endp, base);
+    if (r < 0) {
+        return r;
+    }
+    if (*endp) {
+        *value = 0;
+        return -EINVAL;
+    }
+
+    return 0;
+}
+
 int qemu_parse_fd(const char *param)
 {
     int fd;
commit ff057ccb07f07ee8f34ae4104f7ba8c2dcbc3f9a
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun Jan 27 07:26:05 2013 +0100

    target-cris: Build fix for debug output
    
    Around r3361 (81fdc5f8d2d681da8d255baf0713144f8656bac9) env->debug1 used
    to contain the address of an MMU fault. This is now written into
    env->pregs[PR_EDA] instead.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/target-cris/op_helper.c b/target-cris/op_helper.c
index 0f6a1ee..b580513 100644
--- a/target-cris/op_helper.c
+++ b/target-cris/op_helper.c
@@ -60,7 +60,7 @@ void tlb_fill(CPUCRISState *env, target_ulong addr, int is_write, int mmu_idx,
     int ret;
 
     D_LOG("%s pc=%x tpc=%x ra=%p\n", __func__,
-          env->pc, env->debug1, (void *)retaddr);
+          env->pc, env->pregs[PR_EDA], (void *)retaddr);
     ret = cpu_cris_handle_mmu_fault(env, addr, is_write, mmu_idx);
     if (unlikely(ret)) {
         if (retaddr) {
commit c07ecc6866f8c5eb2e0b23ba20214000310355e0
Author: Laurent Vivier <laurent at vivier.eu>
Date:   Mon Jan 7 11:40:06 2013 +0000

    linux-user: correct reboot()
    
    According to man reboot(2), the 4th argument is only used with
    LINUX_REBOOT_CMD_RESTART2. In other cases, trying to convert
    the value can generate EFAULT.
    
    Signed-off-by: Laurent Vivier <laurent at vivier.eu>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 151f4f3..08538fc 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -101,6 +101,7 @@ int __clone2(int (*fn)(void *), void *child_stack_base,
 #include <linux/fb.h>
 #include <linux/vt.h>
 #include <linux/dm-ioctl.h>
+#include <linux/reboot.h>
 #include "linux_loop.h"
 #include "cpu-uname.h"
 
@@ -6451,10 +6452,17 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
         break;
 #endif
     case TARGET_NR_reboot:
-        if (!(p = lock_user_string(arg4)))
-            goto efault;
-        ret = reboot(arg1, arg2, arg3, p);
-        unlock_user(p, arg4, 0);
+        if (arg3 == LINUX_REBOOT_CMD_RESTART2) {
+           /* arg4 must be ignored in all other cases */
+           p = lock_user_string(arg4);
+           if (!p) {
+              goto efault;
+           }
+           ret = get_errno(reboot(arg1, arg2, arg3, p));
+           unlock_user(p, arg4, 0);
+        } else {
+           ret = get_errno(reboot(arg1, arg2, arg3, NULL));
+        }
         break;
 #ifdef TARGET_NR_readdir
     case TARGET_NR_readdir:
commit 1b09aeb90827c1d91383a9eae42ce8f25909857b
Author: Laurent Vivier <Laurent at Vivier.EU>
Date:   Tue Jan 1 08:24:11 2013 +0000

    linux-user: correct setsockopt()
    
    SO_SNDTIMEO and SO_RCVTIMEO take a struct timeval, not an int
    
    To test this, you can use :
    
    QEMU_STRACE= ping localhost 2>&1 |grep TIMEO
    568 setsockopt(3,SOL_SOCKET,SO_SNDTIMEO,{1,0},8) = 0
    568 setsockopt(3,SOL_SOCKET,SO_RCVTIMEO,{1,0},8) = 0
    
    Signed-off-by: Laurent Vivier <laurent at vivier.eu>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index a6f4271..151f4f3 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -1489,6 +1489,28 @@ static abi_long do_setsockopt(int sockfd, int level, int optname,
         break;
     case TARGET_SOL_SOCKET:
         switch (optname) {
+        case TARGET_SO_RCVTIMEO:
+        {
+                struct timeval tv;
+
+                optname = SO_RCVTIMEO;
+
+set_timeout:
+                if (optlen != sizeof(struct target_timeval)) {
+                    return -TARGET_EINVAL;
+                }
+
+                if (copy_from_user_timeval(&tv, optval_addr)) {
+                    return -TARGET_EFAULT;
+                }
+
+                ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname,
+                                &tv, sizeof(tv)));
+                return ret;
+        }
+        case TARGET_SO_SNDTIMEO:
+                optname = SO_SNDTIMEO;
+                goto set_timeout;
             /* Options with 'int' argument.  */
         case TARGET_SO_DEBUG:
 		optname = SO_DEBUG;
@@ -1540,12 +1562,6 @@ static abi_long do_setsockopt(int sockfd, int level, int optname,
         case TARGET_SO_RCVLOWAT:
 		optname = SO_RCVLOWAT;
 		break;
-        case TARGET_SO_RCVTIMEO:
-		optname = SO_RCVTIMEO;
-		break;
-        case TARGET_SO_SNDTIMEO:
-		optname = SO_SNDTIMEO;
-		break;
             break;
         default:
             goto unimplemented;
commit 910ee4e5f4a1df5b1bd144dfca1ae466e2a86a78
Author: Laurent Vivier <Laurent at Vivier.EU>
Date:   Mon Dec 31 09:45:06 2012 +0000

    linux-user: correct print_timeval() swap tv_sec and tv_usec
    
    Signed-off-by: Laurent Vivier <Laurent at Vivier.EU>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/linux-user/strace.c b/linux-user/strace.c
index 6ec90e8..4e91a6e 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -682,7 +682,7 @@ print_timeval(abi_ulong tv_addr, int last)
         if (!tv)
             return;
         gemu_log("{" TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "}%s",
-            tv->tv_sec, tv->tv_usec, get_comma(last));
+            tswapal(tv->tv_sec), tswapal(tv->tv_usec), get_comma(last));
         unlock_user(tv, tv_addr, 0);
     } else
         gemu_log("NULL%s", get_comma(last));
commit 79dd77de124c47263f54e5f686273487e0016a8f
Author: Laurent Vivier <laurent at vivier.eu>
Date:   Thu Dec 20 11:00:11 2012 +0000

    linux-user: correct msgrcv()
    
    All parameters must be swapped before the call of do_msgrcv().
    
    Allow faked (debian fakeroot daemon) to work properly.
    
    WITHOUT this patch:
    
    $ faked-sysv --foreground --debug
    using 1723744788 as msg key
    msg_key=1723744788
    1723744788:431
    FAKEROOT: msg=131072, key=1723744788
    FAKEROOT: r=-1, received message type=-150996052, message=-160219330
    FAKEROOT, get_msg: Bad address
    r=14, EINTR=4
    fakeroot: clearing up message queues and semaphores, signal=-1
    fakeroot: database save FAILED
    
    WITH this patch:
    
    $ faked-sysv --foreground --debug
    using 1569385744 as msg key
    msg_key=1569385744
    1569385744:424
    FAKEROOT: msg=0, key=1569385744
    ^C
    fakeroot: clearing up message queues and semaphores, signal=2
    fakeroot: database save FAILED
    
    Signed-off-by: Laurent Vivier <laurent at vivier.eu>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 693e66f..a6f4271 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -2897,7 +2897,7 @@ static inline abi_long do_msgrcv(int msqid, abi_long msgp,
         return -TARGET_EFAULT;
 
     host_mb = g_malloc(msgsz+sizeof(long));
-    ret = get_errno(msgrcv(msqid, host_mb, msgsz, tswapal(msgtyp), msgflg));
+    ret = get_errno(msgrcv(msqid, host_mb, msgsz, msgtyp, msgflg));
 
     if (ret > 0) {
         abi_ulong target_mtext_addr = msgp + sizeof(abi_ulong);
@@ -3189,7 +3189,7 @@ static abi_long do_ipc(unsigned int call, int first,
                     break;
                 }
 
-                ret = do_msgrcv(first, tmp->msgp, second, tmp->msgtyp, third);
+                ret = do_msgrcv(first, tswapal(tmp->msgp), second, tswapal(tmp->msgtyp), third);
 
                 unlock_user_struct(tmp, ptr, 0);
                 break;


More information about the Spice-commits mailing list