Merge remote-tracking branch 'stefanha/tracing' into staging
authorAnthony Liguori <aliguori@us.ibm.com>
Wed, 6 Feb 2013 22:36:16 +0000 (16:36 -0600)
committerAnthony Liguori <aliguori@us.ibm.com>
Wed, 6 Feb 2013 22:36:16 +0000 (16:36 -0600)
# 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

15 files changed:
configure
hmp-commands.hx
hmp.c
hmp.h
hw/9pfs/virtio-9p.c
hw/e1000.c
include/qemu/bswap.h
pc-bios/bios.bin
qapi-schema.json
qemu-char.c
qemu-options.hx
qmp-commands.hx
target-m68k/translate.c
ui/vnc_keysym.h
util/iov.c

index 0657b1a1b581712c4143251ad81f2c2e11686515..8789324a9b36d943583e0d053d2e1bddb834550f 100755 (executable)
--- 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>
index bdd48f3469e0cd3fb76d7b4e3ee732e22f005ecf..64008a92d1b24b532335c4d201a4e3c463b715f1 100644 (file)
@@ -841,40 +841,39 @@ 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
-@item memchar_write @var{device} @var{data}
-@findex memchar_write
-Provide writing interface for CirMemCharDriver. Write @var{data}
-to char device 'memory'.
+@item ringbuf_write @var{device} @var{data}
+@findex ringbuf_write
+Write @var{data} to ring buffer character device @var{device}.
+@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
-@item memchar_read @var{device}
-@findex memchar_read
-Provide read interface for CirMemCharDriver. Read from char device
-'memory' and return the data.
-
-@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.
+@item ringbuf_read @var{device}
+@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.
 
 ETEXI
 
@@ -1523,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
-@item chardev_add args
-@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
-@item chardev_remove id
-@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",
diff --git a/hmp.c b/hmp.c
index 1689e6f1fdc124c4a5ac71974ef3d980e782b2a4..420d48bea61a24112fbb9ece2c1fe0862567ade4 100644 (file)
--- a/hmp.c
+++ b/hmp.c
@@ -662,38 +662,46 @@ 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)
 {
-    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_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");
-    MemCharRead *meminfo;
+    char *data;
     Error *errp = NULL;
+    int i;
 
-    meminfo = 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);
         return;
     }
 
-    if (meminfo->count > 0) {
-        monitor_printf(mon, "%s\n", meminfo->data);
-    }
+    for (i = 0; data[i]; i++) {
+        unsigned char ch = data[i];
 
-    qapi_free_MemCharRead(meminfo);
+        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);
 }
 
 static void hmp_cont_cb(void *opaque, int err)
diff --git a/hmp.h b/hmp.h
index 076d8cf378f19892a9fb899207b90ac5182dfbf3..30b3c20ca4d847fd6c2ceb6ffaaba8a7f06bc6c2 100644 (file)
--- 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);
index b7958396201037d833edb6a79a24ae9670a2857e..d3ea820eae46ac9c1069a8687717f5d38ab1e976 100644 (file)
@@ -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);
 }
index bb150c67dc9cdbc08630fcb1de456646d414e570..d6fe815edacf38153b3feb421aa8480acdfb73a6 100644 (file)
@@ -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),
index e6d4798142044c19587a14b15eb069f1b77202a9..d3af35d1d9d2bc27752bf63fa28b382618046bc2 100644 (file)
@@ -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
index 924bee30d54a711a9d849ec4c67d38bef9ca03f4..ab5dd9db6addf9d6a6f67697231ef604bab02fc8 100644 (file)
Binary files a/pc-bios/bios.bin and b/pc-bios/bios.bin differ
index cdd8384915e321aea25f0694114d0dd84194584f..736f881b75b3ea26d9cccc661d9c99bc11eb7e40 100644 (file)
 #
 # 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
 ##
   '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
 #
-# @size: the size to write in bytes.
+# @data: data to write
 #
-# @data: the source data write to memchar.
-#
-# @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
-#          If @device is not a valid char device, DeviceNotFound
 #
 # Since: 1.4
 ##
