aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile6
-rw-r--r--audio/audio_win_int.c1
-rw-r--r--block/win32-aio.c1
-rw-r--r--blockdev.c280
-rw-r--r--hw/arm/highbank.c1
-rw-r--r--hw/audio/marvell_88w8618.c1
-rw-r--r--hw/i386/kvm/pci-assign.c18
-rw-r--r--hw/mips/mips_malta.c1
-rw-r--r--hw/misc/lm32_sys.c1
-rw-r--r--hw/net/rtl8139.c3
-rw-r--r--hw/net/virtio-net.c99
-rw-r--r--hw/nvram/fw_cfg.c4
-rw-r--r--hw/ppc/spapr.c2
-rw-r--r--hw/ppc/spapr_hcall.c1
-rw-r--r--hw/timer/exynos4210_rtc.c1
-rw-r--r--include/block/coroutine_int.h4
-rw-r--r--include/hw/i386/pc.h5
-rw-r--r--include/hw/virtio/virtio-net.h13
-rw-r--r--include/qapi/qmp/qlist.h1
-rw-r--r--include/qemu-common.h1
-rw-r--r--include/qemu/config-file.h1
-rw-r--r--linux-user/signal.c16
-rw-r--r--linux-user/syscall.c4
-rw-r--r--monitor.c1
-rw-r--r--net/tap-bsd.c3
-rw-r--r--page_cache.c1
-rw-r--r--qapi-schema-test.json15
-rw-r--r--qapi-schema.json27
-rw-r--r--qemu-char.c20
-rw-r--r--qemu-coroutine-lock.c56
-rw-r--r--qemu-coroutine.c23
-rw-r--r--qemu-io.c46
-rw-r--r--qemu-options.hx7
-rw-r--r--qobject/json-parser.c26
-rw-r--r--qom/object.c4
-rw-r--r--scripts/qapi-types.py45
-rw-r--r--scripts/qapi-visit.py36
-rw-r--r--scripts/qapi.py23
-rw-r--r--slirp/misc.c2
-rw-r--r--target-mips/cpu.h1
-rw-r--r--target-mips/dsp_helper.c16
-rw-r--r--target-mips/helper.c4
-rw-r--r--target-moxie/helper.c2
-rw-r--r--target-ppc/kvm.c2
-rwxr-xr-xtests/qemu-iotests/05458
-rw-r--r--tests/qemu-iotests/054.out10
-rw-r--r--tests/qemu-iotests/common.rc2
-rw-r--r--tests/qemu-iotests/group1
-rwxr-xr-xtests/qemu-iotests/qcow2.py17
-rw-r--r--tests/tcg/linux-test.c1
-rw-r--r--tests/test-qmp-input-visitor.c358
-rw-r--r--tests/test-qmp-output-visitor.c332
-rw-r--r--tests/test-visitor-serialization.c476
-rw-r--r--trace-events2
-rw-r--r--translate-all.c1
-rw-r--r--ui/input.c13
-rw-r--r--vl.c4
57 files changed, 1812 insertions, 288 deletions
diff --git a/Makefile b/Makefile
index 7dc02042be..9695c9d14d 100644
--- a/Makefile
+++ b/Makefile
@@ -178,7 +178,7 @@ Makefile: $(version-obj-y) $(version-lobj-y)
# Build libraries
libqemustub.a: $(stub-obj-y)
-libqemuutil.a: $(util-obj-y)
+libqemuutil.a: $(util-obj-y) qapi-types.o qapi-visit.o
######################################################################
@@ -215,10 +215,10 @@ $(SRC_PATH)/qga/qapi-schema.json $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py)
qapi-types.c qapi-types.h :\
$(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-types.py $(qapi-py)
- $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-types.py $(gen-out-type) -o "." < $<, " GEN $@")
+ $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-types.py $(gen-out-type) -o "." -b < $<, " GEN $@")
qapi-visit.c qapi-visit.h :\
$(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-visit.py $(qapi-py)
- $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-visit.py $(gen-out-type) -o "." < $<, " GEN $@")
+ $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-visit.py $(gen-out-type) -o "." -b < $<, " GEN $@")
qmp-commands.h qmp-marshal.c :\
$(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py)
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py $(gen-out-type) -m -o "." < $<, " GEN $@")
diff --git a/audio/audio_win_int.c b/audio/audio_win_int.c
index 58690524c4..e1324056a4 100644
--- a/audio/audio_win_int.c
+++ b/audio/audio_win_int.c
@@ -1,7 +1,6 @@
/* public domain */
#include "qemu-common.h"
-#include "audio.h"
#define AUDIO_CAP "win-int"
#include <windows.h>
diff --git a/block/win32-aio.c b/block/win32-aio.c
index 5d0fbbfb7d..fcb7c754da 100644
--- a/block/win32-aio.c
+++ b/block/win32-aio.c
@@ -25,7 +25,6 @@
#include "qemu/timer.h"
#include "block/block_int.h"
#include "qemu/module.h"
-#include "qemu-common.h"
#include "block/aio.h"
#include "raw-aio.h"
#include "qemu/event_notifier.h"
diff --git a/blockdev.c b/blockdev.c
index 7c9d8dd0ac..d1ec99af73 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -750,8 +750,8 @@ void do_commit(Monitor *mon, const QDict *qdict)
static void blockdev_do_action(int kind, void *data, Error **errp)
{
- BlockdevAction action;
- BlockdevActionList list;
+ TransactionAction action;
+ TransactionActionList list;
action.kind = kind;
action.data = data;
@@ -773,27 +773,176 @@ void qmp_blockdev_snapshot_sync(const char *device, const char *snapshot_file,
.has_mode = has_mode,
.mode = mode,
};
- blockdev_do_action(BLOCKDEV_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC, &snapshot,
- errp);
+ blockdev_do_action(TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC,
+ &snapshot, errp);
}
/* New and old BlockDriverState structs for group snapshots */
-typedef struct BlkTransactionStates {
+
+typedef struct BlkTransactionStates BlkTransactionStates;
+
+/* Only prepare() may fail. In a single transaction, only one of commit() or
+ abort() will be called, clean() will always be called if it present. */
+typedef struct BdrvActionOps {
+ /* Size of state struct, in bytes. */
+ size_t instance_size;
+ /* Prepare the work, must NOT be NULL. */
+ void (*prepare)(BlkTransactionStates *common, Error **errp);
+ /* Commit the changes, must NOT be NULL. */
+ void (*commit)(BlkTransactionStates *common);
+ /* Abort the changes on fail, can be NULL. */
+ void (*abort)(BlkTransactionStates *common);
+ /* Clean up resource in the end, can be NULL. */
+ void (*clean)(BlkTransactionStates *common);
+} BdrvActionOps;
+
+/*
+ * This structure must be arranged as first member in child type, assuming
+ * that compiler will also arrange it to the same address with parent instance.
+ * Later it will be used in free().
+ */
+struct BlkTransactionStates {
+ TransactionAction *action;
+ const BdrvActionOps *ops;
+ QSIMPLEQ_ENTRY(BlkTransactionStates) entry;
+};
+
+/* external snapshot private data */
+typedef struct ExternalSnapshotStates {
+ BlkTransactionStates common;
BlockDriverState *old_bs;
BlockDriverState *new_bs;
- QSIMPLEQ_ENTRY(BlkTransactionStates) entry;
-} BlkTransactionStates;
+} ExternalSnapshotStates;
+
+static void external_snapshot_prepare(BlkTransactionStates *common,
+ Error **errp)
+{
+ BlockDriver *proto_drv;
+ BlockDriver *drv;
+ int flags, ret;
+ Error *local_err = NULL;
+ const char *device;
+ const char *new_image_file;
+ const char *format = "qcow2";
+ enum NewImageMode mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS;
+ ExternalSnapshotStates *states =
+ DO_UPCAST(ExternalSnapshotStates, common, common);
+ TransactionAction *action = common->action;
+
+ /* get parameters */
+ g_assert(action->kind == TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC);
+
+ device = action->blockdev_snapshot_sync->device;
+ new_image_file = action->blockdev_snapshot_sync->snapshot_file;
+ if (action->blockdev_snapshot_sync->has_format) {
+ format = action->blockdev_snapshot_sync->format;
+ }
+ if (action->blockdev_snapshot_sync->has_mode) {
+ mode = action->blockdev_snapshot_sync->mode;
+ }
+
+ /* start processing */
+ drv = bdrv_find_format(format);
+ if (!drv) {
+ error_set(errp, QERR_INVALID_BLOCK_FORMAT, format);
+ return;
+ }
+
+ states->old_bs = bdrv_find(device);
+ if (!states->old_bs) {
+ error_set(errp, QERR_DEVICE_NOT_FOUND, device);
+ return;
+ }
+
+ if (!bdrv_is_inserted(states->old_bs)) {
+ error_set(errp, QERR_DEVICE_HAS_NO_MEDIUM, device);
+ return;
+ }
+
+ if (bdrv_in_use(states->old_bs)) {
+ error_set(errp, QERR_DEVICE_IN_USE, device);
+ return;
+ }
+
+ if (!bdrv_is_read_only(states->old_bs)) {
+ if (bdrv_flush(states->old_bs)) {
+ error_set(errp, QERR_IO_ERROR);
+ return;
+ }
+ }
+
+ flags = states->old_bs->open_flags;
+
+ proto_drv = bdrv_find_protocol(new_image_file);
+ if (!proto_drv) {
+ error_set(errp, QERR_INVALID_BLOCK_FORMAT, format);
+ return;
+ }
+
+ /* create new image w/backing file */
+ if (mode != NEW_IMAGE_MODE_EXISTING) {
+ bdrv_img_create(new_image_file, format,
+ states->old_bs->filename,
+ states->old_bs->drv->format_name,
+ NULL, -1, flags, &local_err, false);
+ if (error_is_set(&local_err)) {
+ error_propagate(errp, local_err);
+ return;
+ }
+ }
+
+ /* We will manually add the backing_hd field to the bs later */
+ states->new_bs = bdrv_new("");
+ /* TODO Inherit bs->options or only take explicit options with an
+ * extended QMP command? */
+ ret = bdrv_open(states->new_bs, new_image_file, NULL,
+ flags | BDRV_O_NO_BACKING, drv);
+ if (ret != 0) {
+ error_set(errp, QERR_OPEN_FILE_FAILED, new_image_file);
+ }
+}
+
+static void external_snapshot_commit(BlkTransactionStates *common)
+{
+ ExternalSnapshotStates *states =
+ DO_UPCAST(ExternalSnapshotStates, common, common);
+
+ /* This removes our old bs from the bdrv_states, and adds the new bs */
+ bdrv_append(states->new_bs, states->old_bs);
+ /* We don't need (or want) to use the transactional
+ * bdrv_reopen_multiple() across all the entries at once, because we
+ * don't want to abort all of them if one of them fails the reopen */
+ bdrv_reopen(states->new_bs, states->new_bs->open_flags & ~BDRV_O_RDWR,
+ NULL);
+}
+
+static void external_snapshot_abort(BlkTransactionStates *common)
+{
+ ExternalSnapshotStates *states =
+ DO_UPCAST(ExternalSnapshotStates, common, common);
+ if (states->new_bs) {
+ bdrv_delete(states->new_bs);
+ }
+}
+
+static const BdrvActionOps actions[] = {
+ [TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC] = {
+ .instance_size = sizeof(ExternalSnapshotStates),
+ .prepare = external_snapshot_prepare,
+ .commit = external_snapshot_commit,
+ .abort = external_snapshot_abort,
+ },
+};
/*
* 'Atomic' group snapshots. The snapshots are taken as a set, and if any fail
* then we do not pivot any of the devices in the group, and abandon the
* snapshots
*/
-void qmp_transaction(BlockdevActionList *dev_list, Error **errp)
+void qmp_transaction(TransactionActionList *dev_list, Error **errp)
{
- int ret = 0;
- BlockdevActionList *dev_entry = dev_list;
+ TransactionActionList *dev_entry = dev_list;
BlkTransactionStates *states, *next;
Error *local_err = NULL;
@@ -805,109 +954,29 @@ void qmp_transaction(BlockdevActionList *dev_list, Error **errp)
/* We don't do anything in this loop that commits us to the snapshot */
while (NULL != dev_entry) {
- BlockdevAction *dev_info = NULL;
- BlockDriver *proto_drv;
- BlockDriver *drv;
- int flags;
- enum NewImageMode mode;
- const char *new_image_file;
- const char *device;
- const char *format = "qcow2";
+ TransactionAction *dev_info = NULL;
+ const BdrvActionOps *ops;
dev_info = dev_entry->value;
dev_entry = dev_entry->next;
- states = g_malloc0(sizeof(BlkTransactionStates));
- QSIMPLEQ_INSERT_TAIL(&snap_bdrv_states, states, entry);
-
- switch (dev_info->kind) {
- case BLOCKDEV_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC:
- device = dev_info->blockdev_snapshot_sync->device;
- if (!dev_info->blockdev_snapshot_sync->has_mode) {
- dev_info->blockdev_snapshot_sync->mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS;
- }
- new_image_file = dev_info->blockdev_snapshot_sync->snapshot_file;
- if (dev_info->blockdev_snapshot_sync->has_format) {
- format = dev_info->blockdev_snapshot_sync->format;
- }
- mode = dev_info->blockdev_snapshot_sync->mode;
- break;
- default:
- abort();
- }
+ assert(dev_info->kind < ARRAY_SIZE(actions));
- drv = bdrv_find_format(format);
- if (!drv) {
- error_set(errp, QERR_INVALID_BLOCK_FORMAT, format);
- goto delete_and_fail;
- }
-
- states->old_bs = bdrv_find(device);
- if (!states->old_bs) {
- error_set(errp, QERR_DEVICE_NOT_FOUND, device);
- goto delete_and_fail;
- }
-
- if (!bdrv_is_inserted(states->old_bs)) {
- error_set(errp, QERR_DEVICE_HAS_NO_MEDIUM, device);
- goto delete_and_fail;
- }
-
- if (bdrv_in_use(states->old_bs)) {
- error_set(errp, QERR_DEVICE_IN_USE, device);
- goto delete_and_fail;
- }
-
- if (!bdrv_is_read_only(states->old_bs)) {
- if (bdrv_flush(states->old_bs)) {
- error_set(errp, QERR_IO_ERROR);
- goto delete_and_fail;
- }
- }
-
- flags = states->old_bs->open_flags;
-
- proto_drv = bdrv_find_protocol(new_image_file);
- if (!proto_drv) {
- error_set(errp, QERR_INVALID_BLOCK_FORMAT, format);
- goto delete_and_fail;
- }
-
- /* create new image w/backing file */
- if (mode != NEW_IMAGE_MODE_EXISTING) {
- bdrv_img_create(new_image_file, format,
- states->old_bs->filename,
- states->old_bs->drv->format_name,
- NULL, -1, flags, &local_err, false);
- if (error_is_set(&local_err)) {
- error_propagate(errp, local_err);
- goto delete_and_fail;
- }
- }
+ ops = &actions[dev_info->kind];
+ states = g_malloc0(ops->instance_size);
+ states->ops = ops;
+ states->action = dev_info;
+ QSIMPLEQ_INSERT_TAIL(&snap_bdrv_states, states, entry);
- /* We will manually add the backing_hd field to the bs later */
- states->new_bs = bdrv_new("");
- /* TODO Inherit bs->options or only take explicit options with an
- * extended QMP command? */
- ret = bdrv_open(states->new_bs, new_image_file, NULL,
- flags | BDRV_O_NO_BACKING, drv);
- if (ret != 0) {
- error_set(errp, QERR_OPEN_FILE_FAILED, new_image_file);
+ states->ops->prepare(states, &local_err);
+ if (error_is_set(&local_err)) {
+ error_propagate(errp, local_err);
goto delete_and_fail;
}
}
-
- /* Now we are going to do the actual pivot. Everything up to this point
- * is reversible, but we are committed at this point */
QSIMPLEQ_FOREACH(states, &snap_bdrv_states, entry) {
- /* This removes our old bs from the bdrv_states, and adds the new bs */
- bdrv_append(states->new_bs, states->old_bs);
- /* We don't need (or want) to use the transactional
- * bdrv_reopen_multiple() across all the entries at once, because we
- * don't want to abort all of them if one of them fails the reopen */
- bdrv_reopen(states->new_bs, states->new_bs->open_flags & ~BDRV_O_RDWR,
- NULL);
+ states->ops->commit(states);
}
/* success */
@@ -919,12 +988,15 @@ delete_and_fail:
* the original bs for all images
*/
QSIMPLEQ_FOREACH(states, &snap_bdrv_states, entry) {
- if (states->new_bs) {
- bdrv_delete(states->new_bs);
+ if (states->ops->abort) {
+ states->ops->abort(states);
}
}
exit:
QSIMPLEQ_FOREACH_SAFE(states, &snap_bdrv_states, entry, next) {
+ if (states->ops->clean) {
+ states->ops->clean(states);
+ }
g_free(states);
}
}
diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c
index 0fd9465cfa..4405dbd3bd 100644
--- a/hw/arm/highbank.c
+++ b/hw/arm/highbank.c
@@ -24,7 +24,6 @@
#include "net/net.h"
#include "sysemu/sysemu.h"
#include "hw/boards.h"
-#include "hw/sysbus.h"
#include "sysemu/blockdev.h"
#include "exec/address-spaces.h"
diff --git a/hw/audio/marvell_88w8618.c b/hw/audio/marvell_88w8618.c
index de06dfd7d2..c5d88a7841 100644
--- a/hw/audio/marvell_88w8618.c
+++ b/hw/audio/marvell_88w8618.c
@@ -12,7 +12,6 @@
#include "hw/sysbus.h"
#include "hw/hw.h"
#include "hw/i2c/i2c.h"
-#include "hw/sysbus.h"
#include "audio/audio.h"
#define MP_AUDIO_SIZE 0x00001000
diff --git a/hw/i386/kvm/pci-assign.c b/hw/i386/kvm/pci-assign.c
index c1e08ec1a0..ff855904ba 100644
--- a/hw/i386/kvm/pci-assign.c
+++ b/hw/i386/kvm/pci-assign.c
@@ -1026,6 +1026,21 @@ static void assigned_dev_update_msi(PCIDevice *pci_dev)
}
}
+static void assigned_dev_update_msi_msg(PCIDevice *pci_dev)
+{
+ AssignedDevice *assigned_dev = DO_UPCAST(AssignedDevice, dev, pci_dev);
+ uint8_t ctrl_byte = pci_get_byte(pci_dev->config + pci_dev->msi_cap +
+ PCI_MSI_FLAGS);
+
+ if (assigned_dev->assigned_irq_type != ASSIGNED_IRQ_MSI ||
+ !(ctrl_byte & PCI_MSI_FLAGS_ENABLE)) {
+ return;
+ }
+
+ kvm_irqchip_update_msi_route(kvm_state, assigned_dev->msi_virq[0],
+ msi_get_message(pci_dev, 0));
+}
+
static bool assigned_dev_msix_masked(MSIXTableEntry *entry)
{
return (entry->ctrl & cpu_to_le32(0x1)) != 0;
@@ -1201,6 +1216,9 @@ static void assigned_dev_pci_write_config(PCIDevice *pci_dev, uint32_t address,
if (range_covers_byte(address, len,
pci_dev->msi_cap + PCI_MSI_FLAGS)) {
assigned_dev_update_msi(pci_dev);
+ } else if (ranges_overlap(address, len, /* 32bit MSI only */
+ pci_dev->msi_cap + PCI_MSI_ADDRESS_LO, 6)) {
+ assigned_dev_update_msi_msg(pci_dev);
}
}
if (assigned_dev->cap.available & ASSIGNED_DEVICE_CAP_MSIX) {
diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c
index 9d521ccb19..5033d51224 100644
--- a/hw/mips/mips_malta.c
+++ b/hw/mips/mips_malta.c
@@ -37,7 +37,6 @@
#include "sysemu/char.h"
#include "sysemu/sysemu.h"
#include "sysemu/arch_init.h"
-#include "hw/boards.h"
#include "qemu/log.h"
#include "hw/mips/bios.h"
#include "hw/ide.h"
diff --git a/hw/misc/lm32_sys.c b/hw/misc/lm32_sys.c
index 33a3b80ce7..aeaf2b7b7b 100644
--- a/hw/misc/lm32_sys.c
+++ b/hw/misc/lm32_sys.c
@@ -34,7 +34,6 @@
#include "qemu/log.h"
#include "qemu/error-report.h"
#include "sysemu/sysemu.h"
-#include "qemu/log.h"
enum {
R_CTRL = 0,
diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c
index 9369507422..7993f9f5b9 100644
--- a/hw/net/rtl8139.c
+++ b/hw/net/rtl8139.c
@@ -2575,6 +2575,9 @@ static void rtl8139_RxBufPtr_write(RTL8139State *s, uint32_t val)
/* this value is off by 16 */
s->RxBufPtr = MOD2(val + 0x10, s->RxBufferSize);
+ /* more buffer space may be available so try to receive */
+ qemu_flush_queued_packets(qemu_get_queue(s->nic));
+
DPRINTF(" CAPR write: rx buffer length %d head 0x%04x read 0x%04x\n",
s->RxBufferSize, s->RxBufAddr, s->RxBufPtr);
}
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index bed0822f0a..1ea95564a5 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -359,6 +359,34 @@ static uint32_t virtio_net_bad_features(VirtIODevice *vdev)
return features;
}
+static void virtio_net_apply_guest_offloads(VirtIONet *n)
+{
+ tap_set_offload(qemu_get_subqueue(n->nic, 0)->peer,
+ !!(n->curr_guest_offloads & (1ULL << VIRTIO_NET_F_GUEST_CSUM)),
+ !!(n->curr_guest_offloads & (1ULL << VIRTIO_NET_F_GUEST_TSO4)),
+ !!(n->curr_guest_offloads & (1ULL << VIRTIO_NET_F_GUEST_TSO6)),
+ !!(n->curr_guest_offloads & (1ULL << VIRTIO_NET_F_GUEST_ECN)),
+ !!(n->curr_guest_offloads & (1ULL << VIRTIO_NET_F_GUEST_UFO)));
+}
+
+static uint64_t virtio_net_guest_offloads_by_features(uint32_t features)
+{
+ static const uint64_t guest_offloads_mask =
+ (1ULL << VIRTIO_NET_F_GUEST_CSUM) |
+ (1ULL << VIRTIO_NET_F_GUEST_TSO4) |
+ (1ULL << VIRTIO_NET_F_GUEST_TSO6) |
+ (1ULL << VIRTIO_NET_F_GUEST_ECN) |
+ (1ULL << VIRTIO_NET_F_GUEST_UFO);
+
+ return guest_offloads_mask & features;
+}
+
+static inline uint64_t virtio_net_supported_guest_offloads(VirtIONet *n)
+{
+ VirtIODevice *vdev = VIRTIO_DEVICE(n);
+ return virtio_net_guest_offloads_by_features(vdev->guest_features);
+}
+
static void virtio_net_set_features(VirtIODevice *vdev, uint32_t features)
{
VirtIONet *n = VIRTIO_NET(vdev);
@@ -369,12 +397,9 @@ static void virtio_net_set_features(VirtIODevice *vdev, uint32_t features)
virtio_net_set_mrg_rx_bufs(n, !!(features & (1 << VIRTIO_NET_F_MRG_RXBUF)));
if (n->has_vnet_hdr) {
- tap_set_offload(qemu_get_subqueue(n->nic, 0)->peer,
- (features >> VIRTIO_NET_F_GUEST_CSUM) & 1,
- (features >> VIRTIO_NET_F_GUEST_TSO4) & 1,
- (features >> VIRTIO_NET_F_GUEST_TSO6) & 1,
- (features >> VIRTIO_NET_F_GUEST_ECN) & 1,
- (features >> VIRTIO_NET_F_GUEST_UFO) & 1);
+ n->curr_guest_offloads =
+ virtio_net_guest_offloads_by_features(features);
+ virtio_net_apply_guest_offloads(n);
}
for (i = 0; i < n->max_queues; i++) {
@@ -420,6 +445,43 @@ static int virtio_net_handle_rx_mode(VirtIONet *n, uint8_t cmd,
return VIRTIO_NET_OK;
}
+static int virtio_net_handle_offloads(VirtIONet *n, uint8_t cmd,
+ struct iovec *iov, unsigned int iov_cnt)
+{
+ VirtIODevice *vdev = VIRTIO_DEVICE(n);
+ uint64_t offloads;
+ size_t s;
+
+ if (!((1 << VIRTIO_NET_F_CTRL_GUEST_OFFLOADS) & vdev->guest_features)) {
+ return VIRTIO_NET_ERR;
+ }
+
+ s = iov_to_buf(iov, iov_cnt, 0, &offloads, sizeof(offloads));
+ if (s != sizeof(offloads)) {
+ return VIRTIO_NET_ERR;
+ }
+
+ if (cmd == VIRTIO_NET_CTRL_GUEST_OFFLOADS_SET) {
+ uint64_t supported_offloads;
+
+ if (!n->has_vnet_hdr) {
+ return VIRTIO_NET_ERR;
+ }
+
+ supported_offloads = virtio_net_supported_guest_offloads(n);
+ if (offloads & ~supported_offloads) {
+ return VIRTIO_NET_ERR;
+ }
+
+ n->curr_guest_offloads = offloads;
+ virtio_net_apply_guest_offloads(n);
+
+ return VIRTIO_NET_OK;
+ } else {
+ return VIRTIO_NET_ERR;
+ }
+}
+
static int virtio_net_handle_mac(VirtIONet *n, uint8_t cmd,
struct iovec *iov, unsigned int iov_cnt)
{
@@ -590,6 +652,8 @@ static void virtio_net_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
status = virtio_net_handle_vlan_table(n, ctrl.cmd, iov, iov_cnt);
} else if (ctrl.class == VIRTIO_NET_CTRL_MQ) {
status = virtio_net_handle_mq(n, ctrl.cmd, iov, iov_cnt);
+ } else if (ctrl.class == VIRTIO_NET_CTRL_GUEST_OFFLOADS) {
+ status = virtio_net_handle_offloads(n, ctrl.cmd, iov, iov_cnt);
}
s = iov_from_buf(elem.in_sg, elem.in_num, 0, &status, sizeof(status));
@@ -1110,6 +1174,10 @@ static void virtio_net_save(QEMUFile *f, void *opaque)
qemu_put_be32(f, n->vqs[i].tx_waiting);
}
}
+
+ if ((1 << VIRTIO_NET_F_CTRL_GUEST_OFFLOADS) & vdev->guest_features) {
+ qemu_put_be64(f, n->curr_guest_offloads);
+ }
}
static int virtio_net_load(QEMUFile *f, void *opaque, int version_id)
@@ -1167,15 +1235,6 @@ static int virtio_net_load(QEMUFile *f, void *opaque, int version_id)
error_report("virtio-net: saved image requires vnet_hdr=on");
return -1;
}
-
- if (n->has_vnet_hdr) {
- tap_set_offload(qemu_get_queue(n->nic)->peer,
- (vdev->guest_features >> VIRTIO_NET_F_GUEST_CSUM) & 1,
- (vdev->guest_features >> VIRTIO_NET_F_GUEST_TSO4) & 1,
- (vdev->guest_features >> VIRTIO_NET_F_GUEST_TSO6) & 1,
- (vdev->guest_features >> VIRTIO_NET_F_GUEST_ECN) & 1,
- (vdev->guest_features >> VIRTIO_NET_F_GUEST_UFO) & 1);
- }
}
if (version_id >= 9) {
@@ -1209,6 +1268,16 @@ static int virtio_net_load(QEMUFile *f, void *opaque, int version_id)
}
}
+ if ((1 << VIRTIO_NET_F_CTRL_GUEST_OFFLOADS) & vdev->guest_features) {
+ n->curr_guest_offloads = qemu_get_be64(f);
+ } else {
+ n->curr_guest_offloads = virtio_net_supported_guest_offloads(n);
+ }
+
+ if (peer_has_vnet_hdr(n)) {
+ virtio_net_apply_guest_offloads(n);
+ }
+
virtio_net_set_queues(n);
/* Find the first multicast entry in the saved MAC filter */
diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c
index 1a7e49c132..479113bd81 100644
--- a/hw/nvram/fw_cfg.c
+++ b/hw/nvram/fw_cfg.c
@@ -54,7 +54,7 @@ struct FWCfgState {
#define JPG_FILE 0
#define BMP_FILE 1
-static char *read_splashfile(char *filename, size_t *file_sizep,
+static char *read_splashfile(char *filename, gsize *file_sizep,
int *file_typep)
{
GError *err = NULL;
@@ -112,7 +112,7 @@ static void fw_cfg_bootsplash(FWCfgState *s)
const char *boot_splash_filename = NULL;
char *p;
char *filename, *file_data;
- size_t file_size;
+ gsize file_size;
int file_type;
const char *temp;
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index c96ac8131f..218ea23da8 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -43,8 +43,6 @@
#include "hw/ppc/xics.h"
#include "hw/pci/msi.h"
-#include "sysemu/kvm.h"
-#include "kvm_ppc.h"
#include "hw/pci/pci.h"
#include "exec/address-spaces.h"
diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
index f518aee216..8f0b7e8076 100644
--- a/hw/ppc/spapr_hcall.c
+++ b/hw/ppc/spapr_hcall.c
@@ -1,6 +1,5 @@
#include "sysemu/sysemu.h"
#include "cpu.h"
-#include "sysemu/sysemu.h"
#include "helper_regs.h"
#include "hw/ppc/spapr.h"
#include "mmu-hash64.h"
diff --git a/hw/timer/exynos4210_rtc.c b/hw/timer/exynos4210_rtc.c
index bceee44cb2..3ac77f9262 100644
--- a/hw/timer/exynos4210_rtc.c
+++ b/hw/timer/exynos4210_rtc.c
@@ -31,7 +31,6 @@
#include "hw/ptimer.h"
#include "hw/hw.h"
-#include "qemu/timer.h"
#include "sysemu/sysemu.h"
#include "hw/arm/exynos4210.h"
diff --git a/include/block/coroutine_int.h b/include/block/coroutine_int.h
index 17eb71e723..f133d65af8 100644
--- a/include/block/coroutine_int.h
+++ b/include/block/coroutine_int.h
@@ -38,6 +38,9 @@ struct Coroutine {
void *entry_arg;
Coroutine *caller;
QSLIST_ENTRY(Coroutine) pool_next;
+
+ /* Coroutines that should be woken up when we yield or terminate */
+ QTAILQ_HEAD(, Coroutine) co_queue_wakeup;
QTAILQ_ENTRY(Coroutine) co_queue_next;
};
@@ -45,5 +48,6 @@ Coroutine *qemu_coroutine_new(void);
void qemu_coroutine_delete(Coroutine *co);
CoroutineAction qemu_coroutine_switch(Coroutine *from, Coroutine *to,
CoroutineAction action);
+void coroutine_fn qemu_co_queue_run_restart(Coroutine *co);
#endif
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index 2bd7090248..663426cee8 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -7,7 +7,6 @@
#include "hw/isa/isa.h"
#include "hw/block/fdc.h"
#include "net/net.h"
-#include "exec/memory.h"
#include "hw/i386/ioapic.h"
/* PC-style peripherals (also used by other machines). */
@@ -217,6 +216,10 @@ int e820_add_entry(uint64_t, uint64_t, uint32_t);
.property = "vectors",\
/* DEV_NVECTORS_UNSPECIFIED as a uint32_t string */\
.value = stringify(0xFFFFFFFF),\
+ },{ \
+ .driver = "virtio-net-pci", \
+ .property = "ctrl_guest_offloads", \
+ .value = "off", \
},{\
.driver = "e1000",\
.property = "romfile",\
diff --git a/include/hw/virtio/virtio-net.h b/include/hw/virtio/virtio-net.h
index beeead7a1a..b315ac91a4 100644
--- a/include/hw/virtio/virtio-net.h
+++ b/include/hw/virtio/virtio-net.h
@@ -31,6 +31,8 @@
/* The feature bitmap for virtio net */
#define VIRTIO_NET_F_CSUM 0 /* Host handles pkts w/ partial csum */
#define VIRTIO_NET_F_GUEST_CSUM 1 /* Guest handles pkts w/ partial csum */
+#define VIRTIO_NET_F_CTRL_GUEST_OFFLOADS 2 /* Control channel offload
+ * configuration support */
#define VIRTIO_NET_F_MAC 5 /* Host has given MAC address. */
#define VIRTIO_NET_F_GSO 6 /* Host handles pkts w/ any GSO type */
#define VIRTIO_NET_F_GUEST_TSO4 7 /* Guest can handle TSOv4 in. */
@@ -190,6 +192,7 @@ typedef struct VirtIONet {
size_t config_size;
char *netclient_name;
char *netclient_type;
+ uint64_t curr_guest_offloads;
} VirtIONet;
#define VIRTIO_NET_CTRL_MAC 1
@@ -229,6 +232,15 @@ struct virtio_net_ctrl_mq {
#define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN 1
#define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX 0x8000
+/*
+ * Control network offloads
+ *
+ * Dynamic offloads are available with the
+ * VIRTIO_NET_F_CTRL_GUEST_OFFLOADS feature bit.
+ */
+#define VIRTIO_NET_CTRL_GUEST_OFFLOADS 5
+ #define VIRTIO_NET_CTRL_GUEST_OFFLOADS_SET 0
+
#define DEFINE_VIRTIO_NET_FEATURES(_state, _field) \
DEFINE_VIRTIO_COMMON_FEATURES(_state, _field), \
DEFINE_PROP_BIT("csum", _state, _field, VIRTIO_NET_F_CSUM, true), \
@@ -249,6 +261,7 @@ 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("ctrl_guest_offloads", _state, _field, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS, true), \
DEFINE_PROP_BIT("mq", _state, _field, VIRTIO_NET_F_MQ, false)
#define DEFINE_VIRTIO_NET_PROPERTIES(_state, _field) \
diff --git a/include/qapi/qmp/qlist.h b/include/qapi/qmp/qlist.h
index 382f04c3c4..6cc4831df3 100644
--- a/include/qapi/qmp/qlist.h
+++ b/include/qapi/qmp/qlist.h
@@ -15,7 +15,6 @@
#include "qapi/qmp/qobject.h"
#include "qemu/queue.h"
-#include "qemu/queue.h"
typedef struct QListEntry {
QObject *value;
diff --git a/include/qemu-common.h b/include/qemu-common.h
index b9057d18cf..cb82ef3d42 100644
--- a/include/qemu-common.h
+++ b/include/qemu-common.h
@@ -45,6 +45,7 @@
#if defined(__GLIBC__)
# include <pty.h>
#elif defined CONFIG_BSD
+# include <termios.h>
# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
# include <libutil.h>
# else
diff --git a/include/qemu/config-file.h b/include/qemu/config-file.h
index ccfccae2b4..ad4a9e5c3a 100644
--- a/include/qemu/config-file.h
+++ b/include/qemu/config-file.h
@@ -4,7 +4,6 @@
#include <stdio.h>
#include "qemu/option.h"
#include "qapi/error.h"
-#include "qemu/option.h"
QemuOptsList *qemu_find_opts(const char *group);
QemuOptsList *qemu_find_opts_err(const char *group, Error **errp);
diff --git a/linux-user/signal.c b/linux-user/signal.c
index 1055507224..5da8452b2a 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -2528,7 +2528,8 @@ setup_sigcontext(CPUMIPSState *regs, struct target_sigcontext *sc)
int err = 0;
int i;
- err |= __put_user(regs->active_tc.PC, &sc->sc_pc);
+ err |= __put_user(exception_resume_pc(regs), &sc->sc_pc);
+ regs->hflags &= ~MIPS_HFLAG_BMASK;
__put_user(0, &sc->sc_regs[0]);
for (i = 1; i < 32; ++i) {
@@ -2620,6 +2621,15 @@ get_sigframe(struct target_sigaction *ka, CPUMIPSState *regs, size_t frame_size)
return (sp - frame_size) & ~7;
}
+static void mips_set_hflags_isa_mode_from_pc(CPUMIPSState *env)
+{
+ if (env->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
+ env->hflags &= ~MIPS_HFLAG_M16;
+ env->hflags |= (env->active_tc.PC & 1) << MIPS_HFLAG_M16_SHIFT;
+ env->active_tc.PC &= ~(target_ulong) 1;
+ }
+}
+
# if defined(TARGET_ABI_MIPSO32)
/* compare linux/arch/mips/kernel/signal.c:setup_frame() */
static void setup_frame(int sig, struct target_sigaction * ka,
@@ -2662,6 +2672,7 @@ static void setup_frame(int sig, struct target_sigaction * ka,
* since it returns to userland using eret
* we cannot do this here, and we must set PC directly */
regs->active_tc.PC = regs->active_tc.gpr[25] = ka->_sa_handler;
+ mips_set_hflags_isa_mode_from_pc(regs);
unlock_user_struct(frame, frame_addr, 1);
return;
@@ -2709,6 +2720,7 @@ long do_sigreturn(CPUMIPSState *regs)
#endif
regs->active_tc.PC = regs->CP0_EPC;
+ mips_set_hflags_isa_mode_from_pc(regs);
/* I am not sure this is right, but it seems to work
* maybe a problem with nested signals ? */
regs->CP0_EPC = 0;
@@ -2771,6 +2783,7 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka,
* since it returns to userland using eret
* we cannot do this here, and we must set PC directly */
env->active_tc.PC = env->active_tc.gpr[25] = ka->_sa_handler;
+ mips_set_hflags_isa_mode_from_pc(env);
unlock_user_struct(frame, frame_addr, 1);
return;
@@ -2804,6 +2817,7 @@ long do_rt_sigreturn(CPUMIPSState *env)
goto badframe;
env->active_tc.PC = env->CP0_EPC;
+ mips_set_hflags_isa_mode_from_pc(env);
/* I am not sure this is right, but it seems to work
* maybe a problem with nested signals ? */
env->CP0_EPC = 0;
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 30e93bc0d0..1b3c0ed5f7 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -5050,10 +5050,10 @@ static int open_self_maps(void *cpu_env, int fd)
}
if (h2g_valid(min) && h2g_valid(max)) {
dprintf(fd, TARGET_ABI_FMT_lx "-" TARGET_ABI_FMT_lx
- " %c%c%c%c %08" PRIx64 " %02x:%02x %d%s%s\n",
+ " %c%c%c%c %08" PRIx64 " %02x:%02x %d %s%s\n",
h2g(min), h2g(max), flag_r, flag_w,
flag_x, flag_p, offset, dev_maj, dev_min, inode,
- path[0] ? " " : "", path);
+ path[0] ? " " : "", path);
}
}
diff --git a/monitor.c b/monitor.c
index 62aaebe660..6ce2a4e61b 100644
--- a/monitor.c
+++ b/monitor.c
@@ -63,7 +63,6 @@
#ifdef CONFIG_TRACE_SIMPLE
#include "trace/simple.h"
#endif
-#include "ui/qemu-spice.h"
#include "exec/memory.h"
#include "qmp-commands.h"
#include "hmp.h"
diff --git a/net/tap-bsd.c b/net/tap-bsd.c
index bcdb2682b5..f61d580963 100644
--- a/net/tap-bsd.c
+++ b/net/tap-bsd.c
@@ -44,7 +44,8 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr,
struct stat s;
#endif
-#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__)
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \
+ defined(__OpenBSD__) || defined(__APPLE__)
/* if no ifname is given, always start the search from tap0/tun0. */
int i;
char dname[100];
diff --git a/page_cache.c b/page_cache.c
index 938a79c9ea..a05db643cc 100644
--- a/page_cache.c
+++ b/page_cache.c
@@ -21,7 +21,6 @@
#include <sys/types.h>
#include <stdbool.h>
#include <glib.h>
-#include <strings.h>
#include "qemu-common.h"
#include "migration/page_cache.h"
diff --git a/qapi-schema-test.json b/qapi-schema-test.json
index 9eae3501d7..4434fa3961 100644
--- a/qapi-schema-test.json
+++ b/qapi-schema-test.json
@@ -32,6 +32,21 @@
{ 'union': 'UserDefUnion',
'data': { 'a' : 'UserDefA', 'b' : 'UserDefB' } }
+# for testing native lists
+{ 'union': 'UserDefNativeListUnion',
+ 'data': { 'integer': ['int'],
+ 's8': ['int8'],
+ 's16': ['int16'],
+ 's32': ['int32'],
+ 's64': ['int64'],
+ 'u8': ['uint8'],
+ 'u16': ['uint16'],
+ 'u32': ['uint32'],
+ 'u64': ['uint64'],
+ 'number': ['number'],
+ 'boolean': ['bool'],
+ 'string': ['str'] } }
+
# testing commands
{ 'command': 'user_def_cmd', 'data': {} }
{ 'command': 'user_def_cmd1', 'data': {'ud1a': 'UserDefOne'} }
diff --git a/qapi-schema.json b/qapi-schema.json
index 9302e7db01..ef1f657efb 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -1609,12 +1609,12 @@
'*mode': 'NewImageMode' } }
##
-# @BlockdevAction
+# @TransactionAction
#
# A discriminated record of operations that can be performed with
# @transaction.
##
-{ 'union': 'BlockdevAction',
+{ 'union': 'TransactionAction',
'data': {
'blockdev-snapshot-sync': 'BlockdevSnapshot'
} }
@@ -1622,25 +1622,24 @@
##
# @transaction
#
-# Atomically operate on a group of one or more block devices. If
-# any operation fails, then the entire set of actions will be
-# abandoned and the appropriate error returned. The only operation
-# supported is currently blockdev-snapshot-sync.
+# Executes a number of transactionable QMP commands atomically. If any
+# operation fails, then the entire set of actions will be abandoned and the
+# appropriate error returned.
#
# List of:
-# @BlockdevAction: information needed for the device snapshot
+# @TransactionAction: information needed for the respective operation
#
# Returns: nothing on success
-# If @device is not a valid block device, DeviceNotFound
+# Errors depend on the operations of the transaction
#
-# Note: The transaction aborts on the first failure. Therefore, there will
-# be only one device or snapshot file returned in an error condition, and
+# Note: The transaction aborts on the first failure. Therefore, there will be
+# information on only one failed operation returned in an error condition, and
# subsequent actions will not have been attempted.
#
# Since 1.1
##
{ 'command': 'transaction',
- 'data': { 'actions': [ 'BlockdevAction' ] } }
+ 'data': { 'actions': [ 'TransactionAction' ] } }
##
# @blockdev-snapshot-sync
@@ -3286,7 +3285,7 @@
'*rows' : 'int' } }
##
-# @ChardevRingbuf:
+# @ChardevMemory:
#
# Configuration info for memory chardevs
#
@@ -3294,7 +3293,7 @@
#
# Since: 1.5
##
-{ 'type': 'ChardevRingbuf', 'data': { '*size' : 'int' } }
+{ 'type': 'ChardevMemory', 'data': { '*size' : 'int' } }
##
# @ChardevBackend:
@@ -3321,7 +3320,7 @@
'spicevmc' : 'ChardevSpiceChannel',
'spiceport' : 'ChardevSpicePort',
'vc' : 'ChardevVC',
- 'memory' : 'ChardevRingbuf' } }
+ 'memory' : 'ChardevMemory' } }
##
# @ChardevReturn:
diff --git a/qemu-char.c b/qemu-char.c
index cff2896065..4f8382e540 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -2875,8 +2875,8 @@ static void ringbuf_chr_close(struct CharDriverState *chr)
chr->opaque = NULL;
}
-static CharDriverState *qemu_chr_open_ringbuf(ChardevRingbuf *opts,
- Error **errp)
+static CharDriverState *qemu_chr_open_memory(ChardevMemory *opts,
+ Error **errp)
{
CharDriverState *chr;
RingBufCharDriver *d;
@@ -2888,7 +2888,7 @@ static CharDriverState *qemu_chr_open_ringbuf(ChardevRingbuf *opts,
/* The size must be power of 2 */
if (d->size & (d->size - 1)) {
- error_setg(errp, "size of ringbuf chardev must be power of two");
+ error_setg(errp, "size of memory chardev must be power of two");
goto fail;
}
@@ -2920,7 +2920,7 @@ void qmp_ringbuf_write(const char *device, const char *data,
CharDriverState *chr;
const uint8_t *write_data;
int ret;
- size_t write_count;
+ gsize write_count;
chr = qemu_chr_find(device);
if (!chr) {
@@ -3190,12 +3190,12 @@ static void qemu_chr_parse_pipe(QemuOpts *opts, ChardevBackend *backend,
backend->pipe->device = g_strdup(device);
}
-static void qemu_chr_parse_ringbuf(QemuOpts *opts, ChardevBackend *backend,
- Error **errp)
+static void qemu_chr_parse_memory(QemuOpts *opts, ChardevBackend *backend,
+ Error **errp)
{
int val;
- backend->memory = g_new0(ChardevRingbuf, 1);
+ backend->memory = g_new0(ChardevMemory, 1);
val = qemu_opt_get_number(opts, "size", 0);
if (val != 0) {
@@ -3276,6 +3276,7 @@ CharDriverState *qemu_chr_new_from_opts(QemuOpts *opts,
ChardevReturn *ret = NULL;
const char *id = qemu_opts_id(opts);
const char *bid = NULL;
+ char *filename = g_strdup(qemu_opt_get(opts, "backend"));
if (qemu_opt_get_bool(opts, "mux", 0)) {
bid = g_strdup_printf("%s-base", id);
@@ -3308,6 +3309,7 @@ CharDriverState *qemu_chr_new_from_opts(QemuOpts *opts,
}
chr = qemu_chr_find(id);
+ chr->filename = filename;
qapi_out:
qapi_free_ChardevBackend(backend);
@@ -3787,7 +3789,7 @@ ChardevReturn *qmp_chardev_add(const char *id, ChardevBackend *backend,
chr = vc_init(backend->vc);
break;
case CHARDEV_BACKEND_KIND_MEMORY:
- chr = qemu_chr_open_ringbuf(backend->memory, errp);
+ chr = qemu_chr_open_memory(backend->memory, errp);
break;
default:
error_setg(errp, "unknown chardev backend (%d)", backend->kind);
@@ -3832,7 +3834,7 @@ static void register_types(void)
register_char_driver("socket", qemu_chr_open_socket);
register_char_driver("udp", qemu_chr_open_udp);
register_char_driver_qapi("memory", CHARDEV_BACKEND_KIND_MEMORY,
- qemu_chr_parse_ringbuf);
+ qemu_chr_parse_memory);
register_char_driver_qapi("file", CHARDEV_BACKEND_KIND_FILE,
qemu_chr_parse_file_out);
register_char_driver_qapi("stdio", CHARDEV_BACKEND_KIND_STDIO,
diff --git a/qemu-coroutine-lock.c b/qemu-coroutine-lock.c
index 86efe1f86a..d9fea4989d 100644
--- a/qemu-coroutine-lock.c
+++ b/qemu-coroutine-lock.c
@@ -26,39 +26,11 @@
#include "block/coroutine.h"
#include "block/coroutine_int.h"
#include "qemu/queue.h"
-#include "block/aio.h"
#include "trace.h"
-/* Coroutines are awoken from a BH to allow the current coroutine to complete
- * its flow of execution. The BH may run after the CoQueue has been destroyed,
- * so keep BH data in a separate heap-allocated struct.
- */
-typedef struct {
- QEMUBH *bh;
- QTAILQ_HEAD(, Coroutine) entries;
-} CoQueueNextData;
-
-static void qemu_co_queue_next_bh(void *opaque)
-{
- CoQueueNextData *data = opaque;
- Coroutine *next;
-
- trace_qemu_co_queue_next_bh();
- while ((next = QTAILQ_FIRST(&data->entries))) {
- QTAILQ_REMOVE(&data->entries, next, co_queue_next);
- qemu_coroutine_enter(next, NULL);
- }
-
- qemu_bh_delete(data->bh);
- g_slice_free(CoQueueNextData, data);
-}
-
void qemu_co_queue_init(CoQueue *queue)
{
QTAILQ_INIT(&queue->entries);
-
- /* This will be exposed to callers once there are multiple AioContexts */
- queue->ctx = qemu_get_aio_context();
}
void coroutine_fn qemu_co_queue_wait(CoQueue *queue)
@@ -77,23 +49,37 @@ void coroutine_fn qemu_co_queue_wait_insert_head(CoQueue *queue)
assert(qemu_in_coroutine());
}
+/**
+ * qemu_co_queue_run_restart:
+ *
+ * Enter each coroutine that was previously marked for restart by
+ * qemu_co_queue_next() or qemu_co_queue_restart_all(). This function is
+ * invoked by the core coroutine code when the current coroutine yields or
+ * terminates.
+ */
+void qemu_co_queue_run_restart(Coroutine *co)
+{
+ Coroutine *next;
+
+ trace_qemu_co_queue_run_restart(co);
+ while ((next = QTAILQ_FIRST(&co->co_queue_wakeup))) {
+ QTAILQ_REMOVE(&co->co_queue_wakeup, next, co_queue_next);
+ qemu_coroutine_enter(next, NULL);
+ }
+}
+
static bool qemu_co_queue_do_restart(CoQueue *queue, bool single)
{
+ Coroutine *self = qemu_coroutine_self();
Coroutine *next;
- CoQueueNextData *data;
if (QTAILQ_EMPTY(&queue->entries)) {
return false;
}
- data = g_slice_new(CoQueueNextData);
- data->bh = aio_bh_new(queue->ctx, qemu_co_queue_next_bh, data);
- QTAILQ_INIT(&data->entries);
- qemu_bh_schedule(data->bh);
-
while ((next = QTAILQ_FIRST(&queue->entries)) != NULL) {
QTAILQ_REMOVE(&queue->entries, next, co_queue_next);
- QTAILQ_INSERT_TAIL(&data->entries, next, co_queue_next);
+ QTAILQ_INSERT_TAIL(&self->co_queue_wakeup, next, co_queue_next);
trace_qemu_co_queue_next(next);
if (single) {
break;
diff --git a/qemu-coroutine.c b/qemu-coroutine.c
index 25a14c605d..423430d3a0 100644
--- a/qemu-coroutine.c
+++ b/qemu-coroutine.c
@@ -14,6 +14,7 @@
#include "trace.h"
#include "qemu-common.h"
+#include "qemu/thread.h"
#include "block/coroutine.h"
#include "block/coroutine_int.h"
@@ -23,6 +24,7 @@ enum {
};
/** Free list to speed up creation */
+static QemuMutex pool_lock;
static QSLIST_HEAD(, Coroutine) pool = QSLIST_HEAD_INITIALIZER(pool);
static unsigned int pool_size;
@@ -30,31 +32,44 @@ Coroutine *qemu_coroutine_create(CoroutineEntry *entry)
{
Coroutine *co;
+ qemu_mutex_lock(&pool_lock);
co = QSLIST_FIRST(&pool);
if (co) {
QSLIST_REMOVE_HEAD(&pool, pool_next);
pool_size--;
- } else {
+ }
+ qemu_mutex_unlock(&pool_lock);
+
+ if (!co) {
co = qemu_coroutine_new();
}
co->entry = entry;
+ QTAILQ_INIT(&co->co_queue_wakeup);
return co;
}
static void coroutine_delete(Coroutine *co)
{
+ qemu_mutex_lock(&pool_lock);
if (pool_size < POOL_MAX_SIZE) {
QSLIST_INSERT_HEAD(&pool, co, pool_next);
co->caller = NULL;
pool_size++;
+ qemu_mutex_unlock(&pool_lock);
return;
}
+ qemu_mutex_unlock(&pool_lock);
qemu_coroutine_delete(co);
}
-static void __attribute__((destructor)) coroutine_cleanup(void)
+static void __attribute__((constructor)) coroutine_pool_init(void)
+{
+ qemu_mutex_init(&pool_lock);
+}
+
+static void __attribute__((destructor)) coroutine_pool_cleanup(void)
{
Coroutine *co;
Coroutine *tmp;
@@ -63,6 +78,8 @@ static void __attribute__((destructor)) coroutine_cleanup(void)
QSLIST_REMOVE_HEAD(&pool, pool_next);
qemu_coroutine_delete(co);
}
+
+ qemu_mutex_destroy(&pool_lock);
}
static void coroutine_swap(Coroutine *from, Coroutine *to)
@@ -71,6 +88,8 @@ static void coroutine_swap(Coroutine *from, Coroutine *to)
ret = qemu_coroutine_switch(from, to, COROUTINE_YIELD);
+ qemu_co_queue_run_restart(to);
+
switch (ret) {
case COROUTINE_YIELD:
return;
diff --git a/qemu-io.c b/qemu-io.c
index 475a8bd034..5e6680b247 100644
--- a/qemu-io.c
+++ b/qemu-io.c
@@ -1635,12 +1635,43 @@ static const cmdinfo_t alloc_cmd = {
.oneline = "checks if a sector is present in the file",
};
+
+static int map_is_allocated(int64_t sector_num, int64_t nb_sectors, int64_t *pnum)
+{
+ int num, num_checked;
+ int ret, firstret;
+
+ num_checked = MIN(nb_sectors, INT_MAX);
+ ret = bdrv_is_allocated(bs, sector_num, num_checked, &num);
+ if (ret < 0) {
+ return ret;
+ }
+
+ firstret = ret;
+ *pnum = num;
+
+ while (nb_sectors > 0 && ret == firstret) {
+ sector_num += num;
+ nb_sectors -= num;
+
+ num_checked = MIN(nb_sectors, INT_MAX);
+ ret = bdrv_is_allocated(bs, sector_num, num_checked, &num);
+ if (ret == firstret) {
+ *pnum += num;
+ } else {
+ break;
+ }
+ }
+
+ return firstret;
+}
+
static int map_f(int argc, char **argv)
{
int64_t offset;
int64_t nb_sectors;
char s1[64];
- int num, num_checked;
+ int64_t num;
int ret;
const char *retstr;
@@ -1648,12 +1679,17 @@ static int map_f(int argc, char **argv)
nb_sectors = bs->total_sectors;
do {
- num_checked = MIN(nb_sectors, INT_MAX);
- ret = bdrv_is_allocated(bs, offset, num_checked, &num);
+ ret = map_is_allocated(offset, nb_sectors, &num);
+ if (ret < 0) {
+ error_report("Failed to get allocation status: %s", strerror(-ret));
+ return 0;
+ }
+
retstr = ret ? " allocated" : "not allocated";
cvtstr(offset << 9ULL, s1, sizeof(s1));
- printf("[% 24" PRId64 "] % 8d/% 8d sectors %s at offset %s (%d)\n",
- offset << 9ULL, num, num_checked, retstr, s1, ret);
+ printf("[% 24" PRId64 "] % 8" PRId64 "/% 8" PRId64 " sectors %s "
+ "at offset %s (%d)\n",
+ offset << 9ULL, num, nb_sectors, retstr, s1, ret);
offset += num;
nb_sectors -= num;
diff --git a/qemu-options.hx b/qemu-options.hx
index fb62b75ccb..bf94862b58 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -1779,7 +1779,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 ringbuf,id=id[,size=size]\n"
+ "-chardev memory,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
@@ -1817,7 +1817,7 @@ Backend is one of:
@option{udp},
@option{msmouse},
@option{vc},
-@option{ringbuf},
+@option{memory},
@option{file},
@option{pipe},
@option{console},
@@ -1926,7 +1926,7 @@ 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 ringbuf ,id=@var{id} [,size=@var{size}]
+@item -chardev memory ,id=@var{id} [,size=@var{size}]
Create a ring buffer with fixed size @option{size}.
@var{size} must be a power of two, and defaults to @code{64K}).
@@ -2528,6 +2528,7 @@ Redirect the monitor to host device @var{dev} (same devices as the
serial port).
The default device is @code{vc} in graphical mode and @code{stdio} in
non graphical mode.
+Use @code{-monitor none} to disable the default monitor.
ETEXI
DEF("qmp", HAS_ARG, QEMU_OPTION_qmp, \
"-qmp dev like -monitor but opens in 'control' mode\n",
diff --git a/qobject/json-parser.c b/qobject/json-parser.c
index 05279c11eb..e7947b340c 100644
--- a/qobject/json-parser.c
+++ b/qobject/json-parser.c
@@ -640,9 +640,29 @@ static QObject *parse_literal(JSONParserContext *ctxt)
case JSON_STRING:
obj = QOBJECT(qstring_from_escaped_str(ctxt, token));
break;
- case JSON_INTEGER:
- obj = QOBJECT(qint_from_int(strtoll(token_get_value(token), NULL, 10)));
- break;
+ case JSON_INTEGER: {
+ /* A possibility exists that this is a whole-valued float where the
+ * fractional part was left out due to being 0 (.0). It's not a big
+ * deal to treat these as ints in the parser, so long as users of the
+ * resulting QObject know to expect a QInt in place of a QFloat in
+ * cases like these.
+ *
+ * However, in some cases these values will overflow/underflow a
+ * QInt/int64 container, thus we should assume these are to be handled
+ * as QFloats/doubles rather than silently changing their values.
+ *
+ * strtoll() indicates these instances by setting errno to ERANGE
+ */
+ int64_t value;
+
+ errno = 0; /* strtoll doesn't set errno on success */
+ value = strtoll(token_get_value(token), NULL, 10);
+ if (errno != ERANGE) {
+ obj = QOBJECT(qint_from_int(value));
+ break;
+ }
+ /* fall through to JSON_FLOAT */
+ }
case JSON_FLOAT:
/* FIXME dependent on locale */
obj = QOBJECT(qfloat_from_double(strtod(token_get_value(token), NULL)));
diff --git a/qom/object.c b/qom/object.c
index ec88231fa9..803b94bb66 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -442,7 +442,7 @@ Object *object_dynamic_cast_assert(Object *obj, const char *typename,
int i;
Object *inst;
- for (i = 0; i < OBJECT_CLASS_CAST_CACHE; i++) {
+ for (i = 0; obj && i < OBJECT_CLASS_CAST_CACHE; i++) {
if (obj->class->cast_cache[i] == typename) {
goto out;
}
@@ -458,7 +458,7 @@ Object *object_dynamic_cast_assert(Object *obj, const char *typename,
assert(obj == inst);
- if (obj == inst) {
+ if (obj && obj == inst) {
for (i = 1; i < OBJECT_CLASS_CAST_CACHE; i++) {
obj->class->cast_cache[i - 1] = obj->class->cast_cache[i];
}
diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py
index 9e19920970..fd42d71da1 100644
--- a/scripts/qapi-types.py
+++ b/scripts/qapi-types.py
@@ -16,8 +16,21 @@ import os
import getopt
import errno
-def generate_fwd_struct(name, members):
+def generate_fwd_struct(name, members, builtin_type=False):
+ if builtin_type:
+ return mcgen('''
+
+typedef struct %(name)sList
+{
+ %(type)s value;
+ struct %(name)sList *next;
+} %(name)sList;
+''',
+ type=c_type(name),
+ name=name)
+
return mcgen('''
+
typedef struct %(name)s %(name)s;
typedef struct %(name)sList
@@ -164,6 +177,7 @@ void qapi_free_%(type)s(%(c_type)s obj);
def generate_type_cleanup(name):
ret = mcgen('''
+
void qapi_free_%(type)s(%(c_type)s obj)
{
QapiDeallocVisitor *md;
@@ -184,8 +198,9 @@ void qapi_free_%(type)s(%(c_type)s obj)
try:
- opts, args = getopt.gnu_getopt(sys.argv[1:], "chp:o:",
- ["source", "header", "prefix=", "output-dir="])
+ opts, args = getopt.gnu_getopt(sys.argv[1:], "chbp:o:",
+ ["source", "header", "builtins",
+ "prefix=", "output-dir="])
except getopt.GetoptError, err:
print str(err)
sys.exit(1)
@@ -197,6 +212,7 @@ h_file = 'qapi-types.h'
do_c = False
do_h = False
+do_builtins = False
for o, a in opts:
if o in ("-p", "--prefix"):
@@ -207,6 +223,8 @@ for o, a in opts:
do_c = True
elif o in ("-h", "--header"):
do_h = True
+ elif o in ("-b", "--builtins"):
+ do_builtins = True
if not do_c and not do_h:
do_c = True
@@ -282,6 +300,11 @@ fdecl.write(mcgen('''
exprs = parse_schema(sys.stdin)
exprs = filter(lambda expr: not expr.has_key('gen'), exprs)
+fdecl.write(guardstart("QAPI_TYPES_BUILTIN_STRUCT_DECL"))
+for typename in builtin_types:
+ fdecl.write(generate_fwd_struct(typename, None, builtin_type=True))
+fdecl.write(guardend("QAPI_TYPES_BUILTIN_STRUCT_DECL"))
+
for expr in exprs:
ret = "\n"
if expr.has_key('type'):
@@ -298,6 +321,22 @@ for expr in exprs:
continue
fdecl.write(ret)
+# to avoid header dependency hell, we always generate declarations
+# for built-in types in our header files and simply guard them
+fdecl.write(guardstart("QAPI_TYPES_BUILTIN_CLEANUP_DECL"))
+for typename in builtin_types:
+ fdecl.write(generate_type_cleanup_decl(typename + "List"))
+fdecl.write(guardend("QAPI_TYPES_BUILTIN_CLEANUP_DECL"))
+
+# ...this doesn't work for cases where we link in multiple objects that
+# have the functions defined, so we use -b option to provide control
+# over these cases
+if do_builtins:
+ fdef.write(guardstart("QAPI_TYPES_BUILTIN_CLEANUP_DEF"))
+ for typename in builtin_types:
+ fdef.write(generate_type_cleanup(typename + "List"))
+ fdef.write(guardend("QAPI_TYPES_BUILTIN_CLEANUP_DEF"))
+
for expr in exprs:
ret = "\n"
if expr.has_key('type'):
diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
index a276540a18..6cac05acd5 100644
--- a/scripts/qapi-visit.py
+++ b/scripts/qapi-visit.py
@@ -174,7 +174,7 @@ void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **
''',
abbrev = de_camel_case(name).upper(),
enum = c_fun(de_camel_case(key),False).upper(),
- c_type=members[key],
+ c_type=type_name(members[key]),
c_name=c_fun(key))
ret += mcgen('''
@@ -202,12 +202,14 @@ void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **
return ret
-def generate_declaration(name, members, genlist=True):
- ret = mcgen('''
+def generate_declaration(name, members, genlist=True, builtin_type=False):
+ ret = ""
+ if not builtin_type:
+ ret += mcgen('''
void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **errp);
''',
- name=name)
+ name=name)
if genlist:
ret += mcgen('''
@@ -235,8 +237,9 @@ void visit_type_%(name)s(Visitor *m, %(name)s * obj, const char *name, Error **e
name=name)
try:
- opts, args = getopt.gnu_getopt(sys.argv[1:], "chp:o:",
- ["source", "header", "prefix=", "output-dir="])
+ opts, args = getopt.gnu_getopt(sys.argv[1:], "chbp:o:",
+ ["source", "header", "builtins", "prefix=",
+ "output-dir="])
except getopt.GetoptError, err:
print str(err)
sys.exit(1)
@@ -248,6 +251,7 @@ h_file = 'qapi-visit.h'
do_c = False
do_h = False
+do_builtins = False
for o, a in opts:
if o in ("-p", "--prefix"):
@@ -258,6 +262,8 @@ for o, a in opts:
do_c = True
elif o in ("-h", "--header"):
do_h = True
+ elif o in ("-b", "--builtins"):
+ do_builtins = True
if not do_c and not do_h:
do_c = True
@@ -324,11 +330,29 @@ fdecl.write(mcgen('''
#include "qapi/visitor.h"
#include "%(prefix)sqapi-types.h"
+
''',
prefix=prefix, guard=guardname(h_file)))
exprs = parse_schema(sys.stdin)
+# to avoid header dependency hell, we always generate declarations
+# for built-in types in our header files and simply guard them
+fdecl.write(guardstart("QAPI_VISIT_BUILTIN_VISITOR_DECL"))
+for typename in builtin_types:
+ fdecl.write(generate_declaration(typename, None, genlist=True,
+ builtin_type=True))
+fdecl.write(guardend("QAPI_VISIT_BUILTIN_VISITOR_DECL"))
+
+# ...this doesn't work for cases where we link in multiple objects that
+# have the functions defined, so we use -b option to provide control
+# over these cases
+if do_builtins:
+ fdef.write(guardstart("QAPI_VISIT_BUILTIN_VISITOR_DEF"))
+ for typename in builtin_types:
+ fdef.write(generate_visit_list(typename, None))
+ fdef.write(guardend("QAPI_VISIT_BUILTIN_VISITOR_DEF"))
+
for expr in exprs:
if expr.has_key('type'):
ret = generate_visit_struct(expr['type'], expr['data'])
diff --git a/scripts/qapi.py b/scripts/qapi.py
index afc5f32aeb..02ad668ca3 100644
--- a/scripts/qapi.py
+++ b/scripts/qapi.py
@@ -11,6 +11,12 @@
from ordereddict import OrderedDict
+builtin_types = [
+ 'str', 'int', 'number', 'bool',
+ 'int8', 'int16', 'int32', 'int64',
+ 'uint8', 'uint16', 'uint32', 'uint64'
+]
+
def tokenize(data):
while len(data):
ch = data[0]
@@ -242,3 +248,20 @@ def guardname(filename):
for substr in [".", " ", "-"]:
guard = guard.replace(substr, "_")
return guard.upper() + '_H'
+
+def guardstart(name):
+ return mcgen('''
+
+#ifndef %(name)s
+#define %(name)s
+
+''',
+ name=guardname(name))
+
+def guardend(name):
+ return mcgen('''
+
+#endif /* %(name)s */
+
+''',
+ name=guardname(name))
diff --git a/slirp/misc.c b/slirp/misc.c
index 8ecced547f..0bcc481939 100644
--- a/slirp/misc.c
+++ b/slirp/misc.c
@@ -242,8 +242,6 @@ strdup(str)
}
#endif
-#include "monitor/monitor.h"
-
void lprint(const char *format, ...)
{
va_list args;
diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index cedf03df43..6e761e03b6 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -668,6 +668,7 @@ void r4k_invalidate_tlb (CPUMIPSState *env, int idx, int use_extra);
hwaddr cpu_mips_translate_address (CPUMIPSState *env, target_ulong address,
int rw);
#endif
+target_ulong exception_resume_pc (CPUMIPSState *env);
static inline void cpu_get_tb_cpu_state(CPUMIPSState *env, target_ulong *pc,
target_ulong *cs_base, int *flags)
diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c
index 918a898699..4116de93c3 100644
--- a/target-mips/dsp_helper.c
+++ b/target-mips/dsp_helper.c
@@ -2902,13 +2902,13 @@ target_ulong helper_bitrev(target_ulong rt)
return (target_ulong)rd;
}
-#define BIT_INSV(name, posfilter, sizefilter, ret_type) \
+#define BIT_INSV(name, posfilter, ret_type) \
target_ulong helper_##name(CPUMIPSState *env, target_ulong rs, \
target_ulong rt) \
{ \
uint32_t pos, size, msb, lsb; \
- target_ulong filter; \
- target_ulong temp, temprs, temprt; \
+ uint32_t const sizefilter = 0x3F; \
+ target_ulong temp; \
target_ulong dspc; \
\
dspc = env->active_tc.DSPControl; \
@@ -2923,18 +2923,14 @@ target_ulong helper_##name(CPUMIPSState *env, target_ulong rs, \
return rt; \
} \
\
- filter = ((int64_t)0x01 << size) - 1; \
- filter = filter << pos; \
- temprs = (rs << pos) & filter; \
- temprt = rt & ~filter; \
- temp = temprs | temprt; \
+ temp = deposit64(rt, pos, size, rs); \
\
return (target_long)(ret_type)temp; \
}
-BIT_INSV(insv, 0x1F, 0x3F, int32_t);
+BIT_INSV(insv, 0x1F, int32_t);
#ifdef TARGET_MIPS64
-BIT_INSV(dinsv, 0x7F, 0x3F, target_long);
+BIT_INSV(dinsv, 0x7F, target_long);
#endif
#undef BIT_INSV
diff --git a/target-mips/helper.c b/target-mips/helper.c
index 3a54acf706..36929ddee7 100644
--- a/target-mips/helper.c
+++ b/target-mips/helper.c
@@ -366,8 +366,7 @@ static const char * const excp_names[EXCP_LAST + 1] = {
[EXCP_CACHE] = "cache error",
};
-#if !defined(CONFIG_USER_ONLY)
-static target_ulong exception_resume_pc (CPUMIPSState *env)
+target_ulong exception_resume_pc (CPUMIPSState *env)
{
target_ulong bad_pc;
target_ulong isa_mode;
@@ -383,6 +382,7 @@ static target_ulong exception_resume_pc (CPUMIPSState *env)
return bad_pc;
}
+#if !defined(CONFIG_USER_ONLY)
static void set_hflags_for_handler (CPUMIPSState *env)
{
/* Exception handlers are entered in 32-bit mode. */
diff --git a/target-moxie/helper.c b/target-moxie/helper.c
index 6e0ac2aa2a..5cfe889ad4 100644
--- a/target-moxie/helper.c
+++ b/target-moxie/helper.c
@@ -116,7 +116,7 @@ int cpu_moxie_handle_mmu_fault(CPUMoxieState *env, target_ulong address,
return 1;
}
-target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
+hwaddr cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
{
return addr;
}
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index 725071e6a7..3ab2946cfb 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -30,8 +30,6 @@
#include "cpu.h"
#include "sysemu/cpus.h"
#include "sysemu/device_tree.h"
-#include "hw/sysbus.h"
-#include "hw/ppc/spapr.h"
#include "mmu-hash64.h"
#include "hw/sysbus.h"
diff --git a/tests/qemu-iotests/054 b/tests/qemu-iotests/054
new file mode 100755
index 0000000000..b36042958c
--- /dev/null
+++ b/tests/qemu-iotests/054
@@ -0,0 +1,58 @@
+#!/bin/bash
+#
+# Test huge qcow2 images
+#
+# Copyright (C) 2013 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+# creator
+owner=kwolf@redhat.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1 # failure is the default!
+
+_cleanup()
+{
+ _cleanup_test_img
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+_supported_fmt qcow2
+_supported_proto generic
+_supported_os Linux
+
+echo
+echo "creating too large image (1 EB)"
+_make_test_img $((1024*1024))T
+
+echo
+echo "creating too large image (1 EB) using qcow2.py"
+_make_test_img 4G
+./qcow2.py $TEST_IMG set-header size $((1024 ** 6))
+_check_test_img
+
+# success, all done
+echo "*** done"
+rm -f $seq.full
+status=0
diff --git a/tests/qemu-iotests/054.out b/tests/qemu-iotests/054.out
new file mode 100644
index 0000000000..0b2fe301ea
--- /dev/null
+++ b/tests/qemu-iotests/054.out
@@ -0,0 +1,10 @@
+QA output created by 054
+
+creating too large image (1 EB)
+qemu-img: The image size is too large for file format 'qcow2'
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1152921504606846976
+
+creating too large image (1 EB) using qcow2.py
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4294967296
+qemu-img: Could not open 'TEST_DIR/t.qcow2': File too large
+*** done
diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc
index 31eb62b604..e9ba3586b5 100644
--- a/tests/qemu-iotests/common.rc
+++ b/tests/qemu-iotests/common.rc
@@ -167,7 +167,7 @@ _cleanup_test_img()
_check_test_img()
{
- $QEMU_IMG check "$@" -f $IMGFMT $TEST_IMG 2>&1 | \
+ $QEMU_IMG check "$@" -f $IMGFMT $TEST_IMG 2>&1 | _filter_testdir | \
sed -e '/allocated.*fragmented.*compressed clusters/d' \
-e 's/qemu-img: This image format does not support checks/No errors were found on the image./' \
-e '/Image end offset: [0-9]\+/d'
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
index bf944d9123..387b050987 100644
--- a/tests/qemu-iotests/group
+++ b/tests/qemu-iotests/group
@@ -60,3 +60,4 @@
#051 rw auto
052 rw auto backing
053 rw auto
+054 rw auto
diff --git a/tests/qemu-iotests/qcow2.py b/tests/qemu-iotests/qcow2.py
index fecf5b9a59..44a2b45641 100755
--- a/tests/qemu-iotests/qcow2.py
+++ b/tests/qemu-iotests/qcow2.py
@@ -149,6 +149,22 @@ def cmd_dump_header(fd):
h.dump()
h.dump_extensions()
+def cmd_set_header(fd, name, value):
+ try:
+ value = int(value, 0)
+ except:
+ print "'%s' is not a valid number" % value
+ sys.exit(1)
+
+ fields = (field[2] for field in QcowHeader.fields)
+ if not name in fields:
+ print "'%s' is not a known header field" % name
+ sys.exit(1)
+
+ h = QcowHeader(fd)
+ h.__dict__[name] = value
+ h.update(fd)
+
def cmd_add_header_ext(fd, magic, data):
try:
magic = int(magic, 0)
@@ -205,6 +221,7 @@ def cmd_set_feature_bit(fd, group, bit):
cmds = [
[ 'dump-header', cmd_dump_header, 0, 'Dump image header and header extensions' ],
+ [ 'set-header', cmd_set_header, 2, 'Set a field in the header'],
[ 'add-header-ext', cmd_add_header_ext, 2, 'Add a header extension' ],
[ 'del-header-ext', cmd_del_header_ext, 1, 'Delete a header extension' ],
[ 'set-feature-bit', cmd_set_feature_bit, 2, 'Set a feature bit'],
diff --git a/tests/tcg/linux-test.c b/tests/tcg/linux-test.c
index 83cb32ddb9..1c6c01318e 100644
--- a/tests/tcg/linux-test.c
+++ b/tests/tcg/linux-test.c
@@ -39,7 +39,6 @@
#include <dirent.h>
#include <setjmp.h>
#include <sys/shm.h>
-#include <sched.h>
#define TESTPATH "/tmp/linux-test.tmp"
#define TESTPORT 7654
diff --git a/tests/test-qmp-input-visitor.c b/tests/test-qmp-input-visitor.c
index 955a4c0b0a..2741eef3fa 100644
--- a/tests/test-qmp-input-visitor.c
+++ b/tests/test-qmp-input-visitor.c
@@ -61,6 +61,31 @@ Visitor *visitor_input_test_init(TestInputVisitorData *data,
return v;
}
+/* similar to visitor_input_test_init(), but does not expect a string
+ * literal/format json_string argument and so can be used for
+ * programatically generated strings (and we can't pass in programatically
+ * generated strings via %s format parameters since qobject_from_jsonv()
+ * will wrap those in double-quotes and treat the entire object as a
+ * string)
+ */
+static Visitor *visitor_input_test_init_raw(TestInputVisitorData *data,
+ const char *json_string)
+{
+ Visitor *v;
+
+ data->obj = qobject_from_json(json_string);
+
+ g_assert(data->obj != NULL);
+
+ data->qiv = qmp_input_visitor_new(data->obj);
+ g_assert(data->qiv != NULL);
+
+ v = qmp_input_get_visitor(data->qiv);
+ g_assert(v != NULL);
+
+ return v;
+}
+
static void test_visitor_in_int(TestInputVisitorData *data,
const void *unused)
{
@@ -75,6 +100,24 @@ static void test_visitor_in_int(TestInputVisitorData *data,
g_assert_cmpint(res, ==, value);
}
+static void test_visitor_in_int_overflow(TestInputVisitorData *data,
+ const void *unused)
+{
+ int64_t res = 0;
+ Error *errp = NULL;
+ Visitor *v;
+
+ /* this will overflow a Qint/int64, so should be deserialized into
+ * a QFloat/double field instead, leading to an error if we pass it
+ * to visit_type_int. confirm this.
+ */
+ v = visitor_input_test_init(data, "%f", DBL_MAX);
+
+ visit_type_int(v, &res, NULL, &errp);
+ g_assert(error_is_set(&errp));
+ error_free(errp);
+}
+
static void test_visitor_in_bool(TestInputVisitorData *data,
const void *unused)
{
@@ -259,6 +302,287 @@ static void test_visitor_in_union(TestInputVisitorData *data,
qapi_free_UserDefUnion(tmp);
}
+static void test_native_list_integer_helper(TestInputVisitorData *data,
+ const void *unused,
+ UserDefNativeListUnionKind kind)
+{
+ UserDefNativeListUnion *cvalue = NULL;
+ Error *err = NULL;
+ Visitor *v;
+ GString *gstr_list = g_string_new("");
+ GString *gstr_union = g_string_new("");
+ int i;
+
+ for (i = 0; i < 32; i++) {
+ g_string_append_printf(gstr_list, "%d", i);
+ if (i != 31) {
+ g_string_append(gstr_list, ", ");
+ }
+ }
+ g_string_append_printf(gstr_union, "{ 'type': '%s', 'data': [ %s ] }",
+ UserDefNativeListUnionKind_lookup[kind],
+ gstr_list->str);
+ v = visitor_input_test_init_raw(data, gstr_union->str);
+
+ visit_type_UserDefNativeListUnion(v, &cvalue, NULL, &err);
+ g_assert(err == NULL);
+ g_assert(cvalue != NULL);
+ g_assert_cmpint(cvalue->kind, ==, kind);
+
+ switch (kind) {
+ case USER_DEF_NATIVE_LIST_UNION_KIND_INTEGER: {
+ intList *elem = NULL;
+ for (i = 0, elem = cvalue->integer; elem; elem = elem->next, i++) {
+ g_assert_cmpint(elem->value, ==, i);
+ }
+ break;
+ }
+ case USER_DEF_NATIVE_LIST_UNION_KIND_S8: {
+ int8List *elem = NULL;
+ for (i = 0, elem = cvalue->s8; elem; elem = elem->next, i++) {
+ g_assert_cmpint(elem->value, ==, i);
+ }
+ break;
+ }
+ case USER_DEF_NATIVE_LIST_UNION_KIND_S16: {
+ int16List *elem = NULL;
+ for (i = 0, elem = cvalue->s16; elem; elem = elem->next, i++) {
+ g_assert_cmpint(elem->value, ==, i);
+ }
+ break;
+ }
+ case USER_DEF_NATIVE_LIST_UNION_KIND_S32: {
+ int32List *elem = NULL;
+ for (i = 0, elem = cvalue->s32; elem; elem = elem->next, i++) {
+ g_assert_cmpint(elem->value, ==, i);
+ }
+ break;
+ }
+ case USER_DEF_NATIVE_LIST_UNION_KIND_S64: {
+ int64List *elem = NULL;
+ for (i = 0, elem = cvalue->s64; elem; elem = elem->next, i++) {
+ g_assert_cmpint(elem->value, ==, i);
+ }
+ break;
+ }
+ case USER_DEF_NATIVE_LIST_UNION_KIND_U8: {
+ uint8List *elem = NULL;
+ for (i = 0, elem = cvalue->u8; elem; elem = elem->next, i++) {
+ g_assert_cmpint(elem->value, ==, i);
+ }
+ break;
+ }
+ case USER_DEF_NATIVE_LIST_UNION_KIND_U16: {
+ uint16List *elem = NULL;
+ for (i = 0, elem = cvalue->u16; elem; elem = elem->next, i++) {
+ g_assert_cmpint(elem->value, ==, i);
+ }
+ break;
+ }
+ case USER_DEF_NATIVE_LIST_UNION_KIND_U32: {
+ uint32List *elem = NULL;
+ for (i = 0, elem = cvalue->u32; elem; elem = elem->next, i++) {
+ g_assert_cmpint(elem->value, ==, i);
+ }
+ break;
+ }
+ case USER_DEF_NATIVE_LIST_UNION_KIND_U64: {
+ uint64List *elem = NULL;
+ for (i = 0, elem = cvalue->u64; elem; elem = elem->next, i++) {
+ g_assert_cmpint(elem->value, ==, i);
+ }
+ break;
+ }
+ default:
+ g_assert(false);
+ }
+
+ g_string_free(gstr_union, true);
+ g_string_free(gstr_list, true);
+ qapi_free_UserDefNativeListUnion(cvalue);
+}
+
+static void test_visitor_in_native_list_int(TestInputVisitorData *data,
+ const void *unused)
+{
+ test_native_list_integer_helper(data, unused,
+ USER_DEF_NATIVE_LIST_UNION_KIND_INTEGER);
+}
+
+static void test_visitor_in_native_list_int8(TestInputVisitorData *data,
+ const void *unused)
+{
+ test_native_list_integer_helper(data, unused,
+ USER_DEF_NATIVE_LIST_UNION_KIND_S8);
+}
+
+static void test_visitor_in_native_list_int16(TestInputVisitorData *data,
+ const void *unused)
+{
+ test_native_list_integer_helper(data, unused,
+ USER_DEF_NATIVE_LIST_UNION_KIND_S16);
+}
+
+static void test_visitor_in_native_list_int32(TestInputVisitorData *data,
+ const void *unused)
+{
+ test_native_list_integer_helper(data, unused,
+ USER_DEF_NATIVE_LIST_UNION_KIND_S32);
+}
+
+static void test_visitor_in_native_list_int64(TestInputVisitorData *data,
+ const void *unused)
+{
+ test_native_list_integer_helper(data, unused,
+ USER_DEF_NATIVE_LIST_UNION_KIND_S64);
+}
+
+static void test_visitor_in_native_list_uint8(TestInputVisitorData *data,
+ const void *unused)
+{
+ test_native_list_integer_helper(data, unused,
+ USER_DEF_NATIVE_LIST_UNION_KIND_U8);
+}
+
+static void test_visitor_in_native_list_uint16(TestInputVisitorData *data,
+ const void *unused)
+{
+ test_native_list_integer_helper(data, unused,
+ USER_DEF_NATIVE_LIST_UNION_KIND_U16);
+}
+
+static void test_visitor_in_native_list_uint32(TestInputVisitorData *data,
+ const void *unused)
+{
+ test_native_list_integer_helper(data, unused,
+ USER_DEF_NATIVE_LIST_UNION_KIND_U32);
+}
+
+static void test_visitor_in_native_list_uint64(TestInputVisitorData *data,
+ const void *unused)
+{
+ test_native_list_integer_helper(data, unused,
+ USER_DEF_NATIVE_LIST_UNION_KIND_U64);
+}
+
+static void test_visitor_in_native_list_bool(TestInputVisitorData *data,
+ const void *unused)
+{
+ UserDefNativeListUnion *cvalue = NULL;
+ boolList *elem = NULL;
+ Error *err = NULL;
+ Visitor *v;
+ GString *gstr_list = g_string_new("");
+ GString *gstr_union = g_string_new("");
+ int i;
+
+ for (i = 0; i < 32; i++) {
+ g_string_append_printf(gstr_list, "%s",
+ (i % 3 == 0) ? "true" : "false");
+ if (i != 31) {
+ g_string_append(gstr_list, ", ");
+ }
+ }
+ g_string_append_printf(gstr_union, "{ 'type': 'boolean', 'data': [ %s ] }",
+ gstr_list->str);
+ v = visitor_input_test_init_raw(data, gstr_union->str);
+
+ visit_type_UserDefNativeListUnion(v, &cvalue, NULL, &err);
+ g_assert(err == NULL);
+ g_assert(cvalue != NULL);
+ g_assert_cmpint(cvalue->kind, ==, USER_DEF_NATIVE_LIST_UNION_KIND_BOOLEAN);
+
+ for (i = 0, elem = cvalue->boolean; elem; elem = elem->next, i++) {
+ g_assert_cmpint(elem->value, ==, (i % 3 == 0) ? 1 : 0);
+ }
+
+ g_string_free(gstr_union, true);
+ g_string_free(gstr_list, true);
+ qapi_free_UserDefNativeListUnion(cvalue);
+}
+
+static void test_visitor_in_native_list_string(TestInputVisitorData *data,
+ const void *unused)
+{
+ UserDefNativeListUnion *cvalue = NULL;
+ strList *elem = NULL;
+ Error *err = NULL;
+ Visitor *v;
+ GString *gstr_list = g_string_new("");
+ GString *gstr_union = g_string_new("");
+ int i;
+
+ for (i = 0; i < 32; i++) {
+ g_string_append_printf(gstr_list, "'%d'", i);
+ if (i != 31) {
+ g_string_append(gstr_list, ", ");
+ }
+ }
+ g_string_append_printf(gstr_union, "{ 'type': 'string', 'data': [ %s ] }",
+ gstr_list->str);
+ v = visitor_input_test_init_raw(data, gstr_union->str);
+
+ visit_type_UserDefNativeListUnion(v, &cvalue, NULL, &err);
+ g_assert(err == NULL);
+ g_assert(cvalue != NULL);
+ g_assert_cmpint(cvalue->kind, ==, USER_DEF_NATIVE_LIST_UNION_KIND_STRING);
+
+ for (i = 0, elem = cvalue->string; elem; elem = elem->next, i++) {
+ gchar str[8];
+ sprintf(str, "%d", i);
+ g_assert_cmpstr(elem->value, ==, str);
+ }
+
+ g_string_free(gstr_union, true);
+ g_string_free(gstr_list, true);
+ qapi_free_UserDefNativeListUnion(cvalue);
+}
+
+#define DOUBLE_STR_MAX 16
+
+static void test_visitor_in_native_list_number(TestInputVisitorData *data,
+ const void *unused)
+{
+ UserDefNativeListUnion *cvalue = NULL;
+ numberList *elem = NULL;
+ Error *err = NULL;
+ Visitor *v;
+ GString *gstr_list = g_string_new("");
+ GString *gstr_union = g_string_new("");
+ int i;
+
+ for (i = 0; i < 32; i++) {
+ g_string_append_printf(gstr_list, "%f", (double)i / 3);
+ if (i != 31) {
+ g_string_append(gstr_list, ", ");
+ }
+ }
+ g_string_append_printf(gstr_union, "{ 'type': 'number', 'data': [ %s ] }",
+ gstr_list->str);
+ v = visitor_input_test_init_raw(data, gstr_union->str);
+
+ visit_type_UserDefNativeListUnion(v, &cvalue, NULL, &err);
+ g_assert(err == NULL);
+ g_assert(cvalue != NULL);
+ g_assert_cmpint(cvalue->kind, ==, USER_DEF_NATIVE_LIST_UNION_KIND_NUMBER);
+
+ for (i = 0, elem = cvalue->number; elem; elem = elem->next, i++) {
+ GString *double_expected = g_string_new("");
+ GString *double_actual = g_string_new("");
+
+ g_string_printf(double_expected, "%.6f", (double)i / 3);
+ g_string_printf(double_actual, "%.6f", elem->value);
+ g_assert_cmpstr(double_expected->str, ==, double_actual->str);
+
+ g_string_free(double_expected, true);
+ g_string_free(double_actual, true);
+ }
+
+ g_string_free(gstr_union, true);
+ g_string_free(gstr_list, true);
+ qapi_free_UserDefNativeListUnion(cvalue);
+}
+
static void input_visitor_test_add(const char *testpath,
TestInputVisitorData *data,
void (*test_func)(TestInputVisitorData *data, const void *user_data))
@@ -292,6 +616,8 @@ int main(int argc, char **argv)
input_visitor_test_add("/visitor/input/int",
&in_visitor_data, test_visitor_in_int);
+ input_visitor_test_add("/visitor/input/int_overflow",
+ &in_visitor_data, test_visitor_in_int_overflow);
input_visitor_test_add("/visitor/input/bool",
&in_visitor_data, test_visitor_in_bool);
input_visitor_test_add("/visitor/input/number",
@@ -310,6 +636,38 @@ int main(int argc, char **argv)
&in_visitor_data, test_visitor_in_union);
input_visitor_test_add("/visitor/input/errors",
&in_visitor_data, test_visitor_in_errors);
+ input_visitor_test_add("/visitor/input/native_list/int",
+ &in_visitor_data,
+ test_visitor_in_native_list_int);
+ input_visitor_test_add("/visitor/input/native_list/int8",
+ &in_visitor_data,
+ test_visitor_in_native_list_int8);
+ input_visitor_test_add("/visitor/input/native_list/int16",
+ &in_visitor_data,
+ test_visitor_in_native_list_int16);
+ input_visitor_test_add("/visitor/input/native_list/int32",
+ &in_visitor_data,
+ test_visitor_in_native_list_int32);
+ input_visitor_test_add("/visitor/input/native_list/int64",
+ &in_visitor_data,
+ test_visitor_in_native_list_int64);
+ input_visitor_test_add("/visitor/input/native_list/uint8",
+ &in_visitor_data,
+ test_visitor_in_native_list_uint8);
+ input_visitor_test_add("/visitor/input/native_list/uint16",
+ &in_visitor_data,
+ test_visitor_in_native_list_uint16);
+ input_visitor_test_add("/visitor/input/native_list/uint32",
+ &in_visitor_data,
+ test_visitor_in_native_list_uint32);
+ input_visitor_test_add("/visitor/input/native_list/uint64",
+ &in_visitor_data, test_visitor_in_native_list_uint64);
+ input_visitor_test_add("/visitor/input/native_list/bool",
+ &in_visitor_data, test_visitor_in_native_list_bool);
+ input_visitor_test_add("/visitor/input/native_list/str",
+ &in_visitor_data, test_visitor_in_native_list_string);
+ input_visitor_test_add("/visitor/input/native_list/number",
+ &in_visitor_data, test_visitor_in_native_list_number);
g_test_run();
diff --git a/tests/test-qmp-output-visitor.c b/tests/test-qmp-output-visitor.c
index 71367e6efa..0942a41875 100644
--- a/tests/test-qmp-output-visitor.c
+++ b/tests/test-qmp-output-visitor.c
@@ -431,6 +431,314 @@ static void test_visitor_out_union(TestOutputVisitorData *data,
QDECREF(qdict);
}
+static void init_native_list(UserDefNativeListUnion *cvalue)
+{
+ int i;
+ switch (cvalue->kind) {
+ case USER_DEF_NATIVE_LIST_UNION_KIND_INTEGER: {
+ intList **list = &cvalue->integer;
+ for (i = 0; i < 32; i++) {
+ *list = g_new0(intList, 1);
+ (*list)->value = i;
+ (*list)->next = NULL;
+ list = &(*list)->next;
+ }
+ break;
+ }
+ case USER_DEF_NATIVE_LIST_UNION_KIND_S8: {
+ int8List **list = &cvalue->s8;
+ for (i = 0; i < 32; i++) {
+ *list = g_new0(int8List, 1);
+ (*list)->value = i;
+ (*list)->next = NULL;
+ list = &(*list)->next;
+ }
+ break;
+ }
+ case USER_DEF_NATIVE_LIST_UNION_KIND_S16: {
+ int16List **list = &cvalue->s16;
+ for (i = 0; i < 32; i++) {
+ *list = g_new0(int16List, 1);
+ (*list)->value = i;
+ (*list)->next = NULL;
+ list = &(*list)->next;
+ }
+ break;
+ }
+ case USER_DEF_NATIVE_LIST_UNION_KIND_S32: {
+ int32List **list = &cvalue->s32;
+ for (i = 0; i < 32; i++) {
+ *list = g_new0(int32List, 1);
+ (*list)->value = i;
+ (*list)->next = NULL;
+ list = &(*list)->next;
+ }
+ break;
+ }
+ case USER_DEF_NATIVE_LIST_UNION_KIND_S64: {
+ int64List **list = &cvalue->s64;
+ for (i = 0; i < 32; i++) {
+ *list = g_new0(int64List, 1);
+ (*list)->value = i;
+ (*list)->next = NULL;
+ list = &(*list)->next;
+ }
+ break;
+ }
+ case USER_DEF_NATIVE_LIST_UNION_KIND_U8: {
+ uint8List **list = &cvalue->u8;
+ for (i = 0; i < 32; i++) {
+ *list = g_new0(uint8List, 1);
+ (*list)->value = i;
+ (*list)->next = NULL;
+ list = &(*list)->next;
+ }
+ break;
+ }
+ case USER_DEF_NATIVE_LIST_UNION_KIND_U16: {
+ uint16List **list = &cvalue->u16;
+ for (i = 0; i < 32; i++) {
+ *list = g_new0(uint16List, 1);
+ (*list)->value = i;
+ (*list)->next = NULL;
+ list = &(*list)->next;
+ }
+ break;
+ }
+ case USER_DEF_NATIVE_LIST_UNION_KIND_U32: {
+ uint32List **list = &cvalue->u32;
+ for (i = 0; i < 32; i++) {
+ *list = g_new0(uint32List, 1);
+ (*list)->value = i;
+ (*list)->next = NULL;
+ list = &(*list)->next;
+ }
+ break;
+ }
+ case USER_DEF_NATIVE_LIST_UNION_KIND_U64: {
+ uint64List **list = &cvalue->u64;
+ for (i = 0; i < 32; i++) {
+ *list = g_new0(uint64List, 1);
+ (*list)->value = i;
+ (*list)->next = NULL;
+ list = &(*list)->next;
+ }
+ break;
+ }
+ case USER_DEF_NATIVE_LIST_UNION_KIND_BOOLEAN: {
+ boolList **list = &cvalue->boolean;
+ for (i = 0; i < 32; i++) {
+ *list = g_new0(boolList, 1);
+ (*list)->value = (i % 3 == 0);
+ (*list)->next = NULL;
+ list = &(*list)->next;
+ }
+ break;
+ }
+ case USER_DEF_NATIVE_LIST_UNION_KIND_STRING: {
+ strList **list = &cvalue->string;
+ for (i = 0; i < 32; i++) {
+ *list = g_new0(strList, 1);
+ (*list)->value = g_strdup_printf("%d", i);
+ (*list)->next = NULL;
+ list = &(*list)->next;
+ }
+ break;
+ }
+ case USER_DEF_NATIVE_LIST_UNION_KIND_NUMBER: {
+ numberList **list = &cvalue->number;
+ for (i = 0; i < 32; i++) {
+ *list = g_new0(numberList, 1);
+ (*list)->value = (double)i / 3;
+ (*list)->next = NULL;
+ list = &(*list)->next;
+ }
+ break;
+ }
+ default:
+ g_assert(false);
+ }
+}
+
+static void check_native_list(QObject *qobj,
+ UserDefNativeListUnionKind kind)
+{
+ QDict *qdict;
+ QList *qlist;
+ int i;
+
+ g_assert(qobj);
+ g_assert(qobject_type(qobj) == QTYPE_QDICT);
+ qdict = qobject_to_qdict(qobj);
+ g_assert(qdict);
+ g_assert(qdict_haskey(qdict, "data"));
+ qlist = qlist_copy(qobject_to_qlist(qdict_get(qdict, "data")));
+
+ switch (kind) {
+ case USER_DEF_NATIVE_LIST_UNION_KIND_S8:
+ case USER_DEF_NATIVE_LIST_UNION_KIND_S16:
+ case USER_DEF_NATIVE_LIST_UNION_KIND_S32:
+ case USER_DEF_NATIVE_LIST_UNION_KIND_S64:
+ case USER_DEF_NATIVE_LIST_UNION_KIND_U8:
+ case USER_DEF_NATIVE_LIST_UNION_KIND_U16:
+ case USER_DEF_NATIVE_LIST_UNION_KIND_U32:
+ case USER_DEF_NATIVE_LIST_UNION_KIND_U64:
+ /* all integer elements in JSON arrays get stored into QInts when
+ * we convert to QObjects, so we can check them all in the same
+ * fashion, so simply fall through here
+ */
+ case USER_DEF_NATIVE_LIST_UNION_KIND_INTEGER:
+ for (i = 0; i < 32; i++) {
+ QObject *tmp;
+ QInt *qvalue;
+ tmp = qlist_peek(qlist);
+ g_assert(tmp);
+ qvalue = qobject_to_qint(tmp);
+ g_assert_cmpint(qint_get_int(qvalue), ==, i);
+ qobject_decref(qlist_pop(qlist));
+ }
+ break;
+ case USER_DEF_NATIVE_LIST_UNION_KIND_BOOLEAN:
+ for (i = 0; i < 32; i++) {
+ QObject *tmp;
+ QBool *qvalue;
+ tmp = qlist_peek(qlist);
+ g_assert(tmp);
+ qvalue = qobject_to_qbool(tmp);
+ g_assert_cmpint(qbool_get_int(qvalue), ==, (i % 3 == 0) ? 1 : 0);
+ qobject_decref(qlist_pop(qlist));
+ }
+ break;
+ case USER_DEF_NATIVE_LIST_UNION_KIND_STRING:
+ for (i = 0; i < 32; i++) {
+ QObject *tmp;
+ QString *qvalue;
+ gchar str[8];
+ tmp = qlist_peek(qlist);
+ g_assert(tmp);
+ qvalue = qobject_to_qstring(tmp);
+ sprintf(str, "%d", i);
+ g_assert_cmpstr(qstring_get_str(qvalue), ==, str);
+ qobject_decref(qlist_pop(qlist));
+ }
+ break;
+ case USER_DEF_NATIVE_LIST_UNION_KIND_NUMBER:
+ for (i = 0; i < 32; i++) {
+ QObject *tmp;
+ QFloat *qvalue;
+ GString *double_expected = g_string_new("");
+ GString *double_actual = g_string_new("");
+
+ tmp = qlist_peek(qlist);
+ g_assert(tmp);
+ qvalue = qobject_to_qfloat(tmp);
+ g_string_printf(double_expected, "%.6f", (double)i / 3);
+ g_string_printf(double_actual, "%.6f", qfloat_get_double(qvalue));
+ g_assert_cmpstr(double_actual->str, ==, double_expected->str);
+
+ qobject_decref(qlist_pop(qlist));
+ g_string_free(double_expected, true);
+ g_string_free(double_actual, true);
+ }
+ break;
+ default:
+ g_assert(false);
+ }
+ QDECREF(qlist);
+}
+
+static void test_native_list(TestOutputVisitorData *data,
+ const void *unused,
+ UserDefNativeListUnionKind kind)
+{
+ UserDefNativeListUnion *cvalue = g_new0(UserDefNativeListUnion, 1);
+ Error *err = NULL;
+ QObject *obj;
+
+ cvalue->kind = kind;
+ init_native_list(cvalue);
+
+ visit_type_UserDefNativeListUnion(data->ov, &cvalue, NULL, &err);
+ g_assert(err == NULL);
+
+ obj = qmp_output_get_qobject(data->qov);
+ check_native_list(obj, cvalue->kind);
+ qapi_free_UserDefNativeListUnion(cvalue);
+ qobject_decref(obj);
+}
+
+static void test_visitor_out_native_list_int(TestOutputVisitorData *data,
+ const void *unused)
+{
+ test_native_list(data, unused, USER_DEF_NATIVE_LIST_UNION_KIND_INTEGER);
+}
+
+static void test_visitor_out_native_list_int8(TestOutputVisitorData *data,
+ const void *unused)
+{
+ test_native_list(data, unused, USER_DEF_NATIVE_LIST_UNION_KIND_S8);
+}
+
+static void test_visitor_out_native_list_int16(TestOutputVisitorData *data,
+ const void *unused)
+{
+ test_native_list(data, unused, USER_DEF_NATIVE_LIST_UNION_KIND_S16);
+}
+
+static void test_visitor_out_native_list_int32(TestOutputVisitorData *data,
+ const void *unused)
+{
+ test_native_list(data, unused, USER_DEF_NATIVE_LIST_UNION_KIND_S32);
+}
+
+static void test_visitor_out_native_list_int64(TestOutputVisitorData *data,
+ const void *unused)
+{
+ test_native_list(data, unused, USER_DEF_NATIVE_LIST_UNION_KIND_S64);
+}
+
+static void test_visitor_out_native_list_uint8(TestOutputVisitorData *data,
+ const void *unused)
+{
+ test_native_list(data, unused, USER_DEF_NATIVE_LIST_UNION_KIND_U8);
+}
+
+static void test_visitor_out_native_list_uint16(TestOutputVisitorData *data,
+ const void *unused)
+{
+ test_native_list(data, unused, USER_DEF_NATIVE_LIST_UNION_KIND_U16);
+}
+
+static void test_visitor_out_native_list_uint32(TestOutputVisitorData *data,
+ const void *unused)
+{
+ test_native_list(data, unused, USER_DEF_NATIVE_LIST_UNION_KIND_U32);
+}
+
+static void test_visitor_out_native_list_uint64(TestOutputVisitorData *data,
+ const void *unused)
+{
+ test_native_list(data, unused, USER_DEF_NATIVE_LIST_UNION_KIND_U64);
+}
+
+static void test_visitor_out_native_list_bool(TestOutputVisitorData *data,
+ const void *unused)
+{
+ test_native_list(data, unused, USER_DEF_NATIVE_LIST_UNION_KIND_BOOLEAN);
+}
+
+static void test_visitor_out_native_list_str(TestOutputVisitorData *data,
+ const void *unused)
+{
+ test_native_list(data, unused, USER_DEF_NATIVE_LIST_UNION_KIND_STRING);
+}
+
+static void test_visitor_out_native_list_number(TestOutputVisitorData *data,
+ const void *unused)
+{
+ test_native_list(data, unused, USER_DEF_NATIVE_LIST_UNION_KIND_NUMBER);
+}
+
static void output_visitor_test_add(const char *testpath,
TestOutputVisitorData *data,
void (*test_func)(TestOutputVisitorData *data, const void *user_data))
@@ -471,6 +779,30 @@ int main(int argc, char **argv)
&out_visitor_data, test_visitor_out_list_qapi_free);
output_visitor_test_add("/visitor/output/union",
&out_visitor_data, test_visitor_out_union);
+ output_visitor_test_add("/visitor/output/native_list/int",
+ &out_visitor_data, test_visitor_out_native_list_int);
+ output_visitor_test_add("/visitor/output/native_list/int8",
+ &out_visitor_data, test_visitor_out_native_list_int8);
+ output_visitor_test_add("/visitor/output/native_list/int16",
+ &out_visitor_data, test_visitor_out_native_list_int16);
+ output_visitor_test_add("/visitor/output/native_list/int32",
+ &out_visitor_data, test_visitor_out_native_list_int32);
+ output_visitor_test_add("/visitor/output/native_list/int64",
+ &out_visitor_data, test_visitor_out_native_list_int64);
+ output_visitor_test_add("/visitor/output/native_list/uint8",
+ &out_visitor_data, test_visitor_out_native_list_uint8);
+ output_visitor_test_add("/visitor/output/native_list/uint16",
+ &out_visitor_data, test_visitor_out_native_list_uint16);
+ output_visitor_test_add("/visitor/output/native_list/uint32",
+ &out_visitor_data, test_visitor_out_native_list_uint32);
+ output_visitor_test_add("/visitor/output/native_list/uint64",
+ &out_visitor_data, test_visitor_out_native_list_uint64);
+ output_visitor_test_add("/visitor/output/native_list/bool",
+ &out_visitor_data, test_visitor_out_native_list_bool);
+ output_visitor_test_add("/visitor/output/native_list/string",
+ &out_visitor_data, test_visitor_out_native_list_str);
+ output_visitor_test_add("/visitor/output/native_list/number",
+ &out_visitor_data, test_visitor_out_native_list_number);
g_test_run();
diff --git a/tests/test-visitor-serialization.c b/tests/test-visitor-serialization.c
index 8c8adac6a9..ee7916b806 100644
--- a/tests/test-visitor-serialization.c
+++ b/tests/test-visitor-serialization.c
@@ -23,6 +23,25 @@
#include "qapi/qmp-output-visitor.h"
#include "qapi/string-input-visitor.h"
#include "qapi/string-output-visitor.h"
+#include "qapi-types.h"
+#include "qapi-visit.h"
+#include "qapi/dealloc-visitor.h"
+
+enum PrimitiveTypeKind {
+ PTYPE_STRING = 0,
+ PTYPE_BOOLEAN,
+ PTYPE_NUMBER,
+ PTYPE_INTEGER,
+ PTYPE_U8,
+ PTYPE_U16,
+ PTYPE_U32,
+ PTYPE_U64,
+ PTYPE_S8,
+ PTYPE_S16,
+ PTYPE_S32,
+ PTYPE_S64,
+ PTYPE_EOL,
+};
typedef struct PrimitiveType {
union {
@@ -40,26 +59,42 @@ typedef struct PrimitiveType {
int64_t s64;
intmax_t max;
} value;
- enum {
- PTYPE_STRING = 0,
- PTYPE_BOOLEAN,
- PTYPE_NUMBER,
- PTYPE_INTEGER,
- PTYPE_U8,
- PTYPE_U16,
- PTYPE_U32,
- PTYPE_U64,
- PTYPE_S8,
- PTYPE_S16,
- PTYPE_S32,
- PTYPE_S64,
- PTYPE_EOL,
- } type;
+ enum PrimitiveTypeKind type;
const char *description;
} PrimitiveType;
+typedef struct PrimitiveList {
+ union {
+ strList *strings;
+ boolList *booleans;
+ numberList *numbers;
+ intList *integers;
+ int8List *s8_integers;
+ int16List *s16_integers;
+ int32List *s32_integers;
+ int64List *s64_integers;
+ uint8List *u8_integers;
+ uint16List *u16_integers;
+ uint32List *u32_integers;
+ uint64List *u64_integers;
+ } value;
+ enum PrimitiveTypeKind type;
+ const char *description;
+} PrimitiveList;
+
/* test helpers */
+typedef void (*VisitorFunc)(Visitor *v, void **native, Error **errp);
+
+static void dealloc_helper(void *native_in, VisitorFunc visit, Error **errp)
+{
+ QapiDeallocVisitor *qdv = qapi_dealloc_visitor_new();
+
+ visit(qapi_dealloc_get_visitor(qdv), &native_in, errp);
+
+ qapi_dealloc_visitor_cleanup(qdv);
+}
+
static void visit_primitive_type(Visitor *v, void **native, Error **errp)
{
PrimitiveType *pt = *native;
@@ -105,6 +140,51 @@ static void visit_primitive_type(Visitor *v, void **native, Error **errp)
}
}
+static void visit_primitive_list(Visitor *v, void **native, Error **errp)
+{
+ PrimitiveList *pl = *native;
+ switch (pl->type) {
+ case PTYPE_STRING:
+ visit_type_strList(v, &pl->value.strings, NULL, errp);
+ break;
+ case PTYPE_BOOLEAN:
+ visit_type_boolList(v, &pl->value.booleans, NULL, errp);
+ break;
+ case PTYPE_NUMBER:
+ visit_type_numberList(v, &pl->value.numbers, NULL, errp);
+ break;
+ case PTYPE_INTEGER:
+ visit_type_intList(v, &pl->value.integers, NULL, errp);
+ break;
+ case PTYPE_S8:
+ visit_type_int8List(v, &pl->value.s8_integers, NULL, errp);
+ break;
+ case PTYPE_S16:
+ visit_type_int16List(v, &pl->value.s16_integers, NULL, errp);
+ break;
+ case PTYPE_S32:
+ visit_type_int32List(v, &pl->value.s32_integers, NULL, errp);
+ break;
+ case PTYPE_S64:
+ visit_type_int64List(v, &pl->value.s64_integers, NULL, errp);
+ break;
+ case PTYPE_U8:
+ visit_type_uint8List(v, &pl->value.u8_integers, NULL, errp);
+ break;
+ case PTYPE_U16:
+ visit_type_uint16List(v, &pl->value.u16_integers, NULL, errp);
+ break;
+ case PTYPE_U32:
+ visit_type_uint32List(v, &pl->value.u32_integers, NULL, errp);
+ break;
+ case PTYPE_U64:
+ visit_type_uint64List(v, &pl->value.u64_integers, NULL, errp);
+ break;
+ default:
+ g_assert(false);
+ }
+}
+
typedef struct TestStruct
{
int64_t integer;
@@ -206,12 +286,11 @@ static void visit_nested_struct_list(Visitor *v, void **native, Error **errp)
/* test cases */
-typedef void (*VisitorFunc)(Visitor *v, void **native, Error **errp);
-
typedef enum VisitorCapabilities {
VCAP_PRIMITIVES = 1,
VCAP_STRUCTURES = 2,
VCAP_LISTS = 4,
+ VCAP_PRIMITIVE_LISTS = 8,
} VisitorCapabilities;
typedef struct SerializeOps {
@@ -229,17 +308,6 @@ typedef struct TestArgs {
void *test_data;
} TestArgs;
-#define FLOAT_STRING_PRECISION 6 /* corresponding to n in %.nf formatting */
-static gsize calc_float_string_storage(double value)
-{
- int whole_value = value;
- gsize i = 0;
- do {
- i++;
- } while (whole_value /= 10);
- return i + 2 + FLOAT_STRING_PRECISION;
-}
-
static void test_primitives(gconstpointer opaque)
{
TestArgs *args = (TestArgs *) opaque;
@@ -248,7 +316,6 @@ static void test_primitives(gconstpointer opaque)
PrimitiveType *pt_copy = g_malloc0(sizeof(*pt_copy));
Error *err = NULL;
void *serialize_data;
- char *double1, *double2;
pt_copy->type = pt->type;
ops->serialize(pt, &serialize_data, visit_primitive_type, &err);
@@ -260,14 +327,17 @@ static void test_primitives(gconstpointer opaque)
g_assert_cmpstr(pt->value.string, ==, pt_copy->value.string);
g_free((char *)pt_copy->value.string);
} else if (pt->type == PTYPE_NUMBER) {
+ GString *double_expected = g_string_new("");
+ GString *double_actual = g_string_new("");
/* we serialize with %f for our reference visitors, so rather than fuzzy
* floating math to test "equality", just compare the formatted values
*/
- double1 = g_malloc0(calc_float_string_storage(pt->value.number));
- double2 = g_malloc0(calc_float_string_storage(pt_copy->value.number));
- g_assert_cmpstr(double1, ==, double2);
- g_free(double1);
- g_free(double2);
+ g_string_printf(double_expected, "%.6f", pt->value.number);
+ g_string_printf(double_actual, "%.6f", pt_copy->value.number);
+ g_assert_cmpstr(double_actual->str, ==, double_expected->str);
+
+ g_string_free(double_expected, true);
+ g_string_free(double_actual, true);
} else if (pt->type == PTYPE_BOOLEAN) {
g_assert_cmpint(!!pt->value.max, ==, !!pt->value.max);
} else {
@@ -279,6 +349,328 @@ static void test_primitives(gconstpointer opaque)
g_free(pt_copy);
}
+static void test_primitive_lists(gconstpointer opaque)
+{
+ TestArgs *args = (TestArgs *) opaque;
+ const SerializeOps *ops = args->ops;
+ PrimitiveType *pt = args->test_data;
+ PrimitiveList pl = { .value = { 0 } };
+ PrimitiveList pl_copy = { .value = { 0 } };
+ PrimitiveList *pl_copy_ptr = &pl_copy;
+ Error *err = NULL;
+ void *serialize_data;
+ void *cur_head = NULL;
+ int i;
+
+ pl.type = pl_copy.type = pt->type;
+
+ /* build up our list of primitive types */
+ for (i = 0; i < 32; i++) {
+ switch (pl.type) {
+ case PTYPE_STRING: {
+ strList *tmp = g_new0(strList, 1);
+ tmp->value = g_strdup(pt->value.string);
+ if (pl.value.strings == NULL) {
+ pl.value.strings = tmp;
+ } else {
+ tmp->next = pl.value.strings;
+ pl.value.strings = tmp;
+ }
+ break;
+ }
+ case PTYPE_INTEGER: {
+ intList *tmp = g_new0(intList, 1);
+ tmp->value = pt->value.integer;
+ if (pl.value.integers == NULL) {
+ pl.value.integers = tmp;
+ } else {
+ tmp->next = pl.value.integers;
+ pl.value.integers = tmp;
+ }
+ break;
+ }
+ case PTYPE_S8: {
+ int8List *tmp = g_new0(int8List, 1);
+ tmp->value = pt->value.s8;
+ if (pl.value.s8_integers == NULL) {
+ pl.value.s8_integers = tmp;
+ } else {
+ tmp->next = pl.value.s8_integers;
+ pl.value.s8_integers = tmp;
+ }
+ break;
+ }
+ case PTYPE_S16: {
+ int16List *tmp = g_new0(int16List, 1);
+ tmp->value = pt->value.s16;
+ if (pl.value.s16_integers == NULL) {
+ pl.value.s16_integers = tmp;
+ } else {
+ tmp->next = pl.value.s16_integers;
+ pl.value.s16_integers = tmp;
+ }
+ break;
+ }
+ case PTYPE_S32: {
+ int32List *tmp = g_new0(int32List, 1);
+ tmp->value = pt->value.s32;
+ if (pl.value.s32_integers == NULL) {
+ pl.value.s32_integers = tmp;
+ } else {
+ tmp->next = pl.value.s32_integers;
+ pl.value.s32_integers = tmp;
+ }
+ break;
+ }
+ case PTYPE_S64: {
+ int64List *tmp = g_new0(int64List, 1);
+ tmp->value = pt->value.s64;
+ if (pl.value.s64_integers == NULL) {
+ pl.value.s64_integers = tmp;
+ } else {
+ tmp->next = pl.value.s64_integers;
+ pl.value.s64_integers = tmp;
+ }
+ break;
+ }
+ case PTYPE_U8: {
+ uint8List *tmp = g_new0(uint8List, 1);
+ tmp->value = pt->value.u8;
+ if (pl.value.u8_integers == NULL) {
+ pl.value.u8_integers = tmp;
+ } else {
+ tmp->next = pl.value.u8_integers;
+ pl.value.u8_integers = tmp;
+ }
+ break;
+ }
+ case PTYPE_U16: {
+ uint16List *tmp = g_new0(uint16List, 1);
+ tmp->value = pt->value.u16;
+ if (pl.value.u16_integers == NULL) {
+ pl.value.u16_integers = tmp;
+ } else {
+ tmp->next = pl.value.u16_integers;
+ pl.value.u16_integers = tmp;
+ }
+ break;
+ }
+ case PTYPE_U32: {
+ uint32List *tmp = g_new0(uint32List, 1);
+ tmp->value = pt->value.u32;
+ if (pl.value.u32_integers == NULL) {
+ pl.value.u32_integers = tmp;
+ } else {
+ tmp->next = pl.value.u32_integers;
+ pl.value.u32_integers = tmp;
+ }
+ break;
+ }
+ case PTYPE_U64: {
+ uint64List *tmp = g_new0(uint64List, 1);
+ tmp->value = pt->value.u64;
+ if (pl.value.u64_integers == NULL) {
+ pl.value.u64_integers = tmp;
+ } else {
+ tmp->next = pl.value.u64_integers;
+ pl.value.u64_integers = tmp;
+ }
+ break;
+ }
+ case PTYPE_NUMBER: {
+ numberList *tmp = g_new0(numberList, 1);
+ tmp->value = pt->value.number;
+ if (pl.value.numbers == NULL) {
+ pl.value.numbers = tmp;
+ } else {
+ tmp->next = pl.value.numbers;
+ pl.value.numbers = tmp;
+ }
+ break;
+ }
+ case PTYPE_BOOLEAN: {
+ boolList *tmp = g_new0(boolList, 1);
+ tmp->value = pt->value.boolean;
+ if (pl.value.booleans == NULL) {
+ pl.value.booleans = tmp;
+ } else {
+ tmp->next = pl.value.booleans;
+ pl.value.booleans = tmp;
+ }
+ break;
+ }
+ default:
+ g_assert(0);
+ }
+ }
+
+ ops->serialize((void **)&pl, &serialize_data, visit_primitive_list, &err);
+ ops->deserialize((void **)&pl_copy_ptr, serialize_data, visit_primitive_list, &err);
+
+ g_assert(err == NULL);
+ i = 0;
+
+ /* compare our deserialized list of primitives to the original */
+ do {
+ switch (pl_copy.type) {
+ case PTYPE_STRING: {
+ strList *ptr;
+ if (cur_head) {
+ ptr = cur_head;
+ cur_head = ptr->next;
+ } else {
+ cur_head = ptr = pl_copy.value.strings;
+ }
+ g_assert_cmpstr(pt->value.string, ==, ptr->value);
+ break;
+ }
+ case PTYPE_INTEGER: {
+ intList *ptr;
+ if (cur_head) {
+ ptr = cur_head;
+ cur_head = ptr->next;
+ } else {
+ cur_head = ptr = pl_copy.value.integers;
+ }
+ g_assert_cmpint(pt->value.integer, ==, ptr->value);
+ break;
+ }
+ case PTYPE_S8: {
+ int8List *ptr;
+ if (cur_head) {
+ ptr = cur_head;
+ cur_head = ptr->next;
+ } else {
+ cur_head = ptr = pl_copy.value.s8_integers;
+ }
+ g_assert_cmpint(pt->value.s8, ==, ptr->value);
+ break;
+ }
+ case PTYPE_S16: {
+ int16List *ptr;
+ if (cur_head) {
+ ptr = cur_head;
+ cur_head = ptr->next;
+ } else {
+ cur_head = ptr = pl_copy.value.s16_integers;
+ }
+ g_assert_cmpint(pt->value.s16, ==, ptr->value);
+ break;
+ }
+ case PTYPE_S32: {
+ int32List *ptr;
+ if (cur_head) {
+ ptr = cur_head;
+ cur_head = ptr->next;
+ } else {
+ cur_head = ptr = pl_copy.value.s32_integers;
+ }
+ g_assert_cmpint(pt->value.s32, ==, ptr->value);
+ break;
+ }
+ case PTYPE_S64: {
+ int64List *ptr;
+ if (cur_head) {
+ ptr = cur_head;
+ cur_head = ptr->next;
+ } else {
+ cur_head = ptr = pl_copy.value.s64_integers;
+ }
+ g_assert_cmpint(pt->value.s64, ==, ptr->value);
+ break;
+ }
+ case PTYPE_U8: {
+ uint8List *ptr;
+ if (cur_head) {
+ ptr = cur_head;
+ cur_head = ptr->next;
+ } else {
+ cur_head = ptr = pl_copy.value.u8_integers;
+ }
+ g_assert_cmpint(pt->value.u8, ==, ptr->value);
+ break;
+ }
+ case PTYPE_U16: {
+ uint16List *ptr;
+ if (cur_head) {
+ ptr = cur_head;
+ cur_head = ptr->next;
+ } else {
+ cur_head = ptr = pl_copy.value.u16_integers;
+ }
+ g_assert_cmpint(pt->value.u16, ==, ptr->value);
+ break;
+ }
+ case PTYPE_U32: {
+ uint32List *ptr;
+ if (cur_head) {
+ ptr = cur_head;
+ cur_head = ptr->next;
+ } else {
+ cur_head = ptr = pl_copy.value.u32_integers;
+ }
+ g_assert_cmpint(pt->value.u32, ==, ptr->value);
+ break;
+ }
+ case PTYPE_U64: {
+ uint64List *ptr;
+ if (cur_head) {
+ ptr = cur_head;
+ cur_head = ptr->next;
+ } else {
+ cur_head = ptr = pl_copy.value.u64_integers;
+ }
+ g_assert_cmpint(pt->value.u64, ==, ptr->value);
+ break;
+ }
+ case PTYPE_NUMBER: {
+ numberList *ptr;
+ GString *double_expected = g_string_new("");
+ GString *double_actual = g_string_new("");
+ if (cur_head) {
+ ptr = cur_head;
+ cur_head = ptr->next;
+ } else {
+ cur_head = ptr = pl_copy.value.numbers;
+ }
+ /* we serialize with %f for our reference visitors, so rather than
+ * fuzzy floating math to test "equality", just compare the
+ * formatted values
+ */
+ g_string_printf(double_expected, "%.6f", pt->value.number);
+ g_string_printf(double_actual, "%.6f", ptr->value);
+ g_assert_cmpstr(double_actual->str, ==, double_expected->str);
+ g_string_free(double_expected, true);
+ g_string_free(double_actual, true);
+ break;
+ }
+ case PTYPE_BOOLEAN: {
+ boolList *ptr;
+ if (cur_head) {
+ ptr = cur_head;
+ cur_head = ptr->next;
+ } else {
+ cur_head = ptr = pl_copy.value.booleans;
+ }
+ g_assert_cmpint(!!pt->value.boolean, ==, !!ptr->value);
+ break;
+ }
+ default:
+ g_assert(0);
+ }
+ i++;
+ } while (cur_head);
+
+ g_assert_cmpint(i, ==, 33);
+
+ ops->cleanup(serialize_data);
+ dealloc_helper(&pl, visit_primitive_list, &err);
+ g_assert(!err);
+ dealloc_helper(&pl_copy, visit_primitive_list, &err);
+ g_assert(!err);
+ g_free(args);
+}
+
static void test_struct(gconstpointer opaque)
{
TestArgs *args = (TestArgs *) opaque;
@@ -728,7 +1120,8 @@ static const SerializeOps visitors[] = {
.serialize = qmp_serialize,
.deserialize = qmp_deserialize,
.cleanup = qmp_cleanup,
- .caps = VCAP_PRIMITIVES | VCAP_STRUCTURES | VCAP_LISTS
+ .caps = VCAP_PRIMITIVES | VCAP_STRUCTURES | VCAP_LISTS |
+ VCAP_PRIMITIVE_LISTS
},
{
.type = "String",
@@ -782,6 +1175,19 @@ static void add_visitor_type(const SerializeOps *ops)
args->test_data = NULL;
g_test_add_data_func(testname, args, test_nested_struct_list);
}
+
+ if (ops->caps & VCAP_PRIMITIVE_LISTS) {
+ i = 0;
+ while (pt_values[i].type != PTYPE_EOL) {
+ sprintf(testname, "%s/primitive_list/%s", testname_prefix,
+ pt_values[i].description);
+ args = g_malloc0(sizeof(*args));
+ args->ops = ops;
+ args->test_data = &pt_values[i];
+ g_test_add_data_func(testname, args, test_primitive_lists);
+ i++;
+ }
+ }
}
int main(int argc, char **argv)
diff --git a/trace-events b/trace-events
index b123b0f38d..c5f1ccb96d 100644
--- a/trace-events
+++ b/trace-events
@@ -822,7 +822,7 @@ qemu_coroutine_yield(void *from, void *to) "from %p to %p"
qemu_coroutine_terminate(void *co) "self %p"
# qemu-coroutine-lock.c
-qemu_co_queue_next_bh(void) ""
+qemu_co_queue_run_restart(void *co) "co %p"
qemu_co_queue_next(void *nxt) "next %p"
qemu_co_mutex_lock_entry(void *mutex, void *self) "mutex %p self %p"
qemu_co_mutex_lock_return(void *mutex, void *self) "mutex %p self %p"
diff --git a/translate-all.c b/translate-all.c
index 0d84b0d0c6..211be314cb 100644
--- a/translate-all.c
+++ b/translate-all.c
@@ -55,7 +55,6 @@
#else
#include "exec/address-spaces.h"
#endif
-#include "qemu/timer.h"
#include "exec/cputlb.h"
#include "translate-all.h"
diff --git a/ui/input.c b/ui/input.c
index 8ca1a03e12..92c44ca810 100644
--- a/ui/input.c
+++ b/ui/input.c
@@ -28,6 +28,7 @@
#include "qapi/error.h"
#include "qmp-commands.h"
#include "qapi-types.h"
+#include "ui/keymaps.h"
struct QEMUPutMouseEntry {
QEMUPutMouseEvent *qemu_put_mouse_event;
@@ -260,10 +261,10 @@ static void free_keycodes(void)
static void release_keys(void *opaque)
{
while (keycodes_size > 0) {
- if (keycodes[--keycodes_size] & 0x80) {
- kbd_put_keycode(0xe0);
+ if (keycodes[--keycodes_size] & SCANCODE_GREY) {
+ kbd_put_keycode(SCANCODE_EMUL0);
}
- kbd_put_keycode(keycodes[keycodes_size] | 0x80);
+ kbd_put_keycode(keycodes[keycodes_size] | SCANCODE_UP);
}
free_keycodes();
@@ -297,10 +298,10 @@ void qmp_send_key(KeyValueList *keys, bool has_hold_time, int64_t hold_time,
return;
}
- if (keycode & 0x80) {
- kbd_put_keycode(0xe0);
+ if (keycode & SCANCODE_GREY) {
+ kbd_put_keycode(SCANCODE_EMUL0);
}
- kbd_put_keycode(keycode & 0x7f);
+ kbd_put_keycode(keycode & SCANCODE_KEYCODEMASK);
keycodes = g_realloc(keycodes, sizeof(int) * (keycodes_size + 1));
keycodes[keycodes_size++] = keycode;
diff --git a/vl.c b/vl.c
index 59dc0b45da..510d2c2ce4 100644
--- a/vl.c
+++ b/vl.c
@@ -3366,8 +3366,10 @@ int main(int argc, char **argv, char **envp)
break;
}
case QEMU_OPTION_monitor:
- monitor_parse(optarg, "readline");
default_monitor = 0;
+ if (strncmp(optarg, "none", 4)) {
+ monitor_parse(optarg, "readline");
+ }
break;
case QEMU_OPTION_qmp:
monitor_parse(optarg, "control");