diff options
| -rwxr-xr-x | configure | 2 | ||||
| -rw-r--r-- | hmp-commands.hx | 102 | ||||
| -rw-r--r-- | hmp.c | 30 | ||||
| -rw-r--r-- | hmp.h | 4 | ||||
| -rw-r--r-- | hw/9pfs/virtio-9p.c | 12 | ||||
| -rw-r--r-- | hw/e1000.c | 42 | ||||
| -rw-r--r-- | include/qemu/bswap.h | 12 | ||||
| -rw-r--r-- | pc-bios/bios.bin | bin | 262144 -> 131072 bytes | |||
| -rw-r--r-- | qapi-schema.json | 71 | ||||
| -rw-r--r-- | qemu-char.c | 140 | ||||
| -rw-r--r-- | qemu-options.hx | 13 | ||||
| -rw-r--r-- | qmp-commands.hx | 61 | ||||
| -rw-r--r-- | target-m68k/translate.c | 2 | ||||
| -rw-r--r-- | ui/vnc_keysym.h | 4 | ||||
| -rw-r--r-- | util/iov.c | 4 |
15 files changed, 266 insertions, 233 deletions
diff --git a/configure b/configure index 0657b1a1b5..8789324a9b 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> diff --git a/hmp-commands.hx b/hmp-commands.hx index bdd48f3469..64008a92d1 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -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 1689e6f1fd..420d48bea6 100644 --- 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 076d8cf378..30b3c20ca4 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/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c index b795839620..d3ea820eae 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); } diff --git a/hw/e1000.c b/hw/e1000.c index bb150c67dc..d6fe815eda 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), diff --git a/include/qemu/bswap.h b/include/qemu/bswap.h index e6d4798142..d3af35d1d9 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 diff --git a/pc-bios/bios.bin b/pc-bios/bios.bin index 924bee30d5..ab5dd9db6a 100644 --- a/pc-bios/bios.bin +++ b/pc-bios/bios.bin Binary files differdiff --git a/qapi-schema.json b/qapi-schema.json index cdd8384915..736f881b75 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,64 +339,57 @@ '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: diff --git a/qemu-char.c b/qemu-char.c index ac5d62dd9a..a3ba02127f 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 */ @@ -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 */ } }, diff --git a/qemu-options.hx b/qemu-options.hx index 2d44137bf9..046bdc0f63 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}, -@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} diff --git a/qmp-commands.hx b/qmp-commands.hx index bbb21f3583..799adea1b7 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -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 diff --git a/target-m68k/translate.c b/target-m68k/translate.c index e763195f86..3f1478cc20 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, diff --git a/ui/vnc_keysym.h b/ui/vnc_keysym.h index df33cfe53c..6250bec692 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 */ diff --git a/util/iov.c b/util/iov.c index c0f5c56618..fbe675d373 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) { |