summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSeokYeon Hwang <syeon.hwang@samsung.com>2015-11-10 22:09:17 +0900
committerSeokYeon Hwang <syeon.hwang@samsung.com>2015-11-10 22:09:17 +0900
commitbe6540fef422bf5d63edf0a53d2e94c41ff173e6 (patch)
treecc3b8a89971601eb039fe97f6b7f99203b5babb5
parent7aafbd24cca1d5b83677ac467f82fbc370577533 (diff)
parent32d24131b2d1d98384b96c80f6cd3482550dc68a (diff)
downloadqemu-be6540fef422bf5d63edf0a53d2e94c41ff173e6.tar.gz
qemu-be6540fef422bf5d63edf0a53d2e94c41ff173e6.tar.bz2
qemu-be6540fef422bf5d63edf0a53d2e94c41ff173e6.zip
Merge tag 'v2.4.1' into tizen_3.0_develop
v2.4.1 Change-Id: I8d62d785e1d693dc2ce29ddc3bdaf4e5ad30da61 Signed-off-by: SeokYeon Hwang <syeon.hwang@samsung.com>
-rw-r--r--VERSION2
-rw-r--r--block/iscsi.c4
-rw-r--r--block/mirror.c15
-rw-r--r--block/nfs.c2
-rw-r--r--block/qcow2-cluster.c28
-rw-r--r--block/qcow2-refcount.c12
-rw-r--r--block/qcow2.h6
-rw-r--r--cpus.c12
-rw-r--r--hw/arm/allwinner-a10.c6
-rw-r--r--hw/arm/digic.c6
-rw-r--r--hw/arm/pxa2xx.c2
-rw-r--r--hw/arm/xlnx-zynqmp.c6
-rw-r--r--hw/block/virtio-blk.c12
-rw-r--r--hw/char/virtio-serial-bus.c2
-rw-r--r--hw/display/cg3.c4
-rw-r--r--hw/display/tcx.c2
-rw-r--r--hw/ide/ahci.c22
-rw-r--r--hw/ide/core.c35
-rw-r--r--hw/ide/internal.h1
-rw-r--r--hw/input/virtio-input.c4
-rw-r--r--hw/misc/arm_integrator_debug.c2
-rw-r--r--hw/misc/macio/cuda.c2
-rw-r--r--hw/misc/macio/mac_dbdma.c12
-rw-r--r--hw/misc/macio/macio.c14
-rw-r--r--hw/misc/zynq_slcr.c8
-rw-r--r--hw/net/rtl8139.c8
-rw-r--r--hw/net/vhost_net.c2
-rw-r--r--hw/net/virtio-net.c73
-rw-r--r--hw/net/vmxnet3.c1
-rw-r--r--hw/pci-host/versatile.c11
-rw-r--r--hw/pcmcia/pxa2xx.c6
-rw-r--r--hw/ppc/spapr_pci.c12
-rw-r--r--hw/s390x/css.c2
-rw-r--r--hw/scsi/scsi-disk.c4
-rw-r--r--hw/scsi/vhost-scsi.c2
-rw-r--r--hw/scsi/virtio-scsi.c13
-rw-r--r--hw/virtio/dataplane/vring.c79
-rw-r--r--hw/virtio/vhost.c4
-rw-r--r--hw/virtio/virtio-balloon.c2
-rw-r--r--hw/virtio/virtio.c35
-rw-r--r--include/exec/exec-all.h6
-rw-r--r--include/hw/qdev-core.h13
-rw-r--r--include/hw/virtio/dataplane/vring.h4
-rw-r--r--include/hw/virtio/virtio-access.h2
-rw-r--r--include/hw/virtio/virtio.h13
-rw-r--r--include/standard-headers/linux/input.h4
-rw-r--r--memory.c17
-rw-r--r--migration/migration.c8
-rw-r--r--nbd.c21
-rw-r--r--net/net.c8
-rwxr-xr-xpc-bios/u-boot.e500bin330260 -> 347788 bytes
-rw-r--r--qdev-monitor.c9
-rw-r--r--qemu-img.c3
-rw-r--r--qmp.c11
-rw-r--r--qom/object.c53
-rw-r--r--scripts/dump-guest-memory.py2
-rwxr-xr-xscripts/update-linux-headers.sh1
-rw-r--r--slirp/tcp_input.c8
-rw-r--r--target-alpha/cpu.c7
-rw-r--r--target-arm/arm-semi.c2
-rw-r--r--target-arm/cpu.c11
-rw-r--r--target-arm/translate-a64.c22
-rw-r--r--target-arm/translate.c10
-rw-r--r--target-arm/translate.h8
-rw-r--r--target-cris/cpu.c7
-rw-r--r--target-i386/cpu.c8
-rw-r--r--target-lm32/cpu.c7
-rw-r--r--target-m68k/cpu.c7
-rw-r--r--target-microblaze/cpu.c6
-rw-r--r--target-mips/cpu.c7
-rw-r--r--target-moxie/cpu.c7
-rw-r--r--target-openrisc/cpu.c7
-rw-r--r--target-ppc/int_helper.c19
-rw-r--r--target-ppc/kvm.c4
-rw-r--r--target-ppc/translate.c11
-rw-r--r--target-s390x/cpu.c7
-rw-r--r--target-s390x/kvm.c3
-rw-r--r--target-sh4/cpu.c7
-rw-r--r--target-sparc/cpu.c7
-rw-r--r--target-tricore/cpu.c6
-rw-r--r--target-unicore32/cpu.c7
-rw-r--r--target-xtensa/cpu.c7
-rw-r--r--target-xtensa/translate.c6
-rw-r--r--tcg/aarch64/tcg-target.c28
-rw-r--r--tcg/mips/tcg-target.c26
-rw-r--r--tests/Makefile20
-rw-r--r--tests/device-introspect-test.c158
-rw-r--r--tests/drive_del-test.c22
-rw-r--r--tests/ide-test.c8
-rw-r--r--tests/libqtest.c37
-rw-r--r--tests/libqtest.h33
-rw-r--r--trace-events3
-rw-r--r--ui/gtk.c21
-rw-r--r--util/qemu-config.c8
-rw-r--r--vl.c33
95 files changed, 919 insertions, 336 deletions
diff --git a/VERSION b/VERSION
index 81b7c51245..005119baaa 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.4.0.1
+2.4.1
diff --git a/block/iscsi.c b/block/iscsi.c
index 50029168eb..93f1ee4c63 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -1214,6 +1214,10 @@ static void iscsi_readcapacity_sync(IscsiLun *iscsilun, Error **errp)
if (task == NULL || task->status != SCSI_STATUS_GOOD) {
error_setg(errp, "iSCSI: failed to send readcapacity10 command.");
+ } else if (!iscsilun->block_size ||
+ iscsilun->block_size % BDRV_SECTOR_SIZE) {
+ error_setg(errp, "iSCSI: the target returned an invalid "
+ "block size of %d.", iscsilun->block_size);
}
if (task) {
scsi_free_scsi_task(task);
diff --git a/block/mirror.c b/block/mirror.c
index fc4d8f561e..b2fb4b9b1a 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -60,6 +60,7 @@ typedef struct MirrorBlockJob {
int sectors_in_flight;
int ret;
bool unmap;
+ bool waiting_for_io;
} MirrorBlockJob;
typedef struct MirrorOp {
@@ -114,11 +115,7 @@ static void mirror_iteration_done(MirrorOp *op, int ret)
qemu_iovec_destroy(&op->qiov);
g_slice_free(MirrorOp, op);
- /* Enter coroutine when it is not sleeping. The coroutine sleeps to
- * rate-limit itself. The coroutine will eventually resume since there is
- * a sleep timeout so don't wake it early.
- */
- if (s->common.busy) {
+ if (s->waiting_for_io) {
qemu_coroutine_enter(s->common.co, NULL);
}
}
@@ -203,7 +200,9 @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s)
/* Wait for I/O to this cluster (from a previous iteration) to be done. */
while (test_bit(next_chunk, s->in_flight_bitmap)) {
trace_mirror_yield_in_flight(s, sector_num, s->in_flight);
+ s->waiting_for_io = true;
qemu_coroutine_yield();
+ s->waiting_for_io = false;
}
do {
@@ -239,7 +238,9 @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s)
*/
while (nb_chunks == 0 && s->buf_free_count < added_chunks) {
trace_mirror_yield_buf_busy(s, nb_chunks, s->in_flight);
+ s->waiting_for_io = true;
qemu_coroutine_yield();
+ s->waiting_for_io = false;
}
if (s->buf_free_count < nb_chunks + added_chunks) {
trace_mirror_break_buf_busy(s, nb_chunks, s->in_flight);
@@ -333,7 +334,9 @@ static void mirror_free_init(MirrorBlockJob *s)
static void mirror_drain(MirrorBlockJob *s)
{
while (s->in_flight > 0) {
+ s->waiting_for_io = true;
qemu_coroutine_yield();
+ s->waiting_for_io = false;
}
}
@@ -506,7 +509,9 @@ static void coroutine_fn mirror_run(void *opaque)
if (s->in_flight == MAX_IN_FLIGHT || s->buf_free_count == 0 ||
(cnt == 0 && s->in_flight > 0)) {
trace_mirror_yield(s, s->in_flight, s->buf_free_count, cnt);
+ s->waiting_for_io = true;
qemu_coroutine_yield();
+ s->waiting_for_io = false;
continue;
} else if (cnt != 0) {
delay_ns = mirror_iteration(s);
diff --git a/block/nfs.c b/block/nfs.c
index c026ff6883..02eb4e4643 100644
--- a/block/nfs.c
+++ b/block/nfs.c
@@ -475,7 +475,7 @@ static int64_t nfs_get_allocated_file_size(BlockDriverState *bs)
aio_poll(client->aio_context, true);
}
- return (task.ret < 0 ? task.ret : st.st_blocks * st.st_blksize);
+ return (task.ret < 0 ? task.ret : st.st_blocks * 512);
}
static int nfs_file_truncate(BlockDriverState *bs, int64_t offset)
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index b43f186eb8..7e94fe70e9 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -298,7 +298,7 @@ fail:
* as contiguous. (This allows it, for example, to stop at the first compressed
* cluster which may require a different handling)
*/
-static int count_contiguous_clusters(uint64_t nb_clusters, int cluster_size,
+static int count_contiguous_clusters(int nb_clusters, int cluster_size,
uint64_t *l2_table, uint64_t stop_flags)
{
int i;
@@ -321,7 +321,7 @@ static int count_contiguous_clusters(uint64_t nb_clusters, int cluster_size,
return i;
}
-static int count_contiguous_free_clusters(uint64_t nb_clusters, uint64_t *l2_table)
+static int count_contiguous_free_clusters(int nb_clusters, uint64_t *l2_table)
{
int i;
@@ -495,6 +495,7 @@ int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,
if (nb_needed > nb_available) {
nb_needed = nb_available;
}
+ assert(nb_needed <= INT_MAX);
*cluster_offset = 0;
@@ -530,6 +531,8 @@ int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,
l2_index = (offset >> s->cluster_bits) & (s->l2_size - 1);
*cluster_offset = be64_to_cpu(l2_table[l2_index]);
+
+ /* nb_needed <= INT_MAX, thus nb_clusters <= INT_MAX, too */
nb_clusters = size_to_clusters(s, nb_needed << 9);
ret = qcow2_get_cluster_type(*cluster_offset);
@@ -960,7 +963,7 @@ static int handle_copied(BlockDriverState *bs, uint64_t guest_offset,
int l2_index;
uint64_t cluster_offset;
uint64_t *l2_table;
- unsigned int nb_clusters;
+ uint64_t nb_clusters;
unsigned int keep_clusters;
int ret;
@@ -979,6 +982,7 @@ static int handle_copied(BlockDriverState *bs, uint64_t guest_offset,
l2_index = offset_to_l2_index(s, guest_offset);
nb_clusters = MIN(nb_clusters, s->l2_size - l2_index);
+ assert(nb_clusters <= INT_MAX);
/* Find L2 entry for the first involved cluster */
ret = get_cluster_table(bs, guest_offset, &l2_table, &l2_index);
@@ -1061,7 +1065,7 @@ out:
* restarted, but the whole request should not be failed.
*/
static int do_alloc_cluster_offset(BlockDriverState *bs, uint64_t guest_offset,
- uint64_t *host_offset, unsigned int *nb_clusters)
+ uint64_t *host_offset, uint64_t *nb_clusters)
{
BDRVQcowState *s = bs->opaque;
@@ -1079,7 +1083,7 @@ static int do_alloc_cluster_offset(BlockDriverState *bs, uint64_t guest_offset,
*host_offset = cluster_offset;
return 0;
} else {
- int ret = qcow2_alloc_clusters_at(bs, *host_offset, *nb_clusters);
+ int64_t ret = qcow2_alloc_clusters_at(bs, *host_offset, *nb_clusters);
if (ret < 0) {
return ret;
}
@@ -1115,7 +1119,7 @@ static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
int l2_index;
uint64_t *l2_table;
uint64_t entry;
- unsigned int nb_clusters;
+ uint64_t nb_clusters;
int ret;
uint64_t alloc_cluster_offset;
@@ -1133,6 +1137,7 @@ static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
l2_index = offset_to_l2_index(s, guest_offset);
nb_clusters = MIN(nb_clusters, s->l2_size - l2_index);
+ assert(nb_clusters <= INT_MAX);
/* Find L2 entry for the first involved cluster */
ret = get_cluster_table(bs, guest_offset, &l2_table, &l2_index);
@@ -1426,7 +1431,8 @@ int qcow2_decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset)
* clusters.
*/
static int discard_single_l2(BlockDriverState *bs, uint64_t offset,
- unsigned int nb_clusters, enum qcow2_discard_type type, bool full_discard)
+ uint64_t nb_clusters, enum qcow2_discard_type type,
+ bool full_discard)
{
BDRVQcowState *s = bs->opaque;
uint64_t *l2_table;
@@ -1441,6 +1447,7 @@ static int discard_single_l2(BlockDriverState *bs, uint64_t offset,
/* Limit nb_clusters to one L2 table */
nb_clusters = MIN(nb_clusters, s->l2_size - l2_index);
+ assert(nb_clusters <= INT_MAX);
for (i = 0; i < nb_clusters; i++) {
uint64_t old_l2_entry;
@@ -1503,7 +1510,7 @@ int qcow2_discard_clusters(BlockDriverState *bs, uint64_t offset,
{
BDRVQcowState *s = bs->opaque;
uint64_t end_offset;
- unsigned int nb_clusters;
+ uint64_t nb_clusters;
int ret;
end_offset = offset + (nb_sectors << BDRV_SECTOR_BITS);
@@ -1545,7 +1552,7 @@ fail:
* clusters.
*/
static int zero_single_l2(BlockDriverState *bs, uint64_t offset,
- unsigned int nb_clusters)
+ uint64_t nb_clusters)
{
BDRVQcowState *s = bs->opaque;
uint64_t *l2_table;
@@ -1560,6 +1567,7 @@ static int zero_single_l2(BlockDriverState *bs, uint64_t offset,
/* Limit nb_clusters to one L2 table */
nb_clusters = MIN(nb_clusters, s->l2_size - l2_index);
+ assert(nb_clusters <= INT_MAX);
for (i = 0; i < nb_clusters; i++) {
uint64_t old_offset;
@@ -1584,7 +1592,7 @@ static int zero_single_l2(BlockDriverState *bs, uint64_t offset,
int qcow2_zero_clusters(BlockDriverState *bs, uint64_t offset, int nb_sectors)
{
BDRVQcowState *s = bs->opaque;
- unsigned int nb_clusters;
+ uint64_t nb_clusters;
int ret;
/* The zero flag is only supported by version 3 and newer */
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index b0ee42d81b..0b6c302ee1 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -875,8 +875,8 @@ int64_t qcow2_alloc_clusters(BlockDriverState *bs, uint64_t size)
return offset;
}
-int qcow2_alloc_clusters_at(BlockDriverState *bs, uint64_t offset,
- int nb_clusters)
+int64_t qcow2_alloc_clusters_at(BlockDriverState *bs, uint64_t offset,
+ int64_t nb_clusters)
{
BDRVQcowState *s = bs->opaque;
uint64_t cluster_index, refcount;
@@ -1259,7 +1259,7 @@ static size_t refcount_array_byte_size(BDRVQcowState *s, uint64_t entries)
static int realloc_refcount_array(BDRVQcowState *s, void **array,
int64_t *size, int64_t new_size)
{
- size_t old_byte_size, new_byte_size;
+ int64_t old_byte_size, new_byte_size;
void *new_ptr;
/* Round to clusters so the array can be directly written to disk */
@@ -1275,13 +1275,17 @@ static int realloc_refcount_array(BDRVQcowState *s, void **array,
assert(new_byte_size > 0);
+ if (new_byte_size > SIZE_MAX) {
+ return -ENOMEM;
+ }
+
new_ptr = g_try_realloc(*array, new_byte_size);
if (!new_ptr) {
return -ENOMEM;
}
if (new_byte_size > old_byte_size) {
- memset((void *)((uintptr_t)new_ptr + old_byte_size), 0,
+ memset((char *)new_ptr + old_byte_size, 0,
new_byte_size - old_byte_size);
}
diff --git a/block/qcow2.h b/block/qcow2.h
index 72e132838a..4b5a6afc80 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -412,7 +412,7 @@ static inline int64_t offset_into_cluster(BDRVQcowState *s, int64_t offset)
return offset & (s->cluster_size - 1);
}
-static inline int size_to_clusters(BDRVQcowState *s, int64_t size)
+static inline uint64_t size_to_clusters(BDRVQcowState *s, uint64_t size)
{
return (size + (s->cluster_size - 1)) >> s->cluster_bits;
}
@@ -506,8 +506,8 @@ int qcow2_update_cluster_refcount(BlockDriverState *bs, int64_t cluster_index,
enum qcow2_discard_type type);
int64_t qcow2_alloc_clusters(BlockDriverState *bs, uint64_t size);
-int qcow2_alloc_clusters_at(BlockDriverState *bs, uint64_t offset,
- int nb_clusters);
+int64_t qcow2_alloc_clusters_at(BlockDriverState *bs, uint64_t offset,
+ int64_t nb_clusters);
int64_t qcow2_alloc_bytes(BlockDriverState *bs, int size);
void qcow2_free_clusters(BlockDriverState *bs,
int64_t offset, int64_t size,
diff --git a/cpus.c b/cpus.c
index ce4fa3876a..b4c53491ff 100644
--- a/cpus.c
+++ b/cpus.c
@@ -1185,7 +1185,8 @@ void qemu_cpu_kick(CPUState *cpu)
{
qemu_cond_broadcast(cpu->halt_cond);
#ifdef CONFIG_HAX
- if (((hax_enabled() && hax_ug_platform()) || !tcg_enabled()) && !cpu->thread_kicked) {
+ if (((hax_enabled() && hax_ug_platform()) ||
+ !tcg_enabled()) && !cpu->thread_kicked) {
#else
if (!tcg_enabled() && !cpu->thread_kicked) {
#endif
@@ -1231,14 +1232,11 @@ void qemu_mutex_lock_iothread(void)
/* In the simple case there is no need to bump the VCPU thread out of
* TCG code execution.
*/
-#ifdef CONFIG_HAX
- if (!tcg_enabled() || qemu_in_vcpu_thread() ||
- !first_cpu || !first_cpu->thread ||
- (hax_enabled() && hax_ug_platform())) {
-#else
if (!tcg_enabled() || qemu_in_vcpu_thread() ||
- !first_cpu || !first_cpu->thread) {
+#ifdef CONFIG_HAX
+ (hax_enabled() && hax_ug_platform()) ||
#endif
+ !first_cpu || !first_cpu->created) {
qemu_mutex_lock(&qemu_global_mutex);
atomic_dec(&iothread_requesting_mutex);
} else {
diff --git a/hw/arm/allwinner-a10.c b/hw/arm/allwinner-a10.c
index ff249af335..43dc0a12de 100644
--- a/hw/arm/allwinner-a10.c
+++ b/hw/arm/allwinner-a10.c
@@ -103,6 +103,12 @@ static void aw_a10_class_init(ObjectClass *oc, void *data)
DeviceClass *dc = DEVICE_CLASS(oc);
dc->realize = aw_a10_realize;
+
+ /*
+ * Reason: creates an ARM CPU, thus use after free(), see
+ * arm_cpu_class_init()
+ */
+ dc->cannot_destroy_with_object_finalize_yet = true;
}
static const TypeInfo aw_a10_type_info = {
diff --git a/hw/arm/digic.c b/hw/arm/digic.c
index ec8c330602..90f8190c48 100644
--- a/hw/arm/digic.c
+++ b/hw/arm/digic.c
@@ -97,6 +97,12 @@ static void digic_class_init(ObjectClass *oc, void *data)
DeviceClass *dc = DEVICE_CLASS(oc);
dc->realize = digic_realize;
+
+ /*
+ * Reason: creates an ARM CPU, thus use after free(), see
+ * arm_cpu_class_init()
+ */
+ dc->cannot_destroy_with_object_finalize_yet = true;
}
static const TypeInfo digic_type_info = {
diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c
index ec353f79c4..d94e20777f 100644
--- a/hw/arm/pxa2xx.c
+++ b/hw/arm/pxa2xx.c
@@ -1959,7 +1959,7 @@ static void pxa2xx_fir_instance_init(Object *obj)
PXA2xxFIrState *s = PXA2XX_FIR(obj);
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
- memory_region_init_io(&s->iomem, NULL, &pxa2xx_fir_ops, s,
+ memory_region_init_io(&s->iomem, obj, &pxa2xx_fir_ops, s,
"pxa2xx-fir", 0x1000);
sysbus_init_mmio(sbd, &s->iomem);
sysbus_init_irq(sbd, &s->irq);
diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
index 62ef4ceb32..5157565f99 100644
--- a/hw/arm/xlnx-zynqmp.c
+++ b/hw/arm/xlnx-zynqmp.c
@@ -248,6 +248,12 @@ static void xlnx_zynqmp_class_init(ObjectClass *oc, void *data)
dc->props = xlnx_zynqmp_props;
dc->realize = xlnx_zynqmp_realize;
+
+ /*
+ * Reason: creates an ARM CPU, thus use after free(), see
+ * arm_cpu_class_init()
+ */
+ dc->cannot_destroy_with_object_finalize_yet = true;
}
static const TypeInfo xlnx_zynqmp_type_info = {
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
index 1556c9cf5a..5625a9fa76 100644
--- a/hw/block/virtio-blk.c
+++ b/hw/block/virtio-blk.c
@@ -731,7 +731,7 @@ static uint64_t virtio_blk_get_features(VirtIODevice *vdev, uint64_t features,
virtio_add_feature(&features, VIRTIO_BLK_F_GEOMETRY);
virtio_add_feature(&features, VIRTIO_BLK_F_TOPOLOGY);
virtio_add_feature(&features, VIRTIO_BLK_F_BLK_SIZE);
- if (__virtio_has_feature(features, VIRTIO_F_VERSION_1)) {
+ if (virtio_has_feature(features, VIRTIO_F_VERSION_1)) {
if (s->conf.scsi) {
error_setg(errp, "Please set scsi=off for virtio-blk devices in order to use virtio 1.0");
return 0;
@@ -782,10 +782,11 @@ static void virtio_blk_set_status(VirtIODevice *vdev, uint8_t status)
*
* s->blk would erroneously be placed in writethrough mode.
*/
- if (!virtio_has_feature(vdev, VIRTIO_BLK_F_CONFIG_WCE)) {
+ if (!virtio_vdev_has_feature(vdev, VIRTIO_BLK_F_CONFIG_WCE)) {
aio_context_acquire(blk_get_aio_context(s->blk));
blk_set_enable_write_cache(s->blk,
- virtio_has_feature(vdev, VIRTIO_BLK_F_WCE));
+ virtio_vdev_has_feature(vdev,
+ VIRTIO_BLK_F_WCE));
aio_context_release(blk_get_aio_context(s->blk));
}
}
@@ -793,6 +794,11 @@ static void virtio_blk_set_status(VirtIODevice *vdev, uint8_t status)
static void virtio_blk_save(QEMUFile *f, void *opaque)
{
VirtIODevice *vdev = VIRTIO_DEVICE(opaque);
+ VirtIOBlock *s = VIRTIO_BLK(vdev);
+
+ if (s->dataplane) {
+ virtio_blk_data_plane_stop(s->dataplane);
+ }
virtio_save(vdev, f);
}
diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c
index bc56f5d520..be97058712 100644
--- a/hw/char/virtio-serial-bus.c
+++ b/hw/char/virtio-serial-bus.c
@@ -76,7 +76,7 @@ static VirtIOSerialPort *find_port_by_name(char *name)
static bool use_multiport(VirtIOSerial *vser)
{
VirtIODevice *vdev = VIRTIO_DEVICE(vser);
- return virtio_has_feature(vdev, VIRTIO_CONSOLE_F_MULTIPORT);
+ return virtio_vdev_has_feature(vdev, VIRTIO_CONSOLE_F_MULTIPORT);
}
static size_t write_to_port(VirtIOSerialPort *port,
diff --git a/hw/display/cg3.c b/hw/display/cg3.c
index 34dcbc3119..2d3bd70817 100644
--- a/hw/display/cg3.c
+++ b/hw/display/cg3.c
@@ -280,12 +280,12 @@ static void cg3_initfn(Object *obj)
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
CG3State *s = CG3(obj);
- memory_region_init_ram(&s->rom, NULL, "cg3.prom", FCODE_MAX_ROM_SIZE,
+ memory_region_init_ram(&s->rom, obj, "cg3.prom", FCODE_MAX_ROM_SIZE,
&error_abort);
memory_region_set_readonly(&s->rom, true);
sysbus_init_mmio(sbd, &s->rom);
- memory_region_init_io(&s->reg, NULL, &cg3_reg_ops, s, "cg3.reg",
+ memory_region_init_io(&s->reg, obj, &cg3_reg_ops, s, "cg3.reg",
CG3_REG_SIZE);
sysbus_init_mmio(sbd, &s->reg);
}
diff --git a/hw/display/tcx.c b/hw/display/tcx.c
index 6acdc2d282..327ce30196 100644
--- a/hw/display/tcx.c
+++ b/hw/display/tcx.c
@@ -944,7 +944,7 @@ static void tcx_initfn(Object *obj)
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
TCXState *s = TCX(obj);
- memory_region_init_ram(&s->rom, NULL, "tcx.prom", FCODE_MAX_ROM_SIZE,
+ memory_region_init_ram(&s->rom, OBJECT(s), "tcx.prom", FCODE_MAX_ROM_SIZE,
&error_abort);
memory_region_set_readonly(&s->rom, true);
sysbus_init_mmio(sbd, &s->rom);
diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
index 48749c1dc1..378ad60c3c 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -50,7 +50,6 @@ static void ahci_reset_port(AHCIState *s, int port);
static void ahci_write_fis_d2h(AHCIDevice *ad, uint8_t *cmd_fis);
static void ahci_init_d2h(AHCIDevice *ad);
static int ahci_dma_prepare_buf(IDEDMA *dma, int32_t limit);
-static void ahci_commit_buf(IDEDMA *dma, uint32_t tx_bytes);
static bool ahci_map_clb_address(AHCIDevice *ad);
static bool ahci_map_fis_address(AHCIDevice *ad);
static void ahci_unmap_clb_address(AHCIDevice *ad);
@@ -1290,7 +1289,7 @@ out:
s->data_ptr = s->data_end;
/* Update number of transferred bytes, destroy sglist */
- ahci_commit_buf(dma, size);
+ dma_buf_commit(s, size);
s->end_transfer_func(s);
@@ -1332,9 +1331,8 @@ static void ahci_restart(IDEDMA *dma)
}
/**
- * Called in DMA R/W chains to read the PRDT, utilizing ahci_populate_sglist.
- * Not currently invoked by PIO R/W chains,
- * which invoke ahci_populate_sglist via ahci_start_transfer.
+ * Called in DMA and PIO R/W chains to read the PRDT.
+ * Not shared with NCQ pathways.
*/
static int32_t ahci_dma_prepare_buf(IDEDMA *dma, int32_t limit)
{
@@ -1353,21 +1351,16 @@ static int32_t ahci_dma_prepare_buf(IDEDMA *dma, int32_t limit)
}
/**
- * Destroys the scatter-gather list,
- * and updates the command header with a bytes-read value.
- * called explicitly via ahci_dma_rw_buf (ATAPI DMA),
- * and ahci_start_transfer (PIO R/W),
- * and called via callback from ide_dma_cb for DMA R/W paths.
+ * Updates the command header with a bytes-read value.
+ * Called via dma_buf_commit, for both DMA and PIO paths.
+ * sglist destruction is handled within dma_buf_commit.
*/
static void ahci_commit_buf(IDEDMA *dma, uint32_t tx_bytes)
{
AHCIDevice *ad = DO_UPCAST(AHCIDevice, dma, dma);
- IDEState *s = &ad->port.ifs[0];
tx_bytes += le32_to_cpu(ad->cur_cmd->status);
ad->cur_cmd->status = cpu_to_le32(tx_bytes);
-
- qemu_sglist_destroy(&s->sg);
}
static int ahci_dma_rw_buf(IDEDMA *dma, int is_write)
@@ -1388,10 +1381,9 @@ static int ahci_dma_rw_buf(IDEDMA *dma, int is_write)
}
/* free sglist, update byte count */
- ahci_commit_buf(dma, l);
+ dma_buf_commit(s, l);
s->io_buffer_index += l;
- s->io_buffer_offset += l;
DPRINTF(ad->port_no, "len=%#x\n", l);
diff --git a/hw/ide/core.c b/hw/ide/core.c
index 50449cae09..1cc6945d80 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -591,7 +591,6 @@ static void ide_sector_read_cb(void *opaque, int ret)
s->nsector -= n;
/* Allow the guest to read the io_buffer */
ide_transfer_start(s, s->io_buffer, n * BDRV_SECTOR_SIZE, ide_sector_read);
- s->io_buffer_offset += 512 * n;
ide_set_irq(s->bus);
}
@@ -635,11 +634,12 @@ static void ide_sector_read(IDEState *s)
ide_sector_read_cb, s);
}
-static void dma_buf_commit(IDEState *s, uint32_t tx_bytes)
+void dma_buf_commit(IDEState *s, uint32_t tx_bytes)
{
if (s->bus->dma->ops->commit_buf) {
s->bus->dma->ops->commit_buf(s->bus->dma, tx_bytes);
}
+ s->io_buffer_offset += tx_bytes;
qemu_sglist_destroy(&s->sg);
}
@@ -842,7 +842,6 @@ static void ide_sector_write_cb(void *opaque, int ret)
n = s->req_nb_sectors;
}
s->nsector -= n;
- s->io_buffer_offset += 512 * n;
ide_set_sector(s, ide_get_sector(s) + n);
if (s->nsector == 0) {
@@ -1747,11 +1746,11 @@ static const struct {
} ide_cmd_table[0x100] = {
/* NOP not implemented, mandatory for CD */
[CFA_REQ_EXT_ERROR_CODE] = { cmd_cfa_req_ext_error_code, CFA_OK },
- [WIN_DSM] = { cmd_data_set_management, ALL_OK },
+ [WIN_DSM] = { cmd_data_set_management, HD_CFA_OK },
[WIN_DEVICE_RESET] = { cmd_device_reset, CD_OK },
[WIN_RECAL] = { cmd_nop, HD_CFA_OK | SET_DSC},
[WIN_READ] = { cmd_read_pio, ALL_OK },
- [WIN_READ_ONCE] = { cmd_read_pio, ALL_OK },
+ [WIN_READ_ONCE] = { cmd_read_pio, HD_CFA_OK },
[WIN_READ_EXT] = { cmd_read_pio, HD_CFA_OK },
[WIN_READDMA_EXT] = { cmd_read_dma, HD_CFA_OK },
[WIN_READ_NATIVE_MAX_EXT] = { cmd_read_native_max, HD_CFA_OK | SET_DSC },
@@ -1770,12 +1769,12 @@ static const struct {
[CFA_TRANSLATE_SECTOR] = { cmd_cfa_translate_sector, CFA_OK },
[WIN_DIAGNOSE] = { cmd_exec_dev_diagnostic, ALL_OK },
[WIN_SPECIFY] = { cmd_nop, HD_CFA_OK | SET_DSC },
- [WIN_STANDBYNOW2] = { cmd_nop, ALL_OK },
- [WIN_IDLEIMMEDIATE2] = { cmd_nop, ALL_OK },
- [WIN_STANDBY2] = { cmd_nop, ALL_OK },
- [WIN_SETIDLE2] = { cmd_nop, ALL_OK },
- [WIN_CHECKPOWERMODE2] = { cmd_check_power_mode, ALL_OK | SET_DSC },
- [WIN_SLEEPNOW2] = { cmd_nop, ALL_OK },
+ [WIN_STANDBYNOW2] = { cmd_nop, HD_CFA_OK },
+ [WIN_IDLEIMMEDIATE2] = { cmd_nop, HD_CFA_OK },
+ [WIN_STANDBY2] = { cmd_nop, HD_CFA_OK },
+ [WIN_SETIDLE2] = { cmd_nop, HD_CFA_OK },
+ [WIN_CHECKPOWERMODE2] = { cmd_check_power_mode, HD_CFA_OK | SET_DSC },
+ [WIN_SLEEPNOW2] = { cmd_nop, HD_CFA_OK },
[WIN_PACKETCMD] = { cmd_packet, CD_OK },
[WIN_PIDENTIFY] = { cmd_identify_packet, CD_OK },
[WIN_SMART] = { cmd_smart, HD_CFA_OK | SET_DSC },
@@ -1789,19 +1788,19 @@ static const struct {
[WIN_WRITEDMA] = { cmd_write_dma, HD_CFA_OK },
[WIN_WRITEDMA_ONCE] = { cmd_write_dma, HD_CFA_OK },
[CFA_WRITE_MULTI_WO_ERASE] = { cmd_write_multiple, CFA_OK },
- [WIN_STANDBYNOW1] = { cmd_nop, ALL_OK },
- [WIN_IDLEIMMEDIATE] = { cmd_nop, ALL_OK },
- [WIN_STANDBY] = { cmd_nop, ALL_OK },
- [WIN_SETIDLE1] = { cmd_nop, ALL_OK },
- [WIN_CHECKPOWERMODE1] = { cmd_check_power_mode, ALL_OK | SET_DSC },
- [WIN_SLEEPNOW1] = { cmd_nop, ALL_OK },
+ [WIN_STANDBYNOW1] = { cmd_nop, HD_CFA_OK },
+ [WIN_IDLEIMMEDIATE] = { cmd_nop, HD_CFA_OK },
+ [WIN_STANDBY] = { cmd_nop, HD_CFA_OK },
+ [WIN_SETIDLE1] = { cmd_nop, HD_CFA_OK },
+ [WIN_CHECKPOWERMODE1] = { cmd_check_power_mode, HD_CFA_OK | SET_DSC },
+ [WIN_SLEEPNOW1] = { cmd_nop, HD_CFA_OK },
[WIN_FLUSH_CACHE] = { cmd_flush_cache, ALL_OK },
[WIN_FLUSH_CACHE_EXT] = { cmd_flush_cache, HD_CFA_OK },
[WIN_IDENTIFY] = { cmd_identify, ALL_OK },
[WIN_SETFEATURES] = { cmd_set_features, ALL_OK | SET_DSC },
[IBM_SENSE_CONDITION] = { cmd_ibm_sense_condition, CFA_OK | SET_DSC },
[CFA_WEAR_LEVEL] = { cmd_cfa_erase_sectors, HD_CFA_OK | SET_DSC },
- [WIN_READ_NATIVE_MAX] = { cmd_read_native_max, ALL_OK | SET_DSC },
+ [WIN_READ_NATIVE_MAX] = { cmd_read_native_max, HD_CFA_OK | SET_DSC },
};
static bool ide_cmd_permitted(IDEState *s, uint32_t cmd)
diff --git a/hw/ide/internal.h b/hw/ide/internal.h
index 30fdcbc5fa..7288a677a4 100644
--- a/hw/ide/internal.h
+++ b/hw/ide/internal.h
@@ -536,6 +536,7 @@ int64_t ide_get_sector(IDEState *s);
void ide_set_sector(IDEState *s, int64_t sector_num);
void ide_start_dma(IDEState *s, BlockCompletionFunc *cb);
+void dma_buf_commit(IDEState *s, uint32_t tx_bytes);
void ide_dma_error(IDEState *s);
void ide_atapi_cmd_ok(IDEState *s);
diff --git a/hw/input/virtio-input.c b/hw/input/virtio-input.c
index 7b25d27693..1f5a40de35 100644
--- a/hw/input/virtio-input.c
+++ b/hw/input/virtio-input.c
@@ -20,6 +20,10 @@ void virtio_input_send(VirtIOInput *vinput, virtio_input_event *event)
unsigned have, need;
int i, len;
+ if (!vinput->active) {
+ return;
+ }
+
/* queue up events ... */
if (vinput->qindex == vinput->qsize) {
vinput->qsize++;
diff --git a/hw/misc/arm_integrator_debug.c b/hw/misc/arm_integrator_debug.c
index 99b720fbb9..6d9dd74e38 100644
--- a/hw/misc/arm_integrator_debug.c
+++ b/hw/misc/arm_integrator_debug.c
@@ -79,7 +79,7 @@ static void intdbg_control_init(Object *obj)
SysBusDevice *sd = SYS_BUS_DEVICE(obj);
IntegratorDebugState *s = INTEGRATOR_DEBUG(obj);
- memory_region_init_io(&s->iomem, NULL, &intdbg_control_ops,
+ memory_region_init_io(&s->iomem, obj, &intdbg_control_ops,
NULL, "dbg-leds", 0x1000000);
sysbus_init_mmio(sd, &s->iomem);
}
diff --git a/hw/misc/macio/cuda.c b/hw/misc/macio/cuda.c
index f3984e3a20..5d7043e99c 100644
--- a/hw/misc/macio/cuda.c
+++ b/hw/misc/macio/cuda.c
@@ -713,7 +713,7 @@ static void cuda_initfn(Object *obj)
CUDAState *s = CUDA(obj);
int i;
- memory_region_init_io(&s->mem, NULL, &cuda_ops, s, "cuda", 0x2000);
+ memory_region_init_io(&s->mem, obj, &cuda_ops, s, "cuda", 0x2000);
sysbus_init_mmio(d, &s->mem);
sysbus_init_irq(d, &s->irq);
diff --git a/hw/misc/macio/mac_dbdma.c b/hw/misc/macio/mac_dbdma.c
index b25e8511b2..779683cc07 100644
--- a/hw/misc/macio/mac_dbdma.c
+++ b/hw/misc/macio/mac_dbdma.c
@@ -590,10 +590,11 @@ dbdma_control_write(DBDMA_channel *ch)
if ((ch->regs[DBDMA_STATUS] & RUN) && !(status & RUN)) {
/* RUN is cleared */
status &= ~(ACTIVE|DEAD);
- if ((status & FLUSH) && ch->flush) {
- ch->flush(&ch->io);
- status &= ~FLUSH;
- }
+ }
+
+ if ((status & FLUSH) && ch->flush) {
+ ch->flush(&ch->io);
+ status &= ~FLUSH;
}
DBDMA_DPRINTF(" status 0x%08x\n", status);
@@ -603,9 +604,6 @@ dbdma_control_write(DBDMA_channel *ch)
if (status & ACTIVE) {
DBDMA_kick(dbdma_from_ch(ch));
}
- if ((status & FLUSH) && ch->flush) {
- ch->flush(&ch->io);
- }
}
static void dbdma_write(void *opaque, hwaddr addr,
diff --git a/hw/misc/macio/macio.c b/hw/misc/macio/macio.c
index e3c0242d41..c661f86c21 100644
--- a/hw/misc/macio/macio.c
+++ b/hw/misc/macio/macio.c
@@ -105,10 +105,10 @@ static void macio_escc_legacy_setup(MacIOState *macio_state)
0xF0, 0xE0,
};
- memory_region_init(escc_legacy, NULL, "escc-legacy", 256);
+ memory_region_init(escc_legacy, OBJECT(macio_state), "escc-legacy", 256);
for (i = 0; i < ARRAY_SIZE(maps); i += 2) {
MemoryRegion *port = g_new(MemoryRegion, 1);
- memory_region_init_alias(port, NULL, "escc-legacy-port",
+ memory_region_init_alias(port, OBJECT(macio_state), "escc-legacy-port",
macio_state->escc_mem, maps[i+1], 0x2);
memory_region_add_subregion(escc_legacy, maps[i], port);
}
@@ -131,6 +131,10 @@ static void macio_common_realize(PCIDevice *d, Error **errp)
MacIOState *s = MACIO(d);
SysBusDevice *sysbus_dev;
Error *err = NULL;
+ MemoryRegion *dbdma_mem;
+
+ s->dbdma = DBDMA_init(&dbdma_mem);
+ memory_region_add_subregion(&s->bar, 0x08000, dbdma_mem);
object_property_set_bool(OBJECT(&s->cuda), true, "realized", &err);
if (err) {
@@ -328,16 +332,12 @@ static void macio_newworld_init(Object *obj)
static void macio_instance_init(Object *obj)
{
MacIOState *s = MACIO(obj);
- MemoryRegion *dbdma_mem;
- memory_region_init(&s->bar, NULL, "macio", 0x80000);
+ memory_region_init(&s->bar, obj, "macio", 0x80000);
object_initialize(&s->cuda, sizeof(s->cuda), TYPE_CUDA);
qdev_set_parent_bus(DEVICE(&s->cuda), sysbus_get_default());
object_property_add_child(obj, "cuda", OBJECT(&s->cuda), NULL);
-
- s->dbdma = DBDMA_init(&dbdma_mem);
- memory_region_add_subregion(&s->bar, 0x08000, dbdma_mem);
}
static const VMStateDescription vmstate_macio_oldworld = {
diff --git a/hw/misc/zynq_slcr.c b/hw/misc/zynq_slcr.c
index 964f2532ff..3d7870850b 100644
--- a/hw/misc/zynq_slcr.c
+++ b/hw/misc/zynq_slcr.c
@@ -393,12 +393,12 @@ static void zynq_slcr_write(void *opaque, hwaddr offset,
return;
}
- if (!s->regs[LOCKSTA]) {
- s->regs[offset / 4] = val;
- } else {
- DB_PRINT("SCLR registers are locked. Unlock them first\n");
+ if (s->regs[LOCKSTA]) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "SCLR registers are locked. Unlock them first\n");
return;
}
+ s->regs[offset] = val;
switch (offset) {
case PSS_RST_CTRL:
diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c
index edbb61ccf3..cb51613eb3 100644
--- a/hw/net/rtl8139.c
+++ b/hw/net/rtl8139.c
@@ -1148,7 +1148,9 @@ static ssize_t rtl8139_do_receive(NetClientState *nc, const uint8_t *buf, size_t
/* if receiver buffer is empty then avail == 0 */
- if (avail != 0 && size + 8 >= avail)
+#define RX_ALIGN(x) (((x) + 3) & ~0x3)
+
+ if (avail != 0 && RX_ALIGN(size + 8) >= avail)
{
DPRINTF("rx overflow: rx buffer length %d head 0x%04x "
"read 0x%04x === available 0x%04x need 0x%04x\n",
@@ -1157,7 +1159,7 @@ static ssize_t rtl8139_do_receive(NetClientState *nc, const uint8_t *buf, size_t
s->IntrStatus |= RxOverflow;
++s->RxMissed;
rtl8139_update_irq(s);
- return size_;
+ return 0;
}
packet_header |= RxStatusOK;
@@ -1176,7 +1178,7 @@ static ssize_t rtl8139_do_receive(NetClientState *nc, const uint8_t *buf, size_t
rtl8139_write_buffer(s, (uint8_t *)&val, 4);
/* correct buffer write pointer */
- s->RxBufAddr = MOD2((s->RxBufAddr + 3) & ~0x3, s->RxBufferSize);
+ s->RxBufAddr = MOD2(RX_ALIGN(s->RxBufAddr), s->RxBufferSize);
/* now we can signal we have received something */
diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
index 5c1d11f517..1d76b94c84 100644
--- a/hw/net/vhost_net.c
+++ b/hw/net/vhost_net.c
@@ -197,7 +197,7 @@ static int vhost_net_set_vnet_endian(VirtIODevice *dev, NetClientState *peer,
{
int r = 0;
- if (virtio_has_feature(dev, VIRTIO_F_VERSION_1) ||
+ if (virtio_vdev_has_feature(dev, VIRTIO_F_VERSION_1) ||
(virtio_legacy_is_cross_endian(dev) && !virtio_is_big_endian(dev))) {
r = qemu_set_vnet_le(peer, set);
if (r) {
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 1510839547..4aa93fb931 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -86,8 +86,8 @@ static void virtio_net_set_config(VirtIODevice *vdev, const uint8_t *config)
memcpy(&netcfg, config, n->config_size);
- if (!virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_MAC_ADDR) &&
- !virtio_has_feature(vdev, VIRTIO_F_VERSION_1) &&
+ if (!virtio_vdev_has_feature(vdev, VIRTIO_NET_F_CTRL_MAC_ADDR) &&
+ !virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1) &&
memcmp(netcfg.mac, n->mac, ETH_ALEN)) {
memcpy(n->mac, netcfg.mac, ETH_ALEN);
qemu_format_nic_info_str(qemu_get_queue(n->nic), n->mac);
@@ -304,7 +304,7 @@ static RxFilterInfo *virtio_net_query_rxfilter(NetClientState *nc)
info->multicast_table = str_list;
info->vlan_table = get_vlan_table(n);
- if (!virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_VLAN)) {
+ if (!virtio_vdev_has_feature(vdev, VIRTIO_NET_F_CTRL_VLAN)) {
info->vlan = RX_STATE_ALL;
} else if (!info->vlan_table) {
info->vlan = RX_STATE_NONE;
@@ -529,13 +529,13 @@ static void virtio_net_set_features(VirtIODevice *vdev, uint64_t features)
int i;
virtio_net_set_multiqueue(n,
- __virtio_has_feature(features, VIRTIO_NET_F_MQ));
+ virtio_has_feature(features, VIRTIO_NET_F_MQ));
virtio_net_set_mrg_rx_bufs(n,
- __virtio_has_feature(features,
- VIRTIO_NET_F_MRG_RXBUF),
- __virtio_has_feature(features,
- VIRTIO_F_VERSION_1));
+ virtio_has_feature(features,
+ VIRTIO_NET_F_MRG_RXBUF),
+ virtio_has_feature(features,
+ VIRTIO_F_VERSION_1));
if (n->has_vnet_hdr) {
n->curr_guest_offloads =
@@ -552,7 +552,7 @@ static void virtio_net_set_features(VirtIODevice *vdev, uint64_t features)
vhost_net_ack_features(get_vhost_net(nc->peer), features);
}
- if (__virtio_has_feature(features, VIRTIO_NET_F_CTRL_VLAN)) {
+ if (virtio_has_feature(features, VIRTIO_NET_F_CTRL_VLAN)) {
memset(n->vlans, 0, MAX_VLAN >> 3);
} else {
memset(n->vlans, 0xff, MAX_VLAN >> 3);
@@ -599,7 +599,7 @@ static int virtio_net_handle_offloads(VirtIONet *n, uint8_t cmd,
uint64_t offloads;
size_t s;
- if (!virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS)) {
+ if (!virtio_vdev_has_feature(vdev, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS)) {
return VIRTIO_NET_ERR;
}
@@ -1086,13 +1086,7 @@ static ssize_t virtio_net_receive(NetClientState *nc, const uint8_t *buf, size_t
* must have consumed the complete packet.
* Otherwise, drop it. */
if (!n->mergeable_rx_bufs && offset < size) {
-#if 0
- error_report("virtio-net truncated non-mergeable packet: "
- "i %zd mergeable %d offset %zd, size %zd, "
- "guest hdr len %zd, host hdr len %zd",
- i, n->mergeable_rx_bufs,
- offset, size, n->guest_hdr_len, n->host_hdr_len);
-#endif
+ virtqueue_discard(q->rx_vq, &elem, total);
return size;
}
@@ -1453,7 +1447,7 @@ static void virtio_net_save_device(VirtIODevice *vdev, QEMUFile *f)
}
}
- if (virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS)) {
+ if (virtio_vdev_has_feature(vdev, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS)) {
qemu_put_be64(f, n->curr_guest_offloads);
}
}
@@ -1462,11 +1456,33 @@ static int virtio_net_load(QEMUFile *f, void *opaque, int version_id)
{
VirtIONet *n = opaque;
VirtIODevice *vdev = VIRTIO_DEVICE(n);
+ int ret;
if (version_id < 2 || version_id > VIRTIO_NET_VM_VERSION)
return -EINVAL;
- return virtio_load(vdev, f, version_id);
+ ret = virtio_load(vdev, f, version_id);
+ if (ret) {
+ return ret;
+ }
+
+ if (virtio_vdev_has_feature(vdev, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS)) {
+ 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);
+ }
+
+ if (virtio_vdev_has_feature(vdev, VIRTIO_NET_F_GUEST_ANNOUNCE) &&
+ virtio_vdev_has_feature(vdev, VIRTIO_NET_F_CTRL_VQ)) {
+ n->announce_counter = SELF_ANNOUNCE_ROUNDS;
+ timer_mod(n->announce_timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL));
+ }
+
+ return 0;
}
static int virtio_net_load_device(VirtIODevice *vdev, QEMUFile *f,
@@ -1479,7 +1495,8 @@ static int virtio_net_load_device(VirtIODevice *vdev, QEMUFile *f,
n->vqs[0].tx_waiting = qemu_get_be32(f);
virtio_net_set_mrg_rx_bufs(n, qemu_get_be32(f),
- virtio_has_feature(vdev, VIRTIO_F_VERSION_1));
+ virtio_vdev_has_feature(vdev,
+ VIRTIO_F_VERSION_1));
if (version_id >= 3)
n->status = qemu_get_be16(f);
@@ -1562,16 +1579,6 @@ static int virtio_net_load_device(VirtIODevice *vdev, QEMUFile *f,
}
}
- if (virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS)) {
- 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 */
@@ -1589,12 +1596,6 @@ static int virtio_net_load_device(VirtIODevice *vdev, QEMUFile *f,
qemu_get_subqueue(n->nic, i)->link_down = link_down;
}
- if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_ANNOUNCE) &&
- virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_VQ)) {
- n->announce_counter = SELF_ANNOUNCE_ROUNDS;
- timer_mod(n->announce_timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL));
- }
-
return 0;
}
diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c
index 59b06b8412..2504425cf9 100644
--- a/hw/net/vmxnet3.c
+++ b/hw/net/vmxnet3.c
@@ -1988,7 +1988,6 @@ static void vmxnet3_set_link_status(NetClientState *nc)
static NetClientInfo net_vmxnet3_info = {
.type = NET_CLIENT_OPTIONS_KIND_NIC,
.size = sizeof(NICState),
- .can_receive = vmxnet3_can_receive,
.receive = vmxnet3_receive,
.link_status_changed = vmxnet3_set_link_status,
};
diff --git a/hw/pci-host/versatile.c b/hw/pci-host/versatile.c
index 6d23553094..7172b90958 100644
--- a/hw/pci-host/versatile.c
+++ b/hw/pci-host/versatile.c
@@ -500,6 +500,8 @@ static void pci_vpb_class_init(ObjectClass *klass, void *data)
dc->reset = pci_vpb_reset;
dc->vmsd = &pci_vpb_vmstate;
dc->props = pci_vpb_properties;
+ /* Reason: object_unref() hangs */
+ dc->cannot_destroy_with_object_finalize_yet = true;
}
static const TypeInfo pci_vpb_info = {
@@ -521,10 +523,19 @@ static void pci_realview_init(Object *obj)
s->mem_win_size[2] = 0x08000000;
}
+static void pci_realview_class_init(ObjectClass *class, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(class);
+
+ /* Reason: object_unref() hangs */
+ dc->cannot_destroy_with_object_finalize_yet = true;
+}
+
static const TypeInfo pci_realview_info = {
.name = "realview_pci",
.parent = TYPE_VERSATILE_PCI,
.instance_init = pci_realview_init,
+ .class_init = pci_realview_class_init,
};
static void versatile_pci_register_types(void)
diff --git a/hw/pcmcia/pxa2xx.c b/hw/pcmcia/pxa2xx.c
index a7e187743d..812716e1c8 100644
--- a/hw/pcmcia/pxa2xx.c
+++ b/hw/pcmcia/pxa2xx.c
@@ -163,7 +163,7 @@ static void pxa2xx_pcmcia_initfn(Object *obj)
sysbus_init_mmio(sbd, &s->container_mem);
/* Socket I/O Memory Space */
- memory_region_init_io(&s->iomem, NULL, &pxa2xx_pcmcia_io_ops, s,
+ memory_region_init_io(&s->iomem, obj, &pxa2xx_pcmcia_io_ops, s,
"pxa2xx-pcmcia-io", 0x04000000);
memory_region_add_subregion(&s->container_mem, 0x00000000,
&s->iomem);
@@ -171,13 +171,13 @@ static void pxa2xx_pcmcia_initfn(Object *obj)
/* Then next 64 MB is reserved */
/* Socket Attribute Memory Space */
- memory_region_init_io(&s->attr_iomem, NULL, &pxa2xx_pcmcia_attr_ops, s,
+ memory_region_init_io(&s->attr_iomem, obj, &pxa2xx_pcmcia_attr_ops, s,
"pxa2xx-pcmcia-attribute", 0x04000000);
memory_region_add_subregion(&s->container_mem, 0x08000000,
&s->attr_iomem);
/* Socket Common Memory Space */
- memory_region_init_io(&s->common_iomem, NULL, &pxa2xx_pcmcia_common_ops, s,
+ memory_region_init_io(&s->common_iomem, obj, &pxa2xx_pcmcia_common_ops, s,
"pxa2xx-pcmcia-common", 0x04000000);
memory_region_add_subregion(&s->container_mem, 0x0c000000,
&s->common_iomem);
diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
index a8f79d8003..119fa5e465 100644
--- a/hw/ppc/spapr_pci.c
+++ b/hw/ppc/spapr_pci.c
@@ -955,6 +955,7 @@ static int spapr_populate_pci_child_dt(PCIDevice *dev, void *fdt, int offset,
int pci_status, err;
char *buf = NULL;
uint32_t drc_index = spapr_phb_get_pci_drc_index(sphb, dev);
+ uint32_t max_msi, max_msix;
if (pci_default_read_config(dev, PCI_HEADER_TYPE, 1) ==
PCI_HEADER_TYPE_BRIDGE) {
@@ -1035,8 +1036,15 @@ static int spapr_populate_pci_child_dt(PCIDevice *dev, void *fdt, int offset,
RESOURCE_CELLS_ADDRESS));
_FDT(fdt_setprop_cell(fdt, offset, "#size-cells",
RESOURCE_CELLS_SIZE));
- _FDT(fdt_setprop_cell(fdt, offset, "ibm,req#msi-x",
- RESOURCE_CELLS_SIZE));
+
+ max_msi = msi_nr_vectors_allocated(dev);
+ if (max_msi) {
+ _FDT(fdt_setprop_cell(fdt, offset, "ibm,req#msi", max_msi));
+ }
+ max_msix = dev->msix_entries_nr;
+ if (max_msix) {
+ _FDT(fdt_setprop_cell(fdt, offset, "ibm,req#msi-x", max_msix));
+ }
populate_resource_props(dev, &rp);
_FDT(fdt_setprop(fdt, offset, "reg", (uint8_t *)rp.reg, rp.reg_len));
diff --git a/hw/s390x/css.c b/hw/s390x/css.c
index 5df450e00b..97d93d56df 100644
--- a/hw/s390x/css.c
+++ b/hw/s390x/css.c
@@ -392,6 +392,8 @@ static void sch_handle_start_func(SubchDev *sch, ORB *orb)
path = 0x80;
if (!(s->ctrl & SCSW_ACTL_SUSP)) {
+ s->cstat = 0;
+ s->dstat = 0;
/* Look at the orb and try to execute the channel program. */
assert(orb != NULL); /* resume does not pass an orb */
p->intparm = orb->intparm;
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
index 64f0694734..0e0bc64400 100644
--- a/hw/scsi/scsi-disk.c
+++ b/hw/scsi/scsi-disk.c
@@ -1683,6 +1683,10 @@ static void scsi_write_same_complete(void *opaque, int ret)
if (data->iov.iov_len) {
block_acct_start(blk_get_stats(s->qdev.conf.blk), &r->acct,
data->iov.iov_len, BLOCK_ACCT_WRITE);
+ /* blk_aio_write doesn't like the qiov size being different from
+ * nb_sectors, make sure they match.
+ */
+ qemu_iovec_init_external(&data->qiov, &data->iov, 1);
r->req.aiocb = blk_aio_writev(s->qdev.conf.blk, data->sector,
&data->qiov, data->iov.iov_len / 512,
scsi_write_same_complete, data);
diff --git a/hw/scsi/vhost-scsi.c b/hw/scsi/vhost-scsi.c
index a69918bef8..62d91003bf 100644
--- a/hw/scsi/vhost-scsi.c
+++ b/hw/scsi/vhost-scsi.c
@@ -291,7 +291,7 @@ static char *vhost_scsi_get_fw_dev_path(FWPathProvider *p, BusState *bus,
{
VHostSCSI *s = VHOST_SCSI(dev);
/* format: channel@channel/vhost-scsi@target,lun */
- return g_strdup_printf("channel@%x/%s@%x,%x", s->channel,
+ return g_strdup_printf("/channel@%x/%s@%x,%x", s->channel,
qdev_fw_name(dev), s->target, s->lun);
}
diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
index 811c3da8bd..93c33e11f8 100644
--- a/hw/scsi/virtio-scsi.c
+++ b/hw/scsi/virtio-scsi.c
@@ -145,7 +145,7 @@ static int virtio_scsi_parse_req(VirtIOSCSIReq *req,
*
* TODO: always disable this workaround for virtio 1.0 devices.
*/
- if (!virtio_has_feature(vdev, VIRTIO_F_ANY_LAYOUT)) {
+ if (!virtio_vdev_has_feature(vdev, VIRTIO_F_ANY_LAYOUT)) {
if (req->elem.out_num) {
req_size = req->elem.out_sg[0].iov_len;
}
@@ -662,6 +662,11 @@ static void virtio_scsi_reset(VirtIODevice *vdev)
static void virtio_scsi_save(QEMUFile *f, void *opaque)
{
VirtIODevice *vdev = VIRTIO_DEVICE(opaque);
+ VirtIOSCSI *s = VIRTIO_SCSI(vdev);
+
+ if (s->dataplane_started) {
+ virtio_scsi_dataplane_stop(s);
+ }
virtio_save(vdev, f);
}
@@ -754,7 +759,7 @@ static void virtio_scsi_change(SCSIBus *bus, SCSIDevice *dev, SCSISense sense)
VirtIOSCSI *s = container_of(bus, VirtIOSCSI, bus);
VirtIODevice *vdev = VIRTIO_DEVICE(s);
- if (virtio_has_feature(vdev, VIRTIO_SCSI_F_CHANGE) &&
+ if (virtio_vdev_has_feature(vdev, VIRTIO_SCSI_F_CHANGE) &&
dev->type != TYPE_ROM) {
virtio_scsi_push_event(s, dev, VIRTIO_SCSI_T_PARAM_CHANGE,
sense.asc | (sense.ascq << 8));
@@ -778,7 +783,7 @@ static void virtio_scsi_hotplug(HotplugHandler *hotplug_dev, DeviceState *dev,
aio_context_release(s->ctx);
}
- if (virtio_has_feature(vdev, VIRTIO_SCSI_F_HOTPLUG)) {
+ if (virtio_vdev_has_feature(vdev, VIRTIO_SCSI_F_HOTPLUG)) {
virtio_scsi_push_event(s, sd,
VIRTIO_SCSI_T_TRANSPORT_RESET,
VIRTIO_SCSI_EVT_RESET_RESCAN);
@@ -792,7 +797,7 @@ static void virtio_scsi_hotunplug(HotplugHandler *hotplug_dev, DeviceState *dev,
VirtIOSCSI *s = VIRTIO_SCSI(vdev);
SCSIDevice *sd = SCSI_DEVICE(dev);
- if (virtio_has_feature(vdev, VIRTIO_SCSI_F_HOTPLUG)) {
+ if (virtio_vdev_has_feature(vdev, VIRTIO_SCSI_F_HOTPLUG)) {
virtio_scsi_push_event(s, sd,
VIRTIO_SCSI_T_TRANSPORT_RESET,
VIRTIO_SCSI_EVT_RESET_REMOVED);
diff --git a/hw/virtio/dataplane/vring.c b/hw/virtio/dataplane/vring.c
index 07fd69c69e..68f1994434 100644
--- a/hw/virtio/dataplane/vring.c
+++ b/hw/virtio/dataplane/vring.c
@@ -67,22 +67,53 @@ static void vring_unmap(void *buffer, bool is_write)
/* Map the guest's vring to host memory */
bool vring_setup(Vring *vring, VirtIODevice *vdev, int n)
{
- hwaddr vring_addr = virtio_queue_get_ring_addr(vdev, n);
- hwaddr vring_size = virtio_queue_get_ring_size(vdev, n);
- void *vring_ptr;
+ struct vring *vr = &vring->vr;
+ hwaddr addr;
+ hwaddr size;
+ void *ptr;
vring->broken = false;
-
- vring_ptr = vring_map(&vring->mr, vring_addr, vring_size, true);
- if (!vring_ptr) {
- error_report("Failed to map vring "
- "addr %#" HWADDR_PRIx " size %" HWADDR_PRIu,
- vring_addr, vring_size);
- vring->broken = true;
- return false;
+ vr->num = virtio_queue_get_num(vdev, n);
+
+ addr = virtio_queue_get_desc_addr(vdev, n);
+ size = virtio_queue_get_desc_size(vdev, n);
+ /* Map the descriptor area as read only */
+ ptr = vring_map(&vring->mr_desc, addr, size, false);
+ if (!ptr) {
+ error_report("Failed to map 0x%" HWADDR_PRIx " byte for vring desc "
+ "at 0x%" HWADDR_PRIx,
+ size, addr);
+ goto out_err_desc;
}
-
- vring_init(&vring->vr, virtio_queue_get_num(vdev, n), vring_ptr, 4096);
+ vr->desc = ptr;
+
+ addr = virtio_queue_get_avail_addr(vdev, n);
+ size = virtio_queue_get_avail_size(vdev, n);
+ /* Add the size of the used_event_idx */
+ size += sizeof(uint16_t);
+ /* Map the driver area as read only */
+ ptr = vring_map(&vring->mr_avail, addr, size, false);
+ if (!ptr) {
+ error_report("Failed to map 0x%" HWADDR_PRIx " byte for vring avail "
+ "at 0x%" HWADDR_PRIx,
+ size, addr);
+ goto out_err_avail;
+ }
+ vr->avail = ptr;
+
+ addr = virtio_queue_get_used_addr(vdev, n);
+ size = virtio_queue_get_used_size(vdev, n);
+ /* Add the size of the avail_event_idx */
+ size += sizeof(uint16_t);
+ /* Map the device area as read-write */
+ ptr = vring_map(&vring->mr_used, addr, size, true);
+ if (!ptr) {
+ error_report("Failed to map 0x%" HWADDR_PRIx " byte for vring used "
+ "at 0x%" HWADDR_PRIx,
+ size, addr);
+ goto out_err_used;
+ }
+ vr->used = ptr;
vring->last_avail_idx = virtio_queue_get_last_avail_idx(vdev, n);
vring->last_used_idx = vring_get_used_idx(vdev, vring);
@@ -92,6 +123,14 @@ bool vring_setup(Vring *vring, VirtIODevice *vdev, int n)
trace_vring_setup(virtio_queue_get_ring_addr(vdev, n),
vring->vr.desc, vring->vr.avail, vring->vr.used);
return true;
+
+out_err_used:
+ memory_region_unref(vring->mr_avail);
+out_err_avail:
+ memory_region_unref(vring->mr_desc);
+out_err_desc:
+ vring->broken = true;
+ return false;
}
void vring_teardown(Vring *vring, VirtIODevice *vdev, int n)
@@ -99,13 +138,15 @@ void vring_teardown(Vring *vring, VirtIODevice *vdev, int n)
virtio_queue_set_last_avail_idx(vdev, n, vring->last_avail_idx);
virtio_queue_invalidate_signalled_used(vdev, n);
- memory_region_unref(vring->mr);
+ memory_region_unref(vring->mr_desc);
+ memory_region_unref(vring->mr_avail);
+ memory_region_unref(vring->mr_used);
}
/* Disable guest->host notifies */
void vring_disable_notification(VirtIODevice *vdev, Vring *vring)
{
- if (!virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) {
+ if (!virtio_vdev_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) {
vring_set_used_flags(vdev, vring, VRING_USED_F_NO_NOTIFY);
}
}
@@ -116,7 +157,7 @@ void vring_disable_notification(VirtIODevice *vdev, Vring *vring)
*/
bool vring_enable_notification(VirtIODevice *vdev, Vring *vring)
{
- if (virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) {
+ if (virtio_vdev_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) {
vring_avail_event(&vring->vr) = vring->vr.avail->idx;
} else {
vring_clear_used_flags(vdev, vring, VRING_USED_F_NO_NOTIFY);
@@ -135,12 +176,12 @@ bool vring_should_notify(VirtIODevice *vdev, Vring *vring)
* interrupts. */
smp_mb();
- if (virtio_has_feature(vdev, VIRTIO_F_NOTIFY_ON_EMPTY) &&
+ if (virtio_vdev_has_feature(vdev, VIRTIO_F_NOTIFY_ON_EMPTY) &&
unlikely(!vring_more_avail(vdev, vring))) {
return true;
}
- if (!virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) {
+ if (!virtio_vdev_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) {
return !(vring_get_avail_flags(vdev, vring) &
VRING_AVAIL_F_NO_INTERRUPT);
}
@@ -402,7 +443,7 @@ int vring_pop(VirtIODevice *vdev, Vring *vring,
/* On success, increment avail index. */
vring->last_avail_idx++;
- if (virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) {
+ if (virtio_vdev_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) {
vring_avail_event(&vring->vr) =
virtio_tswap16(vdev, vring->last_avail_idx);
}
diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index 2712c6fc0a..a08c36bb45 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -742,7 +742,7 @@ static int vhost_virtqueue_start(struct vhost_dev *dev,
return -errno;
}
- if (!virtio_has_feature(vdev, VIRTIO_F_VERSION_1) &&
+ if (!virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1) &&
virtio_legacy_is_cross_endian(vdev)) {
r = vhost_virtqueue_set_vring_endian_legacy(dev,
virtio_is_big_endian(vdev),
@@ -839,7 +839,7 @@ static void vhost_virtqueue_stop(struct vhost_dev *dev,
/* In the cross-endian case, we need to reset the vring endianness to
* native as legacy devices expect so by default.
*/
- if (!virtio_has_feature(vdev, VIRTIO_F_VERSION_1) &&
+ if (!virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1) &&
virtio_legacy_is_cross_endian(vdev)) {
r = vhost_virtqueue_set_vring_endian_legacy(dev,
!virtio_is_big_endian(vdev),
diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c
index 3577b7af91..c419b17143 100644
--- a/hw/virtio/virtio-balloon.c
+++ b/hw/virtio/virtio-balloon.c
@@ -70,7 +70,7 @@ static inline void reset_stats(VirtIOBalloon *dev)
static bool balloon_stats_supported(const VirtIOBalloon *s)
{
VirtIODevice *vdev = VIRTIO_DEVICE(s);
- return virtio_has_feature(vdev, VIRTIO_BALLOON_F_STATS_VQ);
+ return virtio_vdev_has_feature(vdev, VIRTIO_BALLOON_F_STATS_VQ);
}
static bool balloon_stats_enabled(const VirtIOBalloon *s)
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index 788b556a74..d24f77551a 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -220,7 +220,7 @@ static inline void vring_set_avail_event(VirtQueue *vq, uint16_t val)
void virtio_queue_set_notification(VirtQueue *vq, int enable)
{
vq->notification = enable;
- if (virtio_has_feature(vq->vdev, VIRTIO_RING_F_EVENT_IDX)) {
+ if (virtio_vdev_has_feature(vq->vdev, VIRTIO_RING_F_EVENT_IDX)) {
vring_set_avail_event(vq, vring_avail_idx(vq));
} else if (enable) {
vring_used_flags_unset_bit(vq, VRING_USED_F_NO_NOTIFY);
@@ -243,14 +243,12 @@ int virtio_queue_empty(VirtQueue *vq)
return vring_avail_idx(vq) == vq->last_avail_idx;
}
-void virtqueue_fill(VirtQueue *vq, const VirtQueueElement *elem,
- unsigned int len, unsigned int idx)
+static void virtqueue_unmap_sg(VirtQueue *vq, const VirtQueueElement *elem,
+ unsigned int len)
{
unsigned int offset;
int i;
- trace_virtqueue_fill(vq, elem, len, idx);
-
offset = 0;
for (i = 0; i < elem->in_num; i++) {
size_t size = MIN(len - offset, elem->in_sg[i].iov_len);
@@ -266,6 +264,21 @@ void virtqueue_fill(VirtQueue *vq, const VirtQueueElement *elem,
cpu_physical_memory_unmap(elem->out_sg[i].iov_base,
elem->out_sg[i].iov_len,
0, elem->out_sg[i].iov_len);
+}
+
+void virtqueue_discard(VirtQueue *vq, const VirtQueueElement *elem,
+ unsigned int len)
+{
+ vq->last_avail_idx--;
+ virtqueue_unmap_sg(vq, elem, len);
+}
+
+void virtqueue_fill(VirtQueue *vq, const VirtQueueElement *elem,
+ unsigned int len, unsigned int idx)
+{
+ trace_virtqueue_fill(vq, elem, len, idx);
+
+ virtqueue_unmap_sg(vq, elem, len);
idx = (idx + vring_used_idx(vq)) % vq->vring.num;
@@ -471,7 +484,7 @@ int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem)
max = vq->vring.num;
i = head = virtqueue_get_head(vq, vq->last_avail_idx++);
- if (virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) {
+ if (virtio_vdev_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) {
vring_set_avail_event(vq, vq->last_avail_idx);
}
@@ -560,7 +573,7 @@ int virtio_set_status(VirtIODevice *vdev, uint8_t val)
VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
trace_virtio_set_status(vdev, val);
- if (virtio_has_feature(vdev, VIRTIO_F_VERSION_1)) {
+ if (virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1)) {
if (!(vdev->status & VIRTIO_CONFIG_S_FEATURES_OK) &&
val & VIRTIO_CONFIG_S_FEATURES_OK) {
int ret = virtio_validate_features(vdev);
@@ -898,7 +911,7 @@ void virtio_queue_set_align(VirtIODevice *vdev, int n, int align)
VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
/* virtio-1 compliant devices cannot change the alignment */
- if (virtio_has_feature(vdev, VIRTIO_F_VERSION_1)) {
+ if (virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1)) {
error_report("tried to modify queue alignment for virtio-1 device");
return;
}
@@ -993,12 +1006,12 @@ static bool vring_notify(VirtIODevice *vdev, VirtQueue *vq)
/* We need to expose used array entries before checking used event. */
smp_mb();
/* Always notify when queue is empty (when feature acknowledge) */
- if (virtio_has_feature(vdev, VIRTIO_F_NOTIFY_ON_EMPTY) &&
+ if (virtio_vdev_has_feature(vdev, VIRTIO_F_NOTIFY_ON_EMPTY) &&
!vq->inuse && vring_avail_idx(vq) == vq->last_avail_idx) {
return true;
}
- if (!virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) {
+ if (!virtio_vdev_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) {
return !(vring_avail_flags(vq) & VRING_AVAIL_F_NO_INTERRUPT);
}
@@ -1035,7 +1048,7 @@ static bool virtio_device_endian_needed(void *opaque)
VirtIODevice *vdev = opaque;
assert(vdev->device_endian != VIRTIO_DEVICE_ENDIAN_UNKNOWN);
- if (!virtio_has_feature(vdev, VIRTIO_F_VERSION_1)) {
+ if (!virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1)) {
return vdev->device_endian != virtio_default_endian();
}
/* Devices conforming to VIRTIO 1.0 or later are always LE. */
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
index a6fce04f65..60f12bc65c 100644
--- a/include/exec/exec-all.h
+++ b/include/exec/exec-all.h
@@ -308,11 +308,7 @@ extern uintptr_t tci_tb_ptr;
to indicate the compressed mode; subtracting two works around that. It
is also the case that there are no host isas that contain a call insn
smaller than 4 bytes, so we don't worry about special-casing this. */
-#if defined(CONFIG_TCG_INTERPRETER)
-# define GETPC_ADJ 0
-#else
-# define GETPC_ADJ 2
-#endif
+#define GETPC_ADJ 2
#define GETPC() (GETRA() - GETPC_ADJ)
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
index 038b54d94b..8057aedaa6 100644
--- a/include/hw/qdev-core.h
+++ b/include/hw/qdev-core.h
@@ -114,6 +114,19 @@ typedef struct DeviceClass {
* TODO remove once we're there
*/
bool cannot_instantiate_with_device_add_yet;
+ /*
+ * Does this device model survive object_unref(object_new(TNAME))?
+ * All device models should, and this flag shouldn't exist. Some
+ * devices crash in object_new(), some crash or hang in
+ * object_unref(). Makes introspecting properties with
+ * qmp_device_list_properties() dangerous. Bad, because it's used
+ * by -device FOO,help. This flag serves to protect that code.
+ * It should never be set without a comment explaining why it is
+ * set.
+ * TODO remove once we're there
+ */
+ bool cannot_destroy_with_object_finalize_yet;
+
bool hotpluggable;
/* callbacks */
diff --git a/include/hw/virtio/dataplane/vring.h b/include/hw/virtio/dataplane/vring.h
index 8d97db9e2d..a596e4c175 100644
--- a/include/hw/virtio/dataplane/vring.h
+++ b/include/hw/virtio/dataplane/vring.h
@@ -22,7 +22,9 @@
#include "hw/virtio/virtio.h"
typedef struct {
- MemoryRegion *mr; /* memory region containing the vring */
+ MemoryRegion *mr_desc; /* memory region for the vring desc */
+ MemoryRegion *mr_avail; /* memory region for the vring avail */
+ MemoryRegion *mr_used; /* memory region for the vring used */
struct vring vr; /* virtqueue vring mapped to host memory */
uint16_t last_avail_idx; /* last processed avail ring index */
uint16_t last_used_idx; /* last processed used ring index */
diff --git a/include/hw/virtio/virtio-access.h b/include/hw/virtio/virtio-access.h
index 1ec1dfdb6c..8aec843c8f 100644
--- a/include/hw/virtio/virtio-access.h
+++ b/include/hw/virtio/virtio-access.h
@@ -19,7 +19,7 @@
static inline bool virtio_access_is_big_endian(VirtIODevice *vdev)
{
- if (virtio_has_feature(vdev, VIRTIO_F_VERSION_1)) {
+ if (virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1)) {
/* Devices conforming to VIRTIO 1.0 or later are always LE. */
return false;
}
diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
index cccae89d83..9d09115fab 100644
--- a/include/hw/virtio/virtio.h
+++ b/include/hw/virtio/virtio.h
@@ -146,6 +146,8 @@ void virtio_del_queue(VirtIODevice *vdev, int n);
void virtqueue_push(VirtQueue *vq, const VirtQueueElement *elem,
unsigned int len);
void virtqueue_flush(VirtQueue *vq, unsigned int count);
+void virtqueue_discard(VirtQueue *vq, const VirtQueueElement *elem,
+ unsigned int len);
void virtqueue_fill(VirtQueue *vq, const VirtQueueElement *elem,
unsigned int len, unsigned int idx);
@@ -261,26 +263,27 @@ static inline void virtio_clear_feature(uint64_t *features, unsigned int fbit)
*features &= ~(1ULL << fbit);
}
-static inline bool __virtio_has_feature(uint64_t features, unsigned int fbit)
+static inline bool virtio_has_feature(uint64_t features, unsigned int fbit)
{
assert(fbit < 64);
return !!(features & (1ULL << fbit));
}
-static inline bool virtio_has_feature(VirtIODevice *vdev, unsigned int fbit)
+static inline bool virtio_vdev_has_feature(VirtIODevice *vdev,
+ unsigned int fbit)
{
- return __virtio_has_feature(vdev->guest_features, fbit);
+ return virtio_has_feature(vdev->guest_features, fbit);
}
static inline bool virtio_host_has_feature(VirtIODevice *vdev,
unsigned int fbit)
{
- return __virtio_has_feature(vdev->host_features, fbit);
+ return virtio_has_feature(vdev->host_features, fbit);
}
static inline bool virtio_is_big_endian(VirtIODevice *vdev)
{
- if (!virtio_has_feature(vdev, VIRTIO_F_VERSION_1)) {
+ if (!virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1)) {
assert(vdev->device_endian != VIRTIO_DEVICE_ENDIAN_UNKNOWN);
return vdev->device_endian == VIRTIO_DEVICE_ENDIAN_BIG;
}
diff --git a/include/standard-headers/linux/input.h b/include/standard-headers/linux/input.h
index b003c67059..43f1850b6b 100644
--- a/include/standard-headers/linux/input.h
+++ b/include/standard-headers/linux/input.h
@@ -887,8 +887,8 @@ struct input_keymap_entry {
#define SW_ROTATE_LOCK 0x0c /* set = rotate locked/disabled */
#define SW_LINEIN_INSERT 0x0d /* set = inserted */
#define SW_MUTE_DEVICE 0x0e /* set = device disabled */
-#define SW_MAX 0x0f
-#define SW_CNT (SW_MAX+1)
+#define SW_MAX_ 0x0f
+#define SW_CNT (SW_MAX_+1)
/*
* Misc events
diff --git a/memory.c b/memory.c
index 4eb138a429..10c1df5360 100644
--- a/memory.c
+++ b/memory.c
@@ -1312,7 +1312,22 @@ static void memory_region_finalize(Object *obj)
{
MemoryRegion *mr = MEMORY_REGION(obj);
- assert(QTAILQ_EMPTY(&mr->subregions));
+ assert(!mr->container);
+
+ /* We know the region is not visible in any address space (it
+ * does not have a container and cannot be a root either because
+ * it has no references, so we can blindly clear mr->enabled.
+ * memory_region_set_enabled instead could trigger a transaction
+ * and cause an infinite loop.
+ */
+ mr->enabled = false;
+ memory_region_transaction_begin();
+ while (!QTAILQ_EMPTY(&mr->subregions)) {
+ MemoryRegion *subregion = QTAILQ_FIRST(&mr->subregions);
+ memory_region_del_subregion(mr, subregion);
+ }
+ memory_region_transaction_commit();
+
mr->destructor(mr);
memory_region_clear_coalescing(mr);
g_free((char *)mr->name);
diff --git a/migration/migration.c b/migration/migration.c
index 662e77e4eb..c4a7d0b705 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -286,12 +286,12 @@ static void process_incoming_migration_co(void *opaque)
migrate_decompress_threads_join();
exit(EXIT_FAILURE);
}
- migrate_generate_event(MIGRATION_STATUS_COMPLETED);
qemu_announce_self();
/* Make sure all file formats flush their mutable metadata */
bdrv_invalidate_cache_all(&local_err);
if (local_err) {
+ migrate_generate_event(MIGRATION_STATUS_FAILED);
error_report_err(local_err);
migrate_decompress_threads_join();
exit(EXIT_FAILURE);
@@ -312,6 +312,12 @@ static void process_incoming_migration_co(void *opaque)
runstate_set(global_state_get_runstate());
}
migrate_decompress_threads_join();
+ /*
+ * This must happen after any state changes since as soon as an external
+ * observer sees this event they might start to prod at the VM assuming
+ * it's ready to use.
+ */
+ migrate_generate_event(MIGRATION_STATUS_COMPLETED);
}
void process_incoming_migration(QEMUFile *f)
diff --git a/nbd.c b/nbd.c
index 06b501ba67..07240bd3e3 100644
--- a/nbd.c
+++ b/nbd.c
@@ -1131,12 +1131,6 @@ void nbd_export_close(NBDExport *exp)
}
nbd_export_set_name(exp, NULL);
nbd_export_put(exp);
- if (exp->blk) {
- blk_remove_aio_context_notifier(exp->blk, blk_aio_attached,
- blk_aio_detach, exp);
- blk_unref(exp->blk);
- exp->blk = NULL;
- }
}
void nbd_export_get(NBDExport *exp)
@@ -1159,6 +1153,13 @@ void nbd_export_put(NBDExport *exp)
exp->close(exp);
}
+ if (exp->blk) {
+ blk_remove_aio_context_notifier(exp->blk, blk_aio_attached,
+ blk_aio_detach, exp);
+ blk_unref(exp->blk);
+ exp->blk = NULL;
+ }
+
g_free(exp);
}
}
@@ -1305,6 +1306,14 @@ static void nbd_trip(void *opaque)
goto invalid_request;
}
+ if (client->closing) {
+ /*
+ * The client may be closed when we are blocked in
+ * nbd_co_receive_request()
+ */
+ goto done;
+ }
+
switch (command) {
case NBD_CMD_READ:
TRACE("Request type is READ");
diff --git a/net/net.c b/net/net.c
index f8a6bd1f07..d9548245f0 100644
--- a/net/net.c
+++ b/net/net.c
@@ -517,20 +517,28 @@ void qemu_set_vnet_hdr_len(NetClientState *nc, int len)
int qemu_set_vnet_le(NetClientState *nc, bool is_le)
{
+#ifdef HOST_WORDS_BIGENDIAN
if (!nc || !nc->info->set_vnet_le) {
return -ENOSYS;
}
return nc->info->set_vnet_le(nc, is_le);
+#else
+ return 0;
+#endif
}
int qemu_set_vnet_be(NetClientState *nc, bool is_be)
{
+#ifdef HOST_WORDS_BIGENDIAN
+ return 0;
+#else
if (!nc || !nc->info->set_vnet_be) {
return -ENOSYS;
}
return nc->info->set_vnet_be(nc, is_be);
+#endif
}
int qemu_can_send_packet(NetClientState *sender)
diff --git a/pc-bios/u-boot.e500 b/pc-bios/u-boot.e500
index bdb2a5e6f7..6e547de6f9 100755
--- a/pc-bios/u-boot.e500
+++ b/pc-bios/u-boot.e500
Binary files differ
diff --git a/qdev-monitor.c b/qdev-monitor.c
index f9e2d6258d..0e147478ca 100644
--- a/qdev-monitor.c
+++ b/qdev-monitor.c
@@ -237,9 +237,12 @@ int qdev_device_help(QemuOpts *opts)
return 0;
}
- qdev_get_device_class(&driver, &local_err);
- if (local_err) {
- goto error;
+ if (!object_class_by_name(driver)) {
+ const char *typename = find_typename_by_alias(driver);
+
+ if (typename) {
+ driver = typename;
+ }
}
prop_list = qmp_device_list_properties(driver, &local_err);
diff --git a/qemu-img.c b/qemu-img.c
index 75f4ee4421..6ff4e852b1 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -2931,7 +2931,7 @@ static int img_amend(int argc, char **argv)
if (!is_valid_option_list(optarg)) {
error_report("Invalid option list: %s", optarg);
ret = -1;
- goto out;
+ goto out_no_progress;
}
if (!options) {
options = g_strdup(optarg);
@@ -3031,6 +3031,7 @@ static int img_amend(int argc, char **argv)
out:
qemu_progress_end();
+out_no_progress:
blk_unref(blk);
qemu_opts_del(opts);
qemu_opts_free(create_opts);
diff --git a/qmp.c b/qmp.c
index 403805a551..6998ca2fc6 100644
--- a/qmp.c
+++ b/qmp.c
@@ -514,6 +514,17 @@ DevicePropertyInfoList *qmp_device_list_properties(const char *typename,
return NULL;
}
+ if (object_class_is_abstract(klass)) {
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "name",
+ "non-abstract device type");
+ return NULL;
+ }
+
+ if (DEVICE_CLASS(klass)->cannot_destroy_with_object_finalize_yet) {
+ error_setg(errp, "Can't list properties of device '%s'", typename);
+ return NULL;
+ }
+
obj = object_new(typename);
QTAILQ_FOREACH(prop, &obj->properties, node) {
diff --git a/qom/object.c b/qom/object.c
index eea8edf3d3..e14b9d866c 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -1079,6 +1079,7 @@ typedef struct EnumProperty {
int object_property_get_enum(Object *obj, const char *name,
const char *typename, Error **errp)
{
+ Error *err = NULL;
StringOutputVisitor *sov;
StringInputVisitor *siv;
char *str;
@@ -1100,7 +1101,12 @@ int object_property_get_enum(Object *obj, const char *name,
enumprop = prop->opaque;
sov = string_output_visitor_new(false);
- object_property_get(obj, string_output_get_visitor(sov), name, errp);
+ object_property_get(obj, string_output_get_visitor(sov), name, &err);
+ if (err) {
+ error_propagate(errp, err);
+ string_output_visitor_cleanup(sov);
+ return 0;
+ }
str = string_output_get_string(sov);
siv = string_input_visitor_new(str);
string_output_visitor_cleanup(sov);
@@ -1116,21 +1122,27 @@ int object_property_get_enum(Object *obj, const char *name,
void object_property_get_uint16List(Object *obj, const char *name,
uint16List **list, Error **errp)
{
+ Error *err = NULL;
StringOutputVisitor *ov;
StringInputVisitor *iv;
char *str;
ov = string_output_visitor_new(false);
object_property_get(obj, string_output_get_visitor(ov),
- name, errp);
+ name, &err);
+ if (err) {
+ error_propagate(errp, err);
+ goto out;
+ }
str = string_output_get_string(ov);
iv = string_input_visitor_new(str);
visit_type_uint16List(string_input_get_visitor(iv),
list, NULL, errp);
g_free(str);
- string_output_visitor_cleanup(ov);
string_input_visitor_cleanup(iv);
+out:
+ string_output_visitor_cleanup(ov);
}
void object_property_parse(Object *obj, const char *string,
@@ -1581,12 +1593,16 @@ static void property_get_str(Object *obj, Visitor *v, void *opaque,
{
StringProperty *prop = opaque;
char *value;
+ Error *err = NULL;
- value = prop->get(obj, errp);
- if (value) {
- visit_type_str(v, &value, name, errp);
- g_free(value);
+ value = prop->get(obj, &err);
+ if (err) {
+ error_propagate(errp, err);
+ return;
}
+
+ visit_type_str(v, &value, name, errp);
+ g_free(value);
}
static void property_set_str(Object *obj, Visitor *v, void *opaque,
@@ -1646,8 +1662,14 @@ static void property_get_bool(Object *obj, Visitor *v, void *opaque,
{
BoolProperty *prop = opaque;
bool value;
+ Error *err = NULL;
+
+ value = prop->get(obj, &err);
+ if (err) {
+ error_propagate(errp, err);
+ return;
+ }
- value = prop->get(obj, errp);
visit_type_bool(v, &value, name, errp);
}
@@ -1701,8 +1723,14 @@ static void property_get_enum(Object *obj, Visitor *v, void *opaque,
{
EnumProperty *prop = opaque;
int value;
+ Error *err = NULL;
+
+ value = prop->get(obj, &err);
+ if (err) {
+ error_propagate(errp, err);
+ return;
+ }
- value = prop->get(obj, errp);
visit_type_enum(v, &value, prop->strings, NULL, name, errp);
}
@@ -1711,8 +1739,13 @@ static void property_set_enum(Object *obj, Visitor *v, void *opaque,
{
EnumProperty *prop = opaque;
int value;
+ Error *err = NULL;
- visit_type_enum(v, &value, prop->strings, NULL, name, errp);
+ visit_type_enum(v, &value, prop->strings, NULL, name, &err);
+ if (err) {
+ error_propagate(errp, err);
+ return;
+ }
prop->set(obj, value, errp);
}
diff --git a/scripts/dump-guest-memory.py b/scripts/dump-guest-memory.py
index dc8e44acf8..08796fff8c 100644
--- a/scripts/dump-guest-memory.py
+++ b/scripts/dump-guest-memory.py
@@ -118,7 +118,7 @@ shape and this command should mostly work."""
def qemu_get_ram_block(self, ram_addr):
ram_blocks = gdb.parse_and_eval("ram_list.blocks")
for block in self.qlist_foreach(ram_blocks, "next"):
- if (ram_addr - block["offset"] < block["length"]):
+ if (ram_addr - block["offset"] < block["used_length"]):
return block
raise gdb.GdbError("Bad ram offset %x" % ram_addr)
diff --git a/scripts/update-linux-headers.sh b/scripts/update-linux-headers.sh
index f0e830c2d6..201032846c 100755
--- a/scripts/update-linux-headers.sh
+++ b/scripts/update-linux-headers.sh
@@ -57,6 +57,7 @@ cp_virtio() {
-e 's/__attribute__((packed))/QEMU_PACKED/' \
-e 's/__inline__/inline/' \
-e '/sys\/ioctl.h/d' \
+ -e 's/SW_MAX/SW_MAX_/' \
"$f" > "$to/$header";
done
fi
diff --git a/slirp/tcp_input.c b/slirp/tcp_input.c
index f946db8dc0..00a77b4a5f 100644
--- a/slirp/tcp_input.c
+++ b/slirp/tcp_input.c
@@ -584,7 +584,13 @@ findso:
goto cont_input;
}
- if((tcp_fconnect(so) == -1) && (errno != EINPROGRESS) && (errno != EWOULDBLOCK)) {
+ if ((tcp_fconnect(so) == -1) &&
+#if defined(_WIN32)
+ socket_error() != WSAEWOULDBLOCK
+#else
+ (errno != EINPROGRESS) && (errno != EWOULDBLOCK)
+#endif
+ ) {
u_char code=ICMP_UNREACH_NET;
DEBUG_MISC((dfd, " tcp fconnect errno = %d-%s\n",
errno,strerror(errno)));
diff --git a/target-alpha/cpu.c b/target-alpha/cpu.c
index 421d7e5364..ff1926a5d0 100644
--- a/target-alpha/cpu.c
+++ b/target-alpha/cpu.c
@@ -298,6 +298,13 @@ static void alpha_cpu_class_init(ObjectClass *oc, void *data)
dc->vmsd = &vmstate_alpha_cpu;
#endif
cc->gdb_num_core_regs = 67;
+
+ /*
+ * Reason: alpha_cpu_initfn() calls cpu_exec_init(), which saves
+ * the object in cpus -> dangling pointer after final
+ * object_unref().
+ */
+ dc->cannot_destroy_with_object_finalize_yet = true;
}
static const TypeInfo alpha_cpu_type_info = {
diff --git a/target-arm/arm-semi.c b/target-arm/arm-semi.c
index a2a7369567..42522a70d9 100644
--- a/target-arm/arm-semi.c
+++ b/target-arm/arm-semi.c
@@ -260,7 +260,7 @@ uint32_t do_arm_semihosting(CPUARMState *env)
return (uint32_t)-1;
len = strlen(s);
if (use_gdb_syscalls()) {
- gdb_do_syscall(arm_semi_cb, "write,2,%x,%x\n", args, len);
+ gdb_do_syscall(arm_semi_cb, "write,2,%x,%x", args, len);
ret = env->regs[0];
} else {
ret = write(STDERR_FILENO, s, len);
diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index 8b4323dd08..ce0b8c09c5 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -1403,6 +1403,17 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data)
cc->debug_excp_handler = arm_debug_excp_handler;
cc->disas_set_info = arm_disas_set_info;
+
+ /*
+ * Reason: arm_cpu_initfn() calls cpu_exec_init(), which saves
+ * the object in cpus -> dangling pointer after final
+ * object_unref().
+ *
+ * Once this is fixed, the devices that create ARM CPUs should be
+ * updated not to set cannot_destroy_with_object_finalize_yet,
+ * unless they still screw up something else.
+ */
+ dc->cannot_destroy_with_object_finalize_yet = true;
}
static void cpu_register(const ARMCPUInfo *info)
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index 689f2be896..0f923d36c1 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -39,16 +39,9 @@
static TCGv_i64 cpu_X[32];
static TCGv_i64 cpu_pc;
-static TCGv_i32 cpu_NF, cpu_ZF, cpu_CF, cpu_VF;
/* Load/store exclusive handling */
-static TCGv_i64 cpu_exclusive_addr;
-static TCGv_i64 cpu_exclusive_val;
static TCGv_i64 cpu_exclusive_high;
-#ifdef CONFIG_USER_ONLY
-static TCGv_i64 cpu_exclusive_test;
-static TCGv_i32 cpu_exclusive_info;
-#endif
static const char *regnames[] = {
"x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",
@@ -104,23 +97,8 @@ void a64_translate_init(void)
regnames[i]);
}
- cpu_NF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, NF), "NF");
- cpu_ZF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, ZF), "ZF");
- cpu_CF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, CF), "CF");
- cpu_VF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, VF), "VF");
-
- cpu_exclusive_addr = tcg_global_mem_new_i64(TCG_AREG0,
- offsetof(CPUARMState, exclusive_addr), "exclusive_addr");
- cpu_exclusive_val = tcg_global_mem_new_i64(TCG_AREG0,
- offsetof(CPUARMState, exclusive_val), "exclusive_val");
cpu_exclusive_high = tcg_global_mem_new_i64(TCG_AREG0,
offsetof(CPUARMState, exclusive_high), "exclusive_high");
-#ifdef CONFIG_USER_ONLY
- cpu_exclusive_test = tcg_global_mem_new_i64(TCG_AREG0,
- offsetof(CPUARMState, exclusive_test), "exclusive_test");
- cpu_exclusive_info = tcg_global_mem_new_i32(TCG_AREG0,
- offsetof(CPUARMState, exclusive_info), "exclusive_info");
-#endif
}
static inline ARMMMUIdx get_a64_user_mem_index(DisasContext *s)
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 69ac18c108..43853221f6 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -64,12 +64,12 @@ TCGv_ptr cpu_env;
/* We reuse the same 64-bit temporaries for efficiency. */
static TCGv_i64 cpu_V0, cpu_V1, cpu_M0;
static TCGv_i32 cpu_R[16];
-static TCGv_i32 cpu_CF, cpu_NF, cpu_VF, cpu_ZF;
-static TCGv_i64 cpu_exclusive_addr;
-static TCGv_i64 cpu_exclusive_val;
+TCGv_i32 cpu_CF, cpu_NF, cpu_VF, cpu_ZF;
+TCGv_i64 cpu_exclusive_addr;
+TCGv_i64 cpu_exclusive_val;
#ifdef CONFIG_USER_ONLY
-static TCGv_i64 cpu_exclusive_test;
-static TCGv_i32 cpu_exclusive_info;
+TCGv_i64 cpu_exclusive_test;
+TCGv_i32 cpu_exclusive_info;
#endif
/* FIXME: These should be removed. */
diff --git a/target-arm/translate.h b/target-arm/translate.h
index 9ab978fb75..679bdbcbc9 100644
--- a/target-arm/translate.h
+++ b/target-arm/translate.h
@@ -62,7 +62,15 @@ typedef struct DisasContext {
TCGv_i64 tmp_a64[TMP_A64_MAX];
} DisasContext;
+/* Share the TCG temporaries common between 32 and 64 bit modes. */
extern TCGv_ptr cpu_env;
+extern TCGv_i32 cpu_NF, cpu_ZF, cpu_CF, cpu_VF;
+extern TCGv_i64 cpu_exclusive_addr;
+extern TCGv_i64 cpu_exclusive_val;
+#ifdef CONFIG_USER_ONLY
+extern TCGv_i64 cpu_exclusive_test;
+extern TCGv_i32 cpu_exclusive_info;
+#endif
static inline int arm_dc_feature(DisasContext *dc, int feature)
{
diff --git a/target-cris/cpu.c b/target-cris/cpu.c
index b17e849e2a..aa5e1c57c1 100644
--- a/target-cris/cpu.c
+++ b/target-cris/cpu.c
@@ -308,6 +308,13 @@ static void cris_cpu_class_init(ObjectClass *oc, void *data)
cc->gdb_stop_before_watchpoint = true;
cc->disas_set_info = cris_disas_set_info;
+
+ /*
+ * Reason: cris_cpu_initfn() calls cpu_exec_init(), which saves
+ * the object in cpus -> dangling pointer after final
+ * object_unref().
+ */
+ dc->cannot_destroy_with_object_finalize_yet = true;
}
static const TypeInfo cris_cpu_type_info = {
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index 7a779b1653..4d1b085332 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -1475,6 +1475,8 @@ static void host_x86_cpu_class_init(ObjectClass *oc, void *data)
*/
dc->props = host_x86_cpu_properties;
+ /* Reason: host_x86_cpu_initfn() dies when !kvm_enabled() */
+ dc->cannot_destroy_with_object_finalize_yet = true;
}
static void host_x86_cpu_initfn(Object *obj)
@@ -3200,6 +3202,12 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
#endif
cc->cpu_exec_enter = x86_cpu_exec_enter;
cc->cpu_exec_exit = x86_cpu_exec_exit;
+
+ /*
+ * Reason: x86_cpu_initfn() calls cpu_exec_init(), which saves the
+ * object in cpus -> dangling pointer after final object_unref().
+ */
+ dc->cannot_destroy_with_object_finalize_yet = true;
}
static const TypeInfo x86_cpu_type_info = {
diff --git a/target-lm32/cpu.c b/target-lm32/cpu.c
index c2b77c6986..d0ab2786ae 100644
--- a/target-lm32/cpu.c
+++ b/target-lm32/cpu.c
@@ -275,6 +275,13 @@ static void lm32_cpu_class_init(ObjectClass *oc, void *data)
cc->gdb_num_core_regs = 32 + 7;
cc->gdb_stop_before_watchpoint = true;
cc->debug_excp_handler = lm32_debug_excp_handler;
+
+ /*
+ * Reason: lm32_cpu_initfn() calls cpu_exec_init(), which saves
+ * the object in cpus -> dangling pointer after final
+ * object_unref().
+ */
+ dc->cannot_destroy_with_object_finalize_yet = true;
}
static void lm32_register_cpu_type(const LM32CPUInfo *info)
diff --git a/target-m68k/cpu.c b/target-m68k/cpu.c
index 4f246da748..97527ef32a 100644
--- a/target-m68k/cpu.c
+++ b/target-m68k/cpu.c
@@ -212,6 +212,13 @@ static void m68k_cpu_class_init(ObjectClass *c, void *data)
dc->vmsd = &vmstate_m68k_cpu;
cc->gdb_num_core_regs = 18;
cc->gdb_core_xml_file = "cf-core.xml";
+
+ /*
+ * Reason: m68k_cpu_initfn() calls cpu_exec_init(), which saves
+ * the object in cpus -> dangling pointer after final
+ * object_unref().
+ */
+ dc->cannot_destroy_with_object_finalize_yet = true;
}
static void register_cpu_type(const M68kCPUInfo *info)
diff --git a/target-microblaze/cpu.c b/target-microblaze/cpu.c
index 9ac509af3e..15b46f7686 100644
--- a/target-microblaze/cpu.c
+++ b/target-microblaze/cpu.c
@@ -264,6 +264,12 @@ static void mb_cpu_class_init(ObjectClass *oc, void *data)
cc->gdb_num_core_regs = 32 + 5;
cc->disas_set_info = mb_disas_set_info;
+
+ /*
+ * Reason: mb_cpu_initfn() calls cpu_exec_init(), which saves the
+ * object in cpus -> dangling pointer after final object_unref().
+ */
+ dc->cannot_destroy_with_object_finalize_yet = true;
}
static const TypeInfo mb_cpu_type_info = {
diff --git a/target-mips/cpu.c b/target-mips/cpu.c
index 4027d0f417..7fe1f0407f 100644
--- a/target-mips/cpu.c
+++ b/target-mips/cpu.c
@@ -153,6 +153,13 @@ static void mips_cpu_class_init(ObjectClass *c, void *data)
cc->gdb_num_core_regs = 73;
cc->gdb_stop_before_watchpoint = true;
+
+ /*
+ * Reason: mips_cpu_initfn() calls cpu_exec_init(), which saves
+ * the object in cpus -> dangling pointer after final
+ * object_unref().
+ */
+ dc->cannot_destroy_with_object_finalize_yet = true;
}
static const TypeInfo mips_cpu_type_info = {
diff --git a/target-moxie/cpu.c b/target-moxie/cpu.c
index 6b035aaab3..3af37799b7 100644
--- a/target-moxie/cpu.c
+++ b/target-moxie/cpu.c
@@ -114,6 +114,13 @@ static void moxie_cpu_class_init(ObjectClass *oc, void *data)
cc->get_phys_page_debug = moxie_cpu_get_phys_page_debug;
cc->vmsd = &vmstate_moxie_cpu;
#endif
+
+ /*
+ * Reason: moxie_cpu_initfn() calls cpu_exec_init(), which saves
+ * the object in cpus -> dangling pointer after final
+ * object_unref().
+ */
+ dc->cannot_destroy_with_object_finalize_yet = true;
}
static void moxielite_initfn(Object *obj)
diff --git a/target-openrisc/cpu.c b/target-openrisc/cpu.c
index d97f3c03c2..cc5e2d1c5d 100644
--- a/target-openrisc/cpu.c
+++ b/target-openrisc/cpu.c
@@ -177,6 +177,13 @@ static void openrisc_cpu_class_init(ObjectClass *oc, void *data)
dc->vmsd = &vmstate_openrisc_cpu;
#endif
cc->gdb_num_core_regs = 32 + 3;
+
+ /*
+ * Reason: openrisc_cpu_initfn() calls cpu_exec_init(), which saves
+ * the object in cpus -> dangling pointer after final
+ * object_unref().
+ */
+ dc->cannot_destroy_with_object_finalize_yet = true;
}
static void cpu_register(const OpenRISCCPUInfo *info)
diff --git a/target-ppc/int_helper.c b/target-ppc/int_helper.c
index 0a55d5e54b..b122868108 100644
--- a/target-ppc/int_helper.c
+++ b/target-ppc/int_helper.c
@@ -2327,24 +2327,28 @@ void helper_vsbox(ppc_avr_t *r, ppc_avr_t *a)
void helper_vcipher(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
{
+ ppc_avr_t result;
int i;
VECTOR_FOR_INORDER_I(i, u32) {
- r->AVRW(i) = b->AVRW(i) ^
+ result.AVRW(i) = b->AVRW(i) ^
(AES_Te0[a->AVRB(AES_shifts[4*i + 0])] ^
AES_Te1[a->AVRB(AES_shifts[4*i + 1])] ^
AES_Te2[a->AVRB(AES_shifts[4*i + 2])] ^
AES_Te3[a->AVRB(AES_shifts[4*i + 3])]);
}
+ *r = result;
}
void helper_vcipherlast(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
{
+ ppc_avr_t result;
int i;
VECTOR_FOR_INORDER_I(i, u8) {
- r->AVRB(i) = b->AVRB(i) ^ (AES_sbox[a->AVRB(AES_shifts[i])]);
+ result.AVRB(i) = b->AVRB(i) ^ (AES_sbox[a->AVRB(AES_shifts[i])]);
}
+ *r = result;
}
void helper_vncipher(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
@@ -2369,11 +2373,13 @@ void helper_vncipher(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
void helper_vncipherlast(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
{
+ ppc_avr_t result;
int i;
VECTOR_FOR_INORDER_I(i, u8) {
- r->AVRB(i) = b->AVRB(i) ^ (AES_isbox[a->AVRB(AES_ishifts[i])]);
+ result.AVRB(i) = b->AVRB(i) ^ (AES_isbox[a->AVRB(AES_ishifts[i])]);
}
+ *r = result;
}
#define ROTRu32(v, n) (((v) >> (n)) | ((v) << (32-n)))
@@ -2460,16 +2466,19 @@ void helper_vshasigmad(ppc_avr_t *r, ppc_avr_t *a, uint32_t st_six)
void helper_vpermxor(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
{
+ ppc_avr_t result;
int i;
+
VECTOR_FOR_INORDER_I(i, u8) {
int indexA = c->u8[i] >> 4;
int indexB = c->u8[i] & 0xF;
#if defined(HOST_WORDS_BIGENDIAN)
- r->u8[i] = a->u8[indexA] ^ b->u8[indexB];
+ result.u8[i] = a->u8[indexA] ^ b->u8[indexB];
#else
- r->u8[i] = a->u8[15-indexA] ^ b->u8[15-indexB];
+ result.u8[i] = a->u8[15-indexA] ^ b->u8[15-indexB];
#endif
}
+ *r = result;
}
#undef VECTOR_FOR_INORDER_I
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index 110436d088..a307a13deb 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -2188,6 +2188,7 @@ static void kvmppc_host_cpu_initfn(Object *obj)
static void kvmppc_host_cpu_class_init(ObjectClass *oc, void *data)
{
+ DeviceClass *dc = DEVICE_CLASS(oc);
PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
uint32_t vmx = kvmppc_get_vmx();
uint32_t dfp = kvmppc_get_dfp();
@@ -2214,6 +2215,9 @@ static void kvmppc_host_cpu_class_init(ObjectClass *oc, void *data)
if (icache_size != -1) {
pcc->l1_icache_size = icache_size;
}
+
+ /* Reason: kvmppc_host_cpu_initfn() dies when !kvm_enabled() */
+ dc->cannot_destroy_with_object_finalize_yet = true;
}
bool kvmppc_has_cap_epr(void)
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 84c5cead6b..c0eed13f98 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -10670,6 +10670,13 @@ GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 1, opc3, 0, PPC_NONE, fl2), \
GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 2, opc3, 0, PPC_NONE, fl2), \
GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 3, opc3, 0, PPC_NONE, fl2)
+#undef GEN_XX2IFORM
+#define GEN_XX2IFORM(name, opc2, opc3, fl2) \
+GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 0, opc3, 1, PPC_NONE, fl2), \
+GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 1, opc3, 1, PPC_NONE, fl2), \
+GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 2, opc3, 1, PPC_NONE, fl2), \
+GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 3, opc3, 1, PPC_NONE, fl2)
+
#undef GEN_XX3_RC_FORM
#define GEN_XX3_RC_FORM(name, opc2, opc3, fl2) \
GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 0x00, opc3 | 0x00, 0, PPC_NONE, fl2), \
@@ -10731,8 +10738,8 @@ GEN_XX3FORM(xsnmaddadp, 0x04, 0x14, PPC2_VSX),
GEN_XX3FORM(xsnmaddmdp, 0x04, 0x15, PPC2_VSX),
GEN_XX3FORM(xsnmsubadp, 0x04, 0x16, PPC2_VSX),
GEN_XX3FORM(xsnmsubmdp, 0x04, 0x17, PPC2_VSX),
-GEN_XX2FORM(xscmpodp, 0x0C, 0x05, PPC2_VSX),
-GEN_XX2FORM(xscmpudp, 0x0C, 0x04, PPC2_VSX),
+GEN_XX2IFORM(xscmpodp, 0x0C, 0x05, PPC2_VSX),
+GEN_XX2IFORM(xscmpudp, 0x0C, 0x04, PPC2_VSX),
GEN_XX3FORM(xsmaxdp, 0x00, 0x14, PPC2_VSX),
GEN_XX3FORM(xsmindp, 0x00, 0x15, PPC2_VSX),
GEN_XX2FORM(xscvdpsp, 0x12, 0x10, PPC2_VSX),
diff --git a/target-s390x/cpu.c b/target-s390x/cpu.c
index c3e21b445c..ccfaa8a919 100644
--- a/target-s390x/cpu.c
+++ b/target-s390x/cpu.c
@@ -353,6 +353,13 @@ static void s390_cpu_class_init(ObjectClass *oc, void *data)
#endif
cc->gdb_num_core_regs = S390_NUM_CORE_REGS;
cc->gdb_core_xml_file = "s390x-core64.xml";
+
+ /*
+ * Reason: s390_cpu_initfn() calls cpu_exec_init(), which saves
+ * the object in cpus -> dangling pointer after final
+ * object_unref().
+ */
+ dc->cannot_destroy_with_object_finalize_yet = true;
}
static const TypeInfo s390_cpu_type_info = {
diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index ae3a0affec..6d1f284da0 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -2079,6 +2079,9 @@ void kvm_s390_crw_mchk(void)
.u.mchk.cr14 = 1 << 28,
.u.mchk.mcic = 0x00400f1d40330000ULL,
};
+ if (kvm_check_extension(kvm_state, KVM_CAP_S390_VECTOR_REGISTERS)) {
+ irq.u.mchk.mcic |= 0x0000004000000000ULL;
+ }
kvm_s390_floating_interrupt(&irq);
}
diff --git a/target-sh4/cpu.c b/target-sh4/cpu.c
index 5c65ab4df5..64e4467c04 100644
--- a/target-sh4/cpu.c
+++ b/target-sh4/cpu.c
@@ -290,6 +290,13 @@ static void superh_cpu_class_init(ObjectClass *oc, void *data)
#endif
dc->vmsd = &vmstate_sh_cpu;
cc->gdb_num_core_regs = 59;
+
+ /*
+ * Reason: superh_cpu_initfn() calls cpu_exec_init(), which saves
+ * the object in cpus -> dangling pointer after final
+ * object_unref().
+ */
+ dc->cannot_destroy_with_object_finalize_yet = true;
}
static const TypeInfo superh_cpu_type_info = {
diff --git a/target-sparc/cpu.c b/target-sparc/cpu.c
index 9528e3afbb..82bb72ab79 100644
--- a/target-sparc/cpu.c
+++ b/target-sparc/cpu.c
@@ -854,6 +854,13 @@ static void sparc_cpu_class_init(ObjectClass *oc, void *data)
#else
cc->gdb_num_core_regs = 72;
#endif
+
+ /*
+ * Reason: sparc_cpu_initfn() calls cpu_exec_init(), which saves
+ * the object in cpus -> dangling pointer after final
+ * object_unref().
+ */
+ dc->cannot_destroy_with_object_finalize_yet = true;
}
static const TypeInfo sparc_cpu_type_info = {
diff --git a/target-tricore/cpu.c b/target-tricore/cpu.c
index 2029ef651a..ed8b030ef5 100644
--- a/target-tricore/cpu.c
+++ b/target-tricore/cpu.c
@@ -170,6 +170,12 @@ static void tricore_cpu_class_init(ObjectClass *c, void *data)
cc->set_pc = tricore_cpu_set_pc;
cc->synchronize_from_tb = tricore_cpu_synchronize_from_tb;
+ /*
+ * Reason: tricore_cpu_initfn() calls cpu_exec_init(), which saves
+ * the object in cpus -> dangling pointer after final
+ * object_unref().
+ */
+ dc->cannot_destroy_with_object_finalize_yet = true;
}
static void cpu_register(const TriCoreCPUInfo *info)
diff --git a/target-unicore32/cpu.c b/target-unicore32/cpu.c
index fc451a1a35..e5252ebaf8 100644
--- a/target-unicore32/cpu.c
+++ b/target-unicore32/cpu.c
@@ -155,6 +155,13 @@ static void uc32_cpu_class_init(ObjectClass *oc, void *data)
cc->get_phys_page_debug = uc32_cpu_get_phys_page_debug;
#endif
dc->vmsd = &vmstate_uc32_cpu;
+
+ /*
+ * Reason: uc32_cpu_initfn() calls cpu_exec_init(), which saves
+ * the object in cpus -> dangling pointer after final
+ * object_unref().
+ */
+ dc->cannot_destroy_with_object_finalize_yet = true;
}
static void uc32_register_cpu_type(const UniCore32CPUInfo *info)
diff --git a/target-xtensa/cpu.c b/target-xtensa/cpu.c
index da8129db50..4e49bee9b5 100644
--- a/target-xtensa/cpu.c
+++ b/target-xtensa/cpu.c
@@ -155,6 +155,13 @@ static void xtensa_cpu_class_init(ObjectClass *oc, void *data)
#endif
cc->debug_excp_handler = xtensa_breakpoint_handler;
dc->vmsd = &vmstate_xtensa_cpu;
+
+ /*
+ * Reason: xtensa_cpu_initfn() calls cpu_exec_init(), which saves
+ * the object in cpus -> dangling pointer after final
+ * object_unref().
+ */
+ dc->cannot_destroy_with_object_finalize_yet = true;
}
static const TypeInfo xtensa_cpu_type_info = {
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index f2118c24c0..7a074e0e91 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -1943,7 +1943,8 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
switch (OP2) {
case 0: /*L32E*/
HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
- if (gen_check_privilege(dc)) {
+ if (gen_check_privilege(dc) &&
+ gen_window_check2(dc, RRR_S, RRR_T)) {
TCGv_i32 addr = tcg_temp_new_i32();
tcg_gen_addi_i32(addr, cpu_R[RRR_S],
(0xffffffc0 | (RRR_R << 2)));
@@ -1954,7 +1955,8 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
case 4: /*S32E*/
HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
- if (gen_check_privilege(dc)) {
+ if (gen_check_privilege(dc) &&
+ gen_window_check2(dc, RRR_S, RRR_T)) {
TCGv_i32 addr = tcg_temp_new_i32();
tcg_gen_addi_i32(addr, cpu_R[RRR_S],
(0xffffffc0 | (RRR_R << 2)));
diff --git a/tcg/aarch64/tcg-target.c b/tcg/aarch64/tcg-target.c
index b7ec4f5ace..bad8b1de96 100644
--- a/tcg/aarch64/tcg-target.c
+++ b/tcg/aarch64/tcg-target.c
@@ -56,6 +56,12 @@ static const int tcg_target_call_oarg_regs[1] = {
#define TCG_REG_TMP TCG_REG_X30
#ifndef CONFIG_SOFTMMU
+/* Note that XZR cannot be encoded in the address base register slot,
+ as that actaully encodes SP. So if we need to zero-extend the guest
+ address, via the address index register slot, we need to load even
+ a zero guest base into a register. */
+#define USE_GUEST_BASE (GUEST_BASE != 0 || TARGET_LONG_BITS == 32)
+
# ifdef CONFIG_USE_GUEST_BASE
# define TCG_REG_GUEST_BASE TCG_REG_X28
# else
@@ -1216,9 +1222,13 @@ static void tcg_out_qemu_ld(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
add_qemu_ldst_label(s, true, oi, ext, data_reg, addr_reg,
s->code_ptr, label_ptr);
#else /* !CONFIG_SOFTMMU */
- tcg_out_qemu_ld_direct(s, memop, ext, data_reg,
- GUEST_BASE ? TCG_REG_GUEST_BASE : TCG_REG_XZR,
- otype, addr_reg);
+ if (USE_GUEST_BASE) {
+ tcg_out_qemu_ld_direct(s, memop, ext, data_reg,
+ TCG_REG_GUEST_BASE, otype, addr_reg);
+ } else {
+ tcg_out_qemu_ld_direct(s, memop, ext, data_reg,
+ addr_reg, TCG_TYPE_I64, TCG_REG_XZR);
+ }
#endif /* CONFIG_SOFTMMU */
}
@@ -1238,9 +1248,13 @@ static void tcg_out_qemu_st(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
add_qemu_ldst_label(s, false, oi, s_bits == MO_64, data_reg, addr_reg,
s->code_ptr, label_ptr);
#else /* !CONFIG_SOFTMMU */
- tcg_out_qemu_st_direct(s, memop, data_reg,
- GUEST_BASE ? TCG_REG_GUEST_BASE : TCG_REG_XZR,
- otype, addr_reg);
+ if (USE_GUEST_BASE) {
+ tcg_out_qemu_st_direct(s, memop, data_reg,
+ TCG_REG_GUEST_BASE, otype, addr_reg);
+ } else {
+ tcg_out_qemu_st_direct(s, memop, data_reg,
+ addr_reg, TCG_TYPE_I64, TCG_REG_XZR);
+ }
#endif /* CONFIG_SOFTMMU */
}
@@ -1795,7 +1809,7 @@ static void tcg_target_qemu_prologue(TCGContext *s)
CPU_TEMP_BUF_NLONGS * sizeof(long));
#if defined(CONFIG_USE_GUEST_BASE)
- if (GUEST_BASE) {
+ if (USE_GUEST_BASE) {
tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_GUEST_BASE, GUEST_BASE);
tcg_regset_set_reg(s->reserved_regs, TCG_REG_GUEST_BASE);
}
diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c
index e97980df0b..2ccd0e8269 100644
--- a/tcg/mips/tcg-target.c
+++ b/tcg/mips/tcg-target.c
@@ -962,30 +962,34 @@ static void tcg_out_tlb_load(TCGContext *s, TCGReg base, TCGReg addrl,
add_off -= 0x7ff0;
}
- /* Load the tlb comparator. */
- if (TARGET_LONG_BITS == 64) {
- tcg_out_opc_imm(s, OPC_LW, TCG_TMP0, TCG_REG_A0, cmp_off + LO_OFF);
- tcg_out_opc_imm(s, OPC_LW, base, TCG_REG_A0, cmp_off + HI_OFF);
- } else {
- tcg_out_opc_imm(s, OPC_LW, TCG_TMP0, TCG_REG_A0, cmp_off);
- }
+ /* Load the (low half) tlb comparator. */
+ tcg_out_opc_imm(s, OPC_LW, TCG_TMP0, TCG_REG_A0,
+ cmp_off + (TARGET_LONG_BITS == 64 ? LO_OFF : 0));
/* Mask the page bits, keeping the alignment bits to compare against.
- In between, load the tlb addend for the fast path. */
+ In between on 32-bit targets, load the tlb addend for the fast path. */
tcg_out_movi(s, TCG_TYPE_I32, TCG_TMP1,
TARGET_PAGE_MASK | ((1 << s_bits) - 1));
- tcg_out_opc_imm(s, OPC_LW, TCG_REG_A0, TCG_REG_A0, add_off);
+ if (TARGET_LONG_BITS == 32) {
+ tcg_out_opc_imm(s, OPC_LW, TCG_REG_A0, TCG_REG_A0, add_off);
+ }
tcg_out_opc_reg(s, OPC_AND, TCG_TMP1, TCG_TMP1, addrl);
label_ptr[0] = s->code_ptr;
tcg_out_opc_br(s, OPC_BNE, TCG_TMP1, TCG_TMP0);
+ /* Load and test the high half tlb comparator. */
if (TARGET_LONG_BITS == 64) {
/* delay slot */
- tcg_out_nop(s);
+ tcg_out_opc_imm(s, OPC_LW, TCG_TMP0, TCG_REG_A0, cmp_off + HI_OFF);
+
+ /* Load the tlb addend for the fast path. We can't do it earlier with
+ 64-bit targets or we'll clobber a0 before reading the high half tlb
+ comparator. */
+ tcg_out_opc_imm(s, OPC_LW, TCG_REG_A0, TCG_REG_A0, add_off);
label_ptr[1] = s->code_ptr;
- tcg_out_opc_br(s, OPC_BNE, addrh, base);
+ tcg_out_opc_br(s, OPC_BNE, addrh, TCG_TMP0);
}
/* delay slot */
diff --git a/tests/Makefile b/tests/Makefile
index 749458224a..b453eb44ae 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -82,6 +82,9 @@ check-block-$(CONFIG_POSIX) += tests/qemu-iotests-quick.sh
# All QTests for now are POSIX-only, but the dependencies are
# really in libqtest, not in the testcases themselves.
+check-qtest-generic-y = tests/device-introspect-test$(EXESUF)
+gcov-files-generic-y = qdev-monitor.c qmp.c
+
gcov-files-ipack-y += hw/ipack/ipack.c
check-qtest-ipack-y += tests/ipoctal232-test$(EXESUF)
gcov-files-ipack-y += hw/char/ipoctal232.c
@@ -211,10 +214,7 @@ gcov-files-ppc64-y += ppc64-softmmu/hw/ppc/spapr_pci.c
check-qtest-microblazeel-y = $(check-qtest-microblaze-y)
check-qtest-xtensaeb-y = $(check-qtest-xtensa-y)
-# qom-test works for all sysemu architectures:
-$(foreach target,$(SYSEMU_TARGET_LIST), \
- $(if $(findstring tests/qom-test$(EXESUF), $(check-qtest-$(target)-y)),, \
- $(eval check-qtest-$(target)-y += tests/qom-test$(EXESUF))))
+check-qtest-generic-y += tests/qom-test$(EXESUF)
check-qapi-schema-y := $(addprefix tests/qapi-schema/, \
comments.json empty.json enum-empty.json enum-missing-data.json \
@@ -357,6 +357,7 @@ libqos-omap-obj-y = $(libqos-obj-y) tests/libqos/i2c-omap.o
libqos-usb-obj-y = $(libqos-pc-obj-y) tests/libqos/usb.o
libqos-virtio-obj-y = $(libqos-pc-obj-y) tests/libqos/virtio.o tests/libqos/virtio-pci.o tests/libqos/virtio-mmio.o tests/libqos/malloc-generic.o
+tests/device-introspect-test$(EXESUF): tests/device-introspect-test.o
tests/rtc-test$(EXESUF): tests/rtc-test.o
tests/m48t59-test$(EXESUF): tests/m48t59-test.o
tests/endianness-test$(EXESUF): tests/endianness-test.o
@@ -418,8 +419,11 @@ endif
TARGETS=$(patsubst %-softmmu,%, $(filter %-softmmu,$(TARGET_DIRS)))
ifeq ($(CONFIG_POSIX),y)
-QTEST_TARGETS=$(foreach TARGET,$(TARGETS), $(if $(check-qtest-$(TARGET)-y), $(TARGET),))
+QTEST_TARGETS = $(TARGETS)
check-qtest-y=$(foreach TARGET,$(TARGETS), $(check-qtest-$(TARGET)-y))
+check-qtest-y += $(check-qtest-generic-y)
+else
+QTEST_TARGETS =
endif
qtest-obj-y = tests/libqtest.o libqemuutil.a libqemustub.a
@@ -457,8 +461,8 @@ $(patsubst %, check-qtest-%, $(QTEST_TARGETS)): check-qtest-%: $(check-qtest-y)
$(call quiet-command,QTEST_QEMU_BINARY=$*-softmmu/qemu-system-$* \
QTEST_QEMU_IMG=qemu-img$(EXESUF) \
MALLOC_PERTURB_=$${MALLOC_PERTURB_:-$$((RANDOM % 255 + 1))} \
- gtester $(GTESTER_OPTIONS) -m=$(SPEED) $(check-qtest-$*-y),"GTESTER $@")
- $(if $(CONFIG_GCOV),@for f in $(gcov-files-$*-y); do \
+ gtester $(GTESTER_OPTIONS) -m=$(SPEED) $(check-qtest-$*-y) $(check-qtest-generic-y),"GTESTER $@")
+ $(if $(CONFIG_GCOV),@for f in $(gcov-files-$*-y) $(gcov-files-generic-y); do \
echo Gcov report for $$f:;\
$(GCOV) $(GCOV_OPTIONS) $$f -o `dirname $$f`; \
done,)
@@ -469,7 +473,7 @@ $(patsubst %, check-%, $(check-unit-y)): check-%: %
$(call quiet-command, \
MALLOC_PERTURB_=$${MALLOC_PERTURB_:-$$((RANDOM % 255 + 1))} \
gtester $(GTESTER_OPTIONS) -m=$(SPEED) $*,"GTESTER $*")
- $(if $(CONFIG_GCOV),@for f in $(gcov-files-$(subst tests/,,$*)-y); do \
+ $(if $(CONFIG_GCOV),@for f in $(gcov-files-$(subst tests/,,$*)-y) $(gcov-files-generic-y); do \
echo Gcov report for $$f:;\
$(GCOV) $(GCOV_OPTIONS) $$f -o `dirname $$f`; \
done,)
diff --git a/tests/device-introspect-test.c b/tests/device-introspect-test.c
new file mode 100644
index 0000000000..f240b5c827
--- /dev/null
+++ b/tests/device-introspect-test.c
@@ -0,0 +1,158 @@
+/*
+ * Device introspection test cases
+ *
+ * Copyright (c) 2015 Red Hat Inc.
+ *
+ * Authors:
+ * Markus Armbruster <armbru@redhat.com>,
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+/*
+ * Covers QMP device-list-properties and HMP device_add help. We
+ * currently don't check that their output makes sense, only that QEMU
+ * survives. Useful since we've had an astounding number of crash
+ * bugs around here.
+ */
+
+#include <glib.h>
+#include <stdarg.h>
+#include "qemu-common.h"
+#include "qapi/qmp/qstring.h"
+#include "libqtest.h"
+
+const char common_args[] = "-nodefaults -machine none";
+
+static QList *device_type_list(bool abstract)
+{
+ QDict *resp;
+ QList *ret;
+
+ resp = qmp("{'execute': 'qom-list-types',"
+ " 'arguments': {'implements': 'device', 'abstract': %i}}",
+ abstract);
+ g_assert(qdict_haskey(resp, "return"));
+ ret = qdict_get_qlist(resp, "return");
+ QINCREF(ret);
+ QDECREF(resp);
+ return ret;
+}
+
+static void test_one_device(const char *type)
+{
+ QDict *resp;
+ char *help, *qom_tree;
+
+ /*
+ * Skip this part for the abstract device test case, because
+ * device-list-properties crashes for such devices.
+ * FIXME fix it not to crash
+ */
+ if (strcmp(type, "device")) {
+ resp = qmp("{'execute': 'device-list-properties',"
+ " 'arguments': {'typename': %s}}",
+ type);
+ QDECREF(resp);
+ }
+
+ help = hmp("device_add \"%s,help\"", type);
+ g_free(help);
+
+ /*
+ * Some devices leave dangling pointers in QOM behind.
+ * "info qom-tree" has a good chance at crashing then
+ */
+ qom_tree = hmp("info qom-tree");
+ g_free(qom_tree);
+}
+
+static void test_device_intro_list(void)
+{
+ QList *types;
+ char *help;
+
+ qtest_start(common_args);
+
+ types = device_type_list(true);
+ QDECREF(types);
+
+ help = hmp("device_add help");
+ g_free(help);
+
+ qtest_end();
+}
+
+static void test_device_intro_none(void)
+{
+ qtest_start(common_args);
+ test_one_device("nonexistent");
+ qtest_end();
+}
+
+static void test_device_intro_abstract(void)
+{
+ qtest_start(common_args);
+ test_one_device("device");
+ qtest_end();
+}
+
+static bool blacklisted(const char *type)
+{
+ static const char *blacklist[] = {
+ /* hang in object_unref(): */
+ "realview_pci", "versatile_pci",
+ /* create a CPU, thus use after free (see below): */
+ "allwinner-a10", "digic", "fsl,imx25", "fsl,imx31", "xlnx,zynqmp",
+ };
+ size_t len = strlen(type);
+ int i;
+
+ if (len >= 4 && !strcmp(type + len - 4, "-cpu")) {
+ /* use after free: cpu_exec_init() saves CPUState in cpus */
+ return true;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(blacklist); i++) {
+ if (!strcmp(blacklist[i], type)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+static void test_device_intro_concrete(void)
+{
+ QList *types;
+ QListEntry *entry;
+ const char *type;
+
+ qtest_start(common_args);
+ types = device_type_list(false);
+
+ QLIST_FOREACH_ENTRY(types, entry) {
+ type = qdict_get_try_str(qobject_to_qdict(qlist_entry_obj(entry)),
+ "name");
+ g_assert(type);
+ if (blacklisted(type)) {
+ continue; /* FIXME broken device, skip */
+ }
+ test_one_device(type);
+ }
+
+ QDECREF(types);
+ qtest_end();
+}
+
+int main(int argc, char **argv)
+{
+ g_test_init(&argc, &argv, NULL);
+
+ qtest_add_func("device/introspect/list", test_device_intro_list);
+ qtest_add_func("device/introspect/none", test_device_intro_none);
+ qtest_add_func("device/introspect/abstract", test_device_intro_abstract);
+ qtest_add_func("device/introspect/concrete", test_device_intro_concrete);
+
+ return g_test_run();
+}
diff --git a/tests/drive_del-test.c b/tests/drive_del-test.c
index 8951f6f610..33909469f1 100644
--- a/tests/drive_del-test.c
+++ b/tests/drive_del-test.c
@@ -16,28 +16,18 @@
static void drive_add(void)
{
- QDict *response;
+ char *resp = hmp("drive_add 0 if=none,id=drive0");
- response = qmp("{'execute': 'human-monitor-command',"
- " 'arguments': {"
- " 'command-line': 'drive_add 0 if=none,id=drive0'"
- "}}");
- g_assert(response);
- g_assert_cmpstr(qdict_get_try_str(response, "return"), ==, "OK\r\n");
- QDECREF(response);
+ g_assert_cmpstr(resp, ==, "OK\r\n");
+ g_free(resp);
}
static void drive_del(void)
{
- QDict *response;
+ char *resp = hmp("drive_del drive0");
- response = qmp("{'execute': 'human-monitor-command',"
- " 'arguments': {"
- " 'command-line': 'drive_del drive0'"
- "}}");
- g_assert(response);
- g_assert_cmpstr(qdict_get_try_str(response, "return"), ==, "");
- QDECREF(response);
+ g_assert_cmpstr(resp, ==, "");
+ g_free(resp);
}
static void device_del(void)
diff --git a/tests/ide-test.c b/tests/ide-test.c
index 4a07e3a9d0..ef0a473437 100644
--- a/tests/ide-test.c
+++ b/tests/ide-test.c
@@ -488,9 +488,7 @@ static void test_flush(void)
tmp_path);
/* Delay the completion of the flush request until we explicitly do it */
- qmp_discard_response("{'execute':'human-monitor-command', 'arguments': {"
- " 'command-line':"
- " 'qemu-io ide0-hd0 \"break flush_to_os A\"'} }");
+ g_free(hmp("qemu-io ide0-hd0 \"break flush_to_os A\""));
/* FLUSH CACHE command on device 0*/
outb(IDE_BASE + reg_device, 0);
@@ -502,9 +500,7 @@ static void test_flush(void)
assert_bit_clear(data, DF | ERR | DRQ);
/* Complete the command */
- qmp_discard_response("{'execute':'human-monitor-command', 'arguments': {"
- " 'command-line':"
- " 'qemu-io ide0-hd0 \"resume A\"'} }");
+ g_free(hmp("qemu-io ide0-hd0 \"resume A\""));
/* Check registers */
data = inb(IDE_BASE + reg_device);
diff --git a/tests/libqtest.c b/tests/libqtest.c
index e5188e0327..f1b8206c3c 100644
--- a/tests/libqtest.c
+++ b/tests/libqtest.c
@@ -484,6 +484,33 @@ void qtest_qmp_eventwait(QTestState *s, const char *event)
}
}
+char *qtest_hmpv(QTestState *s, const char *fmt, va_list ap)
+{
+ char *cmd;
+ QDict *resp;
+ char *ret;
+
+ cmd = g_strdup_vprintf(fmt, ap);
+ resp = qtest_qmp(s, "{'execute': 'human-monitor-command',"
+ " 'arguments': {'command-line': %s}}",
+ cmd);
+ ret = g_strdup(qdict_get_try_str(resp, "return"));
+ g_assert(ret);
+ QDECREF(resp);
+ g_free(cmd);
+ return ret;
+}
+
+char *qtest_hmp(QTestState *s, const char *fmt, ...)
+{
+ va_list ap;
+ char *ret;
+
+ va_start(ap, fmt);
+ ret = qtest_hmpv(s, fmt, ap);
+ va_end(ap);
+ return ret;
+}
const char *qtest_get_arch(void)
{
@@ -775,6 +802,16 @@ void qmp_discard_response(const char *fmt, ...)
qtest_qmpv_discard_response(global_qtest, fmt, ap);
va_end(ap);
}
+char *hmp(const char *fmt, ...)
+{
+ va_list ap;
+ char *ret;
+
+ va_start(ap, fmt);
+ ret = qtest_hmpv(global_qtest, fmt, ap);
+ va_end(ap);
+ return ret;
+}
bool qtest_big_endian(void)
{
diff --git a/tests/libqtest.h b/tests/libqtest.h
index ec42031523..55bccbf0e6 100644
--- a/tests/libqtest.h
+++ b/tests/libqtest.h
@@ -120,6 +120,29 @@ QDict *qtest_qmp_receive(QTestState *s);
void qtest_qmp_eventwait(QTestState *s, const char *event);
/**
+ * qtest_hmpv:
+ * @s: #QTestState instance to operate on.
+ * @fmt...: HMP command to send to QEMU
+ *
+ * Send HMP command to QEMU via QMP's human-monitor-command.
+ *
+ * Returns: the command's output. The caller should g_free() it.
+ */
+char *qtest_hmp(QTestState *s, const char *fmt, ...);
+
+/**
+ * qtest_hmpv:
+ * @s: #QTestState instance to operate on.
+ * @fmt: HMP command to send to QEMU
+ * @ap: HMP command arguments
+ *
+ * Send HMP command to QEMU via QMP's human-monitor-command.
+ *
+ * Returns: the command's output. The caller should g_free() it.
+ */
+char *qtest_hmpv(QTestState *s, const char *fmt, va_list ap);
+
+/**
* qtest_get_irq:
* @s: #QTestState instance to operate on.
* @num: Interrupt to observe.
@@ -499,6 +522,16 @@ static inline void qmp_eventwait(const char *event)
}
/**
+ * hmp:
+ * @fmt...: HMP command to send to QEMU
+ *
+ * Send HMP command to QEMU via QMP's human-monitor-command.
+ *
+ * Returns: the command's output. The caller should g_free() it.
+ */
+char *hmp(const char *fmt, ...);
+
+/**
* get_irq:
* @num: Interrupt to observe.
*
diff --git a/trace-events b/trace-events
index 94bf3bb184..e198730780 100644
--- a/trace-events
+++ b/trace-events
@@ -601,9 +601,6 @@ scsi_request_sense(int target, int lun, int tag) "target %d lun %d tag %d"
vm_state_notify(int running, int reason) "running %d reason %d"
load_file(const char *name, const char *path) "name %s location %s"
runstate_set(int new_state) "new state %d"
-g_malloc(size_t size, void *ptr) "size %zu ptr %p"
-g_realloc(void *ptr, size_t size, void *newptr) "ptr %p size %zu newptr %p"
-g_free(void *ptr) "ptr %p"
system_wakeup_request(int reason) "reason=%d"
qemu_system_shutdown_request(void) ""
qemu_system_powerdown_request(void) ""
diff --git a/ui/gtk.c b/ui/gtk.c
index df2a79e7ac..11ea2cf37c 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -1941,7 +1941,8 @@ void gtk_display_init(DisplayState *ds, bool full_screen, bool grab_on_hover)
s->free_scale = FALSE;
- setlocale(LC_ALL, "");
+ /* LC_MESSAGES only. See early_gtk_display_init() for details */
+ setlocale(LC_MESSAGES, "");
bindtextdomain("qemu", CONFIG_QEMU_LOCALEDIR);
textdomain("qemu");
@@ -2010,6 +2011,24 @@ void gtk_display_init(DisplayState *ds, bool full_screen, bool grab_on_hover)
void early_gtk_display_init(int opengl)
{
+ /* The QEMU code relies on the assumption that it's always run in
+ * the C locale. Therefore it is not prepared to deal with
+ * operations that produce different results depending on the
+ * locale, such as printf's formatting of decimal numbers, and
+ * possibly others.
+ *
+ * Since GTK+ calls setlocale() by default -importing the locale
+ * settings from the environment- we must prevent it from doing so
+ * using gtk_disable_setlocale().
+ *
+ * QEMU's GTK+ UI, however, _does_ have translations for some of
+ * the menu items. As a trade-off between a functionally correct
+ * QEMU and a fully internationalized UI we support importing
+ * LC_MESSAGES from the environment (see the setlocale() call
+ * earlier in this file). This allows us to display translated
+ * messages leaving everything else untouched.
+ */
+ gtk_disable_setlocale();
gtkinit = gtk_init_check(NULL, NULL);
if (!gtkinit) {
/* don't exit yet, that'll break -help */
diff --git a/util/qemu-config.c b/util/qemu-config.c
index 5fcfd0e6ac..687fd34cc6 100644
--- a/util/qemu-config.c
+++ b/util/qemu-config.c
@@ -219,6 +219,14 @@ static QemuOptsList machine_opts = {
.name = "suppress-vmdesc",
.type = QEMU_OPT_BOOL,
.help = "Set on to disable self-describing migration",
+ },{
+ .name = "aes-key-wrap",
+ .type = QEMU_OPT_BOOL,
+ .help = "enable/disable AES key wrapping using the CPACF wrapping key",
+ },{
+ .name = "dea-key-wrap",
+ .type = QEMU_OPT_BOOL,
+ .help = "enable/disable DEA key wrapping using the CPACF wrapping key",
},
{ /* End of list */ }
}
diff --git a/vl.c b/vl.c
index 46ada404ef..3405c042ef 100644
--- a/vl.c
+++ b/vl.c
@@ -2825,28 +2825,6 @@ static const QEMUOption *lookup_opt(int argc, char **argv,
return popt;
}
-#if !GLIB_CHECK_VERSION(2, 46, 0)
-static gpointer malloc_and_trace(gsize n_bytes)
-{
- void *ptr = malloc(n_bytes);
- trace_g_malloc(n_bytes, ptr);
- return ptr;
-}
-
-static gpointer realloc_and_trace(gpointer mem, gsize n_bytes)
-{
- void *ptr = realloc(mem, n_bytes);
- trace_g_realloc(mem, n_bytes, ptr);
- return ptr;
-}
-
-static void free_and_trace(gpointer mem)
-{
- trace_g_free(mem);
- free(mem);
-}
-#endif
-
static int machine_set_property(void *opaque,
const char *name, const char *value,
Error **errp)
@@ -3079,13 +3057,6 @@ int main(int argc, char **argv, char **envp)
bool userconfig = true;
const char *log_mask = NULL;
const char *log_file = NULL;
-#if !GLIB_CHECK_VERSION(2, 46, 0)
- GMemVTable mem_trace = {
- .malloc = malloc_and_trace,
- .realloc = realloc_and_trace,
- .free = free_and_trace,
- };
-#endif
const char *trace_events = NULL;
const char *trace_file = NULL;
ram_addr_t maxram_size;
@@ -3111,10 +3082,6 @@ int main(int argc, char **argv, char **envp)
error_set_progname(argv[0]);
qemu_init_exec_dir(argv[0]);
-#if !GLIB_CHECK_VERSION(2, 46, 0)
- g_mem_set_vtable(&mem_trace);
-#endif
-
module_call_init(MODULE_INIT_QOM);
qemu_add_opts(&qemu_drive_opts);