diff options
102 files changed, 1388 insertions, 1184 deletions
diff --git a/.gitignore b/.gitignore index 1c9d63d651..6e48b5ed3f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,64 +1,64 @@ -config-devices.* -config-all-devices.* -config-all-disas.* -config-host.* -config-target.* -config.status -trace/generated-tracers.h -trace/generated-tracers.c -trace/generated-tracers-dtrace.h -trace/generated-tracers.dtrace -trace/generated-events.h -trace/generated-events.c -libcacard/trace/generated-tracers.c +/config-devices.* +/config-all-devices.* +/config-all-disas.* +/config-host.* +/config-target.* +/config.status +/trace/generated-tracers.h +/trace/generated-tracers.c +/trace/generated-tracers-dtrace.h +/trace/generated-tracers.dtrace +/trace/generated-events.h +/trace/generated-events.c +/libcacard/trace/generated-tracers.c *-timestamp -*-softmmu -*-darwin-user -*-linux-user -*-bsd-user +/*-softmmu +/*-darwin-user +/*-linux-user +/*-bsd-user libdis* libuser -linux-headers/asm -qapi-generated -qapi-types.[ch] -qapi-visit.[ch] -qmp-commands.h -qmp-marshal.c -qemu-doc.html -qemu-tech.html -qemu-doc.info -qemu-tech.info -qemu.1 -qemu.pod -qemu-img.1 -qemu-img.pod -qemu-img -qemu-nbd -qemu-nbd.8 -qemu-nbd.pod -qemu-options.def -qemu-options.texi -qemu-img-cmds.texi -qemu-img-cmds.h -qemu-io -qemu-ga -qemu-bridge-helper -qemu-monitor.texi -vscclient -qmp-commands.txt -test-bitops -test-coroutine -test-int128 -test-opts-visitor -test-qmp-input-visitor -test-qmp-output-visitor -test-string-input-visitor -test-string-output-visitor -test-visitor-serialization -fsdev/virtfs-proxy-helper -fsdev/virtfs-proxy-helper.1 -fsdev/virtfs-proxy-helper.pod -.gdbinit +/linux-headers/asm +/qapi-generated +/qapi-types.[ch] +/qapi-visit.[ch] +/qmp-commands.h +/qmp-marshal.c +/qemu-doc.html +/qemu-tech.html +/qemu-doc.info +/qemu-tech.info +/qemu.1 +/qemu.pod +/qemu-img.1 +/qemu-img.pod +/qemu-img +/qemu-nbd +/qemu-nbd.8 +/qemu-nbd.pod +/qemu-options.def +/qemu-options.texi +/qemu-img-cmds.texi +/qemu-img-cmds.h +/qemu-io +/qemu-ga +/qemu-bridge-helper +/qemu-monitor.texi +/qmp-commands.txt +/vscclient +/test-bitops +/test-coroutine +/test-int128 +/test-opts-visitor +/test-qmp-input-visitor +/test-qmp-output-visitor +/test-string-input-visitor +/test-string-output-visitor +/test-visitor-serialization +/fsdev/virtfs-proxy-helper +/fsdev/virtfs-proxy-helper.1 +/fsdev/virtfs-proxy-helper.pod +/.gdbinit *.a *.aux *.cp @@ -77,7 +77,7 @@ fsdev/virtfs-proxy-helper.pod *.tp *.vr *.d -!scripts/qemu-guest-agent/fsfreeze-hook.d +!/scripts/qemu-guest-agent/fsfreeze-hook.d *.o *.lo *.la @@ -90,22 +90,22 @@ fsdev/virtfs-proxy-helper.pod *.gcda *.gcno patches -pc-bios/bios-pq/status -pc-bios/vgabios-pq/status -pc-bios/optionrom/linuxboot.asm -pc-bios/optionrom/linuxboot.bin -pc-bios/optionrom/linuxboot.raw -pc-bios/optionrom/linuxboot.img -pc-bios/optionrom/multiboot.asm -pc-bios/optionrom/multiboot.bin -pc-bios/optionrom/multiboot.raw -pc-bios/optionrom/multiboot.img -pc-bios/optionrom/kvmvapic.asm -pc-bios/optionrom/kvmvapic.bin -pc-bios/optionrom/kvmvapic.raw -pc-bios/optionrom/kvmvapic.img -pc-bios/s390-ccw/s390-ccw.elf -pc-bios/s390-ccw/s390-ccw.img +/pc-bios/bios-pq/status +/pc-bios/vgabios-pq/status +/pc-bios/optionrom/linuxboot.asm +/pc-bios/optionrom/linuxboot.bin +/pc-bios/optionrom/linuxboot.raw +/pc-bios/optionrom/linuxboot.img +/pc-bios/optionrom/multiboot.asm +/pc-bios/optionrom/multiboot.bin +/pc-bios/optionrom/multiboot.raw +/pc-bios/optionrom/multiboot.img +/pc-bios/optionrom/kvmvapic.asm +/pc-bios/optionrom/kvmvapic.bin +/pc-bios/optionrom/kvmvapic.raw +/pc-bios/optionrom/kvmvapic.img +/pc-bios/s390-ccw/s390-ccw.elf +/pc-bios/s390-ccw/s390-ccw.img .stgit-* cscope.* tags @@ -421,7 +421,7 @@ static void coroutine_fn bdrv_create_co_entry(void *opaque) assert(cco->drv); ret = cco->drv->bdrv_create(cco->filename, cco->options, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { error_propagate(&cco->err, local_err); } cco->ret = ret; @@ -460,7 +460,7 @@ int bdrv_create(BlockDriver *drv, const char* filename, ret = cco.ret; if (ret < 0) { - if (error_is_set(&cco.err)) { + if (cco.err) { error_propagate(errp, cco.err); } else { error_setg_errno(errp, -ret, "Could not create image"); @@ -486,7 +486,7 @@ int bdrv_create_file(const char* filename, QEMUOptionParameter *options, } ret = bdrv_create(drv, filename, options, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { error_propagate(errp, local_err); } return ret; @@ -796,6 +796,13 @@ static int bdrv_assign_node_name(BlockDriverState *bs, return -EINVAL; } + /* takes care of avoiding namespaces collisions */ + if (bdrv_find(node_name)) { + error_setg(errp, "node-name=%s is conflicting with a device id", + node_name); + return -EINVAL; + } + /* takes care of avoiding duplicates node names */ if (bdrv_find_node(node_name)) { error_setg(errp, "Duplicate node name"); @@ -909,7 +916,7 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file, } if (ret < 0) { - if (error_is_set(&local_err)) { + if (local_err) { error_propagate(errp, local_err); } else if (bs->filename[0]) { error_setg_errno(errp, -ret, "Could not open '%s'", bs->filename); @@ -977,9 +984,8 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename, } QDECREF(options); - bs = bdrv_find(reference); + bs = bdrv_lookup_bs(reference, reference, errp); if (!bs) { - error_setg(errp, "Cannot find block device '%s'", reference); return -ENODEV; } bdrv_ref(bs); @@ -1031,7 +1037,7 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename, /* Parse the filename and open it */ if (drv->bdrv_parse_filename && filename) { drv->bdrv_parse_filename(filename, options, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { error_propagate(errp, local_err); ret = -EINVAL; goto fail; @@ -1400,7 +1406,7 @@ fail: QDECREF(bs->options); QDECREF(options); bs->options = NULL; - if (error_is_set(&local_err)) { + if (local_err) { error_propagate(errp, local_err); } return ret; @@ -1408,7 +1414,7 @@ fail: close_and_fail: bdrv_close(bs); QDECREF(options); - if (error_is_set(&local_err)) { + if (local_err) { error_propagate(errp, local_err); } return ret; @@ -3574,30 +3580,26 @@ BlockDriverState *bdrv_lookup_bs(const char *device, { BlockDriverState *bs = NULL; - if ((!device && !node_name) || (device && node_name)) { - error_setg(errp, "Use either device or node-name but not both"); - return NULL; - } - if (device) { bs = bdrv_find(device); - if (!bs) { - error_set(errp, QERR_DEVICE_NOT_FOUND, device); - return NULL; + if (bs) { + return bs; } - - return bs; } - bs = bdrv_find_node(node_name); + if (node_name) { + bs = bdrv_find_node(node_name); - if (!bs) { - error_set(errp, QERR_DEVICE_NOT_FOUND, node_name); - return NULL; + if (bs) { + return bs; + } } - return bs; + error_setg(errp, "Cannot find device=%s nor node_name=%s", + device ? device : "", + node_name ? node_name : ""); + return NULL; } BlockDriverState *bdrv_next(BlockDriverState *bs) @@ -5338,7 +5340,7 @@ out: free_option_parameters(create_options); free_option_parameters(param); - if (error_is_set(&local_err)) { + if (local_err) { error_propagate(errp, local_err); } } diff --git a/block/blkdebug.c b/block/blkdebug.c index 8eb0db0723..ee10013362 100644 --- a/block/blkdebug.c +++ b/block/blkdebug.c @@ -303,7 +303,7 @@ static int read_config(BDRVBlkdebugState *s, const char *filename, } qemu_config_parse_qdict(options, config_groups, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { error_propagate(errp, local_err); ret = -EINVAL; goto fail; @@ -393,7 +393,7 @@ static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags, opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort); qemu_opts_absorb_qdict(opts, options, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { error_propagate(errp, local_err); ret = -EINVAL; goto out; diff --git a/block/blkverify.c b/block/blkverify.c index cfcbcf41c3..1563c88324 100644 --- a/block/blkverify.c +++ b/block/blkverify.c @@ -128,7 +128,7 @@ static int blkverify_open(BlockDriverState *bs, QDict *options, int flags, opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort); qemu_opts_absorb_qdict(opts, options, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { error_propagate(errp, local_err); ret = -EINVAL; goto fail; diff --git a/block/curl.c b/block/curl.c index a8075847b8..bb1fc4ae28 100644 --- a/block/curl.c +++ b/block/curl.c @@ -463,7 +463,7 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags, opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort); qemu_opts_absorb_qdict(opts, options, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { qerror_report_err(local_err); error_free(local_err); goto out_noclean; diff --git a/block/gluster.c b/block/gluster.c index a009b15ded..58eab07829 100644 --- a/block/gluster.c +++ b/block/gluster.c @@ -282,7 +282,7 @@ static int qemu_gluster_open(BlockDriverState *bs, QDict *options, opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort); qemu_opts_absorb_qdict(opts, options, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { qerror_report_err(local_err); error_free(local_err); ret = -EINVAL; diff --git a/block/iscsi.c b/block/iscsi.c index 8d0f9667c5..f8e496f8ef 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -1099,6 +1099,10 @@ fail: /* * We support iscsi url's on the form * iscsi://[<username>%<password>@]<host>[:<port>]/<targetname>/<lun> + * + * Note: flags are currently not used by iscsi_open. If this function + * is changed such that flags are used, please examine iscsi_reopen_prepare() + * to see if needs to be changed as well. */ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags, Error **errp) @@ -1123,7 +1127,7 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags, opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort); qemu_opts_absorb_qdict(opts, options, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { qerror_report_err(local_err); error_free(local_err); ret = -EINVAL; @@ -1336,11 +1340,13 @@ static int iscsi_refresh_limits(BlockDriverState *bs) return 0; } -/* We have nothing to do for iSCSI reopen, stub just returns - * success */ +/* Since iscsi_open() ignores bdrv_flags, there is nothing to do here in + * prepare. Note that this will not re-establish a connection with an iSCSI + * target - it is effectively a NOP. */ static int iscsi_reopen_prepare(BDRVReopenState *state, BlockReopenQueue *queue, Error **errp) { + /* NOP */ return 0; } diff --git a/block/mirror.c b/block/mirror.c index 2a4333474e..e683959570 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -633,6 +633,8 @@ void commit_active_start(BlockDriverState *bs, BlockDriverState *base, { int64_t length, base_length; int orig_base_flags; + int ret; + Error *local_err = NULL; orig_base_flags = bdrv_get_flags(base); @@ -642,19 +644,23 @@ void commit_active_start(BlockDriverState *bs, BlockDriverState *base, length = bdrv_getlength(bs); if (length < 0) { - error_setg(errp, "Unable to determine length of %s", bs->filename); + error_setg_errno(errp, -length, + "Unable to determine length of %s", bs->filename); goto error_restore_flags; } base_length = bdrv_getlength(base); if (base_length < 0) { - error_setg(errp, "Unable to determine length of %s", base->filename); + error_setg_errno(errp, -base_length, + "Unable to determine length of %s", base->filename); goto error_restore_flags; } if (length > base_length) { - if (bdrv_truncate(base, length) < 0) { - error_setg(errp, "Top image %s is larger than base image %s, and " + ret = bdrv_truncate(base, length); + if (ret < 0) { + error_setg_errno(errp, -ret, + "Top image %s is larger than base image %s, and " "resize of base image failed", bs->filename, base->filename); goto error_restore_flags; @@ -663,9 +669,10 @@ void commit_active_start(BlockDriverState *bs, BlockDriverState *base, bdrv_ref(base); mirror_start_job(bs, base, speed, 0, 0, - on_error, on_error, cb, opaque, errp, + on_error, on_error, cb, opaque, &local_err, &commit_active_job_driver, false, base); - if (error_is_set(errp)) { + if (error_is_set(&local_err)) { + error_propagate(errp, local_err); goto error_restore_flags; } diff --git a/block/nbd.c b/block/nbd.c index 327e913002..abae506f04 100644 --- a/block/nbd.c +++ b/block/nbd.c @@ -209,7 +209,7 @@ static int nbd_config(BDRVNBDState *s, QDict *options, char **export) &error_abort); qemu_opts_absorb_qdict(s->socket_opts, options, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { qerror_report_err(local_err); error_free(local_err); return -EINVAL; diff --git a/block/qapi.c b/block/qapi.c index 8f4134b40a..8f2b4dbe7d 100644 --- a/block/qapi.c +++ b/block/qapi.c @@ -271,7 +271,7 @@ void bdrv_query_info(BlockDriverState *bs, p_image_info = &info->inserted->image; while (1) { bdrv_query_image_info(bs0, p_image_info, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { error_propagate(errp, local_err); goto err; } @@ -336,7 +336,7 @@ BlockInfoList *qmp_query_block(Error **errp) while ((bs = bdrv_next(bs))) { BlockInfoList *info = g_malloc0(sizeof(*info)); bdrv_query_info(bs, &info->value, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { error_propagate(errp, local_err); goto err; } diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c index ad8bf3dcd9..2fc6320aa1 100644 --- a/block/qcow2-snapshot.c +++ b/block/qcow2-snapshot.c @@ -606,7 +606,8 @@ int qcow2_snapshot_delete(BlockDriverState *bs, s->nb_snapshots--; ret = qcow2_write_snapshots(bs); if (ret < 0) { - error_setg(errp, "Failed to remove snapshot from snapshot list"); + error_setg_errno(errp, -ret, + "Failed to remove snapshot from snapshot list"); return ret; } @@ -624,7 +625,7 @@ int qcow2_snapshot_delete(BlockDriverState *bs, ret = qcow2_update_snapshot_refcount(bs, sn.l1_table_offset, sn.l1_size, -1); if (ret < 0) { - error_setg(errp, "Failed to free the cluster and L1 table"); + error_setg_errno(errp, -ret, "Failed to free the cluster and L1 table"); return ret; } qcow2_free_clusters(bs, sn.l1_table_offset, sn.l1_size * sizeof(uint64_t), @@ -633,7 +634,8 @@ int qcow2_snapshot_delete(BlockDriverState *bs, /* must update the copied flag on the current cluster offsets */ ret = qcow2_update_snapshot_refcount(bs, s->l1_table_offset, s->l1_size, 0); if (ret < 0) { - error_setg(errp, "Failed to update snapshot status in disk"); + error_setg_errno(errp, -ret, + "Failed to update snapshot status in disk"); return ret; } diff --git a/block/qcow2.c b/block/qcow2.c index 0b4335ca5b..b1dbdb120e 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -671,7 +671,7 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags, /* Enable lazy_refcounts according to image and command line options */ opts = qemu_opts_create(&qcow2_runtime_opts, NULL, 0, &error_abort); qemu_opts_absorb_qdict(opts, options, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { error_propagate(errp, local_err); ret = -EINVAL; goto fail; @@ -1605,7 +1605,7 @@ static int qcow2_create2(const char *filename, int64_t total_size, ret = bdrv_open(bs, filename, NULL, BDRV_O_RDWR | BDRV_O_CACHE_WB | BDRV_O_NO_BACKING, drv, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { error_propagate(errp, local_err); goto out; } @@ -1685,7 +1685,7 @@ static int qcow2_create(const char *filename, QEMUOptionParameter *options, ret = qcow2_create2(filename, sectors, backing_file, backing_fmt, flags, cluster_size, prealloc, options, version, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { error_propagate(errp, local_err); } return ret; diff --git a/block/raw-posix.c b/block/raw-posix.c index 126a634e45..161ea14812 100644 --- a/block/raw-posix.c +++ b/block/raw-posix.c @@ -361,7 +361,7 @@ static int raw_open_common(BlockDriverState *bs, QDict *options, opts = qemu_opts_create(&raw_runtime_opts, NULL, 0, &error_abort); qemu_opts_absorb_qdict(opts, options, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { error_propagate(errp, local_err); ret = -EINVAL; goto fail; @@ -448,7 +448,7 @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags, s->type = FTYPE_FILE; ret = raw_open_common(bs, options, flags, 0, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { error_propagate(errp, local_err); } return ret; @@ -1597,7 +1597,7 @@ static int hdev_open(BlockDriverState *bs, QDict *options, int flags, ret = raw_open_common(bs, options, flags, 0, &local_err); if (ret < 0) { - if (error_is_set(&local_err)) { + if (local_err) { error_propagate(errp, local_err); } return ret; @@ -1832,7 +1832,7 @@ static int floppy_open(BlockDriverState *bs, QDict *options, int flags, /* open will not fail even if no floppy is inserted, so add O_NONBLOCK */ ret = raw_open_common(bs, options, flags, O_NONBLOCK, &local_err); if (ret) { - if (error_is_set(&local_err)) { + if (local_err) { error_propagate(errp, local_err); } return ret; @@ -1961,7 +1961,7 @@ static int cdrom_open(BlockDriverState *bs, QDict *options, int flags, /* open will not fail even if no CD is inserted, so add O_NONBLOCK */ ret = raw_open_common(bs, options, flags, O_NONBLOCK, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { error_propagate(errp, local_err); } return ret; @@ -2078,7 +2078,7 @@ static int cdrom_open(BlockDriverState *bs, QDict *options, int flags, ret = raw_open_common(bs, options, flags, 0, &local_err); if (ret) { - if (error_is_set(&local_err)) { + if (local_err) { error_propagate(errp, local_err); } return ret; diff --git a/block/raw-win32.c b/block/raw-win32.c index beb7f2395e..ae1c8e6cca 100644 --- a/block/raw-win32.c +++ b/block/raw-win32.c @@ -279,7 +279,7 @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags, opts = qemu_opts_create(&raw_runtime_opts, NULL, 0, &error_abort); qemu_opts_absorb_qdict(opts, options, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { error_propagate(errp, local_err); ret = -EINVAL; goto fail; @@ -594,7 +594,7 @@ static int hdev_open(BlockDriverState *bs, QDict *options, int flags, QemuOpts *opts = qemu_opts_create(&raw_runtime_opts, NULL, 0, &error_abort); qemu_opts_absorb_qdict(opts, options, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { error_propagate(errp, local_err); ret = -EINVAL; goto done; diff --git a/block/raw_bsd.c b/block/raw_bsd.c index af8706dc97..01ea692a46 100644 --- a/block/raw_bsd.c +++ b/block/raw_bsd.c @@ -146,7 +146,7 @@ static int raw_create(const char *filename, QEMUOptionParameter *options, int ret; ret = bdrv_create_file(filename, options, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { error_propagate(errp, local_err); } return ret; diff --git a/block/rbd.c b/block/rbd.c index 121fae221e..dbc79f4525 100644 --- a/block/rbd.c +++ b/block/rbd.c @@ -440,7 +440,7 @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags, opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort); qemu_opts_absorb_qdict(opts, options, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { qerror_report_err(local_err); error_free(local_err); qemu_opts_del(opts); diff --git a/block/sheepdog.c b/block/sheepdog.c index 672b9c97a2..e6c0376566 100644 --- a/block/sheepdog.c +++ b/block/sheepdog.c @@ -1385,7 +1385,7 @@ static int sd_open(BlockDriverState *bs, QDict *options, int flags, opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort); qemu_opts_absorb_qdict(opts, options, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { qerror_report_err(local_err); error_free(local_err); ret = -EINVAL; diff --git a/block/snapshot.c b/block/snapshot.c index 9047f8ddc9..85c52ff455 100644 --- a/block/snapshot.c +++ b/block/snapshot.c @@ -345,7 +345,7 @@ int bdrv_snapshot_load_tmp_by_id_or_name(BlockDriverState *bs, ret = bdrv_snapshot_load_tmp(bs, NULL, id_or_name, &local_err); } - if (error_is_set(&local_err)) { + if (local_err) { error_propagate(errp, local_err); } diff --git a/block/vmdk.c b/block/vmdk.c index e809e2ef46..ff6f5ee911 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -1502,7 +1502,7 @@ static int vmdk_create_extent(const char *filename, int64_t filesize, if (flat) { ret = bdrv_truncate(bs, filesize); if (ret < 0) { - error_setg(errp, "Could not truncate file"); + error_setg_errno(errp, -ret, "Could not truncate file"); } goto exit; } @@ -1562,7 +1562,7 @@ static int vmdk_create_extent(const char *filename, int64_t filesize, ret = bdrv_truncate(bs, le64_to_cpu(header.grain_offset) << 9); if (ret < 0) { - error_setg(errp, "Could not truncate file"); + error_setg_errno(errp, -ret, "Could not truncate file"); goto exit; } @@ -1846,7 +1846,7 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options, if (desc_offset == 0) { ret = bdrv_truncate(new_bs, desc_len); if (ret < 0) { - error_setg(errp, "Could not truncate file"); + error_setg_errno(errp, -ret, "Could not truncate file"); } } exit: diff --git a/block/vvfat.c b/block/vvfat.c index 664941c560..a19e4ca227 100644 --- a/block/vvfat.c +++ b/block/vvfat.c @@ -1085,7 +1085,7 @@ DLOG(if (stderr == NULL) { opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort); qemu_opts_absorb_qdict(opts, options, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { qerror_report_err(local_err); error_free(local_err); ret = -EINVAL; diff --git a/blockdev.c b/blockdev.c index d71f815a76..3cc8cda2bd 100644 --- a/blockdev.c +++ b/blockdev.c @@ -308,7 +308,6 @@ typedef enum { MEDIA_DISK, MEDIA_CDROM } DriveMediaType; /* Takes the ownership of bs_opts */ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts, - BlockInterfaceType type, Error **errp) { const char *buf; @@ -331,13 +330,13 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts, * stay in bs_opts for processing by bdrv_open(). */ id = qdict_get_try_str(bs_opts, "id"); opts = qemu_opts_create(&qemu_common_drive_opts, id, 1, &error); - if (error_is_set(&error)) { + if (error) { error_propagate(errp, error); return NULL; } qemu_opts_absorb_qdict(opts, bs_opts, &error); - if (error_is_set(&error)) { + if (error) { error_propagate(errp, error); goto early_err; } @@ -437,13 +436,8 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts, on_write_error = BLOCKDEV_ON_ERROR_ENOSPC; if ((buf = qemu_opt_get(opts, "werror")) != NULL) { - if (type != IF_IDE && type != IF_SCSI && type != IF_VIRTIO && type != IF_NONE) { - error_setg(errp, "werror is not supported by this bus type"); - goto early_err; - } - on_write_error = parse_block_error_action(buf, 0, &error); - if (error_is_set(&error)) { + if (error) { error_propagate(errp, error); goto early_err; } @@ -451,25 +445,25 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts, on_read_error = BLOCKDEV_ON_ERROR_REPORT; if ((buf = qemu_opt_get(opts, "rerror")) != NULL) { - if (type != IF_IDE && type != IF_VIRTIO && type != IF_SCSI && type != IF_NONE) { - error_report("rerror is not supported by this bus type"); - goto early_err; - } - on_read_error = parse_block_error_action(buf, 1, &error); - if (error_is_set(&error)) { + if (error) { error_propagate(errp, error); goto early_err; } } + if (bdrv_find_node(qemu_opts_id(opts))) { + error_setg(errp, "device id=%s is conflicting with a node-name", + qemu_opts_id(opts)); + goto early_err; + } + /* init */ dinfo = g_malloc0(sizeof(*dinfo)); dinfo->id = g_strdup(qemu_opts_id(opts)); dinfo->bdrv = bdrv_new(dinfo->id); dinfo->bdrv->open_flags = snapshot ? BDRV_O_SNAPSHOT : 0; dinfo->bdrv->read_only = ro; - dinfo->type = type; dinfo->refcount = 1; if (serial != NULL) { dinfo->serial = g_strdup(serial); @@ -609,6 +603,14 @@ QemuOptsList qemu_legacy_drive_opts = { .type = QEMU_OPT_BOOL, .help = "open drive file as read-only", },{ + .name = "rerror", + .type = QEMU_OPT_STRING, + .help = "read error action", + },{ + .name = "werror", + .type = QEMU_OPT_STRING, + .help = "write error action", + },{ .name = "copy-on-read", .type = QEMU_OPT_BOOL, .help = "copy read data from backing file into image file", @@ -629,6 +631,7 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type) int cyls, heads, secs, translation; int max_devs, bus_id, unit_id, index; const char *devaddr; + const char *werror, *rerror; bool read_only = false; bool copy_on_read; const char *filename; @@ -688,7 +691,7 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type) legacy_opts = qemu_opts_create(&qemu_legacy_drive_opts, NULL, 0, &error_abort); qemu_opts_absorb_qdict(legacy_opts, bs_opts, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { qerror_report_err(local_err); error_free(local_err); goto fail; @@ -876,16 +879,37 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type) filename = qemu_opt_get(legacy_opts, "file"); + /* Check werror/rerror compatibility with if=... */ + werror = qemu_opt_get(legacy_opts, "werror"); + if (werror != NULL) { + if (type != IF_IDE && type != IF_SCSI && type != IF_VIRTIO && + type != IF_NONE) { + error_report("werror is not supported by this bus type"); + goto fail; + } + qdict_put(bs_opts, "werror", qstring_from_str(werror)); + } + + rerror = qemu_opt_get(legacy_opts, "rerror"); + if (rerror != NULL) { + if (type != IF_IDE && type != IF_VIRTIO && type != IF_SCSI && + type != IF_NONE) { + error_report("rerror is not supported by this bus type"); + goto fail; + } + qdict_put(bs_opts, "rerror", qstring_from_str(rerror)); + } + /* Actual block device init: Functionality shared with blockdev-add */ - dinfo = blockdev_init(filename, bs_opts, type, &local_err); + dinfo = blockdev_init(filename, bs_opts, &local_err); if (dinfo == NULL) { - if (error_is_set(&local_err)) { + if (local_err) { qerror_report_err(local_err); error_free(local_err); } goto fail; } else { - assert(!error_is_set(&local_err)); + assert(!local_err); } /* Set legacy DriveInfo fields */ @@ -897,6 +921,7 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type) dinfo->secs = secs; dinfo->trans = translation; + dinfo->type = type; dinfo->bus = bus_id; dinfo->unit = unit_id; dinfo->devaddr = devaddr; @@ -1021,7 +1046,7 @@ SnapshotInfo *qmp_blockdev_snapshot_delete_internal_sync(const char *device, } ret = bdrv_snapshot_find_by_id_and_name(bs, id, name, &sn, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { error_propagate(errp, local_err); return NULL; } @@ -1034,7 +1059,7 @@ SnapshotInfo *qmp_blockdev_snapshot_delete_internal_sync(const char *device, } bdrv_snapshot_delete(bs, id, name, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { error_propagate(errp, local_err); return NULL; } @@ -1248,7 +1273,7 @@ static void external_snapshot_prepare(BlkTransactionState *common, state->old_bs = bdrv_lookup_bs(has_device ? device : NULL, has_node_name ? node_name : NULL, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { error_propagate(errp, local_err); return; } @@ -1293,7 +1318,7 @@ static void external_snapshot_prepare(BlkTransactionState *common, state->old_bs->filename, state->old_bs->drv->format_name, NULL, -1, flags, &local_err, false); - if (error_is_set(&local_err)) { + if (local_err) { error_propagate(errp, local_err); return; } @@ -1314,8 +1339,6 @@ static void external_snapshot_prepare(BlkTransactionState *common, if (ret != 0) { error_propagate(errp, local_err); } - - QDECREF(options); } static void external_snapshot_commit(BlkTransactionState *common) @@ -1364,7 +1387,7 @@ static void drive_backup_prepare(BlkTransactionState *common, Error **errp) backup->has_on_source_error, backup->on_source_error, backup->has_on_target_error, backup->on_target_error, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { error_propagate(errp, local_err); state->bs = NULL; state->job = NULL; @@ -1456,7 +1479,7 @@ void qmp_transaction(TransactionActionList *dev_list, Error **errp) QSIMPLEQ_INSERT_TAIL(&snap_bdrv_states, state, entry); state->ops->prepare(state, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { error_propagate(errp, local_err); goto delete_and_fail; } @@ -1537,7 +1560,7 @@ void qmp_block_passwd(bool has_device, const char *device, bs = bdrv_lookup_bs(has_device ? device : NULL, has_node_name ? node_name : NULL, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { error_propagate(errp, local_err); return; } @@ -1602,7 +1625,7 @@ void qmp_change_blockdev(const char *device, const char *filename, } eject_device(bs, 0, &err); - if (error_is_set(&err)) { + if (err) { error_propagate(errp, err); return; } @@ -1739,7 +1762,7 @@ void qmp_block_resize(bool has_device, const char *device, bs = bdrv_lookup_bs(has_device ? device : NULL, has_node_name ? node_name : NULL, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { error_propagate(errp, local_err); return; } @@ -1832,7 +1855,7 @@ void qmp_block_stream(const char *device, bool has_base, stream_start(bs, base_bs, base, has_speed ? speed : 0, on_error, block_job_cb, bs, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { error_propagate(errp, local_err); return; } @@ -1990,7 +2013,7 @@ void qmp_drive_backup(const char *device, const char *target, } } - if (error_is_set(&local_err)) { + if (local_err) { error_propagate(errp, local_err); return; } @@ -2131,7 +2154,7 @@ void qmp_drive_mirror(const char *device, const char *target, } } - if (error_is_set(&local_err)) { + if (local_err) { error_propagate(errp, local_err); return; } @@ -2270,7 +2293,7 @@ void qmp_blockdev_add(BlockdevOptions *options, Error **errp) visit_type_BlockdevOptions(qmp_output_get_visitor(ov), &options, NULL, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { error_propagate(errp, local_err); goto fail; } @@ -2280,8 +2303,8 @@ void qmp_blockdev_add(BlockdevOptions *options, Error **errp) qdict_flatten(qdict); - blockdev_init(NULL, qdict, IF_NONE, &local_err); - if (error_is_set(&local_err)) { + blockdev_init(NULL, qdict, &local_err); + if (local_err) { error_propagate(errp, local_err); goto fail; } diff --git a/blockjob.c b/blockjob.c index 9e5fd5c162..b3ce14cebd 100644 --- a/blockjob.c +++ b/blockjob.c @@ -61,7 +61,7 @@ void *block_job_create(const BlockJobDriver *driver, BlockDriverState *bs, Error *local_err = NULL; block_job_set_speed(job, speed, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { bs->job = NULL; g_free(job); bdrv_set_in_use(bs, 0); @@ -92,7 +92,7 @@ void block_job_set_speed(BlockJob *job, int64_t speed, Error **errp) return; } job->driver->set_speed(job, speed, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { error_propagate(errp, local_err); return; } @@ -1392,6 +1392,11 @@ EOF pie="no" fi fi + + if compile_prog "-fno-pie" "-nopie"; then + CFLAGS_NOPIE="-fno-pie" + LDFLAGS_NOPIE="-nopie" + fi fi ########################################## @@ -1474,9 +1479,11 @@ esac feature_not_found() { feature=$1 + remedy=$2 error_exit "User requested feature $feature" \ - "configure was not able to find it" + "configure was not able to find it." \ + "$remedy" } # --- @@ -1524,7 +1531,7 @@ int main(void) { } EOF if ! compile_object ; then - feature_not_found "nptl" + feature_not_found "nptl" "Install glibc and linux kernel headers." fi fi @@ -1555,7 +1562,7 @@ if test "$seccomp" != "no" ; then seccomp="yes" else if test "$seccomp" = "yes"; then - feature_not_found "libseccomp" + feature_not_found "libseccomp" "Install libseccomp devel >= 2.1.0" fi seccomp="no" fi @@ -1580,7 +1587,7 @@ EOF if ! compile_prog "" "$xen_libs" ; then # Xen not found if test "$xen" = "yes" ; then - feature_not_found "xen" + feature_not_found "xen" "Install xen devel" fi xen=no @@ -1703,7 +1710,7 @@ EOF # Xen version unsupported else if test "$xen" = "yes" ; then - feature_not_found "xen (unsupported version)" + feature_not_found "xen (unsupported version)" "Install supported xen (e.g. 4.0, 3.4, 3.3)" fi xen=no fi @@ -1752,7 +1759,7 @@ if test "$sparse" != "no" ; then sparse=yes else if test "$sparse" = "yes" ; then - feature_not_found "sparse" + feature_not_found "sparse" "Install sparse binary" fi sparse=no fi @@ -1774,7 +1781,7 @@ if test "$gtk" != "no"; then fi if ! $pkg_config --exists "$gtkpackage >= $gtkversion"; then if test "$gtk" = "yes" ; then - feature_not_found "gtk" + feature_not_found "gtk" "Install gtk2 or gtk3 (requires --with-gtkabi=3.0 option to configure) devel" fi gtk="no" elif ! $pkg_config --exists "$vtepackage >= $vteversion"; then @@ -1809,7 +1816,7 @@ elif has ${sdl_config}; then _sdlversion=`$sdlconfig --version | sed 's/[^0-9]//g'` else if test "$sdl" = "yes" ; then - feature_not_found "sdl" + feature_not_found "sdl" "Install SDL devel" fi sdl=no fi @@ -1853,7 +1860,7 @@ EOF fi # static link else # sdl not found if test "$sdl" = "yes" ; then - feature_not_found "sdl" + feature_not_found "sdl" "Install SDL devel" fi sdl=no fi # sdl compile test @@ -1919,10 +1926,10 @@ EOF QEMU_CFLAGS="$QEMU_CFLAGS $vnc_tls_cflags" else if test "$vnc_tls" = "yes" ; then - feature_not_found "vnc-tls" + feature_not_found "vnc-tls" "Install gnutls devel" fi if test "$vnc_ws" = "yes" ; then - feature_not_found "vnc-ws" + feature_not_found "vnc-ws" "Install gnutls devel" fi vnc_tls=no vnc_ws=no @@ -1946,7 +1953,7 @@ EOF QEMU_CFLAGS="$QEMU_CFLAGS $vnc_sasl_cflags" else if test "$vnc_sasl" = "yes" ; then - feature_not_found "vnc-sasl" + feature_not_found "vnc-sasl" "Install Cyrus SASL devel" fi vnc_sasl=no fi @@ -1968,7 +1975,7 @@ EOF QEMU_CFLAGS="$QEMU_CFLAGS $vnc_jpeg_cflags" else if test "$vnc_jpeg" = "yes" ; then - feature_not_found "vnc-jpeg" + feature_not_found "vnc-jpeg" "Install libjpeg-turbo devel" fi vnc_jpeg=no fi @@ -2000,7 +2007,7 @@ EOF QEMU_CFLAGS="$QEMU_CFLAGS $vnc_png_cflags" else if test "$vnc_png" = "yes" ; then - feature_not_found "vnc-png" + feature_not_found "vnc-png" "Install libpng devel" fi vnc_png=no fi @@ -2044,7 +2051,7 @@ EOF libs_tools="$uuid_libs $libs_tools" else if test "$uuid" = "yes" ; then - feature_not_found "uuid" + feature_not_found "uuid" "Install libuuid devel" fi uuid=no fi @@ -2078,7 +2085,7 @@ EOF xfs="yes" else if test "$xfs" = "yes" ; then - feature_not_found "xfs" + feature_not_found "xfs" "Instal xfsprogs/xfslibs devel" fi xfs=no fi @@ -2104,7 +2111,7 @@ EOF libs_tools="$vde_libs $libs_tools" else if test "$vde" = "yes" ; then - feature_not_found "vde" + feature_not_found "vde" "Install vde (Virtual Distributed Ethernet) devel" fi vde=no fi @@ -2147,7 +2154,7 @@ EOF libs_tools="$cap_libs $libs_tools" else if test "$cap_ng" = "yes" ; then - feature_not_found "cap_ng" + feature_not_found "cap_ng" "Install libcap-ng devel" fi cap_ng=no fi @@ -2252,7 +2259,7 @@ EOF libs_softmmu="$brlapi_libs $libs_softmmu" else if test "$brlapi" = "yes" ; then - feature_not_found "brlapi" + feature_not_found "brlapi" "Install brlapi devel" fi brlapi=no fi @@ -2289,7 +2296,7 @@ EOF curses=yes else if test "$curses" = "yes" ; then - feature_not_found "curses" + feature_not_found "curses" "Install ncurses devel" fi curses=no fi @@ -2315,7 +2322,7 @@ EOF libs_softmmu="$curl_libs $libs_softmmu" else if test "$curl" = "yes" ; then - feature_not_found "curl" + feature_not_found "curl" "Install libcurl devel" fi curl=no fi @@ -2335,7 +2342,7 @@ EOF libs_softmmu="$bluez_libs $libs_softmmu" else if test "$bluez" = "yes" ; then - feature_not_found "bluez" + feature_not_found "bluez" "Install bluez-libs/libbluetooth devel" fi bluez="no" fi @@ -2471,7 +2478,7 @@ EOF libs_softmmu="$rbd_libs $libs_softmmu" else if test "$rbd" = "yes" ; then - feature_not_found "rados block device" + feature_not_found "rados block device" "Install librbd/ceph devel" fi rbd=no fi @@ -2537,7 +2544,7 @@ EOF libs_tools="$libs_tools -laio" else if test "$linux_aio" = "yes" ; then - feature_not_found "linux AIO" + feature_not_found "linux AIO" "Install libaio devel" fi linux_aio=no fi @@ -2585,7 +2592,7 @@ EOF libattr=yes else if test "$attr" = "yes" ; then - feature_not_found "ATTR" + feature_not_found "ATTR" "Install libc6 or libattr devel" fi attr=no fi @@ -2662,8 +2669,8 @@ EOF fdt_libs="-L\$(BUILD_DIR)/dtc/libfdt $fdt_libs" elif test "$fdt" = "yes" ; then # have neither and want - prompt for system/submodule install - error_exit "DTC not present. Your options:" \ - " (1) Preferred: Install the DTC devel package" \ + error_exit "DTC (libfdt) not present. Your options:" \ + " (1) Preferred: Install the DTC (libfdt) devel package" \ " (2) Fetch the DTC submodule, using:" \ " git submodule update --init dtc" else @@ -2689,7 +2696,7 @@ EOF glx=yes else if test "$glx" = "yes" ; then - feature_not_found "glx" + feature_not_found "glx" "Install GL devel (e.g. MESA)" fi glx_libs= glx=no @@ -2714,7 +2721,7 @@ if test "$glusterfs" != "no" ; then fi else if test "$glusterfs" = "yes" ; then - feature_not_found "GlusterFS backend support" + feature_not_found "GlusterFS backend support" "Install glusterfs-api devel" fi glusterfs="no" fi @@ -3034,7 +3041,7 @@ if test "$docs" != "no" ; then docs=yes else if test "$docs" = "yes" ; then - feature_not_found "docs" + feature_not_found "docs" "Install texinfo and Perl/perl-podlators" fi docs=no fi @@ -3083,7 +3090,7 @@ EOF LIBS="$LIBS -liscsi" else if test "$libiscsi" = "yes" ; then - feature_not_found "libiscsi" + feature_not_found "libiscsi" "Install libiscsi devel" fi libiscsi="no" fi @@ -3167,7 +3174,7 @@ EOF spice_server_version=$($pkg_config --modversion spice-server) else if test "$spice" = "yes" ; then - feature_not_found "spice" + feature_not_found "spice" "Install spice-server and spice-protocol devel" fi spice="no" fi @@ -3217,7 +3224,7 @@ if test "$libusb" != "no" ; then libs_softmmu="$libs_softmmu $libusb_libs" else if test "$libusb" = "yes"; then - feature_not_found "libusb" + feature_not_found "libusb" "Install libusb devel" fi libusb="no" fi @@ -3233,7 +3240,7 @@ if test "$usb_redir" != "no" ; then libs_softmmu="$libs_softmmu $usb_redir_libs" else if test "$usb_redir" = "yes"; then - feature_not_found "usb-redir" + feature_not_found "usb-redir" "Install usbredir devel" fi usb_redir="no" fi @@ -4320,7 +4327,7 @@ if test "$trace_backend" = "ftrace"; then echo "CONFIG_TRACE_FTRACE=y" >> $config_host_mak trace_default=no else - feature_not_found "ftrace(trace backend)" + feature_not_found "ftrace(trace backend)" "ftrace requires Linux" fi fi echo "CONFIG_TRACE_FILE=$trace_file" >> $config_host_mak @@ -4376,6 +4383,7 @@ echo "LD=$ld" >> $config_host_mak echo "WINDRES=$windres" >> $config_host_mak echo "LIBTOOL=$libtool" >> $config_host_mak echo "CFLAGS=$CFLAGS" >> $config_host_mak +echo "CFLAGS_NOPIE=$CFLAGS_NOPIE" >> $config_host_mak echo "QEMU_CFLAGS=$QEMU_CFLAGS" >> $config_host_mak echo "QEMU_INCLUDES=$QEMU_INCLUDES" >> $config_host_mak if test "$sparse" = "yes" ; then @@ -4389,6 +4397,7 @@ else echo "AUTOCONF_HOST := " >> $config_host_mak fi echo "LDFLAGS=$LDFLAGS" >> $config_host_mak +echo "LDFLAGS_NOPIE=$LDFLAGS_NOPIE" >> $config_host_mak echo "LIBTOOLFLAGS=$LIBTOOLFLAGS" >> $config_host_mak echo "LIBS+=$LIBS" >> $config_host_mak echo "LIBS_TOOLS+=$libs_tools" >> $config_host_mak diff --git a/disas/libvixl/a64/disasm-a64.cc b/disas/libvixl/a64/disasm-a64.cc index 4a49748095..5c6b898ea6 100644 --- a/disas/libvixl/a64/disasm-a64.cc +++ b/disas/libvixl/a64/disasm-a64.cc @@ -269,19 +269,19 @@ bool Disassembler::IsMovzMovnImm(unsigned reg_size, uint64_t value) { ((reg_size == kWRegSize) && (value <= 0xffffffff))); // Test for movz: 16 bits set at positions 0, 16, 32 or 48. - if (((value & 0xffffffffffff0000UL) == 0UL) || - ((value & 0xffffffff0000ffffUL) == 0UL) || - ((value & 0xffff0000ffffffffUL) == 0UL) || - ((value & 0x0000ffffffffffffUL) == 0UL)) { + if (((value & 0xffffffffffff0000ULL) == 0ULL) || + ((value & 0xffffffff0000ffffULL) == 0ULL) || + ((value & 0xffff0000ffffffffULL) == 0ULL) || + ((value & 0x0000ffffffffffffULL) == 0ULL)) { return true; } // Test for movn: NOT(16 bits set at positions 0, 16, 32 or 48). if ((reg_size == kXRegSize) && - (((value & 0xffffffffffff0000UL) == 0xffffffffffff0000UL) || - ((value & 0xffffffff0000ffffUL) == 0xffffffff0000ffffUL) || - ((value & 0xffff0000ffffffffUL) == 0xffff0000ffffffffUL) || - ((value & 0x0000ffffffffffffUL) == 0x0000ffffffffffffUL))) { + (((value & 0xffffffffffff0000ULL) == 0xffffffffffff0000ULL) || + ((value & 0xffffffff0000ffffULL) == 0xffffffff0000ffffULL) || + ((value & 0xffff0000ffffffffULL) == 0xffff0000ffffffffULL) || + ((value & 0x0000ffffffffffffULL) == 0x0000ffffffffffffULL))) { return true; } if ((reg_size == kWRegSize) && diff --git a/disas/libvixl/utils.cc b/disas/libvixl/utils.cc index 6f85e61835..a45fb95f47 100644 --- a/disas/libvixl/utils.cc +++ b/disas/libvixl/utils.cc @@ -95,7 +95,7 @@ int CountSetBits(uint64_t value, int width) { ASSERT((width == 32) || (width == 64)); // Mask out unused bits to ensure that they are not counted. - value &= (0xffffffffffffffffUL >> (64-width)); + value &= (0xffffffffffffffffULL >> (64-width)); // Add up the set bits. // The algorithm works by adding pairs of bit fields together iteratively, @@ -108,12 +108,18 @@ int CountSetBits(uint64_t value, int width) { // value = h+g+f+e d+c+b+a // \ | // value = h+g+f+e+d+c+b+a - value = ((value >> 1) & 0x5555555555555555) + (value & 0x5555555555555555); - value = ((value >> 2) & 0x3333333333333333) + (value & 0x3333333333333333); - value = ((value >> 4) & 0x0f0f0f0f0f0f0f0f) + (value & 0x0f0f0f0f0f0f0f0f); - value = ((value >> 8) & 0x00ff00ff00ff00ff) + (value & 0x00ff00ff00ff00ff); - value = ((value >> 16) & 0x0000ffff0000ffff) + (value & 0x0000ffff0000ffff); - value = ((value >> 32) & 0x00000000ffffffff) + (value & 0x00000000ffffffff); + value = ((value >> 1) & 0x5555555555555555ULL) + + (value & 0x5555555555555555ULL); + value = ((value >> 2) & 0x3333333333333333ULL) + + (value & 0x3333333333333333ULL); + value = ((value >> 4) & 0x0f0f0f0f0f0f0f0fULL) + + (value & 0x0f0f0f0f0f0f0f0fULL); + value = ((value >> 8) & 0x00ff00ff00ff00ffULL) + + (value & 0x00ff00ff00ff00ffULL); + value = ((value >> 16) & 0x0000ffff0000ffffULL) + + (value & 0x0000ffff0000ffffULL); + value = ((value >> 32) & 0x00000000ffffffffULL) + + (value & 0x00000000ffffffffULL); return value; } @@ -881,7 +881,7 @@ void hmp_balloon(Monitor *mon, const QDict *qdict) Error *errp = NULL; qmp_balloon(value, &errp); - if (error_is_set(&errp)) { + if (errp) { monitor_printf(mon, "balloon: %s\n", error_get_pretty(errp)); error_free(errp); } @@ -1118,7 +1118,7 @@ void hmp_change(Monitor *mon, const QDict *qdict) } qmp_change(device, target, !!arg, arg, &err); - if (error_is_set(&err) && + if (err && error_get_class(err) == ERROR_CLASS_DEVICE_ENCRYPTED) { error_free(err); monitor_read_block_device_key(mon, device, NULL, NULL); @@ -1234,7 +1234,8 @@ static void hmp_migrate_status_cb(void *opaque) MigrationInfo *info; info = qmp_query_migrate(NULL); - if (!info->has_status || strcmp(info->status, "active") == 0) { + if (!info->has_status || strcmp(info->status, "active") == 0 || + strcmp(info->status, "setup") == 0) { if (info->has_disk) { int progress; @@ -1335,12 +1336,12 @@ void hmp_netdev_add(Monitor *mon, const QDict *qdict) QemuOpts *opts; opts = qemu_opts_from_qdict(qemu_find_opts("netdev"), qdict, &err); - if (error_is_set(&err)) { + if (err) { goto out; } netdev_add(opts, &err); - if (error_is_set(&err)) { + if (err) { qemu_opts_del(opts); } diff --git a/hw/acpi/pcihp.c b/hw/acpi/pcihp.c index 3fa3d7c290..f80c48008c 100644 --- a/hw/acpi/pcihp.c +++ b/hw/acpi/pcihp.c @@ -46,13 +46,15 @@ # define ACPI_PCIHP_DPRINTF(format, ...) do { } while (0) #endif -#define PCI_HOTPLUG_ADDR 0xae00 -#define PCI_HOTPLUG_SIZE 0x0014 -#define PCI_UP_BASE 0xae00 -#define PCI_DOWN_BASE 0xae04 -#define PCI_EJ_BASE 0xae08 -#define PCI_RMV_BASE 0xae0c -#define PCI_SEL_BASE 0xae10 +#define ACPI_PCI_HOTPLUG_STATUS 2 +#define ACPI_PCIHP_ADDR 0xae00 +#define ACPI_PCIHP_SIZE 0x0014 +#define ACPI_PCIHP_LEGACY_SIZE 0x000f +#define PCI_UP_BASE 0x0000 +#define PCI_DOWN_BASE 0x0004 +#define PCI_EJ_BASE 0x0008 +#define PCI_RMV_BASE 0x000c +#define PCI_SEL_BASE 0x0010 typedef struct AcpiPciHpFind { int bsel; @@ -104,19 +106,19 @@ static PCIBus *acpi_pcihp_find_hotplug_bus(AcpiPciHpState *s, int bsel) static bool acpi_pcihp_pc_no_hotplug(AcpiPciHpState *s, PCIDevice *dev) { PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev); + DeviceClass *dc = DEVICE_GET_CLASS(dev); /* * ACPI doesn't allow hotplug of bridge devices. Don't allow * hot-unplug of bridge devices unless they were added by hotplug * (and so, not described by acpi). */ - return (pc->is_bridge && !dev->qdev.hotplugged) || pc->no_hotplug; + return (pc->is_bridge && !dev->qdev.hotplugged) || !dc->hotpluggable; } static void acpi_pcihp_eject_slot(AcpiPciHpState *s, unsigned bsel, unsigned slots) { BusChild *kid, *next; int slot = ffs(slots) - 1; - bool slot_free = true; PCIBus *bus = acpi_pcihp_find_hotplug_bus(s, bsel); if (!bus) { @@ -125,21 +127,17 @@ static void acpi_pcihp_eject_slot(AcpiPciHpState *s, unsigned bsel, unsigned slo /* Mark request as complete */ s->acpi_pcihp_pci_status[bsel].down &= ~(1U << slot); + s->acpi_pcihp_pci_status[bsel].up &= ~(1U << slot); QTAILQ_FOREACH_SAFE(kid, &bus->qbus.children, sibling, next) { DeviceState *qdev = kid->child; PCIDevice *dev = PCI_DEVICE(qdev); if (PCI_SLOT(dev->devfn) == slot) { - if (acpi_pcihp_pc_no_hotplug(s, dev)) { - slot_free = false; - } else { + if (!acpi_pcihp_pc_no_hotplug(s, dev)) { object_unparent(OBJECT(qdev)); } } } - if (slot_free) { - s->acpi_pcihp_pci_status[bsel].device_present &= ~(1U << slot); - } } static void acpi_pcihp_update_hotplug_bus(AcpiPciHpState *s, int bsel) @@ -153,7 +151,6 @@ static void acpi_pcihp_update_hotplug_bus(AcpiPciHpState *s, int bsel) } s->acpi_pcihp_pci_status[bsel].hotplug_enable = ~0; - s->acpi_pcihp_pci_status[bsel].device_present = 0; if (!bus) { return; @@ -166,8 +163,6 @@ static void acpi_pcihp_update_hotplug_bus(AcpiPciHpState *s, int bsel) if (acpi_pcihp_pc_no_hotplug(s, pdev)) { s->acpi_pcihp_pci_status[bsel].hotplug_enable &= ~(1U << slot); } - - s->acpi_pcihp_pci_status[bsel].device_present |= (1U << slot); } } @@ -185,40 +180,47 @@ void acpi_pcihp_reset(AcpiPciHpState *s) acpi_pcihp_update(s); } -static void enable_device(AcpiPciHpState *s, unsigned bsel, int slot) -{ - s->acpi_pcihp_pci_status[bsel].device_present |= (1U << slot); -} - -static void disable_device(AcpiPciHpState *s, unsigned bsel, int slot) -{ - s->acpi_pcihp_pci_status[bsel].down |= (1U << slot); -} - -int acpi_pcihp_device_hotplug(AcpiPciHpState *s, PCIDevice *dev, - PCIHotplugState state) +void acpi_pcihp_device_plug_cb(ACPIREGS *ar, qemu_irq irq, AcpiPciHpState *s, + DeviceState *dev, Error **errp) { - int slot = PCI_SLOT(dev->devfn); - int bsel = acpi_pcihp_get_bsel(dev->bus); + PCIDevice *pdev = PCI_DEVICE(dev); + int slot = PCI_SLOT(pdev->devfn); + int bsel = acpi_pcihp_get_bsel(pdev->bus); if (bsel < 0) { - return -1; + error_setg(errp, "Unsupported bus. Bus doesn't have property '" + ACPI_PCIHP_PROP_BSEL "' set"); + return; } /* Don't send event when device is enabled during qemu machine creation: * it is present on boot, no hotplug event is necessary. We do send an * event when the device is disabled later. */ - if (state == PCI_COLDPLUG_ENABLED) { - s->acpi_pcihp_pci_status[bsel].device_present |= (1U << slot); - return 0; + if (!dev->hotplugged) { + return; } - if (state == PCI_HOTPLUG_ENABLED) { - enable_device(s, bsel, slot); - } else { - disable_device(s, bsel, slot); + s->acpi_pcihp_pci_status[bsel].up |= (1U << slot); + + ar->gpe.sts[0] |= ACPI_PCI_HOTPLUG_STATUS; + acpi_update_sci(ar, irq); +} + +void acpi_pcihp_device_unplug_cb(ACPIREGS *ar, qemu_irq irq, AcpiPciHpState *s, + DeviceState *dev, Error **errp) +{ + PCIDevice *pdev = PCI_DEVICE(dev); + int slot = PCI_SLOT(pdev->devfn); + int bsel = acpi_pcihp_get_bsel(pdev->bus); + if (bsel < 0) { + error_setg(errp, "Unsupported bus. Bus doesn't have property '" + ACPI_PCIHP_PROP_BSEL "' set"); + return; } - return 0; + s->acpi_pcihp_pci_status[bsel].down |= (1U << slot); + + ar->gpe.sts[0] |= ACPI_PCI_HOTPLUG_STATUS; + acpi_update_sci(ar, irq); } static uint64_t pci_read(void *opaque, hwaddr addr, unsigned int size) @@ -232,26 +234,26 @@ static uint64_t pci_read(void *opaque, hwaddr addr, unsigned int size) } switch (addr) { - case PCI_UP_BASE - PCI_HOTPLUG_ADDR: - /* Manufacture an "up" value to cause a device check on any hotplug - * slot with a device. Extra device checks are harmless. */ - val = s->acpi_pcihp_pci_status[bsel].device_present & - s->acpi_pcihp_pci_status[bsel].hotplug_enable; + case PCI_UP_BASE: + val = s->acpi_pcihp_pci_status[bsel].up; + if (!s->legacy_piix) { + s->acpi_pcihp_pci_status[bsel].up = 0; + } ACPI_PCIHP_DPRINTF("pci_up_read %" PRIu32 "\n", val); break; - case PCI_DOWN_BASE - PCI_HOTPLUG_ADDR: + case PCI_DOWN_BASE: val = s->acpi_pcihp_pci_status[bsel].down; ACPI_PCIHP_DPRINTF("pci_down_read %" PRIu32 "\n", val); break; - case PCI_EJ_BASE - PCI_HOTPLUG_ADDR: + case PCI_EJ_BASE: /* No feature defined yet */ ACPI_PCIHP_DPRINTF("pci_features_read %" PRIu32 "\n", val); break; - case PCI_RMV_BASE - PCI_HOTPLUG_ADDR: + case PCI_RMV_BASE: val = s->acpi_pcihp_pci_status[bsel].hotplug_enable; ACPI_PCIHP_DPRINTF("pci_rmv_read %" PRIu32 "\n", val); break; - case PCI_SEL_BASE - PCI_HOTPLUG_ADDR: + case PCI_SEL_BASE: val = s->hotplug_select; ACPI_PCIHP_DPRINTF("pci_sel_read %" PRIu32 "\n", val); default: @@ -266,7 +268,7 @@ static void pci_write(void *opaque, hwaddr addr, uint64_t data, { AcpiPciHpState *s = opaque; switch (addr) { - case PCI_EJ_BASE - PCI_HOTPLUG_ADDR: + case PCI_EJ_BASE: if (s->hotplug_select >= ACPI_PCIHP_MAX_HOTPLUG_BUS) { break; } @@ -274,7 +276,7 @@ static void pci_write(void *opaque, hwaddr addr, uint64_t data, ACPI_PCIHP_DPRINTF("pciej write %" HWADDR_PRIx " <== %" PRIu64 "\n", addr, data); break; - case PCI_SEL_BASE - PCI_HOTPLUG_ADDR: + case PCI_SEL_BASE: s->hotplug_select = data; ACPI_PCIHP_DPRINTF("pcisel write %" HWADDR_PRIx " <== %" PRIu64 "\n", addr, data); @@ -294,13 +296,26 @@ static const MemoryRegionOps acpi_pcihp_io_ops = { }; void acpi_pcihp_init(AcpiPciHpState *s, PCIBus *root_bus, - MemoryRegion *address_space_io) + MemoryRegion *address_space_io, bool bridges_enabled) { + uint16_t io_size = ACPI_PCIHP_SIZE; + s->root= root_bus; + s->legacy_piix = !bridges_enabled; + + if (s->legacy_piix) { + unsigned *bus_bsel = g_malloc(sizeof *bus_bsel); + + io_size = ACPI_PCIHP_LEGACY_SIZE; + + *bus_bsel = ACPI_PCIHP_BSEL_DEFAULT; + object_property_add_uint32_ptr(OBJECT(root_bus), ACPI_PCIHP_PROP_BSEL, + bus_bsel, NULL); + } + memory_region_init_io(&s->io, NULL, &acpi_pcihp_io_ops, s, - "acpi-pci-hotplug", - PCI_HOTPLUG_SIZE); - memory_region_add_subregion(address_space_io, PCI_HOTPLUG_ADDR, &s->io); + "acpi-pci-hotplug", io_size); + memory_region_add_subregion(address_space_io, ACPI_PCIHP_ADDR, &s->io); } const VMStateDescription vmstate_acpi_pcihp_pci_status = { diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c index 33e812d238..67dc0752f7 100644 --- a/hw/acpi/piix4.c +++ b/hw/acpi/piix4.c @@ -32,6 +32,7 @@ #include "hw/acpi/piix4.h" #include "hw/acpi/pcihp.h" #include "hw/acpi/cpu_hotplug.h" +#include "hw/hotplug.h" //#define DEBUG @@ -44,15 +45,6 @@ #define GPE_BASE 0xafe0 #define GPE_LEN 4 -#define PCI_HOTPLUG_ADDR 0xae00 -#define PCI_HOTPLUG_SIZE 0x000f -#define PCI_UP_BASE 0xae00 -#define PCI_DOWN_BASE 0xae04 -#define PCI_EJ_BASE 0xae08 -#define PCI_RMV_BASE 0xae0c - -#define PIIX4_PCI_HOTPLUG_STATUS 2 - struct pci_status { uint32_t up; /* deprecated, maintained for migration compatibility */ uint32_t down; @@ -80,13 +72,6 @@ typedef struct PIIX4PMState { Notifier machine_ready; Notifier powerdown_notifier; - /* for legacy pci hotplug (compatible with qemu 1.6 and older) */ - MemoryRegion io_pci; - struct pci_status pci0_status; - uint32_t pci0_hotplug_enable; - uint32_t pci0_slot_device_present; - - /* for new pci hotplug (with PCI2PCI bridge support) */ AcpiPciHpState acpi_pci_hotplug; bool use_acpi_pci_hotplug; @@ -170,17 +155,6 @@ static void pm_write_config(PCIDevice *d, } } -static void vmstate_pci_status_pre_save(void *opaque) -{ - struct pci_status *pci0_status = opaque; - PIIX4PMState *s = container_of(pci0_status, PIIX4PMState, pci0_status); - - /* We no longer track up, so build a safe value for migrating - * to a version that still does... of course these might get lost - * by an old buggy implementation, but we try. */ - pci0_status->up = s->pci0_slot_device_present & s->pci0_hotplug_enable; -} - static int vmstate_acpi_post_load(void *opaque, int version_id) { PIIX4PMState *s = opaque; @@ -216,10 +190,9 @@ static const VMStateDescription vmstate_pci_status = { .version_id = 1, .minimum_version_id = 1, .minimum_version_id_old = 1, - .pre_save = vmstate_pci_status_pre_save, .fields = (VMStateField []) { - VMSTATE_UINT32(up, struct pci_status), - VMSTATE_UINT32(down, struct pci_status), + VMSTATE_UINT32(up, struct AcpiPciHpPciStatus), + VMSTATE_UINT32(down, struct AcpiPciHpPciStatus), VMSTATE_END_OF_LIST() } }; @@ -256,7 +229,8 @@ static int acpi_load_old(QEMUFile *f, void *opaque, int version_id) qemu_get_be16s(f, &temp); } - ret = vmstate_load_state(f, &vmstate_pci_status, &s->pci0_status, 1); + ret = vmstate_load_state(f, &vmstate_pci_status, + &s->acpi_pci_hotplug.acpi_pcihp_pci_status[ACPI_PCIHP_BSEL_DEFAULT], 1); return ret; } @@ -294,70 +268,18 @@ static const VMStateDescription vmstate_acpi = { VMSTATE_TIMER(ar.tmr.timer, PIIX4PMState), VMSTATE_INT64(ar.tmr.overflow_time, PIIX4PMState), VMSTATE_STRUCT(ar.gpe, PIIX4PMState, 2, vmstate_gpe, ACPIGPE), - VMSTATE_STRUCT_TEST(pci0_status, PIIX4PMState, - vmstate_test_no_use_acpi_pci_hotplug, - 2, vmstate_pci_status, - struct pci_status), + VMSTATE_STRUCT_TEST( + acpi_pci_hotplug.acpi_pcihp_pci_status[ACPI_PCIHP_BSEL_DEFAULT], + PIIX4PMState, + vmstate_test_no_use_acpi_pci_hotplug, + 2, vmstate_pci_status, + struct AcpiPciHpPciStatus), VMSTATE_PCI_HOTPLUG(acpi_pci_hotplug, PIIX4PMState, vmstate_test_use_acpi_pci_hotplug), VMSTATE_END_OF_LIST() } }; -static void acpi_piix_eject_slot(PIIX4PMState *s, unsigned slots) -{ - BusChild *kid, *next; - BusState *bus = qdev_get_parent_bus(DEVICE(s)); - int slot = ffs(slots) - 1; - bool slot_free = true; - - /* Mark request as complete */ - s->pci0_status.down &= ~(1U << slot); - - QTAILQ_FOREACH_SAFE(kid, &bus->children, sibling, next) { - DeviceState *qdev = kid->child; - PCIDevice *dev = PCI_DEVICE(qdev); - PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev); - if (PCI_SLOT(dev->devfn) == slot) { - if (pc->no_hotplug) { - slot_free = false; - } else { - object_unparent(OBJECT(qdev)); - } - } - } - if (slot_free) { - s->pci0_slot_device_present &= ~(1U << slot); - } -} - -static void piix4_update_hotplug(PIIX4PMState *s) -{ - BusState *bus = qdev_get_parent_bus(DEVICE(s)); - BusChild *kid, *next; - - /* Execute any pending removes during reset */ - while (s->pci0_status.down) { - acpi_piix_eject_slot(s, s->pci0_status.down); - } - - s->pci0_hotplug_enable = ~0; - s->pci0_slot_device_present = 0; - - QTAILQ_FOREACH_SAFE(kid, &bus->children, sibling, next) { - DeviceState *qdev = kid->child; - PCIDevice *pdev = PCI_DEVICE(qdev); - PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(pdev); - int slot = PCI_SLOT(pdev->devfn); - - if (pc->no_hotplug) { - s->pci0_hotplug_enable &= ~(1U << slot); - } - - s->pci0_slot_device_present |= (1U << slot); - } -} - static void piix4_reset(void *opaque) { PIIX4PMState *s = opaque; @@ -377,11 +299,7 @@ static void piix4_reset(void *opaque) pci_conf[0x5B] = 0x02; } pm_io_space_update(s); - if (s->use_acpi_pci_hotplug) { - acpi_pcihp_reset(&s->acpi_pci_hotplug); - } else { - piix4_update_hotplug(s); - } + acpi_pcihp_reset(&s->acpi_pci_hotplug); } static void piix4_pm_powerdown_req(Notifier *n, void *opaque) @@ -392,24 +310,26 @@ static void piix4_pm_powerdown_req(Notifier *n, void *opaque) acpi_pm1_evt_power_down(&s->ar); } -static int piix4_acpi_pci_hotplug(DeviceState *qdev, PCIDevice *dev, - PCIHotplugState state) +static void piix4_pci_device_plug_cb(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) { - PIIX4PMState *s = PIIX4_PM(qdev); - int ret = acpi_pcihp_device_hotplug(&s->acpi_pci_hotplug, dev, state); - if (ret < 0) { - return ret; - } - s->ar.gpe.sts[0] |= PIIX4_PCI_HOTPLUG_STATUS; + PIIX4PMState *s = PIIX4_PM(hotplug_dev); + acpi_pcihp_device_plug_cb(&s->ar, s->irq, &s->acpi_pci_hotplug, dev, errp); +} - acpi_update_sci(&s->ar, s->irq); - return 0; +static void piix4_pci_device_unplug_cb(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + PIIX4PMState *s = PIIX4_PM(hotplug_dev); + acpi_pcihp_device_unplug_cb(&s->ar, s->irq, &s->acpi_pci_hotplug, dev, + errp); } -static void piix4_update_bus_hotplug(PCIBus *bus, void *opaque) +static void piix4_update_bus_hotplug(PCIBus *pci_bus, void *opaque) { PIIX4PMState *s = opaque; - pci_bus_hotplug(bus, piix4_acpi_pci_hotplug, DEVICE(s)); + + qbus_set_hotplug_handler(BUS(pci_bus), DEVICE(s), &error_abort); } static void piix4_pm_machine_ready(Notifier *n, void *opaque) @@ -428,6 +348,8 @@ static void piix4_pm_machine_ready(Notifier *n, void *opaque) if (s->use_acpi_pci_hotplug) { pci_for_each_bus(d->bus, piix4_update_bus_hotplug, s); + } else { + piix4_update_bus_hotplug(d->bus, s); } } @@ -545,52 +467,6 @@ I2CBus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base, return s->smb.smbus; } -static Property piix4_pm_properties[] = { - DEFINE_PROP_UINT32("smb_io_base", PIIX4PMState, smb_io_base, 0), - DEFINE_PROP_UINT8(ACPI_PM_PROP_S3_DISABLED, PIIX4PMState, disable_s3, 0), - DEFINE_PROP_UINT8(ACPI_PM_PROP_S4_DISABLED, PIIX4PMState, disable_s4, 0), - DEFINE_PROP_UINT8(ACPI_PM_PROP_S4_VAL, PIIX4PMState, s4_val, 2), - DEFINE_PROP_BOOL("acpi-pci-hotplug-with-bridge-support", PIIX4PMState, - use_acpi_pci_hotplug, true), - DEFINE_PROP_END_OF_LIST(), -}; - -static void piix4_pm_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - - k->no_hotplug = 1; - k->init = piix4_pm_initfn; - k->config_write = pm_write_config; - k->vendor_id = PCI_VENDOR_ID_INTEL; - k->device_id = PCI_DEVICE_ID_INTEL_82371AB_3; - k->revision = 0x03; - k->class_id = PCI_CLASS_BRIDGE_OTHER; - dc->desc = "PM"; - dc->vmsd = &vmstate_acpi; - dc->props = piix4_pm_properties; - /* - * Reason: part of PIIX4 southbridge, needs to be wired up, - * e.g. by mips_malta_init() - */ - dc->cannot_instantiate_with_device_add_yet = true; -} - -static const TypeInfo piix4_pm_info = { - .name = TYPE_PIIX4_PM, - .parent = TYPE_PCI_DEVICE, - .instance_size = sizeof(PIIX4PMState), - .class_init = piix4_pm_class_init, -}; - -static void piix4_pm_register_types(void) -{ - type_register_static(&piix4_pm_info); -} - -type_init(piix4_pm_register_types) - static uint64_t gpe_readb(void *opaque, hwaddr addr, unsigned width) { PIIX4PMState *s = opaque; @@ -621,60 +497,6 @@ static const MemoryRegionOps piix4_gpe_ops = { .endianness = DEVICE_LITTLE_ENDIAN, }; -static uint64_t pci_read(void *opaque, hwaddr addr, unsigned int size) -{ - PIIX4PMState *s = opaque; - uint32_t val = 0; - - switch (addr) { - case PCI_UP_BASE - PCI_HOTPLUG_ADDR: - /* Manufacture an "up" value to cause a device check on any hotplug - * slot with a device. Extra device checks are harmless. */ - val = s->pci0_slot_device_present & s->pci0_hotplug_enable; - PIIX4_DPRINTF("pci_up_read %" PRIu32 "\n", val); - break; - case PCI_DOWN_BASE - PCI_HOTPLUG_ADDR: - val = s->pci0_status.down; - PIIX4_DPRINTF("pci_down_read %" PRIu32 "\n", val); - break; - case PCI_EJ_BASE - PCI_HOTPLUG_ADDR: - /* No feature defined yet */ - PIIX4_DPRINTF("pci_features_read %" PRIu32 "\n", val); - break; - case PCI_RMV_BASE - PCI_HOTPLUG_ADDR: - val = s->pci0_hotplug_enable; - break; - default: - break; - } - - return val; -} - -static void pci_write(void *opaque, hwaddr addr, uint64_t data, - unsigned int size) -{ - switch (addr) { - case PCI_EJ_BASE - PCI_HOTPLUG_ADDR: - acpi_piix_eject_slot(opaque, (uint32_t)data); - PIIX4_DPRINTF("pciej write %" HWADDR_PRIx " <== %" PRIu64 "\n", - addr, data); - break; - default: - break; - } -} - -static const MemoryRegionOps piix4_pci_ops = { - .read = pci_read, - .write = pci_write, - .endianness = DEVICE_LITTLE_ENDIAN, - .valid = { - .min_access_size = 4, - .max_access_size = 4, - }, -}; - static void piix4_cpu_added_req(Notifier *n, void *opaque) { PIIX4PMState *s = container_of(n, PIIX4PMState, cpu_added_notifier); @@ -684,9 +506,6 @@ static void piix4_cpu_added_req(Notifier *n, void *opaque) acpi_update_sci(&s->ar, s->irq); } -static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev, - PCIHotplugState state); - static void piix4_acpi_system_hot_add_init(MemoryRegion *parent, PCIBus *bus, PIIX4PMState *s) { @@ -694,15 +513,8 @@ static void piix4_acpi_system_hot_add_init(MemoryRegion *parent, "acpi-gpe0", GPE_LEN); memory_region_add_subregion(parent, GPE_BASE, &s->io_gpe); - if (s->use_acpi_pci_hotplug) { - acpi_pcihp_init(&s->acpi_pci_hotplug, bus, parent); - } else { - memory_region_init_io(&s->io_pci, OBJECT(s), &piix4_pci_ops, s, - "acpi-pci-hotplug", PCI_HOTPLUG_SIZE); - memory_region_add_subregion(parent, PCI_HOTPLUG_ADDR, - &s->io_pci); - pci_bus_hotplug(bus, piix4_device_hotplug, DEVICE(s)); - } + acpi_pcihp_init(&s->acpi_pci_hotplug, bus, parent, + s->use_acpi_pci_hotplug); AcpiCpuHotplug_init(parent, OBJECT(s), &s->gpe_cpu, PIIX4_CPU_HOTPLUG_IO_BASE); @@ -710,39 +522,55 @@ static void piix4_acpi_system_hot_add_init(MemoryRegion *parent, qemu_register_cpu_added_notifier(&s->cpu_added_notifier); } -static void enable_device(PIIX4PMState *s, int slot) -{ - s->ar.gpe.sts[0] |= PIIX4_PCI_HOTPLUG_STATUS; - s->pci0_slot_device_present |= (1U << slot); -} +static Property piix4_pm_properties[] = { + DEFINE_PROP_UINT32("smb_io_base", PIIX4PMState, smb_io_base, 0), + DEFINE_PROP_UINT8(ACPI_PM_PROP_S3_DISABLED, PIIX4PMState, disable_s3, 0), + DEFINE_PROP_UINT8(ACPI_PM_PROP_S4_DISABLED, PIIX4PMState, disable_s4, 0), + DEFINE_PROP_UINT8(ACPI_PM_PROP_S4_VAL, PIIX4PMState, s4_val, 2), + DEFINE_PROP_BOOL("acpi-pci-hotplug-with-bridge-support", PIIX4PMState, + use_acpi_pci_hotplug, true), + DEFINE_PROP_END_OF_LIST(), +}; -static void disable_device(PIIX4PMState *s, int slot) +static void piix4_pm_class_init(ObjectClass *klass, void *data) { - s->ar.gpe.sts[0] |= PIIX4_PCI_HOTPLUG_STATUS; - s->pci0_status.down |= (1U << slot); -} + DeviceClass *dc = DEVICE_CLASS(klass); + PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass); -static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev, - PCIHotplugState state) -{ - int slot = PCI_SLOT(dev->devfn); - PIIX4PMState *s = PIIX4_PM(qdev); - - /* Don't send event when device is enabled during qemu machine creation: - * it is present on boot, no hotplug event is necessary. We do send an - * event when the device is disabled later. */ - if (state == PCI_COLDPLUG_ENABLED) { - s->pci0_slot_device_present |= (1U << slot); - return 0; - } + k->init = piix4_pm_initfn; + k->config_write = pm_write_config; + k->vendor_id = PCI_VENDOR_ID_INTEL; + k->device_id = PCI_DEVICE_ID_INTEL_82371AB_3; + k->revision = 0x03; + k->class_id = PCI_CLASS_BRIDGE_OTHER; + dc->desc = "PM"; + dc->vmsd = &vmstate_acpi; + dc->props = piix4_pm_properties; + /* + * Reason: part of PIIX4 southbridge, needs to be wired up, + * e.g. by mips_malta_init() + */ + dc->cannot_instantiate_with_device_add_yet = true; + dc->hotpluggable = false; + hc->plug = piix4_pci_device_plug_cb; + hc->unplug = piix4_pci_device_unplug_cb; +} - if (state == PCI_HOTPLUG_ENABLED) { - enable_device(s, slot); - } else { - disable_device(s, slot); +static const TypeInfo piix4_pm_info = { + .name = TYPE_PIIX4_PM, + .parent = TYPE_PCI_DEVICE, + .instance_size = sizeof(PIIX4PMState), + .class_init = piix4_pm_class_init, + .interfaces = (InterfaceInfo[]) { + { TYPE_HOTPLUG_HANDLER }, + { } } +}; - acpi_update_sci(&s->ar, s->irq); - - return 0; +static void piix4_pm_register_types(void) +{ + type_register_static(&piix4_pm_info); } + +type_init(piix4_pm_register_types) diff --git a/hw/char/serial.c b/hw/char/serial.c index 27dab7d9d6..6d3b5aff8b 100644 --- a/hw/char/serial.c +++ b/hw/char/serial.c @@ -225,7 +225,7 @@ static gboolean serial_xmit(GIOChannel *chan, GIOCondition cond, void *opaque) if (s->tsr_retry <= 0) { if (s->fcr & UART_FCR_FE) { - s->tsr = fifo8_is_full(&s->xmit_fifo) ? + s->tsr = fifo8_is_empty(&s->xmit_fifo) ? 0 : fifo8_pop(&s->xmit_fifo); if (!s->xmit_fifo.num) { s->lsr |= UART_LSR_THRE; diff --git a/hw/core/Makefile.objs b/hw/core/Makefile.objs index 950146c6ff..9e324befd6 100644 --- a/hw/core/Makefile.objs +++ b/hw/core/Makefile.objs @@ -2,6 +2,7 @@ common-obj-y += qdev.o qdev-properties.o # irq.o needed for qdev GPIO handling: common-obj-y += irq.o +common-obj-y += hotplug.o common-obj-$(CONFIG_EMPTY_SLOT) += empty_slot.o common-obj-$(CONFIG_XILINX_AXI) += stream.o diff --git a/hw/core/hotplug.c b/hw/core/hotplug.c new file mode 100644 index 0000000000..5573d9d2d9 --- /dev/null +++ b/hw/core/hotplug.c @@ -0,0 +1,48 @@ +/* + * Hotplug handler interface. + * + * Copyright (c) 2014 Red Hat Inc. + * + * Authors: + * Igor Mammedov <imammedo@redhat.com>, + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ +#include "hw/hotplug.h" +#include "qemu/module.h" + +void hotplug_handler_plug(HotplugHandler *plug_handler, + DeviceState *plugged_dev, + Error **errp) +{ + HotplugHandlerClass *hdc = HOTPLUG_HANDLER_GET_CLASS(plug_handler); + + if (hdc->plug) { + hdc->plug(plug_handler, plugged_dev, errp); + } +} + +void hotplug_handler_unplug(HotplugHandler *plug_handler, + DeviceState *plugged_dev, + Error **errp) +{ + HotplugHandlerClass *hdc = HOTPLUG_HANDLER_GET_CLASS(plug_handler); + + if (hdc->unplug) { + hdc->unplug(plug_handler, plugged_dev, errp); + } +} + +static const TypeInfo hotplug_handler_info = { + .name = TYPE_HOTPLUG_HANDLER, + .parent = TYPE_INTERFACE, + .class_size = sizeof(HotplugHandlerClass), +}; + +static void hotplug_handler_register_types(void) +{ + type_register_static(&hotplug_handler_info); +} + +type_init(hotplug_handler_register_types) diff --git a/hw/core/qdev.c b/hw/core/qdev.c index 482a9780d1..c0b857fbd4 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -32,6 +32,7 @@ #include "qapi/visitor.h" #include "qapi/qmp/qjson.h" #include "monitor/monitor.h" +#include "hw/hotplug.h" int qdev_hotplug = 0; static bool qdev_hot_added = false; @@ -212,13 +213,22 @@ void qdev_unplug(DeviceState *dev, Error **errp) error_set(errp, QERR_BUS_NO_HOTPLUG, dev->parent_bus->name); return; } - assert(dc->unplug != NULL); + + if (!dc->hotpluggable) { + error_set(errp, QERR_DEVICE_NO_HOTPLUG, + object_get_typename(OBJECT(dev))); + return; + } qdev_hot_removed = true; - if (dc->unplug(dev) < 0) { - error_set(errp, QERR_UNDEFINED_ERROR); - return; + if (dev->parent_bus && dev->parent_bus->hotplug_handler) { + hotplug_handler_unplug(dev->parent_bus->hotplug_handler, dev, errp); + } else { + assert(dc->unplug != NULL); + if (dc->unplug(dev) < 0) { /* legacy handler */ + error_set(errp, QERR_UNDEFINED_ERROR); + } } } @@ -663,6 +673,11 @@ static void device_set_realized(Object *obj, bool value, Error **err) DeviceClass *dc = DEVICE_GET_CLASS(dev); Error *local_err = NULL; + if (dev->hotplugged && !dc->hotpluggable) { + error_set(err, QERR_DEVICE_NO_HOTPLUG, object_get_typename(obj)); + return; + } + if (value && !dev->realized) { if (!obj->parent && local_err == NULL) { static int unattached_count; @@ -678,6 +693,12 @@ static void device_set_realized(Object *obj, bool value, Error **err) dc->realize(dev, &local_err); } + if (dev->parent_bus && dev->parent_bus->hotplug_handler && + local_err == NULL) { + hotplug_handler_plug(dev->parent_bus->hotplug_handler, + dev, &local_err); + } + if (qdev_get_vmsd(dev) && local_err == NULL) { vmstate_register_with_alias_id(dev, -1, qdev_get_vmsd(dev), dev, dev->instance_id_alias, @@ -703,6 +724,14 @@ static void device_set_realized(Object *obj, bool value, Error **err) dev->realized = value; } +static bool device_get_hotpluggable(Object *obj, Error **err) +{ + DeviceClass *dc = DEVICE_GET_CLASS(obj); + DeviceState *dev = DEVICE(obj); + + return dc->hotpluggable && dev->parent_bus->allow_hotplug; +} + static void device_initfn(Object *obj) { DeviceState *dev = DEVICE(obj); @@ -719,6 +748,8 @@ static void device_initfn(Object *obj) object_property_add_bool(obj, "realized", device_get_realized, device_set_realized, NULL); + object_property_add_bool(obj, "hotpluggable", + device_get_hotpluggable, NULL, NULL); class = object_get_class(OBJECT(dev)); do { @@ -755,6 +786,14 @@ static void device_class_base_init(ObjectClass *class, void *data) * so do not propagate them to the subclasses. */ klass->props = NULL; + + /* by default all devices were considered as hotpluggable, + * so with intent to check it in generic qdev_unplug() / + * device_set_realized() functions make every device + * hotpluggable. Devices that shouldn't be hotpluggable, + * should override it in their class_init() + */ + klass->hotpluggable = true; } static void device_unparent(Object *obj) @@ -840,6 +879,9 @@ static void qbus_initfn(Object *obj) BusState *bus = BUS(obj); QTAILQ_INIT(&bus->children); + object_property_add_link(obj, QDEV_HOTPLUG_HANDLER_PROPERTY, + TYPE_HOTPLUG_HANDLER, + (Object **)&bus->hotplug_handler, NULL); } static char *default_bus_get_fw_dev_path(DeviceState *dev) diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c index e4c345fa82..3a8fc0bf8e 100644 --- a/hw/display/cirrus_vga.c +++ b/hw/display/cirrus_vga.c @@ -2996,7 +2996,6 @@ static void cirrus_vga_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - k->no_hotplug = 1; k->init = pci_cirrus_vga_initfn; k->romfile = VGABIOS_CIRRUS_FILENAME; k->vendor_id = PCI_VENDOR_ID_CIRRUS; @@ -3006,6 +3005,7 @@ static void cirrus_vga_class_init(ObjectClass *klass, void *data) dc->desc = "Cirrus CLGD 54xx VGA"; dc->vmsd = &vmstate_pci_cirrus_vga; dc->props = pci_vga_cirrus_properties; + dc->hotpluggable = false; } static const TypeInfo cirrus_vga_info = { diff --git a/hw/display/qxl.c b/hw/display/qxl.c index 334c2719f8..1471cc093b 100644 --- a/hw/display/qxl.c +++ b/hw/display/qxl.c @@ -2303,7 +2303,6 @@ static void qxl_primary_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - k->no_hotplug = 1; k->init = qxl_init_primary; k->romfile = "vgabios-qxl.bin"; k->vendor_id = REDHAT_PCI_VENDOR_ID; @@ -2314,6 +2313,7 @@ static void qxl_primary_class_init(ObjectClass *klass, void *data) dc->reset = qxl_reset_handler; dc->vmsd = &qxl_vmstate; dc->props = qxl_properties; + dc->hotpluggable = false; } static const TypeInfo qxl_primary_info = { diff --git a/hw/display/vga-pci.c b/hw/display/vga-pci.c index b3a45c81da..f74fc43aa6 100644 --- a/hw/display/vga-pci.c +++ b/hw/display/vga-pci.c @@ -190,7 +190,6 @@ static void vga_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - k->no_hotplug = 1; k->init = pci_std_vga_initfn; k->romfile = "vgabios-stdvga.bin"; k->vendor_id = PCI_VENDOR_ID_QEMU; @@ -198,6 +197,7 @@ static void vga_class_init(ObjectClass *klass, void *data) k->class_id = PCI_CLASS_DISPLAY_VGA; dc->vmsd = &vmstate_vga_pci; dc->props = vga_pci_properties; + dc->hotpluggable = false; set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories); } diff --git a/hw/display/vmware_vga.c b/hw/display/vmware_vga.c index aba292ccde..334e71856e 100644 --- a/hw/display/vmware_vga.c +++ b/hw/display/vmware_vga.c @@ -1296,7 +1296,6 @@ static void vmsvga_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - k->no_hotplug = 1; k->init = pci_vmsvga_initfn; k->romfile = "vgabios-vmware.bin"; k->vendor_id = PCI_VENDOR_ID_VMWARE; @@ -1307,6 +1306,7 @@ static void vmsvga_class_init(ObjectClass *klass, void *data) dc->reset = vmsvga_reset; dc->vmsd = &vmstate_vmware_vga; dc->props = vga_vmware_properties; + dc->hotpluggable = false; set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories); } diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 50e83f3b46..b1a7ebb8e3 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -768,6 +768,7 @@ static void build_pci_bus_end(PCIBus *bus, void *bus_state) memset(slot_hotplug_enable, 0xff, sizeof slot_hotplug_enable); for (i = 0; i < ARRAY_SIZE(bus->devices); ++i) { + DeviceClass *dc; PCIDeviceClass *pc; PCIDevice *pdev = bus->devices[i]; @@ -776,8 +777,9 @@ static void build_pci_bus_end(PCIBus *bus, void *bus_state) } pc = PCI_DEVICE_GET_CLASS(pdev); + dc = DEVICE_GET_CLASS(pdev); - if (pc->no_hotplug || pc->is_bridge) { + if (!dc->hotpluggable || pc->is_bridge) { int slot = PCI_SLOT(i); clear_bit(slot, slot_hotplug_enable); diff --git a/hw/i386/acpi-dsdt-hpet.dsl b/hw/i386/acpi-dsdt-hpet.dsl index dfde174317..44961b87a1 100644 --- a/hw/i386/acpi-dsdt-hpet.dsl +++ b/hw/i386/acpi-dsdt-hpet.dsl @@ -39,9 +39,6 @@ Scope(\_SB) { Return (0x0F) } Name(_CRS, ResourceTemplate() { -#if 0 /* This makes WinXP BSOD for not yet figured reasons. */ - IRQNoFlags() {2, 8} -#endif Memory32Fixed(ReadOnly, 0xFED00000, // Address Base 0x00000400, // Address Length diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 348b15f267..e715a3312d 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -835,8 +835,8 @@ static void load_linux(FWCfgState *fw_cfg, initrd_size = get_image_size(initrd_filename); if (initrd_size < 0) { - fprintf(stderr, "qemu: error reading initrd %s\n", - initrd_filename); + fprintf(stderr, "qemu: error reading initrd %s: %s\n", + initrd_filename, strerror(errno)); exit(1); } diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index 3639a6d099..d5dc1ef336 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -793,6 +793,17 @@ static QEMUMachine xenfv_machine = { .max_cpus = HVM_MAX_VCPUS, .default_machine_opts = "accel=xen", .hot_add_cpu = pc_hot_add_cpu, + .compat_props = (GlobalProperty[]) { + /* xenfv has no fwcfg and so does not load acpi from QEMU. + * as such new acpi features don't work. + */ + { + .driver = "PIIX4_PM", + .property = "acpi-pci-hotplug-with-bridge-support", + .value = "off", + }, + { /* end of list */ } + }, }; #endif diff --git a/hw/ide/piix.c b/hw/ide/piix.c index 9b5960b44e..0eda301ba9 100644 --- a/hw/ide/piix.c +++ b/hw/ide/piix.c @@ -241,13 +241,13 @@ static void piix3_ide_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - k->no_hotplug = 1; k->init = pci_piix_ide_initfn; k->exit = pci_piix_ide_exitfn; k->vendor_id = PCI_VENDOR_ID_INTEL; k->device_id = PCI_DEVICE_ID_INTEL_82371SB_1; k->class_id = PCI_CLASS_STORAGE_IDE; set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); + dc->hotpluggable = false; } static const TypeInfo piix3_ide_info = { @@ -280,13 +280,13 @@ static void piix4_ide_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - k->no_hotplug = 1; k->init = pci_piix_ide_initfn; k->exit = pci_piix_ide_exitfn; k->vendor_id = PCI_VENDOR_ID_INTEL; k->device_id = PCI_DEVICE_ID_INTEL_82371AB; k->class_id = PCI_CLASS_STORAGE_IDE; set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); + dc->hotpluggable = false; } static const TypeInfo piix4_ide_info = { diff --git a/hw/isa/piix4.c b/hw/isa/piix4.c index def6fe3a0f..492cd22fcf 100644 --- a/hw/isa/piix4.c +++ b/hw/isa/piix4.c @@ -107,7 +107,6 @@ static void piix4_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - k->no_hotplug = 1; k->init = piix4_initfn; k->vendor_id = PCI_VENDOR_ID_INTEL; k->device_id = PCI_DEVICE_ID_INTEL_82371AB_0; @@ -119,6 +118,7 @@ static void piix4_class_init(ObjectClass *klass, void *data) * e.g. by mips_malta_init() */ dc->cannot_instantiate_with_device_add_yet = true; + dc->hotpluggable = false; } static const TypeInfo piix4_info = { diff --git a/hw/pci-bridge/pci_bridge_dev.c b/hw/pci-bridge/pci_bridge_dev.c index 440e187c46..e68145c52f 100644 --- a/hw/pci-bridge/pci_bridge_dev.c +++ b/hw/pci-bridge/pci_bridge_dev.c @@ -26,6 +26,7 @@ #include "hw/pci/slotid_cap.h" #include "exec/memory.h" #include "hw/pci/pci_bus.h" +#include "hw/hotplug.h" #define TYPE_PCI_BRIDGE_DEV "pci-bridge" #define PCI_BRIDGE_DEV(obj) \ @@ -136,6 +137,8 @@ static void pci_bridge_dev_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass); + k->init = pci_bridge_dev_initfn; k->exit = pci_bridge_dev_exitfn; k->config_write = pci_bridge_dev_write_config; @@ -148,6 +151,8 @@ static void pci_bridge_dev_class_init(ObjectClass *klass, void *data) dc->props = pci_bridge_dev_properties; dc->vmsd = &pci_bridge_dev_vmstate; set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); + hc->plug = shpc_device_hotplug_cb; + hc->unplug = shpc_device_hot_unplug_cb; } static const TypeInfo pci_bridge_dev_info = { @@ -155,6 +160,10 @@ static const TypeInfo pci_bridge_dev_info = { .parent = TYPE_PCI_BRIDGE, .instance_size = sizeof(PCIBridgeDev), .class_init = pci_bridge_dev_class_init, + .interfaces = (InterfaceInfo[]) { + { TYPE_HOTPLUG_HANDLER }, + { } + } }; static void pci_bridge_dev_register(void) diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c index e89d5c1dfa..ffdc853a62 100644 --- a/hw/pci-host/piix.c +++ b/hw/pci-host/piix.c @@ -628,7 +628,7 @@ static void piix3_class_init(ObjectClass *klass, void *data) dc->desc = "ISA bridge"; dc->vmsd = &vmstate_piix3; - k->no_hotplug = 1; + dc->hotpluggable = false; k->init = piix3_initfn; k->config_write = piix3_write_config; k->vendor_id = PCI_VENDOR_ID_INTEL; @@ -656,7 +656,7 @@ static void piix3_xen_class_init(ObjectClass *klass, void *data) dc->desc = "ISA bridge"; dc->vmsd = &vmstate_piix3; - k->no_hotplug = 1; + dc->hotpluggable = false; k->init = piix3_initfn; k->config_write = piix3_write_config_xen; k->vendor_id = PCI_VENDOR_ID_INTEL; @@ -682,7 +682,6 @@ static void i440fx_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - k->no_hotplug = 1; k->init = i440fx_initfn; k->config_write = i440fx_write_config; k->vendor_id = PCI_VENDOR_ID_INTEL; @@ -696,6 +695,7 @@ static void i440fx_class_init(ObjectClass *klass, void *data) * host-facing part, which can't be device_add'ed, yet. */ dc->cannot_instantiate_with_device_add_yet = true; + dc->hotpluggable = false; } static const TypeInfo i440fx_info = { diff --git a/hw/pci/pci-hotplug-old.c b/hw/pci/pci-hotplug-old.c index 8dbc3c1cab..cf2caebfb1 100644 --- a/hw/pci/pci-hotplug-old.c +++ b/hw/pci/pci-hotplug-old.c @@ -90,7 +90,7 @@ static PCIDevice *qemu_pci_hot_add_nic(Monitor *mon, qemu_opt_set(opts, "type", "nic"); ret = net_client_init(opts, 0, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { qerror_report_err(local_err); error_free(local_err); return NULL; @@ -322,7 +322,7 @@ static int pci_device_hot_remove(Monitor *mon, const char *pci_addr) } qdev_unplug(&d->qdev, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { monitor_printf(mon, "%s\n", error_get_pretty(local_err)); error_free(local_err); return -1; diff --git a/hw/pci/pci.c b/hw/pci/pci.c index 1221f32847..4e0701df38 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -35,6 +35,7 @@ #include "hw/pci/msi.h" #include "hw/pci/msix.h" #include "exec/address-spaces.h" +#include "hw/hotplug.h" //#define DEBUG_PCI #ifdef DEBUG_PCI @@ -346,13 +347,6 @@ void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq, bus->irq_count = g_malloc0(nirq * sizeof(bus->irq_count[0])); } -void pci_bus_hotplug(PCIBus *bus, pci_hotplug_fn hotplug, DeviceState *qdev) -{ - bus->qbus.allow_hotplug = 1; - bus->hotplug = hotplug; - bus->hotplug_qdev = qdev; -} - PCIBus *pci_register_bus(DeviceState *parent, const char *name, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq, void *irq_opaque, @@ -1761,11 +1755,7 @@ static int pci_qdev_init(DeviceState *qdev) pci_dev->devfn); if (pci_dev == NULL) return -1; - if (qdev->hotplugged && pc->no_hotplug) { - qerror_report(QERR_DEVICE_NO_HOTPLUG, object_get_typename(OBJECT(pci_dev))); - do_pci_unregister_device(pci_dev); - return -1; - } + if (pc->init) { rc = pc->init(pci_dev); if (rc != 0) { @@ -1782,34 +1772,9 @@ static int pci_qdev_init(DeviceState *qdev) } pci_add_option_rom(pci_dev, is_default_rom); - if (bus->hotplug) { - /* Let buses differentiate between hotplug and when device is - * enabled during qemu machine creation. */ - rc = bus->hotplug(bus->hotplug_qdev, pci_dev, - qdev->hotplugged ? PCI_HOTPLUG_ENABLED: - PCI_COLDPLUG_ENABLED); - if (rc != 0) { - int r = pci_unregister_device(&pci_dev->qdev); - assert(!r); - return rc; - } - } return 0; } -static int pci_unplug_device(DeviceState *qdev) -{ - PCIDevice *dev = PCI_DEVICE(qdev); - PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev); - - if (pc->no_hotplug) { - qerror_report(QERR_DEVICE_NO_HOTPLUG, object_get_typename(OBJECT(dev))); - return -1; - } - return dev->bus->hotplug(dev->bus->hotplug_qdev, dev, - PCI_HOTPLUG_DISABLED); -} - PCIDevice *pci_create_multifunction(PCIBus *bus, int devfn, bool multifunction, const char *name) { @@ -2280,7 +2245,6 @@ static void pci_device_class_init(ObjectClass *klass, void *data) { DeviceClass *k = DEVICE_CLASS(klass); k->init = pci_qdev_init; - k->unplug = pci_unplug_device; k->exit = pci_unregister_device; k->bus_type = TYPE_PCI_BUS; k->props = pci_props; diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c index ca60cf2177..8ecd11eca2 100644 --- a/hw/pci/pcie.c +++ b/hw/pci/pcie.c @@ -26,6 +26,7 @@ #include "hw/pci/pci_bus.h" #include "hw/pci/pcie_regs.h" #include "qemu/range.h" +#include "qapi/qmp/qerror.h" //#define DEBUG_PCIE #ifdef DEBUG_PCIE @@ -216,28 +217,20 @@ static void pcie_cap_slot_event(PCIDevice *dev, PCIExpressHotPlugEvent event) hotplug_event_notify(dev); } -static int pcie_cap_slot_hotplug(DeviceState *qdev, - PCIDevice *pci_dev, PCIHotplugState state) +static void pcie_cap_slot_hotplug_common(PCIDevice *hotplug_dev, + DeviceState *dev, + uint8_t **exp_cap, Error **errp) { - PCIDevice *d = PCI_DEVICE(qdev); - uint8_t *exp_cap = d->config + d->exp.exp_cap; - uint16_t sltsta = pci_get_word(exp_cap + PCI_EXP_SLTSTA); - - /* Don't send event when device is enabled during qemu machine creation: - * it is present on boot, no hotplug event is necessary. We do send an - * event when the device is disabled later. */ - if (state == PCI_COLDPLUG_ENABLED) { - pci_word_test_and_set_mask(exp_cap + PCI_EXP_SLTSTA, - PCI_EXP_SLTSTA_PDS); - return 0; - } + PCIDevice *pci_dev = PCI_DEVICE(dev); + *exp_cap = hotplug_dev->config + hotplug_dev->exp.exp_cap; + uint16_t sltsta = pci_get_word(*exp_cap + PCI_EXP_SLTSTA); PCIE_DEV_PRINTF(pci_dev, "hotplug state: %d\n", state); if (sltsta & PCI_EXP_SLTSTA_EIS) { /* the slot is electromechanically locked. * This error is propagated up to qdev and then to HMP/QMP. */ - return -EBUSY; + error_setg_errno(errp, -EBUSY, "slot is electromechanically locked"); } /* TODO: multifunction hot-plug. @@ -245,18 +238,40 @@ static int pcie_cap_slot_hotplug(DeviceState *qdev, * hot plugged/unplugged. */ assert(PCI_FUNC(pci_dev->devfn) == 0); +} - if (state == PCI_HOTPLUG_ENABLED) { +void pcie_cap_slot_hotplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, + Error **errp) +{ + uint8_t *exp_cap; + + pcie_cap_slot_hotplug_common(PCI_DEVICE(hotplug_dev), dev, &exp_cap, errp); + + /* Don't send event when device is enabled during qemu machine creation: + * it is present on boot, no hotplug event is necessary. We do send an + * event when the device is disabled later. */ + if (!dev->hotplugged) { pci_word_test_and_set_mask(exp_cap + PCI_EXP_SLTSTA, PCI_EXP_SLTSTA_PDS); - pcie_cap_slot_event(d, PCI_EXP_HP_EV_PDC); - } else { - object_unparent(OBJECT(pci_dev)); - pci_word_test_and_clear_mask(exp_cap + PCI_EXP_SLTSTA, - PCI_EXP_SLTSTA_PDS); - pcie_cap_slot_event(d, PCI_EXP_HP_EV_PDC); + return; } - return 0; + + pci_word_test_and_set_mask(exp_cap + PCI_EXP_SLTSTA, + PCI_EXP_SLTSTA_PDS); + pcie_cap_slot_event(PCI_DEVICE(hotplug_dev), PCI_EXP_HP_EV_PDC); +} + +void pcie_cap_slot_hot_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, + Error **errp) +{ + uint8_t *exp_cap; + + pcie_cap_slot_hotplug_common(PCI_DEVICE(hotplug_dev), dev, &exp_cap, errp); + + object_unparent(OBJECT(dev)); + pci_word_test_and_clear_mask(exp_cap + PCI_EXP_SLTSTA, + PCI_EXP_SLTSTA_PDS); + pcie_cap_slot_event(PCI_DEVICE(hotplug_dev), PCI_EXP_HP_EV_PDC); } /* pci express slot for pci express root/downstream port @@ -305,8 +320,8 @@ void pcie_cap_slot_init(PCIDevice *dev, uint16_t slot) dev->exp.hpev_notified = false; - pci_bus_hotplug(pci_bridge_get_sec_bus(PCI_BRIDGE(dev)), - pcie_cap_slot_hotplug, &dev->qdev); + qbus_set_hotplug_handler(BUS(pci_bridge_get_sec_bus(PCI_BRIDGE(dev))), + DEVICE(dev), NULL); } void pcie_cap_slot_reset(PCIDevice *dev) diff --git a/hw/pci/pcie_port.c b/hw/pci/pcie_port.c index 2adb0300f4..fa24877955 100644 --- a/hw/pci/pcie_port.c +++ b/hw/pci/pcie_port.c @@ -19,6 +19,7 @@ */ #include "hw/pci/pcie_port.h" +#include "hw/hotplug.h" void pcie_port_init_reg(PCIDevice *d) { @@ -149,8 +150,11 @@ static Property pcie_slot_props[] = { static void pcie_slot_class_init(ObjectClass *oc, void *data) { DeviceClass *dc = DEVICE_CLASS(oc); + HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc); dc->props = pcie_slot_props; + hc->plug = pcie_cap_slot_hotplug_cb; + hc->unplug = pcie_cap_slot_hot_unplug_cb; } static const TypeInfo pcie_slot_type_info = { @@ -159,6 +163,10 @@ static const TypeInfo pcie_slot_type_info = { .instance_size = sizeof(PCIESlot), .abstract = true, .class_init = pcie_slot_class_init, + .interfaces = (InterfaceInfo[]) { + { TYPE_HOTPLUG_HANDLER }, + { } + } }; static void pcie_port_register_types(void) diff --git a/hw/pci/shpc.c b/hw/pci/shpc.c index 576244b9f6..180faa7adb 100644 --- a/hw/pci/shpc.c +++ b/hw/pci/shpc.c @@ -7,6 +7,7 @@ #include "hw/pci/pci.h" #include "hw/pci/pci_bus.h" #include "hw/pci/msi.h" +#include "qapi/qmp/qerror.h" /* TODO: model power only and disabled slot states. */ /* TODO: handle SERR and wakeups */ @@ -490,65 +491,93 @@ static const MemoryRegionOps shpc_mmio_ops = { .max_access_size = 4, }, }; - -static int shpc_device_hotplug(DeviceState *qdev, PCIDevice *affected_dev, - PCIHotplugState hotplug_state) +static void shpc_device_hotplug_common(PCIDevice *affected_dev, int *slot, + SHPCDevice *shpc, Error **errp) { int pci_slot = PCI_SLOT(affected_dev->devfn); - uint8_t state; - uint8_t led; - PCIDevice *d = DO_UPCAST(PCIDevice, qdev, qdev); - SHPCDevice *shpc = d->shpc; - int slot = SHPC_PCI_TO_IDX(pci_slot); - if (pci_slot < SHPC_IDX_TO_PCI(0) || slot >= shpc->nslots) { - error_report("Unsupported PCI slot %d for standard hotplug " - "controller. Valid slots are between %d and %d.", - pci_slot, SHPC_IDX_TO_PCI(0), - SHPC_IDX_TO_PCI(shpc->nslots) - 1); - return -1; + *slot = SHPC_PCI_TO_IDX(pci_slot); + + if (pci_slot < SHPC_IDX_TO_PCI(0) || *slot >= shpc->nslots) { + error_setg(errp, "Unsupported PCI slot %d for standard hotplug " + "controller. Valid slots are between %d and %d.", + pci_slot, SHPC_IDX_TO_PCI(0), + SHPC_IDX_TO_PCI(shpc->nslots) - 1); + return; + } +} + +void shpc_device_hotplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, + Error **errp) +{ + Error *local_err = NULL; + PCIDevice *pci_hotplug_dev = PCI_DEVICE(hotplug_dev); + SHPCDevice *shpc = pci_hotplug_dev->shpc; + int slot; + + shpc_device_hotplug_common(PCI_DEVICE(dev), &slot, shpc, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; } + /* Don't send event when device is enabled during qemu machine creation: * it is present on boot, no hotplug event is necessary. We do send an * event when the device is disabled later. */ - if (hotplug_state == PCI_COLDPLUG_ENABLED) { + if (!dev->hotplugged) { shpc_set_status(shpc, slot, 0, SHPC_SLOT_STATUS_MRL_OPEN); shpc_set_status(shpc, slot, SHPC_SLOT_STATUS_PRSNT_7_5W, SHPC_SLOT_STATUS_PRSNT_MASK); - return 0; + return; } - if (hotplug_state == PCI_HOTPLUG_DISABLED) { - shpc->config[SHPC_SLOT_EVENT_LATCH(slot)] |= SHPC_SLOT_EVENT_BUTTON; - state = shpc_get_status(shpc, slot, SHPC_SLOT_STATE_MASK); - led = shpc_get_status(shpc, slot, SHPC_SLOT_PWR_LED_MASK); - if (state == SHPC_STATE_DISABLED && led == SHPC_LED_OFF) { - shpc_free_devices_in_slot(shpc, slot); - shpc_set_status(shpc, slot, 1, SHPC_SLOT_STATUS_MRL_OPEN); - shpc_set_status(shpc, slot, SHPC_SLOT_STATUS_PRSNT_EMPTY, - SHPC_SLOT_STATUS_PRSNT_MASK); - shpc->config[SHPC_SLOT_EVENT_LATCH(slot)] |= - SHPC_SLOT_EVENT_MRL | - SHPC_SLOT_EVENT_PRESENCE; - } + + /* This could be a cancellation of the previous removal. + * We check MRL state to figure out. */ + if (shpc_get_status(shpc, slot, SHPC_SLOT_STATUS_MRL_OPEN)) { + shpc_set_status(shpc, slot, 0, SHPC_SLOT_STATUS_MRL_OPEN); + shpc_set_status(shpc, slot, SHPC_SLOT_STATUS_PRSNT_7_5W, + SHPC_SLOT_STATUS_PRSNT_MASK); + shpc->config[SHPC_SLOT_EVENT_LATCH(slot)] |= + SHPC_SLOT_EVENT_BUTTON | + SHPC_SLOT_EVENT_MRL | + SHPC_SLOT_EVENT_PRESENCE; } else { - /* This could be a cancellation of the previous removal. - * We check MRL state to figure out. */ - if (shpc_get_status(shpc, slot, SHPC_SLOT_STATUS_MRL_OPEN)) { - shpc_set_status(shpc, slot, 0, SHPC_SLOT_STATUS_MRL_OPEN); - shpc_set_status(shpc, slot, SHPC_SLOT_STATUS_PRSNT_7_5W, - SHPC_SLOT_STATUS_PRSNT_MASK); - shpc->config[SHPC_SLOT_EVENT_LATCH(slot)] |= - SHPC_SLOT_EVENT_BUTTON | - SHPC_SLOT_EVENT_MRL | - SHPC_SLOT_EVENT_PRESENCE; - } else { - /* Press attention button to cancel removal */ - shpc->config[SHPC_SLOT_EVENT_LATCH(slot)] |= - SHPC_SLOT_EVENT_BUTTON; - } + /* Press attention button to cancel removal */ + shpc->config[SHPC_SLOT_EVENT_LATCH(slot)] |= + SHPC_SLOT_EVENT_BUTTON; } shpc_set_status(shpc, slot, 0, SHPC_SLOT_STATUS_66); - shpc_interrupt_update(d); - return 0; + shpc_interrupt_update(pci_hotplug_dev); +} + +void shpc_device_hot_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, + Error **errp) +{ + Error *local_err = NULL; + PCIDevice *pci_hotplug_dev = PCI_DEVICE(hotplug_dev); + SHPCDevice *shpc = pci_hotplug_dev->shpc; + uint8_t state; + uint8_t led; + int slot; + + shpc_device_hotplug_common(PCI_DEVICE(dev), &slot, shpc, errp); + if (local_err) { + return; + } + + shpc->config[SHPC_SLOT_EVENT_LATCH(slot)] |= SHPC_SLOT_EVENT_BUTTON; + state = shpc_get_status(shpc, slot, SHPC_SLOT_STATE_MASK); + led = shpc_get_status(shpc, slot, SHPC_SLOT_PWR_LED_MASK); + if (state == SHPC_STATE_DISABLED && led == SHPC_LED_OFF) { + shpc_free_devices_in_slot(shpc, slot); + shpc_set_status(shpc, slot, 1, SHPC_SLOT_STATUS_MRL_OPEN); + shpc_set_status(shpc, slot, SHPC_SLOT_STATUS_PRSNT_EMPTY, + SHPC_SLOT_STATUS_PRSNT_MASK); + shpc->config[SHPC_SLOT_EVENT_LATCH(slot)] |= + SHPC_SLOT_EVENT_MRL | + SHPC_SLOT_EVENT_PRESENCE; + } + shpc_set_status(shpc, slot, 0, SHPC_SLOT_STATUS_66); + shpc_interrupt_update(pci_hotplug_dev); } /* Initialize the SHPC structure in bridge's BAR. */ @@ -616,7 +645,8 @@ int shpc_init(PCIDevice *d, PCIBus *sec_bus, MemoryRegion *bar, unsigned offset) d, "shpc-mmio", SHPC_SIZEOF(d)); shpc_cap_update_dword(d); memory_region_add_subregion(bar, offset, &shpc->mmio); - pci_bus_hotplug(sec_bus, shpc_device_hotplug, &d->qdev); + + qbus_set_hotplug_handler(BUS(sec_bus), DEVICE(d), NULL); d->cap_present |= QEMU_PCI_CAP_SHPC; return 0; diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c index 027a6fa369..843e697bfe 100644 --- a/hw/sd/sdhci.c +++ b/hw/sd/sdhci.c @@ -26,7 +26,6 @@ #include "sysemu/blockdev.h" #include "sysemu/dma.h" #include "qemu/timer.h" -#include "block/block_int.h" #include "qemu/bitops.h" #include "sdhci.h" diff --git a/hw/sparc/leon3.c b/hw/sparc/leon3.c index c583c3d0c5..c16e9e4c81 100644 --- a/hw/sparc/leon3.c +++ b/hw/sparc/leon3.c @@ -45,6 +45,7 @@ typedef struct ResetData { SPARCCPU *cpu; uint32_t entry; /* save kernel entry in case of reset */ + target_ulong sp; /* initial stack pointer */ } ResetData; static void main_cpu_reset(void *opaque) @@ -58,6 +59,7 @@ static void main_cpu_reset(void *opaque) cpu->halted = 0; env->pc = s->entry; env->npc = s->entry + 4; + env->regbase[6] = s->sp; } void leon3_irq_ack(void *irq_manager, int intno) @@ -133,6 +135,7 @@ static void leon3_generic_hw_init(QEMUMachineInitArgs *args) /* Reset data */ reset_info = g_malloc0(sizeof(ResetData)); reset_info->cpu = cpu; + reset_info->sp = 0x40000000 + ram_size; qemu_register_reset(main_cpu_reset, reset_info); /* Allocate IRQ manager */ diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c index 4c532b7d6a..f0c253647e 100644 --- a/hw/usb/dev-network.c +++ b/hw/usb/dev-network.c @@ -1391,7 +1391,7 @@ static USBDevice *usb_net_init(USBBus *bus, const char *cmdline) qemu_opt_set(opts, "model", "usb"); idx = net_client_init(opts, 0, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { qerror_report_err(local_err); error_free(local_err); return NULL; diff --git a/hw/usb/hcd-ehci-pci.c b/hw/usb/hcd-ehci-pci.c index 0c985942f9..484a9bd059 100644 --- a/hw/usb/hcd-ehci-pci.c +++ b/hw/usb/hcd-ehci-pci.c @@ -123,7 +123,7 @@ static void ehci_class_init(ObjectClass *klass, void *data) k->init = usb_ehci_pci_initfn; k->class_id = PCI_CLASS_SERIAL_USB; k->config_write = usb_ehci_pci_write_config; - k->no_hotplug = 1; + dc->hotpluggable = false; dc->vmsd = &vmstate_ehci_pci; dc->props = ehci_pci_properties; } diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c index e38cdebfec..3d35058b14 100644 --- a/hw/usb/hcd-ohci.c +++ b/hw/usb/hcd-ohci.c @@ -1993,10 +1993,10 @@ static void ohci_pci_class_init(ObjectClass *klass, void *data) k->vendor_id = PCI_VENDOR_ID_APPLE; k->device_id = PCI_DEVICE_ID_APPLE_IPID_USB; k->class_id = PCI_CLASS_SERIAL_USB; - k->no_hotplug = 1; set_bit(DEVICE_CATEGORY_USB, dc->categories); dc->desc = "Apple USB Controller"; dc->props = ohci_pci_properties; + dc->hotpluggable = false; } static const TypeInfo ohci_pci_info = { diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index 238d1d2b5f..ad814b58d4 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -1318,7 +1318,7 @@ static void uhci_class_init(ObjectClass *klass, void *data) k->device_id = info->device_id; k->revision = info->revision; k->class_id = PCI_CLASS_SERIAL_USB; - k->no_hotplug = 1; + dc->hotpluggable = false; dc->vmsd = &vmstate_uhci; dc->props = uhci_properties; set_bit(DEVICE_CATEGORY_USB, dc->categories); diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index bafe08590b..0fa814ee09 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -3798,6 +3798,7 @@ static void xhci_class_init(ObjectClass *klass, void *data) dc->vmsd = &vmstate_xhci; dc->props = xhci_properties; dc->reset = xhci_reset; + dc->hotpluggable = false; set_bit(DEVICE_CATEGORY_USB, dc->categories); k->init = usb_xhci_initfn; k->vendor_id = PCI_VENDOR_ID_NEC; @@ -3805,7 +3806,6 @@ static void xhci_class_init(ObjectClass *klass, void *data) k->class_id = PCI_CLASS_SERIAL_USB; k->revision = 0x03; k->is_express = 1; - k->no_hotplug = 1; } static const TypeInfo xhci_info = { diff --git a/include/hw/acpi/acpi.h b/include/hw/acpi/acpi.h index 3e53297a99..a9fae9d5c5 100644 --- a/include/hw/acpi/acpi.h +++ b/include/hw/acpi/acpi.h @@ -24,6 +24,7 @@ #include "qemu/notify.h" #include "qemu/option.h" #include "exec/memory.h" +#include "hw/irq.h" /* from linux include/acpi/actype.h */ /* Default ACPI register widths */ diff --git a/include/hw/acpi/pcihp.h b/include/hw/acpi/pcihp.h index 6230e60954..9323838319 100644 --- a/include/hw/acpi/pcihp.h +++ b/include/hw/acpi/pcihp.h @@ -29,31 +29,34 @@ #include <inttypes.h> #include <qemu/typedefs.h> -#include "hw/pci/pci.h" /* for PCIHotplugState */ +#include "hw/acpi/acpi.h" +#include "migration/vmstate.h" typedef struct AcpiPciHpPciStatus { - uint32_t up; /* deprecated, maintained for migration compatibility */ + uint32_t up; uint32_t down; uint32_t hotplug_enable; - uint32_t device_present; } AcpiPciHpPciStatus; #define ACPI_PCIHP_PROP_BSEL "acpi-pcihp-bsel" #define ACPI_PCIHP_MAX_HOTPLUG_BUS 256 +#define ACPI_PCIHP_BSEL_DEFAULT 0x0 typedef struct AcpiPciHpState { AcpiPciHpPciStatus acpi_pcihp_pci_status[ACPI_PCIHP_MAX_HOTPLUG_BUS]; uint32_t hotplug_select; PCIBus *root; MemoryRegion io; + bool legacy_piix; } AcpiPciHpState; void acpi_pcihp_init(AcpiPciHpState *, PCIBus *root, - MemoryRegion *address_space_io); + MemoryRegion *address_space_io, bool bridges_enabled); -/* Invoke on device hotplug */ -int acpi_pcihp_device_hotplug(AcpiPciHpState *, PCIDevice *, - PCIHotplugState state); +void acpi_pcihp_device_plug_cb(ACPIREGS *ar, qemu_irq irq, AcpiPciHpState *s, + DeviceState *dev, Error **errp); +void acpi_pcihp_device_unplug_cb(ACPIREGS *ar, qemu_irq irq, AcpiPciHpState *s, + DeviceState *dev, Error **errp); /* Called on reset */ void acpi_pcihp_reset(AcpiPciHpState *s); diff --git a/include/hw/hotplug.h b/include/hw/hotplug.h new file mode 100644 index 0000000000..a6533cb0b1 --- /dev/null +++ b/include/hw/hotplug.h @@ -0,0 +1,78 @@ +/* + * Hotplug handler interface. + * + * Copyright (c) 2014 Red Hat Inc. + * + * Authors: + * Igor Mammedov <imammedo@redhat.com>, + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ +#ifndef HOTPLUG_H +#define HOTPLUG_H + +#include "qom/object.h" +#include "qemu/typedefs.h" + +#define TYPE_HOTPLUG_HANDLER "hotplug-handler" + +#define HOTPLUG_HANDLER_CLASS(klass) \ + OBJECT_CLASS_CHECK(HotplugHandlerClass, (klass), TYPE_HOTPLUG_HANDLER) +#define HOTPLUG_HANDLER_GET_CLASS(obj) \ + OBJECT_GET_CLASS(HotplugHandlerClass, (obj), TYPE_HOTPLUG_HANDLER) +#define HOTPLUG_HANDLER(obj) \ + INTERFACE_CHECK(HotplugHandler, (obj), TYPE_HOTPLUG_HANDLER) + + +typedef struct HotplugHandler { + /* <private> */ + Object Parent; +} HotplugHandler; + +/** + * hotplug_fn: + * @plug_handler: a device performing plug/uplug action + * @plugged_dev: a device that has been (un)plugged + * @errp: returns an error if this function fails + */ +typedef void (*hotplug_fn)(HotplugHandler *plug_handler, + DeviceState *plugged_dev, Error **errp); + +/** + * HotplugDeviceClass: + * + * Interface to be implemented by a device performing + * hardware (un)plug functions. + * + * @parent: Opaque parent interface. + * @plug: plug callback. + * @unplug: unplug callback. + */ +typedef struct HotplugHandlerClass { + /* <private> */ + InterfaceClass parent; + + /* <public> */ + hotplug_fn plug; + hotplug_fn unplug; +} HotplugHandlerClass; + +/** + * hotplug_handler_plug: + * + * Call #HotplugHandlerClass.plug callback of @plug_handler. + */ +void hotplug_handler_plug(HotplugHandler *plug_handler, + DeviceState *plugged_dev, + Error **errp); + +/** + * hotplug_handler_unplug: + * + * Call #HotplugHandlerClass.unplug callback of @plug_handler. + */ +void hotplug_handler_unplug(HotplugHandler *plug_handler, + DeviceState *plugged_dev, + Error **errp); +#endif diff --git a/include/hw/loader.h b/include/hw/loader.h index 7a23d6bdc1..91b01224a3 100644 --- a/include/hw/loader.h +++ b/include/hw/loader.h @@ -4,6 +4,13 @@ #include "hw/nvram/fw_cfg.h" /* loader.c */ +/** + * get_image_size: retrieve size of an image file + * @filename: Path to the image file + * + * Returns the size of the image file on success, -1 otherwise. + * On error, errno is also set as appropriate. + */ int get_image_size(const char *filename); int load_image(const char *filename, uint8_t *addr); /* deprecated */ int load_image_targphys(const char *filename, hwaddr, diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index 52523467b6..693dd6b658 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -201,9 +201,6 @@ typedef struct PCIDeviceClass { /* pcie stuff */ int is_express; /* is this device pci express? */ - /* device isn't hot-pluggable */ - int no_hotplug; - /* rom bar */ const char *romfile; } PCIDeviceClass; @@ -330,15 +327,6 @@ typedef void (*pci_set_irq_fn)(void *opaque, int irq_num, int level); typedef int (*pci_map_irq_fn)(PCIDevice *pci_dev, int irq_num); typedef PCIINTxRoute (*pci_route_irq_fn)(void *opaque, int pin); -typedef enum { - PCI_HOTPLUG_DISABLED, - PCI_HOTPLUG_ENABLED, - PCI_COLDPLUG_ENABLED, -} PCIHotplugState; - -typedef int (*pci_hotplug_fn)(DeviceState *qdev, PCIDevice *pci_dev, - PCIHotplugState state); - #define TYPE_PCI_BUS "PCI" #define PCI_BUS(obj) OBJECT_CHECK(PCIBus, (obj), TYPE_PCI_BUS) #define TYPE_PCIE_BUS "PCIE" @@ -357,7 +345,6 @@ PCIBus *pci_bus_new(DeviceState *parent, const char *name, void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq, void *irq_opaque, int nirq); int pci_bus_get_irq_level(PCIBus *bus, int irq_num); -void pci_bus_hotplug(PCIBus *bus, pci_hotplug_fn hotplug, DeviceState *dev); /* 0 <= pin <= 3 0 = INTA, 1 = INTB, 2 = INTC, 3 = INTD */ int pci_swizzle_map_irq_fn(PCIDevice *pci_dev, int pin); PCIBus *pci_register_bus(DeviceState *parent, const char *name, diff --git a/include/hw/pci/pci_bus.h b/include/hw/pci/pci_bus.h index 9df17885ec..fabaeee86b 100644 --- a/include/hw/pci/pci_bus.h +++ b/include/hw/pci/pci_bus.h @@ -16,8 +16,6 @@ struct PCIBus { pci_set_irq_fn set_irq; pci_map_irq_fn map_irq; pci_route_irq_fn route_intx_to_irq; - pci_hotplug_fn hotplug; - DeviceState *hotplug_qdev; void *irq_opaque; PCIDevice *devices[PCI_SLOT_MAX * PCI_FUNC_MAX]; PCIDevice *parent_dev; diff --git a/include/hw/pci/pcie.h b/include/hw/pci/pcie.h index 1966169553..b0bf7e3ce1 100644 --- a/include/hw/pci/pcie.h +++ b/include/hw/pci/pcie.h @@ -25,6 +25,7 @@ #include "hw/pci/pci_regs.h" #include "hw/pci/pcie_regs.h" #include "hw/pci/pcie_aer.h" +#include "hw/hotplug.h" typedef enum { /* for attention and power indicator */ @@ -122,4 +123,8 @@ extern const VMStateDescription vmstate_pcie_device; .offset = vmstate_offset_value(_state, _field, PCIDevice), \ } +void pcie_cap_slot_hotplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, + Error **errp); +void pcie_cap_slot_hot_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, + Error **errp); #endif /* QEMU_PCIE_H */ diff --git a/include/hw/pci/shpc.h b/include/hw/pci/shpc.h index 467911a558..eef1a1ad6e 100644 --- a/include/hw/pci/shpc.h +++ b/include/hw/pci/shpc.h @@ -4,6 +4,8 @@ #include "qemu-common.h" #include "exec/memory.h" #include "migration/vmstate.h" +#include "qapi/error.h" +#include "hw/hotplug.h" struct SHPCDevice { /* Capability offset in device's config space */ @@ -41,6 +43,12 @@ int shpc_init(PCIDevice *dev, PCIBus *sec_bus, MemoryRegion *bar, unsigned off); void shpc_cleanup(PCIDevice *dev, MemoryRegion *bar); void shpc_cap_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int len); + +void shpc_device_hotplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, + Error **errp); +void shpc_device_hot_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, + Error **errp); + extern VMStateInfo shpc_vmstate_info; #define SHPC_VMSTATE(_field, _type) \ VMSTATE_BUFFER_UNSAFE_INFO(_field, _type, 0, shpc_vmstate_info, 0) diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h index d0cda38686..276b336c09 100644 --- a/include/hw/qdev-core.h +++ b/include/hw/qdev-core.h @@ -8,6 +8,7 @@ #include "qom/object.h" #include "hw/irq.h" #include "qapi/error.h" +#include "hw/hotplug.h" enum { DEV_NVECTORS_UNSPECIFIED = -1, @@ -49,6 +50,8 @@ struct VMStateDescription; * is changed to %true. Deprecated, new types inheriting directly from * TYPE_DEVICE should use @realize instead, new leaf types should consult * their respective parent type. + * @hotpluggable: indicates if #DeviceClass is hotpluggable, available + * as readonly "hotpluggable" property of #DeviceState instance * * # Realization # * Devices are constructed in two stages, @@ -109,6 +112,7 @@ typedef struct DeviceClass { * TODO remove once we're there */ bool cannot_instantiate_with_device_add_yet; + bool hotpluggable; /* callbacks */ void (*reset)(DeviceState *dev); @@ -180,14 +184,18 @@ typedef struct BusChild { QTAILQ_ENTRY(BusChild) sibling; } BusChild; +#define QDEV_HOTPLUG_HANDLER_PROPERTY "hotplug-handler" + /** * BusState: + * @hotplug_device: link to a hotplug device associated with bus. */ struct BusState { Object obj; DeviceState *parent; const char *name; int allow_hotplug; + HotplugHandler *hotplug_handler; int max_index; QTAILQ_HEAD(ChildrenHead, BusChild) children; QLIST_ENTRY(BusState) sibling; @@ -320,4 +328,11 @@ extern int qdev_hotplug; char *qdev_get_dev_path(DeviceState *dev); +static inline void qbus_set_hotplug_handler(BusState *bus, DeviceState *handler, + Error **errp) +{ + object_property_set_link(OBJECT(bus), OBJECT(handler), + QDEV_HOTPLUG_HANDLER_PROPERTY, errp); + bus->allow_hotplug = 1; +} #endif diff --git a/include/net/checksum.h b/include/net/checksum.h index 80203fb6e0..2d7a363d40 100644 --- a/include/net/checksum.h +++ b/include/net/checksum.h @@ -19,6 +19,7 @@ #define QEMU_NET_CHECKSUM_H #include <stdint.h> +struct iovec; uint32_t net_checksum_add_cont(int len, uint8_t *buf, int seq); uint16_t net_checksum_finish(uint32_t sum); diff --git a/linux-user/syscall.c b/linux-user/syscall.c index bc0ac98d4f..f3700876a3 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -2177,271 +2177,81 @@ fail: /* do_socketcall() Must return target values and target errnos. */ static abi_long do_socketcall(int num, abi_ulong vptr) { - abi_long ret; - const int n = sizeof(abi_ulong); - - switch(num) { - case SOCKOP_socket: - { - abi_ulong domain, type, protocol; - - if (get_user_ual(domain, vptr) - || get_user_ual(type, vptr + n) - || get_user_ual(protocol, vptr + 2 * n)) - return -TARGET_EFAULT; - - ret = do_socket(domain, type, protocol); - } - break; - case SOCKOP_bind: - { - abi_ulong sockfd; - abi_ulong target_addr; - socklen_t addrlen; - - if (get_user_ual(sockfd, vptr) - || get_user_ual(target_addr, vptr + n) - || get_user_ual(addrlen, vptr + 2 * n)) - return -TARGET_EFAULT; - - ret = do_bind(sockfd, target_addr, addrlen); - } - break; - case SOCKOP_connect: - { - abi_ulong sockfd; - abi_ulong target_addr; - socklen_t addrlen; - - if (get_user_ual(sockfd, vptr) - || get_user_ual(target_addr, vptr + n) - || get_user_ual(addrlen, vptr + 2 * n)) - return -TARGET_EFAULT; - - ret = do_connect(sockfd, target_addr, addrlen); - } - break; - case SOCKOP_listen: - { - abi_ulong sockfd, backlog; - - if (get_user_ual(sockfd, vptr) - || get_user_ual(backlog, vptr + n)) - return -TARGET_EFAULT; - - ret = get_errno(listen(sockfd, backlog)); - } - break; - case SOCKOP_accept: - { - abi_ulong sockfd; - abi_ulong target_addr, target_addrlen; - - if (get_user_ual(sockfd, vptr) - || get_user_ual(target_addr, vptr + n) - || get_user_ual(target_addrlen, vptr + 2 * n)) - return -TARGET_EFAULT; - - ret = do_accept4(sockfd, target_addr, target_addrlen, 0); - } - break; - case SOCKOP_accept4: - { - abi_ulong sockfd; - abi_ulong target_addr, target_addrlen; - abi_ulong flags; - - if (get_user_ual(sockfd, vptr) - || get_user_ual(target_addr, vptr + n) - || get_user_ual(target_addrlen, vptr + 2 * n) - || get_user_ual(flags, vptr + 3 * n)) { + static const unsigned ac[] = { /* number of arguments per call */ + [SOCKOP_socket] = 3, /* domain, type, protocol */ + [SOCKOP_bind] = 3, /* sockfd, addr, addrlen */ + [SOCKOP_connect] = 3, /* sockfd, addr, addrlen */ + [SOCKOP_listen] = 2, /* sockfd, backlog */ + [SOCKOP_accept] = 3, /* sockfd, addr, addrlen */ + [SOCKOP_accept4] = 4, /* sockfd, addr, addrlen, flags */ + [SOCKOP_getsockname] = 3, /* sockfd, addr, addrlen */ + [SOCKOP_getpeername] = 3, /* sockfd, addr, addrlen */ + [SOCKOP_socketpair] = 4, /* domain, type, protocol, tab */ + [SOCKOP_send] = 4, /* sockfd, msg, len, flags */ + [SOCKOP_recv] = 4, /* sockfd, msg, len, flags */ + [SOCKOP_sendto] = 6, /* sockfd, msg, len, flags, addr, addrlen */ + [SOCKOP_recvfrom] = 6, /* sockfd, msg, len, flags, addr, addrlen */ + [SOCKOP_shutdown] = 2, /* sockfd, how */ + [SOCKOP_sendmsg] = 3, /* sockfd, msg, flags */ + [SOCKOP_recvmsg] = 3, /* sockfd, msg, flags */ + [SOCKOP_setsockopt] = 5, /* sockfd, level, optname, optval, optlen */ + [SOCKOP_getsockopt] = 5, /* sockfd, level, optname, optval, optlen */ + }; + abi_long a[6]; /* max 6 args */ + + /* first, collect the arguments in a[] according to ac[] */ + if (num >= 0 && num < ARRAY_SIZE(ac)) { + unsigned i; + assert(ARRAY_SIZE(a) >= ac[num]); /* ensure we have space for args */ + for (i = 0; i < ac[num]; ++i) { + if (get_user_ual(a[i], vptr + i * sizeof(abi_long)) != 0) { return -TARGET_EFAULT; } - - ret = do_accept4(sockfd, target_addr, target_addrlen, flags); - } - break; - case SOCKOP_getsockname: - { - abi_ulong sockfd; - abi_ulong target_addr, target_addrlen; - - if (get_user_ual(sockfd, vptr) - || get_user_ual(target_addr, vptr + n) - || get_user_ual(target_addrlen, vptr + 2 * n)) - return -TARGET_EFAULT; - - ret = do_getsockname(sockfd, target_addr, target_addrlen); } - break; - case SOCKOP_getpeername: - { - abi_ulong sockfd; - abi_ulong target_addr, target_addrlen; - - if (get_user_ual(sockfd, vptr) - || get_user_ual(target_addr, vptr + n) - || get_user_ual(target_addrlen, vptr + 2 * n)) - return -TARGET_EFAULT; - - ret = do_getpeername(sockfd, target_addr, target_addrlen); - } - break; - case SOCKOP_socketpair: - { - abi_ulong domain, type, protocol; - abi_ulong tab; - - if (get_user_ual(domain, vptr) - || get_user_ual(type, vptr + n) - || get_user_ual(protocol, vptr + 2 * n) - || get_user_ual(tab, vptr + 3 * n)) - return -TARGET_EFAULT; - - ret = do_socketpair(domain, type, protocol, tab); - } - break; - case SOCKOP_send: - { - abi_ulong sockfd; - abi_ulong msg; - size_t len; - abi_ulong flags; - - if (get_user_ual(sockfd, vptr) - || get_user_ual(msg, vptr + n) - || get_user_ual(len, vptr + 2 * n) - || get_user_ual(flags, vptr + 3 * n)) - return -TARGET_EFAULT; - - ret = do_sendto(sockfd, msg, len, flags, 0, 0); - } - break; - case SOCKOP_recv: - { - abi_ulong sockfd; - abi_ulong msg; - size_t len; - abi_ulong flags; - - if (get_user_ual(sockfd, vptr) - || get_user_ual(msg, vptr + n) - || get_user_ual(len, vptr + 2 * n) - || get_user_ual(flags, vptr + 3 * n)) - return -TARGET_EFAULT; - - ret = do_recvfrom(sockfd, msg, len, flags, 0, 0); - } - break; - case SOCKOP_sendto: - { - abi_ulong sockfd; - abi_ulong msg; - size_t len; - abi_ulong flags; - abi_ulong addr; - abi_ulong addrlen; - - if (get_user_ual(sockfd, vptr) - || get_user_ual(msg, vptr + n) - || get_user_ual(len, vptr + 2 * n) - || get_user_ual(flags, vptr + 3 * n) - || get_user_ual(addr, vptr + 4 * n) - || get_user_ual(addrlen, vptr + 5 * n)) - return -TARGET_EFAULT; - - ret = do_sendto(sockfd, msg, len, flags, addr, addrlen); - } - break; - case SOCKOP_recvfrom: - { - abi_ulong sockfd; - abi_ulong msg; - size_t len; - abi_ulong flags; - abi_ulong addr; - socklen_t addrlen; - - if (get_user_ual(sockfd, vptr) - || get_user_ual(msg, vptr + n) - || get_user_ual(len, vptr + 2 * n) - || get_user_ual(flags, vptr + 3 * n) - || get_user_ual(addr, vptr + 4 * n) - || get_user_ual(addrlen, vptr + 5 * n)) - return -TARGET_EFAULT; - - ret = do_recvfrom(sockfd, msg, len, flags, addr, addrlen); - } - break; - case SOCKOP_shutdown: - { - abi_ulong sockfd, how; - - if (get_user_ual(sockfd, vptr) - || get_user_ual(how, vptr + n)) - return -TARGET_EFAULT; - - ret = get_errno(shutdown(sockfd, how)); - } - break; - case SOCKOP_sendmsg: - case SOCKOP_recvmsg: - { - abi_ulong fd; - abi_ulong target_msg; - abi_ulong flags; - - if (get_user_ual(fd, vptr) - || get_user_ual(target_msg, vptr + n) - || get_user_ual(flags, vptr + 2 * n)) - return -TARGET_EFAULT; - - ret = do_sendrecvmsg(fd, target_msg, flags, - (num == SOCKOP_sendmsg)); - } - break; - case SOCKOP_setsockopt: - { - abi_ulong sockfd; - abi_ulong level; - abi_ulong optname; - abi_ulong optval; - abi_ulong optlen; - - if (get_user_ual(sockfd, vptr) - || get_user_ual(level, vptr + n) - || get_user_ual(optname, vptr + 2 * n) - || get_user_ual(optval, vptr + 3 * n) - || get_user_ual(optlen, vptr + 4 * n)) - return -TARGET_EFAULT; - - ret = do_setsockopt(sockfd, level, optname, optval, optlen); - } - break; - case SOCKOP_getsockopt: - { - abi_ulong sockfd; - abi_ulong level; - abi_ulong optname; - abi_ulong optval; - socklen_t optlen; - - if (get_user_ual(sockfd, vptr) - || get_user_ual(level, vptr + n) - || get_user_ual(optname, vptr + 2 * n) - || get_user_ual(optval, vptr + 3 * n) - || get_user_ual(optlen, vptr + 4 * n)) - return -TARGET_EFAULT; + } - ret = do_getsockopt(sockfd, level, optname, optval, optlen); - } - break; + /* now when we have the args, actually handle the call */ + switch (num) { + case SOCKOP_socket: /* domain, type, protocol */ + return do_socket(a[0], a[1], a[2]); + case SOCKOP_bind: /* sockfd, addr, addrlen */ + return do_bind(a[0], a[1], a[2]); + case SOCKOP_connect: /* sockfd, addr, addrlen */ + return do_connect(a[0], a[1], a[2]); + case SOCKOP_listen: /* sockfd, backlog */ + return get_errno(listen(a[0], a[1])); + case SOCKOP_accept: /* sockfd, addr, addrlen */ + return do_accept4(a[0], a[1], a[2], 0); + case SOCKOP_accept4: /* sockfd, addr, addrlen, flags */ + return do_accept4(a[0], a[1], a[2], a[3]); + case SOCKOP_getsockname: /* sockfd, addr, addrlen */ + return do_getsockname(a[0], a[1], a[2]); + case SOCKOP_getpeername: /* sockfd, addr, addrlen */ + return do_getpeername(a[0], a[1], a[2]); + case SOCKOP_socketpair: /* domain, type, protocol, tab */ + return do_socketpair(a[0], a[1], a[2], a[3]); + case SOCKOP_send: /* sockfd, msg, len, flags */ + return do_sendto(a[0], a[1], a[2], a[3], 0, 0); + case SOCKOP_recv: /* sockfd, msg, len, flags */ + return do_recvfrom(a[0], a[1], a[2], a[3], 0, 0); + case SOCKOP_sendto: /* sockfd, msg, len, flags, addr, addrlen */ + return do_sendto(a[0], a[1], a[2], a[3], a[4], a[5]); + case SOCKOP_recvfrom: /* sockfd, msg, len, flags, addr, addrlen */ + return do_recvfrom(a[0], a[1], a[2], a[3], a[4], a[5]); + case SOCKOP_shutdown: /* sockfd, how */ + return get_errno(shutdown(a[0], a[1])); + case SOCKOP_sendmsg: /* sockfd, msg, flags */ + return do_sendrecvmsg(a[0], a[1], a[2], 1); + case SOCKOP_recvmsg: /* sockfd, msg, flags */ + return do_sendrecvmsg(a[0], a[1], a[2], 0); + case SOCKOP_setsockopt: /* sockfd, level, optname, optval, optlen */ + return do_setsockopt(a[0], a[1], a[2], a[3], a[4]); + case SOCKOP_getsockopt: /* sockfd, level, optname, optval, optlen */ + return do_getsockopt(a[0], a[1], a[2], a[3], a[4]); default: gemu_log("Unsupported socketcall: %d\n", num); - ret = -TARGET_ENOSYS; - break; + return -TARGET_ENOSYS; } - return ret; } #endif @@ -56,6 +56,7 @@ #include "qapi/qmp/qjson.h" #include "qapi/qmp/json-streamer.h" #include "qapi/qmp/json-parser.h" +#include <qom/object_interfaces.h> #include "qemu/osdep.h" #include "cpu.h" #include "trace.h" @@ -4254,6 +4255,87 @@ static const char *next_arg_type(const char *typestr) return (p != NULL ? ++p : typestr); } +static void device_add_completion(ReadLineState *rs, const char *str) +{ + GSList *list, *elt; + size_t len; + + len = strlen(str); + readline_set_completion_index(rs, len); + list = elt = object_class_get_list(TYPE_DEVICE, false); + while (elt) { + const char *name; + DeviceClass *dc = OBJECT_CLASS_CHECK(DeviceClass, elt->data, + TYPE_DEVICE); + name = object_class_get_name(OBJECT_CLASS(dc)); + if (!strncmp(name, str, len)) { + readline_add_completion(rs, name); + } + elt = elt->next; + } + g_slist_free(list); +} + +static void object_add_completion(ReadLineState *rs, const char *str) +{ + GSList *list, *elt; + size_t len; + + len = strlen(str); + readline_set_completion_index(rs, len); + list = elt = object_class_get_list(TYPE_USER_CREATABLE, false); + while (elt) { + const char *name; + + name = object_class_get_name(OBJECT_CLASS(elt->data)); + if (!strncmp(name, str, len) && strcmp(name, TYPE_USER_CREATABLE)) { + readline_add_completion(rs, name); + } + elt = elt->next; + } + g_slist_free(list); +} + +static void device_del_completion(ReadLineState *rs, BusState *bus, + const char *str, size_t len) +{ + BusChild *kid; + + QTAILQ_FOREACH(kid, &bus->children, sibling) { + DeviceState *dev = kid->child; + BusState *dev_child; + + if (dev->id && !strncmp(str, dev->id, len)) { + readline_add_completion(rs, dev->id); + } + + QLIST_FOREACH(dev_child, &dev->child_bus, sibling) { + device_del_completion(rs, dev_child, str, len); + } + } +} + +static void object_del_completion(ReadLineState *rs, const char *str) +{ + ObjectPropertyInfoList *list, *start; + size_t len; + + len = strlen(str); + readline_set_completion_index(rs, len); + + start = list = qmp_qom_list("/objects", NULL); + while (list) { + ObjectPropertyInfo *info = list->value; + + if (!strncmp(info->type, "child<", 5) + && !strncmp(info->name, str, len)) { + readline_add_completion(rs, info->name); + } + list = list->next; + } + qapi_free_ObjectPropertyInfoList(start); +} + static void monitor_find_completion_by_table(Monitor *mon, const mon_cmd_t *cmd_table, char **args, @@ -4317,6 +4399,13 @@ static void monitor_find_completion_by_table(Monitor *mon, readline_set_completion_index(mon->rs, strlen(str)); bdrv_iterate(block_completion_it, &mbs); break; + case 'O': + if (!strcmp(cmd->name, "device_add") && nb_args == 2) { + device_add_completion(mon->rs, str); + } else if (!strcmp(cmd->name, "object_add") && nb_args == 2) { + object_add_completion(mon->rs, str); + } + break; case 's': case 'S': if (!strcmp(cmd->name, "sendkey")) { @@ -4330,6 +4419,12 @@ static void monitor_find_completion_by_table(Monitor *mon, } else if (!strcmp(cmd->name, "help|?")) { monitor_find_completion_by_table(mon, cmd_table, &args[1], nb_args - 1); + } else if (!strcmp(cmd->name, "device_del") && nb_args == 2) { + size_t len = strlen(str); + readline_set_completion_index(mon->rs, len); + device_del_completion(mon->rs, sysbus_get_default(), str, len); + } else if (!strcmp(cmd->name, "object_del") && nb_args == 2) { + object_del_completion(mon->rs, str); } break; default: @@ -882,7 +882,7 @@ void net_host_device_add(Monitor *mon, const QDict *qdict) qemu_opt_set(opts, "type", device); net_client_init(opts, 0, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { qerror_report_err(local_err); error_free(local_err); monitor_printf(mon, "adding host network device %s failed\n", device); @@ -918,17 +918,17 @@ int qmp_netdev_add(Monitor *mon, const QDict *qdict, QObject **ret) QemuOpts *opts; opts_list = qemu_find_opts_err("netdev", &local_err); - if (error_is_set(&local_err)) { + if (local_err) { goto exit_err; } opts = qemu_opts_from_qdict(opts_list, qdict, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { goto exit_err; } netdev_add(opts, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { qemu_opts_del(opts); goto exit_err; } @@ -1152,7 +1152,7 @@ static int net_init_client(QemuOpts *opts, void *dummy) Error *local_err = NULL; net_client_init(opts, 0, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { qerror_report_err(local_err); error_free(local_err); return -1; @@ -1167,7 +1167,7 @@ static int net_init_netdev(QemuOpts *opts, void *dummy) int ret; ret = net_client_init(opts, 1, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { qerror_report_err(local_err); error_free(local_err); return -1; diff --git a/pc-bios/optionrom/Makefile b/pc-bios/optionrom/Makefile index 57d8bd0d6c..ce4852a4d5 100644 --- a/pc-bios/optionrom/Makefile +++ b/pc-bios/optionrom/Makefile @@ -12,6 +12,7 @@ $(call set-vpath, $(SRC_PATH)/pc-bios/optionrom) CFLAGS := -Wall -Wstrict-prototypes -Werror -fomit-frame-pointer -fno-builtin CFLAGS += -I$(SRC_PATH) CFLAGS += $(call cc-option, $(CFLAGS), -fno-stack-protector) +CFLAGS += $(CFLAGS_NOPIE) QEMU_CFLAGS = $(CFLAGS) build-all: multiboot.bin linuxboot.bin kvmvapic.bin @@ -20,7 +21,7 @@ build-all: multiboot.bin linuxboot.bin kvmvapic.bin .SECONDARY: %.img: %.o - $(call quiet-command,$(LD) -Ttext 0 -e _start -s -o $@ $<," Building $(TARGET_DIR)$@") + $(call quiet-command,$(LD) $(LDFLAGS_NOPIE) -Ttext 0 -e _start -s -o $@ $<," Building $(TARGET_DIR)$@") %.raw: %.img $(call quiet-command,$(OBJCOPY) -O binary -j .text $< $@," Building $(TARGET_DIR)$@") diff --git a/qapi-schema.json b/qapi-schema.json index 2d64ce67d9..473c096fa9 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -495,6 +495,28 @@ { 'command': 'query-chardev', 'returns': ['ChardevInfo'] } ## +# @ChardevBackendInfo: +# +# Information about a character device backend +# +# @name: The backend name +# +# Since: 2.0 +## +{ 'type': 'ChardevBackendInfo', 'data': {'name': 'str'} } + +## +# @query-chardev-backends: +# +# Returns information about character device backends. +# +# Returns: a list of @ChardevBackendInfo +# +# Since: 2.0 +## +{ 'command': 'query-chardev-backends', 'returns': ['ChardevBackendInfo'] } + +## # @DataFormat: # # An enumeration of data format. diff --git a/qdev-monitor.c b/qdev-monitor.c index b37778f0f3..3a7dc0d428 100644 --- a/qdev-monitor.c +++ b/qdev-monitor.c @@ -656,7 +656,7 @@ int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data) DeviceState *dev; opts = qemu_opts_from_qdict(qemu_find_opts("device"), qdict, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { qerror_report_err(local_err); error_free(local_err); return -1; diff --git a/qemu-char.c b/qemu-char.c index 30c5a6afd0..4d50838b3b 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -2725,7 +2725,7 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts) chr = qemu_chr_open_socket_fd(fd, do_nodelay, is_listen, is_telnet, is_waitconnect, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { goto fail; } return chr; @@ -2938,7 +2938,7 @@ QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename) Error *local_err = NULL; opts = qemu_opts_create(qemu_find_opts("chardev"), label, 1, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { qerror_report_err(local_err); error_free(local_err); return NULL; @@ -3323,7 +3323,7 @@ CharDriverState *qemu_chr_new(const char *label, const char *filename, void (*in return NULL; chr = qemu_chr_new_from_opts(opts, init, &err); - if (error_is_set(&err)) { + if (err) { error_report("%s", error_get_pretty(err)); error_free(err); } @@ -3432,6 +3432,25 @@ ChardevInfoList *qmp_query_chardev(Error **errp) return chr_list; } +ChardevBackendInfoList *qmp_query_chardev_backends(Error **errp) +{ + ChardevBackendInfoList *backend_list = NULL; + CharDriver *c = NULL; + GSList *i = NULL; + + for (i = backends; i; i = i->next) { + ChardevBackendInfoList *info = g_malloc0(sizeof(*info)); + c = i->data; + info->value = g_malloc0(sizeof(*info->value)); + info->value->name = g_strdup(c->name); + + info->next = backend_list; + backend_list = info; + } + + return backend_list; +} + CharDriverState *qemu_chr_find(const char *name) { CharDriverState *chr; diff --git a/qemu-img.c b/qemu-img.c index c989850ce7..0927b090de 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -419,7 +419,7 @@ static int img_create(int argc, char **argv) bdrv_img_create(filename, fmt, base_filename, base_fmt, options, img_size, BDRV_O_FLAGS, &local_err, quiet); - if (error_is_set(&local_err)) { + if (local_err) { error_report("%s: %s", filename, error_get_pretty(local_err)); error_free(local_err); return 1; @@ -1289,7 +1289,7 @@ static int img_convert(int argc, char **argv) bdrv_snapshot_load_tmp_by_id_or_name(bs[0], snapshot_name, &local_err); } - if (error_is_set(&local_err)) { + if (local_err) { error_report("Failed to load snapshot: %s", error_get_pretty(local_err)); error_free(local_err); @@ -1775,7 +1775,7 @@ static ImageInfoList *collect_image_info_list(const char *filename, } bdrv_query_image_info(bs, &info, &err); - if (error_is_set(&err)) { + if (err) { error_report("%s", error_get_pretty(err)); error_free(err); goto err; @@ -2184,7 +2184,7 @@ static int img_snapshot(int argc, char **argv) case SNAPSHOT_DELETE: bdrv_snapshot_delete_by_id_or_name(bs, snapshot_name, &err); - if (error_is_set(&err)) { + if (err) { error_report("Could not delete snapshot '%s': (%s)", snapshot_name, error_get_pretty(err)); error_free(err); diff --git a/qga/commands-posix.c b/qga/commands-posix.c index 8100bee67e..cae41716ca 100644 --- a/qga/commands-posix.c +++ b/qga/commands-posix.c @@ -108,7 +108,7 @@ void qmp_guest_shutdown(bool has_mode, const char *mode, Error **err) } ga_wait_child(pid, &status, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { error_propagate(err, local_err); return; } @@ -181,7 +181,7 @@ void qmp_guest_set_time(int64_t time_ns, Error **errp) } ga_wait_child(pid, &status, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { error_propagate(errp, local_err); return; } @@ -669,7 +669,7 @@ static void execute_fsfreeze_hook(FsfreezeHookArg arg, Error **err) } ga_wait_child(pid, &status, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { error_propagate(err, local_err); return; } @@ -713,14 +713,14 @@ int64_t qmp_guest_fsfreeze_freeze(Error **err) slog("guest-fsfreeze called"); execute_fsfreeze_hook(FSFREEZE_HOOK_FREEZE, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { error_propagate(err, local_err); return -1; } QTAILQ_INIT(&mounts); build_fs_mount_list(&mounts, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { error_propagate(err, local_err); return -1; } @@ -780,7 +780,7 @@ int64_t qmp_guest_fsfreeze_thaw(Error **err) QTAILQ_INIT(&mounts); build_fs_mount_list(&mounts, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { error_propagate(err, local_err); return 0; } @@ -861,7 +861,7 @@ void qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **err) QTAILQ_INIT(&mounts); build_fs_mount_list(&mounts, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { error_propagate(err, local_err); return; } @@ -957,7 +957,7 @@ static void bios_supports_mode(const char *pmutils_bin, const char *pmutils_arg, } ga_wait_child(pid, &status, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { error_propagate(err, local_err); goto out; } @@ -1034,7 +1034,7 @@ static void guest_suspend(const char *pmutils_bin, const char *sysfile_str, } ga_wait_child(pid, &status, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { error_propagate(err, local_err); goto out; } diff --git a/qga/commands-win32.c b/qga/commands-win32.c index a6a0af264b..50094ddfd3 100644 --- a/qga/commands-win32.c +++ b/qga/commands-win32.c @@ -197,7 +197,7 @@ int64_t qmp_guest_fsfreeze_freeze(Error **err) error: qmp_guest_fsfreeze_thaw(&local_err); - if (error_is_set(&local_err)) { + if (local_err) { g_debug("cleanup thaw: %s", error_get_pretty(local_err)); error_free(local_err); } diff --git a/qmp-commands.hx b/qmp-commands.hx index cce6b81da4..8a0e8320c6 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -1924,6 +1924,47 @@ EQMP }, SQMP +query-chardev-backends +------------- + +List available character device backends. + +Each backend is represented by a json-object, the returned value is a json-array +of all backends. + +Each json-object contains: + +- "name": backend name (json-string) + +Example: + +-> { "execute": "query-chardev-backends" } +<- { + "return":[ + { + "name":"udp" + }, + { + "name":"tcp" + }, + { + "name":"unix" + }, + { + "name":"spiceport" + } + ] + } + +EQMP + + { + .name = "query-chardev-backends", + .args_type = "", + .mhandler.cmd_new = qmp_marshal_input_query_chardev_backends, + }, + +SQMP query-block ----------- @@ -880,7 +880,7 @@ static int del_existing_snapshots(Monitor *mon, const char *name) if (bdrv_can_snapshot(bs) && bdrv_snapshot_find(bs, snapshot, name) >= 0) { bdrv_snapshot_delete_by_id_or_name(bs, name, &err); - if (error_is_set(&err)) { + if (err) { monitor_printf(mon, "Error while deleting snapshot on device '%s':" " %s\n", @@ -1115,7 +1115,7 @@ void do_delvm(Monitor *mon, const QDict *qdict) while ((bs1 = bdrv_next(bs1))) { if (bdrv_can_snapshot(bs1)) { bdrv_snapshot_delete_by_id_or_name(bs, name, &err); - if (error_is_set(&err)) { + if (err) { monitor_printf(mon, "Error while deleting snapshot on device '%s':" " %s\n", diff --git a/scripts/qmp/qmp-shell b/scripts/qmp/qmp-shell index d6b420f18a..d374b357aa 100755 --- a/scripts/qmp/qmp-shell +++ b/scripts/qmp/qmp-shell @@ -31,6 +31,7 @@ # (QEMU) import qmp +import json import readline import sys import pprint @@ -107,6 +108,8 @@ class QMPShell(qmp.QEMUMonitorProtocol): value = True elif opt[1] == 'false': value = False + elif opt[1].startswith('{'): + value = json.loads(opt[1]) else: value = opt[1] qmpcmd['arguments'][opt[0]] = value diff --git a/scripts/switch-timer-api b/scripts/switch-timer-api index a369a083d1..b0e230b9f1 100755 --- a/scripts/switch-timer-api +++ b/scripts/switch-timer-api @@ -20,7 +20,7 @@ sub Syntax print STDERR <<STOP; Usage: $FindBin::Script [options] FILE ... -Translate each FILE to the new Qemu timer API. If no files +Translate each FILE to the new QEMU timer API. If no files are passed, a reasonable guess is taken. Options: diff --git a/target-mips/cpu.h b/target-mips/cpu.h index 9caf4474b9..60c80617a5 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -73,6 +73,7 @@ struct CPUMIPSFPUContext { float_status fp_status; /* fpu implementation/revision register (fir) */ uint32_t fcr0; +#define FCR0_UFRP 28 #define FCR0_F64 22 #define FCR0_L 21 #define FCR0_W 20 @@ -368,6 +369,18 @@ struct CPUMIPSState { #define CP0C3_MT 2 #define CP0C3_SM 1 #define CP0C3_TL 0 + uint32_t CP0_Config4; + uint32_t CP0_Config4_rw_bitmask; +#define CP0C4_M 31 + uint32_t CP0_Config5; + uint32_t CP0_Config5_rw_bitmask; +#define CP0C5_M 31 +#define CP0C5_K 30 +#define CP0C5_CV 29 +#define CP0C5_EVA 28 +#define CP0C5_MSAEn 27 +#define CP0C5_UFR 2 +#define CP0C5_NFExists 0 int32_t CP0_Config6; int32_t CP0_Config7; /* XXX: Maybe make LLAddr per-TC? */ diff --git a/target-mips/helper.h b/target-mips/helper.h index 1a8b86dea5..8c7921a724 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -134,6 +134,8 @@ DEF_HELPER_2(mtc0_ebase, void, env, tl) DEF_HELPER_2(mttc0_ebase, void, env, tl) DEF_HELPER_2(mtc0_config0, void, env, tl) DEF_HELPER_2(mtc0_config2, void, env, tl) +DEF_HELPER_2(mtc0_config4, void, env, tl) +DEF_HELPER_2(mtc0_config5, void, env, tl) DEF_HELPER_2(mtc0_lladdr, void, env, tl) DEF_HELPER_3(mtc0_watchlo, void, env, tl, i32) DEF_HELPER_3(mtc0_watchhi, void, env, tl, i32) @@ -177,7 +179,7 @@ DEF_HELPER_2(yield, tl, env, tl) /* CP1 functions */ DEF_HELPER_2(cfc1, tl, env, i32) -DEF_HELPER_3(ctc1, void, env, tl, i32) +DEF_HELPER_4(ctc1, void, env, tl, i32, i32) DEF_HELPER_2(float_cvtd_s, i64, env, i32) DEF_HELPER_2(float_cvtd_w, i64, env, i32) diff --git a/target-mips/mips-defs.h b/target-mips/mips-defs.h index bf094a3bd5..9dfa5168da 100644 --- a/target-mips/mips-defs.h +++ b/target-mips/mips-defs.h @@ -29,6 +29,8 @@ #define ISA_MIPS32R2 0x00000040 #define ISA_MIPS64 0x00000080 #define ISA_MIPS64R2 0x00000100 +#define ISA_MIPS32R3 0x00000200 +#define ISA_MIPS32R5 0x00000400 /* MIPS ASEs. */ #define ASE_MIPS16 0x00001000 @@ -64,6 +66,12 @@ #define CPU_MIPS32R2 (CPU_MIPS32 | ISA_MIPS32R2) #define CPU_MIPS64R2 (CPU_MIPS64 | CPU_MIPS32R2 | ISA_MIPS64R2) +/* MIPS Technologies "Release 3" */ +#define CPU_MIPS32R3 (CPU_MIPS32R2 | ISA_MIPS32R3) + +/* MIPS Technologies "Release 5" */ +#define CPU_MIPS32R5 (CPU_MIPS32R3 | ISA_MIPS32R5) + /* Strictly follow the architecture standard: - Disallow "special" instruction handling for PMON/SPIM. Note that we still maintain Count/Compare to match the host clock. */ diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index 8e3a6d7da6..2ef6633f47 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -1489,6 +1489,18 @@ void helper_mtc0_config2(CPUMIPSState *env, target_ulong arg1) env->CP0_Config2 = (env->CP0_Config2 & 0x8FFF0FFF); } +void helper_mtc0_config4(CPUMIPSState *env, target_ulong arg1) +{ + env->CP0_Config4 = (env->CP0_Config4 & (~env->CP0_Config4_rw_bitmask)) | + (arg1 & env->CP0_Config4_rw_bitmask); +} + +void helper_mtc0_config5(CPUMIPSState *env, target_ulong arg1) +{ + env->CP0_Config5 = (env->CP0_Config5 & (~env->CP0_Config5_rw_bitmask)) | + (arg1 & env->CP0_Config5_rw_bitmask); +} + void helper_mtc0_lladdr(CPUMIPSState *env, target_ulong arg1) { target_long mask = env->CP0_LLAddr_rw_bitmask; @@ -2187,12 +2199,23 @@ static inline void restore_flush_mode(CPUMIPSState *env) target_ulong helper_cfc1(CPUMIPSState *env, uint32_t reg) { - target_ulong arg1; + target_ulong arg1 = 0; switch (reg) { case 0: arg1 = (int32_t)env->active_fpu.fcr0; break; + case 1: + /* UFR Support - Read Status FR */ + if (env->active_fpu.fcr0 & (1 << FCR0_UFRP)) { + if (env->CP0_Config5 & (1 << CP0C5_UFR)) { + arg1 = (int32_t) + ((env->CP0_Status & (1 << CP0St_FR)) >> CP0St_FR); + } else { + helper_raise_exception(env, EXCP_RI); + } + } + break; case 25: arg1 = ((env->active_fpu.fcr31 >> 24) & 0xfe) | ((env->active_fpu.fcr31 >> 23) & 0x1); break; @@ -2210,9 +2233,33 @@ target_ulong helper_cfc1(CPUMIPSState *env, uint32_t reg) return arg1; } -void helper_ctc1(CPUMIPSState *env, target_ulong arg1, uint32_t reg) +void helper_ctc1(CPUMIPSState *env, target_ulong arg1, uint32_t fs, uint32_t rt) { - switch(reg) { + switch (fs) { + case 1: + /* UFR Alias - Reset Status FR */ + if (!((env->active_fpu.fcr0 & (1 << FCR0_UFRP)) && (rt == 0))) { + return; + } + if (env->CP0_Config5 & (1 << CP0C5_UFR)) { + env->CP0_Status &= ~(1 << CP0St_FR); + compute_hflags(env); + } else { + helper_raise_exception(env, EXCP_RI); + } + break; + case 4: + /* UNFR Alias - Set Status FR */ + if (!((env->active_fpu.fcr0 & (1 << FCR0_UFRP)) && (rt == 0))) { + return; + } + if (env->CP0_Config5 & (1 << CP0C5_UFR)) { + env->CP0_Status |= (1 << CP0St_FR); + compute_hflags(env); + } else { + helper_raise_exception(env, EXCP_RI); + } + break; case 25: if (arg1 & 0xffffff00) return; diff --git a/target-mips/translate.c b/target-mips/translate.c index ef0a2c36b0..083f6ab283 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -4405,7 +4405,14 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel) gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3)); rn = "Config3"; break; - /* 4,5 are reserved */ + case 4: + gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4)); + rn = "Config4"; + break; + case 5: + gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5)); + rn = "Config5"; + break; /* 6,7 are implementation dependent */ case 6: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6)); @@ -4982,7 +4989,17 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel) /* ignored, read only */ rn = "Config3"; break; - /* 4,5 are reserved */ + case 4: + gen_helper_mtc0_config4(cpu_env, arg); + rn = "Config4"; + ctx->bstate = BS_STOP; + break; + case 5: + gen_helper_mtc0_config5(cpu_env, arg); + rn = "Config5"; + /* Stop translation as we may have switched the execution mode */ + ctx->bstate = BS_STOP; + break; /* 6,7 are implementation dependent */ case 6: /* ignored */ @@ -6801,7 +6818,12 @@ static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt, break; case 3: /* XXX: For now we support only a single FPU context. */ - gen_helper_0e1i(ctc1, t0, rd); + { + TCGv_i32 fs_tmp = tcg_const_i32(rd); + + gen_helper_0e2i(ctc1, t0, fs_tmp, rt); + tcg_temp_free_i32(fs_tmp); + } break; /* COP2: Not implemented. */ case 4: @@ -7237,7 +7259,12 @@ static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs) break; case OPC_CTC1: gen_load_gpr(t0, rt); - gen_helper_0e1i(ctc1, t0, fs); + { + TCGv_i32 fs_tmp = tcg_const_i32(fs); + + gen_helper_0e2i(ctc1, t0, fs_tmp, rt); + tcg_temp_free_i32(fs_tmp); + } opn = "ctc1"; break; #if defined(TARGET_MIPS64) @@ -15916,6 +15943,10 @@ void cpu_state_reset(CPUMIPSState *env) env->CP0_Config1 = env->cpu_model->CP0_Config1; env->CP0_Config2 = env->cpu_model->CP0_Config2; env->CP0_Config3 = env->cpu_model->CP0_Config3; + env->CP0_Config4 = env->cpu_model->CP0_Config4; + env->CP0_Config4_rw_bitmask = env->cpu_model->CP0_Config4_rw_bitmask; + env->CP0_Config5 = env->cpu_model->CP0_Config5; + env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask; env->CP0_Config6 = env->cpu_model->CP0_Config6; env->CP0_Config7 = env->cpu_model->CP0_Config7; env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask diff --git a/target-mips/translate_init.c b/target-mips/translate_init.c index c45b1b21b2..29d39e2a39 100644 --- a/target-mips/translate_init.c +++ b/target-mips/translate_init.c @@ -45,6 +45,12 @@ (0 << CP0C3_VEIC) | (0 << CP0C3_VInt) | (0 << CP0C3_SP) | \ (0 << CP0C3_SM) | (0 << CP0C3_TL)) +#define MIPS_CONFIG4 \ +((0 << CP0C4_M)) + +#define MIPS_CONFIG5 \ +((0 << CP0C5_M)) + /* MMU types, the first four entries have the same layout as the CP0C0_MT field. */ enum mips_mmu_types { @@ -64,6 +70,10 @@ struct mips_def_t { int32_t CP0_Config1; int32_t CP0_Config2; int32_t CP0_Config3; + int32_t CP0_Config4; + int32_t CP0_Config4_rw_bitmask; + int32_t CP0_Config5; + int32_t CP0_Config5_rw_bitmask; int32_t CP0_Config6; int32_t CP0_Config7; target_ulong CP0_LLAddr_rw_bitmask; @@ -333,6 +343,39 @@ static const mips_def_t mips_defs[] = .insn_flags = CPU_MIPS32R2 | ASE_MIPS16 | ASE_DSP | ASE_DSPR2, .mmu_type = MMU_TYPE_R4000, }, + { + /* A generic CPU providing MIPS32 Release 5 features. + FIXME: Eventually this should be replaced by a real CPU model. */ + .name = "mips32r5-generic", + .CP0_PRid = 0x00019700, + .CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR) | + (MMU_TYPE_R4000 << CP0C0_MT), + .CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (15 << CP0C1_MMU) | + (0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) | + (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA) | + (1 << CP0C1_CA), + .CP0_Config2 = MIPS_CONFIG2, + .CP0_Config3 = MIPS_CONFIG3 | (1 << CP0C3_M), + .CP0_Config4 = MIPS_CONFIG4 | (1 << CP0C4_M), + .CP0_Config4_rw_bitmask = 0, + .CP0_Config5 = MIPS_CONFIG5 | (1 << CP0C5_UFR), + .CP0_Config5_rw_bitmask = (0 << CP0C5_M) | (1 << CP0C5_K) | + (1 << CP0C5_CV) | (0 << CP0C5_EVA) | + (1 << CP0C5_MSAEn) | (1 << CP0C5_UFR) | + (0 << CP0C5_NFExists), + .CP0_LLAddr_rw_bitmask = 0, + .CP0_LLAddr_shift = 4, + .SYNCI_Step = 32, + .CCRes = 2, + .CP0_Status_rw_bitmask = 0x3778FF1F, + .CP1_fcr0 = (1 << FCR0_UFRP) | (1 << FCR0_F64) | (1 << FCR0_L) | + (1 << FCR0_W) | (1 << FCR0_D) | (1 << FCR0_S) | + (0x93 << FCR0_PRID), + .SEGBITS = 32, + .PABITS = 32, + .insn_flags = CPU_MIPS32R5 | ASE_MIPS16 | ASE_DSP | ASE_DSPR2, + .mmu_type = MMU_TYPE_R4000, + }, #if defined(TARGET_MIPS64) { .name = "R4000", diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c index b381477d29..776cb6eece 100644 --- a/target-openrisc/translate.c +++ b/target-openrisc/translate.c @@ -707,6 +707,8 @@ static void dec_misc(DisasContext *dc, uint32_t insn) uint32_t L6, K5; #endif uint32_t I16, I5, I11, N26, tmp; + TCGMemOp mop; + op0 = extract32(insn, 26, 6); op1 = extract32(insn, 24, 2); ra = extract32(insn, 16, 5); @@ -838,72 +840,46 @@ static void dec_misc(DisasContext *dc, uint32_t insn) /*#ifdef TARGET_OPENRISC64 case 0x20: l.ld LOG_DIS("l.ld r%d, r%d, %d\n", rd, ra, I16); - { - check_ob64s(dc); - TCGv_i64 t0 = tcg_temp_new_i64(); - tcg_gen_addi_i64(t0, cpu_R[ra], sign_extend(I16, 16)); - tcg_gen_qemu_ld64(cpu_R[rd], t0, dc->mem_idx); - tcg_temp_free_i64(t0); - } - break; + check_ob64s(dc); + mop = MO_TEQ; + goto do_load; #endif*/ case 0x21: /* l.lwz */ LOG_DIS("l.lwz r%d, r%d, %d\n", rd, ra, I16); - { - TCGv t0 = tcg_temp_new(); - tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(I16, 16)); - tcg_gen_qemu_ld32u(cpu_R[rd], t0, dc->mem_idx); - tcg_temp_free(t0); - } - break; + mop = MO_TEUL; + goto do_load; case 0x22: /* l.lws */ LOG_DIS("l.lws r%d, r%d, %d\n", rd, ra, I16); - { - TCGv t0 = tcg_temp_new(); - tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(I16, 16)); - tcg_gen_qemu_ld32s(cpu_R[rd], t0, dc->mem_idx); - tcg_temp_free(t0); - } - break; + mop = MO_TESL; + goto do_load; case 0x23: /* l.lbz */ LOG_DIS("l.lbz r%d, r%d, %d\n", rd, ra, I16); - { - TCGv t0 = tcg_temp_new(); - tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(I16, 16)); - tcg_gen_qemu_ld8u(cpu_R[rd], t0, dc->mem_idx); - tcg_temp_free(t0); - } - break; + mop = MO_UB; + goto do_load; case 0x24: /* l.lbs */ LOG_DIS("l.lbs r%d, r%d, %d\n", rd, ra, I16); - { - TCGv t0 = tcg_temp_new(); - tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(I16, 16)); - tcg_gen_qemu_ld8s(cpu_R[rd], t0, dc->mem_idx); - tcg_temp_free(t0); - } - break; + mop = MO_SB; + goto do_load; case 0x25: /* l.lhz */ LOG_DIS("l.lhz r%d, r%d, %d\n", rd, ra, I16); - { - TCGv t0 = tcg_temp_new(); - tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(I16, 16)); - tcg_gen_qemu_ld16u(cpu_R[rd], t0, dc->mem_idx); - tcg_temp_free(t0); - } - break; + mop = MO_TEUW; + goto do_load; case 0x26: /* l.lhs */ LOG_DIS("l.lhs r%d, r%d, %d\n", rd, ra, I16); + mop = MO_TESW; + goto do_load; + + do_load: { TCGv t0 = tcg_temp_new(); tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(I16, 16)); - tcg_gen_qemu_ld16s(cpu_R[rd], t0, dc->mem_idx); + tcg_gen_qemu_ld_tl(cpu_R[rd], t0, dc->mem_idx, mop); tcg_temp_free(t0); } break; @@ -1042,42 +1018,31 @@ static void dec_misc(DisasContext *dc, uint32_t insn) /*#ifdef TARGET_OPENRISC64 case 0x34: l.sd LOG_DIS("l.sd %d, r%d, r%d, %d\n", I5, ra, rb, I11); - { - check_ob64s(dc); - TCGv_i64 t0 = tcg_temp_new_i64(); - tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(tmp, 16)); - tcg_gen_qemu_st64(cpu_R[rb], t0, dc->mem_idx); - tcg_temp_free_i64(t0); - } - break; + check_ob64s(dc); + mop = MO_TEQ; + goto do_store; #endif*/ case 0x35: /* l.sw */ LOG_DIS("l.sw %d, r%d, r%d, %d\n", I5, ra, rb, I11); - { - TCGv t0 = tcg_temp_new(); - tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(tmp, 16)); - tcg_gen_qemu_st32(cpu_R[rb], t0, dc->mem_idx); - tcg_temp_free(t0); - } - break; + mop = MO_TEUL; + goto do_store; case 0x36: /* l.sb */ LOG_DIS("l.sb %d, r%d, r%d, %d\n", I5, ra, rb, I11); - { - TCGv t0 = tcg_temp_new(); - tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(tmp, 16)); - tcg_gen_qemu_st8(cpu_R[rb], t0, dc->mem_idx); - tcg_temp_free(t0); - } - break; + mop = MO_UB; + goto do_store; case 0x37: /* l.sh */ LOG_DIS("l.sh %d, r%d, r%d, %d\n", I5, ra, rb, I11); + mop = MO_TEUW; + goto do_store; + + do_store: { TCGv t0 = tcg_temp_new(); tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(tmp, 16)); - tcg_gen_qemu_st16(cpu_R[rb], t0, dc->mem_idx); + tcg_gen_qemu_st_tl(cpu_R[rb], t0, dc->mem_idx, mop); tcg_temp_free(t0); } break; diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c index 781b72f1ea..7af3fe277d 100644 --- a/target-ppc/kvm.c +++ b/target-ppc/kvm.c @@ -1228,7 +1228,7 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) #endif case KVM_EXIT_EPR: DPRINTF("handle epr\n"); - run->epr.epr = ldl_phys(env->mpic_iack); + run->epr.epr = ldl_phys(cs->as, env->mpic_iack); ret = 0; break; case KVM_EXIT_WATCHDOG: diff --git a/tests/Makefile b/tests/Makefile index 0ef8727873..b17d41e4e2 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -181,7 +181,7 @@ tests/test-xbzrle$(EXESUF): tests/test-xbzrle.o xbzrle.o page_cache.o libqemuuti tests/test-cutils$(EXESUF): tests/test-cutils.o util/cutils.o tests/test-int128$(EXESUF): tests/test-int128.o tests/test-qdev-global-props$(EXESUF): tests/test-qdev-global-props.o \ - hw/core/qdev.o hw/core/qdev-properties.o \ + hw/core/qdev.o hw/core/qdev-properties.o hw/core/hotplug.o\ hw/core/irq.o \ $(qom-core-obj) \ $(test-qapi-obj-y) \ diff --git a/tests/i440fx-test.c b/tests/i440fx-test.c index e398b83018..ad232b561c 100644 --- a/tests/i440fx-test.c +++ b/tests/i440fx-test.c @@ -349,7 +349,7 @@ static void test_i440fx_firmware(FirmwareTestFixture *fixture, qtest_start(cmdline); g_free(cmdline); - /* Qemu has loaded the firmware (because qtest_start() only returns after + /* QEMU has loaded the firmware (because qtest_start() only returns after * the QMP handshake completes). We must unlink the firmware blob right * here, because any assertion firing below would leak it in the * filesystem. This is also the reason why we recreate the blob every time diff --git a/tests/qemu-iotests/005 b/tests/qemu-iotests/005 index 9abcb84e4b..ba1236dfbf 100755 --- a/tests/qemu-iotests/005 +++ b/tests/qemu-iotests/005 @@ -44,6 +44,8 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 _supported_fmt generic _supported_proto generic _supported_os Linux +_unsupported_imgopts "subformat=twoGbMaxExtentFlat" \ + "subformat=twoGbMaxExtentSparse" # vpc is limited to 127GB, so we can't test it here if [ "$IMGFMT" = "vpc" ]; then diff --git a/tests/qemu-iotests/070 b/tests/qemu-iotests/070 index 41bf100701..ce71fa4a22 100755 --- a/tests/qemu-iotests/070 +++ b/tests/qemu-iotests/070 @@ -56,11 +56,22 @@ _use_sample_img iotest-dirtylog-10G-4M.vhdx.bz2 echo echo "=== Verify open image read-only fails, due to dirty log ===" -$QEMU_IO -r -c "read -pP 0xa5 0 18M" "$TEST_IMG" 2>&1 | grep -o "Permission denied" +$QEMU_IO -r -c "read -pP 0xa5 0 18M" "$TEST_IMG" 2>&1 | _filter_testdir \ + | _filter_qemu_io echo "=== Verify open image replays log ===" $QEMU_IO -c "read -pP 0xa5 0 18M" "$TEST_IMG" | _filter_qemu_io +# extract fresh sample image again +_use_sample_img iotest-dirtylog-10G-4M.vhdx.bz2 + +echo "=== Verify qemu-img check -r all replays log ===" +$QEMU_IMG check -r all "$TEST_IMG" 2>&1 | _filter_testdir | _filter_qemu + +echo "=== Verify open image read-only succeeds after log replay ===" +$QEMU_IO -r -c "read -pP 0xa5 0 18M" "$TEST_IMG" 2>&1 | _filter_testdir \ + | _filter_qemu_io + # success, all done echo "*** done" rm -f $seq.full diff --git a/tests/qemu-iotests/070.out b/tests/qemu-iotests/070.out index 9db8ff2650..922d62cb51 100644 --- a/tests/qemu-iotests/070.out +++ b/tests/qemu-iotests/070.out @@ -1,8 +1,21 @@ QA output created by 070 === Verify open image read-only fails, due to dirty log === -Permission denied +qemu-io: can't open device TEST_DIR/iotest-dirtylog-10G-4M.vhdx: VHDX image file 'TEST_DIR/iotest-dirtylog-10G-4M.vhdx' opened read-only, but contains a log that needs to be replayed. To replay the log, execute: + qemu-img check -r all 'TEST_DIR/iotest-dirtylog-10G-4M.vhdx': Operation not permitted + no file open, try 'help open' === Verify open image replays log === read 18874368/18874368 bytes at offset 0 18 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +=== Verify qemu-img check -r all replays log === +The following inconsistencies were found and repaired: + + 0 leaked clusters + 1 corruptions + +Double checking the fixed image now... +No errors were found on the image. +=== Verify open image read-only succeeds after log replay === +read 18874368/18874368 bytes at offset 0 +18 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) *** done diff --git a/tests/test-qmp-input-strict.c b/tests/test-qmp-input-strict.c index 6f68963a3d..38bdf5ec7c 100644 --- a/tests/test-qmp-input-strict.c +++ b/tests/test-qmp-input-strict.c @@ -92,7 +92,7 @@ static void test_validate_struct(TestInputVisitorData *data, v = validate_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo' }"); visit_type_TestStruct(v, &p, NULL, &errp); - g_assert(!error_is_set(&errp)); + g_assert(!errp); g_free(p->string); g_free(p); } @@ -107,7 +107,7 @@ static void test_validate_struct_nested(TestInputVisitorData *data, v = validate_test_init(data, "{ 'string0': 'string0', 'dict1': { 'string1': 'string1', 'dict2': { 'userdef1': { 'integer': 42, 'string': 'string' }, 'string2': 'string2'}}}"); visit_type_UserDefNested(v, &udp, NULL, &errp); - g_assert(!error_is_set(&errp)); + g_assert(!errp); qapi_free_UserDefNested(udp); } @@ -121,7 +121,7 @@ static void test_validate_list(TestInputVisitorData *data, v = validate_test_init(data, "[ { 'string': 'string0', 'integer': 42 }, { 'string': 'string1', 'integer': 43 }, { 'string': 'string2', 'integer': 44 } ]"); visit_type_UserDefOneList(v, &head, NULL, &errp); - g_assert(!error_is_set(&errp)); + g_assert(!errp); qapi_free_UserDefOneList(head); } @@ -135,7 +135,7 @@ static void test_validate_union(TestInputVisitorData *data, v = validate_test_init(data, "{ 'type': 'b', 'data' : { 'integer': 42 } }"); visit_type_UserDefUnion(v, &tmp, NULL, &errp); - g_assert(!error_is_set(&errp)); + g_assert(!errp); qapi_free_UserDefUnion(tmp); } @@ -149,7 +149,7 @@ static void test_validate_fail_struct(TestInputVisitorData *data, v = validate_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo', 'extra': 42 }"); visit_type_TestStruct(v, &p, NULL, &errp); - g_assert(error_is_set(&errp)); + g_assert(errp); if (p) { g_free(p->string); } @@ -166,7 +166,7 @@ static void test_validate_fail_struct_nested(TestInputVisitorData *data, v = validate_test_init(data, "{ 'string0': 'string0', 'dict1': { 'string1': 'string1', 'dict2': { 'userdef1': { 'integer': 42, 'string': 'string', 'extra': [42, 23, {'foo':'bar'}] }, 'string2': 'string2'}}}"); visit_type_UserDefNested(v, &udp, NULL, &errp); - g_assert(error_is_set(&errp)); + g_assert(errp); qapi_free_UserDefNested(udp); } @@ -180,7 +180,7 @@ static void test_validate_fail_list(TestInputVisitorData *data, v = validate_test_init(data, "[ { 'string': 'string0', 'integer': 42 }, { 'string': 'string1', 'integer': 43 }, { 'string': 'string2', 'integer': 44, 'extra': 'ggg' } ]"); visit_type_UserDefOneList(v, &head, NULL, &errp); - g_assert(error_is_set(&errp)); + g_assert(errp); qapi_free_UserDefOneList(head); } @@ -194,7 +194,7 @@ static void test_validate_fail_union(TestInputVisitorData *data, v = validate_test_init(data, "{ 'type': 'b', 'data' : { 'integer': 42 }, 'extra': 'yyy' }"); visit_type_UserDefUnion(v, &tmp, NULL, &errp); - g_assert(error_is_set(&errp)); + g_assert(errp); qapi_free_UserDefUnion(tmp); } diff --git a/tests/test-qmp-input-visitor.c b/tests/test-qmp-input-visitor.c index 1e1c6fa0c2..6eb7dc5bcf 100644 --- a/tests/test-qmp-input-visitor.c +++ b/tests/test-qmp-input-visitor.c @@ -96,7 +96,7 @@ static void test_visitor_in_int(TestInputVisitorData *data, v = visitor_input_test_init(data, "%" PRId64, value); visit_type_int(v, &res, NULL, &errp); - g_assert(!error_is_set(&errp)); + g_assert(!errp); g_assert_cmpint(res, ==, value); } @@ -114,7 +114,7 @@ static void test_visitor_in_int_overflow(TestInputVisitorData *data, v = visitor_input_test_init(data, "%f", DBL_MAX); visit_type_int(v, &res, NULL, &errp); - g_assert(error_is_set(&errp)); + g_assert(errp); error_free(errp); } @@ -128,7 +128,7 @@ static void test_visitor_in_bool(TestInputVisitorData *data, v = visitor_input_test_init(data, "true"); visit_type_bool(v, &res, NULL, &errp); - g_assert(!error_is_set(&errp)); + g_assert(!errp); g_assert_cmpint(res, ==, true); } @@ -142,7 +142,7 @@ static void test_visitor_in_number(TestInputVisitorData *data, v = visitor_input_test_init(data, "%f", value); visit_type_number(v, &res, NULL, &errp); - g_assert(!error_is_set(&errp)); + g_assert(!errp); g_assert_cmpfloat(res, ==, value); } @@ -156,7 +156,7 @@ static void test_visitor_in_string(TestInputVisitorData *data, v = visitor_input_test_init(data, "%s", value); visit_type_str(v, &res, NULL, &errp); - g_assert(!error_is_set(&errp)); + g_assert(!errp); g_assert_cmpstr(res, ==, value); g_free(res); @@ -175,7 +175,7 @@ static void test_visitor_in_enum(TestInputVisitorData *data, v = visitor_input_test_init(data, "%s", EnumOne_lookup[i]); visit_type_EnumOne(v, &res, NULL, &errp); - g_assert(!error_is_set(&errp)); + g_assert(!errp); g_assert_cmpint(i, ==, res); visitor_input_teardown(data, NULL); @@ -223,7 +223,7 @@ static void test_visitor_in_struct(TestInputVisitorData *data, v = visitor_input_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo' }"); visit_type_TestStruct(v, &p, NULL, &errp); - g_assert(!error_is_set(&errp)); + g_assert(!errp); g_assert_cmpint(p->integer, ==, -42); g_assert(p->boolean == true); g_assert_cmpstr(p->string, ==, "foo"); @@ -248,7 +248,7 @@ static void test_visitor_in_struct_nested(TestInputVisitorData *data, v = visitor_input_test_init(data, "{ 'string0': 'string0', 'dict1': { 'string1': 'string1', 'dict2': { 'userdef1': { 'integer': 42, 'string': 'string' }, 'string2': 'string2'}}}"); visit_type_UserDefNested(v, &udp, NULL, &errp); - g_assert(!error_is_set(&errp)); + g_assert(!errp); check_and_free_str(udp->string0, "string0"); check_and_free_str(udp->dict1.string1, "string1"); @@ -272,7 +272,7 @@ static void test_visitor_in_list(TestInputVisitorData *data, v = visitor_input_test_init(data, "[ { 'string': 'string0', 'integer': 42 }, { 'string': 'string1', 'integer': 43 }, { 'string': 'string2', 'integer': 44 } ]"); visit_type_UserDefOneList(v, &head, NULL, &errp); - g_assert(!error_is_set(&errp)); + g_assert(!errp); g_assert(head != NULL); for (i = 0, item = head; item; item = item->next, i++) { @@ -601,7 +601,7 @@ static void test_visitor_in_errors(TestInputVisitorData *data, v = visitor_input_test_init(data, "{ 'integer': false, 'boolean': 'foo', 'string': -42 }"); visit_type_TestStruct(v, &p, NULL, &errp); - g_assert(error_is_set(&errp)); + g_assert(errp); g_assert(p->string == NULL); error_free(errp); diff --git a/tests/test-qmp-output-visitor.c b/tests/test-qmp-output-visitor.c index e073d833bf..f31d168d63 100644 --- a/tests/test-qmp-output-visitor.c +++ b/tests/test-qmp-output-visitor.c @@ -49,7 +49,7 @@ static void test_visitor_out_int(TestOutputVisitorData *data, QObject *obj; visit_type_int(data->ov, &value, NULL, &errp); - g_assert(error_is_set(&errp) == 0); + g_assert(!errp); obj = qmp_output_get_qobject(data->qov); g_assert(obj != NULL); @@ -67,7 +67,7 @@ static void test_visitor_out_bool(TestOutputVisitorData *data, QObject *obj; visit_type_bool(data->ov, &value, NULL, &errp); - g_assert(error_is_set(&errp) == 0); + g_assert(!errp); obj = qmp_output_get_qobject(data->qov); g_assert(obj != NULL); @@ -85,7 +85,7 @@ static void test_visitor_out_number(TestOutputVisitorData *data, QObject *obj; visit_type_number(data->ov, &value, NULL, &errp); - g_assert(error_is_set(&errp) == 0); + g_assert(!errp); obj = qmp_output_get_qobject(data->qov); g_assert(obj != NULL); @@ -103,7 +103,7 @@ static void test_visitor_out_string(TestOutputVisitorData *data, QObject *obj; visit_type_str(data->ov, &string, NULL, &errp); - g_assert(error_is_set(&errp) == 0); + g_assert(!errp); obj = qmp_output_get_qobject(data->qov); g_assert(obj != NULL); @@ -122,7 +122,7 @@ static void test_visitor_out_no_string(TestOutputVisitorData *data, /* A null string should return "" */ visit_type_str(data->ov, &string, NULL, &errp); - g_assert(error_is_set(&errp) == 0); + g_assert(!errp); obj = qmp_output_get_qobject(data->qov); g_assert(obj != NULL); @@ -141,7 +141,7 @@ static void test_visitor_out_enum(TestOutputVisitorData *data, for (i = 0; i < ENUM_ONE_MAX; i++) { visit_type_EnumOne(data->ov, &i, "unused", &errp); - g_assert(!error_is_set(&errp)); + g_assert(!errp); obj = qmp_output_get_qobject(data->qov); g_assert(obj != NULL); @@ -161,7 +161,7 @@ static void test_visitor_out_enum_errors(TestOutputVisitorData *data, for (i = 0; i < ARRAY_SIZE(bad_values) ; i++) { errp = NULL; visit_type_EnumOne(data->ov, &bad_values[i], "unused", &errp); - g_assert(error_is_set(&errp) == true); + g_assert(errp); error_free(errp); } } @@ -198,7 +198,7 @@ static void test_visitor_out_struct(TestOutputVisitorData *data, QDict *qdict; visit_type_TestStruct(data->ov, &p, NULL, &errp); - g_assert(!error_is_set(&errp)); + g_assert(!errp); obj = qmp_output_get_qobject(data->qov); g_assert(obj != NULL); @@ -241,7 +241,7 @@ static void test_visitor_out_struct_nested(TestOutputVisitorData *data, ud2->dict1.dict3.string3 = g_strdup(strings[3]); visit_type_UserDefNested(data->ov, &ud2, "unused", &errp); - g_assert(!error_is_set(&errp)); + g_assert(!errp); obj = qmp_output_get_qobject(data->qov); g_assert(obj != NULL); @@ -288,7 +288,7 @@ static void test_visitor_out_struct_errors(TestOutputVisitorData *data, u.has_enum1 = true; u.enum1 = bad_values[i]; visit_type_UserDefOne(data->ov, &pu, "unused", &errp); - g_assert(error_is_set(&errp) == true); + g_assert(errp); error_free(errp); } } @@ -343,7 +343,7 @@ static void test_visitor_out_list(TestOutputVisitorData *data, } visit_type_TestStructList(data->ov, &head, NULL, &errp); - g_assert(!error_is_set(&errp)); + g_assert(!errp); obj = qmp_output_get_qobject(data->qov); g_assert(obj != NULL); diff --git a/tests/test-string-input-visitor.c b/tests/test-string-input-visitor.c index 5989f8118e..d406263aee 100644 --- a/tests/test-string-input-visitor.c +++ b/tests/test-string-input-visitor.c @@ -60,7 +60,7 @@ static void test_visitor_in_int(TestInputVisitorData *data, v = visitor_input_test_init(data, "-42"); visit_type_int(v, &res, NULL, &errp); - g_assert(!error_is_set(&errp)); + g_assert(!errp); g_assert_cmpint(res, ==, value); } @@ -74,42 +74,42 @@ static void test_visitor_in_bool(TestInputVisitorData *data, v = visitor_input_test_init(data, "true"); visit_type_bool(v, &res, NULL, &errp); - g_assert(!error_is_set(&errp)); + g_assert(!errp); g_assert_cmpint(res, ==, true); visitor_input_teardown(data, unused); v = visitor_input_test_init(data, "yes"); visit_type_bool(v, &res, NULL, &errp); - g_assert(!error_is_set(&errp)); + g_assert(!errp); g_assert_cmpint(res, ==, true); visitor_input_teardown(data, unused); v = visitor_input_test_init(data, "on"); visit_type_bool(v, &res, NULL, &errp); - g_assert(!error_is_set(&errp)); + g_assert(!errp); g_assert_cmpint(res, ==, true); visitor_input_teardown(data, unused); v = visitor_input_test_init(data, "false"); visit_type_bool(v, &res, NULL, &errp); - g_assert(!error_is_set(&errp)); + g_assert(!errp); g_assert_cmpint(res, ==, false); visitor_input_teardown(data, unused); v = visitor_input_test_init(data, "no"); visit_type_bool(v, &res, NULL, &errp); - g_assert(!error_is_set(&errp)); + g_assert(!errp); g_assert_cmpint(res, ==, false); visitor_input_teardown(data, unused); v = visitor_input_test_init(data, "off"); visit_type_bool(v, &res, NULL, &errp); - g_assert(!error_is_set(&errp)); + g_assert(!errp); g_assert_cmpint(res, ==, false); } @@ -123,7 +123,7 @@ static void test_visitor_in_number(TestInputVisitorData *data, v = visitor_input_test_init(data, "3.14"); visit_type_number(v, &res, NULL, &errp); - g_assert(!error_is_set(&errp)); + g_assert(!errp); g_assert_cmpfloat(res, ==, value); } @@ -137,7 +137,7 @@ static void test_visitor_in_string(TestInputVisitorData *data, v = visitor_input_test_init(data, value); visit_type_str(v, &res, NULL, &errp); - g_assert(!error_is_set(&errp)); + g_assert(!errp); g_assert_cmpstr(res, ==, value); g_free(res); @@ -156,7 +156,7 @@ static void test_visitor_in_enum(TestInputVisitorData *data, v = visitor_input_test_init(data, EnumOne_lookup[i]); visit_type_EnumOne(v, &res, NULL, &errp); - g_assert(!error_is_set(&errp)); + g_assert(!errp); g_assert_cmpint(i, ==, res); visitor_input_teardown(data, NULL); diff --git a/tests/test-string-output-visitor.c b/tests/test-string-output-visitor.c index 56cc21d078..22363d100f 100644 --- a/tests/test-string-output-visitor.c +++ b/tests/test-string-output-visitor.c @@ -49,7 +49,7 @@ static void test_visitor_out_int(TestOutputVisitorData *data, char *str; visit_type_int(data->ov, &value, NULL, &errp); - g_assert(error_is_set(&errp) == 0); + g_assert(!errp); str = string_output_get_string(data->sov); g_assert(str != NULL); @@ -65,7 +65,7 @@ static void test_visitor_out_bool(TestOutputVisitorData *data, char *str; visit_type_bool(data->ov, &value, NULL, &errp); - g_assert(error_is_set(&errp) == 0); + g_assert(!errp); str = string_output_get_string(data->sov); g_assert(str != NULL); @@ -81,7 +81,7 @@ static void test_visitor_out_number(TestOutputVisitorData *data, char *str; visit_type_number(data->ov, &value, NULL, &errp); - g_assert(error_is_set(&errp) == 0); + g_assert(!errp); str = string_output_get_string(data->sov); g_assert(str != NULL); @@ -97,7 +97,7 @@ static void test_visitor_out_string(TestOutputVisitorData *data, char *str; visit_type_str(data->ov, &string, NULL, &errp); - g_assert(error_is_set(&errp) == 0); + g_assert(!errp); str = string_output_get_string(data->sov); g_assert(str != NULL); @@ -114,7 +114,7 @@ static void test_visitor_out_no_string(TestOutputVisitorData *data, /* A null string should return "" */ visit_type_str(data->ov, &string, NULL, &errp); - g_assert(error_is_set(&errp) == 0); + g_assert(!errp); str = string_output_get_string(data->sov); g_assert(str != NULL); @@ -131,7 +131,7 @@ static void test_visitor_out_enum(TestOutputVisitorData *data, for (i = 0; i < ENUM_ONE_MAX; i++) { visit_type_EnumOne(data->ov, &i, "unused", &errp); - g_assert(!error_is_set(&errp)); + g_assert(!errp); str = string_output_get_string(data->sov); g_assert(str != NULL); @@ -149,7 +149,7 @@ static void test_visitor_out_enum_errors(TestOutputVisitorData *data, for (i = 0; i < ARRAY_SIZE(bad_values) ; i++) { errp = NULL; visit_type_EnumOne(data->ov, &bad_values[i], "unused", &errp); - g_assert(error_is_set(&errp) == true); + g_assert(errp); error_free(errp); } } @@ -161,7 +161,7 @@ static int configure_tpm(QemuOpts *opts) /* validate backend specific opts */ qemu_opts_validate(opts, be->opts, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { qerror_report_err(local_err); error_free(local_err); return 1; diff --git a/util/qemu-config.c b/util/qemu-config.c index 9298f55ecf..797df71569 100644 --- a/util/qemu-config.c +++ b/util/qemu-config.c @@ -31,7 +31,7 @@ QemuOptsList *qemu_find_opts(const char *group) Error *local_err = NULL; ret = find_list(vm_config_groups, group, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { error_report("%s", error_get_pretty(local_err)); error_free(local_err); } @@ -295,7 +295,7 @@ int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname) if (sscanf(line, "[%63s \"%63[^\"]\"]", group, id) == 2) { /* group with id */ list = find_list(lists, group, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { error_report("%s", error_get_pretty(local_err)); error_free(local_err); goto out; @@ -306,7 +306,7 @@ int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname) if (sscanf(line, "[%63[^]]]", group) == 1) { /* group without id */ list = find_list(lists, group, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { error_report("%s", error_get_pretty(local_err)); error_free(local_err); goto out; @@ -376,13 +376,13 @@ static void config_parse_qdict_section(QDict *options, QemuOptsList *opts, } subopts = qemu_opts_create(opts, NULL, 0, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { error_propagate(errp, local_err); goto out; } qemu_opts_absorb_qdict(subopts, subqdict, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { error_propagate(errp, local_err); goto out; } @@ -416,13 +416,13 @@ static void config_parse_qdict_section(QDict *options, QemuOptsList *opts, opt_name = g_strdup_printf("%s.%u", opts->name, i++); subopts = qemu_opts_create(opts, opt_name, 1, &local_err); g_free(opt_name); - if (error_is_set(&local_err)) { + if (local_err) { error_propagate(errp, local_err); goto out; } qemu_opts_absorb_qdict(subopts, section, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { error_propagate(errp, local_err); qemu_opts_del(subopts); goto out; @@ -450,7 +450,7 @@ void qemu_config_parse_qdict(QDict *options, QemuOptsList **lists, for (i = 0; lists[i]; i++) { config_parse_qdict_section(options, lists[i], &local_err); - if (error_is_set(&local_err)) { + if (local_err) { error_propagate(errp, local_err); return; } diff --git a/util/qemu-option.c b/util/qemu-option.c index 668e5d919f..fd76cd2ada 100644 --- a/util/qemu-option.c +++ b/util/qemu-option.c @@ -246,7 +246,7 @@ int set_option_parameter(QEMUOptionParameter *list, const char *name, switch (list->type) { case OPT_FLAG: parse_option_bool(name, value, &flag, &local_err); - if (!error_is_set(&local_err)) { + if (!local_err) { list->value.n = flag; } break; @@ -269,7 +269,7 @@ int set_option_parameter(QEMUOptionParameter *list, const char *name, return -1; } - if (error_is_set(&local_err)) { + if (local_err) { qerror_report_err(local_err); error_free(local_err); return -1; @@ -640,7 +640,7 @@ static void opt_set(QemuOpts *opts, const char *name, const char *value, opt->desc = desc; opt->str = g_strdup(value); qemu_opt_parse(opt, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { error_propagate(errp, local_err); qemu_opt_del(opt); } @@ -651,7 +651,7 @@ int qemu_opt_set(QemuOpts *opts, const char *name, const char *value) Error *local_err = NULL; opt_set(opts, name, value, false, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { qerror_report_err(local_err); error_free(local_err); return -1; @@ -812,7 +812,7 @@ int qemu_opts_set(QemuOptsList *list, const char *id, Error *local_err = NULL; opts = qemu_opts_create(list, id, 1, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { qerror_report_err(local_err); error_free(local_err); return -1; @@ -897,7 +897,7 @@ static int opts_do_parse(QemuOpts *opts, const char *params, if (strcmp(option, "id") != 0) { /* store and parse */ opt_set(opts, option, value, prepend, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { qerror_report_err(local_err); error_free(local_err); return -1; @@ -945,7 +945,7 @@ static QemuOpts *opts_parse(QemuOptsList *list, const char *params, assert(!defaults || list->merge_lists); opts = qemu_opts_create(list, id, !defaults, &local_err); if (opts == NULL) { - if (error_is_set(&local_err)) { + if (local_err) { qerror_report_err(local_err); error_free(local_err); } @@ -1034,7 +1034,7 @@ QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict, opts = qemu_opts_create(list, qdict_get_try_str(qdict, "id"), 1, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { error_propagate(errp, local_err); return NULL; } @@ -1044,7 +1044,7 @@ QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict, state.errp = &local_err; state.opts = opts; qdict_iter(qdict, qemu_opts_from_qdict_1, &state); - if (error_is_set(&local_err)) { + if (local_err) { error_propagate(errp, local_err); qemu_opts_del(opts); return NULL; @@ -1075,7 +1075,7 @@ void qemu_opts_absorb_qdict(QemuOpts *opts, QDict *qdict, Error **errp) if (find_desc_by_name(opts->list->desc, entry->key)) { qemu_opts_from_qdict_1(entry->key, entry->value, &state); - if (error_is_set(&local_err)) { + if (local_err) { error_propagate(errp, local_err); return; } else { @@ -1129,7 +1129,7 @@ void qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc, Error **errp) } qemu_opt_parse(opt, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { error_propagate(errp, local_err); return; } @@ -27,64 +27,13 @@ #include <time.h> #include <errno.h> #include <sys/time.h> -#include <zlib.h> -#include "qemu/bitmap.h" -/* Needed early for CONFIG_BSD etc. */ #include "config-host.h" -#ifndef _WIN32 -#include <libgen.h> -#include <sys/times.h> -#include <sys/wait.h> -#include <termios.h> -#include <sys/mman.h> -#include <sys/ioctl.h> -#include <sys/resource.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <net/if.h> -#include <arpa/inet.h> -#include <dirent.h> -#include <netdb.h> -#include <sys/select.h> - -#ifdef CONFIG_BSD -#include <sys/stat.h> -#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) -#include <sys/sysctl.h> -#else -#include <util.h> -#endif -#else -#ifdef __linux__ -#include <malloc.h> - -#include <linux/ppdev.h> -#include <linux/parport.h> -#endif - #ifdef CONFIG_SECCOMP #include "sysemu/seccomp.h" #endif -#ifdef __sun__ -#include <sys/stat.h> -#include <sys/ethernet.h> -#include <sys/sockio.h> -#include <netinet/arp.h> -#include <netinet/in_systm.h> -#include <netinet/ip.h> -#include <netinet/ip_icmp.h> // must come after ip.h -#include <netinet/udp.h> -#include <netinet/tcp.h> -#include <net/if.h> -#include <syslog.h> -#include <stropts.h> -#endif -#endif -#endif - #if defined(CONFIG_VDE) #include <libvdeplug.h> #endif @@ -135,6 +84,7 @@ int main(int argc, char **argv) #include "exec/gdbstub.h" #include "qemu/timer.h" #include "sysemu/char.h" +#include "qemu/bitmap.h" #include "qemu/cache-utils.h" #include "sysemu/blockdev.h" #include "hw/block/block.h" @@ -172,9 +122,6 @@ int main(int argc, char **argv) #include "qapi/string-input-visitor.h" #include "qom/object_interfaces.h" -//#define DEBUG_NET -//#define DEBUG_SLIRP - #define DEFAULT_RAM_SIZE 128 #define MAX_VIRTIO_CONSOLES 1 @@ -2321,7 +2268,7 @@ static int chardev_init_func(QemuOpts *opts, void *opaque) Error *local_err = NULL; qemu_chr_new_from_opts(opts, NULL, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { error_report("%s", error_get_pretty(local_err)); error_free(local_err); return -1; |