-{ 'command': 'memchar-write',
-  'data': {'device': 'str', 'size': 'int', 'data': 'str',
+{ 'command': 'ringbuf-write',
+  'data': {'device': 'str', 'data': 'str',
            '*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:
+# @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: @MemCharRead
-#          If @device is not a valid memchr device, DeviceNotFound
+# Returns: data read from the device
 #
 # Since: 1.4
 ##
-{ 'command': 'memchar-read',
+{ 'command': 'ringbuf-read',
   'data': {'device': 'str', 'size': 'int', '*format': 'DataFormat'},
-  'returns': 'MemCharRead' }
+  'returns': 'str' }
 
 ##
 # @CommandInfo:
index ac5d62dd9a323b9e1eab8111562259dd24ed3e89..a3ba02127fe83bc1345253b8ba2e9d8588df80ee 100644 (file)
@@ -98,7 +98,6 @@
 #include "ui/qemu-spice.h"
 
 #define READ_BUF_LEN 4096
-#define CBUFF_SIZE 65536
 
 /***********************************************************/
 /* character device */
@@ -2645,32 +2644,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 bool cirmem_chr_is_empty(const CharDriverState *chr)
+static size_t ringbuf_count(const CharDriverState *chr)
 {
-    const CirMemCharDriver *d = chr->opaque;
+    const RingBufCharDriver *d = chr->opaque;
 
-    return d->cons == d->prod;
+    return d->prod - d->cons;
 }
 
-static size_t qemu_chr_cirmem_count(const CharDriverState *chr)
+static int ringbuf_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
 {
-    const CirMemCharDriver *d = chr->opaque;
-
-    return (d->prod - d->cons);
-}
-
-static int cirmem_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
-{
-    CirMemCharDriver *d = chr->opaque;
+    RingBufCharDriver *d = chr->opaque;
     int i;
 
     if (!buf || (len < 0)) {
@@ -2678,13 +2670,8 @@ 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->cbuf[d->prod++ & (d->size - 1)] = buf[i];
+        if (d->prod - d->cons > d->size) {
             d->cons = d->prod - d->size;
         }
     }
@@ -2692,43 +2679,43 @@ 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 && !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;
 }
 
-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_size(opts, "size", 0);
     if (d->size == 0) {
-        d->size = CBUFF_SIZE;
+        d->size = 65536;
     }
 
     /* 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;
     }
 
@@ -2737,8 +2724,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;
 
@@ -2748,41 +2735,43 @@ fail:
     return NULL;
 }
 
-static bool qemu_is_chr(const CharDriverState *chr, const char *filename)
+static bool chr_is_ringbuf(const CharDriverState *chr)
 {
-    return strcmp(chr->filename, filename);
+    return chr->chr_write == ringbuf_chr_write;
 }
 
-void qmp_memchar_write(const char *device, int64_t size,
-                       const char *data, bool has_format,
-                       enum DataFormat format,
+void qmp_ringbuf_write(const char *device, const char *data,
+                       bool has_format, enum DataFormat format,
                        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) {
-        error_set(errp, QERR_DEVICE_NOT_FOUND, device);
+        error_setg(errp, "Device '%s' not found", device);
         return;
     }
 
-    if (qemu_is_chr(chr, "memory")) {
-        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;
     }
 
-    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);
+    ret = ringbuf_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);
@@ -2790,23 +2779,23 @@ void qmp_memchar_write(const char *device, int64_t size,
     }
 }
 
-MemCharRead *qmp_memchar_read(const char *device, int64_t size,
-                              bool has_format, enum DataFormat format,
-                              Error **errp)
+char *qmp_ringbuf_read(const char *device, int64_t size,
+                       bool has_format, enum DataFormat format,
+                       Error **errp)
 {
     CharDriverState *chr;
-    guchar *read_data;
-    MemCharRead *meminfo;
+    uint8_t *read_data;
     size_t count;
+    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 NULL;
     }
 
-    if (qemu_is_chr(chr, "memory")) {
-        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;
     }
 
@@ -2815,26 +2804,28 @@ 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;
-    }
-
+    count = ringbuf_count(chr);
     size = size > count ? count : size;
-    read_data = g_malloc0(size + 1);
+    read_data = g_malloc(size + 1);
 
-    meminfo->count = cirmem_chr_read(chr, read_data, size);
+    ringbuf_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);
+        g_free(read_data);
     } else {
-        meminfo->data = (char *)read_data;
+        /*
+         * 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;
     }
 
-    return meminfo;
+    return data;
 }
 
 QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename)
@@ -2891,11 +2882,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);
@@ -2995,7 +2981,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 },
@@ -3256,8 +3242,8 @@ QemuOptsList qemu_chardev_opts = {
             .name = "debug",
             .type = QEMU_OPT_NUMBER,
         },{
-            .name = "maxcapacity",
-            .type = QEMU_OPT_NUMBER,
+            .name = "size",
+            .type = QEMU_OPT_SIZE,
         },
         { /* end of list */ }
     },
index 2d44137bf9a974cc4165d1db9301e0334a0200b8..046bdc0f6346a9a55bb1659dc9d348c73b67ee72 100644 (file)
@@ -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},
-@option{memory},
+@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.
 
-@item -chardev memory ,id=@var{id} ,maxcapacity=@var{maxcapacity}
+@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.
-
-@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}.
+@var{size} must be a power of two, and defaults to @code{64K}).
 
 @item -chardev file ,id=@var{id} ,path=@var{path}
 
index bbb21f3583b28639eaf46804cce225638a0760fa..799adea1b7a00af5e358e2baacd40b59ebb7d360 100644 (file)
@@ -466,32 +466,30 @@ Note: inject-nmi fails when the guest doesn't support injecting.
 EQMP
 
     {
-        .name       = "memchar-write",
-        .args_type  = "device:s,size:i,data:s,format:s?",
-        .mhandler.cmd_new = qmp_marshal_input_memchar_write,
+        .name       = "ringbuf-write",
+        .args_type  = "device:s,data:s,format:s?",
+        .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)
-- "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)
-          - 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,
-                               "size": 8,
+-> { "execute": "ringbuf-write",
+                "arguments": { "device": "foo",
                                "data": "abcdefgh",
                                "format": "utf8" } }
 <- { "return": {} }
@@ -499,35 +497,38 @@ 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": { "data": "data string...", "count": 1000 } }
+<- {"return": "abcdefgh"}
 
 EQMP
 
index e763195f8673babf66642a1b997393e476bc2085..3f1478cc201bcc423c43c6d9e4c4916a5c618856 100644 (file)
@@ -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,
index df33cfe53c9dc92113c883a95f99d0a4d3e26e41..6250bec6923d523c267b709830d9d8fc4ece6edd 100644 (file)
@@ -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 */
index c0f5c566185c22828c8ec100435c949630b49e82..fbe675d3730b181a18cbd8a6c12d3057ddb97a30 100644 (file)
@@ -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) {