diff options
124 files changed, 1588 insertions, 835 deletions
diff --git a/Makefile b/Makefile index 884b59dc06..88bce561a8 100644 --- a/Makefile +++ b/Makefile @@ -112,7 +112,8 @@ endif -include $(SUBDIR_DEVICES_MAK_DEP) %/config-devices.mak: default-configs/%.mak - $(call quiet-command,$(SHELL) $(SRC_PATH)/scripts/make_device_config.sh $@.tmp $<, " GEN $@.tmp") + $(call quiet-command, \ + $(SHELL) $(SRC_PATH)/scripts/make_device_config.sh $< $*-config-devices.mak.d $@ > $@.tmp, " GEN $@.tmp") $(call quiet-command, if test -f $@; then \ if cmp -s $@.old $@; then \ mv $@.tmp $@; \ diff --git a/VERSION b/VERSION index 99572f605e..6f898f54a5 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.2.50 +2.2.90 diff --git a/arch_init.c b/arch_init.c index c3f7d3f56d..fcfa32828d 100644 --- a/arch_init.c +++ b/arch_init.c @@ -895,13 +895,7 @@ static int ram_save_setup(QEMUFile *f, void *opaque) * Count the total number of pages used by ram blocks not including any * gaps due to alignment or unplugs. */ - migration_dirty_pages = 0; - QLIST_FOREACH_RCU(block, &ram_list.blocks, next) { - uint64_t block_pages; - - block_pages = block->used_length >> TARGET_PAGE_BITS; - migration_dirty_pages += block_pages; - } + migration_dirty_pages = ram_bytes_total() >> TARGET_PAGE_BITS; memory_global_dirty_log_start(); migration_bitmap_sync(); diff --git a/backends/tpm.c b/backends/tpm.c index 01860c4acb..4efe36736e 100644 --- a/backends/tpm.c +++ b/backends/tpm.c @@ -36,7 +36,7 @@ void tpm_backend_destroy(TPMBackend *s) { TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s); - return k->ops->destroy(s); + k->ops->destroy(s); } int tpm_backend_init(TPMBackend *s, TPMState *state, diff --git a/block.c b/block.c index 191a847940..0fe97de568 100644 --- a/block.c +++ b/block.c @@ -1065,6 +1065,13 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file, goto free_and_fail; } + if (bs->encrypted) { + error_report("Encrypted images are deprecated"); + error_printf("Support for them will be removed in a future release.\n" + "You can use 'qemu-img convert' to convert your image" + " to an unencrypted one.\n"); + } + ret = refresh_total_sectors(bs, bs->total_sectors); if (ret < 0) { error_setg_errno(errp, -ret, "Could not refresh total sector count"); @@ -3814,15 +3821,6 @@ void bdrv_iterate_format(void (*it)(void *opaque, const char *name), g_free(formats); } -/* This function is to find block backend bs */ -/* TODO convert callers to blk_by_name(), then remove */ -BlockDriverState *bdrv_find(const char *name) -{ - BlockBackend *blk = blk_by_name(name); - - return blk ? blk_bs(blk) : NULL; -} - /* This function is to find a node in the bs graph */ BlockDriverState *bdrv_find_node(const char *node_name) { diff --git a/block/nbd-client.c b/block/nbd-client.c index 259f5a3cb6..e1bb9198c5 100644 --- a/block/nbd-client.c +++ b/block/nbd-client.c @@ -386,8 +386,7 @@ int nbd_client_init(BlockDriverState *bs, int sock, const char *export, logout("session init %s\n", export); qemu_set_block(sock); ret = nbd_receive_negotiate(sock, export, - &client->nbdflags, &client->size, - &client->blocksize, errp); + &client->nbdflags, &client->size, errp); if (ret < 0) { logout("Failed to negotiate with the NBD server\n"); closesocket(sock); diff --git a/block/nbd-client.h b/block/nbd-client.h index fa4ff42d22..e8413408b5 100644 --- a/block/nbd-client.h +++ b/block/nbd-client.h @@ -20,7 +20,6 @@ typedef struct NbdClientSession { int sock; uint32_t nbdflags; off_t size; - size_t blocksize; CoMutex send_mutex; CoMutex free_sema; diff --git a/block/nbd.c b/block/nbd.c index 6634a69664..217618612d 100644 --- a/block/nbd.c +++ b/block/nbd.c @@ -248,7 +248,7 @@ static int nbd_establish_connection(BlockDriverState *bs, Error **errp) /* Failed to establish connection */ if (sock < 0) { logout("Failed to establish connection to NBD server\n"); - return -errno; + return -EIO; } return sock; diff --git a/block/qapi.c b/block/qapi.c index 1808e67336..8a19aed446 100644 --- a/block/qapi.c +++ b/block/qapi.c @@ -414,7 +414,7 @@ BlockStatsList *qmp_query_blockstats(bool has_query_nodes, static char *get_human_readable_size(char *buf, int buf_size, int64_t size) { - static const char suffixes[NB_SUFFIXES] = "KMGT"; + static const char suffixes[NB_SUFFIXES] = {'K', 'M', 'G', 'T'}; int64_t base; int i; diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c index dc8d186a82..6cbae1d205 100644 --- a/block/qcow2-refcount.c +++ b/block/qcow2-refcount.c @@ -466,8 +466,20 @@ static int alloc_refcount_block(BlockDriverState *bs, */ BLKDBG_EVENT(bs->file, BLKDBG_REFTABLE_GROW); - /* Calculate the number of refcount blocks needed so far */ - uint64_t blocks_used = DIV_ROUND_UP(cluster_index, s->refcount_block_size); + /* Calculate the number of refcount blocks needed so far; this will be the + * basis for calculating the index of the first cluster used for the + * self-describing refcount structures which we are about to create. + * + * Because we reached this point, there cannot be any refcount entries for + * cluster_index or higher indices yet. However, because new_block has been + * allocated to describe that cluster (and it will assume this role later + * on), we cannot use that index; also, new_block may actually have a higher + * cluster index than cluster_index, so it needs to be taken into account + * here (and 1 needs to be added to its value because that cluster is used). + */ + uint64_t blocks_used = DIV_ROUND_UP(MAX(cluster_index + 1, + (new_block >> s->cluster_bits) + 1), + s->refcount_block_size); if (blocks_used > QCOW_MAX_REFTABLE_SIZE / sizeof(uint64_t)) { return -EFBIG; diff --git a/block/vpc.c b/block/vpc.c index 1533b6a64d..43e768ee76 100644 --- a/block/vpc.c +++ b/block/vpc.c @@ -46,6 +46,7 @@ enum vhd_type { #define VHD_TIMESTAMP_BASE 946684800 #define VHD_MAX_SECTORS (65535LL * 255 * 255) +#define VHD_MAX_GEOMETRY (65535LL * 16 * 255) // always big-endian typedef struct vhd_footer { @@ -65,7 +66,7 @@ typedef struct vhd_footer { char creator_os[4]; // "Wi2k" uint64_t orig_size; - uint64_t size; + uint64_t current_size; uint16_t cyls; uint8_t heads; @@ -215,13 +216,12 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags, bs->total_sectors = (int64_t) be16_to_cpu(footer->cyls) * footer->heads * footer->secs_per_cyl; - /* images created with disk2vhd report a far higher virtual size - * than expected with the cyls * heads * sectors_per_cyl formula. - * use the footer->size instead if the image was created with - * disk2vhd. - */ - if (!strncmp(footer->creator_app, "d2v", 4)) { - bs->total_sectors = be64_to_cpu(footer->size) / BDRV_SECTOR_SIZE; + /* Images that have exactly the maximum geometry are probably bigger and + * would be truncated if we adhered to the geometry for them. Rely on + * footer->current_size for them. */ + if (bs->total_sectors == VHD_MAX_GEOMETRY) { + bs->total_sectors = be64_to_cpu(footer->current_size) / + BDRV_SECTOR_SIZE; } /* Allow a maximum disk size of approximately 2 TB */ @@ -376,38 +376,6 @@ static inline int64_t get_sector_offset(BlockDriverState *bs, bdrv_pwrite_sync(bs->file, bitmap_offset, bitmap, s->bitmap_size); } -// printf("sector: %" PRIx64 ", index: %x, offset: %x, bioff: %" PRIx64 ", bloff: %" PRIx64 "\n", -// sector_num, pagetable_index, pageentry_index, -// bitmap_offset, block_offset); - -// disabled by reason -#if 0 -#ifdef CACHE - if (bitmap_offset != s->last_bitmap) - { - lseek(s->fd, bitmap_offset, SEEK_SET); - - s->last_bitmap = bitmap_offset; - - // Scary! Bitmap is stored as big endian 32bit entries, - // while we used to look it up byte by byte - read(s->fd, s->pageentry_u8, 512); - for (i = 0; i < 128; i++) - be32_to_cpus(&s->pageentry_u32[i]); - } - - if ((s->pageentry_u8[pageentry_index / 8] >> (pageentry_index % 8)) & 1) - return -1; -#else - lseek(s->fd, bitmap_offset + (pageentry_index / 8), SEEK_SET); - - read(s->fd, &bitmap_entry, 1); - - if ((bitmap_entry >> (pageentry_index % 8)) & 1) - return -1; // not allocated -#endif -#endif - return block_offset; } @@ -602,7 +570,7 @@ static int64_t coroutine_fn vpc_co_get_block_status(BlockDriverState *bs, { BDRVVPCState *s = bs->opaque; VHDFooter *footer = (VHDFooter*) s->footer_buf; - int64_t start, offset, next; + int64_t start, offset; bool allocated; int n; @@ -626,20 +594,18 @@ static int64_t coroutine_fn vpc_co_get_block_status(BlockDriverState *bs, *pnum += n; sector_num += n; nb_sectors -= n; - next = start + (*pnum * BDRV_SECTOR_SIZE); - + /* *pnum can't be greater than one block for allocated + * sectors since there is always a bitmap in between. */ + if (allocated) { + return BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID | start; + } if (nb_sectors == 0) { break; } - offset = get_sector_offset(bs, sector_num, 0); - } while ((allocated && offset == next) || (!allocated && offset == -1)); + } while (offset == -1); - if (allocated) { - return BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID | start; - } else { - return 0; - } + return 0; } /* @@ -659,26 +625,20 @@ static int calculate_geometry(int64_t total_sectors, uint16_t* cyls, { uint32_t cyls_times_heads; - /* Allow a maximum disk size of approximately 2 TB */ - if (total_sectors > 65535LL * 255 * 255) { - return -EFBIG; - } + total_sectors = MIN(total_sectors, VHD_MAX_GEOMETRY); - if (total_sectors > 65535 * 16 * 63) { + if (total_sectors >= 65535LL * 16 * 63) { *secs_per_cyl = 255; - if (total_sectors > 65535 * 16 * 255) { - *heads = 255; - } else { - *heads = 16; - } + *heads = 16; cyls_times_heads = total_sectors / *secs_per_cyl; } else { *secs_per_cyl = 17; cyls_times_heads = total_sectors / *secs_per_cyl; *heads = (cyls_times_heads + 1023) / 1024; - if (*heads < 4) + if (*heads < 4) { *heads = 4; + } if (cyls_times_heads >= (*heads * 1024) || *heads > 16) { *secs_per_cyl = 31; @@ -834,20 +794,28 @@ static int vpc_create(const char *filename, QemuOpts *opts, Error **errp) * Calculate matching total_size and geometry. Increase the number of * sectors requested until we get enough (or fail). This ensures that * qemu-img convert doesn't truncate images, but rather rounds up. + * + * If the image size can't be represented by a spec conform CHS geometry, + * we set the geometry to 65535 x 16 x 255 (CxHxS) sectors and use + * the image size from the VHD footer to calculate total_sectors. */ - total_sectors = total_size / BDRV_SECTOR_SIZE; + total_sectors = MIN(VHD_MAX_GEOMETRY, total_size / BDRV_SECTOR_SIZE); for (i = 0; total_sectors > (int64_t)cyls * heads * secs_per_cyl; i++) { - if (calculate_geometry(total_sectors + i, &cyls, &heads, - &secs_per_cyl)) - { + calculate_geometry(total_sectors + i, &cyls, &heads, &secs_per_cyl); + } + + if ((int64_t)cyls * heads * secs_per_cyl == VHD_MAX_GEOMETRY) { + total_sectors = total_size / BDRV_SECTOR_SIZE; + /* Allow a maximum disk size of approximately 2 TB */ + if (total_sectors > VHD_MAX_SECTORS) { ret = -EFBIG; goto out; } + } else { + total_sectors = (int64_t)cyls * heads * secs_per_cyl; + total_size = total_sectors * BDRV_SECTOR_SIZE; } - total_sectors = (int64_t) cyls * heads * secs_per_cyl; - total_size = total_sectors * BDRV_SECTOR_SIZE; - /* Prepare the Hard Disk Footer */ memset(buf, 0, 1024); @@ -869,7 +837,7 @@ static int vpc_create(const char *filename, QemuOpts *opts, Error **errp) footer->major = cpu_to_be16(0x0005); footer->minor = cpu_to_be16(0x0003); footer->orig_size = cpu_to_be64(total_size); - footer->size = cpu_to_be64(total_size); + footer->current_size = cpu_to_be64(total_size); footer->cyls = cpu_to_be16(cyls); footer->heads = heads; footer->secs_per_cyl = secs_per_cyl; diff --git a/block/write-threshold.c b/block/write-threshold.c index c2cd517716..a53c1f5e65 100644 --- a/block/write-threshold.c +++ b/block/write-threshold.c @@ -112,7 +112,7 @@ void qmp_block_set_write_threshold(const char *node_name, bs = bdrv_find_node(node_name); if (!bs) { - error_set(errp, QERR_DEVICE_NOT_FOUND, node_name); + error_setg(errp, "Device '%s' not found", node_name); return; } diff --git a/blockdev-nbd.c b/blockdev-nbd.c index 22e95d17ee..b29e456f1f 100644 --- a/blockdev-nbd.c +++ b/blockdev-nbd.c @@ -105,7 +105,11 @@ void qmp_nbd_server_add(const char *device, bool has_writable, bool writable, writable = false; } - exp = nbd_export_new(blk, 0, -1, writable ? 0 : NBD_FLAG_READ_ONLY, NULL); + exp = nbd_export_new(blk, 0, -1, writable ? 0 : NBD_FLAG_READ_ONLY, NULL, + errp); + if (!exp) { + return; + } nbd_export_set_name(exp, device); diff --git a/blockdev.c b/blockdev.c index b9c1c0cc1a..0b509854b0 100644 --- a/blockdev.c +++ b/blockdev.c @@ -1016,18 +1016,18 @@ fail: void hmp_commit(Monitor *mon, const QDict *qdict) { const char *device = qdict_get_str(qdict, "device"); - BlockDriverState *bs; + BlockBackend *blk; int ret; if (!strcmp(device, "all")) { ret = bdrv_commit_all(); } else { - bs = bdrv_find(device); - if (!bs) { + blk = blk_by_name(device); + if (!blk) { monitor_printf(mon, "Device '%s' not found\n", device); return; } - ret = bdrv_commit(bs); + ret = bdrv_commit(blk_bs(blk)); } if (ret < 0) { monitor_printf(mon, "'commit' error for '%s': %s\n", device, @@ -1092,17 +1092,20 @@ SnapshotInfo *qmp_blockdev_snapshot_delete_internal_sync(const char *device, const char *name, Error **errp) { - BlockDriverState *bs = bdrv_find(device); + BlockDriverState *bs; + BlockBackend *blk; AioContext *aio_context; QEMUSnapshotInfo sn; Error *local_err = NULL; SnapshotInfo *info = NULL; int ret; - if (!bs) { + blk = blk_by_name(device); + if (!blk) { error_set(errp, QERR_DEVICE_NOT_FOUND, device); return NULL; } + bs = blk_bs(blk); if (!has_id) { id = NULL; @@ -1205,6 +1208,7 @@ static void internal_snapshot_prepare(BlkTransactionState *common, Error *local_err = NULL; const char *device; const char *name; + BlockBackend *blk; BlockDriverState *bs; QEMUSnapshotInfo old_sn, *sn; bool ret; @@ -1223,11 +1227,12 @@ static void internal_snapshot_prepare(BlkTransactionState *common, name = internal->name; /* 2. check for validation */ - bs = bdrv_find(device); - if (!bs) { + blk = blk_by_name(device); + if (!blk) { error_set(errp, QERR_DEVICE_NOT_FOUND, device); return; } + bs = blk_bs(blk); /* AioContext is released in .clean() */ state->aio_context = bdrv_get_aio_context(bs); @@ -1494,17 +1499,19 @@ static void drive_backup_prepare(BlkTransactionState *common, Error **errp) { DriveBackupState *state = DO_UPCAST(DriveBackupState, common, common); BlockDriverState *bs; + BlockBackend *blk; DriveBackup *backup; Error *local_err = NULL; assert(common->action->kind == TRANSACTION_ACTION_KIND_DRIVE_BACKUP); backup = common->action->drive_backup; - bs = bdrv_find(backup->device); - if (!bs) { + blk = blk_by_name(backup->device); + if (!blk) { error_set(errp, QERR_DEVICE_NOT_FOUND, backup->device); return; } + bs = blk_bs(blk); /* AioContext is released in .clean() */ state->aio_context = bdrv_get_aio_context(bs); @@ -1559,22 +1566,25 @@ static void blockdev_backup_prepare(BlkTransactionState *common, Error **errp) BlockdevBackupState *state = DO_UPCAST(BlockdevBackupState, common, common); BlockdevBackup *backup; BlockDriverState *bs, *target; + BlockBackend *blk; Error *local_err = NULL; assert(common->action->kind == TRANSACTION_ACTION_KIND_BLOCKDEV_BACKUP); backup = common->action->blockdev_backup; - bs = bdrv_find(backup->device); - if (!bs) { + blk = blk_by_name(backup->device); + if (!blk) { error_set(errp, QERR_DEVICE_NOT_FOUND, backup->device); return; } + bs = blk_bs(blk); - target = bdrv_find(backup->target); - if (!target) { + blk = blk_by_name(backup->target); + if (!blk) { error_set(errp, QERR_DEVICE_NOT_FOUND, backup->target); return; } + target = blk_bs(blk); /* AioContext is released in .clean() */ state->aio_context = bdrv_get_aio_context(bs); @@ -1881,13 +1891,15 @@ void qmp_block_set_io_throttle(const char *device, int64_t bps, int64_t bps_rd, { ThrottleConfig cfg; BlockDriverState *bs; + BlockBackend *blk; AioContext *aio_context; - bs = bdrv_find(device); - if (!bs) { + blk = blk_by_name(device); + if (!blk) { error_set(errp, QERR_DEVICE_NOT_FOUND, device); return; } + bs = blk_bs(blk); memset(&cfg, 0, sizeof(cfg)); cfg.buckets[THROTTLE_BPS_TOTAL].avg = bps; @@ -2091,6 +2103,7 @@ void qmp_block_stream(const char *device, bool has_on_error, BlockdevOnError on_error, Error **errp) { + BlockBackend *blk; BlockDriverState *bs; BlockDriverState *base_bs = NULL; AioContext *aio_context; @@ -2101,11 +2114,12 @@ void qmp_block_stream(const char *device, on_error = BLOCKDEV_ON_ERROR_REPORT; } - bs = bdrv_find(device); - if (!bs) { + blk = blk_by_name(device); + if (!blk) { error_set(errp, QERR_DEVICE_NOT_FOUND, device); return; } + bs = blk_bs(blk); aio_context = bdrv_get_aio_context(bs); aio_context_acquire(aio_context); @@ -2155,6 +2169,7 @@ void qmp_block_commit(const char *device, bool has_speed, int64_t speed, Error **errp) { + BlockBackend *blk; BlockDriverState *bs; BlockDriverState *base_bs, *top_bs; AioContext *aio_context; @@ -2173,11 +2188,12 @@ void qmp_block_commit(const char *device, * 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) { + blk = blk_by_name(device); + if (!blk) { error_set(errp, QERR_DEVICE_NOT_FOUND, device); return; } + bs = blk_bs(blk); aio_context = bdrv_get_aio_context(bs); aio_context_acquire(aio_context); @@ -2258,6 +2274,7 @@ void qmp_drive_backup(const char *device, const char *target, bool has_on_target_error, BlockdevOnError on_target_error, Error **errp) { + BlockBackend *blk; BlockDriverState *bs; BlockDriverState *target_bs; BlockDriverState *source = NULL; @@ -2281,11 +2298,12 @@ void qmp_drive_backup(const char *device, const char *target, mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS; } - bs = bdrv_find(device); - if (!bs) { + blk = blk_by_name(device); + if (!blk) { error_set(errp, QERR_DEVICE_NOT_FOUND, device); return; } + bs = blk_bs(blk); aio_context = bdrv_get_aio_context(bs); aio_context_acquire(aio_context); @@ -2385,6 +2403,7 @@ void qmp_blockdev_backup(const char *device, const char *target, BlockdevOnError on_target_error, Error **errp) { + BlockBackend *blk; BlockDriverState *bs; BlockDriverState *target_bs; Error *local_err = NULL; @@ -2400,20 +2419,22 @@ void qmp_blockdev_backup(const char *device, const char *target, on_target_error = BLOCKDEV_ON_ERROR_REPORT; } - bs = bdrv_find(device); - if (!bs) { + blk = blk_by_name(device); + if (!blk) { error_set(errp, QERR_DEVICE_NOT_FOUND, device); return; } + bs = blk_bs(blk); aio_context = bdrv_get_aio_context(bs); aio_context_acquire(aio_context); - target_bs = bdrv_find(target); - if (!target_bs) { + blk = blk_by_name(target); + if (!blk) { error_set(errp, QERR_DEVICE_NOT_FOUND, target); goto out; } + target_bs = blk_bs(blk); bdrv_ref(target_bs); bdrv_set_aio_context(target_bs, aio_context); @@ -2442,6 +2463,7 @@ void qmp_drive_mirror(const char *device, const char *target, bool has_on_target_error, BlockdevOnError on_target_error, Error **errp) { + BlockBackend *blk; BlockDriverState *bs; BlockDriverState *source, *target_bs; AioContext *aio_context; @@ -2481,11 +2503,12 @@ void qmp_drive_mirror(const char *device, const char *target, return; } - bs = bdrv_find(device); - if (!bs) { + blk = blk_by_name(device); + if (!blk) { error_set(errp, QERR_DEVICE_NOT_FOUND, device); return; } + bs = blk_bs(blk); aio_context = bdrv_get_aio_context(bs); aio_context_acquire(aio_context); @@ -2623,12 +2646,14 @@ out: static BlockJob *find_block_job(const char *device, AioContext **aio_context, Error **errp) { + BlockBackend *blk; BlockDriverState *bs; - bs = bdrv_find(device); - if (!bs) { + blk = blk_by_name(device); + if (!blk) { goto notfound; } + bs = blk_bs(blk); *aio_context = bdrv_get_aio_context(bs); aio_context_acquire(*aio_context); @@ -2733,6 +2758,7 @@ void qmp_change_backing_file(const char *device, const char *backing_file, Error **errp) { + BlockBackend *blk; BlockDriverState *bs = NULL; AioContext *aio_context; BlockDriverState *image_bs = NULL; @@ -2741,12 +2767,12 @@ void qmp_change_backing_file(const char *device, int open_flags; int ret; - /* find the top layer BDS of the chain */ - bs = bdrv_find(device); - if (!bs) { + blk = blk_by_name(device); + if (!blk) { error_set(errp, QERR_DEVICE_NOT_FOUND, device); return; } + bs = blk_bs(blk); aio_context = bdrv_get_aio_context(bs); aio_context_acquire(aio_context); diff --git a/configure b/configure index b858756afc..589798e49d 100755 --- a/configure +++ b/configure @@ -3119,9 +3119,24 @@ libs_softmmu="$libs_softmmu $fdt_libs" ########################################## # opengl probe (for sdl2, milkymist-tmu2) + +# GLX probe, used by milkymist-tmu2 +# this is temporary, code will be switched to egl mid-term. +cat > $TMPC << EOF +#include <X11/Xlib.h> +#include <GL/gl.h> +#include <GL/glx.h> +int main(void) { glBegin(0); glXQueryVersion(0,0,0); return 0; } +EOF +if compile_prog "" "-lGL -lX11" ; then + have_glx=yes +else + have_glx=no +fi + if test "$opengl" != "no" ; then - opengl_pkgs="gl glx" - if $pkg_config $opengl_pkgs x11; then + opengl_pkgs="gl" + if $pkg_config $opengl_pkgs x11 && test "$have_glx" = "yes"; then opengl_cflags="$($pkg_config --cflags $opengl_pkgs) $x11_cflags" opengl_libs="$($pkg_config --libs $opengl_pkgs) $x11_libs" opengl=yes @@ -5253,7 +5268,9 @@ case "$target_name" in \( "$target_name" = "ppcemb" -a "$cpu" = "ppc64" \) -o \ \( "$target_name" = "mipsel" -a "$cpu" = "mips" \) -o \ \( "$target_name" = "x86_64" -a "$cpu" = "i386" \) -o \ - \( "$target_name" = "i386" -a "$cpu" = "x86_64" \) \) ; then + \( "$target_name" = "i386" -a "$cpu" = "x86_64" \) -o \ + \( "$target_name" = "x86_64" -a "$cpu" = "x32" \) -o \ + \( "$target_name" = "i386" -a "$cpu" = "x32" \) \) ; then echo "CONFIG_KVM=y" >> $config_target_mak if test "$vhost_net" = "yes" ; then echo "CONFIG_VHOST_NET=y" >> $config_target_mak diff --git a/cpus.c b/cpus.c index 1ce90a12e8..314df16190 100644 --- a/cpus.c +++ b/cpus.c @@ -1353,7 +1353,7 @@ static int tcg_cpu_exec(CPUArchState *env) } ret = cpu_exec(env); #ifdef CONFIG_PROFILER - qemu_time += profile_getclock() - ti; + tcg_time += profile_getclock() - ti; #endif if (use_icount) { /* Fold pending instructions back into the diff --git a/disas/cris.c b/disas/cris.c index 9dfb4e3885..e6cff7a765 100644 --- a/disas/cris.c +++ b/disas/cris.c @@ -1210,21 +1210,10 @@ cris_cc_strings[] = "le", "a", /* This is a placeholder. In v0, this would be "ext". In v32, this - is "sb". See cris_conds15. */ + is "sb". */ "wf" }; -/* Different names and semantics for condition 1111 (0xf). */ -const struct cris_cond15 cris_cond15s[] = -{ - /* FIXME: In what version did condition "ext" disappear? */ - {"ext", cris_ver_v0_3}, - {"wf", cris_ver_v10}, - {"sb", cris_ver_v32p}, - {NULL, 0} -}; - - /* * Local variables: * eval: (c-set-style "gnu") diff --git a/exec.c b/exec.c index e97071a3ec..8b922db612 100644 --- a/exec.c +++ b/exec.c @@ -380,7 +380,6 @@ MemoryRegion *address_space_translate(AddressSpace *as, hwaddr addr, IOMMUTLBEntry iotlb; MemoryRegionSection *section; MemoryRegion *mr; - hwaddr len = *plen; rcu_read_lock(); for (;;) { @@ -395,7 +394,7 @@ MemoryRegion *address_space_translate(AddressSpace *as, hwaddr addr, iotlb = mr->iommu_ops->translate(mr, addr, is_write); addr = ((iotlb.translated_addr & ~iotlb.addr_mask) | (addr & iotlb.addr_mask)); - len = MIN(len, (addr | iotlb.addr_mask) - addr + 1); + *plen = MIN(*plen, (addr | iotlb.addr_mask) - addr + 1); if (!(iotlb.perm & (1 << is_write))) { mr = &io_mem_unassigned; break; @@ -406,10 +405,9 @@ MemoryRegion *address_space_translate(AddressSpace *as, hwaddr addr, if (xen_enabled() && memory_access_is_direct(mr, is_write)) { hwaddr page = ((addr & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE) - addr; - len = MIN(page, len); + *plen = MIN(page, *plen); } - *plen = len; *xlat = addr; rcu_read_unlock(); return mr; diff --git a/fsdev/virtfs-proxy-helper.c b/fsdev/virtfs-proxy-helper.c index 13fe032543..a698e2dbb3 100644 --- a/fsdev/virtfs-proxy-helper.c +++ b/fsdev/virtfs-proxy-helper.c @@ -117,7 +117,7 @@ error: static int init_capabilities(void) { - /* helper needs following capbabilities only */ + /* helper needs following capabilities only */ cap_value_t cap_list[] = { CAP_CHOWN, CAP_DAC_OVERRIDE, diff --git a/hmp-commands.hx b/hmp-commands.hx index 9c1e849859..3089533a4f 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -47,7 +47,6 @@ ETEXI .args_type = "", .params = "", .help = "quit the emulator", - .user_print = monitor_user_noop, .mhandler.cmd = hmp_quit, }, @@ -205,7 +204,6 @@ ETEXI STEXI @item change @var{device} @var{setting} @findex change - Change the configuration of a device. @table @option @@ -523,7 +521,6 @@ ETEXI STEXI @item p or print/@var{fmt} @var{expr} @findex print - Print expression value. Only the @var{format} part of @var{fmt} is used. ETEXI @@ -537,6 +534,8 @@ ETEXI }, STEXI +@item i/@var{fmt} @var{addr} [.@var{index}] +@findex i Read I/O port. ETEXI @@ -549,6 +548,8 @@ ETEXI }, STEXI +@item o/@var{fmt} @var{addr} @var{val} +@findex o Write to I/O port. ETEXI @@ -564,7 +565,6 @@ ETEXI STEXI @item sendkey @var{keys} @findex sendkey - Send @var{keys} to the guest. @var{keys} could be the name of the key or the raw value in hexadecimal format. Use @code{-} to press several keys simultaneously. Example: @@ -587,7 +587,6 @@ ETEXI STEXI @item system_reset @findex system_reset - Reset the system. ETEXI @@ -602,7 +601,6 @@ ETEXI STEXI @item system_powerdown @findex system_powerdown - Power down the system (if supported). ETEXI @@ -617,7 +615,6 @@ ETEXI STEXI @item sum @var{addr} @var{size} @findex sum - Compute the checksum of a memory region. ETEXI @@ -632,7 +629,6 @@ ETEXI STEXI @item usb_add @var{devname} @findex usb_add - Add the USB device @var{devname}. For details of available devices see @ref{usb_devices} ETEXI @@ -648,7 +644,6 @@ ETEXI STEXI @item usb_del @var{devname} @findex usb_del - Remove the USB device @var{devname} from the QEMU virtual USB hub. @var{devname} has the syntax @code{bus.addr}. Use the monitor command @code{info usb} to see the devices you can remove. @@ -667,7 +662,6 @@ ETEXI STEXI @item device_add @var{config} @findex device_add - Add device. ETEXI @@ -683,7 +677,6 @@ ETEXI STEXI @item device_del @var{id} @findex device_del - Remove device @var{id}. ETEXI @@ -824,7 +817,6 @@ ETEXI STEXI @item boot_set @var{bootdevicelist} @findex boot_set - Define new values for the boot device list. Those values will override the values specified on the command line through the @code{-boot} option. @@ -1539,9 +1531,9 @@ ETEXI }, STEXI -@item block_set_io_throttle @var{device} @var{bps} @var{bps_rd} @var{bps_wr} @var{iops} @var{iops_rd} @var{iops_wr} -@findex block_set_io_throttle -Change I/O throttle limits for a block drive to @var{bps} @var{bps_rd} @var{bps_wr} @var{iops} @var{iops_rd} @var{iops_wr} +@item block_passwd @var{device} @var{password} +@findex block_passwd +Set the encrypted device @var{device} password to @var{password} ETEXI { @@ -1553,9 +1545,9 @@ ETEXI }, STEXI -@item block_passwd @var{device} @var{password} -@findex block_passwd -Set the encrypted device @var{device} password to @var{password} +@item block_set_io_throttle @var{device} @var{bps} @var{bps_rd} @var{bps_wr} @var{iops} @var{iops_rd} @var{iops_wr} +@findex block_set_io_throttle +Change I/O throttle limits for a block drive to @var{bps} @var{bps_rd} @var{bps_wr} @var{iops} @var{iops_rd} @var{iops_wr} ETEXI { @@ -1569,7 +1561,6 @@ ETEXI STEXI @item set_password [ vnc | spice ] password [ action-if-connected ] @findex set_password - Change spice/vnc password. Use zero to make the password stay valid forever. @var{action-if-connected} specifies what should happen in case a connection is established: @var{fail} makes the password change @@ -1589,7 +1580,6 @@ ETEXI STEXI @item expire_password [ vnc | spice ] expire-time @findex expire_password - Specify when a password for spice/vnc becomes invalid. @var{expire-time} accepts: @@ -1620,9 +1610,8 @@ ETEXI }, STEXI -@item chardev_add args -@findex chardev_add - +@item chardev-add args +@findex chardev-add chardev_add accepts the same parameters as the -chardev command line switch. ETEXI @@ -1637,9 +1626,8 @@ ETEXI }, STEXI -@item chardev_remove id -@findex chardev_remove - +@item chardev-remove id +@findex chardev-remove Removes the chardev @var{id}. ETEXI @@ -1655,7 +1643,6 @@ ETEXI STEXI @item qemu-io @var{device} @var{command} @findex qemu-io - Executes a qemu-io command on the given block device. ETEXI @@ -1670,10 +1657,37 @@ ETEXI STEXI @item cpu-add @var{id} +@findex cpu-add Add CPU with id @var{id} ETEXI { + .name = "qom-list", + .args_type = "path:s?", + .params = "path", + .help = "list QOM properties", + .mhandler.cmd = hmp_qom_list, + }, + +STEXI +@item qom-list [@var{path}] +Print QOM properties of object at location @var{path} +ETEXI + + { + .name = "qom-set", + .args_type = "path:s,property:s,value:s", + .params = "path property value", + .help = "set QOM property", + .mhandler.cmd = hmp_qom_set, + }, + +STEXI +@item qom-set @var{path} @var{property} @var{value} +Set QOM property @var{property} of object at location @var{path} to value @var{value} +ETEXI + + { .name = "info", .args_type = "item:s?", .params = "[subcommand]", @@ -1756,6 +1770,8 @@ show balloon information show device tree @item info qdm show qdev device model list +@item info qom-tree +show object composition tree @item info roms show roms @item info tpm diff --git a/hmp.c b/hmp.c index f6cde86b93..f31ae2796a 100644 --- a/hmp.c +++ b/hmp.c @@ -162,7 +162,8 @@ void hmp_info_migrate(Monitor *mon, const QDict *qdict) } if (info->has_status) { - monitor_printf(mon, "Migration status: %s\n", info->status); + monitor_printf(mon, "Migration status: %s\n", + MigrationStatus_lookup[info->status]); monitor_printf(mon, "total time: %" PRIu64 " milliseconds\n", info->total_time); if (info->has_expected_downtime) { @@ -1123,11 +1124,7 @@ void hmp_migrate_incoming(Monitor *mon, const QDict *qdict) qmp_migrate_incoming(uri, &err); - if (err) { - monitor_printf(mon, "%s\n", error_get_pretty(err)); - error_free(err); - return; - } + hmp_handle_error(mon, &err); } void hmp_migrate_set_downtime(Monitor *mon, const QDict *qdict) @@ -1345,21 +1342,21 @@ void hmp_block_job_complete(Monitor *mon, const QDict *qdict) hmp_handle_error(mon, &error); } -typedef struct MigrationStatus +typedef struct HMPMigrationStatus { QEMUTimer *timer; Monitor *mon; bool is_block_migration; -} MigrationStatus; +} HMPMigrationStatus; static void hmp_migrate_status_cb(void *opaque) { - MigrationStatus *status = opaque; + HMPMigrationStatus *status = opaque; MigrationInfo *info; info = qmp_query_migrate(NULL); - if (!info->has_status || strcmp(info->status, "active") == 0 || - strcmp(info->status, "setup") == 0) { + if (!info->has_status || info->status == MIGRATION_STATUS_ACTIVE || + info->status == MIGRATION_STATUS_SETUP) { if (info->has_disk) { int progress; @@ -1402,7 +1399,7 @@ void hmp_migrate(Monitor *mon, const QDict *qdict) } if (!detach) { - MigrationStatus *status; + HMPMigrationStatus *status; if (monitor_suspend(mon) < 0) { monitor_printf(mon, "terminal does not allow synchronous " @@ -1866,3 +1863,50 @@ void hmp_info_memory_devices(Monitor *mon, const QDict *qdict) qapi_free_MemoryDeviceInfoList(info_list); } + +void hmp_qom_list(Monitor *mon, const QDict *qdict) +{ + const char *path = qdict_get_try_str(qdict, "path"); + ObjectPropertyInfoList *list; + Error *err = NULL; + + if (path == NULL) { + monitor_printf(mon, "/\n"); + return; + } + + list = qmp_qom_list(path, &err); + if (err == NULL) { + ObjectPropertyInfoList *start = list; + while (list != NULL) { + ObjectPropertyInfo *value = list->value; + + monitor_printf(mon, "%s (%s)\n", + value->name, value->type); + list = list->next; + } + qapi_free_ObjectPropertyInfoList(start); + } + hmp_handle_error(mon, &err); +} + +void hmp_qom_set(Monitor *mon, const QDict *qdict) +{ + const char *path = qdict_get_str(qdict, "path"); + const char *property = qdict_get_str(qdict, "property"); + const char *value = qdict_get_str(qdict, "value"); + Error *err = NULL; + bool ambiguous = false; + Object *obj; + + obj = object_resolve_path(path, &ambiguous); + if (obj == NULL) { + error_set(&err, QERR_DEVICE_NOT_FOUND, path); + } else { + if (ambiguous) { + monitor_printf(mon, "Warning: Path '%s' is ambiguous\n", path); + } + object_property_parse(obj, value, property, &err); + } + hmp_handle_error(mon, &err); +} diff --git a/hmp.h b/hmp.h index 371f8d45cd..2b9308be7c 100644 --- a/hmp.h +++ b/hmp.h @@ -96,6 +96,8 @@ void hmp_object_add(Monitor *mon, const QDict *qdict); void hmp_object_del(Monitor *mon, const QDict *qdict); void hmp_info_memdev(Monitor *mon, const QDict *qdict); void hmp_info_memory_devices(Monitor *mon, const QDict *qdict); +void hmp_qom_list(Monitor *mon, const QDict *qdict); +void hmp_qom_set(Monitor *mon, const QDict *qdict); void object_add_completion(ReadLineState *rs, int nb_args, const char *str); void object_del_completion(ReadLineState *rs, int nb_args, const char *str); void device_add_completion(ReadLineState *rs, int nb_args, const char *str); diff --git a/hw/9pfs/virtio-9p-handle.c b/hw/9pfs/virtio-9p-handle.c index 4b79cefd13..13eabb98a4 100644 --- a/hw/9pfs/virtio-9p-handle.c +++ b/hw/9pfs/virtio-9p-handle.c @@ -140,7 +140,7 @@ static int handle_opendir(FsContext *ctx, static void handle_rewinddir(FsContext *ctx, V9fsFidOpenState *fs) { - return rewinddir(fs->dir); + rewinddir(fs->dir); } static off_t handle_telldir(FsContext *ctx, V9fsFidOpenState *fs) @@ -157,7 +157,7 @@ static int handle_readdir_r(FsContext *ctx, V9fsFidOpenState *fs, static void handle_seekdir(FsContext *ctx, V9fsFidOpenState *fs, off_t off) { - return seekdir(fs->dir, off); + seekdir(fs->dir, off); } static ssize_t handle_preadv(FsContext *ctx, V9fsFidOpenState *fs, diff --git a/hw/9pfs/virtio-9p-local.c b/hw/9pfs/virtio-9p-local.c index d6b1c0cdde..f1f2e2573b 100644 --- a/hw/9pfs/virtio-9p-local.c +++ b/hw/9pfs/virtio-9p-local.c @@ -378,7 +378,7 @@ static int local_opendir(FsContext *ctx, static void local_rewinddir(FsContext *ctx, V9fsFidOpenState *fs) { - return rewinddir(fs->dir); + rewinddir(fs->dir); } static off_t local_telldir(FsContext *ctx, V9fsFidOpenState *fs) @@ -409,7 +409,7 @@ again: static void local_seekdir(FsContext *ctx, V9fsFidOpenState *fs, off_t off) { - return seekdir(fs->dir, off); + seekdir(fs->dir, off); } static ssize_t local_preadv(FsContext *ctx, V9fsFidOpenState *fs, diff --git a/hw/9pfs/virtio-9p-proxy.c b/hw/9pfs/virtio-9p-proxy.c index 71b6198bbd..1bc7881f03 100644 --- a/hw/9pfs/virtio-9p-proxy.c +++ b/hw/9pfs/virtio-9p-proxy.c @@ -669,7 +669,7 @@ static int proxy_opendir(FsContext *ctx, static void proxy_rewinddir(FsContext *ctx, V9fsFidOpenState *fs) { - return rewinddir(fs->dir); + rewinddir(fs->dir); } static off_t proxy_telldir(FsContext *ctx, V9fsFidOpenState *fs) @@ -686,7 +686,7 @@ static int proxy_readdir_r(FsContext *ctx, V9fsFidOpenState *fs, static void proxy_seekdir(FsContext *ctx, V9fsFidOpenState *fs, off_t off) { - return seekdir(fs->dir, off); + seekdir(fs->dir, off); } static ssize_t proxy_preadv(FsContext *ctx, V9fsFidOpenState *fs, diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c index 5861a5b826..4964da0d7e 100644 --- a/hw/9pfs/virtio-9p.c +++ b/hw/9pfs/virtio-9p.c @@ -1950,7 +1950,8 @@ static void v9fs_write(void *opaque) err = pdu_unmarshal(pdu, offset, "dqd", &fid, &off, &count); if (err < 0) { - return complete_pdu(s, pdu, err); + complete_pdu(s, pdu, err); + return; } offset += err; v9fs_init_qiov_from_pdu(&qiov_full, pdu, offset, count, true); diff --git a/hw/arm/digic_boards.c b/hw/arm/digic_boards.c index 7114c36e38..e576646e86 100644 --- a/hw/arm/digic_boards.c +++ b/hw/arm/digic_boards.c @@ -113,6 +113,7 @@ static void digic_load_rom(DigicBoardState *s, hwaddr addr, error_report("Couldn't load rom image '%s'.", filename); exit(1); } + g_free(fn); } } diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c index a92cdc3322..ddd10dc26f 100644 --- a/hw/arm/highbank.c +++ b/hw/arm/highbank.c @@ -282,6 +282,7 @@ static void calxeda_init(MachineState *machine, enum cxmachines machine_id) if (load_image_targphys("sysram.bin", 0xfff88000, filesize) < 0) { hw_error("Unable to load %s\n", bios_name); } + g_free(sysboot_filename); } else { hw_error("Unable to find %s\n", bios_name); } diff --git a/hw/arm/nseries.c b/hw/arm/nseries.c index 4d7be5e740..2a5406d98d 100644 --- a/hw/arm/nseries.c +++ b/hw/arm/nseries.c @@ -1403,12 +1403,12 @@ static struct arm_boot_info n810_binfo = { static void n800_init(MachineState *machine) { - return n8x0_init(machine, &n800_binfo, 800); + n8x0_init(machine, &n800_binfo, 800); } static void n810_init(MachineState *machine) { - return n8x0_init(machine, &n810_binfo, 810); + n8x0_init(machine, &n810_binfo, 810); } static QEMUMachine n800_machine = { diff --git a/hw/arm/omap1.c b/hw/arm/omap1.c index abb183c2d5..061504495d 100644 --- a/hw/arm/omap1.c +++ b/hw/arm/omap1.c @@ -207,7 +207,8 @@ static void omap_mpu_timer_write(void *opaque, hwaddr addr, struct omap_mpu_timer_s *s = (struct omap_mpu_timer_s *) opaque; if (size != 4) { - return omap_badwidth_write32(opaque, addr, value); + omap_badwidth_write32(opaque, addr, value); + return; } switch (addr) { @@ -314,7 +315,8 @@ static void omap_wd_timer_write(void *opaque, hwaddr addr, struct omap_watchdog_timer_s *s = (struct omap_watchdog_timer_s *) opaque; if (size != 2) { - return omap_badwidth_write16(opaque, addr, value); + omap_badwidth_write16(opaque, addr, value); + return; } switch (addr) { @@ -440,7 +442,8 @@ static void omap_os_timer_write(void *opaque, hwaddr addr, int offset = addr & OMAP_MPUI_REG_MASK; if (size != 4) { - return omap_badwidth_write32(opaque, addr, value); + omap_badwidth_write32(opaque, addr, value); + return; } switch (offset) { @@ -585,7 +588,8 @@ static void omap_ulpd_pm_write(void *opaque, hwaddr addr, uint16_t diff; if (size != 2) { - return omap_badwidth_write16(opaque, addr, value); + omap_badwidth_write16(opaque, addr, value); + return; } switch (addr) { @@ -857,7 +861,8 @@ static void omap_pin_cfg_write(void *opaque, hwaddr addr, uint32_t diff; if (size != 4) { - return omap_badwidth_write32(opaque, addr, value); + omap_badwidth_write32(opaque, addr, value); + return; } switch (addr) { @@ -1012,7 +1017,8 @@ static void omap_id_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { if (size != 4) { - return omap_badwidth_write32(opaque, addr, value); + omap_badwidth_write32(opaque, addr, value); + return; } OMAP_BAD_REG(addr); @@ -1081,7 +1087,8 @@ static void omap_mpui_write(void *opaque, hwaddr addr, struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque; if (size != 4) { - return omap_badwidth_write32(opaque, addr, value); + omap_badwidth_write32(opaque, addr, value); + return; } switch (addr) { @@ -1175,7 +1182,8 @@ static void omap_tipb_bridge_write(void *opaque, hwaddr addr, struct omap_tipb_bridge_s *s = (struct omap_tipb_bridge_s *) opaque; if (size < 2) { - return omap_badwidth_write16(opaque, addr, value); + omap_badwidth_write16(opaque, addr, value); + return; } switch (addr) { @@ -1284,7 +1292,8 @@ static void omap_tcmi_write(void *opaque, hwaddr addr, struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque; if (size != 4) { - return omap_badwidth_write32(opaque, addr, value); + omap_badwidth_write32(opaque, addr, value); + return; } switch (addr) { @@ -1379,7 +1388,8 @@ static void omap_dpll_write(void *opaque, hwaddr addr, int div, mult; if (size != 2) { - return omap_badwidth_write16(opaque, addr, value); + omap_badwidth_write16(opaque, addr, value); + return; } if (addr == 0x00) { /* CTL_REG */ @@ -1647,7 +1657,8 @@ static void omap_clkm_write(void *opaque, hwaddr addr, }; if (size != 2) { - return omap_badwidth_write16(opaque, addr, value); + omap_badwidth_write16(opaque, addr, value); + return; } switch (addr) { @@ -1775,7 +1786,8 @@ static void omap_clkdsp_write(void *opaque, hwaddr addr, uint16_t diff; if (size != 2) { - return omap_badwidth_write16(opaque, addr, value); + omap_badwidth_write16(opaque, addr, value); + return; } switch (addr) { @@ -1982,7 +1994,8 @@ static void omap_mpuio_write(void *opaque, hwaddr addr, int ln; if (size != 2) { - return omap_badwidth_write16(opaque, addr, value); + omap_badwidth_write16(opaque, addr, value); + return; } switch (offset) { @@ -2210,7 +2223,8 @@ static void omap_uwire_write(void *opaque, hwaddr addr, int offset = addr & OMAP_MPUI_REG_MASK; if (size != 2) { - return omap_badwidth_write16(opaque, addr, value); + omap_badwidth_write16(opaque, addr, value); + return; } switch (offset) { @@ -2349,7 +2363,8 @@ static void omap_pwl_write(void *opaque, hwaddr addr, int offset = addr & OMAP_MPUI_REG_MASK; if (size != 1) { - return omap_badwidth_write8(opaque, addr, value); + omap_badwidth_write8(opaque, addr, value); + return; } switch (offset) { @@ -2444,7 +2459,8 @@ static void omap_pwt_write(void *opaque, hwaddr addr, int offset = addr & OMAP_MPUI_REG_MASK; if (size != 1) { - return omap_badwidth_write8(opaque, addr, value); + omap_badwidth_write8(opaque, addr, value); + return; } switch (offset) { @@ -2637,7 +2653,8 @@ static void omap_rtc_write(void *opaque, hwaddr addr, time_t ti[2]; if (size != 1) { - return omap_badwidth_write8(opaque, addr, value); + omap_badwidth_write8(opaque, addr, value); + return; } switch (offset) { @@ -3410,9 +3427,14 @@ static void omap_mcbsp_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { switch (size) { - case 2: return omap_mcbsp_writeh(opaque, addr, value); - case 4: return omap_mcbsp_writew(opaque, addr, value); - default: return omap_badwidth_write16(opaque, addr, value); + case 2: + omap_mcbsp_writeh(opaque, addr, value); + break; + case 4: + omap_mcbsp_writew(opaque, addr, value); + break; + default: + omap_badwidth_write16(opaque, addr, value); } } @@ -3586,7 +3608,8 @@ static void omap_lpg_write(void *opaque, hwaddr addr, int offset = addr & OMAP_MPUI_REG_MASK; if (size != 1) { - return omap_badwidth_write8(opaque, addr, value); + omap_badwidth_write8(opaque, addr, value); + return; } switch (offset) { diff --git a/hw/arm/omap2.c b/hw/arm/omap2.c index b083ebebc8..32390140c0 100644 --- a/hw/arm/omap2.c +++ b/hw/arm/omap2.c @@ -447,7 +447,8 @@ static void omap_eac_write(void *opaque, hwaddr addr, struct omap_eac_s *s = (struct omap_eac_s *) opaque; if (size != 2) { - return omap_badwidth_write16(opaque, addr, value); + omap_badwidth_write16(opaque, addr, value); + return; } switch (addr) { @@ -692,7 +693,8 @@ static void omap_sti_write(void *opaque, hwaddr addr, struct omap_sti_s *s = (struct omap_sti_s *) opaque; if (size != 4) { - return omap_badwidth_write32(opaque, addr, value); + omap_badwidth_write32(opaque, addr, value); + return; } switch (addr) { @@ -757,7 +759,8 @@ static void omap_sti_fifo_write(void *opaque, hwaddr addr, uint8_t byte = value; if (size != 1) { - return omap_badwidth_write8(opaque, addr, size); + omap_badwidth_write8(opaque, addr, size); + return; } if (ch == STI_TRACE_CONTROL_CHANNEL) { @@ -1359,7 +1362,8 @@ static void omap_prcm_write(void *opaque, hwaddr addr, struct omap_prcm_s *s = (struct omap_prcm_s *) opaque; if (size != 4) { - return omap_badwidth_write32(opaque, addr, value); + omap_badwidth_write32(opaque, addr, value); + return; } switch (addr) { diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c index 8496c1622a..e9a7cede64 100644 --- a/hw/arm/vexpress.c +++ b/hw/arm/vexpress.c @@ -562,7 +562,7 @@ static void vexpress_common_init(MachineState *machine) * If a bios file was provided, attempt to map it into memory */ if (bios_name) { - const char *fn; + char *fn; if (drive_get(IF_PFLASH, 0, 0)) { error_report("The contents of the first flash device may be " @@ -576,6 +576,7 @@ static void vexpress_common_init(MachineState *machine) error_report("Could not load ROM image '%s'", bios_name); exit(1); } + g_free(fn); } /* Motherboard peripherals: the wiring is the same but the diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 9072bc2b1c..b652b07ced 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -552,7 +552,7 @@ static void create_flash(const VirtBoardInfo *vbi) char *nodename; if (bios_name) { - const char *fn; + char *fn; if (drive_get(IF_PFLASH, 0, 0)) { error_report("The contents of the first flash device may be " @@ -565,6 +565,7 @@ static void create_flash(const VirtBoardInfo *vbi) error_report("Could not load ROM image '%s'", bios_name); exit(1); } + g_free(fn); } create_one_flash("virt.flash0", flashbase, flashsize); @@ -770,7 +771,7 @@ static void machvirt_init(MachineState *machine) cc->parse_features(CPU(cpuobj), cpuopts, &err); g_free(cpuopts); if (err) { - error_report("%s", error_get_pretty(err)); + error_report_err(err); exit(1); } diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c index 7044b357dc..a5dc2a4366 100644 --- a/hw/char/cadence_uart.c +++ b/hw/char/cadence_uart.c @@ -476,18 +476,12 @@ static void cadence_uart_reset(DeviceState *dev) uart_update_status(s); } -static int cadence_uart_init(SysBusDevice *dev) +static void cadence_uart_realize(DeviceState *dev, Error **errp) { UartState *s = CADENCE_UART(dev); - memory_region_init_io(&s->iomem, OBJECT(s), &uart_ops, s, "uart", 0x1000); - sysbus_init_mmio(dev, &s->iomem); - sysbus_init_irq(dev, &s->irq); - s->fifo_trigger_handle = timer_new_ns(QEMU_CLOCK_VIRTUAL, - (QEMUTimerCB *)fifo_trigger_update, s); - - s->char_tx_time = (get_ticks_per_sec() / 9600) * 10; + fifo_trigger_update, s); s->chr = qemu_char_get_next_serial(); @@ -495,8 +489,18 @@ static int cadence_uart_init(SysBusDevice *dev) qemu_chr_add_handlers(s->chr, uart_can_receive, uart_receive, uart_event, s); } +} - return 0; +static void cadence_uart_init(Object *obj) +{ + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + UartState *s = CADENCE_UART(obj); + + memory_region_init_io(&s->iomem, obj, &uart_ops, s, "uart", 0x1000); + sysbus_init_mmio(sbd, &s->iomem); + sysbus_init_irq(sbd, &s->irq); + + s->char_tx_time = (get_ticks_per_sec() / 9600) * 10; } static int cadence_uart_post_load(void *opaque, int version_id) @@ -528,9 +532,8 @@ static const VMStateDescription vmstate_cadence_uart = { static void cadence_uart_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass); - sdc->init = cadence_uart_init; + dc->realize = cadence_uart_realize; dc->vmsd = &vmstate_cadence_uart; dc->reset = cadence_uart_reset; } @@ -539,6 +542,7 @@ static const TypeInfo cadence_uart_info = { .name = TYPE_CADENCE_UART, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(UartState), + .instance_init = cadence_uart_init, .class_init = cadence_uart_class_init, }; diff --git a/hw/char/omap_uart.c b/hw/char/omap_uart.c index 0b91693602..88f20943e4 100644 --- a/hw/char/omap_uart.c +++ b/hw/char/omap_uart.c @@ -112,7 +112,8 @@ static void omap_uart_write(void *opaque, hwaddr addr, struct omap_uart_s *s = (struct omap_uart_s *) opaque; if (size == 4) { - return omap_badwidth_write8(opaque, addr, value); + omap_badwidth_write8(opaque, addr, value); + return; } switch (addr) { diff --git a/hw/core/loader.c b/hw/core/loader.c index 76d8acace9..d4c441fd18 100644 --- a/hw/core/loader.c +++ b/hw/core/loader.c @@ -267,7 +267,7 @@ int load_aout(const char *filename, hwaddr addr, int max_sz, /* ELF loader */ -static void *load_at(int fd, int offset, int size) +static void *load_at(int fd, off_t offset, size_t size) { void *ptr; if (lseek(fd, offset, SEEK_SET) < 0) diff --git a/hw/core/qdev.c b/hw/core/qdev.c index 6be58669f7..6e6a65d49b 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -501,8 +501,9 @@ void qdev_connect_gpio_out_named(DeviceState *dev, const char *name, int n, * with an error without doing anything. If it has none, it will * never fail. So we can just call it with a NULL Error pointer. */ - object_property_add_child(qdev_get_machine(), "non-qdev-gpio[*]", - OBJECT(pin), NULL); + object_property_add_child(container_get(qdev_get_machine(), + "/unattached"), + "non-qdev-gpio[*]", OBJECT(pin), NULL); } object_property_set_link(OBJECT(dev), OBJECT(pin), propname, &error_abort); g_free(propname); diff --git a/hw/display/omap_dss.c b/hw/display/omap_dss.c index 24ccbcc7a1..f1fef2767e 100644 --- a/hw/display/omap_dss.c +++ b/hw/display/omap_dss.c @@ -212,7 +212,8 @@ static void omap_diss_write(void *opaque, hwaddr addr, struct omap_dss_s *s = (struct omap_dss_s *) opaque; if (size != 4) { - return omap_badwidth_write32(opaque, addr, value); + omap_badwidth_write32(opaque, addr, value); + return; } switch (addr) { @@ -377,7 +378,8 @@ static void omap_disc_write(void *opaque, hwaddr addr, struct omap_dss_s *s = (struct omap_dss_s *) opaque; if (size != 4) { - return omap_badwidth_write32(opaque, addr, value); + omap_badwidth_write32(opaque, addr, value); + return; } switch (addr) { @@ -736,7 +738,8 @@ static void omap_rfbi_write(void *opaque, hwaddr addr, struct omap_dss_s *s = (struct omap_dss_s *) opaque; if (size != 4) { - return omap_badwidth_write32(opaque, addr, value); + omap_badwidth_write32(opaque, addr, value); + return; } switch (addr) { @@ -928,7 +931,8 @@ static void omap_venc_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { if (size != 4) { - return omap_badwidth_write32(opaque, addr, size); + omap_badwidth_write32(opaque, addr, size); + return; } switch (addr) { @@ -1016,7 +1020,8 @@ static void omap_im3_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { if (size != 4) { - return omap_badwidth_write32(opaque, addr, value); + omap_badwidth_write32(opaque, addr, value); + return; } switch (addr) { diff --git a/hw/display/vga.c b/hw/display/vga.c index c0f7b343bb..d1d296c74e 100644 --- a/hw/display/vga.c +++ b/hw/display/vga.c @@ -1997,7 +1997,7 @@ static void vga_mem_write(void *opaque, hwaddr addr, { VGACommonState *s = opaque; - return vga_mem_writeb(s, addr, data); + vga_mem_writeb(s, addr, data); } const MemoryRegionOps vga_mem_ops = { diff --git a/hw/dma/omap_dma.c b/hw/dma/omap_dma.c index 756a87acb8..97c57a03c0 100644 --- a/hw/dma/omap_dma.c +++ b/hw/dma/omap_dma.c @@ -136,7 +136,7 @@ struct omap_dma_s { static inline void omap_dma_interrupts_update(struct omap_dma_s *s) { - return s->intr_update(s); + s->intr_update(s); } static void omap_dma_channel_load(struct omap_dma_channel_s *ch) @@ -1502,7 +1502,8 @@ static void omap_dma_write(void *opaque, hwaddr addr, int reg, ch; if (size != 2) { - return omap_badwidth_write16(opaque, addr, value); + omap_badwidth_write16(opaque, addr, value); + return; } switch (addr) { @@ -1857,7 +1858,8 @@ static void omap_dma4_write(void *opaque, hwaddr addr, struct omap_dma_channel_s *ch; if (size == 1) { - return omap_badwidth_write16(opaque, addr, value); + omap_badwidth_write16(opaque, addr, value); + return; } switch (addr) { diff --git a/hw/gpio/omap_gpio.c b/hw/gpio/omap_gpio.c index 938782a45d..9a43486890 100644 --- a/hw/gpio/omap_gpio.c +++ b/hw/gpio/omap_gpio.c @@ -113,7 +113,8 @@ static void omap_gpio_write(void *opaque, hwaddr addr, int ln; if (size != 2) { - return omap_badwidth_write16(opaque, addr, value); + omap_badwidth_write16(opaque, addr, value); + return; } switch (offset) { diff --git a/hw/i386/pc.c b/hw/i386/pc.c index b5b2aadb52..4b46c299c3 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -45,6 +45,7 @@ #include "sysemu/sysemu.h" #include "sysemu/numa.h" #include "sysemu/kvm.h" +#include "sysemu/qtest.h" #include "kvm_i386.h" #include "hw/xen/xen.h" #include "sysemu/block-backend.h" @@ -653,7 +654,7 @@ static uint32_t x86_cpu_apic_id_from_index(unsigned int cpu_index) correct_id = x86_apicid_from_cpu_idx(smp_cores, smp_threads, cpu_index); if (compat_apic_id_mode) { - if (cpu_index != correct_id && !warned) { + if (cpu_index != correct_id && !warned && !qtest_enabled()) { error_report("APIC IDs set in compatibility mode, " "CPU topology won't match the configuration"); warned = true; @@ -992,18 +993,26 @@ void pc_acpi_smi_interrupt(void *opaque, int irq, int level) static X86CPU *pc_new_cpu(const char *cpu_model, int64_t apic_id, DeviceState *icc_bridge, Error **errp) { - X86CPU *cpu; + X86CPU *cpu = NULL; Error *local_err = NULL; - cpu = cpu_x86_create(cpu_model, icc_bridge, &local_err); + if (icc_bridge == NULL) { + error_setg(&local_err, "Invalid icc-bridge value"); + goto out; + } + + cpu = cpu_x86_create(cpu_model, &local_err); if (local_err != NULL) { - error_propagate(errp, local_err); - return NULL; + goto out; } + qdev_set_parent_bus(DEVICE(cpu), qdev_get_child_bus(icc_bridge, "icc")); + object_unref(OBJECT(cpu)); + object_property_set_int(OBJECT(cpu), apic_id, "apic-id", &local_err); object_property_set_bool(OBJECT(cpu), true, "realized", &local_err); +out: if (local_err) { error_propagate(errp, local_err); object_unref(OBJECT(cpu)); diff --git a/hw/i386/smbios.c b/hw/i386/smbios.c index f2e9ab62ce..1341e02344 100644 --- a/hw/i386/smbios.c +++ b/hw/i386/smbios.c @@ -91,6 +91,7 @@ static struct { static struct { const char *loc_pfx, *bank, *manufacturer, *serial, *asset, *part; + uint16_t speed; } type17; static QemuOptsList qemu_smbios_opts = { @@ -304,6 +305,10 @@ static const QemuOptDesc qemu_smbios_type17_opts[] = { .name = "part", .type = QEMU_OPT_STRING, .help = "part number", + },{ + .name = "speed", + .type = QEMU_OPT_NUMBER, + .help = "maximum capable speed", }, { /* end of list */ } }; @@ -697,13 +702,13 @@ static void smbios_build_type_17_table(unsigned instance, uint64_t size) SMBIOS_TABLE_SET_STR(17, bank_locator_str, type17.bank); t->memory_type = 0x07; /* RAM */ t->type_detail = cpu_to_le16(0x02); /* Other */ - t->speed = cpu_to_le16(0); /* Unknown */ + t->speed = cpu_to_le16(type17.speed); SMBIOS_TABLE_SET_STR(17, manufacturer_str, type17.manufacturer); SMBIOS_TABLE_SET_STR(17, serial_number_str, type17.serial); SMBIOS_TABLE_SET_STR(17, asset_tag_number_str, type17.asset); SMBIOS_TABLE_SET_STR(17, part_number_str, type17.part); t->attributes = 0; /* Unknown */ - t->configured_clock_speed = cpu_to_le16(0); /* Unknown */ + t->configured_clock_speed = t->speed; /* reuse value for max speed */ t->minimum_voltage = cpu_to_le16(0); /* Unknown */ t->maximum_voltage = cpu_to_le16(0); /* Unknown */ t->configured_voltage = cpu_to_le16(0); /* Unknown */ @@ -1083,6 +1088,7 @@ void smbios_entry_add(QemuOpts *opts) save_opt(&type17.serial, opts, "serial"); save_opt(&type17.asset, opts, "asset"); save_opt(&type17.part, opts, "part"); + type17.speed = qemu_opt_get_number(opts, "speed", 0); return; default: error_report("Don't know how to build fields for SMBIOS type %ld", diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c index 270ce05b58..a04c822832 100644 --- a/hw/intc/arm_gic.c +++ b/hw/intc/arm_gic.c @@ -704,7 +704,8 @@ static void gic_cpu_write(GICState *s, int cpu, int offset, uint32_t value) s->bpr[cpu] = (value & 0x7); break; case 0x10: /* End Of Interrupt */ - return gic_complete_irq(s, cpu, value & 0x3ff); + gic_complete_irq(s, cpu, value & 0x3ff); + return; case 0x1c: /* Aliased Binary Point */ if (s->revision >= 2) { s->abpr[cpu] = (value & 0x7); diff --git a/hw/intc/etraxfs_pic.c b/hw/intc/etraxfs_pic.c index 636262b49f..bd588681ef 100644 --- a/hw/intc/etraxfs_pic.c +++ b/hw/intc/etraxfs_pic.c @@ -131,11 +131,13 @@ static void nmi_handler(void *opaque, int irq, int level) } static void irq_handler(void *opaque, int irq, int level) -{ +{ struct etrax_pic *fs = (void *)opaque; - if (irq >= 30) - return nmi_handler(opaque, irq, level); + if (irq >= 30) { + nmi_handler(opaque, irq, level); + return; + } irq -= 1; fs->regs[R_R_VECT] &= ~(1 << irq); diff --git a/hw/mem/pc-dimm.c b/hw/mem/pc-dimm.c index de81b9ceab..39f0c97c0c 100644 --- a/hw/mem/pc-dimm.c +++ b/hw/mem/pc-dimm.c @@ -351,6 +351,7 @@ static void pc_dimm_class_init(ObjectClass *oc, void *data) dc->realize = pc_dimm_realize; dc->props = pc_dimm_properties; + dc->desc = "DIMM memory module"; ddc->get_memory_region = pc_dimm_get_memory_region; } diff --git a/hw/misc/omap_gpmc.c b/hw/misc/omap_gpmc.c index a0de52f9bf..74fc91c8e9 100644 --- a/hw/misc/omap_gpmc.c +++ b/hw/misc/omap_gpmc.c @@ -624,7 +624,8 @@ static void omap_gpmc_write(void *opaque, hwaddr addr, struct omap_gpmc_cs_file_s *f; if (size != 4 && gpmc_wordaccess_only(addr)) { - return omap_badwidth_write32(opaque, addr, value); + omap_badwidth_write32(opaque, addr, value); + return; } switch (addr) { diff --git a/hw/misc/omap_l4.c b/hw/misc/omap_l4.c index f2372500c0..245ceac84c 100644 --- a/hw/misc/omap_l4.c +++ b/hw/misc/omap_l4.c @@ -82,7 +82,8 @@ static void omap_l4ta_write(void *opaque, hwaddr addr, struct omap_target_agent_s *s = (struct omap_target_agent_s *) opaque; if (size != 4) { - return omap_badwidth_write32(opaque, addr, value); + omap_badwidth_write32(opaque, addr, value); + return; } switch (addr) { diff --git a/hw/misc/omap_sdrc.c b/hw/misc/omap_sdrc.c index ed62caf03f..3de0c0e9d0 100644 --- a/hw/misc/omap_sdrc.c +++ b/hw/misc/omap_sdrc.c @@ -92,7 +92,8 @@ static void omap_sdrc_write(void *opaque, hwaddr addr, struct omap_sdrc_s *s = (struct omap_sdrc_s *) opaque; if (size != 4) { - return omap_badwidth_write32(opaque, addr, value); + omap_badwidth_write32(opaque, addr, value); + return; } switch (addr) { diff --git a/hw/misc/omap_tap.c b/hw/misc/omap_tap.c index 9d2b71014c..6f02bb9e4c 100644 --- a/hw/misc/omap_tap.c +++ b/hw/misc/omap_tap.c @@ -95,7 +95,8 @@ static void omap_tap_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { if (size != 4) { - return omap_badwidth_write32(opaque, addr, value); + omap_badwidth_write32(opaque, addr, value); + return; } OMAP_BAD_REG(addr); diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c index 78a37be42b..4caf5364da 100644 --- a/hw/nvram/fw_cfg.c +++ b/hw/nvram/fw_cfg.c @@ -472,7 +472,7 @@ void fw_cfg_add_string(FWCfgState *s, uint16_t key, const char *value) { size_t sz = strlen(value) + 1; - return fw_cfg_add_bytes(s, key, g_memdup(value, sz), sz); + fw_cfg_add_bytes(s, key, g_memdup(value, sz), sz); } void fw_cfg_add_i16(FWCfgState *s, uint16_t key, uint16_t value) diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c index 1abbbb192e..1463e65b5d 100644 --- a/hw/pci/pcie.c +++ b/hw/pci/pcie.c @@ -84,7 +84,7 @@ int pcie_cap_init(PCIDevice *dev, uint8_t offset, uint8_t type, uint8_t port) pci_set_long(exp_cap + PCI_EXP_DEVCAP2, PCI_EXP_DEVCAP2_EFF | PCI_EXP_DEVCAP2_EETLPP); - pci_set_word(dev->wmask + pos, PCI_EXP_DEVCTL2_EETLPPB); + pci_set_word(dev->wmask + pos + PCI_EXP_DEVCTL2, PCI_EXP_DEVCTL2_EETLPPB); return pos; } diff --git a/hw/pci/pcie_aer.c b/hw/pci/pcie_aer.c index 5a25c32a3d..eaa3e6ea94 100644 --- a/hw/pci/pcie_aer.c +++ b/hw/pci/pcie_aer.c @@ -123,7 +123,7 @@ int pcie_aer_init(PCIDevice *dev, uint16_t offset) PCI_ERR_UNC_SUPPORTED); pci_long_test_and_set_mask(dev->w1cmask + offset + PCI_ERR_COR_STATUS, - PCI_ERR_COR_STATUS); + PCI_ERR_COR_SUPPORTED); pci_set_long(dev->config + offset + PCI_ERR_COR_MASK, PCI_ERR_COR_MASK_DEFAULT); @@ -433,7 +433,7 @@ static void pcie_aer_update_log(PCIDevice *dev, const PCIEAERErr *err) } if ((err->flags & PCIE_AER_ERR_TLP_PREFIX_PRESENT) && - (pci_get_long(dev->config + dev->exp.exp_cap + PCI_EXP_DEVCTL2) & + (pci_get_long(dev->config + dev->exp.exp_cap + PCI_EXP_DEVCAP2) & PCI_EXP_DEVCAP2_EETLPP)) { for (i = 0; i < ARRAY_SIZE(err->prefix); ++i) { /* 7.10.12 tlp prefix log register */ @@ -618,12 +618,12 @@ static bool pcie_aer_inject_uncor_error(PCIEAERInject *inj, bool is_fatal) * non-Function specific error must be recorded in all functions. * It is the responsibility of the caller of this function. * It is also caller's responsibility to determine which function should - * report the rerror. + * report the error. * * 6.2.4 Error Logging - * 6.2.5 Sqeunce of Device Error Signaling and Logging Operations - * table 6-2: Flowchard Showing Sequence of Device Error Signaling and Logging - * Operations + * 6.2.5 Sequence of Device Error Signaling and Logging Operations + * Figure 6-2: Flowchart Showing Sequence of Device Error Signaling and Logging + * Operations */ int pcie_aer_inject_error(PCIDevice *dev, const PCIEAERErr *err) { diff --git a/hw/scsi/virtio-scsi-dataplane.c b/hw/scsi/virtio-scsi-dataplane.c index 3f40ff090f..c069cd764c 100644 --- a/hw/scsi/virtio-scsi-dataplane.c +++ b/hw/scsi/virtio-scsi-dataplane.c @@ -45,7 +45,7 @@ static VirtIOSCSIVring *virtio_scsi_vring_init(VirtIOSCSI *s, { BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(s))); VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); - VirtIOSCSIVring *r = g_slice_new(VirtIOSCSIVring); + VirtIOSCSIVring *r; int rc; /* Set up virtqueue notify */ @@ -56,6 +56,8 @@ static VirtIOSCSIVring *virtio_scsi_vring_init(VirtIOSCSI *s, s->dataplane_fenced = true; return NULL; } + + r = g_slice_new(VirtIOSCSIVring); r->host_notifier = *virtio_queue_get_host_notifier(vq); r->guest_notifier = *virtio_queue_get_guest_notifier(vq); aio_set_event_notifier(s->ctx, &r->host_notifier, handler); diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c index da0cff83f7..c9bea067e1 100644 --- a/hw/scsi/virtio-scsi.c +++ b/hw/scsi/virtio-scsi.c @@ -146,8 +146,12 @@ 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)) { - req_size = req->elem.out_sg[0].iov_len; - resp_size = req->elem.in_sg[0].iov_len; + if (req->elem.out_num) { + req_size = req->elem.out_sg[0].iov_len; + } + if (req->elem.in_num) { + resp_size = req->elem.in_sg[0].iov_len; + } } out_size = qemu_sgl_concat(req, req->elem.out_sg, diff --git a/hw/sd/omap_mmc.c b/hw/sd/omap_mmc.c index 86c477d720..d072deca11 100644 --- a/hw/sd/omap_mmc.c +++ b/hw/sd/omap_mmc.c @@ -406,7 +406,8 @@ static void omap_mmc_write(void *opaque, hwaddr offset, struct omap_mmc_s *s = (struct omap_mmc_s *) opaque; if (size != 2) { - return omap_badwidth_write16(opaque, offset, value); + omap_badwidth_write16(opaque, offset, value); + return; } switch (offset) { diff --git a/hw/ssi/omap_spi.c b/hw/ssi/omap_spi.c index 0ed3b110e6..119e325a64 100644 --- a/hw/ssi/omap_spi.c +++ b/hw/ssi/omap_spi.c @@ -226,7 +226,8 @@ static void omap_mcspi_write(void *opaque, hwaddr addr, int ch = 0; if (size != 4) { - return omap_badwidth_write32(opaque, addr, value); + omap_badwidth_write32(opaque, addr, value); + return; } switch (addr) { diff --git a/hw/timer/a9gtimer.c b/hw/timer/a9gtimer.c index b087bbddb8..dd4aae8b3a 100644 --- a/hw/timer/a9gtimer.c +++ b/hw/timer/a9gtimer.c @@ -121,7 +121,7 @@ static void a9_gtimer_update_no_sync(void *opaque) { A9GTimerState *s = A9_GTIMER(opaque); - return a9_gtimer_update(s, false); + a9_gtimer_update(s, false); } static uint64_t a9_gtimer_read(void *opaque, hwaddr addr, unsigned size) diff --git a/hw/timer/omap_gptimer.c b/hw/timer/omap_gptimer.c index b7f3d49ca6..b8c8c0137d 100644 --- a/hw/timer/omap_gptimer.c +++ b/hw/timer/omap_gptimer.c @@ -444,7 +444,7 @@ static void omap_gp_timer_writeh(void *opaque, hwaddr addr, struct omap_gp_timer_s *s = (struct omap_gp_timer_s *) opaque; if (addr & 2) - return omap_gp_timer_write(opaque, addr, (value << 16) | s->writeh); + omap_gp_timer_write(opaque, addr, (value << 16) | s->writeh); else s->writeh = (uint16_t) value; } diff --git a/hw/tpm/tpm_tis.c b/hw/tpm/tpm_tis.c index 9084ca439e..815c8eace1 100644 --- a/hw/tpm/tpm_tis.c +++ b/hw/tpm/tpm_tis.c @@ -868,7 +868,7 @@ static void tpm_tis_mmio_write_intern(void *opaque, hwaddr addr, static void tpm_tis_mmio_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { - return tpm_tis_mmio_write_intern(opaque, addr, val, size, false); + tpm_tis_mmio_write_intern(opaque, addr, val, size, false); } static const MemoryRegionOps tpm_tis_memory_ops = { diff --git a/hw/usb/hcd-musb.c b/hw/usb/hcd-musb.c index 40809f610e..61cc87894e 100644 --- a/hw/usb/hcd-musb.c +++ b/hw/usb/hcd-musb.c @@ -554,8 +554,10 @@ static void musb_schedule_cb(USBPort *port, USBPacket *packey) timeout = ep->timeout[dir]; else if (ep->interrupt[dir]) timeout = 8; - else - return musb_cb_tick(ep); + else { + musb_cb_tick(ep); + return; + } if (!ep->intv_timer[dir]) ep->intv_timer[dir] = timer_new_ns(QEMU_CLOCK_VIRTUAL, musb_cb_tick, ep); @@ -772,9 +774,11 @@ static void musb_rx_packet_complete(USBPacket *packey, void *opaque) /* NAK timeouts are only generated in Bulk transfers and * Data-errors in Isochronous. */ - if (ep->interrupt[1]) - return musb_packet(s, ep, epnum, USB_TOKEN_IN, - packey->iov.size, musb_rx_packet_complete, 1); + if (ep->interrupt[1]) { + musb_packet(s, ep, epnum, USB_TOKEN_IN, + packey->iov.size, musb_rx_packet_complete, 1); + return; + } ep->csr[1] |= MGC_M_RXCSR_DATAERROR; if (!epnum) @@ -864,8 +868,7 @@ static void musb_tx_rdy(MUSBState *s, int epnum) * but it doesn't make sense for us to do that. */ } - return musb_packet(s, ep, epnum, pid, - total, musb_tx_packet_complete, 0); + musb_packet(s, ep, epnum, pid, total, musb_tx_packet_complete, 0); } static void musb_rx_req(MUSBState *s, int epnum) @@ -929,8 +932,7 @@ static void musb_rx_req(MUSBState *s, int epnum) } #endif - return musb_packet(s, ep, epnum, USB_TOKEN_IN, - total, musb_rx_packet_complete, 1); + musb_packet(s, ep, epnum, USB_TOKEN_IN, total, musb_rx_packet_complete, 1); } static uint8_t musb_read_fifo(MUSBEndPoint *ep) diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index 3c6e430048..17c1260c0d 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -759,8 +759,9 @@ void virtio_queue_set_align(VirtIODevice *vdev, int n, int align) void virtio_queue_notify_vq(VirtQueue *vq) { - if (vq->vring.desc) { + if (vq->vring.desc && vq->handle_output) { VirtIODevice *vdev = vq->vdev; + trace_virtio_queue_notify(vdev, vq - vdev->vq, vq); vq->handle_output(vdev, vq); } diff --git a/include/block/block.h b/include/block/block.h index 473c746342..4c57d63fe2 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -381,7 +381,6 @@ int bdrv_media_changed(BlockDriverState *bs); void bdrv_lock_medium(BlockDriverState *bs, bool locked); void bdrv_eject(BlockDriverState *bs, bool eject_flag); const char *bdrv_get_format_name(BlockDriverState *bs); -BlockDriverState *bdrv_find(const char *name); BlockDriverState *bdrv_find_node(const char *node_name); BlockDeviceInfoList *bdrv_named_nodes_list(void); BlockDriverState *bdrv_lookup_bs(const char *device, diff --git a/include/block/nbd.h b/include/block/nbd.h index ca9a5ac5b3..65f409d804 100644 --- a/include/block/nbd.h +++ b/include/block/nbd.h @@ -54,8 +54,8 @@ struct nbd_reply { /* Reply types. */ #define NBD_REP_ACK (1) /* Data sending finished. */ #define NBD_REP_SERVER (2) /* Export description. */ -#define NBD_REP_ERR_UNSUP ((1 << 31) | 1) /* Unknown option. */ -#define NBD_REP_ERR_INVALID ((1 << 31) | 3) /* Invalid length. */ +#define NBD_REP_ERR_UNSUP ((UINT32_C(1) << 31) | 1) /* Unknown option. */ +#define NBD_REP_ERR_INVALID ((UINT32_C(1) << 31) | 3) /* Invalid length. */ #define NBD_CMD_MASK_COMMAND 0x0000ffff #define NBD_CMD_FLAG_FUA (1 << 16) @@ -75,8 +75,8 @@ enum { ssize_t nbd_wr_sync(int fd, void *buffer, size_t size, bool do_read); int nbd_receive_negotiate(int csock, const char *name, uint32_t *flags, - off_t *size, size_t *blocksize, Error **errp); -int nbd_init(int fd, int csock, uint32_t flags, off_t size, size_t blocksize); + off_t *size, Error **errp); +int nbd_init(int fd, int csock, uint32_t flags, off_t size); ssize_t nbd_send_request(int csock, struct nbd_request *request); ssize_t nbd_receive_reply(int csock, struct nbd_reply *reply); int nbd_client(int fd); @@ -86,7 +86,8 @@ typedef struct NBDExport NBDExport; typedef struct NBDClient NBDClient; NBDExport *nbd_export_new(BlockBackend *blk, off_t dev_offset, off_t size, - uint32_t nbdflags, void (*close)(NBDExport *)); + uint32_t nbdflags, void (*close)(NBDExport *), + Error **errp); void nbd_export_close(NBDExport *exp); void nbd_export_get(NBDExport *exp); void nbd_export_put(NBDExport *exp); diff --git a/include/hw/elf_ops.h b/include/hw/elf_ops.h index 16a627bdeb..bd71968143 100644 --- a/include/hw/elf_ops.h +++ b/include/hw/elf_ops.h @@ -315,7 +315,9 @@ static int glue(load_elf, SZ)(const char *name, int fd, glue(load_symbols, SZ)(&ehdr, fd, must_swab, clear_lsb); size = ehdr.e_phnum * sizeof(phdr[0]); - lseek(fd, ehdr.e_phoff, SEEK_SET); + if (lseek(fd, ehdr.e_phoff, SEEK_SET) != ehdr.e_phoff) { + goto fail; + } phdr = g_malloc0(size); if (!phdr) goto fail; diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index be2d9b8703..b97c2956ec 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -137,7 +137,7 @@ enum { #define PCI_CONFIG_HEADER_SIZE 0x40 /* Size of the standard PCI config space */ #define PCI_CONFIG_SPACE_SIZE 0x100 -/* Size of the standart PCIe config space: 4KB */ +/* Size of the standard PCIe config space: 4KB */ #define PCIE_CONFIG_SPACE_SIZE 0x1000 #define PCI_NUM_PINS 4 /* A-D */ diff --git a/include/hw/pci/pcie_aer.h b/include/hw/pci/pcie_aer.h index bcac80a7b0..2fb83882be 100644 --- a/include/hw/pci/pcie_aer.h +++ b/include/hw/pci/pcie_aer.h @@ -51,7 +51,7 @@ struct PCIEAERLog { PCIEAERErr *log; }; -/* aer error message: error signaling message has only error sevirity and +/* aer error message: error signaling message has only error severity and source id. See 2.2.8.3 error signaling messages */ struct PCIEAERMsg { /* diff --git a/include/hw/pci/pcie_regs.h b/include/hw/pci/pcie_regs.h index 652d9fc58c..848ab1c206 100644 --- a/include/hw/pci/pcie_regs.h +++ b/include/hw/pci/pcie_regs.h @@ -72,7 +72,7 @@ #define PCI_EXP_DEVCAP2_EFF 0x100000 #define PCI_EXP_DEVCAP2_EETLPP 0x200000 -#define PCI_EXP_DEVCTL2_EETLPPB 0x80 +#define PCI_EXP_DEVCTL2_EETLPPB 0x8000 /* ARI */ #define PCI_ARI_VER 1 diff --git a/include/migration/migration.h b/include/migration/migration.h index 5e16af60fd..bf09968d76 100644 --- a/include/migration/migration.h +++ b/include/migration/migration.h @@ -139,7 +139,6 @@ void migrate_add_blocker(Error *reason); */ void migrate_del_blocker(Error *reason); -bool migrate_rdma_pin_all(void); bool migrate_zero_blocks(void); bool migrate_auto_converge(void); diff --git a/include/migration/qemu-file.h b/include/migration/qemu-file.h index 94a8c978a4..745a850e51 100644 --- a/include/migration/qemu-file.h +++ b/include/migration/qemu-file.h @@ -133,7 +133,6 @@ bool qemu_file_mode_is_not_valid(const char *mode); bool qemu_file_is_writable(QEMUFile *f); QEMUSizedBuffer *qsb_create(const uint8_t *buffer, size_t len); -QEMUSizedBuffer *qsb_clone(const QEMUSizedBuffer *); void qsb_free(QEMUSizedBuffer *); size_t qsb_set_length(QEMUSizedBuffer *qsb, size_t length); size_t qsb_get_length(const QEMUSizedBuffer *qsb); diff --git a/include/monitor/qdev.h b/include/monitor/qdev.h index 5eb4a1171e..719075283c 100644 --- a/include/monitor/qdev.h +++ b/include/monitor/qdev.h @@ -8,6 +8,7 @@ void hmp_info_qtree(Monitor *mon, const QDict *qdict); void hmp_info_qdm(Monitor *mon, const QDict *qdict); +void hmp_info_qom_tree(Monitor *mon, const QDict *dict); int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data); int qdev_device_help(QemuOpts *opts); DeviceState *qdev_device_add(QemuOpts *opts); diff --git a/include/qemu/timer.h b/include/qemu/timer.h index eba8b2109c..e5bd494c07 100644 --- a/include/qemu/timer.h +++ b/include/qemu/timer.h @@ -999,11 +999,10 @@ static inline int64_t cpu_get_real_ticks (void) #ifdef CONFIG_PROFILER static inline int64_t profile_getclock(void) { - return cpu_get_real_ticks(); + return get_clock(); } -extern int64_t qemu_time, qemu_time_start; -extern int64_t tlb_flush_time; +extern int64_t tcg_time; extern int64_t dev_time; #endif diff --git a/include/qom/cpu.h b/include/qom/cpu.h index d6279c01f5..9dafb4817e 100644 --- a/include/qom/cpu.h +++ b/include/qom/cpu.h @@ -593,7 +593,7 @@ static inline void cpu_unaligned_access(CPUState *cpu, vaddr addr, { CPUClass *cc = CPU_GET_CLASS(cpu); - return cc->do_unaligned_access(cpu, addr, is_write, is_user, retaddr); + cc->do_unaligned_access(cpu, addr, is_write, is_user, retaddr); } #endif diff --git a/kvm-all.c b/kvm-all.c index 55025cc366..335438adb5 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -528,13 +528,33 @@ int kvm_vm_check_extension(KVMState *s, unsigned int extension) return ret; } +static uint32_t adjust_ioeventfd_endianness(uint32_t val, uint32_t size) +{ +#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN) + /* The kernel expects ioeventfd values in HOST_WORDS_BIGENDIAN + * endianness, but the memory core hands them in target endianness. + * For example, PPC is always treated as big-endian even if running + * on KVM and on PPC64LE. Correct here. + */ + switch (size) { + case 2: + val = bswap16(val); + break; + case 4: + val = bswap32(val); + break; + } +#endif + return val; +} + static int kvm_set_ioeventfd_mmio(int fd, hwaddr addr, uint32_t val, bool assign, uint32_t size, bool datamatch) { int ret; struct kvm_ioeventfd iofd; - iofd.datamatch = datamatch ? val : 0; + iofd.datamatch = datamatch ? adjust_ioeventfd_endianness(val, size) : 0; iofd.addr = addr; iofd.len = size; iofd.flags = 0; @@ -564,7 +584,7 @@ static int kvm_set_ioeventfd_pio(int fd, uint16_t addr, uint16_t val, bool assign, uint32_t size, bool datamatch) { struct kvm_ioeventfd kick = { - .datamatch = datamatch ? val : 0, + .datamatch = datamatch ? adjust_ioeventfd_endianness(val, size) : 0, .addr = addr, .flags = KVM_IOEVENTFD_FLAG_PIO, .len = size, diff --git a/memory.c b/memory.c index 20f6d9eeac..ee3f2a8a95 100644 --- a/memory.c +++ b/memory.c @@ -868,7 +868,7 @@ void memory_region_init(MemoryRegion *mr, uint64_t size) { if (!owner) { - owner = qdev_get_machine(); + owner = container_get(qdev_get_machine(), "/unattached"); } object_initialize(mr, sizeof(*mr), TYPE_MEMORY_REGION); diff --git a/migration/block.c b/migration/block.c index 0c7610600b..085c0fae05 100644 --- a/migration/block.c +++ b/migration/block.c @@ -23,6 +23,7 @@ #include "migration/block.h" #include "migration/migration.h" #include "sysemu/blockdev.h" +#include "sysemu/block-backend.h" #include <assert.h> #define BLOCK_SIZE (1 << 20) @@ -783,6 +784,7 @@ static int block_load(QEMUFile *f, void *opaque, int version_id) char device_name[256]; int64_t addr; BlockDriverState *bs, *bs_prev = NULL; + BlockBackend *blk; uint8_t *buf; int64_t total_sectors = 0; int nr_sectors; @@ -800,12 +802,13 @@ static int block_load(QEMUFile *f, void *opaque, int version_id) qemu_get_buffer(f, (uint8_t *)device_name, len); device_name[len] = '\0'; - bs = bdrv_find(device_name); - if (!bs) { + blk = blk_by_name(device_name); + if (!blk) { fprintf(stderr, "Error unknown block device %s\n", device_name); return -EINVAL; } + bs = blk_bs(blk); if (bs != bs_prev) { bs_prev = bs; diff --git a/migration/migration.c b/migration/migration.c index 2c805f11f5..bc424907f3 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -26,16 +26,6 @@ #include "qmp-commands.h" #include "trace.h" -enum { - MIG_STATE_ERROR = -1, - MIG_STATE_NONE, - MIG_STATE_SETUP, - MIG_STATE_CANCELLING, - MIG_STATE_CANCELLED, - MIG_STATE_ACTIVE, - MIG_STATE_COMPLETED, -}; - #define MAX_THROTTLE (32 << 20) /* Migration speed throttling */ /* Amount of time to allocate to each "chunk" of bandwidth-throttled @@ -58,7 +48,7 @@ static bool deferred_incoming; MigrationState *migrate_get_current(void) { static MigrationState current_migration = { - .state = MIG_STATE_NONE, + .state = MIGRATION_STATUS_NONE, .bandwidth_limit = MAX_THROTTLE, .xbzrle_cache_size = DEFAULT_MIGRATE_CACHE_SIZE, .mbps = -1, @@ -123,8 +113,7 @@ static void process_incoming_migration_co(void *opaque) /* Make sure all file formats flush their mutable metadata */ bdrv_invalidate_cache_all(&local_err); if (local_err) { - qerror_report_err(local_err); - error_free(local_err); + error_report_err(local_err); exit(EXIT_FAILURE); } @@ -201,18 +190,16 @@ MigrationInfo *qmp_query_migrate(Error **errp) MigrationState *s = migrate_get_current(); switch (s->state) { - case MIG_STATE_NONE: + case MIGRATION_STATUS_NONE: /* no migration has happened ever */ break; - case MIG_STATE_SETUP: + case MIGRATION_STATUS_SETUP: info->has_status = true; - info->status = g_strdup("setup"); info->has_total_time = false; break; - case MIG_STATE_ACTIVE: - case MIG_STATE_CANCELLING: + case MIGRATION_STATUS_ACTIVE: + case MIGRATION_STATUS_CANCELLING: info->has_status = true; - info->status = g_strdup("active"); info->has_total_time = true; info->total_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME) - s->total_time; @@ -244,11 +231,10 @@ MigrationInfo *qmp_query_migrate(Error **errp) get_xbzrle_cache_stats(info); break; - case MIG_STATE_COMPLETED: + case MIGRATION_STATUS_COMPLETED: get_xbzrle_cache_stats(info); info->has_status = true; - info->status = g_strdup("completed"); info->has_total_time = true; info->total_time = s->total_time; info->has_downtime = true; @@ -268,15 +254,14 @@ MigrationInfo *qmp_query_migrate(Error **errp) info->ram->mbps = s->mbps; info->ram->dirty_sync_count = s->dirty_sync_count; break; - case MIG_STATE_ERROR: + case MIGRATION_STATUS_FAILED: info->has_status = true; - info->status = g_strdup("failed"); break; - case MIG_STATE_CANCELLED: + case MIGRATION_STATUS_CANCELLED: info->has_status = true; - info->status = g_strdup("cancelled"); break; } + info->status = s->state; return info; } @@ -287,7 +272,8 @@ void qmp_migrate_set_capabilities(MigrationCapabilityStatusList *params, MigrationState *s = migrate_get_current(); MigrationCapabilityStatusList *cap; - if (s->state == MIG_STATE_ACTIVE || s->state == MIG_STATE_SETUP) { + if (s->state == MIGRATION_STATUS_ACTIVE || + s->state == MIGRATION_STATUS_SETUP) { error_set(errp, QERR_MIGRATION_ACTIVE); return; } @@ -323,12 +309,13 @@ static void migrate_fd_cleanup(void *opaque) s->file = NULL; } - assert(s->state != MIG_STATE_ACTIVE); + assert(s->state != MIGRATION_STATUS_ACTIVE); - if (s->state != MIG_STATE_COMPLETED) { + if (s->state != MIGRATION_STATUS_COMPLETED) { qemu_savevm_state_cancel(); - if (s->state == MIG_STATE_CANCELLING) { - migrate_set_state(s, MIG_STATE_CANCELLING, MIG_STATE_CANCELLED); + if (s->state == MIGRATION_STATUS_CANCELLING) { + migrate_set_state(s, MIGRATION_STATUS_CANCELLING, + MIGRATION_STATUS_CANCELLED); } } @@ -339,8 +326,8 @@ void migrate_fd_error(MigrationState *s) { trace_migrate_fd_error(); assert(s->file == NULL); - s->state = MIG_STATE_ERROR; - trace_migrate_set_state(MIG_STATE_ERROR); + s->state = MIGRATION_STATUS_FAILED; + trace_migrate_set_state(MIGRATION_STATUS_FAILED); notifier_list_notify(&migration_state_notifiers, s); } @@ -352,11 +339,12 @@ static void migrate_fd_cancel(MigrationState *s) do { old_state = s->state; - if (old_state != MIG_STATE_SETUP && old_state != MIG_STATE_ACTIVE) { + if (old_state != MIGRATION_STATUS_SETUP && + old_state != MIGRATION_STATUS_ACTIVE) { break; } - migrate_set_state(s, old_state, MIG_STATE_CANCELLING); - } while (s->state != MIG_STATE_CANCELLING); + migrate_set_state(s, old_state, MIGRATION_STATUS_CANCELLING); + } while (s->state != MIGRATION_STATUS_CANCELLING); /* * If we're unlucky the migration code might be stuck somewhere in a @@ -365,7 +353,7 @@ static void migrate_fd_cancel(MigrationState *s) * The outgoing qemu file gets closed in migrate_fd_cleanup that is * called in a bh, so there is no race against this cancel. */ - if (s->state == MIG_STATE_CANCELLING && f) { + if (s->state == MIGRATION_STATUS_CANCELLING && f) { qemu_file_shutdown(f); } } @@ -382,18 +370,18 @@ void remove_migration_state_change_notifier(Notifier *notify) bool migration_in_setup(MigrationState *s) { - return s->state == MIG_STATE_SETUP; + return s->state == MIGRATION_STATUS_SETUP; } bool migration_has_finished(MigrationState *s) { - return s->state == MIG_STATE_COMPLETED; + return s->state == MIGRATION_STATUS_COMPLETED; } bool migration_has_failed(MigrationState *s) { - return (s->state == MIG_STATE_CANCELLED || - s->state == MIG_STATE_ERROR); + return (s->state == MIGRATION_STATUS_CANCELLED || + s->state == MIGRATION_STATUS_FAILED); } static MigrationState *migrate_init(const MigrationParams *params) @@ -413,8 +401,8 @@ static MigrationState *migrate_init(const MigrationParams *params) s->xbzrle_cache_size = xbzrle_cache_size; s->bandwidth_limit = bandwidth_limit; - s->state = MIG_STATE_SETUP; - trace_migrate_set_state(MIG_STATE_SETUP); + s->state = MIGRATION_STATUS_SETUP; + trace_migrate_set_state(MIGRATION_STATUS_SETUP); s->total_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME); return s; @@ -435,11 +423,15 @@ void migrate_del_blocker(Error *reason) void qmp_migrate_incoming(const char *uri, Error **errp) { Error *local_err = NULL; + static bool once = true; if (!deferred_incoming) { - error_setg(errp, "'-incoming defer' is required for migrate_incoming"); + error_setg(errp, "For use with '-incoming defer'"); return; } + if (!once) { + error_setg(errp, "The incoming migration has already been started"); + } qemu_start_incoming_migration(uri, &local_err); @@ -448,7 +440,7 @@ void qmp_migrate_incoming(const char *uri, Error **errp) return; } - deferred_incoming = false; + once = false; } void qmp_migrate(const char *uri, bool has_blk, bool blk, @@ -463,8 +455,9 @@ void qmp_migrate(const char *uri, bool has_blk, bool blk, params.blk = has_blk && blk; params.shared = has_inc && inc; - if (s->state == MIG_STATE_ACTIVE || s->state == MIG_STATE_SETUP || - s->state == MIG_STATE_CANCELLING) { + if (s->state == MIGRATION_STATUS_ACTIVE || + s->state == MIGRATION_STATUS_SETUP || + s->state == MIGRATION_STATUS_CANCELLING) { error_set(errp, QERR_MIGRATION_ACTIVE); return; } @@ -501,7 +494,7 @@ void qmp_migrate(const char *uri, bool has_blk, bool blk, #endif } else { error_set(errp, QERR_INVALID_PARAMETER_VALUE, "uri", "a valid migration protocol"); - s->state = MIG_STATE_ERROR; + s->state = MIGRATION_STATUS_FAILED; return; } @@ -576,15 +569,6 @@ void qmp_migrate_set_downtime(double value, Error **errp) max_downtime = (uint64_t)value; } -bool migrate_rdma_pin_all(void) -{ - MigrationState *s; - - s = migrate_get_current(); - - return s->enabled_capabilities[MIGRATION_CAPABILITY_RDMA_PIN_ALL]; -} - bool migrate_auto_converge(void) { MigrationState *s; @@ -636,9 +620,9 @@ static void *migration_thread(void *opaque) qemu_savevm_state_begin(s->file, &s->params); s->setup_time = qemu_clock_get_ms(QEMU_CLOCK_HOST) - setup_start; - migrate_set_state(s, MIG_STATE_SETUP, MIG_STATE_ACTIVE); + migrate_set_state(s, MIGRATION_STATUS_SETUP, MIGRATION_STATUS_ACTIVE); - while (s->state == MIG_STATE_ACTIVE) { + while (s->state == MIGRATION_STATUS_ACTIVE) { int64_t current_time; uint64_t pending_size; @@ -663,19 +647,22 @@ static void *migration_thread(void *opaque) qemu_mutex_unlock_iothread(); if (ret < 0) { - migrate_set_state(s, MIG_STATE_ACTIVE, MIG_STATE_ERROR); + migrate_set_state(s, MIGRATION_STATUS_ACTIVE, + MIGRATION_STATUS_FAILED); break; } if (!qemu_file_get_error(s->file)) { - migrate_set_state(s, MIG_STATE_ACTIVE, MIG_STATE_COMPLETED); + migrate_set_state(s, MIGRATION_STATUS_ACTIVE, + MIGRATION_STATUS_COMPLETED); break; } } } if (qemu_file_get_error(s->file)) { - migrate_set_state(s, MIG_STATE_ACTIVE, MIG_STATE_ERROR); + migrate_set_state(s, MIGRATION_STATUS_ACTIVE, + MIGRATION_STATUS_FAILED); break; } current_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME); @@ -707,7 +694,7 @@ static void *migration_thread(void *opaque) } qemu_mutex_lock_iothread(); - if (s->state == MIG_STATE_COMPLETED) { + if (s->state == MIGRATION_STATUS_COMPLETED) { int64_t end_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME); uint64_t transferred_bytes = qemu_ftell(s->file); s->total_time = end_time - s->total_time; @@ -730,8 +717,8 @@ static void *migration_thread(void *opaque) void migrate_fd_connect(MigrationState *s) { - s->state = MIG_STATE_SETUP; - trace_migrate_set_state(MIG_STATE_SETUP); + s->state = MIGRATION_STATUS_SETUP; + trace_migrate_set_state(MIGRATION_STATUS_SETUP); /* This is a best 1st approximation. ns to ms */ s->expected_downtime = max_downtime/1000000; diff --git a/migration/qemu-file-buf.c b/migration/qemu-file-buf.c index e56a8ad1e0..16a51a1e17 100644 --- a/migration/qemu-file-buf.c +++ b/migration/qemu-file-buf.c @@ -365,37 +365,6 @@ ssize_t qsb_write_at(QEMUSizedBuffer *qsb, const uint8_t *source, return count; } -/** - * Create a deep copy of the given QEMUSizedBuffer. - * - * @qsb: A QEMUSizedBuffer - * - * Returns a clone of @qsb or NULL on allocation failure - */ -QEMUSizedBuffer *qsb_clone(const QEMUSizedBuffer *qsb) -{ - QEMUSizedBuffer *out = qsb_create(NULL, qsb_get_length(qsb)); - size_t i; - ssize_t res; - off_t pos = 0; - - if (!out) { - return NULL; - } - - for (i = 0; i < qsb->n_iov; i++) { - res = qsb_write_at(out, qsb->iov[i].iov_base, - pos, qsb->iov[i].iov_len); - if (res < 0) { - qsb_free(out); - return NULL; - } - pos += res; - } - - return out; -} - typedef struct QEMUBuffer { QEMUSizedBuffer *qsb; QEMUFile *file; diff --git a/migration/rdma.c b/migration/rdma.c index d1c19ffdac..e6c3a67b54 100644 --- a/migration/rdma.c +++ b/migration/rdma.c @@ -493,8 +493,8 @@ static inline uint64_t ram_chunk_index(const uint8_t *start, static inline uint8_t *ram_chunk_start(const RDMALocalBlock *rdma_ram_block, uint64_t i) { - return (uint8_t *) (((uintptr_t) rdma_ram_block->local_host_addr) - + (i << RDMA_REG_CHUNK_SHIFT)); + return (uint8_t *)(uintptr_t)(rdma_ram_block->local_host_addr + + (i << RDMA_REG_CHUNK_SHIFT)); } static inline uint8_t *ram_chunk_end(const RDMALocalBlock *rdma_ram_block, @@ -515,7 +515,7 @@ static int rdma_add_block(RDMAContext *rdma, void *host_addr, { RDMALocalBlocks *local = &rdma->local_ram_blocks; RDMALocalBlock *block = g_hash_table_lookup(rdma->blockmap, - (void *) block_offset); + (void *)(uintptr_t)block_offset); RDMALocalBlock *old = local->block; assert(block == NULL); @@ -526,9 +526,11 @@ static int rdma_add_block(RDMAContext *rdma, void *host_addr, int x; for (x = 0; x < local->nb_blocks; x++) { - g_hash_table_remove(rdma->blockmap, (void *)old[x].offset); - g_hash_table_insert(rdma->blockmap, (void *)old[x].offset, - &local->block[x]); + g_hash_table_remove(rdma->blockmap, + (void *)(uintptr_t)old[x].offset); + g_hash_table_insert(rdma->blockmap, + (void *)(uintptr_t)old[x].offset, + &local->block[x]); } memcpy(local->block, old, sizeof(RDMALocalBlock) * local->nb_blocks); g_free(old); @@ -551,9 +553,9 @@ static int rdma_add_block(RDMAContext *rdma, void *host_addr, g_hash_table_insert(rdma->blockmap, (void *) block_offset, block); - trace_rdma_add_block(local->nb_blocks, (uint64_t) block->local_host_addr, + trace_rdma_add_block(local->nb_blocks, (uintptr_t) block->local_host_addr, block->offset, block->length, - (uint64_t) (block->local_host_addr + block->length), + (uintptr_t) (block->local_host_addr + block->length), BITS_TO_LONGS(block->nb_chunks) * sizeof(unsigned long) * 8, block->nb_chunks); @@ -634,7 +636,7 @@ static int rdma_delete_block(RDMAContext *rdma, ram_addr_t block_offset) block->remote_keys = NULL; for (x = 0; x < local->nb_blocks; x++) { - g_hash_table_remove(rdma->blockmap, (void *)old[x].offset); + g_hash_table_remove(rdma->blockmap, (void *)(uintptr_t)old[x].offset); } if (local->nb_blocks > 1) { @@ -657,9 +659,9 @@ static int rdma_delete_block(RDMAContext *rdma, ram_addr_t block_offset) } trace_rdma_delete_block(local->nb_blocks, - (uint64_t)block->local_host_addr, + (uintptr_t)block->local_host_addr, block->offset, block->length, - (uint64_t)(block->local_host_addr + block->length), + (uintptr_t)(block->local_host_addr + block->length), BITS_TO_LONGS(block->nb_chunks) * sizeof(unsigned long) * 8, block->nb_chunks); @@ -669,8 +671,9 @@ static int rdma_delete_block(RDMAContext *rdma, ram_addr_t block_offset) if (local->nb_blocks) { for (x = 0; x < local->nb_blocks; x++) { - g_hash_table_insert(rdma->blockmap, (void *)local->block[x].offset, - &local->block[x]); + g_hash_table_insert(rdma->blockmap, + (void *)(uintptr_t)local->block[x].offset, + &local->block[x]); } } @@ -1075,7 +1078,7 @@ static int qemu_rdma_reg_whole_ram_blocks(RDMAContext *rdma) * This search cannot fail or the migration will fail. */ static int qemu_rdma_search_ram_block(RDMAContext *rdma, - uint64_t block_offset, + uintptr_t block_offset, uint64_t offset, uint64_t length, uint64_t *block_index, @@ -1103,7 +1106,7 @@ static int qemu_rdma_search_ram_block(RDMAContext *rdma, * to perform the actual RDMA operation. */ static int qemu_rdma_register_and_get_keys(RDMAContext *rdma, - RDMALocalBlock *block, uint8_t *host_addr, + RDMALocalBlock *block, uintptr_t host_addr, uint32_t *lkey, uint32_t *rkey, int chunk, uint8_t *chunk_start, uint8_t *chunk_end) { @@ -1140,11 +1143,12 @@ static int qemu_rdma_register_and_get_keys(RDMAContext *rdma, if (!block->pmr[chunk]) { perror("Failed to register chunk!"); fprintf(stderr, "Chunk details: block: %d chunk index %d" - " start %" PRIu64 " end %" PRIu64 " host %" PRIu64 - " local %" PRIu64 " registrations: %d\n", - block->index, chunk, (uint64_t) chunk_start, - (uint64_t) chunk_end, (uint64_t) host_addr, - (uint64_t) block->local_host_addr, + " start %" PRIuPTR " end %" PRIuPTR + " host %" PRIuPTR + " local %" PRIuPTR " registrations: %d\n", + block->index, chunk, (uintptr_t)chunk_start, + (uintptr_t)chunk_end, host_addr, + (uintptr_t)block->local_host_addr, rdma->total_registrations); return -1; } @@ -1378,8 +1382,8 @@ static uint64_t qemu_rdma_poll(RDMAContext *rdma, uint64_t *wr_id_out, RDMALocalBlock *block = &(rdma->local_ram_blocks.block[index]); trace_qemu_rdma_poll_write(print_wrid(wr_id), wr_id, rdma->nb_sent, - index, chunk, - block->local_host_addr, (void *)block->remote_host_addr); + index, chunk, block->local_host_addr, + (void *)(uintptr_t)block->remote_host_addr); clear_bit(chunk, block->transit_bitmap); @@ -1522,7 +1526,7 @@ static int qemu_rdma_post_send_control(RDMAContext *rdma, uint8_t *buf, RDMAWorkRequestData *wr = &rdma->wr_data[RDMA_WRID_CONTROL]; struct ibv_send_wr *bad_wr; struct ibv_sge sge = { - .addr = (uint64_t)(wr->control), + .addr = (uintptr_t)(wr->control), .length = head->len + sizeof(RDMAControlHeader), .lkey = wr->control_mr->lkey, }; @@ -1576,7 +1580,7 @@ static int qemu_rdma_post_recv_control(RDMAContext *rdma, int idx) { struct ibv_recv_wr *bad_wr; struct ibv_sge sge = { - .addr = (uint64_t)(rdma->wr_data[idx].control), + .addr = (uintptr_t)(rdma->wr_data[idx].control), .length = RDMA_CONTROL_MAX_BUFFER, .lkey = rdma->wr_data[idx].control_mr->lkey, }; @@ -1823,11 +1827,12 @@ static int qemu_rdma_write_one(QEMUFile *f, RDMAContext *rdma, }; retry: - sge.addr = (uint64_t)(block->local_host_addr + + sge.addr = (uintptr_t)(block->local_host_addr + (current_addr - block->offset)); sge.length = length; - chunk = ram_chunk_index(block->local_host_addr, (uint8_t *) sge.addr); + chunk = ram_chunk_index(block->local_host_addr, + (uint8_t *)(uintptr_t)sge.addr); chunk_start = ram_chunk_start(block, chunk); if (block->is_ram_block) { @@ -1880,8 +1885,9 @@ retry: * memset() + madvise() the entire chunk without RDMA. */ - if (can_use_buffer_find_nonzero_offset((void *)sge.addr, length) - && buffer_find_nonzero_offset((void *)sge.addr, + if (can_use_buffer_find_nonzero_offset((void *)(uintptr_t)sge.addr, + length) + && buffer_find_nonzero_offset((void *)(uintptr_t)sge.addr, length) == length) { RDMACompress comp = { .offset = current_addr, @@ -1931,8 +1937,7 @@ retry: } /* try to overlap this single registration with the one we sent. */ - if (qemu_rdma_register_and_get_keys(rdma, block, - (uint8_t *) sge.addr, + if (qemu_rdma_register_and_get_keys(rdma, block, sge.addr, &sge.lkey, NULL, chunk, chunk_start, chunk_end)) { error_report("cannot get lkey"); @@ -1951,8 +1956,7 @@ retry: block->remote_host_addr = reg_result->host_addr; } else { /* already registered before */ - if (qemu_rdma_register_and_get_keys(rdma, block, - (uint8_t *)sge.addr, + if (qemu_rdma_register_and_get_keys(rdma, block, sge.addr, &sge.lkey, NULL, chunk, chunk_start, chunk_end)) { error_report("cannot get lkey!"); @@ -1964,7 +1968,7 @@ retry: } else { send_wr.wr.rdma.rkey = block->remote_rkey; - if (qemu_rdma_register_and_get_keys(rdma, block, (uint8_t *)sge.addr, + if (qemu_rdma_register_and_get_keys(rdma, block, sge.addr, &sge.lkey, NULL, chunk, chunk_start, chunk_end)) { error_report("cannot get lkey!"); @@ -2364,10 +2368,10 @@ err_rdma_source_connect: static int qemu_rdma_dest_init(RDMAContext *rdma, Error **errp) { - int ret = -EINVAL, idx; + int ret, idx; struct rdma_cm_id *listen_id; char ip[40] = "unknown"; - struct rdma_addrinfo *res; + struct rdma_addrinfo *res, *e; char port_str[16]; for (idx = 0; idx < RDMA_WRID_MAX; idx++) { @@ -2375,7 +2379,7 @@ static int qemu_rdma_dest_init(RDMAContext *rdma, Error **errp) rdma->wr_data[idx].control_curr = NULL; } - if (rdma->host == NULL) { + if (!rdma->host || !rdma->host[0]) { ERROR(errp, "RDMA host is not set!"); rdma->error_state = -EINVAL; return -1; @@ -2398,40 +2402,33 @@ static int qemu_rdma_dest_init(RDMAContext *rdma, Error **errp) snprintf(port_str, 16, "%d", rdma->port); port_str[15] = '\0'; - if (rdma->host && strcmp("", rdma->host)) { - struct rdma_addrinfo *e; + ret = rdma_getaddrinfo(rdma->host, port_str, NULL, &res); + if (ret < 0) { + ERROR(errp, "could not rdma_getaddrinfo address %s", rdma->host); + goto err_dest_init_bind_addr; + } - ret = rdma_getaddrinfo(rdma->host, port_str, NULL, &res); - if (ret < 0) { - ERROR(errp, "could not rdma_getaddrinfo address %s", rdma->host); - goto err_dest_init_bind_addr; + for (e = res; e != NULL; e = e->ai_next) { + inet_ntop(e->ai_family, + &((struct sockaddr_in *) e->ai_dst_addr)->sin_addr, ip, sizeof ip); + trace_qemu_rdma_dest_init_trying(rdma->host, ip); + ret = rdma_bind_addr(listen_id, e->ai_dst_addr); + if (ret) { + continue; } - - for (e = res; e != NULL; e = e->ai_next) { - inet_ntop(e->ai_family, - &((struct sockaddr_in *) e->ai_dst_addr)->sin_addr, ip, sizeof ip); - trace_qemu_rdma_dest_init_trying(rdma->host, ip); - ret = rdma_bind_addr(listen_id, e->ai_dst_addr); - if (!ret) { - if (e->ai_family == AF_INET6) { - ret = qemu_rdma_broken_ipv6_kernel(errp, listen_id->verbs); - if (ret) { - continue; - } - } - - goto listen; + if (e->ai_family == AF_INET6) { + ret = qemu_rdma_broken_ipv6_kernel(errp, listen_id->verbs); + if (ret) { + continue; } } + break; + } + if (!e) { ERROR(errp, "Error: could not rdma_bind_addr!"); goto err_dest_init_bind_addr; - } else { - ERROR(errp, "migration host and port not specified!"); - ret = -EINVAL; - goto err_dest_init_bind_addr; } -listen: rdma->listen_id = listen_id; qemu_rdma_dump_gid("dest_init", listen_id); @@ -2977,7 +2974,7 @@ static int qemu_rdma_registration_handle(QEMUFile *f, void *opaque, */ for (i = 0; i < local->nb_blocks; i++) { rdma->block[i].remote_host_addr = - (uint64_t)(local->block[i].local_host_addr); + (uintptr_t)(local->block[i].local_host_addr); if (rdma->pin_all) { rdma->block[i].remote_rkey = local->block[i].mr->rkey; @@ -3034,14 +3031,14 @@ static int qemu_rdma_registration_handle(QEMUFile *f, void *opaque, chunk_start = ram_chunk_start(block, chunk); chunk_end = ram_chunk_end(block, chunk + reg->chunks); if (qemu_rdma_register_and_get_keys(rdma, block, - (uint8_t *)host_addr, NULL, ®_result->rkey, + (uintptr_t)host_addr, NULL, ®_result->rkey, chunk, chunk_start, chunk_end)) { error_report("cannot get rkey"); ret = -EINVAL; goto out; } - reg_result->host_addr = (uint64_t) block->local_host_addr; + reg_result->host_addr = (uintptr_t)block->local_host_addr; trace_qemu_rdma_registration_handle_register_rkey( reg_result->rkey); diff --git a/monitor.c b/monitor.c index c86a89e9b0..432db9503a 100644 --- a/monitor.c +++ b/monitor.c @@ -73,6 +73,7 @@ #include "block/qapi.h" #include "qapi/qmp-event.h" #include "qapi-event.h" +#include "sysemu/block-backend.h" /* for hmp_info_irq/pic */ #if defined(TARGET_SPARC) @@ -1974,7 +1975,7 @@ static void hmp_info_numa(Monitor *mon, const QDict *qdict) #ifdef CONFIG_PROFILER -int64_t qemu_time; +int64_t tcg_time; int64_t dev_time; static void hmp_info_profile(Monitor *mon, const QDict *qdict) @@ -1982,8 +1983,8 @@ static void hmp_info_profile(Monitor *mon, const QDict *qdict) monitor_printf(mon, "async time %" PRId64 " (%0.3f)\n", dev_time, dev_time / (double)get_ticks_per_sec()); monitor_printf(mon, "qemu time %" PRId64 " (%0.3f)\n", - qemu_time, qemu_time / (double)get_ticks_per_sec()); - qemu_time = 0; + tcg_time, tcg_time / (double)get_ticks_per_sec()); + tcg_time = 0; dev_time = 0; } #else @@ -2889,6 +2890,13 @@ static mon_cmd_t info_cmds[] = { .mhandler.cmd = hmp_info_qdm, }, { + .name = "qom-tree", + .args_type = "path:s?", + .params = "[path]", + .help = "show QOM composition tree", + .mhandler.cmd = hmp_info_qom_tree, + }, + { .name = "roms", .args_type = "", .params = "", @@ -4683,11 +4691,13 @@ static void monitor_find_completion_by_table(Monitor *mon, if (cmd->sub_table) { /* do the job again */ - return monitor_find_completion_by_table(mon, cmd->sub_table, - &args[1], nb_args - 1); + monitor_find_completion_by_table(mon, cmd->sub_table, + &args[1], nb_args - 1); + return; } if (cmd->command_completion) { - return cmd->command_completion(mon->rs, nb_args, args[nb_args - 1]); + cmd->command_completion(mon->rs, nb_args, args[nb_args - 1]); + return; } ptype = next_arg_type(cmd->args_type); @@ -5414,15 +5424,15 @@ int monitor_read_block_device_key(Monitor *mon, const char *device, BlockCompletionFunc *completion_cb, void *opaque) { - BlockDriverState *bs; + BlockBackend *blk; - bs = bdrv_find(device); - if (!bs) { + blk = blk_by_name(device); + if (!blk) { monitor_printf(mon, "Device not found %s\n", device); return -1; } - return monitor_read_bdrv_key_start(mon, bs, completion_cb, opaque); + return monitor_read_bdrv_key_start(mon, blk_bs(blk), completion_cb, opaque); } QemuOptsList qemu_mon_opts = { diff --git a/nbd.c b/nbd.c index 71159aff6a..91b7d56239 100644 --- a/nbd.c +++ b/nbd.c @@ -193,6 +193,26 @@ static ssize_t read_sync(int fd, void *buffer, size_t size) return nbd_wr_sync(fd, buffer, size, true); } +static ssize_t drop_sync(int fd, size_t size) +{ + ssize_t ret, dropped = size; + uint8_t *buffer = g_malloc(MIN(65536, size)); + + while (size > 0) { + ret = read_sync(fd, buffer, MIN(65536, size)); + if (ret < 0) { + g_free(buffer); + return ret; + } + + assert(ret <= size); + size -= ret; + } + + g_free(buffer); + return dropped; +} + static ssize_t write_sync(int fd, void *buffer, size_t size) { int ret; @@ -303,6 +323,9 @@ static int nbd_handle_list(NBDClient *client, uint32_t length) csock = client->sock; if (length) { + if (drop_sync(csock, length) != length) { + return -EIO; + } return nbd_send_rep(csock, NBD_REP_ERR_INVALID, NBD_OPT_LIST); } @@ -350,30 +373,39 @@ fail: static int nbd_receive_options(NBDClient *client) { + int csock = client->sock; + uint32_t flags; + + /* Client sends: + [ 0 .. 3] client flags + + [ 0 .. 7] NBD_OPTS_MAGIC + [ 8 .. 11] NBD option + [12 .. 15] Data length + ... Rest of request + + [ 0 .. 7] NBD_OPTS_MAGIC + [ 8 .. 11] Second NBD option + [12 .. 15] Data length + ... Rest of request + */ + + if (read_sync(csock, &flags, sizeof(flags)) != sizeof(flags)) { + LOG("read failed"); + return -EIO; + } + TRACE("Checking client flags"); + be32_to_cpus(&flags); + if (flags != 0 && flags != NBD_FLAG_C_FIXED_NEWSTYLE) { + LOG("Bad client flags received"); + return -EIO; + } + while (1) { - int csock = client->sock; + int ret; uint32_t tmp, length; uint64_t magic; - /* Client sends: - [ 0 .. 3] client flags - [ 4 .. 11] NBD_OPTS_MAGIC - [12 .. 15] NBD option - [16 .. 19] length - ... Rest of request - */ - - if (read_sync(csock, &tmp, sizeof(tmp)) != sizeof(tmp)) { - LOG("read failed"); - return -EINVAL; - } - TRACE("Checking client flags"); - tmp = be32_to_cpu(tmp); - if (tmp != 0 && tmp != NBD_FLAG_C_FIXED_NEWSTYLE) { - LOG("Bad client flags received"); - return -EINVAL; - } - if (read_sync(csock, &magic, sizeof(magic)) != sizeof(magic)) { LOG("read failed"); return -EINVAL; @@ -398,8 +430,9 @@ static int nbd_receive_options(NBDClient *client) TRACE("Checking option"); switch (be32_to_cpu(tmp)) { case NBD_OPT_LIST: - if (nbd_handle_list(client, length) < 0) { - return 1; + ret = nbd_handle_list(client, length); + if (ret < 0) { + return ret; } break; @@ -494,7 +527,7 @@ fail: } int nbd_receive_negotiate(int csock, const char *name, uint32_t *flags, - off_t *size, size_t *blocksize, Error **errp) + off_t *size, Error **errp) { char buf[256]; uint64_t magic, s; @@ -602,7 +635,6 @@ int nbd_receive_negotiate(int csock, const char *name, uint32_t *flags, goto fail; } *size = be64_to_cpu(s); - *blocksize = 1024; TRACE("Size is %" PRIu64, *size); if (!name) { @@ -616,7 +648,7 @@ int nbd_receive_negotiate(int csock, const char *name, uint32_t *flags, error_setg(errp, "Failed to read export flags"); goto fail; } - *flags |= be32_to_cpu(tmp); + *flags |= be16_to_cpu(tmp); } if (read_sync(csock, &buf, 124) != 124) { error_setg(errp, "Failed to read reserved block"); @@ -629,7 +661,7 @@ fail: } #ifdef __linux__ -int nbd_init(int fd, int csock, uint32_t flags, off_t size, size_t blocksize) +int nbd_init(int fd, int csock, uint32_t flags, off_t size) { TRACE("Setting NBD socket"); @@ -639,17 +671,17 @@ int nbd_init(int fd, int csock, uint32_t flags, off_t size, size_t blocksize) return -serrno; } - TRACE("Setting block size to %lu", (unsigned long)blocksize); + TRACE("Setting block size to %lu", (unsigned long)BDRV_SECTOR_SIZE); - if (ioctl(fd, NBD_SET_BLKSIZE, blocksize) < 0) { + if (ioctl(fd, NBD_SET_BLKSIZE, (size_t)BDRV_SECTOR_SIZE) < 0) { int serrno = errno; LOG("Failed setting NBD block size"); return -serrno; } - TRACE("Setting size to %zd block(s)", (size_t)(size / blocksize)); + TRACE("Setting size to %zd block(s)", (size_t)(size / BDRV_SECTOR_SIZE)); - if (ioctl(fd, NBD_SET_SIZE_BLOCKS, size / blocksize) < 0) { + if (ioctl(fd, NBD_SET_SIZE_BLOCKS, size / (size_t)BDRV_SECTOR_SIZE) < 0) { int serrno = errno; LOG("Failed setting size (in blocks)"); return -serrno; @@ -714,7 +746,7 @@ int nbd_client(int fd) return ret; } #else -int nbd_init(int fd, int csock, uint32_t flags, off_t size, size_t blocksize) +int nbd_init(int fd, int csock, uint32_t flags, off_t size) { return -ENOTSUP; } @@ -965,7 +997,8 @@ static void blk_aio_detach(void *opaque) } NBDExport *nbd_export_new(BlockBackend *blk, off_t dev_offset, off_t size, - uint32_t nbdflags, void (*close)(NBDExport *)) + uint32_t nbdflags, void (*close)(NBDExport *), + Error **errp) { NBDExport *exp = g_malloc0(sizeof(NBDExport)); exp->refcount = 1; @@ -973,7 +1006,14 @@ NBDExport *nbd_export_new(BlockBackend *blk, off_t dev_offset, off_t size, exp->blk = blk; exp->dev_offset = dev_offset; exp->nbdflags = nbdflags; - exp->size = size == -1 ? blk_getlength(blk) : size; + exp->size = size < 0 ? blk_getlength(blk) : size; + if (exp->size < 0) { + error_setg_errno(errp, -exp->size, + "Failed to determine the NBD export's length"); + goto fail; + } + exp->size -= exp->size % BDRV_SECTOR_SIZE; + exp->close = close; exp->ctx = blk_get_aio_context(blk); blk_ref(blk); @@ -985,6 +1025,10 @@ NBDExport *nbd_export_new(BlockBackend *blk, off_t dev_offset, off_t size, */ blk_invalidate_cache(blk, NULL); return exp; + +fail: + g_free(exp); + return NULL; } NBDExport *nbd_export_find(const char *name) @@ -1295,7 +1339,7 @@ static void nbd_trip(void *opaque) default: LOG("invalid request type (%u) received", request.type); invalid_request: - reply.error = -EINVAL; + reply.error = EINVAL; error_reply: if (nbd_co_send_reply(req, &reply, 0) < 0) { goto out; diff --git a/qapi-schema.json b/qapi-schema.json index 2b3e275983..ac9594d66d 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -410,19 +410,43 @@ 'cache-miss': 'int', 'cache-miss-rate': 'number', 'overflow': 'int' } } +# @MigrationStatus: +# +# An enumeration of migration status. +# +# @none: no migration has ever happened. +# +# @setup: migration process has been initiated. +# +# @cancelling: in the process of cancelling migration. +# +# @cancelled: cancelling migration is finished. +# +# @active: in the process of doing migration. +# +# @completed: migration is finished. +# +# @failed: some error occurred during migration process. +# +# Since: 2.3 +# +## +{ 'enum': 'MigrationStatus', + 'data': [ 'none', 'setup', 'cancelling', 'cancelled', + 'active', 'completed', 'failed' ] } + ## # @MigrationInfo # # Information about current migration process. # -# @status: #optional string describing the current migration status. -# As of 0.14.0 this can be 'setup', 'active', 'completed', 'failed' or -# 'cancelled'. If this field is not returned, no migration process +# @status: #optional @MigrationStatus describing the current migration status. +# If this field is not returned, no migration process # has been initiated # # @ram: #optional @MigrationStats containing detailed migration # status, only returned if status is 'active' or -# 'completed'. 'comppleted' (since 1.2) +# 'completed'(since 1.2) # # @disk: #optional @MigrationStats containing detailed disk migration # status, only returned if status is 'active' and it is a block @@ -453,7 +477,7 @@ # Since: 0.14.0 ## { 'type': 'MigrationInfo', - 'data': {'*status': 'str', '*ram': 'MigrationStats', + 'data': {'*status': 'MigrationStatus', '*ram': 'MigrationStats', '*disk': 'MigrationStats', '*xbzrle-cache': 'XBZRLECacheStats', '*total-time': 'int', @@ -1750,6 +1774,9 @@ # Returns: nothing on success # # Since: 2.3 +# Note: It's a bad idea to use a string for the uri, but it needs to stay +# compatible with -incoming and the format of the uri is already exposed +# above libvirt ## { 'command': 'migrate-incoming', 'data': {'uri': 'str' } } diff --git a/qapi/block-core.json b/qapi/block-core.json index 90586a5949..42c885047f 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -1961,10 +1961,6 @@ # @write-threshold: configured threshold for the block device, bytes. # Use 0 to disable the threshold. # -# Returns: Nothing on success -# If @node name is not found on the block device graph, -# DeviceNotFound -# # Since: 2.3 ## { 'command': 'block-set-write-threshold', diff --git a/qdev-monitor.c b/qdev-monitor.c index 5d30ac534c..1d87f573e8 100644 --- a/qdev-monitor.c +++ b/qdev-monitor.c @@ -678,6 +678,63 @@ void hmp_info_qdm(Monitor *mon, const QDict *qdict) qdev_print_devinfos(true); } +typedef struct QOMCompositionState { + Monitor *mon; + int indent; +} QOMCompositionState; + +static void print_qom_composition(Monitor *mon, Object *obj, int indent); + +static int print_qom_composition_child(Object *obj, void *opaque) +{ + QOMCompositionState *s = opaque; + + print_qom_composition(s->mon, obj, s->indent); + + return 0; +} + +static void print_qom_composition(Monitor *mon, Object *obj, int indent) +{ + QOMCompositionState s = { + .mon = mon, + .indent = indent + 2, + }; + char *name; + + if (obj == object_get_root()) { + name = g_strdup(""); + } else { + name = object_get_canonical_path_component(obj); + } + monitor_printf(mon, "%*s/%s (%s)\n", indent, "", name, + object_get_typename(obj)); + g_free(name); + object_child_foreach(obj, print_qom_composition_child, &s); +} + +void hmp_info_qom_tree(Monitor *mon, const QDict *dict) +{ + const char *path = qdict_get_try_str(dict, "path"); + Object *obj; + bool ambiguous = false; + + if (path) { + obj = object_resolve_path(path, &ambiguous); + if (!obj) { + monitor_printf(mon, "Path '%s' could not be resolved.\n", path); + return; + } + if (ambiguous) { + monitor_printf(mon, "Warning: Path '%s' is ambiguous.\n", path); + return; + } + } else { + obj = qdev_get_machine(); + } + print_qom_composition(mon, obj, 0); +} + int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data) { Error *local_err = NULL; diff --git a/qemu-coroutine-io.c b/qemu-coroutine-io.c index d4049260da..28dc7351ac 100644 --- a/qemu-coroutine-io.c +++ b/qemu-coroutine-io.c @@ -45,7 +45,7 @@ qemu_co_sendv_recvv(int sockfd, struct iovec *iov, unsigned iov_cnt, if (err == EAGAIN || err == EWOULDBLOCK) { qemu_coroutine_yield(); } else if (done == 0) { - return -1; + return -err; } else { break; } diff --git a/qemu-doc.texi b/qemu-doc.texi index f5b0dc4588..8aa6dbf5d7 100644 --- a/qemu-doc.texi +++ b/qemu-doc.texi @@ -539,8 +539,8 @@ storage. @item qcow2 QEMU image format, the most versatile format. Use it to have smaller images (useful if your filesystem does not supports holes, for example -on Windows), optional AES encryption, zlib based compression and -support of multiple VM snapshots. +on Windows), zlib based compression and support of multiple VM +snapshots. Supported options: @table @code @@ -574,9 +574,10 @@ original file must then be securely erased using a program like shred, though even this is ineffective with many modern storage technologies. @end itemize -Use of qcow / qcow2 encryption is thus strongly discouraged. Users are -recommended to use an alternative encryption technology such as the -Linux dm-crypt / LUKS system. +Use of qcow / qcow2 encryption with QEMU is deprecated, and support for +it will go away in a future release. Users are recommended to use an +alternative encryption technology such as the Linux dm-crypt / LUKS +system. @item cluster_size Changes the qcow2 cluster size (must be between 512 and 2M). Smaller cluster diff --git a/qemu-img.c b/qemu-img.c index 5af6f455df..9dddfbefce 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -274,8 +274,7 @@ static int print_block_option_help(const char *filename, const char *fmt) if (filename) { proto_drv = bdrv_find_protocol(filename, true, &local_err); if (!proto_drv) { - qerror_report_err(local_err); - error_free(local_err); + error_report_err(local_err); qemu_opts_free(create_opts); return 1; } @@ -1526,8 +1525,7 @@ static int img_convert(int argc, char **argv) proto_drv = bdrv_find_protocol(out_filename, true, &local_err); if (!proto_drv) { - qerror_report_err(local_err); - error_free(local_err); + error_report_err(local_err); ret = -1; goto out; } @@ -1554,8 +1552,7 @@ static int img_convert(int argc, char **argv) if (options) { qemu_opts_do_parse(opts, options, NULL, &local_err); if (local_err) { - error_report("Invalid options for file format '%s'", out_fmt); - error_free(local_err); + error_report_err(local_err); ret = -1; goto out; } @@ -3001,8 +2998,7 @@ static int img_amend(int argc, char **argv) if (options) { qemu_opts_do_parse(opts, options, NULL, &err); if (err) { - error_report("Invalid options for file format '%s'", fmt); - error_free(err); + error_report_err(err); ret = -1; goto out; } diff --git a/qemu-nbd.c b/qemu-nbd.c index 064b000b43..7e690fff7e 100644 --- a/qemu-nbd.c +++ b/qemu-nbd.c @@ -142,8 +142,9 @@ static void read_partition(uint8_t *p, struct partition_record *r) r->end_head = p[5]; r->end_cylinder = p[7] | ((p[6] << 2) & 0x300); r->end_sector = p[6] & 0x3f; - r->start_sector_abs = p[8] | p[9] << 8 | p[10] << 16 | p[11] << 24; - r->nb_sectors_abs = p[12] | p[13] << 8 | p[14] << 16 | p[15] << 24; + + r->start_sector_abs = le32_to_cpup((uint32_t *)(p + 8)); + r->nb_sectors_abs = le32_to_cpup((uint32_t *)(p + 12)); } static int find_partition(BlockBackend *blk, int partition, @@ -167,8 +168,9 @@ static int find_partition(BlockBackend *blk, int partition, for (i = 0; i < 4; i++) { read_partition(&data[446 + 16 * i], &mbr[i]); - if (!mbr[i].nb_sectors_abs) + if (!mbr[i].system || !mbr[i].nb_sectors_abs) { continue; + } if (mbr[i].system == 0xF || mbr[i].system == 0x5) { struct partition_record ext[4]; @@ -182,8 +184,9 @@ static int find_partition(BlockBackend *blk, int partition, for (j = 0; j < 4; j++) { read_partition(&data1[446 + 16 * j], &ext[j]); - if (!ext[j].nb_sectors_abs) + if (!ext[j].system || !ext[j].nb_sectors_abs) { continue; + } if ((ext_partnum + j + 1) == partition) { *offset = (uint64_t)ext[j].start_sector_abs << 9; @@ -276,7 +279,6 @@ static void *nbd_client_thread(void *arg) { char *device = arg; off_t size; - size_t blocksize; uint32_t nbdflags; int fd, sock; int ret; @@ -289,7 +291,7 @@ static void *nbd_client_thread(void *arg) } ret = nbd_receive_negotiate(sock, NULL, &nbdflags, - &size, &blocksize, &local_error); + &size, &local_error); if (ret < 0) { if (local_error) { fprintf(stderr, "%s\n", error_get_pretty(local_error)); @@ -305,7 +307,7 @@ static void *nbd_client_thread(void *arg) goto out_socket; } - ret = nbd_init(fd, sock, nbdflags, size, blocksize); + ret = nbd_init(fd, sock, nbdflags, size); if (ret < 0) { goto out_fd; } @@ -633,7 +635,9 @@ int main(int argc, char **argv) * print errors and exit with the proper status code. */ pid = fork(); - if (pid == 0) { + if (pid < 0) { + err(EXIT_FAILURE, "Failed to fork"); + } else if (pid == 0) { close(stderr_fd[0]); ret = qemu_daemon(1, 0); @@ -715,6 +719,10 @@ int main(int argc, char **argv) bs->detect_zeroes = detect_zeroes; fd_size = blk_getlength(blk); + if (fd_size < 0) { + errx(EXIT_FAILURE, "Failed to determine the image length: %s", + strerror(-fd_size)); + } if (partition != -1) { ret = find_partition(blk, partition, &dev_offset, &fd_size); @@ -724,7 +732,11 @@ int main(int argc, char **argv) } } - exp = nbd_export_new(blk, dev_offset, fd_size, nbdflags, nbd_export_closed); + exp = nbd_export_new(blk, dev_offset, fd_size, nbdflags, nbd_export_closed, + &local_err); + if (!exp) { + errx(EXIT_FAILURE, "%s", error_get_pretty(local_err)); + } if (sockpath) { fd = unix_socket_incoming(sockpath); diff --git a/qemu-options.hx b/qemu-options.hx index c513352ea8..16ff72c9e8 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -1403,7 +1403,7 @@ DEF("smbios", HAS_ARG, QEMU_OPTION_smbios, " [,asset=str][,part=str]\n" " specify SMBIOS type 4 fields\n" "-smbios type=17[,loc_pfx=str][,bank=str][,manufacturer=str][,serial=str]\n" - " [,asset=str][,part=str]\n" + " [,asset=str][,part=str][,speed=%d]\n" " specify SMBIOS type 17 fields\n", QEMU_ARCH_I386) STEXI @@ -1426,7 +1426,7 @@ Specify SMBIOS type 3 fields @item -smbios type=4[,sock_pfx=@var{str}][,manufacturer=@var{str}][,version=@var{str}][,serial=@var{str}][,asset=@var{str}][,part=@var{str}] Specify SMBIOS type 4 fields -@item -smbios type=17[,loc_pfx=@var{str}][,bank=@var{str}][,manufacturer=@var{str}][,serial=@var{str}][,asset=@var{str}][,part=@var{str}] +@item -smbios type=17[,loc_pfx=@var{str}][,bank=@var{str}][,manufacturer=@var{str}][,serial=@var{str}][,asset=@var{str}][,part=@var{str}][,speed=@var{%d}] Specify SMBIOS type 17 fields ETEXI diff --git a/qga/commands-posix.c b/qga/commands-posix.c index d5bb5cb5da..ba8de62436 100644 --- a/qga/commands-posix.c +++ b/qga/commands-posix.c @@ -2283,6 +2283,7 @@ GuestMemoryBlockInfo *qmp_guest_get_memory_block_info(Error **errp) buf = g_malloc0(20); ga_read_sysfs_file(dirfd, "block_size_bytes", buf, 20, &local_err); + close(dirfd); if (local_err) { g_free(buf); error_propagate(errp, local_err); diff --git a/qmp-commands.hx b/qmp-commands.hx index 06639248f2..87f0f01636 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -276,7 +276,6 @@ EQMP .args_type = "device:O", .params = "driver[,prop=value][,...]", .help = "add device, like -device on the command line", - .user_print = monitor_user_noop, .mhandler.cmd_new = do_device_add, }, @@ -786,7 +785,6 @@ EQMP .args_type = "protocol:s,hostname:s,port:i?,tls-port:i?,cert-subject:s?", .params = "protocol hostname port tls-port cert-subject", .help = "send migration info to spice/vnc client", - .user_print = monitor_user_noop, .mhandler.cmd_async = client_migrate_info, .flags = MONITOR_CMD_ASYNC, }, @@ -822,7 +820,6 @@ EQMP .args_type = "paging:b,protocol:s,begin:i?,end:i?,format:s?", .params = "-p protocol [begin] [length] [format]", .help = "dump guest memory to file", - .user_print = monitor_user_noop, .mhandler.cmd_new = qmp_marshal_input_dump_guest_memory, }, @@ -1862,7 +1859,6 @@ EQMP .args_type = "", .params = "", .help = "enable QMP capabilities", - .user_print = monitor_user_noop, .mhandler.cmd_new = do_qmp_capabilities, }, diff --git a/qom/cpu.c b/qom/cpu.c index 970377e960..108bfa205a 100644 --- a/qom/cpu.c +++ b/qom/cpu.c @@ -96,7 +96,7 @@ void cpu_get_memory_mapping(CPUState *cpu, MemoryMappingList *list, { CPUClass *cc = CPU_GET_CLASS(cpu); - return cc->get_memory_mapping(cpu, list, errp); + cc->get_memory_mapping(cpu, list, errp); } static void cpu_common_get_memory_mapping(CPUState *cpu, diff --git a/savevm.c b/savevm.c index e7d97eea93..3b0e222cb3 100644 --- a/savevm.c +++ b/savevm.c @@ -941,8 +941,7 @@ int qemu_loadvm_state(QEMUFile *f) int file_error_after_eof = -1; if (qemu_savevm_state_blocked(&local_err)) { - error_report("%s", error_get_pretty(local_err)); - error_free(local_err); + error_report_err(local_err); return -EINVAL; } diff --git a/scripts/coverity-model.c b/scripts/coverity-model.c index 58356afa66..cdda2591d9 100644 --- a/scripts/coverity-model.c +++ b/scripts/coverity-model.c @@ -123,7 +123,7 @@ void *g_malloc_n(size_t nmemb, size_t size) __coverity_negative_sink__(nmemb); __coverity_negative_sink__(size); sz = nmemb * size; - ptr = __coverity_alloc__(size); + ptr = __coverity_alloc__(sz); __coverity_mark_as_uninitialized_buffer__(ptr); __coverity_mark_as_afm_allocated__(ptr, "g_free"); return ptr; @@ -137,7 +137,7 @@ void *g_malloc0_n(size_t nmemb, size_t size) __coverity_negative_sink__(nmemb); __coverity_negative_sink__(size); sz = nmemb * size; - ptr = __coverity_alloc__(size); + ptr = __coverity_alloc__(sz); __coverity_writeall0__(ptr); __coverity_mark_as_afm_allocated__(ptr, "g_free"); return ptr; @@ -151,7 +151,7 @@ void *g_realloc_n(void *ptr, size_t nmemb, size_t size) __coverity_negative_sink__(size); sz = nmemb * size; __coverity_escape__(ptr); - ptr = __coverity_alloc__(size); + ptr = __coverity_alloc__(sz); /* * Memory beyond the old size isn't actually initialized. Can't * model that. See Coverity's realloc() model diff --git a/scripts/make_device_config.sh b/scripts/make_device_config.sh index 7958086132..c1afb3ffaa 100644 --- a/scripts/make_device_config.sh +++ b/scripts/make_device_config.sh @@ -1,10 +1,12 @@ #! /bin/sh -# Construct a target device config file from a default, pulling in any -# files from include directives. +# Writes a target device config file to stdout, from a default and from +# include directives therein. Also emits Makefile dependencies. +# +# Usage: make_device_config.sh SRC DEPFILE-NAME DEPFILE-TARGET > DEST -dest=$1 -dep=`dirname $1`-`basename $1`.d -src=$2 +src=$1 +dep=$2 +target=$3 src_dir=`dirname $src` all_includes= @@ -22,7 +24,7 @@ while [ -n "$f" ] ; do [ $? = 0 ] || exit 1 all_includes="$all_includes $f" done -process_includes $src > $dest +process_includes $src -cat $src $all_includes | grep -v '^include' > $dest -echo "$1: $all_includes" > $dep +cat $src $all_includes | grep -v '^include' +echo "$target: $all_includes" > $dep diff --git a/scripts/qmp/qom-tree b/scripts/qmp/qom-tree new file mode 100755 index 0000000000..aea11d4b1a --- /dev/null +++ b/scripts/qmp/qom-tree @@ -0,0 +1,70 @@ +#!/usr/bin/python +## +# QEMU Object Model test tools +# +# Copyright IBM, Corp. 2011 +# Copyright (c) 2013 SUSE LINUX Products GmbH +# +# Authors: +# Anthony Liguori <aliguori@amazon.com> +# Andreas Faerber <afaerber@suse.de> +# +# This work is licensed under the terms of the GNU GPL, version 2 or later. See +# the COPYING file in the top-level directory. +## + +import sys +import os +from qmp import QEMUMonitorProtocol + +cmd, args = sys.argv[0], sys.argv[1:] +socket_path = None +path = None +prop = None + +def usage(): + return '''environment variables: + QMP_SOCKET=<path | addr:port> +usage: + %s [-h] [-s <QMP socket path | addr:port>] [<path>] +''' % cmd + +def usage_error(error_msg = "unspecified error"): + sys.stderr.write('%s\nERROR: %s\n' % (usage(), error_msg)) + exit(1) + +if len(args) > 0: + if args[0] == "-h": + print usage() + exit(0); + elif args[0] == "-s": + try: + socket_path = args[1] + except: + usage_error("missing argument: QMP socket path or address"); + args = args[2:] + +if not socket_path: + if os.environ.has_key('QMP_SOCKET'): + socket_path = os.environ['QMP_SOCKET'] + else: + usage_error("no QMP socket path or address given"); + +srv = QEMUMonitorProtocol(socket_path) +srv.connect() + +def list_node(path): + print '%s' % path + items = srv.command('qom-list', path=path) + for item in items: + if not item['type'].startswith('child<'): + try: + print ' %s: %s (%s)' % (item['name'], srv.command('qom-get', path=path, property=item['name']), item['type']) + except: + print ' %s: <EXCEPTION> (%s)' % (item['name'], item['type']) + print '' + for item in items: + if item['type'].startswith('child<'): + list_node(path + '/' + item['name']) + +list_node('/machine') diff --git a/target-cris/opcode-cris.h b/target-cris/opcode-cris.h index 779d4aab70..e7ebb98cd0 100644 --- a/target-cris/opcode-cris.h +++ b/target-cris/opcode-cris.h @@ -108,16 +108,6 @@ struct cris_support_reg }; extern const struct cris_support_reg cris_support_regs[]; -struct cris_cond15 -{ - /* The name of the condition. */ - const char *const name; - - /* What CPU version this condition name applies to. */ - enum cris_insn_version_usage applicable_version; -}; -extern const struct cris_cond15 cris_conds15[]; - /* Opcode-dependent constants. */ #define AUTOINCR_BIT (0x04) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index ed7e5d5de3..f01690bfea 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -2076,8 +2076,7 @@ static void x86_cpu_load_def(X86CPU *cpu, X86CPUDefinition *def, Error **errp) } -X86CPU *cpu_x86_create(const char *cpu_model, DeviceState *icc_bridge, - Error **errp) +X86CPU *cpu_x86_create(const char *cpu_model, Error **errp) { X86CPU *cpu = NULL; X86CPUClass *xcc; @@ -2108,15 +2107,6 @@ X86CPU *cpu_x86_create(const char *cpu_model, DeviceState *icc_bridge, cpu = X86_CPU(object_new(object_class_get_name(oc))); -#ifndef CONFIG_USER_ONLY - if (icc_bridge == NULL) { - error_setg(&error, "Invalid icc-bridge value"); - goto out; - } - qdev_set_parent_bus(DEVICE(cpu), qdev_get_child_bus(icc_bridge, "icc")); - object_unref(OBJECT(cpu)); -#endif - x86_cpu_parse_featurestr(CPU(cpu), features, &error); if (error) { goto out; @@ -2139,7 +2129,7 @@ X86CPU *cpu_x86_init(const char *cpu_model) Error *error = NULL; X86CPU *cpu; - cpu = cpu_x86_create(cpu_model, NULL, &error); + cpu = cpu_x86_create(cpu_model, &error); if (error) { goto out; } diff --git a/target-i386/cpu.h b/target-i386/cpu.h index e4c27b1fa8..15db6d7aba 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -982,8 +982,7 @@ typedef struct CPUX86State { #include "cpu-qom.h" X86CPU *cpu_x86_init(const char *cpu_model); -X86CPU *cpu_x86_create(const char *cpu_model, DeviceState *icc_bridge, - Error **errp); +X86CPU *cpu_x86_create(const char *cpu_model, Error **errp); int cpu_x86_exec(CPUX86State *s); void x86_cpu_list(FILE *f, fprintf_function cpu_fprintf); void x86_cpudef_setup(void); diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c index 349f2a0033..46528de325 100644 --- a/target-mips/dsp_helper.c +++ b/target-mips/dsp_helper.c @@ -3678,7 +3678,7 @@ void cpu_wrdsp(uint32_t rs, uint32_t mask_num, CPUMIPSState *env) void helper_wrdsp(target_ulong rs, target_ulong mask_num, CPUMIPSState *env) { - return cpu_wrdsp(rs, mask_num, env); + cpu_wrdsp(rs, mask_num, env); } uint32_t cpu_rddsp(uint32_t mask_num, CPUMIPSState *env) diff --git a/target-mips/translate.c b/target-mips/translate.c index 9059bfd9f1..fd063a2aae 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -10531,14 +10531,25 @@ static void gen_rdhwr(DisasContext *ctx, int rt, int rd) tcg_temp_free(t0); } +static inline void clear_branch_hflags(DisasContext *ctx) +{ + ctx->hflags &= ~MIPS_HFLAG_BMASK; + if (ctx->bstate == BS_NONE) { + save_cpu_state(ctx, 0); + } else { + /* it is not safe to save ctx->hflags as hflags may be changed + in execution time by the instruction in delay / forbidden slot. */ + tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK); + } +} + static void gen_branch(DisasContext *ctx, int insn_bytes) { if (ctx->hflags & MIPS_HFLAG_BMASK) { int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK; /* Branches completion */ - ctx->hflags &= ~MIPS_HFLAG_BMASK; + clear_branch_hflags(ctx); ctx->bstate = BS_BRANCH; - save_cpu_state(ctx, 0); /* FIXME: Need to clear can_do_io. */ switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) { case MIPS_HFLAG_FBNSLOT: @@ -10596,8 +10607,8 @@ static void gen_branch(DisasContext *ctx, int insn_bytes) tcg_gen_exit_tb(0); break; default: - MIPS_DEBUG("unknown branch"); - break; + fprintf(stderr, "unknown branch 0x%x\n", proc_hflags); + abort(); } } } @@ -18403,12 +18414,14 @@ static void gen_msa(CPUMIPSState *env, DisasContext *ctx) case OPC_LD_H: case OPC_LD_W: case OPC_LD_D: + save_cpu_state(ctx, 1); gen_helper_msa_ld_df(cpu_env, tdf, twd, trs, ts10); break; case OPC_ST_B: case OPC_ST_H: case OPC_ST_W: case OPC_ST_D: + save_cpu_state(ctx, 1); gen_helper_msa_st_df(cpu_env, tdf, twd, trs, ts10); break; } @@ -18438,6 +18451,7 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx) if (ctx->pc & 0x3) { env->CP0_BadVAddr = ctx->pc; generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL); + ctx->bstate = BS_STOP; return; } diff --git a/target-moxie/mmu.h b/target-moxie/mmu.h index e01ffc22c4..abc79297cd 100644 --- a/target-moxie/mmu.h +++ b/target-moxie/mmu.h @@ -6,11 +6,11 @@ typedef struct { uint32_t phy; uint32_t pfn; - int g:1; - int v:1; - int k:1; - int w:1; - int e:1; + unsigned g:1; + unsigned v:1; + unsigned k:1; + unsigned w:1; + unsigned e:1; int cause_op; } MoxieMMUResult; diff --git a/target-tricore/translate.c b/target-tricore/translate.c index 15a24f7c98..0b7cf06f94 100644 --- a/target-tricore/translate.c +++ b/target-tricore/translate.c @@ -1111,7 +1111,7 @@ gen_m16add32_q(TCGv ret, TCGv arg1, TCGv arg2, TCGv arg3, uint32_t n) TCGv temp2 = tcg_temp_new(); if (n == 0) { tcg_gen_mul_tl(temp, arg2, arg3); - } else { /* n is exspected to be 1 */ + } else { /* n is expected to be 1 */ tcg_gen_mul_tl(temp, arg2, arg3); tcg_gen_shli_tl(temp, temp, 1); /* catch special case r1 = r2 = 0x8000 */ @@ -1131,7 +1131,7 @@ gen_m16adds32_q(TCGv ret, TCGv arg1, TCGv arg2, TCGv arg3, uint32_t n) TCGv temp2 = tcg_temp_new(); if (n == 0) { tcg_gen_mul_tl(temp, arg2, arg3); - } else { /* n is exspected to be 1 */ + } else { /* n is expected to be 1 */ tcg_gen_mul_tl(temp, arg2, arg3); tcg_gen_shli_tl(temp, temp, 1); /* catch special case r1 = r2 = 0x8000 */ @@ -1156,7 +1156,7 @@ gen_m16add64_q(TCGv rl, TCGv rh, TCGv arg1_low, TCGv arg1_high, TCGv arg2, if (n == 0) { tcg_gen_mul_tl(temp, arg2, arg3); - } else { /* n is exspected to be 1 */ + } else { /* n is expected to be 1 */ tcg_gen_mul_tl(temp, arg2, arg3); tcg_gen_shli_tl(temp, temp, 1); /* catch special case r1 = r2 = 0x8000 */ @@ -1188,7 +1188,7 @@ gen_m16adds64_q(TCGv rl, TCGv rh, TCGv arg1_low, TCGv arg1_high, TCGv arg2, if (n == 0) { tcg_gen_mul_tl(temp, arg2, arg3); - } else { /* n is exspected to be 1 */ + } else { /* n is expected to be 1 */ tcg_gen_mul_tl(temp, arg2, arg3); tcg_gen_shli_tl(temp, temp, 1); /* catch special case r1 = r2 = 0x8000 */ @@ -1975,7 +1975,7 @@ gen_m16sub32_q(TCGv ret, TCGv arg1, TCGv arg2, TCGv arg3, uint32_t n) TCGv temp2 = tcg_temp_new(); if (n == 0) { tcg_gen_mul_tl(temp, arg2, arg3); - } else { /* n is exspected to be 1 */ + } else { /* n is expected to be 1 */ tcg_gen_mul_tl(temp, arg2, arg3); tcg_gen_shli_tl(temp, temp, 1); /* catch special case r1 = r2 = 0x8000 */ @@ -1995,7 +1995,7 @@ gen_m16subs32_q(TCGv ret, TCGv arg1, TCGv arg2, TCGv arg3, uint32_t n) TCGv temp2 = tcg_temp_new(); if (n == 0) { tcg_gen_mul_tl(temp, arg2, arg3); - } else { /* n is exspected to be 1 */ + } else { /* n is expected to be 1 */ tcg_gen_mul_tl(temp, arg2, arg3); tcg_gen_shli_tl(temp, temp, 1); /* catch special case r1 = r2 = 0x8000 */ @@ -2020,7 +2020,7 @@ gen_m16sub64_q(TCGv rl, TCGv rh, TCGv arg1_low, TCGv arg1_high, TCGv arg2, if (n == 0) { tcg_gen_mul_tl(temp, arg2, arg3); - } else { /* n is exspected to be 1 */ + } else { /* n is expected to be 1 */ tcg_gen_mul_tl(temp, arg2, arg3); tcg_gen_shli_tl(temp, temp, 1); /* catch special case r1 = r2 = 0x8000 */ @@ -2052,7 +2052,7 @@ gen_m16subs64_q(TCGv rl, TCGv rh, TCGv arg1_low, TCGv arg1_high, TCGv arg2, if (n == 0) { tcg_gen_mul_tl(temp, arg2, arg3); - } else { /* n is exspected to be 1 */ + } else { /* n is expected to be 1 */ tcg_gen_mul_tl(temp, arg2, arg3); tcg_gen_shli_tl(temp, temp, 1); /* catch special case r1 = r2 = 0x8000 */ @@ -2560,7 +2560,7 @@ gen_mul_q(TCGv rl, TCGv rh, TCGv arg1, TCGv arg2, uint32_t n, uint32_t up_shift) } /* reset v bit */ tcg_gen_movi_tl(cpu_PSW_V, 0); - } else { /* n is exspected to be 1 */ + } else { /* n is expected to be 1 */ tcg_gen_ext_i32_i64(temp_64, arg1); tcg_gen_ext_i32_i64(temp2_64, arg2); @@ -2572,7 +2572,7 @@ gen_mul_q(TCGv rl, TCGv rh, TCGv arg1, TCGv arg2, uint32_t n, uint32_t up_shift) tcg_gen_shri_i64(temp_64, temp_64, up_shift - 1); } tcg_gen_extr_i64_i32(rl, rh, temp_64); - /* overflow only occours if r1 = r2 = 0x8000 */ + /* overflow only occurs if r1 = r2 = 0x8000 */ if (up_shift == 0) {/* result is 64 bit */ tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_PSW_V, rh, 0x80000000); @@ -2605,7 +2605,7 @@ gen_mul_q_16(TCGv ret, TCGv arg1, TCGv arg2, uint32_t n) TCGv temp = tcg_temp_new(); if (n == 0) { tcg_gen_mul_tl(ret, arg1, arg2); - } else { /* n is exspected to be 1 */ + } else { /* n is expected to be 1 */ tcg_gen_mul_tl(ret, arg1, arg2); tcg_gen_shli_tl(ret, ret, 1); /* catch special case r1 = r2 = 0x8000 */ diff --git a/tests/Makefile b/tests/Makefile index 1ef95c95cb..55aa7452b4 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -173,6 +173,7 @@ gcov-files-i386-y += hw/usb/dev-hid.c gcov-files-i386-y += hw/usb/dev-storage.c check-qtest-i386-y += tests/usb-hcd-xhci-test$(EXESUF) gcov-files-i386-y += hw/usb/hcd-xhci.c +check-qtest-i386-y += tests/pc-cpu-test$(EXESUF) check-qtest-i386-$(CONFIG_LINUX) += tests/vhost-user-test$(EXESUF) check-qtest-x86_64-y = $(check-qtest-i386-y) gcov-files-i386-y += i386-softmmu/hw/timer/mc146818rtc.c @@ -363,6 +364,7 @@ tests/usb-hcd-ohci-test$(EXESUF): tests/usb-hcd-ohci-test.o $(libqos-usb-obj-y) tests/usb-hcd-uhci-test$(EXESUF): tests/usb-hcd-uhci-test.o $(libqos-usb-obj-y) tests/usb-hcd-ehci-test$(EXESUF): tests/usb-hcd-ehci-test.o $(libqos-usb-obj-y) tests/usb-hcd-xhci-test$(EXESUF): tests/usb-hcd-xhci-test.o $(libqos-usb-obj-y) +tests/pc-cpu-test$(EXESUF): tests/pc-cpu-test.o tests/vhost-user-test$(EXESUF): tests/vhost-user-test.o qemu-char.o qemu-timer.o $(qtest-obj-y) tests/qemu-iotests/socket_scm_helper$(EXESUF): tests/qemu-iotests/socket_scm_helper.o tests/test-qemu-opts$(EXESUF): tests/test-qemu-opts.o libqemuutil.a libqemustub.a diff --git a/tests/ahci-test.c b/tests/ahci-test.c index cf0b98b962..169e83b6ba 100644 --- a/tests/ahci-test.c +++ b/tests/ahci-test.c @@ -583,7 +583,7 @@ static void ahci_test_port_spec(AHCIQState *ahci, uint8_t port) ASSERT_BIT_CLEAR(reg, AHCI_PX_CMD_MPSP); } /* If, via CPD or MPSP we detect a drive, HPCP must be on. */ - if (BITANY(reg, AHCI_PX_CMD_CPD || AHCI_PX_CMD_MPSP)) { + if (BITANY(reg, AHCI_PX_CMD_CPD | AHCI_PX_CMD_MPSP)) { ASSERT_BIT_SET(reg, AHCI_PX_CMD_HPCP); } /* HPCP and ESP cannot both be active. */ diff --git a/tests/pc-cpu-test.c b/tests/pc-cpu-test.c new file mode 100644 index 0000000000..a0122d3d61 --- /dev/null +++ b/tests/pc-cpu-test.c @@ -0,0 +1,147 @@ +/* + * QTest testcase for PC CPUs + * + * Copyright (c) 2015 SUSE Linux GmbH + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include <glib.h> +#include <string.h> + +#include "qemu-common.h" +#include "libqtest.h" +#include "qemu/osdep.h" +#include "qapi/qmp/types.h" + +struct PCTestData { + const char *machine; + const char *cpu_model; + unsigned sockets; + unsigned cores; + unsigned threads; + unsigned maxcpus; +}; +typedef struct PCTestData PCTestData; + +static void test_pc_with_cpu_add(gconstpointer data) +{ + const PCTestData *s = data; + char *args; + QDict *response; + unsigned int i; + + args = g_strdup_printf("-machine %s -cpu %s " + "-smp sockets=%u,cores=%u,threads=%u,maxcpus=%u", + s->machine, s->cpu_model, + s->sockets, s->cores, s->threads, s->maxcpus); + qtest_start(args); + + for (i = s->sockets * s->cores * s->threads; i < s->maxcpus; i++) { + response = qmp("{ 'execute': 'cpu-add'," + " 'arguments': { 'id': %d } }", i); + g_assert(response); + g_assert(!qdict_haskey(response, "error")); + QDECREF(response); + } + + qtest_end(); + g_free(args); +} + +static void test_pc_without_cpu_add(gconstpointer data) +{ + const PCTestData *s = data; + char *args; + QDict *response; + + args = g_strdup_printf("-machine %s -cpu %s " + "-smp sockets=%u,cores=%u,threads=%u,maxcpus=%u", + s->machine, s->cpu_model, + s->sockets, s->cores, s->threads, s->maxcpus); + qtest_start(args); + + response = qmp("{ 'execute': 'cpu-add'," + " 'arguments': { 'id': %d } }", + s->sockets * s->cores * s->threads); + g_assert(response); + g_assert(qdict_haskey(response, "error")); + QDECREF(response); + + qtest_end(); + g_free(args); +} + +static void add_pc_test_cases(void) +{ + const char *arch = qtest_get_arch(); + QDict *response, *minfo; + QList *list; + const QListEntry *p; + QObject *qobj; + QString *qstr; + const char *mname, *path; + PCTestData *data; + + qtest_start("-machine none"); + response = qmp("{ 'execute': 'query-machines' }"); + g_assert(response); + list = qdict_get_qlist(response, "return"); + g_assert(list); + + for (p = qlist_first(list); p; p = qlist_next(p)) { + minfo = qobject_to_qdict(qlist_entry_obj(p)); + g_assert(minfo); + qobj = qdict_get(minfo, "name"); + g_assert(qobj); + qstr = qobject_to_qstring(qobj); + g_assert(qstr); + mname = qstring_get_str(qstr); + if (!g_str_has_prefix(mname, "pc-")) { + continue; + } + data = g_malloc(sizeof(PCTestData)); + data->machine = mname; + data->cpu_model = "Haswell"; /* 1.3+ theoretically */ + data->sockets = 1; + data->cores = 3; + data->threads = 2; + data->maxcpus = data->sockets * data->cores * data->threads * 2; + if (g_str_has_suffix(mname, "-1.4") || + (strcmp(mname, "pc-1.3") == 0) || + (strcmp(mname, "pc-1.2") == 0) || + (strcmp(mname, "pc-1.1") == 0) || + (strcmp(mname, "pc-1.0") == 0) || + (strcmp(mname, "pc-0.15") == 0) || + (strcmp(mname, "pc-0.14") == 0) || + (strcmp(mname, "pc-0.13") == 0) || + (strcmp(mname, "pc-0.12") == 0) || + (strcmp(mname, "pc-0.11") == 0) || + (strcmp(mname, "pc-0.10") == 0)) { + path = g_strdup_printf("/%s/cpu/%s/init/%ux%ux%u&maxcpus=%u", + arch, mname, data->sockets, data->cores, + data->threads, data->maxcpus); + g_test_add_data_func(path, data, test_pc_without_cpu_add); + } else { + path = g_strdup_printf("/%s/cpu/%s/add/%ux%ux%u&maxcpus=%u", + arch, mname, data->sockets, data->cores, + data->threads, data->maxcpus); + g_test_add_data_func(path, data, test_pc_with_cpu_add); + } + } + qtest_end(); +} + +int main(int argc, char **argv) +{ + const char *arch = qtest_get_arch(); + + g_test_init(&argc, &argv, NULL); + + if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) { + add_pc_test_cases(); + } + + return g_test_run(); +} diff --git a/tests/qemu-iotests/049.out b/tests/qemu-iotests/049.out index 765afdd2a6..9f93666c5b 100644 --- a/tests/qemu-iotests/049.out +++ b/tests/qemu-iotests/049.out @@ -188,6 +188,12 @@ qemu-img create -f qcow2 -o encryption=off TEST_DIR/t.qcow2 64M Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o encryption=on TEST_DIR/t.qcow2 64M +qemu-img: Encrypted images are deprecated +Support for them will be removed in a future release. +You can use 'qemu-img convert' to convert your image to an unencrypted one. +qemu-img: Encrypted images are deprecated +Support for them will be removed in a future release. +You can use 'qemu-img convert' to convert your image to an unencrypted one. Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=on cluster_size=65536 lazy_refcounts=off refcount_bits=16 == Check lazy_refcounts option (only with v3) == diff --git a/tests/qemu-iotests/051.out b/tests/qemu-iotests/051.out index 09895e6136..2890eac084 100644 --- a/tests/qemu-iotests/051.out +++ b/tests/qemu-iotests/051.out @@ -128,13 +128,11 @@ QEMU_PROG: Initialization of device ide-hd failed: Device initialization failed. Testing: -drive if=virtio QEMU X.Y.Z monitor - type 'help' for more information (qemu) QEMU_PROG: -drive if=virtio: Device needs media, but drive is empty -QEMU_PROG: -drive if=virtio: Device initialization failed. QEMU_PROG: -drive if=virtio: Device 'virtio-blk-pci' could not be initialized Testing: -drive if=scsi QEMU X.Y.Z monitor - type 'help' for more information -(qemu) QEMU_PROG: -drive if=scsi: Device needs media, but drive is empty -QEMU_PROG: Initialization of device lsi53c895a failed: Device initialization failed. +(qemu) QEMU_PROG: Initialization of device lsi53c895a failed: Device needs media, but drive is empty Testing: -drive if=none,id=disk -device ide-cd,drive=disk QEMU X.Y.Z monitor - type 'help' for more information diff --git a/tests/qemu-iotests/061.out b/tests/qemu-iotests/061.out index e70f9834d8..5ec248f79b 100644 --- a/tests/qemu-iotests/061.out +++ b/tests/qemu-iotests/061.out @@ -288,7 +288,6 @@ qemu-img: Error while amending options: Invalid argument Unknown compatibility level 0.42. qemu-img: Error while amending options: Invalid argument qemu-img: Invalid parameter 'foo' -qemu-img: Invalid options for file format 'qcow2' Changing the cluster size is not supported. qemu-img: Error while amending options: Operation not supported Changing the encryption flag is not supported. diff --git a/tests/qemu-iotests/087.out b/tests/qemu-iotests/087.out index 0ba2e43b40..c71bb3aa48 100644 --- a/tests/qemu-iotests/087.out +++ b/tests/qemu-iotests/087.out @@ -44,10 +44,19 @@ QMP_VERSION === Encrypted image === +qemu-img: Encrypted images are deprecated +Support for them will be removed in a future release. +You can use 'qemu-img convert' to convert your image to an unencrypted one. +qemu-img: Encrypted images are deprecated +Support for them will be removed in a future release. +You can use 'qemu-img convert' to convert your image to an unencrypted one. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encryption=on Testing: -S QMP_VERSION {"return": {}} +Encrypted images are deprecated +Support for them will be removed in a future release. +You can use 'qemu-img convert' to convert your image to an unencrypted one. {"error": {"class": "GenericError", "desc": "blockdev-add doesn't support encrypted devices"}} {"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"} @@ -57,6 +66,9 @@ QMP_VERSION Testing: QMP_VERSION {"return": {}} +Encrypted images are deprecated +Support for them will be removed in a future release. +You can use 'qemu-img convert' to convert your image to an unencrypted one. {"error": {"class": "GenericError", "desc": "Guest must be stopped for opening of encrypted image"}} {"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"} @@ -66,6 +78,12 @@ QMP_VERSION === Missing driver === +qemu-img: Encrypted images are deprecated +Support for them will be removed in a future release. +You can use 'qemu-img convert' to convert your image to an unencrypted one. +qemu-img: Encrypted images are deprecated +Support for them will be removed in a future release. +You can use 'qemu-img convert' to convert your image to an unencrypted one. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encryption=on Testing: -S QMP_VERSION diff --git a/tests/qemu-iotests/115 b/tests/qemu-iotests/115 new file mode 100755 index 0000000000..a6be1876aa --- /dev/null +++ b/tests/qemu-iotests/115 @@ -0,0 +1,95 @@ +#!/bin/bash +# +# Test case for non-self-referential qcow2 refcount blocks +# +# Copyright (C) 2014 Red Hat, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +# creator +owner=mreitz@redhat.com + +seq="$(basename $0)" +echo "QA output created by $seq" + +here="$PWD" +tmp=/tmp/$$ +status=1 # failure is the default! + +_cleanup() +{ + _cleanup_test_img +} +trap "_cleanup; exit \$status" 0 1 2 3 15 + +# get standard environment, filters and checks +. ./common.rc +. ./common.filter + +_supported_fmt qcow2 +_supported_proto file +_supported_os Linux +# This test relies on refcounts being 64 bits wide (which does not work with +# compat=0.10) +_unsupported_imgopts 'refcount_bits=\([^6]\|.\([^4]\|$\)\)' 'compat=0.10' + +echo +echo '=== Testing large refcount and L1 table ===' +echo + +# Create an image with an L1 table and a refcount table that each span twice the +# number of clusters which can be described by a single refblock; therefore, at +# least two refblocks cannot count their own refcounts because all the clusters +# they describe are part of the L1 table or refcount table. + +# One refblock can describe (with cluster_size=512 and refcount_bits=64) +# 512/8 = 64 clusters, therefore the L1 table should cover 128 clusters, which +# equals 128 * (512/8) = 8192 entries (actually, 8192 - 512/8 = 8129 would +# suffice, but it does not really matter). 8192 L2 tables can in turn describe +# 8192 * 512/8 = 524,288 clusters which cover a space of 256 MB. + +# Since with refcount_bits=64 every refcount block entry is 64 bits wide (just +# like the L2 table entries), the same calculation applies to the refcount table +# as well; the difference is that while for the L1 table the guest disk size is +# concerned, for the refcount table it is the image length that has to be at +# least 256 MB. We can achieve that by using preallocation=metadata for an image +# which has a guest disk size of 256 MB. + +IMGOPTS="$IMGOPTS,refcount_bits=64,cluster_size=512,preallocation=metadata" \ + _make_test_img 256M + +# We know for sure that the L1 and refcount tables do not overlap with any other +# structure because the metadata overlap checks would have caught that case. + +# Because qemu refuses to open qcow2 files whose L1 table does not cover the +# whole guest disk size, it is definitely large enough. On the other hand, to +# test whether the refcount table is large enough, we simply have to verify that +# indeed all the clusters are allocated, which is done by qemu-img check. + +# The final thing we need to test is whether the tables are actually covered by +# refcount blocks; since all clusters of the tables are referenced, we can use +# qemu-img check for that purpose, too. + +$QEMU_IMG check "$TEST_IMG" | \ + sed -e 's/^.* = \([0-9]\+\.[0-9]\+% allocated\).*\(clusters\)$/\1 \2/' \ + -e '/^Image end offset/d' + +# (Note that we cannot use _check_test_img because that function filters out the +# allocation status) + +# success, all done +echo '*** done' +rm -f $seq.full +status=0 diff --git a/tests/qemu-iotests/115.out b/tests/qemu-iotests/115.out new file mode 100644 index 0000000000..7b2c5e02f5 --- /dev/null +++ b/tests/qemu-iotests/115.out @@ -0,0 +1,8 @@ +QA output created by 115 + +=== Testing large refcount and L1 table === + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=268435456 preallocation='metadata' +No errors were found on the image. +100.00% allocated clusters +*** done diff --git a/tests/qemu-iotests/121 b/tests/qemu-iotests/121 new file mode 100755 index 0000000000..0912c3f0cb --- /dev/null +++ b/tests/qemu-iotests/121 @@ -0,0 +1,102 @@ +#!/bin/bash +# +# Test cases for qcow2 refcount table growth +# +# Copyright (C) 2015 Red Hat, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +# creator +owner=mreitz@redhat.com + +seq="$(basename $0)" +echo "QA output created by $seq" + +here="$PWD" +tmp=/tmp/$$ +status=1 # failure is the default! + +_cleanup() +{ + _cleanup_test_img +} +trap "_cleanup; exit \$status" 0 1 2 3 15 + +# get standard environment, filters and checks +. ./common.rc +. ./common.filter + +_supported_fmt qcow2 +_supported_proto file +_supported_os Linux + +echo +echo '=== New refcount structures may not conflict with existing structures ===' + +echo +echo '--- Test 1 ---' +echo + +# Preallocation speeds up the write operation, but preallocating everything will +# destroy the purpose of the write; so preallocate one KB less than what would +# cause a reftable growth... +IMGOPTS='preallocation=metadata,cluster_size=1k' _make_test_img 64512K +# ...and make the image the desired size afterwards. +$QEMU_IMG resize "$TEST_IMG" 65M + +# The first write results in a growth of the refcount table during an allocation +# which has precisely the required size so that the new refcount block allocated +# in alloc_refcount_block() is right after cluster_index; this did lead to a +# different refcount block being written to disk (a zeroed cluster) than what is +# cached (a refblock with one entry having a refcount of 1), and the second +# write would then result in that cached cluster being marked dirty and then +# in it being written to disk. +# This should not happen, the new refcount structures may not conflict with +# new_block. +# (Note that for some reason, 'write 63M 1K' does not trigger the problem) +$QEMU_IO -c 'write 62M 1025K' -c 'write 64M 1M' "$TEST_IMG" | _filter_qemu_io + +_check_test_img + + +echo +echo '--- Test 2 ---' +echo + +IMGOPTS='preallocation=metadata,cluster_size=1k' _make_test_img 64513K +# This results in an L1 table growth which in turn results in some clusters at +# the start of the image becoming free +$QEMU_IMG resize "$TEST_IMG" 65M + +# This write results in a refcount table growth; but the refblock allocated +# immediately before that (new_block) takes cluster index 4 (which is now free) +# and is thus not self-describing (in contrast to test 1, where new_block was +# self-describing). The refcount table growth algorithm then used to place the +# new refcount structures at cluster index 65536 (which is the same as the +# cluster_index parameter in this case), allocating a new refcount block for +# that cluster while new_block already existed, leaking new_block. +# Therefore, the new refcount structures may not be put at cluster_index +# (because new_block already describes that cluster, and the new structures try +# to be self-describing). +$QEMU_IO -c 'write 63M 130K' "$TEST_IMG" | _filter_qemu_io + +_check_test_img + + +# success, all done +echo +echo '*** done' +rm -f $seq.full +status=0 diff --git a/tests/qemu-iotests/121.out b/tests/qemu-iotests/121.out new file mode 100644 index 0000000000..ff18e2c618 --- /dev/null +++ b/tests/qemu-iotests/121.out @@ -0,0 +1,23 @@ +QA output created by 121 + +=== New refcount structures may not conflict with existing structures === + +--- Test 1 --- + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=66060288 preallocation='metadata' +Image resized. +wrote 1049600/1049600 bytes at offset 65011712 +1.001 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 1048576/1048576 bytes at offset 67108864 +1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +No errors were found on the image. + +--- Test 2 --- + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=66061312 preallocation='metadata' +Image resized. +wrote 133120/133120 bytes at offset 66060288 +130 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +No errors were found on the image. + +*** done diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group index 71f19d4ece..62621278e2 100644 --- a/tests/qemu-iotests/group +++ b/tests/qemu-iotests/group @@ -119,6 +119,8 @@ 112 rw auto 113 rw auto quick 114 rw auto quick +115 rw auto 116 rw auto quick +121 rw auto 123 rw auto quick 128 rw auto quick diff --git a/ui/vnc-auth-vencrypt.c b/ui/vnc-auth-vencrypt.c index bc7032e695..a420ccbd1d 100644 --- a/ui/vnc-auth-vencrypt.c +++ b/ui/vnc-auth-vencrypt.c @@ -93,7 +93,6 @@ static int vnc_start_vencrypt_handshake(struct VncState *vs) { } VNC_DEBUG("Handshake done, switching to TLS data mode\n"); - vs->tls.wiremode = VNC_WIREMODE_TLS; qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, vnc_client_write, vs); start_auth_vencrypt_subauth(vs); diff --git a/ui/vnc-tls.c b/ui/vnc-tls.c index 0f59f9b28e..eddd39b08e 100644 --- a/ui/vnc-tls.c +++ b/ui/vnc-tls.c @@ -334,82 +334,77 @@ static int vnc_set_gnutls_priority(gnutls_session_t s, int x509) int vnc_tls_client_setup(struct VncState *vs, int needX509Creds) { - VncStateTLS *tls; - VNC_DEBUG("Do TLS setup\n"); -#ifdef CONFIG_VNC_WS - if (vs->websocket) { - tls = &vs->ws_tls; - } else -#endif /* CONFIG_VNC_WS */ - { - tls = &vs->tls; - } if (vnc_tls_initialize() < 0) { VNC_DEBUG("Failed to init TLS\n"); vnc_client_error(vs); return -1; } - if (tls->session == NULL) { - if (gnutls_init(&tls->session, GNUTLS_SERVER) < 0) { + if (vs->tls.session == NULL) { + if (gnutls_init(&vs->tls.session, GNUTLS_SERVER) < 0) { vnc_client_error(vs); return -1; } - if (gnutls_set_default_priority(tls->session) < 0) { - gnutls_deinit(tls->session); - tls->session = NULL; + if (gnutls_set_default_priority(vs->tls.session) < 0) { + gnutls_deinit(vs->tls.session); + vs->tls.session = NULL; vnc_client_error(vs); return -1; } - if (vnc_set_gnutls_priority(tls->session, needX509Creds) < 0) { - gnutls_deinit(tls->session); - tls->session = NULL; + if (vnc_set_gnutls_priority(vs->tls.session, needX509Creds) < 0) { + gnutls_deinit(vs->tls.session); + vs->tls.session = NULL; vnc_client_error(vs); return -1; } if (needX509Creds) { - gnutls_certificate_server_credentials x509_cred = vnc_tls_initialize_x509_cred(vs->vd); + gnutls_certificate_server_credentials x509_cred = + vnc_tls_initialize_x509_cred(vs->vd); if (!x509_cred) { - gnutls_deinit(tls->session); - tls->session = NULL; + gnutls_deinit(vs->tls.session); + vs->tls.session = NULL; vnc_client_error(vs); return -1; } - if (gnutls_credentials_set(tls->session, GNUTLS_CRD_CERTIFICATE, x509_cred) < 0) { - gnutls_deinit(tls->session); - tls->session = NULL; + if (gnutls_credentials_set(vs->tls.session, + GNUTLS_CRD_CERTIFICATE, x509_cred) < 0) { + gnutls_deinit(vs->tls.session); + vs->tls.session = NULL; gnutls_certificate_free_credentials(x509_cred); vnc_client_error(vs); return -1; } if (vs->vd->tls.x509verify) { VNC_DEBUG("Requesting a client certificate\n"); - gnutls_certificate_server_set_request (tls->session, GNUTLS_CERT_REQUEST); + gnutls_certificate_server_set_request(vs->tls.session, + GNUTLS_CERT_REQUEST); } } else { - gnutls_anon_server_credentials_t anon_cred = vnc_tls_initialize_anon_cred(); + gnutls_anon_server_credentials_t anon_cred = + vnc_tls_initialize_anon_cred(); if (!anon_cred) { - gnutls_deinit(tls->session); - tls->session = NULL; + gnutls_deinit(vs->tls.session); + vs->tls.session = NULL; vnc_client_error(vs); return -1; } - if (gnutls_credentials_set(tls->session, GNUTLS_CRD_ANON, anon_cred) < 0) { - gnutls_deinit(tls->session); - tls->session = NULL; + if (gnutls_credentials_set(vs->tls.session, + GNUTLS_CRD_ANON, anon_cred) < 0) { + gnutls_deinit(vs->tls.session); + vs->tls.session = NULL; gnutls_anon_free_server_credentials(anon_cred); vnc_client_error(vs); return -1; } } - gnutls_transport_set_ptr(tls->session, (gnutls_transport_ptr_t)vs); - gnutls_transport_set_push_function(tls->session, vnc_tls_push); - gnutls_transport_set_pull_function(tls->session, vnc_tls_pull); + gnutls_transport_set_ptr(vs->tls.session, (gnutls_transport_ptr_t)vs); + gnutls_transport_set_push_function(vs->tls.session, vnc_tls_push); + gnutls_transport_set_pull_function(vs->tls.session, vnc_tls_pull); } return 0; } @@ -421,16 +416,7 @@ void vnc_tls_client_cleanup(struct VncState *vs) gnutls_deinit(vs->tls.session); vs->tls.session = NULL; } - vs->tls.wiremode = VNC_WIREMODE_CLEAR; g_free(vs->tls.dname); -#ifdef CONFIG_VNC_WS - if (vs->ws_tls.session) { - gnutls_deinit(vs->ws_tls.session); - vs->ws_tls.session = NULL; - } - vs->ws_tls.wiremode = VNC_WIREMODE_CLEAR; - g_free(vs->ws_tls.dname); -#endif /* CONFIG_VNC_WS */ } diff --git a/ui/vnc-tls.h b/ui/vnc-tls.h index 36a2227fec..f9829c7824 100644 --- a/ui/vnc-tls.h +++ b/ui/vnc-tls.h @@ -33,11 +33,6 @@ #include "qemu/acl.h" -enum { - VNC_WIREMODE_CLEAR, - VNC_WIREMODE_TLS, -}; - typedef struct VncDisplayTLS VncDisplayTLS; typedef struct VncStateTLS VncStateTLS; @@ -55,8 +50,6 @@ struct VncDisplayTLS { /* Per client state */ struct VncStateTLS { - /* Whether data is being TLS encrypted yet */ - int wiremode; gnutls_session_t session; /* Client's Distinguished Name from the x509 cert */ diff --git a/ui/vnc-ws.c b/ui/vnc-ws.c index d75950d7b1..85dbb7e6ae 100644 --- a/ui/vnc-ws.c +++ b/ui/vnc-ws.c @@ -24,16 +24,14 @@ #ifdef CONFIG_VNC_TLS #include "qemu/sockets.h" -static void vncws_tls_handshake_io(void *opaque); - static int vncws_start_tls_handshake(struct VncState *vs) { - int ret = gnutls_handshake(vs->ws_tls.session); + int ret = gnutls_handshake(vs->tls.session); if (ret < 0) { if (!gnutls_error_is_fatal(ret)) { VNC_DEBUG("Handshake interrupted (blocking)\n"); - if (!gnutls_record_get_direction(vs->ws_tls.session)) { + if (!gnutls_record_get_direction(vs->tls.session)) { qemu_set_fd_handler(vs->csock, vncws_tls_handshake_io, NULL, vs); } else { @@ -47,40 +45,34 @@ static int vncws_start_tls_handshake(struct VncState *vs) return -1; } + if (vs->vd->tls.x509verify) { + if (vnc_tls_validate_certificate(vs) < 0) { + VNC_DEBUG("Client verification failed\n"); + vnc_client_error(vs); + return -1; + } else { + VNC_DEBUG("Client verification passed\n"); + } + } + VNC_DEBUG("Handshake done, switching to TLS data mode\n"); - vs->ws_tls.wiremode = VNC_WIREMODE_TLS; qemu_set_fd_handler2(vs->csock, NULL, vncws_handshake_read, NULL, vs); return 0; } -static void vncws_tls_handshake_io(void *opaque) +void vncws_tls_handshake_io(void *opaque) { struct VncState *vs = (struct VncState *)opaque; - VNC_DEBUG("Handshake IO continue\n"); - vncws_start_tls_handshake(vs); -} - -void vncws_tls_handshake_peek(void *opaque) -{ - VncState *vs = opaque; - long ret; - - if (!vs->ws_tls.session) { - char peek[4]; - ret = qemu_recv(vs->csock, peek, sizeof(peek), MSG_PEEK); - if (ret && (strncmp(peek, "\x16", 1) == 0 - || strncmp(peek, "\x80", 1) == 0)) { - VNC_DEBUG("TLS Websocket connection recognized"); - vnc_tls_client_setup(vs, 1); - vncws_start_tls_handshake(vs); - } else { - vncws_handshake_read(vs); + if (!vs->tls.session) { + VNC_DEBUG("TLS Websocket setup\n"); + if (vnc_tls_client_setup(vs, vs->vd->tls.x509cert != NULL) < 0) { + return; } - } else { - qemu_set_fd_handler2(vs->csock, NULL, vncws_handshake_read, NULL, vs); } + VNC_DEBUG("Handshake IO continue\n"); + vncws_start_tls_handshake(vs); } #endif /* CONFIG_VNC_TLS */ diff --git a/ui/vnc-ws.h b/ui/vnc-ws.h index 95c1b0aeae..ef229b7c0c 100644 --- a/ui/vnc-ws.h +++ b/ui/vnc-ws.h @@ -75,7 +75,7 @@ enum { }; #ifdef CONFIG_VNC_TLS -void vncws_tls_handshake_peek(void *opaque); +void vncws_tls_handshake_io(void *opaque); #endif /* CONFIG_VNC_TLS */ void vncws_handshake_read(void *opaque); long vnc_client_write_ws(VncState *vs); diff --git a/ui/vnc.c b/ui/vnc.c index 6f9b718814..cffb5b74b3 100644 --- a/ui/vnc.c +++ b/ui/vnc.c @@ -1343,15 +1343,8 @@ long vnc_client_write_buf(VncState *vs, const uint8_t *data, size_t datalen) if (vs->tls.session) { ret = vnc_client_write_tls(&vs->tls.session, data, datalen); } else { -#ifdef CONFIG_VNC_WS - if (vs->ws_tls.session) { - ret = vnc_client_write_tls(&vs->ws_tls.session, data, datalen); - } else -#endif /* CONFIG_VNC_WS */ #endif /* CONFIG_VNC_TLS */ - { - ret = send(vs->csock, (const void *)data, datalen, 0); - } + ret = send(vs->csock, (const void *)data, datalen, 0); #ifdef CONFIG_VNC_TLS } #endif /* CONFIG_VNC_TLS */ @@ -1491,15 +1484,8 @@ long vnc_client_read_buf(VncState *vs, uint8_t *data, size_t datalen) if (vs->tls.session) { ret = vnc_client_read_tls(&vs->tls.session, data, datalen); } else { -#ifdef CONFIG_VNC_WS - if (vs->ws_tls.session) { - ret = vnc_client_read_tls(&vs->ws_tls.session, data, datalen); - } else -#endif /* CONFIG_VNC_WS */ #endif /* CONFIG_VNC_TLS */ - { - ret = qemu_recv(vs->csock, data, datalen, 0); - } + ret = qemu_recv(vs->csock, data, datalen, 0); #ifdef CONFIG_VNC_TLS } #endif /* CONFIG_VNC_TLS */ @@ -2400,34 +2386,34 @@ static int protocol_client_msg(VncState *vs, uint8_t *data, size_t len) case 4: vs->as.fmt = AUD_FMT_U32; break; case 5: vs->as.fmt = AUD_FMT_S32; break; default: - printf("Invalid audio format %d\n", read_u8(data, 4)); + VNC_DEBUG("Invalid audio format %d\n", read_u8(data, 4)); vnc_client_error(vs); break; } vs->as.nchannels = read_u8(data, 5); if (vs->as.nchannels != 1 && vs->as.nchannels != 2) { - printf("Invalid audio channel coount %d\n", - read_u8(data, 5)); + VNC_DEBUG("Invalid audio channel coount %d\n", + read_u8(data, 5)); vnc_client_error(vs); break; } vs->as.freq = read_u32(data, 6); break; default: - printf ("Invalid audio message %d\n", read_u8(data, 4)); + VNC_DEBUG("Invalid audio message %d\n", read_u8(data, 4)); vnc_client_error(vs); break; } break; default: - printf("Msg: %d\n", read_u16(data, 0)); + VNC_DEBUG("Msg: %d\n", read_u16(data, 0)); vnc_client_error(vs); break; } break; default: - printf("Msg: %d\n", data[0]); + VNC_DEBUG("Msg: %d\n", data[0]); vnc_client_error(vs); break; } @@ -3010,15 +2996,18 @@ static void vnc_connect(VncDisplay *vd, int csock, if (skipauth) { vs->auth = VNC_AUTH_NONE; -#ifdef CONFIG_VNC_TLS vs->subauth = VNC_AUTH_INVALID; -#endif } else { - vs->auth = vd->auth; -#ifdef CONFIG_VNC_TLS - vs->subauth = vd->subauth; -#endif + if (websocket) { + vs->auth = vd->ws_auth; + vs->subauth = VNC_AUTH_INVALID; + } else { + vs->auth = vd->auth; + vs->subauth = vd->subauth; + } } + VNC_DEBUG("Client sock=%d ws=%d auth=%d subauth=%d\n", + csock, websocket, vs->auth, vs->subauth); vs->lossy_rect = g_malloc0(VNC_STAT_ROWS * sizeof (*vs->lossy_rect)); for (i = 0; i < VNC_STAT_ROWS; ++i) { @@ -3032,8 +3021,8 @@ static void vnc_connect(VncDisplay *vd, int csock, if (websocket) { vs->websocket = 1; #ifdef CONFIG_VNC_TLS - if (vd->tls.x509cert) { - qemu_set_fd_handler2(vs->csock, NULL, vncws_tls_handshake_peek, + if (vd->ws_tls) { + qemu_set_fd_handler2(vs->csock, NULL, vncws_tls_handshake_io, NULL, vs); } else #endif /* CONFIG_VNC_TLS */ @@ -3206,8 +3195,8 @@ static void vnc_display_close(VncDisplay *vs) } #endif /* CONFIG_VNC_WS */ vs->auth = VNC_AUTH_INVALID; -#ifdef CONFIG_VNC_TLS vs->subauth = VNC_AUTH_INVALID; +#ifdef CONFIG_VNC_TLS vs->tls.x509verify = 0; #endif } @@ -3318,6 +3307,134 @@ static QemuOptsList qemu_vnc_opts = { }, }; + +static void +vnc_display_setup_auth(VncDisplay *vs, + bool password, + bool sasl, + bool tls, + bool x509, + bool websocket) +{ + /* + * We have a choice of 3 authentication options + * + * 1. none + * 2. vnc + * 3. sasl + * + * The channel can be run in 2 modes + * + * 1. clear + * 2. tls + * + * And TLS can use 2 types of credentials + * + * 1. anon + * 2. x509 + * + * We thus have 9 possible logical combinations + * + * 1. clear + none + * 2. clear + vnc + * 3. clear + sasl + * 4. tls + anon + none + * 5. tls + anon + vnc + * 6. tls + anon + sasl + * 7. tls + x509 + none + * 8. tls + x509 + vnc + * 9. tls + x509 + sasl + * + * These need to be mapped into the VNC auth schemes + * in an appropriate manner. In regular VNC, all the + * TLS options get mapped into VNC_AUTH_VENCRYPT + * sub-auth types. + * + * In websockets, the https:// protocol already provides + * TLS support, so there is no need to make use of the + * VeNCrypt extension. Furthermore, websockets browser + * clients could not use VeNCrypt even if they wanted to, + * as they cannot control when the TLS handshake takes + * place. Thus there is no option but to rely on https://, + * meaning combinations 4->6 and 7->9 will be mapped to + * VNC auth schemes in the same way as combos 1->3. + * + * Regardless of fact that we have a different mapping to + * VNC auth mechs for plain VNC vs websockets VNC, the end + * result has the same security characteristics. + */ + if (password) { + if (tls) { + vs->auth = VNC_AUTH_VENCRYPT; + if (websocket) { + vs->ws_tls = true; + } + if (x509) { + VNC_DEBUG("Initializing VNC server with x509 password auth\n"); + vs->subauth = VNC_AUTH_VENCRYPT_X509VNC; + } else { + VNC_DEBUG("Initializing VNC server with TLS password auth\n"); + vs->subauth = VNC_AUTH_VENCRYPT_TLSVNC; + } + } else { + VNC_DEBUG("Initializing VNC server with password auth\n"); + vs->auth = VNC_AUTH_VNC; + vs->subauth = VNC_AUTH_INVALID; + } + if (websocket) { + vs->ws_auth = VNC_AUTH_VNC; + } else { + vs->ws_auth = VNC_AUTH_INVALID; + } + } else if (sasl) { + if (tls) { + vs->auth = VNC_AUTH_VENCRYPT; + if (websocket) { + vs->ws_tls = true; + } + if (x509) { + VNC_DEBUG("Initializing VNC server with x509 SASL auth\n"); + vs->subauth = VNC_AUTH_VENCRYPT_X509SASL; + } else { + VNC_DEBUG("Initializing VNC server with TLS SASL auth\n"); + vs->subauth = VNC_AUTH_VENCRYPT_TLSSASL; + } + } else { + VNC_DEBUG("Initializing VNC server with SASL auth\n"); + vs->auth = VNC_AUTH_SASL; + vs->subauth = VNC_AUTH_INVALID; + } + if (websocket) { + vs->ws_auth = VNC_AUTH_SASL; + } else { + vs->ws_auth = VNC_AUTH_INVALID; + } + } else { + if (tls) { + vs->auth = VNC_AUTH_VENCRYPT; + if (websocket) { + vs->ws_tls = true; + } + if (x509) { + VNC_DEBUG("Initializing VNC server with x509 no auth\n"); + vs->subauth = VNC_AUTH_VENCRYPT_X509NONE; + } else { + VNC_DEBUG("Initializing VNC server with TLS no auth\n"); + vs->subauth = VNC_AUTH_VENCRYPT_TLSNONE; + } + } else { + VNC_DEBUG("Initializing VNC server with no auth\n"); + vs->auth = VNC_AUTH_NONE; + vs->subauth = VNC_AUTH_INVALID; + } + if (websocket) { + vs->ws_auth = VNC_AUTH_NONE; + } else { + vs->ws_auth = VNC_AUTH_INVALID; + } + } +} + void vnc_display_open(const char *id, Error **errp) { VncDisplay *vs = vnc_display_find(id); @@ -3332,15 +3449,13 @@ void vnc_display_open(const char *id, Error **errp) char *h; bool has_ipv4 = false; bool has_ipv6 = false; -#ifdef CONFIG_VNC_WS const char *websocket; -#endif -#ifdef CONFIG_VNC_TLS bool tls = false, x509 = false; +#ifdef CONFIG_VNC_TLS const char *path; #endif -#ifdef CONFIG_VNC_SASL bool sasl = false; +#ifdef CONFIG_VNC_SASL int saslErr; #endif #if defined(CONFIG_VNC_TLS) || defined(CONFIG_VNC_SASL) @@ -3404,11 +3519,15 @@ void vnc_display_open(const char *id, Error **errp) reverse = qemu_opt_get_bool(opts, "reverse", false); lock_key_sync = qemu_opt_get_bool(opts, "lock-key-sync", true); -#ifdef CONFIG_VNC_SASL sasl = qemu_opt_get_bool(opts, "sasl", false); -#endif -#ifdef CONFIG_VNC_TLS +#ifndef CONFIG_VNC_SASL + if (sasl) { + error_setg(errp, "VNC SASL auth requires cyrus-sasl support"); + goto fail; + } +#endif /* CONFIG_VNC_SASL */ tls = qemu_opt_get_bool(opts, "tls", false); +#ifdef CONFIG_VNC_TLS path = qemu_opt_get(opts, "x509"); if (!path) { path = qemu_opt_get(opts, "x509verify"); @@ -3424,7 +3543,12 @@ void vnc_display_open(const char *id, Error **errp) goto fail; } } -#endif +#else /* ! CONFIG_VNC_TLS */ + if (tls) { + error_setg(errp, "VNC TLS auth requires gnutls support"); + goto fail; + } +#endif /* ! CONFIG_VNC_TLS */ #if defined(CONFIG_VNC_TLS) || defined(CONFIG_VNC_SASL) acl = qemu_opt_get_bool(opts, "acl", false); #endif @@ -3446,14 +3570,16 @@ void vnc_display_open(const char *id, Error **errp) } vs->connections_limit = qemu_opt_get_number(opts, "connections", 32); - #ifdef CONFIG_VNC_WS websocket = qemu_opt_get(opts, "websocket"); if (websocket) { +#ifdef CONFIG_VNC_WS vs->ws_enabled = true; qemu_opt_set(wsopts, "port", websocket, &error_abort); - +#else /* ! CONFIG_VNC_WS */ + error_setg(errp, "Websockets protocol requires gnutls support"); + goto fail; +#endif /* ! CONFIG_VNC_WS */ } -#endif /* CONFIG_VNC_WS */ #ifdef CONFIG_VNC_JPEG vs->lossy = qemu_opt_get_bool(opts, "lossy", false); @@ -3501,82 +3627,7 @@ void vnc_display_open(const char *id, Error **errp) } #endif - /* - * Combinations we support here: - * - * - no-auth (clear text, no auth) - * - password (clear text, weak auth) - * - sasl (encrypt, good auth *IF* using Kerberos via GSSAPI) - * - tls (encrypt, weak anonymous creds, no auth) - * - tls + password (encrypt, weak anonymous creds, weak auth) - * - tls + sasl (encrypt, weak anonymous creds, good auth) - * - tls + x509 (encrypt, good x509 creds, no auth) - * - tls + x509 + password (encrypt, good x509 creds, weak auth) - * - tls + x509 + sasl (encrypt, good x509 creds, good auth) - * - * NB1. TLS is a stackable auth scheme. - * NB2. the x509 schemes have option to validate a client cert dname - */ - if (password) { -#ifdef CONFIG_VNC_TLS - if (tls) { - vs->auth = VNC_AUTH_VENCRYPT; - if (x509) { - VNC_DEBUG("Initializing VNC server with x509 password auth\n"); - vs->subauth = VNC_AUTH_VENCRYPT_X509VNC; - } else { - VNC_DEBUG("Initializing VNC server with TLS password auth\n"); - vs->subauth = VNC_AUTH_VENCRYPT_TLSVNC; - } - } else { -#endif /* CONFIG_VNC_TLS */ - VNC_DEBUG("Initializing VNC server with password auth\n"); - vs->auth = VNC_AUTH_VNC; -#ifdef CONFIG_VNC_TLS - vs->subauth = VNC_AUTH_INVALID; - } -#endif /* CONFIG_VNC_TLS */ -#ifdef CONFIG_VNC_SASL - } else if (sasl) { -#ifdef CONFIG_VNC_TLS - if (tls) { - vs->auth = VNC_AUTH_VENCRYPT; - if (x509) { - VNC_DEBUG("Initializing VNC server with x509 SASL auth\n"); - vs->subauth = VNC_AUTH_VENCRYPT_X509SASL; - } else { - VNC_DEBUG("Initializing VNC server with TLS SASL auth\n"); - vs->subauth = VNC_AUTH_VENCRYPT_TLSSASL; - } - } else { -#endif /* CONFIG_VNC_TLS */ - VNC_DEBUG("Initializing VNC server with SASL auth\n"); - vs->auth = VNC_AUTH_SASL; -#ifdef CONFIG_VNC_TLS - vs->subauth = VNC_AUTH_INVALID; - } -#endif /* CONFIG_VNC_TLS */ -#endif /* CONFIG_VNC_SASL */ - } else { -#ifdef CONFIG_VNC_TLS - if (tls) { - vs->auth = VNC_AUTH_VENCRYPT; - if (x509) { - VNC_DEBUG("Initializing VNC server with x509 no auth\n"); - vs->subauth = VNC_AUTH_VENCRYPT_X509NONE; - } else { - VNC_DEBUG("Initializing VNC server with TLS no auth\n"); - vs->subauth = VNC_AUTH_VENCRYPT_TLSNONE; - } - } else { -#endif - VNC_DEBUG("Initializing VNC server with no auth\n"); - vs->auth = VNC_AUTH_NONE; -#ifdef CONFIG_VNC_TLS - vs->subauth = VNC_AUTH_INVALID; - } -#endif - } + vnc_display_setup_auth(vs, password, sasl, tls, x509, websocket); #ifdef CONFIG_VNC_SASL if ((saslErr = sasl_server_init(NULL, "qemu")) != SASL_OK) { @@ -3594,7 +3645,7 @@ void vnc_display_open(const char *id, Error **errp) dev = qdev_find_recursive(sysbus_get_default(), device_id); if (dev == NULL) { - error_set(errp, QERR_DEVICE_NOT_FOUND, device_id); + error_setg(errp, "Device '%s' not found", device_id); goto fail; } diff --git a/ui/vnc.h b/ui/vnc.h index 66a02986c7..e19ac396f2 100644 --- a/ui/vnc.h +++ b/ui/vnc.h @@ -180,10 +180,12 @@ struct VncDisplay char *password; time_t expires; int auth; + int subauth; /* Used by VeNCrypt */ + int ws_auth; /* Used by websockets */ + bool ws_tls; /* Used by websockets */ bool lossy; bool non_adaptive; #ifdef CONFIG_VNC_TLS - int subauth; /* Used by VeNCrypt */ VncDisplayTLS tls; #endif #ifdef CONFIG_VNC_SASL @@ -284,18 +286,15 @@ struct VncState int minor; int auth; + int subauth; /* Used by VeNCrypt */ char challenge[VNC_AUTH_CHALLENGE_SIZE]; #ifdef CONFIG_VNC_TLS - int subauth; /* Used by VeNCrypt */ VncStateTLS tls; #endif #ifdef CONFIG_VNC_SASL VncStateSASL sasl; #endif #ifdef CONFIG_VNC_WS -#ifdef CONFIG_VNC_TLS - VncStateTLS ws_tls; -#endif /* CONFIG_VNC_TLS */ bool encode_ws; bool websocket; #endif /* CONFIG_VNC_WS */ diff --git a/util/uri.c b/util/uri.c index 1cfd78bdb5..550b984587 100644 --- a/util/uri.c +++ b/util/uri.c @@ -320,19 +320,23 @@ static int rfc3986_parse_port(URI *uri, const char **str) { const char *cur = *str; + int port = 0; if (ISA_DIGIT(cur)) { - if (uri != NULL) - uri->port = 0; - while (ISA_DIGIT(cur)) { - if (uri != NULL) - uri->port = uri->port * 10 + (*cur - '0'); - cur++; - } - *str = cur; - return(0); + while (ISA_DIGIT(cur)) { + port = port * 10 + (*cur - '0'); + if (port > 65535) { + return 1; + } + cur++; + } + if (uri) { + uri->port = port; + } + *str = cur; + return 0; } - return(1); + return 1; } /** diff --git a/vl.c b/vl.c index 694deb4c1f..69617d640a 100644 --- a/vl.c +++ b/vl.c @@ -1012,6 +1012,7 @@ static int parse_add_fd(QemuOpts *opts, void *opaque) int fd, dupfd, flags; int64_t fdset_id; const char *fd_opaque = NULL; + AddfdInfo *fdinfo; fd = qemu_opt_get_number(opts, "fd", -1); fdset_id = qemu_opt_get_number(opts, "set", -1); @@ -1061,8 +1062,9 @@ static int parse_add_fd(QemuOpts *opts, void *opaque) } /* add the duplicate fd, and optionally the opaque string, to the fd set */ - monitor_fdset_add_fd(dupfd, true, fdset_id, fd_opaque ? true : false, - fd_opaque, NULL); + fdinfo = monitor_fdset_add_fd(dupfd, true, fdset_id, !!fd_opaque, fd_opaque, + &error_abort); + g_free(fdinfo); return 0; } |