|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [qemu-upstream-unstable] Merge tag 'v2.0.2' into master
=== This changeset includes merge from high-traffic branch ===
Commits on that branch are not reported individually.
commit c9d8f8b755e8960edf7725e05f3e6ac743a5e12e
Merge: ea772ca487e219e5d5b82d50da460c4145238038
f053f6b83d01b47adf3b8f29eb0c0769755d1f9c
Author: Anthony PERARD <anthony.perard@xxxxxxxxxx>
AuthorDate: Wed Sep 24 15:25:27 2014 +0100
Commit: Anthony PERARD <anthony.perard@xxxxxxxxxx>
CommitDate: Wed Sep 24 15:25:27 2014 +0100
Merge tag 'v2.0.2' into master
VERSION | 2 +-
arch_init.c | 110 ++++++++++++-----------
async.c | 14 ++-
block.c | 34 ++++---
block/mirror.c | 19 +++-
block/qapi.c | 1 +
block/qcow.c | 44 ++++++++--
block/qcow2.c | 3 +-
block/sheepdog.c | 4 +-
block/vvfat.c | 6 +-
blockdev-nbd.c | 9 ++-
blockdev.c | 23 ++++-
blockjob.c | 14 +++
configure | 2 +-
coroutine-win32.c | 13 +++-
cputlb.c | 6 +-
disas/Makefile.objs | 2 +-
hw/arm/boot.c | 8 ++-
hw/arm/omap1.c | 14 ++--
hw/arm/omap2.c | 2 +-
hw/arm/pxa2xx.c | 12 ++-
hw/arm/spitz.c | 4 +-
hw/arm/z2.c | 2 +-
hw/char/cadence_uart.c | 15 +++-
hw/char/virtio-serial-bus.c | 16 ++--
hw/core/irq.c | 4 +-
hw/core/qdev.c | 45 +++++-----
hw/display/ssd0323.c | 24 +++++
hw/dma/omap_dma.c | 4 +-
hw/gpio/zaurus.c | 10 ++
hw/i386/acpi-build.c | 7 +-
hw/i386/kvm/pci-assign.c | 12 ++--
hw/i386/pc.c | 2 +-
hw/i386/pc_piix.c | 20 +++--
hw/i386/pc_q35.c | 12 ++--
hw/i386/smbios.c | 18 +++--
hw/ide/ahci.c | 2 +-
hw/ide/microdrive.c | 2 +-
hw/input/tsc210x.c | 12 +++
hw/intc/i8259.c | 4 +-
hw/intc/openpic.c | 16 +++-
hw/misc/cbus.c | 6 +-
hw/misc/imx_ccm.c | 1 +
hw/net/stellaris_enet.c | 23 ++++--
hw/net/virtio-net.c | 37 +++++++-
hw/pci/pci.c | 2 +-
hw/pci/pcie_aer.c | 10 ++-
hw/pcmcia/pxa2xx.c | 2 +-
hw/ppc/spapr_pci.c | 15 +++
hw/s390x/css.c | 24 ++++-
hw/scsi/megasas.c | 17 ++++
hw/scsi/mfi.h | 9 ++
hw/scsi/scsi-disk.c | 2 +-
hw/scsi/vhost-scsi.c | 8 ++-
hw/scsi/virtio-scsi.c | 26 ++++--
hw/sd/omap_mmc.c | 2 +-
hw/sd/sdhci.c | 8 +-
hw/sd/ssi-sd.c | 9 ++
hw/sh4/sh7750.c | 3 +-
hw/ssi/pl022.c | 14 +++
hw/timer/hpet.c | 13 +++
hw/timer/i8254.c | 4 +-
hw/timer/mc146818rtc.c | 2 +-
hw/timer/omap_gptimer.c | 4 +-
hw/usb/bus.c | 4 +-
hw/usb/dev-bluetooth.c | 24 ++++--
hw/usb/hcd-xhci.c | 1 +
hw/virtio/vhost.c | 10 ++-
hw/virtio/virtio.c | 33 ++++++-
hw/xtensa/xtensa_lx60.c | 8 +-
include/block/blockjob.h | 8 ++
include/hw/i386/smbios.h | 6 +-
include/hw/virtio/virtio-net.h | 4 +-
include/hw/virtio/virtio-scsi.h | 7 ++-
include/migration/vmstate.h | 9 ++
kvm-all.c | 7 +-
linux-user/elfload.c | 117 ++++++++++++++++++++----
linux-user/syscall.c | 16 ++++
migration-rdma.c | 20 ++--
migration.c | 2 +-
nbd.c | 7 +-
po/Makefile | 4 +-
qapi-schema.json | 7 +-
qapi/qapi-dealloc-visitor.c | 4 +-
qdev-monitor.c | 2 +-
qemu-img.c | 2 +-
qemu-io.c | 2 +
qemu-nbd.c | 5 +-
qga/commands-win32.c | 6 +-
qmp-commands.hx | 5 +-
target-arm/helper.c | 8 +-
target-arm/translate-a64.c | 5 +-
target-arm/translate.c | 34 +++++---
target-i386/cpu.c | 22 +++--
target-i386/cpu.h | 11 ++-
target-s390x/kvm.c | 190 +++++++++++++++++++++++----------------
target-xtensa/translate.c | 4 +-
tcg/i386/tcg-target.c | 3 +-
tests/qemu-iotests/040 | 38 ++++++---
tests/qemu-iotests/040.out | 4 +-
tests/qemu-iotests/041 | 16 +++-
tests/qemu-iotests/041.out | 4 +-
tests/qemu-iotests/092 | 98 ++++++++++++++++++++
tests/qemu-iotests/092.out | 38 ++++++++
tests/qemu-iotests/group | 1 +
trace-events | 5 +
ui/curses.c | 4 +-
vmstate.c | 117 ++++++++++++++-----------
108 files changed, 1248 insertions(+), 488 deletions(-)
diff --git a/VERSION b/VERSION
index 227cea2..e9307ca 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.0.0
+2.0.2
diff --git a/arch_init.c b/arch_init.c
index 60c975d..3ec70de 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -992,70 +992,68 @@ static int ram_load(QEMUFile *f, void *opaque, int
version_id)
{
ram_addr_t addr;
int flags, ret = 0;
- int error;
static uint64_t seq_iter;
seq_iter++;
- if (version_id < 4 || version_id > 4) {
- return -EINVAL;
+ if (version_id != 4) {
+ ret = -EINVAL;
}
- do {
+ while (!ret) {
addr = qemu_get_be64(f);
flags = addr & ~TARGET_PAGE_MASK;
addr &= TARGET_PAGE_MASK;
if (flags & RAM_SAVE_FLAG_MEM_SIZE) {
- if (version_id == 4) {
- /* Synchronize RAM block list */
- char id[256];
- ram_addr_t length;
- ram_addr_t total_ram_bytes = addr;
-
- while (total_ram_bytes) {
- RAMBlock *block;
- uint8_t len;
-
- len = qemu_get_byte(f);
- qemu_get_buffer(f, (uint8_t *)id, len);
- id[len] = 0;
- length = qemu_get_be64(f);
-
- QTAILQ_FOREACH(block, &ram_list.blocks, next) {
- if (!strncmp(id, block->idstr, sizeof(id))) {
- if (block->length != length) {
- fprintf(stderr,
- "Length mismatch: %s: " RAM_ADDR_FMT
- " in != " RAM_ADDR_FMT "\n", id,
length,
- block->length);
- ret = -EINVAL;
- goto done;
- }
- break;
+ /* Synchronize RAM block list */
+ char id[256];
+ ram_addr_t length;
+ ram_addr_t total_ram_bytes = addr;
+
+ while (total_ram_bytes) {
+ RAMBlock *block;
+ uint8_t len;
+
+ len = qemu_get_byte(f);
+ qemu_get_buffer(f, (uint8_t *)id, len);
+ id[len] = 0;
+ length = qemu_get_be64(f);
+
+ QTAILQ_FOREACH(block, &ram_list.blocks, next) {
+ if (!strncmp(id, block->idstr, sizeof(id))) {
+ if (block->length != length) {
+ fprintf(stderr,
+ "Length mismatch: %s: " RAM_ADDR_FMT
+ " in != " RAM_ADDR_FMT "\n", id, length,
+ block->length);
+ ret = -EINVAL;
}
+ break;
}
+ }
- if (!block) {
- fprintf(stderr, "Unknown ramblock \"%s\", cannot "
- "accept migration\n", id);
- ret = -EINVAL;
- goto done;
- }
-
- total_ram_bytes -= length;
+ if (!block) {
+ fprintf(stderr, "Unknown ramblock \"%s\", cannot "
+ "accept migration\n", id);
+ ret = -EINVAL;
+ }
+ if (ret) {
+ break;
}
- }
- }
- if (flags & RAM_SAVE_FLAG_COMPRESS) {
+ total_ram_bytes -= length;
+ }
+ } else if (flags & RAM_SAVE_FLAG_COMPRESS) {
void *host;
uint8_t ch;
host = host_from_stream_offset(f, addr, flags);
if (!host) {
- return -EINVAL;
+ error_report("Illegal RAM offset " RAM_ADDR_FMT, addr);
+ ret = -EINVAL;
+ break;
}
ch = qemu_get_byte(f);
@@ -1065,31 +1063,39 @@ static int ram_load(QEMUFile *f, void *opaque, int
version_id)
host = host_from_stream_offset(f, addr, flags);
if (!host) {
- return -EINVAL;
+ error_report("Illegal RAM offset " RAM_ADDR_FMT, addr);
+ ret = -EINVAL;
+ break;
}
qemu_get_buffer(f, host, TARGET_PAGE_SIZE);
} else if (flags & RAM_SAVE_FLAG_XBZRLE) {
void *host = host_from_stream_offset(f, addr, flags);
if (!host) {
- return -EINVAL;
+ error_report("Illegal RAM offset " RAM_ADDR_FMT, addr);
+ ret = -EINVAL;
+ break;
}
if (load_xbzrle(f, addr, host) < 0) {
+ error_report("Failed to decompress XBZRLE page at "
+ RAM_ADDR_FMT, addr);
ret = -EINVAL;
- goto done;
+ break;
}
} else if (flags & RAM_SAVE_FLAG_HOOK) {
ram_control_load_hook(f, flags);
+ } else if (flags & RAM_SAVE_FLAG_EOS) {
+ /* normal exit */
+ break;
+ } else {
+ error_report("Unknown migration flags: %#x", flags);
+ ret = -EINVAL;
+ break;
}
- error = qemu_file_get_error(f);
- if (error) {
- ret = error;
- goto done;
- }
- } while (!(flags & RAM_SAVE_FLAG_EOS));
+ ret = qemu_file_get_error(f);
+ }
-done:
DPRINTF("Completed load of VM with exit code %d seq iteration "
"%" PRIu64 "\n", ret, seq_iter);
return ret;
diff --git a/async.c b/async.c
index 6930185..5b6fe6b 100644
--- a/async.c
+++ b/async.c
@@ -117,15 +117,21 @@ void qemu_bh_schedule_idle(QEMUBH *bh)
void qemu_bh_schedule(QEMUBH *bh)
{
+ AioContext *ctx;
+
if (bh->scheduled)
return;
+ ctx = bh->ctx;
bh->idle = 0;
- /* Make sure that idle & any writes needed by the callback are done
- * before the locations are read in the aio_bh_poll.
+ /* Make sure that:
+ * 1. idle & any writes needed by the callback are done before the
+ * locations are read in the aio_bh_poll.
+ * 2. ctx is loaded before scheduled is set and the callback has a chance
+ * to execute.
*/
- smp_wmb();
+ smp_mb();
bh->scheduled = 1;
- aio_notify(bh->ctx);
+ aio_notify(ctx);
}
diff --git a/block.c b/block.c
index 990a754..5448430 100644
--- a/block.c
+++ b/block.c
@@ -1058,14 +1058,14 @@ fail:
*/
int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp)
{
- char backing_filename[PATH_MAX];
- int back_flags, ret;
+ char *backing_filename = g_malloc0(PATH_MAX);
+ int back_flags, ret = 0;
BlockDriver *back_drv = NULL;
Error *local_err = NULL;
if (bs->backing_hd != NULL) {
QDECREF(options);
- return 0;
+ goto free_exit;
}
/* NULL means an empty set of options */
@@ -1078,10 +1078,9 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict
*options, Error **errp)
backing_filename[0] = '\0';
} else if (bs->backing_file[0] == '\0' && qdict_size(options) == 0) {
QDECREF(options);
- return 0;
+ goto free_exit;
} else {
- bdrv_get_full_backing_filename(bs, backing_filename,
- sizeof(backing_filename));
+ bdrv_get_full_backing_filename(bs, backing_filename, PATH_MAX);
}
if (bs->backing_format[0] != '\0') {
@@ -1102,7 +1101,7 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict
*options, Error **errp)
error_setg(errp, "Could not open backing file: %s",
error_get_pretty(local_err));
error_free(local_err);
- return ret;
+ goto free_exit;
}
if (bs->backing_hd->file) {
@@ -1113,7 +1112,9 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict
*options, Error **errp)
/* Recalculate the BlockLimits with the backing file */
bdrv_refresh_limits(bs);
- return 0;
+free_exit:
+ g_free(backing_filename);
+ return ret;
}
/*
@@ -1157,6 +1158,7 @@ int bdrv_open_image(BlockDriverState **pbs, const char
*filename,
bdref_key);
ret = -EINVAL;
}
+ QDECREF(image_options);
goto done;
}
@@ -1170,8 +1172,7 @@ done:
void bdrv_append_temp_snapshot(BlockDriverState *bs, Error **errp)
{
/* TODO: extra byte is a hack to ensure MAX_PATH space on Windows. */
- char tmp_filename[PATH_MAX + 1];
-
+ char *tmp_filename = g_malloc0(PATH_MAX + 1);
int64_t total_size;
BlockDriver *bdrv_qcow2;
QEMUOptionParameter *create_options;
@@ -1187,15 +1188,15 @@ void bdrv_append_temp_snapshot(BlockDriverState *bs,
Error **errp)
total_size = bdrv_getlength(bs);
if (total_size < 0) {
error_setg_errno(errp, -total_size, "Could not get image size");
- return;
+ goto out;
}
total_size &= BDRV_SECTOR_MASK;
/* Create the temporary image */
- ret = get_tmp_filename(tmp_filename, sizeof(tmp_filename));
+ ret = get_tmp_filename(tmp_filename, PATH_MAX + 1);
if (ret < 0) {
error_setg_errno(errp, -ret, "Could not get temporary filename");
- return;
+ goto out;
}
bdrv_qcow2 = bdrv_find_format("qcow2");
@@ -1211,7 +1212,7 @@ void bdrv_append_temp_snapshot(BlockDriverState *bs,
Error **errp)
"'%s': %s", tmp_filename,
error_get_pretty(local_err));
error_free(local_err);
- return;
+ goto out;
}
/* Prepare a new options QDict for the temporary file */
@@ -1228,10 +1229,13 @@ void bdrv_append_temp_snapshot(BlockDriverState *bs,
Error **errp)
bs->open_flags & ~BDRV_O_SNAPSHOT, bdrv_qcow2, &local_err);
if (ret < 0) {
error_propagate(errp, local_err);
- return;
+ goto out;
}
bdrv_append(bs_snapshot, bs);
+
+out:
+ g_free(tmp_filename);
}
/*
diff --git a/block/mirror.c b/block/mirror.c
index 0ef41f9..6e502e3 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -259,9 +259,11 @@ static uint64_t coroutine_fn
mirror_iteration(MirrorBlockJob *s)
next_sector = sector_num;
while (nb_chunks-- > 0) {
MirrorBuffer *buf = QSIMPLEQ_FIRST(&s->buf_free);
+ size_t remaining = (nb_sectors * BDRV_SECTOR_SIZE) - op->qiov.size;
+
QSIMPLEQ_REMOVE_HEAD(&s->buf_free, next);
s->buf_free_count--;
- qemu_iovec_add(&op->qiov, buf, s->granularity);
+ qemu_iovec_add(&op->qiov, buf, MIN(s->granularity, remaining));
/* Advance the HBitmapIter in parallel, so that we do not examine
* the same sector twice.
@@ -324,9 +326,18 @@ static void coroutine_fn mirror_run(void *opaque)
}
s->common.len = bdrv_getlength(bs);
- if (s->common.len <= 0) {
- block_job_completed(&s->common, s->common.len);
- return;
+ if (s->common.len < 0) {
+ ret = s->common.len;
+ goto immediate_exit;
+ } else if (s->common.len == 0) {
+ /* Report BLOCK_JOB_READY and wait for complete. */
+ block_job_ready(&s->common);
+ s->synced = true;
+ while (!block_job_is_cancelled(&s->common) && !s->should_complete) {
+ block_job_yield(&s->common);
+ }
+ s->common.cancelled = false;
+ goto immediate_exit;
}
length = (bdrv_getlength(bs) + s->granularity - 1) / s->granularity;
diff --git a/block/qapi.c b/block/qapi.c
index 8f2b4db..a69c00d 100644
--- a/block/qapi.c
+++ b/block/qapi.c
@@ -474,6 +474,7 @@ static void dump_qobject(fprintf_function func_fprintf,
void *f,
case QTYPE_QERROR: {
QString *value = qerror_human((QError *)obj);
func_fprintf(f, "%s", qstring_get_str(value));
+ QDECREF(value);
break;
}
case QTYPE_NONE:
diff --git a/block/qcow.c b/block/qcow.c
index d5a7d5f..c0a3b89 100644
--- a/block/qcow.c
+++ b/block/qcow.c
@@ -48,9 +48,10 @@ typedef struct QCowHeader {
uint64_t size; /* in bytes */
uint8_t cluster_bits;
uint8_t l2_bits;
+ uint16_t padding;
uint32_t crypt_method;
uint64_t l1_table_offset;
-} QCowHeader;
+} QEMU_PACKED QCowHeader;
#define L2_CACHE_SIZE 16
@@ -60,7 +61,7 @@ typedef struct BDRVQcowState {
int cluster_sectors;
int l2_bits;
int l2_size;
- int l1_size;
+ unsigned int l1_size;
uint64_t cluster_offset_mask;
uint64_t l1_table_offset;
uint64_t *l1_table;
@@ -96,7 +97,8 @@ static int qcow_open(BlockDriverState *bs, QDict *options,
int flags,
Error **errp)
{
BDRVQcowState *s = bs->opaque;
- int len, i, shift, ret;
+ unsigned int len, i, shift;
+ int ret;
QCowHeader header;
ret = bdrv_pread(bs->file, 0, &header, sizeof(header));
@@ -126,11 +128,25 @@ static int qcow_open(BlockDriverState *bs, QDict
*options, int flags,
goto fail;
}
- if (header.size <= 1 || header.cluster_bits < 9) {
- error_setg(errp, "invalid value in qcow header");
+ if (header.size <= 1) {
+ error_setg(errp, "Image size is too small (must be at least 2 bytes)");
+ ret = -EINVAL;
+ goto fail;
+ }
+ if (header.cluster_bits < 9 || header.cluster_bits > 16) {
+ error_setg(errp, "Cluster size must be between 512 and 64k");
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ /* l2_bits specifies number of entries; storing a uint64_t in each entry,
+ * so bytes = num_entries << 3. */
+ if (header.l2_bits < 9 - 3 || header.l2_bits > 16 - 3) {
+ error_setg(errp, "L2 table size must be between 512 and 64k");
ret = -EINVAL;
goto fail;
}
+
if (header.crypt_method > QCOW_CRYPT_AES) {
error_setg(errp, "invalid encryption method in qcow header");
ret = -EINVAL;
@@ -150,7 +166,19 @@ static int qcow_open(BlockDriverState *bs, QDict *options,
int flags,
/* read the level 1 table */
shift = s->cluster_bits + s->l2_bits;
- s->l1_size = (header.size + (1LL << shift) - 1) >> shift;
+ if (header.size > UINT64_MAX - (1LL << shift)) {
+ error_setg(errp, "Image too large");
+ ret = -EINVAL;
+ goto fail;
+ } else {
+ uint64_t l1_size = (header.size + (1LL << shift) - 1) >> shift;
+ if (l1_size > INT_MAX / sizeof(uint64_t)) {
+ error_setg(errp, "Image too large");
+ ret = -EINVAL;
+ goto fail;
+ }
+ s->l1_size = l1_size;
+ }
s->l1_table_offset = header.l1_table_offset;
s->l1_table = g_malloc(s->l1_size * sizeof(uint64_t));
@@ -174,7 +202,9 @@ static int qcow_open(BlockDriverState *bs, QDict *options,
int flags,
if (header.backing_file_offset != 0) {
len = header.backing_file_size;
if (len > 1023) {
- len = 1023;
+ error_setg(errp, "Backing file name too long");
+ ret = -EINVAL;
+ goto fail;
}
ret = bdrv_pread(bs->file, header.backing_file_offset,
bs->backing_file, len);
diff --git a/block/qcow2.c b/block/qcow2.c
index e903d97..57c353d 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -1306,6 +1306,7 @@ static void qcow2_invalidate_cache(BlockDriverState *bs,
Error **errp)
options = qdict_clone_shallow(bs->options);
ret = qcow2_open(bs, options, flags, &local_err);
+ QDECREF(options);
if (local_err) {
error_setg(errp, "Could not reopen qcow2 layer: %s",
error_get_pretty(local_err));
@@ -1316,8 +1317,6 @@ static void qcow2_invalidate_cache(BlockDriverState *bs,
Error **errp)
return;
}
- QDECREF(options);
-
if (crypt_method) {
s->crypt_method = crypt_method;
memcpy(&s->aes_encrypt_key, &aes_encrypt_key, sizeof(aes_encrypt_key));
diff --git a/block/sheepdog.c b/block/sheepdog.c
index 0eb33ee..7dcebce 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -2149,6 +2149,7 @@ static int sd_snapshot_create(BlockDriverState *bs,
QEMUSnapshotInfo *sn_info)
strncpy(s->inode.tag, sn_info->name, sizeof(s->inode.tag));
/* we don't need to update entire object */
datalen = SD_INODE_SIZE - sizeof(s->inode.data_vdi_id);
+ inode = g_malloc(datalen);
/* refresh inode. */
fd = connect_to_sdog(s);
@@ -2171,8 +2172,6 @@ static int sd_snapshot_create(BlockDriverState *bs,
QEMUSnapshotInfo *sn_info)
goto cleanup;
}
- inode = (SheepdogInode *)g_malloc(datalen);
-
ret = read_object(fd, (char *)inode, vid_to_vdi_oid(new_vid),
s->inode.nr_copies, datalen, 0, s->cache_flags);
@@ -2186,6 +2185,7 @@ static int sd_snapshot_create(BlockDriverState *bs,
QEMUSnapshotInfo *sn_info)
s->inode.name, s->inode.snap_id, s->inode.vdi_id);
cleanup:
+ g_free(inode);
closesocket(fd);
return ret;
}
diff --git a/block/vvfat.c b/block/vvfat.c
index 1978c9e..91c63f7 100644
--- a/block/vvfat.c
+++ b/block/vvfat.c
@@ -787,7 +787,9 @@ static int read_directory(BDRVVVFATState* s, int
mapping_index)
s->current_mapping->path=buffer;
s->current_mapping->read_only =
(st.st_mode & (S_IWUSR | S_IWGRP | S_IWOTH)) == 0;
- }
+ } else {
+ g_free(buffer);
+ }
}
closedir(dir);
@@ -1864,7 +1866,7 @@ static int check_directory_consistency(BDRVVVFATState *s,
if (s->used_clusters[cluster_num] & USED_ANY) {
fprintf(stderr, "cluster %d used more than once\n",
(int)cluster_num);
- return 0;
+ goto fail;
}
s->used_clusters[cluster_num] = USED_DIRECTORY;
diff --git a/blockdev-nbd.c b/blockdev-nbd.c
index 922cf56..b3a2474 100644
--- a/blockdev-nbd.c
+++ b/blockdev-nbd.c
@@ -27,8 +27,9 @@ static void nbd_accept(void *opaque)
socklen_t addr_len = sizeof(addr);
int fd = accept(server_fd, (struct sockaddr *)&addr, &addr_len);
- if (fd >= 0) {
- nbd_client_new(NULL, fd, nbd_client_put);
+ if (fd >= 0 && !nbd_client_new(NULL, fd, nbd_client_put)) {
+ shutdown(fd, 2);
+ close(fd);
}
}
@@ -91,6 +92,10 @@ void qmp_nbd_server_add(const char *device, bool
has_writable, bool writable,
error_set(errp, QERR_DEVICE_NOT_FOUND, device);
return;
}
+ if (!bdrv_is_inserted(bs)) {
+ error_set(errp, QERR_DEVICE_HAS_NO_MEDIUM, device);
+ return;
+ }
if (!has_writable) {
writable = false;
diff --git a/blockdev.c b/blockdev.c
index 5dd01ea..4d98224 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -332,7 +332,7 @@ static DriveInfo *blockdev_init(const char *file, QDict
*bs_opts,
opts = qemu_opts_create(&qemu_common_drive_opts, id, 1, &error);
if (error) {
error_propagate(errp, error);
- return NULL;
+ goto err_no_opts;
}
qemu_opts_absorb_qdict(opts, bs_opts, &error);
@@ -527,8 +527,9 @@ err:
QTAILQ_REMOVE(&drives, dinfo, next);
g_free(dinfo);
early_err:
- QDECREF(bs_opts);
qemu_opts_del(opts);
+err_no_opts:
+ QDECREF(bs_opts);
return NULL;
}
@@ -902,6 +903,7 @@ DriveInfo *drive_init(QemuOpts *all_opts,
BlockInterfaceType block_default_type)
/* Actual block device init: Functionality shared with blockdev-add */
dinfo = blockdev_init(filename, bs_opts, &local_err);
+ bs_opts = NULL;
if (dinfo == NULL) {
if (local_err) {
qerror_report_err(local_err);
@@ -939,6 +941,7 @@ DriveInfo *drive_init(QemuOpts *all_opts,
BlockInterfaceType block_default_type)
fail:
qemu_opts_del(legacy_opts);
+ QDECREF(bs_opts);
return dinfo;
}
@@ -1864,7 +1867,8 @@ void qmp_block_stream(const char *device, bool has_base,
}
void qmp_block_commit(const char *device,
- bool has_base, const char *base, const char *top,
+ bool has_base, const char *base,
+ bool has_top, const char *top,
bool has_speed, int64_t speed,
Error **errp)
{
@@ -1883,6 +1887,11 @@ void qmp_block_commit(const char *device,
/* drain all i/o before commits */
bdrv_drain_all();
+ /* Important Note:
+ * libvirt relies on the DeviceNotFound error class in order to probe for
+ * live commit feature versions; for this to work, we must make sure to
+ * perform the device lookup before any generic errors that may occur in a
+ * scenario in which all optional arguments are omitted. */
bs = bdrv_find(device);
if (!bs) {
error_set(errp, QERR_DEVICE_NOT_FOUND, device);
@@ -1892,7 +1901,7 @@ void qmp_block_commit(const char *device,
/* default top_bs is the active layer */
top_bs = bs;
- if (top) {
+ if (has_top && top) {
if (strcmp(bs->filename, top) != 0) {
top_bs = bdrv_find_backing_image(bs, top);
}
@@ -1914,6 +1923,12 @@ void qmp_block_commit(const char *device,
return;
}
+ /* Do not allow attempts to commit an image into itself */
+ if (top_bs == base_bs) {
+ error_setg(errp, "cannot commit an image into itself");
+ return;
+ }
+
if (top_bs == bs) {
commit_active_start(bs, base_bs, speed, on_error, block_job_cb,
bs, &local_err);
diff --git a/blockjob.c b/blockjob.c
index b3ce14c..bf10f82 100644
--- a/blockjob.c
+++ b/blockjob.c
@@ -206,6 +206,20 @@ void block_job_sleep_ns(BlockJob *job, QEMUClockType type,
int64_t ns)
job->busy = true;
}
+void block_job_yield(BlockJob *job)
+{
+ assert(job->busy);
+
+ /* Check cancellation *before* setting busy = false, too! */
+ if (block_job_is_cancelled(job)) {
+ return;
+ }
+
+ job->busy = false;
+ qemu_coroutine_yield();
+ job->busy = true;
+}
+
BlockJobInfo *block_job_query(BlockJob *job)
{
BlockJobInfo *info = g_new0(BlockJobInfo, 1);
diff --git a/configure b/configure
index 69b9f56..ffce604 100755
--- a/configure
+++ b/configure
@@ -2624,7 +2624,7 @@ done
if test "$modules" = yes; then
shacmd_probe="sha1sum sha1 shasum"
for c in $shacmd_probe; do
- if which $c &>/dev/null; then
+ if which $c >/dev/null 2>&1; then
shacmd="$c"
break
fi
diff --git a/coroutine-win32.c b/coroutine-win32.c
index edc1f72..17ace37 100644
--- a/coroutine-win32.c
+++ b/coroutine-win32.c
@@ -36,8 +36,17 @@ typedef struct
static __thread CoroutineWin32 leader;
static __thread Coroutine *current;
-CoroutineAction qemu_coroutine_switch(Coroutine *from_, Coroutine *to_,
- CoroutineAction action)
+/* This function is marked noinline to prevent GCC from inlining it
+ * into coroutine_trampoline(). If we allow it to do that then it
+ * hoists the code to get the address of the TLS variable "current"
+ * out of the while() loop. This is an invalid transformation because
+ * the SwitchToFiber() call may be called when running thread A but
+ * return in thread B, and so we might be in a different thread
+ * context each time round the loop.
+ */
+CoroutineAction __attribute__((noinline))
+qemu_coroutine_switch(Coroutine *from_, Coroutine *to_,
+ CoroutineAction action)
{
CoroutineWin32 *from = DO_UPCAST(CoroutineWin32, base, from_);
CoroutineWin32 *to = DO_UPCAST(CoroutineWin32, base, to_);
diff --git a/cputlb.c b/cputlb.c
index 7bd3573..214c945 100644
--- a/cputlb.c
+++ b/cputlb.c
@@ -331,8 +331,10 @@ tb_page_addr_t get_page_addr_code(CPUArchState *env1,
target_ulong addr)
}
#define MMUSUFFIX _cmmu
-#undef GETPC
-#define GETPC() ((uintptr_t)0)
+#undef GETPC_ADJ
+#define GETPC_ADJ 0
+#undef GETRA
+#define GETRA() ((uintptr_t)0)
#define SOFTMMU_CODE_ACCESS
#define SHIFT 0
diff --git a/disas/Makefile.objs b/disas/Makefile.objs
index 41c2374..a70c592 100644
--- a/disas/Makefile.objs
+++ b/disas/Makefile.objs
@@ -4,7 +4,7 @@ common-obj-$(CONFIG_ARM_DIS) += arm.o
common-obj-$(CONFIG_ARM_A64_DIS) += arm-a64.o
common-obj-$(CONFIG_ARM_A64_DIS) += libvixl/
libvixldir = $(SRC_PATH)/disas/libvixl
-$(obj)/arm-a64.o: QEMU_CFLAGS += -I$(libvixldir)
+$(obj)/arm-a64.o: QEMU_CFLAGS := -I$(libvixldir) $(QEMU_CFLAGS)
common-obj-$(CONFIG_CRIS_DIS) += cris.o
common-obj-$(CONFIG_HPPA_DIS) += hppa.o
common-obj-$(CONFIG_I386_DIS) += i386.o
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
index 3d1f4a2..1241761 100644
--- a/hw/arm/boot.c
+++ b/hw/arm/boot.c
@@ -417,8 +417,12 @@ static void do_cpu_reset(void *opaque)
if (info) {
if (!info->is_linux) {
/* Jump to the entry point. */
- env->regs[15] = info->entry & 0xfffffffe;
- env->thumb = info->entry & 1;
+ if (env->aarch64) {
+ env->pc = info->entry;
+ } else {
+ env->regs[15] = info->entry & 0xfffffffe;
+ env->thumb = info->entry & 1;
+ }
} else {
if (CPU(cpu) == first_cpu) {
if (env->aarch64) {
diff --git a/hw/arm/omap1.c b/hw/arm/omap1.c
index b433748..9f5d159 100644
--- a/hw/arm/omap1.c
+++ b/hw/arm/omap1.c
@@ -172,7 +172,7 @@ static void omap_timer_clk_update(void *opaque, int line,
int on)
static void omap_timer_clk_setup(struct omap_mpu_timer_s *timer)
{
omap_clk_adduser(timer->clk,
- qemu_allocate_irqs(omap_timer_clk_update, timer, 1)[0]);
+ qemu_allocate_irq(omap_timer_clk_update, timer, 0));
timer->rate = omap_clk_getrate(timer->clk);
}
@@ -2098,7 +2098,7 @@ static struct omap_mpuio_s *omap_mpuio_init(MemoryRegion
*memory,
"omap-mpuio", 0x800);
memory_region_add_subregion(memory, base, &s->iomem);
- omap_clk_adduser(clk, qemu_allocate_irqs(omap_mpuio_onoff, s, 1)[0]);
+ omap_clk_adduser(clk, qemu_allocate_irq(omap_mpuio_onoff, s, 0));
return s;
}
@@ -2401,7 +2401,7 @@ static struct omap_pwl_s *omap_pwl_init(MemoryRegion
*system_memory,
"omap-pwl", 0x800);
memory_region_add_subregion(system_memory, base, &s->iomem);
- omap_clk_adduser(clk, qemu_allocate_irqs(omap_pwl_clk_update, s, 1)[0]);
+ omap_clk_adduser(clk, qemu_allocate_irq(omap_pwl_clk_update, s, 0));
return s;
}
@@ -3485,8 +3485,8 @@ static void omap_mcbsp_i2s_start(void *opaque, int line,
int level)
void omap_mcbsp_i2s_attach(struct omap_mcbsp_s *s, I2SCodec *slave)
{
s->codec = slave;
- slave->rx_swallow = qemu_allocate_irqs(omap_mcbsp_i2s_swallow, s, 1)[0];
- slave->tx_start = qemu_allocate_irqs(omap_mcbsp_i2s_start, s, 1)[0];
+ slave->rx_swallow = qemu_allocate_irq(omap_mcbsp_i2s_swallow, s, 0);
+ slave->tx_start = qemu_allocate_irq(omap_mcbsp_i2s_start, s, 0);
}
/* LED Pulse Generators */
@@ -3634,7 +3634,7 @@ static struct omap_lpg_s *omap_lpg_init(MemoryRegion
*system_memory,
memory_region_init_io(&s->iomem, NULL, &omap_lpg_ops, s, "omap-lpg",
0x800);
memory_region_add_subregion(system_memory, base, &s->iomem);
- omap_clk_adduser(clk, qemu_allocate_irqs(omap_lpg_clk_update, s, 1)[0]);
+ omap_clk_adduser(clk, qemu_allocate_irq(omap_lpg_clk_update, s, 0));
return s;
}
@@ -3848,7 +3848,7 @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion
*system_memory,
s->sdram_size = sdram_size;
s->sram_size = OMAP15XX_SRAM_SIZE;
- s->wakeup = qemu_allocate_irqs(omap_mpu_wakeup, s, 1)[0];
+ s->wakeup = qemu_allocate_irq(omap_mpu_wakeup, s, 0);
/* Clocks */
omap_clk_init(s);
diff --git a/hw/arm/omap2.c b/hw/arm/omap2.c
index 36efde0..dc53a7a 100644
--- a/hw/arm/omap2.c
+++ b/hw/arm/omap2.c
@@ -2260,7 +2260,7 @@ struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion
*sysmem,
s->sdram_size = sdram_size;
s->sram_size = OMAP242X_SRAM_SIZE;
- s->wakeup = qemu_allocate_irqs(omap_mpu_wakeup, s, 1)[0];
+ s->wakeup = qemu_allocate_irq(omap_mpu_wakeup, s, 0);
/* Clocks */
omap_clk_init(s);
diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c
index 0429148..c652147 100644
--- a/hw/arm/pxa2xx.c
+++ b/hw/arm/pxa2xx.c
@@ -732,7 +732,7 @@ static void pxa2xx_ssp_save(QEMUFile *f, void *opaque)
static int pxa2xx_ssp_load(QEMUFile *f, void *opaque, int version_id)
{
PXA2xxSSPState *s = (PXA2xxSSPState *) opaque;
- int i;
+ int i, v;
s->enable = qemu_get_be32(f);
@@ -746,7 +746,11 @@ static int pxa2xx_ssp_load(QEMUFile *f, void *opaque, int
version_id)
qemu_get_8s(f, &s->ssrsa);
qemu_get_8s(f, &s->ssacd);
- s->rx_level = qemu_get_byte(f);
+ v = qemu_get_byte(f);
+ if (v < 0 || v > ARRAY_SIZE(s->rx_fifo)) {
+ return -EINVAL;
+ }
+ s->rx_level = v;
s->rx_start = 0;
for (i = 0; i < s->rx_level; i ++)
s->rx_fifo[i] = qemu_get_byte(f);
@@ -2055,7 +2059,7 @@ PXA2xxState *pxa270_init(MemoryRegion *address_space,
fprintf(stderr, "Unable to find CPU definition\n");
exit(1);
}
- s->reset = qemu_allocate_irqs(pxa2xx_reset, s, 1)[0];
+ s->reset = qemu_allocate_irq(pxa2xx_reset, s, 0);
/* SDRAM & Internal Memory Storage */
memory_region_init_ram(&s->sdram, NULL, "pxa270.sdram", sdram_size);
@@ -2186,7 +2190,7 @@ PXA2xxState *pxa255_init(MemoryRegion *address_space,
unsigned int sdram_size)
fprintf(stderr, "Unable to find CPU definition\n");
exit(1);
}
- s->reset = qemu_allocate_irqs(pxa2xx_reset, s, 1)[0];
+ s->reset = qemu_allocate_irq(pxa2xx_reset, s, 0);
/* SDRAM & Internal Memory Storage */
memory_region_init_ram(&s->sdram, NULL, "pxa255.sdram", sdram_size);
diff --git a/hw/arm/spitz.c b/hw/arm/spitz.c
index 392ca84..713d021 100644
--- a/hw/arm/spitz.c
+++ b/hw/arm/spitz.c
@@ -744,7 +744,7 @@ static void spitz_i2c_setup(PXA2xxState *cpu)
spitz_wm8750_addr(wm, 0, 0);
qdev_connect_gpio_out(cpu->gpio, SPITZ_GPIO_WM,
- qemu_allocate_irqs(spitz_wm8750_addr, wm, 1)[0]);
+ qemu_allocate_irq(spitz_wm8750_addr, wm, 0));
/* .. and to the sound interface. */
cpu->i2s->opaque = wm;
cpu->i2s->codec_out = wm8750_dac_dat;
@@ -850,7 +850,7 @@ static void spitz_gpio_setup(PXA2xxState *cpu, int slots)
* wouldn't guarantee that a guest ever exits the loop.
*/
spitz_hsync = 0;
- lcd_hsync = qemu_allocate_irqs(spitz_lcd_hsync_handler, cpu, 1)[0];
+ lcd_hsync = qemu_allocate_irq(spitz_lcd_hsync_handler, cpu, 0);
pxa2xx_gpio_read_notifier(cpu->gpio, lcd_hsync);
pxa2xx_lcd_vsync_notifier(cpu->lcd, lcd_hsync);
diff --git a/hw/arm/z2.c b/hw/arm/z2.c
index 67c1be8..ef5424d 100644
--- a/hw/arm/z2.c
+++ b/hw/arm/z2.c
@@ -365,7 +365,7 @@ static void z2_init(QEMUMachineInitArgs *args)
wm8750_data_req_set(wm, mpu->i2s->data_req, mpu->i2s);
qdev_connect_gpio_out(mpu->gpio, Z2_GPIO_LCD_CS,
- qemu_allocate_irqs(z2_lcd_cs, z2_lcd, 1)[0]);
+ qemu_allocate_irq(z2_lcd_cs, z2_lcd, 0));
z2_binfo.kernel_filename = kernel_filename;
z2_binfo.kernel_cmdline = kernel_cmdline;
diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c
index 1f3d162..ce20e1a 100644
--- a/hw/char/cadence_uart.c
+++ b/hw/char/cadence_uart.c
@@ -175,8 +175,10 @@ static void uart_send_breaks(UartState *s)
{
int break_enabled = 1;
- qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_BREAK,
- &break_enabled);
+ if (s->chr) {
+ qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_BREAK,
+ &break_enabled);
+ }
}
static void uart_parameters_setup(UartState *s)
@@ -227,7 +229,9 @@ static void uart_parameters_setup(UartState *s)
packet_size += ssp.data_bits + ssp.stop_bits;
s->char_tx_time = (get_ticks_per_sec() / ssp.speed) * packet_size;
- qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
+ if (s->chr) {
+ qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
+ }
}
static int uart_can_receive(void *opaque)
@@ -295,6 +299,7 @@ static gboolean cadence_uart_xmit(GIOChannel *chan,
GIOCondition cond,
/* instant drain the fifo when there's no back-end */
if (!s->chr) {
s->tx_count = 0;
+ return FALSE;
}
if (!s->tx_count) {
@@ -375,7 +380,9 @@ static void uart_read_rx_fifo(UartState *s, uint32_t *c)
*c = s->rx_fifo[rx_rpos];
s->rx_count--;
- qemu_chr_accept_input(s->chr);
+ if (s->chr) {
+ qemu_chr_accept_input(s->chr);
+ }
} else {
*c = 0;
}
diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c
index 2b647b6..ee1ba16 100644
--- a/hw/char/virtio-serial-bus.c
+++ b/hw/char/virtio-serial-bus.c
@@ -670,6 +670,7 @@ static int virtio_serial_load(QEMUFile *f, void *opaque,
int version_id)
uint32_t max_nr_ports, nr_active_ports, ports_map;
unsigned int i;
int ret;
+ uint32_t tmp;
if (version_id > 3) {
return -EINVAL;
@@ -685,17 +686,12 @@ static int virtio_serial_load(QEMUFile *f, void *opaque,
int version_id)
return 0;
}
- /* The config space */
- qemu_get_be16s(f, &s->config.cols);
- qemu_get_be16s(f, &s->config.rows);
-
- qemu_get_be32s(f, &max_nr_ports);
- tswap32s(&max_nr_ports);
- if (max_nr_ports > tswap32(s->config.max_nr_ports)) {
- /* Source could have had more ports than us. Fail migration. */
- return -EINVAL;
- }
+ /* Unused */
+ qemu_get_be16s(f, (uint16_t *) &tmp);
+ qemu_get_be16s(f, (uint16_t *) &tmp);
+ qemu_get_be32s(f, &tmp);
+ max_nr_ports = tswap32(s->config.max_nr_ports);
for (i = 0; i < (max_nr_ports + 31) / 32; i++) {
qemu_get_be32s(f, &ports_map);
diff --git a/hw/core/irq.c b/hw/core/irq.c
index 03c8cb3..3d284c6 100644
--- a/hw/core/irq.c
+++ b/hw/core/irq.c
@@ -102,7 +102,7 @@ qemu_irq qemu_irq_invert(qemu_irq irq)
{
/* The default state for IRQs is low, so raise the output now. */
qemu_irq_raise(irq);
- return qemu_allocate_irqs(qemu_notirq, irq, 1)[0];
+ return qemu_allocate_irq(qemu_notirq, irq, 0);
}
static void qemu_splitirq(void *opaque, int line, int level)
@@ -117,7 +117,7 @@ qemu_irq qemu_irq_split(qemu_irq irq1, qemu_irq irq2)
qemu_irq *s = g_malloc0(2 * sizeof(qemu_irq));
s[0] = irq1;
s[1] = irq2;
- return qemu_allocate_irqs(qemu_splitirq, s, 1)[0];
+ return qemu_allocate_irq(qemu_splitirq, s, 0);
}
static void proxy_irq_handler(void *opaque, int n, int level)
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index 60f9df1..79db470 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -174,14 +174,14 @@ int qdev_init(DeviceState *dev)
return 0;
}
-static void device_realize(DeviceState *dev, Error **err)
+static void device_realize(DeviceState *dev, Error **errp)
{
DeviceClass *dc = DEVICE_GET_CLASS(dev);
if (dc->init) {
int rc = dc->init(dev);
if (rc < 0) {
- error_setg(err, "Device initialization failed.");
+ error_setg(errp, "Device initialization failed.");
return;
}
}
@@ -504,43 +504,46 @@ static void bus_unparent(Object *obj)
}
}
-static bool bus_get_realized(Object *obj, Error **err)
+static bool bus_get_realized(Object *obj, Error **errp)
{
BusState *bus = BUS(obj);
return bus->realized;
}
-static void bus_set_realized(Object *obj, bool value, Error **err)
+static void bus_set_realized(Object *obj, bool value, Error **errp)
{
BusState *bus = BUS(obj);
BusClass *bc = BUS_GET_CLASS(bus);
+ BusChild *kid;
Error *local_err = NULL;
if (value && !bus->realized) {
if (bc->realize) {
bc->realize(bus, &local_err);
+ }
+ /* TODO: recursive realization */
+ } else if (!value && bus->realized) {
+ QTAILQ_FOREACH(kid, &bus->children, sibling) {
+ DeviceState *dev = kid->child;
+ object_property_set_bool(OBJECT(dev), false, "realized",
+ &local_err);
if (local_err != NULL) {
- goto error;
+ break;
}
-
}
- } else if (!value && bus->realized) {
- if (bc->unrealize) {
+ if (bc->unrealize && local_err == NULL) {
bc->unrealize(bus, &local_err);
-
- if (local_err != NULL) {
- goto error;
- }
}
}
- bus->realized = value;
- return;
+ if (local_err != NULL) {
+ error_propagate(errp, local_err);
+ return;
+ }
-error:
- error_propagate(err, local_err);
+ bus->realized = value;
}
void qbus_create_inplace(void *bus, size_t size, const char *typename,
@@ -724,13 +727,13 @@ void qdev_property_add_static(DeviceState *dev, Property
*prop,
}
}
-static bool device_get_realized(Object *obj, Error **err)
+static bool device_get_realized(Object *obj, Error **errp)
{
DeviceState *dev = DEVICE(obj);
return dev->realized;
}
-static void device_set_realized(Object *obj, bool value, Error **err)
+static void device_set_realized(Object *obj, bool value, Error **errp)
{
DeviceState *dev = DEVICE(obj);
DeviceClass *dc = DEVICE_GET_CLASS(dev);
@@ -738,7 +741,7 @@ static void device_set_realized(Object *obj, bool value,
Error **err)
Error *local_err = NULL;
if (dev->hotplugged && !dc->hotpluggable) {
- error_set(err, QERR_DEVICE_NO_HOTPLUG, object_get_typename(obj));
+ error_set(errp, QERR_DEVICE_NO_HOTPLUG, object_get_typename(obj));
return;
}
@@ -797,14 +800,14 @@ static void device_set_realized(Object *obj, bool value,
Error **err)
}
if (local_err != NULL) {
- error_propagate(err, local_err);
+ error_propagate(errp, local_err);
return;
}
dev->realized = value;
}
-static bool device_get_hotpluggable(Object *obj, Error **err)
+static bool device_get_hotpluggable(Object *obj, Error **errp)
{
DeviceClass *dc = DEVICE_GET_CLASS(obj);
DeviceState *dev = DEVICE(obj);
diff --git a/hw/display/ssd0323.c b/hw/display/ssd0323.c
index 971152e..9727007 100644
--- a/hw/display/ssd0323.c
+++ b/hw/display/ssd0323.c
@@ -312,18 +312,42 @@ static int ssd0323_load(QEMUFile *f, void *opaque, int
version_id)
return -EINVAL;
s->cmd_len = qemu_get_be32(f);
+ if (s->cmd_len < 0 || s->cmd_len > ARRAY_SIZE(s->cmd_data)) {
+ return -EINVAL;
+ }
s->cmd = qemu_get_be32(f);
for (i = 0; i < 8; i++)
s->cmd_data[i] = qemu_get_be32(f);
s->row = qemu_get_be32(f);
+ if (s->row < 0 || s->row >= 80) {
+ return -EINVAL;
+ }
s->row_start = qemu_get_be32(f);
+ if (s->row_start < 0 || s->row_start >= 80) {
+ return -EINVAL;
+ }
s->row_end = qemu_get_be32(f);
+ if (s->row_end < 0 || s->row_end >= 80) {
+ return -EINVAL;
+ }
s->col = qemu_get_be32(f);
+ if (s->col < 0 || s->col >= 64) {
+ return -EINVAL;
+ }
s->col_start = qemu_get_be32(f);
+ if (s->col_start < 0 || s->col_start >= 64) {
+ return -EINVAL;
+ }
s->col_end = qemu_get_be32(f);
+ if (s->col_end < 0 || s->col_end >= 64) {
+ return -EINVAL;
+ }
s->redraw = qemu_get_be32(f);
s->remap = qemu_get_be32(f);
s->mode = qemu_get_be32(f);
+ if (s->mode != SSD0323_CMD && s->mode != SSD0323_DATA) {
+ return -EINVAL;
+ }
qemu_get_buffer(f, s->framebuffer, sizeof(s->framebuffer));
ss->cs = qemu_get_be32(f);
diff --git a/hw/dma/omap_dma.c b/hw/dma/omap_dma.c
index 0e8cccd..bb02279 100644
--- a/hw/dma/omap_dma.c
+++ b/hw/dma/omap_dma.c
@@ -1660,7 +1660,7 @@ struct soc_dma_s *omap_dma_init(hwaddr base, qemu_irq
*irqs,
}
omap_dma_setcaps(s);
- omap_clk_adduser(s->clk, qemu_allocate_irqs(omap_dma_clk_update, s, 1)[0]);
+ omap_clk_adduser(s->clk, qemu_allocate_irq(omap_dma_clk_update, s, 0));
omap_dma_reset(s->dma);
omap_dma_clk_update(s, 0, 1);
@@ -2082,7 +2082,7 @@ struct soc_dma_s *omap_dma4_init(hwaddr base, qemu_irq
*irqs,
s->intr_update = omap_dma_interrupts_4_update;
omap_dma_setcaps(s);
- omap_clk_adduser(s->clk, qemu_allocate_irqs(omap_dma_clk_update, s, 1)[0]);
+ omap_clk_adduser(s->clk, qemu_allocate_irq(omap_dma_clk_update, s, 0));
omap_dma_reset(s->dma);
omap_dma_clk_update(s, 0, !!s->dma->freq);
diff --git a/hw/gpio/zaurus.c b/hw/gpio/zaurus.c
index dc79a8b..8e2ce04 100644
--- a/hw/gpio/zaurus.c
+++ b/hw/gpio/zaurus.c
@@ -203,6 +203,15 @@ static bool is_version_0 (void *opaque, int version_id)
return version_id == 0;
}
+static bool vmstate_scoop_validate(void *opaque, int version_id)
+{
+ ScoopInfo *s = opaque;
+
+ return !(s->prev_level & 0xffff0000) &&
+ !(s->gpio_level & 0xffff0000) &&
+ !(s->gpio_dir & 0xffff0000);
+}
+
static const VMStateDescription vmstate_scoop_regs = {
.name = "scoop",
.version_id = 1,
@@ -215,6 +224,7 @@ static const VMStateDescription vmstate_scoop_regs = {
VMSTATE_UINT32(gpio_level, ScoopInfo),
VMSTATE_UINT32(gpio_dir, ScoopInfo),
VMSTATE_UINT32(prev_level, ScoopInfo),
+ VMSTATE_VALIDATE("irq levels are 16 bit", vmstate_scoop_validate),
VMSTATE_UINT16(mcr, ScoopInfo),
VMSTATE_UINT16(cdr, ScoopInfo),
VMSTATE_UINT16(ccr, ScoopInfo),
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index c98df88..985a188 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -1410,15 +1410,16 @@ void acpi_build(PcGuestInfo *guest_info,
AcpiBuildTables *tables)
/* ACPI tables pointed to by RSDT */
acpi_add_table(table_offsets, tables->table_data);
build_fadt(tables->table_data, tables->linker, &pm, facs, dsdt);
- acpi_add_table(table_offsets, tables->table_data);
+ acpi_add_table(table_offsets, tables->table_data);
build_ssdt(tables->table_data, tables->linker, &cpu, &pm, &misc, &pci,
guest_info);
- acpi_add_table(table_offsets, tables->table_data);
- build_madt(tables->table_data, tables->linker, &cpu, guest_info);
acpi_add_table(table_offsets, tables->table_data);
+ build_madt(tables->table_data, tables->linker, &cpu, guest_info);
+
if (misc.has_hpet) {
+ acpi_add_table(table_offsets, tables->table_data);
build_hpet(tables->table_data, tables->linker);
}
if (guest_info->numa_nodes) {
diff --git a/hw/i386/kvm/pci-assign.c b/hw/i386/kvm/pci-assign.c
index a825871..76aa86e 100644
--- a/hw/i386/kvm/pci-assign.c
+++ b/hw/i386/kvm/pci-assign.c
@@ -1258,6 +1258,7 @@ static int assigned_device_pci_cap_init(PCIDevice
*pci_dev)
if (pos != 0 && kvm_device_msix_supported(kvm_state)) {
int bar_nr;
uint32_t msix_table_entry;
+ uint16_t msix_max;
if (!check_irqchip_in_kernel()) {
return -ENOTSUP;
@@ -1269,9 +1270,10 @@ static int assigned_device_pci_cap_init(PCIDevice
*pci_dev)
}
pci_dev->msix_cap = pos;
- pci_set_word(pci_dev->config + pos + PCI_MSIX_FLAGS,
- pci_get_word(pci_dev->config + pos + PCI_MSIX_FLAGS) &
- PCI_MSIX_FLAGS_QSIZE);
+ msix_max = (pci_get_word(pci_dev->config + pos + PCI_MSIX_FLAGS) &
+ PCI_MSIX_FLAGS_QSIZE) + 1;
+ msix_max = MIN(msix_max, KVM_MAX_MSIX_PER_DEV);
+ pci_set_word(pci_dev->config + pos + PCI_MSIX_FLAGS, msix_max - 1);
/* Only enable and function mask bits are writable */
pci_set_word(pci_dev->wmask + pos + PCI_MSIX_FLAGS,
@@ -1281,9 +1283,7 @@ static int assigned_device_pci_cap_init(PCIDevice
*pci_dev)
bar_nr = msix_table_entry & PCI_MSIX_FLAGS_BIRMASK;
msix_table_entry &= ~PCI_MSIX_FLAGS_BIRMASK;
dev->msix_table_addr = pci_region[bar_nr].base_addr + msix_table_entry;
- dev->msix_max = pci_get_word(pci_dev->config + pos + PCI_MSIX_FLAGS);
- dev->msix_max &= PCI_MSIX_FLAGS_QSIZE;
- dev->msix_max += 1;
+ dev->msix_max = msix_max;
}
/* Minimal PM support, nothing writable, device appears to NAK changes */
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 30d3bfa..c9dcd98 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -655,7 +655,7 @@ static FWCfgState *bochs_bios_init(void)
acpi_tables, acpi_tables_len);
fw_cfg_add_i32(fw_cfg, FW_CFG_IRQ0_OVERRIDE, kvm_allows_irq0_override());
- smbios_table = smbios_get_table(&smbios_len);
+ smbios_table = smbios_get_table_legacy(&smbios_len);
if (smbios_table)
fw_cfg_add_bytes(fw_cfg, FW_CFG_SMBIOS_ENTRIES,
smbios_table, smbios_len);
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index 1b3cd18..ce708c7 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -63,7 +63,7 @@ static const int ide_irq[MAX_IDE_BUS] = { 14, 15 };
static bool has_pci_info;
static bool has_acpi_build = true;
-static bool smbios_type1_defaults = true;
+static bool smbios_defaults = true;
/* Make sure that guest addresses aligned at 1Gbyte boundaries get mapped to
* host addresses aligned at 1Gbyte boundaries. This way we can use 1GByte
* pages in the host.
@@ -166,10 +166,10 @@ static void pc_init1(QEMUMachineInitArgs *args,
guest_info->has_pci_info = has_pci_info;
guest_info->isapc_ram_fw = !pci_enabled;
- if (smbios_type1_defaults) {
+ if (smbios_defaults) {
/* These values are guest ABI, do not change */
- smbios_set_type1_defaults("QEMU", "Standard PC (i440FX + PIIX, 1996)",
- args->machine->name);
+ smbios_set_defaults("QEMU", "Standard PC (i440FX + PIIX, 1996)",
+ args->machine->name);
}
/* allocate ram and load rom/bios */
@@ -294,7 +294,7 @@ static void pc_init_pci(QEMUMachineInitArgs *args)
static void pc_compat_1_7(QEMUMachineInitArgs *args)
{
- smbios_type1_defaults = false;
+ smbios_defaults = false;
gigabyte_align = false;
option_rom_has_mr = true;
x86_cpu_compat_disable_kvm_features(FEAT_1_ECX, CPUID_EXT_X2APIC);
@@ -375,7 +375,10 @@ static void pc_init_pci_no_kvmclock(QEMUMachineInitArgs
*args)
{
has_pci_info = false;
has_acpi_build = false;
- smbios_type1_defaults = false;
+ smbios_defaults = false;
+ gigabyte_align = false;
+ option_rom_has_mr = true;
+ rom_file_has_mr = false;
x86_cpu_compat_disable_kvm_features(FEAT_KVM, KVM_FEATURE_PV_EOI);
enable_compat_apic_id_mode();
pc_init1(args, 1, 0);
@@ -385,7 +388,10 @@ static void pc_init_isa(QEMUMachineInitArgs *args)
{
has_pci_info = false;
has_acpi_build = false;
- smbios_type1_defaults = false;
+ smbios_defaults = false;
+ gigabyte_align = false;
+ option_rom_has_mr = true;
+ rom_file_has_mr = false;
if (!args->cpu_model) {
args->cpu_model = "486";
}
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index c529e02..c6187a4 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -53,7 +53,7 @@ extern uint64_t max_ram_below_4g;
static bool has_pci_info;
static bool has_acpi_build = true;
-static bool smbios_type1_defaults = true;
+static bool smbios_defaults = true;
/* Make sure that guest addresses aligned at 1Gbyte boundaries get mapped to
* host addresses aligned at 1Gbyte boundaries. This way we can use 1GByte
* pages in the host.
@@ -153,10 +153,10 @@ static void pc_q35_init(QEMUMachineInitArgs *args)
guest_info->isapc_ram_fw = false;
guest_info->has_acpi_build = has_acpi_build;
- if (smbios_type1_defaults) {
+ if (smbios_defaults) {
/* These values are guest ABI, do not change */
- smbios_set_type1_defaults("QEMU", "Standard PC (Q35 + ICH9, 2009)",
- args->machine->name);
+ smbios_set_defaults("QEMU", "Standard PC (Q35 + ICH9, 2009)",
+ args->machine->name);
}
/* allocate ram and load rom/bios */
@@ -265,7 +265,7 @@ static void pc_q35_init(QEMUMachineInitArgs *args)
static void pc_compat_1_7(QEMUMachineInitArgs *args)
{
- smbios_type1_defaults = false;
+ smbios_defaults = false;
gigabyte_align = false;
option_rom_has_mr = true;
x86_cpu_compat_disable_kvm_features(FEAT_1_ECX, CPUID_EXT_X2APIC);
@@ -374,7 +374,7 @@ static QEMUMachine pc_q35_machine_v1_4 = {
.name = "pc-q35-1.4",
.init = pc_q35_init_1_4,
.compat_props = (GlobalProperty[]) {
- PC_COMPAT_1_4,
+ PC_Q35_COMPAT_1_4,
{ /* end of list */ }
},
};
diff --git a/hw/i386/smbios.c b/hw/i386/smbios.c
index e8f41ad..e734d4c 100644
--- a/hw/i386/smbios.c
+++ b/hw/i386/smbios.c
@@ -21,9 +21,8 @@
#include "hw/i386/smbios.h"
#include "hw/loader.h"
-/*
- * Structures shared with the BIOS
- */
+
+/* legacy structures and constants for <= 2.0 machines */
struct smbios_header {
uint16_t length;
uint8_t type;
@@ -46,6 +45,9 @@ struct smbios_table {
static uint8_t *smbios_entries;
static size_t smbios_entries_len;
+/* end: legacy structures & constants for <= 2.0 machines */
+
+
static int smbios_type4_count = 0;
static bool smbios_immutable;
@@ -187,6 +189,8 @@ static void smbios_check_collision(int type, int entry)
}
}
+
+/* legacy setup functions for <= 2.0 machines */
static void smbios_add_field(int type, int offset, const void *data, size_t
len)
{
struct smbios_field *field;
@@ -256,8 +260,8 @@ static void smbios_build_type_1_fields(void)
}
}
-void smbios_set_type1_defaults(const char *manufacturer,
- const char *product, const char *version)
+void smbios_set_defaults(const char *manufacturer, const char *product,
+ const char *version)
{
if (!type1.manufacturer) {
type1.manufacturer = manufacturer;
@@ -270,7 +274,7 @@ void smbios_set_type1_defaults(const char *manufacturer,
}
}
-uint8_t *smbios_get_table(size_t *length)
+uint8_t *smbios_get_table_legacy(size_t *length)
{
if (!smbios_immutable) {
smbios_build_type_0_fields();
@@ -281,6 +285,8 @@ uint8_t *smbios_get_table(size_t *length)
*length = smbios_entries_len;
return smbios_entries;
}
+/* end: legacy setup functions for <= 2.0 machines */
+
static void save_opt(const char **dest, QemuOpts *opts, const char *name)
{
diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
index bfe633f..457a7a1 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -1293,7 +1293,7 @@ const VMStateDescription vmstate_ahci = {
VMSTATE_UINT32(control_regs.impl, AHCIState),
VMSTATE_UINT32(control_regs.version, AHCIState),
VMSTATE_UINT32(idp_index, AHCIState),
- VMSTATE_INT32(ports, AHCIState),
+ VMSTATE_INT32_EQUAL(ports, AHCIState),
VMSTATE_END_OF_LIST()
},
};
diff --git a/hw/ide/microdrive.c b/hw/ide/microdrive.c
index 21d6495..c73c5a7 100644
--- a/hw/ide/microdrive.c
+++ b/hw/ide/microdrive.c
@@ -594,7 +594,7 @@ static void microdrive_realize(DeviceState *dev, Error
**errp)
{
MicroDriveState *md = MICRODRIVE(dev);
- ide_init2(&md->bus, qemu_allocate_irqs(md_set_irq, md, 1)[0]);
+ ide_init2(&md->bus, qemu_allocate_irq(md_set_irq, md, 0));
}
static void microdrive_init(Object *obj)
diff --git a/hw/input/tsc210x.c b/hw/input/tsc210x.c
index 485c9e5..aa5b688 100644
--- a/hw/input/tsc210x.c
+++ b/hw/input/tsc210x.c
@@ -1070,9 +1070,21 @@ static int tsc210x_load(QEMUFile *f, void *opaque, int
version_id)
s->enabled = qemu_get_byte(f);
s->host_mode = qemu_get_byte(f);
s->function = qemu_get_byte(f);
+ if (s->function < 0 || s->function >= ARRAY_SIZE(mode_regs)) {
+ return -EINVAL;
+ }
s->nextfunction = qemu_get_byte(f);
+ if (s->nextfunction < 0 || s->nextfunction >= ARRAY_SIZE(mode_regs)) {
+ return -EINVAL;
+ }
s->precision = qemu_get_byte(f);
+ if (s->precision < 0 || s->precision >= ARRAY_SIZE(resolution)) {
+ return -EINVAL;
+ }
s->nextprecision = qemu_get_byte(f);
+ if (s->nextprecision < 0 || s->nextprecision >= ARRAY_SIZE(resolution)) {
+ return -EINVAL;
+ }
s->filter = qemu_get_byte(f);
s->pin_func = qemu_get_byte(f);
s->ref = qemu_get_byte(f);
diff --git a/hw/intc/i8259.c b/hw/intc/i8259.c
index c6f248b..ec01393 100644
--- a/hw/intc/i8259.c
+++ b/hw/intc/i8259.c
@@ -412,7 +412,7 @@ static const MemoryRegionOps pic_elcr_ioport_ops = {
},
};
-static void pic_realize(DeviceState *dev, Error **err)
+static void pic_realize(DeviceState *dev, Error **errp)
{
PICCommonState *s = PIC_COMMON(dev);
PICClass *pc = PIC_GET_CLASS(dev);
@@ -425,7 +425,7 @@ static void pic_realize(DeviceState *dev, Error **err)
qdev_init_gpio_out(dev, s->int_out, ARRAY_SIZE(s->int_out));
qdev_init_gpio_in(dev, pic_set_irq, 8);
- pc->parent_realize(dev, err);
+ pc->parent_realize(dev, errp);
}
void pic_info(Monitor *mon, const QDict *qdict)
diff --git a/hw/intc/openpic.c b/hw/intc/openpic.c
index be76fbd..17136c9 100644
--- a/hw/intc/openpic.c
+++ b/hw/intc/openpic.c
@@ -41,6 +41,7 @@
#include "hw/sysbus.h"
#include "hw/pci/msi.h"
#include "qemu/bitops.h"
+#include "qapi/qmp/qerror.h"
//#define DEBUG_OPENPIC
@@ -1416,7 +1417,7 @@ static void openpic_load_IRQ_queue(QEMUFile* f, IRQQueue
*q)
static int openpic_load(QEMUFile* f, void *opaque, int version_id)
{
OpenPICState *opp = (OpenPICState *)opaque;
- unsigned int i;
+ unsigned int i, nb_cpus;
if (version_id != 1) {
return -EINVAL;
@@ -1428,7 +1429,11 @@ static int openpic_load(QEMUFile* f, void *opaque, int
version_id)
qemu_get_be32s(f, &opp->spve);
qemu_get_be32s(f, &opp->tfrr);
- qemu_get_be32s(f, &opp->nb_cpus);
+ qemu_get_be32s(f, &nb_cpus);
+ if (opp->nb_cpus != nb_cpus) {
+ return -EINVAL;
+ }
+ assert(nb_cpus > 0 && nb_cpus <= MAX_CPU);
for (i = 0; i < opp->nb_cpus; i++) {
qemu_get_sbe32s(f, &opp->dst[i].ctpr);
@@ -1567,6 +1572,13 @@ static void openpic_realize(DeviceState *dev, Error
**errp)
{NULL}
};
+ if (opp->nb_cpus > MAX_CPU) {
+ error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
+ TYPE_OPENPIC, "nb_cpus", (uint64_t)opp->nb_cpus,
+ (uint64_t)0, (uint64_t)MAX_CPU);
+ return;
+ }
+
switch (opp->model) {
case OPENPIC_MODEL_FSL_MPIC_20:
default:
diff --git a/hw/misc/cbus.c b/hw/misc/cbus.c
index 29b467b..495d507 100644
--- a/hw/misc/cbus.c
+++ b/hw/misc/cbus.c
@@ -135,9 +135,9 @@ CBus *cbus_init(qemu_irq dat)
CBusPriv *s = (CBusPriv *) g_malloc0(sizeof(*s));
s->dat_out = dat;
- s->cbus.clk = qemu_allocate_irqs(cbus_clk, s, 1)[0];
- s->cbus.dat = qemu_allocate_irqs(cbus_dat, s, 1)[0];
- s->cbus.sel = qemu_allocate_irqs(cbus_sel, s, 1)[0];
+ s->cbus.clk = qemu_allocate_irq(cbus_clk, s, 0);
+ s->cbus.dat = qemu_allocate_irq(cbus_dat, s, 0);
+ s->cbus.sel = qemu_allocate_irq(cbus_sel, s, 0);
s->sel = 1;
s->clk = 0;
diff --git a/hw/misc/imx_ccm.c b/hw/misc/imx_ccm.c
index 63e33a4..449183d 100644
--- a/hw/misc/imx_ccm.c
+++ b/hw/misc/imx_ccm.c
@@ -68,6 +68,7 @@ static const VMStateDescription vmstate_imx_ccm = {
VMSTATE_UINT32(pmcr0, IMXCCMState),
VMSTATE_UINT32(pmcr1, IMXCCMState),
VMSTATE_UINT32(pll_refclk_freq, IMXCCMState),
+ VMSTATE_END_OF_LIST()
},
.post_load = imx_ccm_post_load,
};
diff --git a/hw/net/stellaris_enet.c b/hw/net/stellaris_enet.c
index d04e6a4..9cc6262 100644
--- a/hw/net/stellaris_enet.c
+++ b/hw/net/stellaris_enet.c
@@ -8,6 +8,7 @@
*/
#include "hw/sysbus.h"
#include "net/net.h"
+#include "migration/migration.h"
#include <zlib.h>
//#define DEBUG_STELLARIS_ENET 1
@@ -75,6 +76,7 @@ typedef struct {
NICConf conf;
qemu_irq irq;
MemoryRegion mmio;
+ Error *migration_blocker;
} stellaris_enet_state;
static void stellaris_enet_update(stellaris_enet_state *s)
@@ -253,17 +255,19 @@ static void stellaris_enet_write(void *opaque, hwaddr
offset,
s->tx_fifo[s->tx_fifo_len++] = value >> 24;
}
} else {
- s->tx_fifo[s->tx_fifo_len++] = value;
- s->tx_fifo[s->tx_fifo_len++] = value >> 8;
- s->tx_fifo[s->tx_fifo_len++] = value >> 16;
- s->tx_fifo[s->tx_fifo_len++] = value >> 24;
+ if (s->tx_fifo_len + 4 <= ARRAY_SIZE(s->tx_fifo)) {
+ s->tx_fifo[s->tx_fifo_len++] = value;
+ s->tx_fifo[s->tx_fifo_len++] = value >> 8;
+ s->tx_fifo[s->tx_fifo_len++] = value >> 16;
+ s->tx_fifo[s->tx_fifo_len++] = value >> 24;
+ }
if (s->tx_fifo_len >= s->tx_frame_len) {
/* We don't implement explicit CRC, so just chop it off. */
if ((s->tctl & SE_TCTL_CRC) == 0)
s->tx_frame_len -= 4;
if ((s->tctl & SE_TCTL_PADEN) && s->tx_frame_len < 60) {
memset(&s->tx_fifo[s->tx_frame_len], 0, 60 -
s->tx_frame_len);
- s->tx_fifo_len = 60;
+ s->tx_frame_len = 60;
}
qemu_send_packet(qemu_get_queue(s->nic), s->tx_fifo,
s->tx_frame_len);
@@ -360,7 +364,7 @@ static int stellaris_enet_load(QEMUFile *f, void *opaque,
int version_id)
stellaris_enet_state *s = (stellaris_enet_state *)opaque;
int i;
- if (version_id != 1)
+ if (1)
return -EINVAL;
s->ris = qemu_get_be32(f);
@@ -421,6 +425,10 @@ static int stellaris_enet_init(SysBusDevice *sbd)
stellaris_enet_reset(s);
register_savevm(dev, "stellaris_enet", -1, 1,
stellaris_enet_save, stellaris_enet_load, s);
+
+ error_setg(&s->migration_blocker,
+ "stellaris_enet does not support migration");
+ migrate_add_blocker(s->migration_blocker);
return 0;
}
@@ -428,6 +436,9 @@ static void stellaris_enet_unrealize(DeviceState *dev,
Error **errp)
{
stellaris_enet_state *s = STELLARIS_ENET(dev);
+ migrate_del_blocker(s->migration_blocker);
+ error_free(s->migration_blocker);
+
unregister_savevm(DEVICE(s), "stellaris_enet", s);
memory_region_destroy(&s->mmio);
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 33bd233..2ac6ce5 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -863,6 +863,14 @@ static int virtio_net_has_buffers(VirtIONetQueue *q, int
bufsize)
return 1;
}
+static void virtio_net_hdr_swap(struct virtio_net_hdr *hdr)
+{
+ tswap16s(&hdr->hdr_len);
+ tswap16s(&hdr->gso_size);
+ tswap16s(&hdr->csum_start);
+ tswap16s(&hdr->csum_offset);
+}
+
/* dhclient uses AF_PACKET but doesn't pass auxdata to the kernel so
* it never finds out that the packets don't have valid checksums. This
* causes dhclient to get upset. Fedora's carried a patch for ages to
@@ -898,6 +906,7 @@ static void receive_header(VirtIONet *n, const struct iovec
*iov, int iov_cnt,
void *wbuf = (void *)buf;
work_around_broken_dhclient(wbuf, wbuf + n->host_hdr_len,
size - n->host_hdr_len);
+ virtio_net_hdr_swap(wbuf);
iov_from_buf(iov, iov_cnt, 0, buf, sizeof(struct virtio_net_hdr));
} else {
struct virtio_net_hdr hdr = {
@@ -1106,6 +1115,14 @@ static int32_t virtio_net_flush_tx(VirtIONetQueue *q)
exit(1);
}
+ if (n->has_vnet_hdr) {
+ if (out_sg[0].iov_len < n->guest_hdr_len) {
+ error_report("virtio-net header incorrect");
+ exit(1);
+ }
+ virtio_net_hdr_swap((void *) out_sg[0].iov_base);
+ }
+
/*
* If host wants to see the guest header as is, we can
* pass it on unchanged. Otherwise, copy just the parts
@@ -1362,10 +1379,17 @@ static int virtio_net_load(QEMUFile *f, void *opaque,
int version_id)
if (n->mac_table.in_use <= MAC_TABLE_ENTRIES) {
qemu_get_buffer(f, n->mac_table.macs,
n->mac_table.in_use * ETH_ALEN);
- } else if (n->mac_table.in_use) {
- uint8_t *buf = g_malloc0(n->mac_table.in_use);
- qemu_get_buffer(f, buf, n->mac_table.in_use * ETH_ALEN);
- g_free(buf);
+ } else {
+ int64_t i;
+
+ /* Overflow detected - can happen if source has a larger MAC table.
+ * We simply set overflow flag so there's no need to maintain the
+ * table of addresses, discard them all.
+ * Note: 64 bit math to avoid integer overflow.
+ */
+ for (i = 0; i < (int64_t)n->mac_table.in_use * ETH_ALEN; ++i) {
+ qemu_get_byte(f);
+ }
n->mac_table.multi_overflow = n->mac_table.uni_overflow = 1;
n->mac_table.in_use = 0;
}
@@ -1407,6 +1431,11 @@ static int virtio_net_load(QEMUFile *f, void *opaque,
int version_id)
}
n->curr_queues = qemu_get_be16(f);
+ if (n->curr_queues > n->max_queues) {
+ error_report("virtio-net: curr_queues %x > max_queues %x",
+ n->curr_queues, n->max_queues);
+ return -1;
+ }
for (i = 1; i < n->curr_queues; i++) {
n->vqs[i].tx_waiting = qemu_get_be32(f);
}
diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index 2a9f08e..e05d60c 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -830,6 +830,7 @@ static PCIDevice *do_pci_register_device(PCIDevice
*pci_dev, PCIBus *bus,
}
pci_dev->bus = bus;
+ pci_dev->devfn = devfn;
dma_as = pci_device_iommu_address_space(pci_dev);
memory_region_init_alias(&pci_dev->bus_master_enable_region,
@@ -839,7 +840,6 @@ static PCIDevice *do_pci_register_device(PCIDevice
*pci_dev, PCIBus *bus,
address_space_init(&pci_dev->bus_master_as,
&pci_dev->bus_master_enable_region,
name);
- pci_dev->devfn = devfn;
pstrcpy(pci_dev->name, sizeof(pci_dev->name), name);
pci_dev->irq_state = 0;
pci_config_alloc(pci_dev);
diff --git a/hw/pci/pcie_aer.c b/hw/pci/pcie_aer.c
index 991502e..535be2c 100644
--- a/hw/pci/pcie_aer.c
+++ b/hw/pci/pcie_aer.c
@@ -795,6 +795,13 @@ static const VMStateDescription vmstate_pcie_aer_err = {
}
};
+static bool pcie_aer_state_log_num_valid(void *opaque, int version_id)
+{
+ PCIEAERLog *s = opaque;
+
+ return s->log_num <= s->log_max;
+}
+
const VMStateDescription vmstate_pcie_aer_log = {
.name = "PCIE_AER_ERROR_LOG",
.version_id = 1,
@@ -802,7 +809,8 @@ const VMStateDescription vmstate_pcie_aer_log = {
.minimum_version_id_old = 1,
.fields = (VMStateField[]) {
VMSTATE_UINT16(log_num, PCIEAERLog),
- VMSTATE_UINT16(log_max, PCIEAERLog),
+ VMSTATE_UINT16_EQUAL(log_max, PCIEAERLog),
+ VMSTATE_VALIDATE("log_num <= log_max", pcie_aer_state_log_num_valid),
VMSTATE_STRUCT_VARRAY_POINTER_UINT16(log, PCIEAERLog, log_num,
vmstate_pcie_aer_err, PCIEAERErr),
VMSTATE_END_OF_LIST()
diff --git a/hw/pcmcia/pxa2xx.c b/hw/pcmcia/pxa2xx.c
index 96f3774..55e8a2a 100644
--- a/hw/pcmcia/pxa2xx.c
+++ b/hw/pcmcia/pxa2xx.c
@@ -195,7 +195,7 @@ static void pxa2xx_pcmcia_initfn(Object *obj)
memory_region_add_subregion(&s->container_mem, 0x0c000000,
&s->common_iomem);
- s->slot.irq = qemu_allocate_irqs(pxa2xx_pcmcia_set_irq, s, 1)[0];
+ s->slot.irq = qemu_allocate_irq(pxa2xx_pcmcia_set_irq, s, 0);
object_property_add_link(obj, "card", TYPE_PCMCIA_CARD,
(Object **)&s->card,
diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
index cbef095..000c94f 100644
--- a/hw/ppc/spapr_pci.c
+++ b/hw/ppc/spapr_pci.c
@@ -343,6 +343,21 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu,
sPAPREnvironment *spapr,
/* There is no cached config, allocate MSIs */
if (!phb->msi_table[ndev].nvec) {
+ int max_irqs = 0;
+ if (ret_intr_type == RTAS_TYPE_MSI) {
+ max_irqs = msi_nr_vectors_allocated(pdev);
+ } else if (ret_intr_type == RTAS_TYPE_MSIX) {
+ max_irqs = pdev->msix_entries_nr;
+ }
+ if (!max_irqs) {
+ error_report("Requested interrupt type %d is not enabled for
device#%d",
+ ret_intr_type, ndev);
+ rtas_st(rets, 0, -1); /* Hardware error */
+ return;
+ }
+ if (req_num > max_irqs) {
+ req_num = max_irqs;
+ }
irq = spapr_allocate_irq_block(req_num, false,
ret_intr_type == RTAS_TYPE_MSI);
if (irq < 0) {
diff --git a/hw/s390x/css.c b/hw/s390x/css.c
index 7074d2b..d68a29a 100644
--- a/hw/s390x/css.c
+++ b/hw/s390x/css.c
@@ -734,9 +734,11 @@ out:
return ret;
}
-static void copy_irb_to_guest(IRB *dest, const IRB *src)
+static void copy_irb_to_guest(IRB *dest, const IRB *src, PMCW *pmcw)
{
int i;
+ uint16_t stctl = src->scsw.ctrl & SCSW_CTRL_MASK_STCTL;
+ uint16_t actl = src->scsw.ctrl & SCSW_CTRL_MASK_ACTL;
copy_scsw_to_guest(&dest->scsw, &src->scsw);
@@ -746,8 +748,22 @@ static void copy_irb_to_guest(IRB *dest, const IRB *src)
for (i = 0; i < ARRAY_SIZE(dest->ecw); i++) {
dest->ecw[i] = cpu_to_be32(src->ecw[i]);
}
- for (i = 0; i < ARRAY_SIZE(dest->emw); i++) {
- dest->emw[i] = cpu_to_be32(src->emw[i]);
+ /* extended measurements enabled? */
+ if ((src->scsw.flags & SCSW_FLAGS_MASK_ESWF) ||
+ !(pmcw->flags & PMCW_FLAGS_MASK_TF) ||
+ !(pmcw->chars & PMCW_CHARS_MASK_XMWME)) {
+ return;
+ }
+ /* extended measurements pending? */
+ if (!(stctl & SCSW_STCTL_STATUS_PEND)) {
+ return;
+ }
+ if ((stctl & SCSW_STCTL_PRIMARY) ||
+ (stctl == SCSW_STCTL_SECONDARY) ||
+ ((stctl & SCSW_STCTL_INTERMEDIATE) && (actl & SCSW_ACTL_SUSP))) {
+ for (i = 0; i < ARRAY_SIZE(dest->emw); i++) {
+ dest->emw[i] = cpu_to_be32(src->emw[i]);
+ }
}
}
@@ -793,7 +809,7 @@ int css_do_tsch(SubchDev *sch, IRB *target_irb)
}
}
/* Store the irb to the guest. */
- copy_irb_to_guest(target_irb, &irb);
+ copy_irb_to_guest(target_irb, &irb, p);
/* Clear conditions on subchannel, if applicable. */
if (stctl & SCSW_STCTL_STATUS_PEND) {
diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c
index e6e1ffd..1781525 100644
--- a/hw/scsi/megasas.c
+++ b/hw/scsi/megasas.c
@@ -1106,6 +1106,21 @@ static int megasas_dcmd_ld_get_list(MegasasState *s,
MegasasCmd *cmd)
return MFI_STAT_OK;
}
+static int megasas_dcmd_ld_list_query(MegasasState *s, MegasasCmd *cmd)
+{
+ uint16_t flags;
+
+ /* mbox0 contains flags */
+ flags = le16_to_cpu(cmd->frame->dcmd.mbox[0]);
+ trace_megasas_dcmd_ld_list_query(cmd->index, flags);
+ if (flags == MR_LD_QUERY_TYPE_ALL ||
+ flags == MR_LD_QUERY_TYPE_EXPOSED_TO_HOST) {
+ return megasas_dcmd_ld_get_list(s, cmd);
+ }
+
+ return MFI_STAT_OK;
+}
+
static int megasas_ld_get_info_submit(SCSIDevice *sdev, int lun,
MegasasCmd *cmd)
{
@@ -1409,6 +1424,8 @@ static const struct dcmd_cmd_tbl_t {
megasas_dcmd_dummy },
{ MFI_DCMD_LD_GET_LIST, "LD_GET_LIST",
megasas_dcmd_ld_get_list},
+ { MFI_DCMD_LD_LIST_QUERY, "LD_LIST_QUERY",
+ megasas_dcmd_ld_list_query },
{ MFI_DCMD_LD_GET_INFO, "LD_GET_INFO",
megasas_dcmd_ld_get_info },
{ MFI_DCMD_LD_GET_PROP, "LD_GET_PROP",
diff --git a/hw/scsi/mfi.h b/hw/scsi/mfi.h
index cd8355b..a3034f6 100644
--- a/hw/scsi/mfi.h
+++ b/hw/scsi/mfi.h
@@ -164,6 +164,7 @@ typedef enum {
MFI_DCMD_PD_BLINK = 0x02070100,
MFI_DCMD_PD_UNBLINK = 0x02070200,
MFI_DCMD_LD_GET_LIST = 0x03010000,
+ MFI_DCMD_LD_LIST_QUERY = 0x03010100,
MFI_DCMD_LD_GET_INFO = 0x03020000,
MFI_DCMD_LD_GET_PROP = 0x03030000,
MFI_DCMD_LD_SET_PROP = 0x03040000,
@@ -411,6 +412,14 @@ typedef enum {
MR_PD_QUERY_TYPE_EXPOSED_TO_HOST = 5, /*query for system drives */
} mfi_pd_query_type;
+typedef enum {
+ MR_LD_QUERY_TYPE_ALL = 0,
+ MR_LD_QUERY_TYPE_EXPOSED_TO_HOST = 1,
+ MR_LD_QUERY_TYPE_USED_TGT_IDS = 2,
+ MR_LD_QUERY_TYPE_CLUSTER_ACCESS = 3,
+ MR_LD_QUERY_TYPE_CLUSTER_LOCALE = 4,
+} mfi_ld_query_type;
+
/*
* Other propertities and definitions
*/
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
index 48a28ae..da8c436 100644
--- a/hw/scsi/scsi-disk.c
+++ b/hw/scsi/scsi-disk.c
@@ -2520,7 +2520,7 @@ static SCSIRequest *scsi_block_new_request(SCSIDevice *d,
uint32_t tag,
* ones (such as WRITE SAME or EXTENDED COPY, etc.). So, without
* O_DIRECT everything must go through SG_IO.
*/
- if (bdrv_get_flags(s->qdev.conf.bs) & BDRV_O_NOCACHE) {
+ if (!(bdrv_get_flags(s->qdev.conf.bs) & BDRV_O_NOCACHE)) {
break;
}
diff --git a/hw/scsi/vhost-scsi.c b/hw/scsi/vhost-scsi.c
index 3983a5b..9099192 100644
--- a/hw/scsi/vhost-scsi.c
+++ b/hw/scsi/vhost-scsi.c
@@ -196,6 +196,10 @@ static void vhost_scsi_set_status(VirtIODevice *vdev,
uint8_t val)
}
}
+static void vhost_dummy_handle_output(VirtIODevice *vdev, VirtQueue *vq)
+{
+}
+
static void vhost_scsi_realize(DeviceState *dev, Error **errp)
{
VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(dev);
@@ -217,7 +221,9 @@ static void vhost_scsi_realize(DeviceState *dev, Error
**errp)
}
}
- virtio_scsi_common_realize(dev, &err);
+ virtio_scsi_common_realize(dev, &err, vhost_dummy_handle_output,
+ vhost_dummy_handle_output,
+ vhost_dummy_handle_output);
if (err != NULL) {
error_propagate(errp, err);
return;
diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
index b0d7517..d183cd0 100644
--- a/hw/scsi/virtio-scsi.c
+++ b/hw/scsi/virtio-scsi.c
@@ -147,6 +147,15 @@ static void *virtio_scsi_load_request(QEMUFile *f,
SCSIRequest *sreq)
qemu_get_be32s(f, &n);
assert(n < vs->conf.num_queues);
qemu_get_buffer(f, (unsigned char *)&req->elem, sizeof(req->elem));
+ /* TODO: add a way for SCSIBusInfo's load_request to fail,
+ * and fail migration instead of asserting here.
+ * When we do, we might be able to re-enable NDEBUG below.
+ */
+#ifdef NDEBUG
+#error building with NDEBUG is not supported
+#endif
+ assert(req->elem.in_num <= ARRAY_SIZE(req->elem.in_sg));
+ assert(req->elem.out_num <= ARRAY_SIZE(req->elem.out_sg));
virtio_scsi_parse_req(s, vs->cmd_vqs[n], req);
scsi_req_ref(sreq);
@@ -489,7 +498,7 @@ static void virtio_scsi_push_event(VirtIOSCSI *s,
SCSIDevice *dev,
uint32_t event, uint32_t reason)
{
VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(s);
- VirtIOSCSIReq *req = virtio_scsi_pop_req(s, vs->event_vq);
+ VirtIOSCSIReq *req;
VirtIOSCSIEvent *evt;
VirtIODevice *vdev = VIRTIO_DEVICE(s);
int in_size;
@@ -498,6 +507,7 @@ static void virtio_scsi_push_event(VirtIOSCSI *s,
SCSIDevice *dev,
return;
}
+ req = virtio_scsi_pop_req(s, vs->event_vq);
if (!req) {
s->events_dropped = true;
return;
@@ -595,7 +605,9 @@ static struct SCSIBusInfo virtio_scsi_scsi_info = {
.load_request = virtio_scsi_load_request,
};
-void virtio_scsi_common_realize(DeviceState *dev, Error **errp)
+void virtio_scsi_common_realize(DeviceState *dev, Error **errp,
+ HandleOutput ctrl, HandleOutput evt,
+ HandleOutput cmd)
{
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
VirtIOSCSICommon *s = VIRTIO_SCSI_COMMON(dev);
@@ -609,12 +621,12 @@ void virtio_scsi_common_realize(DeviceState *dev, Error
**errp)
s->cdb_size = VIRTIO_SCSI_CDB_SIZE;
s->ctrl_vq = virtio_add_queue(vdev, VIRTIO_SCSI_VQ_SIZE,
- virtio_scsi_handle_ctrl);
+ ctrl);
s->event_vq = virtio_add_queue(vdev, VIRTIO_SCSI_VQ_SIZE,
- virtio_scsi_handle_event);
+ evt);
for (i = 0; i < s->conf.num_queues; i++) {
s->cmd_vqs[i] = virtio_add_queue(vdev, VIRTIO_SCSI_VQ_SIZE,
- virtio_scsi_handle_cmd);
+ cmd);
}
}
@@ -625,7 +637,9 @@ static void virtio_scsi_device_realize(DeviceState *dev,
Error **errp)
static int virtio_scsi_id;
Error *err = NULL;
- virtio_scsi_common_realize(dev, &err);
+ virtio_scsi_common_realize(dev, &err, virtio_scsi_handle_ctrl,
+ virtio_scsi_handle_event,
+ virtio_scsi_handle_cmd);
if (err != NULL) {
error_propagate(errp, err);
return;
diff --git a/hw/sd/omap_mmc.c b/hw/sd/omap_mmc.c
index 937a478..6c92149 100644
--- a/hw/sd/omap_mmc.c
+++ b/hw/sd/omap_mmc.c
@@ -625,7 +625,7 @@ struct omap_mmc_s *omap2_mmc_init(struct
omap_target_agent_s *ta,
exit(1);
}
- s->cdet = qemu_allocate_irqs(omap_mmc_cover_cb, s, 1)[0];
+ s->cdet = qemu_allocate_irq(omap_mmc_cover_cb, s, 0);
sd_set_cb(s->card, NULL, s->cdet);
return s;
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index 843e697..e79a886 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -1168,8 +1168,8 @@ static void sdhci_initfn(Object *obj)
if (s->card == NULL) {
exit(1);
}
- s->eject_cb = qemu_allocate_irqs(sdhci_insert_eject_cb, s, 1)[0];
- s->ro_cb = qemu_allocate_irqs(sdhci_card_readonly_cb, s, 1)[0];
+ s->eject_cb = qemu_allocate_irq(sdhci_insert_eject_cb, s, 0);
+ s->ro_cb = qemu_allocate_irq(sdhci_card_readonly_cb, s, 0);
sd_set_cb(s->card, s->ro_cb, s->eject_cb);
s->insert_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
sdhci_raise_insertion_irq, s);
@@ -1184,8 +1184,8 @@ static void sdhci_uninitfn(Object *obj)
timer_free(s->insert_timer);
timer_del(s->transfer_timer);
timer_free(s->transfer_timer);
- qemu_free_irqs(&s->eject_cb);
- qemu_free_irqs(&s->ro_cb);
+ qemu_free_irq(s->eject_cb);
+ qemu_free_irq(s->ro_cb);
if (s->fifo_buffer) {
g_free(s->fifo_buffer);
diff --git a/hw/sd/ssi-sd.c b/hw/sd/ssi-sd.c
index 3273c8a..b012e57 100644
--- a/hw/sd/ssi-sd.c
+++ b/hw/sd/ssi-sd.c
@@ -230,8 +230,17 @@ static int ssi_sd_load(QEMUFile *f, void *opaque, int
version_id)
for (i = 0; i < 5; i++)
s->response[i] = qemu_get_be32(f);
s->arglen = qemu_get_be32(f);
+ if (s->mode == SSI_SD_CMDARG &&
+ (s->arglen < 0 || s->arglen >= ARRAY_SIZE(s->cmdarg))) {
+ return -EINVAL;
+ }
s->response_pos = qemu_get_be32(f);
s->stopping = qemu_get_be32(f);
+ if (s->mode == SSI_SD_RESPONSE &&
+ (s->response_pos < 0 || s->response_pos >= ARRAY_SIZE(s->response) ||
+ (!s->stopping && s->arglen > ARRAY_SIZE(s->response)))) {
+ return -EINVAL;
+ }
ss->cs = qemu_get_be32(f);
diff --git a/hw/sh4/sh7750.c b/hw/sh4/sh7750.c
index 4a39357..5dda5de 100644
--- a/hw/sh4/sh7750.c
+++ b/hw/sh4/sh7750.c
@@ -838,6 +838,5 @@ SH7750State *sh7750_init(SuperHCPU *cpu, MemoryRegion
*sysmem)
qemu_irq sh7750_irl(SH7750State *s)
{
sh_intc_toggle_source(sh_intc_source(&s->intc, IRL), 1, 0); /* enable */
- return qemu_allocate_irqs(sh_intc_set_irl, sh_intc_source(&s->intc, IRL),
- 1)[0];
+ return qemu_allocate_irq(sh_intc_set_irl, sh_intc_source(&s->intc, IRL),
0);
}
diff --git a/hw/ssi/pl022.c b/hw/ssi/pl022.c
index fd479ef..b19bc71 100644
--- a/hw/ssi/pl022.c
+++ b/hw/ssi/pl022.c
@@ -240,11 +240,25 @@ static const MemoryRegionOps pl022_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
+static int pl022_post_load(void *opaque, int version_id)
+{
+ PL022State *s = opaque;
+
+ if (s->tx_fifo_head < 0 ||
+ s->tx_fifo_head >= ARRAY_SIZE(s->tx_fifo) ||
+ s->rx_fifo_head < 0 ||
+ s->rx_fifo_head >= ARRAY_SIZE(s->rx_fifo)) {
+ return -1;
+ }
+ return 0;
+}
+
static const VMStateDescription vmstate_pl022 = {
.name = "pl022_ssp",
.version_id = 1,
.minimum_version_id = 1,
.minimum_version_id_old = 1,
+ .post_load = pl022_post_load,
.fields = (VMStateField[]) {
VMSTATE_UINT32(cr0, PL022State),
VMSTATE_UINT32(cr1, PL022State),
diff --git a/hw/timer/hpet.c b/hw/timer/hpet.c
index e15d6bc..2792f89 100644
--- a/hw/timer/hpet.c
+++ b/hw/timer/hpet.c
@@ -239,6 +239,18 @@ static int hpet_pre_load(void *opaque)
return 0;
}
+static bool hpet_validate_num_timers(void *opaque, int version_id)
+{
+ HPETState *s = opaque;
+
+ if (s->num_timers < HPET_MIN_TIMERS) {
+ return false;
+ } else if (s->num_timers > HPET_MAX_TIMERS) {
+ return false;
+ }
+ return true;
+}
+
static int hpet_post_load(void *opaque, int version_id)
{
HPETState *s = opaque;
@@ -307,6 +319,7 @@ static const VMStateDescription vmstate_hpet = {
VMSTATE_UINT64(isr, HPETState),
VMSTATE_UINT64(hpet_counter, HPETState),
VMSTATE_UINT8_V(num_timers, HPETState, 2),
+ VMSTATE_VALIDATE("num_timers in range", hpet_validate_num_timers),
VMSTATE_STRUCT_VARRAY_UINT8(timer, HPETState, num_timers, 0,
vmstate_hpet_timer, HPETTimer),
VMSTATE_END_OF_LIST()
diff --git a/hw/timer/i8254.c b/hw/timer/i8254.c
index 28152d8..3450c98 100644
--- a/hw/timer/i8254.c
+++ b/hw/timer/i8254.c
@@ -322,7 +322,7 @@ static void pit_post_load(PITCommonState *s)
}
}
-static void pit_realizefn(DeviceState *dev, Error **err)
+static void pit_realizefn(DeviceState *dev, Error **errp)
{
PITCommonState *pit = PIT_COMMON(dev);
PITClass *pc = PIT_GET_CLASS(dev);
@@ -338,7 +338,7 @@ static void pit_realizefn(DeviceState *dev, Error **err)
qdev_init_gpio_in(dev, pit_irq_control, 1);
- pc->parent_realize(dev, err);
+ pc->parent_realize(dev, errp);
}
static Property pit_properties[] = {
diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c
index 8509309..abcbcae 100644
--- a/hw/timer/mc146818rtc.c
+++ b/hw/timer/mc146818rtc.c
@@ -852,7 +852,7 @@ static void rtc_realizefn(DeviceState *dev, Error **errp)
check_update_timer(s);
s->clock_reset_notifier.notify = rtc_notify_clock_reset;
- qemu_clock_register_reset_notifier(QEMU_CLOCK_REALTIME,
+ qemu_clock_register_reset_notifier(rtc_clock,
&s->clock_reset_notifier);
s->suspend_notifier.notify = rtc_notify_suspend;
diff --git a/hw/timer/omap_gptimer.c b/hw/timer/omap_gptimer.c
index 016207f..b7f3d49 100644
--- a/hw/timer/omap_gptimer.c
+++ b/hw/timer/omap_gptimer.c
@@ -227,7 +227,7 @@ static void omap_gp_timer_clk_update(void *opaque, int
line, int on)
static void omap_gp_timer_clk_setup(struct omap_gp_timer_s *timer)
{
omap_clk_adduser(timer->clk,
- qemu_allocate_irqs(omap_gp_timer_clk_update, timer, 1)[0]);
+ qemu_allocate_irq(omap_gp_timer_clk_update, timer, 0));
timer->rate = omap_clk_getrate(timer->clk);
}
@@ -476,7 +476,7 @@ struct omap_gp_timer_s *omap_gp_timer_init(struct
omap_target_agent_s *ta,
s->clk = fclk;
s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, omap_gp_timer_tick, s);
s->match = timer_new_ns(QEMU_CLOCK_VIRTUAL, omap_gp_timer_match, s);
- s->in = qemu_allocate_irqs(omap_gp_timer_input, s, 1)[0];
+ s->in = qemu_allocate_irq(omap_gp_timer_input, s, 0);
omap_gp_timer_reset(s);
omap_gp_timer_clk_setup(s);
diff --git a/hw/usb/bus.c b/hw/usb/bus.c
index fe70429..e48b19f 100644
--- a/hw/usb/bus.c
+++ b/hw/usb/bus.c
@@ -49,7 +49,9 @@ static int usb_device_post_load(void *opaque, int version_id)
} else {
dev->attached = 1;
}
- if (dev->setup_index >= sizeof(dev->data_buf) ||
+ if (dev->setup_index < 0 ||
+ dev->setup_len < 0 ||
+ dev->setup_index >= sizeof(dev->data_buf) ||
dev->setup_len >= sizeof(dev->data_buf)) {
return -EINVAL;
}
diff --git a/hw/usb/dev-bluetooth.c b/hw/usb/dev-bluetooth.c
index a9661d2..a76e581 100644
--- a/hw/usb/dev-bluetooth.c
+++ b/hw/usb/dev-bluetooth.c
@@ -19,6 +19,7 @@
*/
#include "qemu-common.h"
+#include "qemu/error-report.h"
#include "hw/usb.h"
#include "hw/usb/desc.h"
#include "sysemu/bt.h"
@@ -506,6 +507,14 @@ static int usb_bt_initfn(USBDevice *dev)
usb_desc_create_serial(dev);
usb_desc_init(dev);
+ s->dev.opaque = s;
+ if (!s->hci) {
+ s->hci = bt_new_hci(qemu_find_bt_vlan(0));
+ }
+ s->hci->opaque = s;
+ s->hci->evt_recv = usb_bt_out_hci_packet_event;
+ s->hci->acl_recv = usb_bt_out_hci_packet_acl;
+ usb_bt_handle_reset(&s->dev);
s->intr = usb_ep_get(dev, USB_TOKEN_IN, USB_EVT_EP);
return 0;
@@ -516,6 +525,7 @@ static USBDevice *usb_bt_init(USBBus *bus, const char
*cmdline)
USBDevice *dev;
struct USBBtState *s;
HCIInfo *hci;
+ const char *name = "usb-bt-dongle";
if (*cmdline) {
hci = hci_init(cmdline);
@@ -525,19 +535,17 @@ static USBDevice *usb_bt_init(USBBus *bus, const char
*cmdline)
if (!hci)
return NULL;
- dev = usb_create_simple(bus, "usb-bt-dongle");
+ dev = usb_create(bus, name);
if (!dev) {
+ error_report("Failed to create USB device '%s'", name);
return NULL;
}
s = DO_UPCAST(struct USBBtState, dev, dev);
- s->dev.opaque = s;
-
s->hci = hci;
- s->hci->opaque = s;
- s->hci->evt_recv = usb_bt_out_hci_packet_event;
- s->hci->acl_recv = usb_bt_out_hci_packet_acl;
-
- usb_bt_handle_reset(&s->dev);
+ if (qdev_init(&dev->qdev) < 0) {
+ error_report("Failed to initialize USB device '%s'", name);
+ return NULL;
+ }
return dev;
}
diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index ef3177a..0ceb10d 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -3703,6 +3703,7 @@ static const VMStateDescription vmstate_xhci_event = {
VMSTATE_UINT32(flags, XHCIEvent),
VMSTATE_UINT8(slotid, XHCIEvent),
VMSTATE_UINT8(epid, XHCIEvent),
+ VMSTATE_END_OF_LIST()
}
};
diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index 9e336ad..1d349e0 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -309,7 +309,9 @@ static int vhost_verify_ring_mappings(struct vhost_dev *dev,
uint64_t size)
{
int i;
- for (i = 0; i < dev->nvqs; ++i) {
+ int r = 0;
+
+ for (i = 0; !r && i < dev->nvqs; ++i) {
struct vhost_virtqueue *vq = dev->vqs + i;
hwaddr l;
void *p;
@@ -321,15 +323,15 @@ static int vhost_verify_ring_mappings(struct vhost_dev
*dev,
p = cpu_physical_memory_map(vq->ring_phys, &l, 1);
if (!p || l != vq->ring_size) {
fprintf(stderr, "Unable to map ring buffer for ring %d\n", i);
- return -ENOMEM;
+ r = -ENOMEM;
}
if (p != vq->ring) {
fprintf(stderr, "Ring buffer relocated for ring %d\n", i);
- return -EBUSY;
+ r = -EBUSY;
}
cpu_physical_memory_unmap(p, l, 0, 0);
}
- return 0;
+ return r;
}
static struct vhost_memory_region *vhost_dev_find_reg(struct vhost_dev *dev,
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index aeabf3a..3e4b70c 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -430,6 +430,12 @@ void virtqueue_map_sg(struct iovec *sg, hwaddr *addr,
unsigned int i;
hwaddr len;
+ if (num_sg > VIRTQUEUE_MAX_SIZE) {
+ error_report("virtio: map attempt out of bounds: %zd > %d",
+ num_sg, VIRTQUEUE_MAX_SIZE);
+ exit(1);
+ }
+
for (i = 0; i < num_sg; i++) {
len = sg[i].iov_len;
sg[i].iov_base = cpu_physical_memory_map(addr[i], &len, is_write);
@@ -891,7 +897,9 @@ int virtio_set_features(VirtIODevice *vdev, uint32_t val)
int virtio_load(VirtIODevice *vdev, QEMUFile *f)
{
- int num, i, ret;
+ int i, ret;
+ int32_t config_len;
+ uint32_t num;
uint32_t features;
uint32_t supported_features;
BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
@@ -906,6 +914,9 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f)
qemu_get_8s(f, &vdev->status);
qemu_get_8s(f, &vdev->isr);
qemu_get_be16s(f, &vdev->queue_sel);
+ if (vdev->queue_sel >= VIRTIO_PCI_QUEUE_MAX) {
+ return -1;
+ }
qemu_get_be32s(f, &features);
if (virtio_set_features(vdev, features) < 0) {
@@ -914,11 +925,27 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f)
features, supported_features);
return -1;
}
- vdev->config_len = qemu_get_be32(f);
- qemu_get_buffer(f, vdev->config, vdev->config_len);
+ config_len = qemu_get_be32(f);
+
+ /*
+ * There are cases where the incoming config can be bigger or smaller
+ * than what we have; so load what we have space for, and skip
+ * any excess that's in the stream.
+ */
+ qemu_get_buffer(f, vdev->config, MIN(config_len, vdev->config_len));
+
+ while (config_len > vdev->config_len) {
+ qemu_get_byte(f);
+ config_len--;
+ }
num = qemu_get_be32(f);
+ if (num > VIRTIO_PCI_QUEUE_MAX) {
+ error_report("Invalid number of PCI queues: 0x%x", num);
+ return -1;
+ }
+
for (i = 0; i < num; i++) {
vdev->vq[i].vring.num = qemu_get_be32(f);
if (k->has_variable_vring_alignment) {
diff --git a/hw/xtensa/xtensa_lx60.c b/hw/xtensa/xtensa_lx60.c
index 49c58d1..fc6a513 100644
--- a/hw/xtensa/xtensa_lx60.c
+++ b/hw/xtensa/xtensa_lx60.c
@@ -42,6 +42,7 @@
typedef struct LxBoardDesc {
hwaddr flash_base;
size_t flash_size;
+ size_t flash_boot_base;
size_t flash_sector_size;
size_t sram_size;
} LxBoardDesc;
@@ -266,9 +267,9 @@ static void lx_init(const LxBoardDesc *board,
QEMUMachineInitArgs *args)
MemoryRegion *flash_io = g_malloc(sizeof(*flash_io));
memory_region_init_alias(flash_io, NULL, "lx60.flash",
- flash_mr, 0,
- board->flash_size < 0x02000000 ?
- board->flash_size : 0x02000000);
+ flash_mr, board->flash_boot_base,
+ board->flash_size - board->flash_boot_base < 0x02000000 ?
+ board->flash_size - board->flash_boot_base : 0x02000000);
memory_region_add_subregion(system_memory, 0xfe000000,
flash_io);
}
@@ -313,6 +314,7 @@ static void xtensa_kc705_init(QEMUMachineInitArgs *args)
static const LxBoardDesc kc705_board = {
.flash_base = 0xf0000000,
.flash_size = 0x08000000,
+ .flash_boot_base = 0x06000000,
.flash_sector_size = 0x20000,
.sram_size = 0x2000000,
};
diff --git a/include/block/blockjob.h b/include/block/blockjob.h
index d76de62..395be5b 100644
--- a/include/block/blockjob.h
+++ b/include/block/blockjob.h
@@ -144,6 +144,14 @@ void *block_job_create(const BlockJobDriver *driver,
BlockDriverState *bs,
void block_job_sleep_ns(BlockJob *job, QEMUClockType type, int64_t ns);
/**
+ * block_job_yield:
+ * @job: The job that calls the function.
+ *
+ * Yield the block job coroutine.
+ */
+void block_job_yield(BlockJob *job);
+
+/**
* block_job_completed:
* @job: The job being completed.
* @ret: The status code.
diff --git a/include/hw/i386/smbios.h b/include/hw/i386/smbios.h
index 18fb970..f808199 100644
--- a/include/hw/i386/smbios.h
+++ b/include/hw/i386/smbios.h
@@ -16,9 +16,9 @@
#include "qemu/option.h"
void smbios_entry_add(QemuOpts *opts);
-void smbios_set_type1_defaults(const char *manufacturer,
- const char *product, const char *version);
-uint8_t *smbios_get_table(size_t *length);
+void smbios_set_defaults(const char *manufacturer, const char *product,
+ const char *version);
+uint8_t *smbios_get_table_legacy(size_t *length);
/*
* SMBIOS spec defined tables
diff --git a/include/hw/virtio/virtio-net.h b/include/hw/virtio/virtio-net.h
index df60f16..4b32440 100644
--- a/include/hw/virtio/virtio-net.h
+++ b/include/hw/virtio/virtio-net.h
@@ -176,8 +176,8 @@ typedef struct VirtIONet {
uint8_t nobcast;
uint8_t vhost_started;
struct {
- int in_use;
- int first_multi;
+ uint32_t in_use;
+ uint32_t first_multi;
uint8_t multi_overflow;
uint8_t uni_overflow;
uint8_t *macs;
diff --git a/include/hw/virtio/virtio-scsi.h b/include/hw/virtio/virtio-scsi.h
index 42b1024..e81a643 100644
--- a/include/hw/virtio/virtio-scsi.h
+++ b/include/hw/virtio/virtio-scsi.h
@@ -186,7 +186,12 @@ typedef struct {
DEFINE_PROP_BIT("param_change", _state, _feature_field,
\
VIRTIO_SCSI_F_CHANGE, true)
-void virtio_scsi_common_realize(DeviceState *dev, Error **errp);
+typedef void (*HandleOutput)(VirtIODevice *, VirtQueue *);
+
+void virtio_scsi_common_realize(DeviceState *dev, Error **errp,
+ HandleOutput ctrl, HandleOutput evt,
+ HandleOutput cmd);
+
void virtio_scsi_common_unrealize(DeviceState *dev, Error **errp);
#endif /* _QEMU_VIRTIO_SCSI_H */
diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
index e7e1705..5b71370 100644
--- a/include/migration/vmstate.h
+++ b/include/migration/vmstate.h
@@ -100,6 +100,7 @@ enum VMStateFlags {
VMS_MULTIPLY = 0x200, /* multiply "size" field by field_size */
VMS_VARRAY_UINT8 = 0x400, /* Array with size in uint8_t field*/
VMS_VARRAY_UINT32 = 0x800, /* Array with size in uint32_t field*/
+ VMS_MUST_EXIST = 0x1000, /* Field must exist in input */
};
typedef struct {
@@ -203,6 +204,14 @@ extern const VMStateInfo vmstate_info_bitmap;
.offset = vmstate_offset_value(_state, _field, _type), \
}
+/* Validate state using a boolean predicate. */
+#define VMSTATE_VALIDATE(_name, _test) { \
+ .name = (_name), \
+ .field_exists = (_test), \
+ .flags = VMS_ARRAY | VMS_MUST_EXIST, \
+ .num = 0, /* 0 elements: no data, only run _test */ \
+}
+
#define VMSTATE_POINTER(_field, _state, _version, _info, _type) { \
.name = (stringify(_field)), \
.version_id = (_version), \
diff --git a/kvm-all.c b/kvm-all.c
index 82a9119..2754c15 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -948,7 +948,7 @@ void kvm_init_irq_routing(KVMState *s)
{
int gsi_count, i;
- gsi_count = kvm_check_extension(s, KVM_CAP_IRQ_ROUTING);
+ gsi_count = kvm_check_extension(s, KVM_CAP_IRQ_ROUTING) - 1;
if (gsi_count > 0) {
unsigned int gsi_bits, i;
@@ -2022,12 +2022,13 @@ void kvm_remove_all_breakpoints(CPUState *cpu)
{
struct kvm_sw_breakpoint *bp, *next;
KVMState *s = cpu->kvm_state;
+ CPUState *tmpcpu;
QTAILQ_FOREACH_SAFE(bp, &s->kvm_sw_breakpoints, entry, next) {
if (kvm_arch_remove_sw_breakpoint(cpu, bp) != 0) {
/* Try harder to find a CPU that currently sees the breakpoint. */
- CPU_FOREACH(cpu) {
- if (kvm_arch_remove_sw_breakpoint(cpu, bp) == 0) {
+ CPU_FOREACH(tmpcpu) {
+ if (kvm_arch_remove_sw_breakpoint(tmpcpu, bp) == 0) {
break;
}
}
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index d2380b6..e1ff346 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -267,17 +267,15 @@ static void elf_core_copy_regs(target_elf_gregset_t
*regs, const CPUX86State *en
#ifdef TARGET_ARM
+#ifndef TARGET_AARCH64
+/* 32 bit ARM definitions */
+
#define ELF_START_MMAP 0x80000000
#define elf_check_arch(x) ((x) == ELF_MACHINE)
#define ELF_ARCH ELF_MACHINE
-
-#ifdef TARGET_AARCH64
-#define ELF_CLASS ELFCLASS64
-#else
#define ELF_CLASS ELFCLASS32
-#endif
static inline void init_thread(struct target_pt_regs *regs,
struct image_info *infop)
@@ -285,10 +283,6 @@ static inline void init_thread(struct target_pt_regs *regs,
abi_long stack = infop->start_stack;
memset(regs, 0, sizeof(*regs));
-#ifdef TARGET_AARCH64
- regs->pc = infop->entry & ~0x3ULL;
- regs->sp = stack;
-#else
regs->ARM_cpsr = 0x10;
if (infop->entry & 1)
regs->ARM_cpsr |= CPSR_T;
@@ -302,7 +296,6 @@ static inline void init_thread(struct target_pt_regs *regs,
/* For uClinux PIC binaries. */
/* XXX: Linux does this only on ARM with no MMU (do we care ?) */
regs->ARM_r10 = infop->start_data;
-#endif
}
#define ELF_NREG 18
@@ -346,13 +339,20 @@ enum
ARM_HWCAP_ARM_EDSP = 1 << 7,
ARM_HWCAP_ARM_JAVA = 1 << 8,
ARM_HWCAP_ARM_IWMMXT = 1 << 9,
- ARM_HWCAP_ARM_THUMBEE = 1 << 10,
- ARM_HWCAP_ARM_NEON = 1 << 11,
- ARM_HWCAP_ARM_VFPv3 = 1 << 12,
- ARM_HWCAP_ARM_VFPv3D16 = 1 << 13,
+ ARM_HWCAP_ARM_CRUNCH = 1 << 10,
+ ARM_HWCAP_ARM_THUMBEE = 1 << 11,
+ ARM_HWCAP_ARM_NEON = 1 << 12,
+ ARM_HWCAP_ARM_VFPv3 = 1 << 13,
+ ARM_HWCAP_ARM_VFPv3D16 = 1 << 14,
+ ARM_HWCAP_ARM_TLS = 1 << 15,
+ ARM_HWCAP_ARM_VFPv4 = 1 << 16,
+ ARM_HWCAP_ARM_IDIVA = 1 << 17,
+ ARM_HWCAP_ARM_IDIVT = 1 << 18,
+ ARM_HWCAP_ARM_VFPD32 = 1 << 19,
+ ARM_HWCAP_ARM_LPAE = 1 << 20,
+ ARM_HWCAP_ARM_EVTSTRM = 1 << 21,
};
-#ifndef TARGET_AARCH64
/* The commpage only exists for 32 bit kernels */
#define TARGET_HAS_VALIDATE_GUEST_SPACE
@@ -414,7 +414,6 @@ static int validate_guest_space(unsigned long guest_base,
return 1; /* All good */
}
-#endif
#define ELF_HWCAP get_elf_hwcap()
@@ -427,23 +426,103 @@ static uint32_t get_elf_hwcap(void)
hwcaps |= ARM_HWCAP_ARM_HALF;
hwcaps |= ARM_HWCAP_ARM_THUMB;
hwcaps |= ARM_HWCAP_ARM_FAST_MULT;
- hwcaps |= ARM_HWCAP_ARM_FPA;
/* probe for the extra features */
#define GET_FEATURE(feat, hwcap) \
do { if (arm_feature(&cpu->env, feat)) { hwcaps |= hwcap; } } while (0)
+ /* EDSP is in v5TE and above, but all our v5 CPUs are v5TE */
+ GET_FEATURE(ARM_FEATURE_V5, ARM_HWCAP_ARM_EDSP);
GET_FEATURE(ARM_FEATURE_VFP, ARM_HWCAP_ARM_VFP);
GET_FEATURE(ARM_FEATURE_IWMMXT, ARM_HWCAP_ARM_IWMMXT);
GET_FEATURE(ARM_FEATURE_THUMB2EE, ARM_HWCAP_ARM_THUMBEE);
GET_FEATURE(ARM_FEATURE_NEON, ARM_HWCAP_ARM_NEON);
GET_FEATURE(ARM_FEATURE_VFP3, ARM_HWCAP_ARM_VFPv3);
- GET_FEATURE(ARM_FEATURE_VFP_FP16, ARM_HWCAP_ARM_VFPv3D16);
+ GET_FEATURE(ARM_FEATURE_V6K, ARM_HWCAP_ARM_TLS);
+ GET_FEATURE(ARM_FEATURE_VFP4, ARM_HWCAP_ARM_VFPv4);
+ GET_FEATURE(ARM_FEATURE_ARM_DIV, ARM_HWCAP_ARM_IDIVA);
+ GET_FEATURE(ARM_FEATURE_THUMB_DIV, ARM_HWCAP_ARM_IDIVT);
+ /* All QEMU's VFPv3 CPUs have 32 registers, see VFP_DREG in translate.c.
+ * Note that the ARM_HWCAP_ARM_VFPv3D16 bit is always the inverse of
+ * ARM_HWCAP_ARM_VFPD32 (and so always clear for QEMU); it is unrelated
+ * to our VFP_FP16 feature bit.
+ */
+ GET_FEATURE(ARM_FEATURE_VFP3, ARM_HWCAP_ARM_VFPD32);
+ GET_FEATURE(ARM_FEATURE_LPAE, ARM_HWCAP_ARM_LPAE);
#undef GET_FEATURE
return hwcaps;
}
-#endif
+#else
+/* 64 bit ARM definitions */
+#define ELF_START_MMAP 0x80000000
+
+#define elf_check_arch(x) ((x) == ELF_MACHINE)
+
+#define ELF_ARCH ELF_MACHINE
+#define ELF_CLASS ELFCLASS64
+#define ELF_PLATFORM "aarch64"
+
+static inline void init_thread(struct target_pt_regs *regs,
+ struct image_info *infop)
+{
+ abi_long stack = infop->start_stack;
+ memset(regs, 0, sizeof(*regs));
+
+ regs->pc = infop->entry & ~0x3ULL;
+ regs->sp = stack;
+}
+
+#define ELF_NREG 34
+typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
+
+static void elf_core_copy_regs(target_elf_gregset_t *regs,
+ const CPUARMState *env)
+{
+ int i;
+
+ for (i = 0; i < 32; i++) {
+ (*regs)[i] = tswapreg(env->xregs[i]);
+ }
+ (*regs)[32] = tswapreg(env->pc);
+ (*regs)[33] = tswapreg(pstate_read((CPUARMState *)env));
+}
+
+#define USE_ELF_CORE_DUMP
+#define ELF_EXEC_PAGESIZE 4096
+
+enum {
+ ARM_HWCAP_A64_FP = 1 << 0,
+ ARM_HWCAP_A64_ASIMD = 1 << 1,
+ ARM_HWCAP_A64_EVTSTRM = 1 << 2,
+ ARM_HWCAP_A64_AES = 1 << 3,
+ ARM_HWCAP_A64_PMULL = 1 << 4,
+ ARM_HWCAP_A64_SHA1 = 1 << 5,
+ ARM_HWCAP_A64_SHA2 = 1 << 6,
+ ARM_HWCAP_A64_CRC32 = 1 << 7,
+};
+
+#define ELF_HWCAP get_elf_hwcap()
+
+static uint32_t get_elf_hwcap(void)
+{
+ ARMCPU *cpu = ARM_CPU(thread_cpu);
+ uint32_t hwcaps = 0;
+
+ hwcaps |= ARM_HWCAP_A64_FP;
+ hwcaps |= ARM_HWCAP_A64_ASIMD;
+
+ /* probe for the extra features */
+#define GET_FEATURE(feat, hwcap) \
+ do { if (arm_feature(&cpu->env, feat)) { hwcaps |= hwcap; } } while (0)
+ GET_FEATURE(ARM_FEATURE_V8_AES, ARM_HWCAP_A64_PMULL);
+#undef GET_FEATURE
+
+ return hwcaps;
+}
+
+#endif /* not TARGET_AARCH64 */
+#endif /* TARGET_ARM */
#ifdef TARGET_UNICORE32
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 9864813..2d28bdb 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -7499,6 +7499,22 @@ abi_long do_syscall(void *cpu_env, int num, abi_long
arg1,
ret = get_errno(sys_sched_getaffinity(arg1, mask_size, mask));
if (!is_error(ret)) {
+ if (ret > arg2) {
+ /* More data returned than the caller's buffer will fit.
+ * This only happens if sizeof(abi_long) < sizeof(long)
+ * and the caller passed us a buffer holding an odd number
+ * of abi_longs. If the host kernel is actually using the
+ * extra 4 bytes then fail EINVAL; otherwise we can just
+ * ignore them and only copy the interesting part.
+ */
+ int numcpus = sysconf(_SC_NPROCESSORS_CONF);
+ if (numcpus > arg2 * 8) {
+ ret = -TARGET_EINVAL;
+ break;
+ }
+ ret = arg2;
+ }
+
if (copy_to_user(arg3, mask, ret)) {
goto efault;
}
diff --git a/migration-rdma.c b/migration-rdma.c
index eeb4302..5cd90bd 100644
--- a/migration-rdma.c
+++ b/migration-rdma.c
@@ -1589,13 +1589,11 @@ static int qemu_rdma_post_send_control(RDMAContext
*rdma, uint8_t *buf,
}
- if (ibv_post_send(rdma->qp, &send_wr, &bad_wr)) {
- return -1;
- }
+ ret = ibv_post_send(rdma->qp, &send_wr, &bad_wr);
- if (ret < 0) {
+ if (ret > 0) {
fprintf(stderr, "Failed to use post IB SEND for control!\n");
- return ret;
+ return -ret;
}
ret = qemu_rdma_block_for_wrid(rdma, RDMA_WRID_SEND_CONTROL, NULL);
@@ -2237,10 +2235,6 @@ static void qemu_rdma_cleanup(RDMAContext *rdma)
}
}
- if (rdma->qp) {
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |