diff options
227 files changed, 4097 insertions, 1843 deletions
diff --git a/.gitignore b/.gitignore index 6e74d63ea5..ef7019f35d 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,8 @@ /trace/generated-tracers.dtrace /trace/generated-events.h /trace/generated-events.c +/trace/generated-ust-provider.h +/trace/generated-ust.c /libcacard/trace/generated-tracers.c *-timestamp /*-softmmu @@ -57,6 +57,11 @@ GENERATED_HEADERS += trace/generated-tracers-dtrace.h endif GENERATED_SOURCES += trace/generated-tracers.c +ifeq ($(TRACE_BACKEND),ust) +GENERATED_HEADERS += trace/generated-ust-provider.h +GENERATED_SOURCES += trace/generated-ust.c +endif + # Don't try to regenerate Makefile or configure # We don't generate any of them Makefile: ; @@ -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; @@ -916,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); @@ -1037,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; @@ -1406,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; @@ -1414,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; @@ -5340,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 c97c04060d..f8e496f8ef 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -1127,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; 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.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/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 dfb5ec7529..3cc8cda2bd 100644 --- a/blockdev.c +++ b/blockdev.c @@ -330,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,7 +437,7 @@ 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) { on_write_error = parse_block_error_action(buf, 0, &error); - if (error_is_set(&error)) { + if (error) { error_propagate(errp, error); goto early_err; } @@ -446,7 +446,7 @@ 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) { on_read_error = parse_block_error_action(buf, 1, &error); - if (error_is_set(&error)) { + if (error) { error_propagate(errp, error); goto early_err; } @@ -691,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; @@ -779,6 +779,10 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type) translation = BIOS_ATA_TRANSLATION_NONE; } else if (!strcmp(value, "lba")) { translation = BIOS_ATA_TRANSLATION_LBA; + } else if (!strcmp(value, "large")) { + translation = BIOS_ATA_TRANSLATION_LARGE; + } else if (!strcmp(value, "rechs")) { + translation = BIOS_ATA_TRANSLATION_RECHS; } else if (!strcmp(value, "auto")) { translation = BIOS_ATA_TRANSLATION_AUTO; } else { @@ -899,13 +903,13 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type) /* Actual block device init: Functionality shared with blockdev-add */ dinfo = blockdev_init(filename, bs_opts, &local_err); 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 */ @@ -1042,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; } @@ -1055,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; } @@ -1269,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; } @@ -1314,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; } @@ -1383,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; @@ -1475,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; } @@ -1556,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; } @@ -1621,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; } @@ -1758,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; } @@ -1851,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; } @@ -2009,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; } @@ -2150,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; } @@ -2289,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; } @@ -2300,7 +2304,7 @@ void qmp_blockdev_add(BlockdevOptions *options, Error **errp) qdict_flatten(qdict); blockdev_init(NULL, qdict, &local_err); - if (error_is_set(&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; } @@ -1331,6 +1331,35 @@ else error_exit "\"$cc\" either does not exist or does not work" fi +# Check that the C++ compiler exists and works with the C compiler +if has $cxx; then + cat > $TMPC <<EOF +int c_function(void); +int main(void) { return c_function(); } +EOF + + compile_object + + cat > $TMPC <<EOF +extern "C" { + int c_function(void); +} +int c_function(void) { return 42; } +EOF + + if (cc=$cxx do_cc $QEMU_CFLAGS -o $TMPE $TMPC $TMPO $LDFLAGS); then + # C++ compiler $cxx works ok with C compiler $cc + : + else + echo "C++ compiler $cxx does not work with C compiler $cc" + echo "Disabling C++ specific optional code" + cxx= + fi +else + echo "No C++ compiler available; disabling C++ specific optional code" + cxx= +fi + # Consult white-list to determine whether to enable werror # by default. Only enable by default for git builds z_version=`cut -f3 -d. $source_path/VERSION` @@ -3452,15 +3481,25 @@ fi # For 'ust' backend, test if ust headers are present if test "$trace_backend" = "ust"; then cat > $TMPC << EOF -#include <ust/tracepoint.h> -#include <ust/marker.h> +#include <lttng/tracepoint.h> int main(void) { return 0; } EOF if compile_prog "" "" ; then - LIBS="-lust -lurcu-bp $LIBS" - libs_qga="-lust -lurcu-bp $libs_qga" + if $pkg_config lttng-ust --exists; then + lttng_ust_libs=`$pkg_config --libs lttng-ust` + else + lttng_ust_libs="-llttng-ust" + fi + if $pkg_config liburcu-bp --exists; then + urcu_bp_libs=`$pkg_config --libs liburcu-bp` + else + urcu_bp_libs="-lurcu-bp" + fi + + LIBS="$lttng_ust_libs $urcu_bp_libs $LIBS" + libs_qga="$lttng_ust_libs $urcu_bp_libs $libs_qga" else - error_exit "Trace backend 'ust' missing libust header files" + error_exit "Trace backend 'ust' missing lttng-ust header files" fi fi @@ -3637,7 +3676,18 @@ cpuid_h=no cat > $TMPC << EOF #include <cpuid.h> int main(void) { - return 0; + unsigned a, b, c, d; + int max = __get_cpuid_max(0, 0); + + if (max >= 1) { + __cpuid(1, a, b, c, d); + } + + if (max >= 7) { + __cpuid_count(7, 0, a, b, c, d); + } + + return 0; } EOF if compile_prog "" "" ; then diff --git a/default-configs/ppc-softmmu.mak b/default-configs/ppc-softmmu.mak index f380ca47d7..e5f9d36913 100644 --- a/default-configs/ppc-softmmu.mak +++ b/default-configs/ppc-softmmu.mak @@ -42,6 +42,7 @@ CONFIG_XILINX=y CONFIG_XILINX_ETHLITE=y CONFIG_OPENPIC=y CONFIG_PREP=y +CONFIG_MAC=y CONFIG_E500=y CONFIG_OPENPIC_KVM=$(and $(CONFIG_E500),$(CONFIG_KVM)) # For PReP diff --git a/default-configs/ppc64-softmmu.mak b/default-configs/ppc64-softmmu.mak index fcc04529b4..e2beac6df1 100644 --- a/default-configs/ppc64-softmmu.mak +++ b/default-configs/ppc64-softmmu.mak @@ -43,6 +43,7 @@ CONFIG_XILINX_ETHLITE=y CONFIG_OPENPIC=y CONFIG_PSERIES=y CONFIG_PREP=y +CONFIG_MAC=y CONFIG_E500=y CONFIG_OPENPIC_KVM=$(and $(CONFIG_E500),$(CONFIG_KVM)) # For pSeries diff --git a/default-configs/ppcemb-softmmu.mak b/default-configs/ppcemb-softmmu.mak index fdf1e14a95..1e4fde2190 100644 --- a/default-configs/ppcemb-softmmu.mak +++ b/default-configs/ppcemb-softmmu.mak @@ -3,30 +3,12 @@ include pci.mak include sound.mak include usb.mak -CONFIG_ISA_MMIO=y -CONFIG_ESCC=y CONFIG_M48T59=y CONFIG_VGA=y CONFIG_VGA_PCI=y CONFIG_SERIAL=y -CONFIG_I8254=y -CONFIG_FDC=y CONFIG_I8257=y CONFIG_OPENPIC=y -CONFIG_MACIO=y -CONFIG_CUDA=y -CONFIG_ADB=y -CONFIG_MAC_NVRAM=y -CONFIG_MAC_DBDMA=y -CONFIG_HEATHROW_PIC=y -CONFIG_GRACKLE_PCI=y -CONFIG_UNIN_PCI=y -CONFIG_DEC_PCI=y -CONFIG_PPCE500_PCI=y -CONFIG_IDE_ISA=y -CONFIG_IDE_CMD646=y -CONFIG_IDE_MACIO=y -CONFIG_NE2000_ISA=y CONFIG_PFLASH_CFI01=y CONFIG_PFLASH_CFI02=y CONFIG_PTIMER=y @@ -34,5 +16,3 @@ CONFIG_I8259=y CONFIG_XILINX=y CONFIG_XILINX_ETHLITE=y CONFIG_OPENPIC=y -CONFIG_E500=y -CONFIG_OPENPIC_KVM=$(and $(CONFIG_E500),$(CONFIG_KVM)) diff --git a/disas/i386.c b/disas/i386.c index 044e02c032..00ceca9c51 100644 --- a/disas/i386.c +++ b/disas/i386.c @@ -171,6 +171,7 @@ static void print_operand_value (char *buf, size_t bufsize, int hex, bfd_vma dis static void print_displacement (char *, bfd_vma); static void OP_E (int, int); static void OP_G (int, int); +static void OP_vvvv (int, int); static bfd_vma get64 (void); static bfd_signed_vma get32 (void); static bfd_signed_vma get32s (void); @@ -264,6 +265,9 @@ static int rex_used; current instruction. */ static int used_prefixes; +/* The VEX.vvvv register, unencoded. */ +static int vex_reg; + /* Flags stored in PREFIXES. */ #define PREFIX_REPZ 1 #define PREFIX_REPNZ 2 @@ -278,6 +282,10 @@ static int used_prefixes; #define PREFIX_ADDR 0x400 #define PREFIX_FWAIT 0x800 +#define PREFIX_VEX_0F 0x1000 +#define PREFIX_VEX_0F38 0x2000 +#define PREFIX_VEX_0F3A 0x4000 + /* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive) to ADDR (exclusive) are valid. Returns 1 for success, longjmps on error. */ @@ -323,6 +331,7 @@ fetch_data(struct disassemble_info *info, bfd_byte *addr) #define XX { NULL, 0 } +#define Bv { OP_vvvv, v_mode } #define Eb { OP_E, b_mode } #define Ev { OP_E, v_mode } #define Ed { OP_E, d_mode } @@ -671,7 +680,8 @@ fetch_data(struct disassemble_info *info, bfd_byte *addr) #define PREGRP102 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 102 } } #define PREGRP103 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 103 } } #define PREGRP104 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 104 } } - +#define PREGRP105 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 105 } } +#define PREGRP106 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 106 } } #define X86_64_0 NULL, { { NULL, X86_64_SPECIAL }, { NULL, 0 } } #define X86_64_1 NULL, { { NULL, X86_64_SPECIAL }, { NULL, 1 } } @@ -1449,7 +1459,7 @@ static const unsigned char threebyte_0x38_uses_DATA_prefix[256] = { /* c0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* cf */ /* d0 */ 0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1, /* df */ /* e0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ef */ - /* f0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ff */ + /* f0 */ 0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, /* ff */ /* ------------------------------- */ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ }; @@ -1473,7 +1483,7 @@ static const unsigned char threebyte_0x38_uses_REPNZ_prefix[256] = { /* c0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* cf */ /* d0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* df */ /* e0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ef */ - /* f0 */ 1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ff */ + /* f0 */ 1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0, /* ff */ /* ------------------------------- */ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ }; @@ -1497,7 +1507,7 @@ static const unsigned char threebyte_0x38_uses_REPZ_prefix[256] = { /* c0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* cf */ /* d0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* df */ /* e0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ef */ - /* f0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ff */ + /* f0 */ 0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, /* ff */ /* ------------------------------- */ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ }; @@ -2774,6 +2784,22 @@ static const struct dis386 prefix_user_table[][4] = { { "(bad)", { XX } }, }, + /* PREGRP105 */ + { + { "andnS", { Gv, Bv, Ev } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + }, + + /* PREGRP106 */ + { + { "bextrS", { Gv, Ev, Bv } }, + { "sarxS", { Gv, Ev, Bv } }, + { "shlxS", { Gv, Ev, Bv } }, + { "shrxS", { Gv, Ev, Bv } }, + }, + }; static const struct dis386 x86_64_table[][2] = { @@ -3071,12 +3097,12 @@ static const struct dis386 three_byte_table[][256] = { /* f0 */ { PREGRP87 }, { PREGRP88 }, + { PREGRP105 }, { "(bad)", { XX } }, { "(bad)", { XX } }, { "(bad)", { XX } }, { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, + { PREGRP106 }, /* f8 */ { "(bad)", { XX } }, { "(bad)", { XX } }, @@ -3477,6 +3503,74 @@ ckprefix (void) } } +static void +ckvexprefix (void) +{ + int op, vex2, vex3, newrex = 0, newpfx = prefixes; + + if (address_mode == mode_16bit) { + return; + } + + fetch_data(the_info, codep + 1); + op = *codep; + + if (op != 0xc4 && op != 0xc5) { + return; + } + + fetch_data(the_info, codep + 2); + vex2 = codep[1]; + + if (address_mode == mode_32bit && (vex2 & 0xc0) != 0xc0) { + return; + } + + if (op == 0xc4) { + /* Three byte VEX prefix. */ + fetch_data(the_info, codep + 3); + vex3 = codep[2]; + + newrex |= (vex2 & 0x80 ? 0 : REX_R); + newrex |= (vex2 & 0x40 ? 0 : REX_X); + newrex |= (vex2 & 0x20 ? 0 : REX_B); + newrex |= (vex3 & 0x80 ? REX_W : 0); + switch (vex2 & 0x1f) { /* VEX.m-mmmm */ + case 1: + newpfx |= PREFIX_VEX_0F; + break; + case 2: + newpfx |= PREFIX_VEX_0F | PREFIX_VEX_0F38; + break; + case 3: + newpfx |= PREFIX_VEX_0F | PREFIX_VEX_0F3A; + break; + } + vex2 = vex3; + codep += 3; + } else { + /* Two byte VEX prefix. */ + newrex |= (vex2 & 0x80 ? 0 : REX_R); + codep += 2; + } + + vex_reg = (~vex2 >> 3) & 15; /* VEX.vvvv */ + switch (vex2 & 3) { /* VEX.pp */ + case 1: + newpfx |= PREFIX_DATA; /* 0x66 */ + break; + case 2: + newpfx |= PREFIX_REPZ; /* 0xf3 */ + break; + case 3: + newpfx |= PREFIX_REPNZ; /* 0xf2 */ + break; + } + + rex = newrex; + prefixes = newpfx; +} + /* Return the name of the prefix byte PREF, or NULL if PREF is not a prefix byte. */ @@ -3598,6 +3692,7 @@ print_insn (bfd_vma pc, disassemble_info *info) const char *p; struct dis_private priv; unsigned char op; + unsigned char threebyte; if (info->mach == bfd_mach_x86_64_intel_syntax || info->mach == bfd_mach_x86_64) @@ -3752,6 +3847,7 @@ print_insn (bfd_vma pc, disassemble_info *info) obufp = obuf; ckprefix (); + ckvexprefix (); insn_codep = codep; sizeflag = priv.orig_sizeflag; @@ -3775,18 +3871,29 @@ print_insn (bfd_vma pc, disassemble_info *info) } op = 0; + if (prefixes & PREFIX_VEX_0F) + { + used_prefixes |= PREFIX_VEX_0F | PREFIX_VEX_0F38 | PREFIX_VEX_0F3A; + if (prefixes & PREFIX_VEX_0F38) + threebyte = 0x38; + else if (prefixes & PREFIX_VEX_0F3A) + threebyte = 0x3a; + else + threebyte = *codep++; + goto vex_opcode; + } if (*codep == 0x0f) { - unsigned char threebyte; fetch_data(info, codep + 2); - threebyte = *++codep; + threebyte = codep[1]; + codep += 2; + vex_opcode: dp = &dis386_twobyte[threebyte]; - need_modrm = twobyte_has_modrm[*codep]; - uses_DATA_prefix = twobyte_uses_DATA_prefix[*codep]; - uses_REPNZ_prefix = twobyte_uses_REPNZ_prefix[*codep]; - uses_REPZ_prefix = twobyte_uses_REPZ_prefix[*codep]; - uses_LOCK_prefix = (*codep & ~0x02) == 0x20; - codep++; + need_modrm = twobyte_has_modrm[threebyte]; + uses_DATA_prefix = twobyte_uses_DATA_prefix[threebyte]; + uses_REPNZ_prefix = twobyte_uses_REPNZ_prefix[threebyte]; + uses_REPZ_prefix = twobyte_uses_REPZ_prefix[threebyte]; + uses_LOCK_prefix = (threebyte & ~0x02) == 0x20; if (dp->name == NULL && dp->op[0].bytemode == IS_3BYTE_OPCODE) { fetch_data(info, codep + 2); @@ -5291,6 +5398,17 @@ OP_G (int bytemode, int sizeflag) } } +static void +OP_vvvv (int bytemode, int sizeflags) +{ + USED_REX (REX_W); + if (rex & REX_W) { + oappend(names64[vex_reg]); + } else { + oappend(names32[vex_reg]); + } +} + static bfd_vma get64 (void) { diff --git a/docs/tracing.txt b/docs/tracing.txt index bfc261bcaf..bf2e15ce30 100644 --- a/docs/tracing.txt +++ b/docs/tracing.txt @@ -214,6 +214,42 @@ The "ust" backend uses the LTTng Userspace Tracer library. There are no monitor commands built into QEMU, instead UST utilities should be used to list, enable/disable, and dump traces. +Package lttng-tools is required for userspace tracing. You must ensure that the +current user belongs to the "tracing" group, or manually launch the +lttng-sessiond daemon for the current user prior to running any instance of +QEMU. + +While running an instrumented QEMU, LTTng should be able to list all available +events: + + lttng list -u + +Create tracing session: + + lttng create mysession + +Enable events: + + lttng enable-event qemu:g_malloc -u + +Where the events can either be a comma-separated list of events, or "-a" to +enable all tracepoint events. Start and stop tracing as needed: + + lttng start + lttng stop + +View the trace: + + lttng view + +Destroy tracing session: + + lttng destroy + +Babeltrace can be used at any later time to view the trace: + + babeltrace $HOME/lttng-traces/mysession-<date>-<time> + === SystemTap === The "dtrace" backend uses DTrace sdt probes but has only been tested with diff --git a/fpu/softfloat.c b/fpu/softfloat.c index e0ea599769..fc0b179df4 100644 --- a/fpu/softfloat.c +++ b/fpu/softfloat.c @@ -2372,6 +2372,17 @@ float32 float32_muladd(float32 a, float32 b, float32 c, int flags STATUS_PARAM) } } /* Zero plus something non-zero : just return the something */ + if (flags & float_muladd_halve_result) { + if (cExp == 0) { + normalizeFloat32Subnormal(cSig, &cExp, &cSig); + } + /* Subtract one to halve, and one again because roundAndPackFloat32 + * wants one less than the true exponent. + */ + cExp -= 2; + cSig = (cSig | 0x00800000) << 7; + return roundAndPackFloat32(cSign ^ signflip, cExp, cSig STATUS_VAR); + } return packFloat32(cSign ^ signflip, cExp, cSig); } @@ -2408,6 +2419,9 @@ float32 float32_muladd(float32 a, float32 b, float32 c, int flags STATUS_PARAM) /* Throw out the special case of c being an exact zero now */ shift64RightJamming(pSig64, 32, &pSig64); pSig = pSig64; + if (flags & float_muladd_halve_result) { + pExp--; + } return roundAndPackFloat32(zSign, pExp - 1, pSig STATUS_VAR); } @@ -2472,6 +2486,10 @@ float32 float32_muladd(float32 a, float32 b, float32 c, int flags STATUS_PARAM) zSig64 <<= shiftcount; zExp -= shiftcount; } + if (flags & float_muladd_halve_result) { + zExp--; + } + shift64RightJamming(zSig64, 32, &zSig64); return roundAndPackFloat32(zSign, zExp, zSig64 STATUS_VAR); } @@ -4088,6 +4106,17 @@ float64 float64_muladd(float64 a, float64 b, float64 c, int flags STATUS_PARAM) } } /* Zero plus something non-zero : just return the something */ + if (flags & float_muladd_halve_result) { + if (cExp == 0) { + normalizeFloat64Subnormal(cSig, &cExp, &cSig); + } + /* Subtract one to halve, and one again because roundAndPackFloat64 + * wants one less than the true exponent. + */ + cExp -= 2; + cSig = (cSig | 0x0010000000000000ULL) << 10; + return roundAndPackFloat64(cSign ^ signflip, cExp, cSig STATUS_VAR); + } return packFloat64(cSign ^ signflip, cExp, cSig); } @@ -4123,6 +4152,9 @@ float64 float64_muladd(float64 a, float64 b, float64 c, int flags STATUS_PARAM) if (!cSig) { /* Throw out the special case of c being an exact zero now */ shift128RightJamming(pSig0, pSig1, 64, &pSig0, &pSig1); + if (flags & float_muladd_halve_result) { + pExp--; + } return roundAndPackFloat64(zSign, pExp - 1, pSig1 STATUS_VAR); } @@ -4159,6 +4191,9 @@ float64 float64_muladd(float64 a, float64 b, float64 c, int flags STATUS_PARAM) zExp--; } shift128RightJamming(zSig0, zSig1, 64, &zSig0, &zSig1); + if (flags & float_muladd_halve_result) { + zExp--; + } return roundAndPackFloat64(zSign, zExp, zSig1 STATUS_VAR); } else { /* Subtraction */ @@ -4209,6 +4244,9 @@ float64 float64_muladd(float64 a, float64 b, float64 c, int flags STATUS_PARAM) zExp -= (shiftcount + 64); } } + if (flags & float_muladd_halve_result) { + zExp--; + } return roundAndPackFloat64(zSign, zExp, zSig0 STATUS_VAR); } } @@ -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/Makefile.objs b/hw/Makefile.objs index d91b9cc6c6..05a00dc401 100644 --- a/hw/Makefile.objs +++ b/hw/Makefile.objs @@ -12,6 +12,7 @@ devices-dirs-$(CONFIG_SOFTMMU) += i2c/ devices-dirs-$(CONFIG_SOFTMMU) += ide/ devices-dirs-$(CONFIG_SOFTMMU) += input/ devices-dirs-$(CONFIG_SOFTMMU) += intc/ +devices-dirs-$(CONFIG_IPACK) += ipack/ devices-dirs-$(CONFIG_SOFTMMU) += isa/ devices-dirs-$(CONFIG_SOFTMMU) += misc/ devices-dirs-$(CONFIG_SOFTMMU) += net/ diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c index 9f21653e94..67dc0752f7 100644 --- a/hw/acpi/piix4.c +++ b/hw/acpi/piix4.c @@ -439,9 +439,9 @@ Object *piix4_pm_find(void) return o; } -i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base, - qemu_irq sci_irq, qemu_irq smi_irq, - int kvm_enabled, FWCfgState *fw_cfg) +I2CBus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base, + qemu_irq sci_irq, qemu_irq smi_irq, + int kvm_enabled, FWCfgState *fw_cfg) { DeviceState *dev; PIIX4PMState *s; diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c index 4ebb9381b0..9f137e9acd 100644 --- a/hw/arm/exynos4210.c +++ b/hw/arm/exynos4210.c @@ -326,7 +326,7 @@ Exynos4210State *exynos4210_init(MemoryRegion *system_mem, busdev = SYS_BUS_DEVICE(dev); sysbus_connect_irq(busdev, 0, i2c_irq); sysbus_mmio_map(busdev, 0, addr); - s->i2c_if[n] = (i2c_bus *)qdev_get_child_bus(dev, "i2c"); + s->i2c_if[n] = (I2CBus *)qdev_get_child_bus(dev, "i2c"); } diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c index 023e8756e2..50a3b8fe4f 100644 --- a/hw/arm/musicpal.c +++ b/hw/arm/musicpal.c @@ -1593,7 +1593,7 @@ static void musicpal_init(QEMUMachineInitArgs *args) DeviceState *key_dev; DeviceState *wm8750_dev; SysBusDevice *s; - i2c_bus *i2c; + I2CBus *i2c; int i; unsigned long flash_size; DriveInfo *dinfo; @@ -1687,7 +1687,7 @@ static void musicpal_init(QEMUMachineInitArgs *args) dev = sysbus_create_simple(TYPE_MUSICPAL_GPIO, MP_GPIO_BASE, pic[MP_GPIO_IRQ]); i2c_dev = sysbus_create_simple("gpio_i2c", -1, NULL); - i2c = (i2c_bus *)qdev_get_child_bus(i2c_dev, "i2c"); + i2c = (I2CBus *)qdev_get_child_bus(i2c_dev, "i2c"); lcd_dev = sysbus_create_simple(TYPE_MUSICPAL_LCD, MP_LCD_BASE, NULL); key_dev = sysbus_create_simple(TYPE_MUSICPAL_KEY, -1, NULL); diff --git a/hw/arm/nseries.c b/hw/arm/nseries.c index 9ef31ca37a..c28f895c7a 100644 --- a/hw/arm/nseries.c +++ b/hw/arm/nseries.c @@ -202,7 +202,7 @@ static void n8x0_i2c_setup(struct n800_s *s) { DeviceState *dev; qemu_irq tmp_irq = qdev_get_gpio_in(s->mpu->gpio, N8X0_TMP105_GPIO); - i2c_bus *i2c = omap_i2c_bus(s->mpu->i2c[0]); + I2CBus *i2c = omap_i2c_bus(s->mpu->i2c[0]); /* Attach a menelaus PM chip */ dev = i2c_create_slave(i2c, "twl92230", N8X0_MENELAUS_ADDR); diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c index 25ec549e71..45a99c819d 100644 --- a/hw/arm/pxa2xx.c +++ b/hw/arm/pxa2xx.c @@ -224,27 +224,24 @@ static const VMStateDescription vmstate_pxa2xx_cm = { } }; -static int pxa2xx_clkcfg_read(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t *value) +static uint64_t pxa2xx_clkcfg_read(CPUARMState *env, const ARMCPRegInfo *ri) { PXA2xxState *s = (PXA2xxState *)ri->opaque; - *value = s->clkcfg; - return 0; + return s->clkcfg; } -static int pxa2xx_clkcfg_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) +static void pxa2xx_clkcfg_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) { PXA2xxState *s = (PXA2xxState *)ri->opaque; s->clkcfg = value & 0xf; if (value & 2) { printf("%s: CPU frequency change attempt\n", __func__); } - return 0; } -static int pxa2xx_pwrmode_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) +static void pxa2xx_pwrmode_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) { PXA2xxState *s = (PXA2xxState *)ri->opaque; static const char *pwrmode[8] = { @@ -310,36 +307,29 @@ static int pxa2xx_pwrmode_write(CPUARMState *env, const ARMCPRegInfo *ri, printf("%s: machine entered %s mode\n", __func__, pwrmode[value & 7]); } - - return 0; } -static int pxa2xx_cppmnc_read(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t *value) +static uint64_t pxa2xx_cppmnc_read(CPUARMState *env, const ARMCPRegInfo *ri) { PXA2xxState *s = (PXA2xxState *)ri->opaque; - *value = s->pmnc; - return 0; + return s->pmnc; } -static int pxa2xx_cppmnc_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) +static void pxa2xx_cppmnc_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) { PXA2xxState *s = (PXA2xxState *)ri->opaque; s->pmnc = value; - return 0; } -static int pxa2xx_cpccnt_read(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t *value) +static uint64_t pxa2xx_cpccnt_read(CPUARMState *env, const ARMCPRegInfo *ri) { PXA2xxState *s = (PXA2xxState *)ri->opaque; if (s->pmnc & 1) { - *value = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); } else { - *value = 0; + return 0; } - return 0; } static const ARMCPRegInfo pxa_cp_reginfo[] = { @@ -1222,8 +1212,14 @@ static const TypeInfo pxa2xx_rtc_sysbus_info = { }; /* I2C Interface */ -typedef struct { - I2CSlave i2c; + +#define TYPE_PXA2XX_I2C_SLAVE "pxa2xx-i2c-slave" +#define PXA2XX_I2C_SLAVE(obj) \ + OBJECT_CHECK(PXA2xxI2CSlaveState, (obj), TYPE_PXA2XX_I2C_SLAVE) + +typedef struct PXA2xxI2CSlaveState { + I2CSlave parent_obj; + PXA2xxI2CState *host; } PXA2xxI2CSlaveState; @@ -1238,7 +1234,7 @@ struct PXA2xxI2CState { MemoryRegion iomem; PXA2xxI2CSlaveState *slave; - i2c_bus *bus; + I2CBus *bus; qemu_irq irq; uint32_t offset; uint32_t region_size; @@ -1268,7 +1264,7 @@ static void pxa2xx_i2c_update(PXA2xxI2CState *s) /* These are only stubs now. */ static void pxa2xx_i2c_event(I2CSlave *i2c, enum i2c_event event) { - PXA2xxI2CSlaveState *slave = FROM_I2C_SLAVE(PXA2xxI2CSlaveState, i2c); + PXA2xxI2CSlaveState *slave = PXA2XX_I2C_SLAVE(i2c); PXA2xxI2CState *s = slave->host; switch (event) { @@ -1292,10 +1288,12 @@ static void pxa2xx_i2c_event(I2CSlave *i2c, enum i2c_event event) static int pxa2xx_i2c_rx(I2CSlave *i2c) { - PXA2xxI2CSlaveState *slave = FROM_I2C_SLAVE(PXA2xxI2CSlaveState, i2c); + PXA2xxI2CSlaveState *slave = PXA2XX_I2C_SLAVE(i2c); PXA2xxI2CState *s = slave->host; - if ((s->control & (1 << 14)) || !(s->control & (1 << 6))) + + if ((s->control & (1 << 14)) || !(s->control & (1 << 6))) { return 0; + } if (s->status & (1 << 0)) { /* RWM */ s->status |= 1 << 6; /* set ITE */ @@ -1307,10 +1305,12 @@ static int pxa2xx_i2c_rx(I2CSlave *i2c) static int pxa2xx_i2c_tx(I2CSlave *i2c, uint8_t data) { - PXA2xxI2CSlaveState *slave = FROM_I2C_SLAVE(PXA2xxI2CSlaveState, i2c); + PXA2xxI2CSlaveState *slave = PXA2XX_I2C_SLAVE(i2c); PXA2xxI2CState *s = slave->host; - if ((s->control & (1 << 14)) || !(s->control & (1 << 6))) + + if ((s->control & (1 << 14)) || !(s->control & (1 << 6))) { return 1; + } if (!(s->status & (1 << 0))) { /* RWM */ s->status |= 1 << 7; /* set IRF */ @@ -1325,6 +1325,7 @@ static uint64_t pxa2xx_i2c_read(void *opaque, hwaddr addr, unsigned size) { PXA2xxI2CState *s = (PXA2xxI2CState *) opaque; + I2CSlave *slave; addr -= s->offset; switch (addr) { @@ -1333,7 +1334,8 @@ static uint64_t pxa2xx_i2c_read(void *opaque, hwaddr addr, case ISR: return s->status | (i2c_bus_busy(s->bus) << 2); case ISAR: - return s->slave->i2c.address; + slave = I2C_SLAVE(s->slave); + return slave->address; case IDBR: return s->data; case IBMR: @@ -1408,7 +1410,7 @@ static void pxa2xx_i2c_write(void *opaque, hwaddr addr, break; case ISAR: - i2c_set_slave_address(&s->slave->i2c, value & 0x7f); + i2c_set_slave_address(I2C_SLAVE(s->slave), value & 0x7f); break; case IDBR: @@ -1432,7 +1434,7 @@ static const VMStateDescription vmstate_pxa2xx_i2c_slave = { .minimum_version_id = 1, .minimum_version_id_old = 1, .fields = (VMStateField []) { - VMSTATE_I2C_SLAVE(i2c, PXA2xxI2CSlaveState), + VMSTATE_I2C_SLAVE(parent_obj, PXA2xxI2CSlaveState), VMSTATE_END_OF_LIST() } }; @@ -1470,7 +1472,7 @@ static void pxa2xx_i2c_slave_class_init(ObjectClass *klass, void *data) } static const TypeInfo pxa2xx_i2c_slave_info = { - .name = "pxa2xx-i2c-slave", + .name = TYPE_PXA2XX_I2C_SLAVE, .parent = TYPE_I2C_SLAVE, .instance_size = sizeof(PXA2xxI2CSlaveState), .class_init = pxa2xx_i2c_slave_class_init, @@ -1482,7 +1484,7 @@ PXA2xxI2CState *pxa2xx_i2c_init(hwaddr base, DeviceState *dev; SysBusDevice *i2c_dev; PXA2xxI2CState *s; - i2c_bus *i2cbus; + I2CBus *i2cbus; dev = qdev_create(NULL, TYPE_PXA2XX_I2C); qdev_prop_set_uint32(dev, "size", region_size + 1); @@ -1496,8 +1498,8 @@ PXA2xxI2CState *pxa2xx_i2c_init(hwaddr base, s = PXA2XX_I2C(i2c_dev); /* FIXME: Should the slave device really be on a separate bus? */ i2cbus = i2c_init_bus(dev, "dummy"); - dev = i2c_create_slave(i2cbus, "pxa2xx-i2c-slave", 0); - s->slave = FROM_I2C_SLAVE(PXA2xxI2CSlaveState, I2C_SLAVE(dev)); + dev = i2c_create_slave(i2cbus, TYPE_PXA2XX_I2C_SLAVE, 0); + s->slave = PXA2XX_I2C_SLAVE(dev); s->slave->host = s; return s; @@ -1518,7 +1520,7 @@ static int pxa2xx_i2c_initfn(SysBusDevice *sbd) return 0; } -i2c_bus *pxa2xx_i2c_bus(PXA2xxI2CState *s) +I2CBus *pxa2xx_i2c_bus(PXA2xxI2CState *s) { return s->bus; } diff --git a/hw/arm/pxa2xx_pic.c b/hw/arm/pxa2xx_pic.c index 46d337cf84..345fa4a491 100644 --- a/hw/arm/pxa2xx_pic.c +++ b/hw/arm/pxa2xx_pic.c @@ -217,20 +217,17 @@ static const int pxa2xx_cp_reg_map[0x10] = { [0xa] = ICPR2, }; -static int pxa2xx_pic_cp_read(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t *value) +static uint64_t pxa2xx_pic_cp_read(CPUARMState *env, const ARMCPRegInfo *ri) { int offset = pxa2xx_cp_reg_map[ri->crn]; - *value = pxa2xx_pic_mem_read(ri->opaque, offset, 4); - return 0; + return pxa2xx_pic_mem_read(ri->opaque, offset, 4); } -static int pxa2xx_pic_cp_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) +static void pxa2xx_pic_cp_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) { int offset = pxa2xx_cp_reg_map[ri->crn]; pxa2xx_pic_mem_write(ri->opaque, offset, value, 4); - return 0; } #define REGINFO_FOR_PIC_CP(NAME, CRN) \ diff --git a/hw/arm/realview.c b/hw/arm/realview.c index 8d845ddb73..6ef7646002 100644 --- a/hw/arm/realview.c +++ b/hw/arm/realview.c @@ -60,7 +60,7 @@ static void realview_init(QEMUMachineInitArgs *args, qemu_irq mmc_irq[2]; PCIBus *pci_bus = NULL; NICInfo *nd; - i2c_bus *i2c; + I2CBus *i2c; int n; int done_nic = 0; qemu_irq cpu_irq[4]; @@ -255,7 +255,7 @@ static void realview_init(QEMUMachineInitArgs *args, } dev = sysbus_create_simple("versatile_i2c", 0x10002000, NULL); - i2c = (i2c_bus *)qdev_get_child_bus(dev, "i2c"); + i2c = (I2CBus *)qdev_get_child_bus(dev, "i2c"); i2c_create_slave(i2c, "ds1338", 0x68); /* Memory map for RealView Emulation Baseboard: */ diff --git a/hw/arm/spitz.c b/hw/arm/spitz.c index ba172835eb..2decff170f 100644 --- a/hw/arm/spitz.c +++ b/hw/arm/spitz.c @@ -734,7 +734,7 @@ static void spitz_wm8750_addr(void *opaque, int line, int level) static void spitz_i2c_setup(PXA2xxState *cpu) { /* Attach the CPU on one end of our I2C bus. */ - i2c_bus *bus = pxa2xx_i2c_bus(cpu->i2c[0]); + I2CBus *bus = pxa2xx_i2c_bus(cpu->i2c[0]); DeviceState *wm; diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c index 3170d69d42..d6cc77b458 100644 --- a/hw/arm/stellaris.c +++ b/hw/arm/stellaris.c @@ -692,7 +692,7 @@ static int stellaris_sys_init(uint32_t base, qemu_irq irq, typedef struct { SysBusDevice parent_obj; - i2c_bus *bus; + I2CBus *bus; qemu_irq irq; MemoryRegion iomem; uint32_t msa; @@ -868,7 +868,7 @@ static int stellaris_i2c_init(SysBusDevice *sbd) { DeviceState *dev = DEVICE(sbd); stellaris_i2c_state *s = STELLARIS_I2C(dev); - i2c_bus *bus; + I2CBus *bus; sysbus_init_irq(sbd, &s->irq); bus = i2c_init_bus(dev, "i2c"); @@ -1213,7 +1213,7 @@ static void stellaris_init(const char *kernel_filename, const char *cpu_model, qemu_irq adc; int sram_size; int flash_size; - i2c_bus *i2c; + I2CBus *i2c; DeviceState *dev; int i; int j; @@ -1256,7 +1256,7 @@ static void stellaris_init(const char *kernel_filename, const char *cpu_model, if (board->dc2 & (1 << 12)) { dev = sysbus_create_simple(TYPE_STELLARIS_I2C, 0x40020000, pic[8]); - i2c = (i2c_bus *)qdev_get_child_bus(dev, "i2c"); + i2c = (I2CBus *)qdev_get_child_bus(dev, "i2c"); if (board->peripherals & BP_OLED_I2C) { i2c_create_slave(i2c, "ssd0303", 0x3d); } diff --git a/hw/arm/tosa.c b/hw/arm/tosa.c index c00d8c27cc..2069f55432 100644 --- a/hw/arm/tosa.c +++ b/hw/arm/tosa.c @@ -132,15 +132,20 @@ static int tosa_ssp_init(SSISlave *dev) return 0; } +#define TYPE_TOSA_DAC "tosa_dac" +#define TOSA_DAC(obj) OBJECT_CHECK(TosaDACState, (obj), TYPE_TOSA_DAC) + typedef struct { - I2CSlave i2c; + I2CSlave parent_obj; + int len; char buf[3]; } TosaDACState; static int tosa_dac_send(I2CSlave *i2c, uint8_t data) { - TosaDACState *s = FROM_I2C_SLAVE(TosaDACState, i2c); + TosaDACState *s = TOSA_DAC(i2c); + s->buf[s->len] = data; if (s->len ++ > 2) { #ifdef VERBOSE @@ -159,7 +164,8 @@ static int tosa_dac_send(I2CSlave *i2c, uint8_t data) static void tosa_dac_event(I2CSlave *i2c, enum i2c_event event) { - TosaDACState *s = FROM_I2C_SLAVE(TosaDACState, i2c); + TosaDACState *s = TOSA_DAC(i2c); + s->len = 0; switch (event) { case I2C_START_SEND: @@ -194,8 +200,8 @@ static int tosa_dac_init(I2CSlave *i2c) static void tosa_tg_init(PXA2xxState *cpu) { - i2c_bus *bus = pxa2xx_i2c_bus(cpu->i2c[0]); - i2c_create_slave(bus, "tosa_dac", DAC_BASE); + I2CBus *bus = pxa2xx_i2c_bus(cpu->i2c[0]); + i2c_create_slave(bus, TYPE_TOSA_DAC, DAC_BASE); ssi_create_slave(cpu->ssp[1], "tosa-ssp"); } @@ -271,7 +277,7 @@ static void tosa_dac_class_init(ObjectClass *klass, void *data) } static const TypeInfo tosa_dac_info = { - .name = "tosa_dac", + .name = TYPE_TOSA_DAC, .parent = TYPE_I2C_SLAVE, .instance_size = sizeof(TosaDACState), .class_init = tosa_dac_class_init, diff --git a/hw/arm/versatilepb.c b/hw/arm/versatilepb.c index aef2bde0c4..e5493b428f 100644 --- a/hw/arm/versatilepb.c +++ b/hw/arm/versatilepb.c @@ -185,7 +185,7 @@ static void versatile_init(QEMUMachineInitArgs *args, int board_id) DeviceState *pl041; PCIBus *pci_bus; NICInfo *nd; - i2c_bus *i2c; + I2CBus *i2c; int n; int done_smc = 0; DriveInfo *dinfo; @@ -288,7 +288,7 @@ static void versatile_init(QEMUMachineInitArgs *args, int board_id) sysbus_create_simple("pl031", 0x101e8000, pic[10]); dev = sysbus_create_simple("versatile_i2c", 0x10002000, NULL); - i2c = (i2c_bus *)qdev_get_child_bus(dev, "i2c"); + i2c = (I2CBus *)qdev_get_child_bus(dev, "i2c"); i2c_create_slave(i2c, "ds1338", 0x68); /* Add PL041 AACI Interface to the LM4549 codec */ diff --git a/hw/arm/z2.c b/hw/arm/z2.c index 97367b1f8b..67c1be84ac 100644 --- a/hw/arm/z2.c +++ b/hw/arm/z2.c @@ -193,15 +193,20 @@ static const TypeInfo zipit_lcd_info = { .class_init = zipit_lcd_class_init, }; -typedef struct { - I2CSlave i2c; +#define TYPE_AER915 "aer915" +#define AER915(obj) OBJECT_CHECK(AER915State, (obj), TYPE_AER915) + +typedef struct AER915State { + I2CSlave parent_obj; + int len; uint8_t buf[3]; } AER915State; static int aer915_send(I2CSlave *i2c, uint8_t data) { - AER915State *s = FROM_I2C_SLAVE(AER915State, i2c); + AER915State *s = AER915(i2c); + s->buf[s->len] = data; if (s->len++ > 2) { DPRINTF("%s: message too long (%i bytes)\n", @@ -219,7 +224,8 @@ static int aer915_send(I2CSlave *i2c, uint8_t data) static void aer915_event(I2CSlave *i2c, enum i2c_event event) { - AER915State *s = FROM_I2C_SLAVE(AER915State, i2c); + AER915State *s = AER915(i2c); + switch (event) { case I2C_START_SEND: s->len = 0; @@ -238,8 +244,8 @@ static void aer915_event(I2CSlave *i2c, enum i2c_event event) static int aer915_recv(I2CSlave *slave) { + AER915State *s = AER915(slave); int retval = 0x00; - AER915State *s = FROM_I2C_SLAVE(AER915State, slave); switch (s->buf[0]) { /* Return hardcoded battery voltage, @@ -290,7 +296,7 @@ static void aer915_class_init(ObjectClass *klass, void *data) } static const TypeInfo aer915_info = { - .name = "aer915", + .name = TYPE_AER915, .parent = TYPE_I2C_SLAVE, .instance_size = sizeof(AER915State), .class_init = aer915_class_init, @@ -308,7 +314,7 @@ static void z2_init(QEMUMachineInitArgs *args) DriveInfo *dinfo; int be; void *z2_lcd; - i2c_bus *bus; + I2CBus *bus; DeviceState *wm; if (!cpu_model) { @@ -351,7 +357,7 @@ static void z2_init(QEMUMachineInitArgs *args) type_register_static(&aer915_info); z2_lcd = ssi_create_slave(mpu->ssp[1], "zipit-lcd"); bus = pxa2xx_i2c_bus(mpu->i2c[0]); - i2c_create_slave(bus, "aer915", 0x55); + i2c_create_slave(bus, TYPE_AER915, 0x55); wm = i2c_create_slave(bus, "wm8750", 0x1b); mpu->i2s->opaque = wm; mpu->i2s->codec_out = wm8750_dac_dat; diff --git a/hw/audio/adlib.c b/hw/audio/adlib.c index e88d2dd845..28eed81280 100644 --- a/hw/audio/adlib.c +++ b/hw/audio/adlib.c @@ -354,7 +354,7 @@ static void adlib_realizefn (DeviceState *dev, Error **errp) } static Property adlib_properties[] = { - DEFINE_PROP_HEX32 ("iobase", AdlibState, port, 0x220), + DEFINE_PROP_UINT32 ("iobase", AdlibState, port, 0x220), DEFINE_PROP_UINT32 ("freq", AdlibState, freq, 44100), DEFINE_PROP_END_OF_LIST (), }; diff --git a/hw/audio/cs4231a.c b/hw/audio/cs4231a.c index 666096be07..a0ec17a836 100644 --- a/hw/audio/cs4231a.c +++ b/hw/audio/cs4231a.c @@ -673,7 +673,7 @@ static int cs4231a_init (ISABus *bus) } static Property cs4231a_properties[] = { - DEFINE_PROP_HEX32 ("iobase", CSState, port, 0x534), + DEFINE_PROP_UINT32 ("iobase", CSState, port, 0x534), DEFINE_PROP_UINT32 ("irq", CSState, irq, 9), DEFINE_PROP_UINT32 ("dma", CSState, dma, 3), DEFINE_PROP_END_OF_LIST (), diff --git a/hw/audio/gus.c b/hw/audio/gus.c index 71be3c6ba5..e29a5715db 100644 --- a/hw/audio/gus.c +++ b/hw/audio/gus.c @@ -304,7 +304,7 @@ static int GUS_init (ISABus *bus) static Property gus_properties[] = { DEFINE_PROP_UINT32 ("freq", GUSState, freq, 44100), - DEFINE_PROP_HEX32 ("iobase", GUSState, port, 0x240), + DEFINE_PROP_UINT32 ("iobase", GUSState, port, 0x240), DEFINE_PROP_UINT32 ("irq", GUSState, emu.gusirq, 7), DEFINE_PROP_UINT32 ("dma", GUSState, emu.gusdma, 3), DEFINE_PROP_END_OF_LIST (), diff --git a/hw/audio/pcspk.c b/hw/audio/pcspk.c index f980d66b2f..1d81bbe6aa 100644 --- a/hw/audio/pcspk.c +++ b/hw/audio/pcspk.c @@ -181,7 +181,7 @@ static void pcspk_realizefn(DeviceState *dev, Error **errp) } static Property pcspk_properties[] = { - DEFINE_PROP_HEX32("iobase", PCSpkState, iobase, -1), + DEFINE_PROP_UINT32("iobase", PCSpkState, iobase, -1), DEFINE_PROP_PTR("pit", PCSpkState, pit), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/audio/sb16.c b/hw/audio/sb16.c index db79131cf1..bb24e00f2c 100644 --- a/hw/audio/sb16.c +++ b/hw/audio/sb16.c @@ -1399,8 +1399,8 @@ static int SB16_init (ISABus *bus) } static Property sb16_properties[] = { - DEFINE_PROP_HEX32 ("version", SB16State, ver, 0x0405), /* 4.5 */ - DEFINE_PROP_HEX32 ("iobase", SB16State, port, 0x220), + DEFINE_PROP_UINT32 ("version", SB16State, ver, 0x0405), /* 4.5 */ + DEFINE_PROP_UINT32 ("iobase", SB16State, port, 0x220), DEFINE_PROP_UINT32 ("irq", SB16State, irq, 5), DEFINE_PROP_UINT32 ("dma", SB16State, dma, 1), DEFINE_PROP_UINT32 ("dma16", SB16State, hdma, 5), diff --git a/hw/audio/wm8750.c b/hw/audio/wm8750.c index 6b5a3499bb..c18f2457a1 100644 --- a/hw/audio/wm8750.c +++ b/hw/audio/wm8750.c @@ -23,8 +23,12 @@ typedef struct { int dac_hz; } WMRate; -typedef struct { - I2CSlave i2c; +#define TYPE_WM8750 "wm8750" +#define WM8750(obj) OBJECT_CHECK(WM8750State, (obj), TYPE_WM8750) + +typedef struct WM8750State { + I2CSlave parent_obj; + uint8_t i2c_data[2]; int i2c_len; QEMUSoundCard card; @@ -256,7 +260,8 @@ static void wm8750_clk_update(WM8750State *s, int ext) static void wm8750_reset(I2CSlave *i2c) { - WM8750State *s = (WM8750State *) i2c; + WM8750State *s = WM8750(i2c); + s->rate = &wm_rate_table[0]; s->enable = 0; wm8750_clk_update(s, 1); @@ -299,7 +304,7 @@ static void wm8750_reset(I2CSlave *i2c) static void wm8750_event(I2CSlave *i2c, enum i2c_event event) { - WM8750State *s = (WM8750State *) i2c; + WM8750State *s = WM8750(i2c); switch (event) { case I2C_START_SEND: @@ -356,7 +361,7 @@ static void wm8750_event(I2CSlave *i2c, enum i2c_event event) static int wm8750_tx(I2CSlave *i2c, uint8_t data) { - WM8750State *s = (WM8750State *) i2c; + WM8750State *s = WM8750(i2c); uint8_t cmd; uint16_t value; @@ -542,7 +547,7 @@ static int wm8750_tx(I2CSlave *i2c, uint8_t data) break; case WM8750_RESET: /* Reset */ - wm8750_reset(&s->i2c); + wm8750_reset(I2C_SLAVE(s)); break; #ifdef VERBOSE @@ -604,17 +609,17 @@ static const VMStateDescription vmstate_wm8750 = { VMSTATE_UINT8(format, WM8750State), VMSTATE_UINT8(power, WM8750State), VMSTATE_UINT8(rate_vmstate, WM8750State), - VMSTATE_I2C_SLAVE(i2c, WM8750State), + VMSTATE_I2C_SLAVE(parent_obj, WM8750State), VMSTATE_END_OF_LIST() } }; static int wm8750_init(I2CSlave *i2c) { - WM8750State *s = FROM_I2C_SLAVE(WM8750State, i2c); + WM8750State *s = WM8750(i2c); AUD_register_card(CODEC, &s->card); - wm8750_reset(&s->i2c); + wm8750_reset(I2C_SLAVE(s)); return 0; } @@ -622,8 +627,9 @@ static int wm8750_init(I2CSlave *i2c) #if 0 static void wm8750_fini(I2CSlave *i2c) { - WM8750State *s = (WM8750State *) i2c; - wm8750_reset(&s->i2c); + WM8750State *s = WM8750(i2c); + + wm8750_reset(I2C_SLAVE(s)); AUD_remove_card(&s->card); g_free(s); } @@ -632,7 +638,8 @@ static void wm8750_fini(I2CSlave *i2c) void wm8750_data_req_set(DeviceState *dev, void (*data_req)(void *, int, int), void *opaque) { - WM8750State *s = FROM_I2C_SLAVE(WM8750State, I2C_SLAVE(dev)); + WM8750State *s = WM8750(dev); + s->data_req = data_req; s->opaque = opaque; } @@ -702,7 +709,7 @@ static void wm8750_class_init(ObjectClass *klass, void *data) } static const TypeInfo wm8750_info = { - .name = "wm8750", + .name = TYPE_WM8750, .parent = TYPE_I2C_SLAVE, .instance_size = sizeof(WM8750State), .class_init = wm8750_class_init, diff --git a/hw/block/fdc.c b/hw/block/fdc.c index 592b58f9b5..16510077db 100644 --- a/hw/block/fdc.c +++ b/hw/block/fdc.c @@ -2216,7 +2216,7 @@ static const VMStateDescription vmstate_isa_fdc ={ }; static Property isa_fdc_properties[] = { - DEFINE_PROP_HEX32("iobase", FDCtrlISABus, iobase, 0x3f0), + DEFINE_PROP_UINT32("iobase", FDCtrlISABus, iobase, 0x3f0), DEFINE_PROP_UINT32("irq", FDCtrlISABus, irq, 6), DEFINE_PROP_UINT32("dma", FDCtrlISABus, dma, 2), DEFINE_PROP_DRIVE("driveA", FDCtrlISABus, state.drives[0].bs), diff --git a/hw/block/nand.c b/hw/block/nand.c index a871ce059a..6d7c804f01 100644 --- a/hw/block/nand.c +++ b/hw/block/nand.c @@ -632,7 +632,7 @@ DeviceState *nand_init(BlockDriverState *bdrv, int manf_id, int chip_id) if (nand_flash_ids[chip_id].size == 0) { hw_error("%s: Unsupported NAND chip ID.\n", __FUNCTION__); } - dev = qdev_create(NULL, "nand"); + dev = DEVICE(object_new(TYPE_NAND)); qdev_prop_set_uint8(dev, "manufacturer_id", manf_id); qdev_prop_set_uint8(dev, "chip_id", chip_id); if (bdrv) { diff --git a/hw/char/Makefile.objs b/hw/char/Makefile.objs index be2a7d953a..317385d26f 100644 --- a/hw/char/Makefile.objs +++ b/hw/char/Makefile.objs @@ -1,4 +1,4 @@ -common-obj-$(CONFIG_IPACK) += tpci200.o ipoctal232.o ipack.o +common-obj-$(CONFIG_IPACK) += ipoctal232.o common-obj-$(CONFIG_ESCC) += escc.o common-obj-$(CONFIG_PARALLEL) += parallel.o common-obj-$(CONFIG_PL011) += pl011.o diff --git a/hw/char/debugcon.c b/hw/char/debugcon.c index 02d0d57a79..36f1c4adb3 100644 --- a/hw/char/debugcon.c +++ b/hw/char/debugcon.c @@ -110,9 +110,9 @@ static void debugcon_isa_realizefn(DeviceState *dev, Error **errp) } static Property debugcon_isa_properties[] = { - DEFINE_PROP_HEX32("iobase", ISADebugconState, iobase, 0xe9), + DEFINE_PROP_UINT32("iobase", ISADebugconState, iobase, 0xe9), DEFINE_PROP_CHR("chardev", ISADebugconState, state.chr), - DEFINE_PROP_HEX32("readback", ISADebugconState, state.readback, 0xe9), + DEFINE_PROP_UINT32("readback", ISADebugconState, state.readback, 0xe9), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/char/ipoctal232.c b/hw/char/ipoctal232.c index 88e2ccae75..f9c388ed0b 100644 --- a/hw/char/ipoctal232.c +++ b/hw/char/ipoctal232.c @@ -8,7 +8,7 @@ * later version. */ -#include "ipack.h" +#include "hw/ipack/ipack.h" #include "qemu/bitops.h" #include "sysemu/char.h" @@ -108,7 +108,8 @@ struct SCC2698Block { }; struct IPOctalState { - IPackDevice dev; + IPackDevice parent_obj; + SCC2698Channel ch[N_CHANNELS]; SCC2698Block blk[N_BLOCKS]; uint8_t irq_vector; @@ -154,7 +155,7 @@ static const VMStateDescription vmstate_ipoctal = { .minimum_version_id = 1, .minimum_version_id_old = 1, .fields = (VMStateField[]) { - VMSTATE_IPACK_DEVICE(dev, IPOctalState), + VMSTATE_IPACK_DEVICE(parent_obj, IPOctalState), VMSTATE_STRUCT_ARRAY(ch, IPOctalState, N_CHANNELS, 1, vmstate_scc2698_channel, SCC2698Channel), VMSTATE_STRUCT_ARRAY(blk, IPOctalState, N_BLOCKS, 1, @@ -172,6 +173,7 @@ static const uint8_t id_prom_data[] = { static void update_irq(IPOctalState *dev, unsigned block) { + IPackDevice *idev = IPACK_DEVICE(dev); /* Blocks A and B interrupt on INT0#, C and D on INT1#. Thus, to get the status we have to check two blocks. */ SCC2698Block *blk0 = &dev->blk[block]; @@ -179,9 +181,9 @@ static void update_irq(IPOctalState *dev, unsigned block) unsigned intno = block / 2; if ((blk0->isr & blk0->imr) || (blk1->isr & blk1->imr)) { - qemu_irq_raise(dev->dev.irq[intno]); + qemu_irq_raise(idev->irq[intno]); } else { - qemu_irq_lower(dev->dev.irq[intno]); + qemu_irq_lower(idev->irq[intno]); } } @@ -534,9 +536,9 @@ static void hostdev_event(void *opaque, int event) } } -static int ipoctal_init(IPackDevice *ip) +static void ipoctal_realize(DeviceState *dev, Error **errp) { - IPOctalState *s = IPOCTAL(ip); + IPOctalState *s = IPOCTAL(dev); unsigned i; for (i = 0; i < N_CHANNELS; i++) { @@ -552,8 +554,6 @@ static int ipoctal_init(IPackDevice *ip) DPRINTF("Could not redirect channel %u, no chardev set\n", i); } } - - return 0; } static Property ipoctal_properties[] = { @@ -573,7 +573,7 @@ static void ipoctal_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); IPackDeviceClass *ic = IPACK_DEVICE_CLASS(klass); - ic->init = ipoctal_init; + ic->realize = ipoctal_realize; ic->io_read = io_read; ic->io_write = io_write; ic->id_read = id_read; diff --git a/hw/char/parallel.c b/hw/char/parallel.c index 7a3b2647cf..7ac90a512b 100644 --- a/hw/char/parallel.c +++ b/hw/char/parallel.c @@ -595,7 +595,7 @@ bool parallel_mm_init(MemoryRegion *address_space, static Property parallel_isa_properties[] = { DEFINE_PROP_UINT32("index", ISAParallelState, index, -1), - DEFINE_PROP_HEX32("iobase", ISAParallelState, iobase, -1), + DEFINE_PROP_UINT32("iobase", ISAParallelState, iobase, -1), DEFINE_PROP_UINT32("irq", ISAParallelState, isairq, 7), DEFINE_PROP_CHR("chardev", ISAParallelState, state.chr), DEFINE_PROP_END_OF_LIST(), diff --git a/hw/char/serial-isa.c b/hw/char/serial-isa.c index 5cb77b311a..c9fcb2761f 100644 --- a/hw/char/serial-isa.c +++ b/hw/char/serial-isa.c @@ -88,7 +88,7 @@ static const VMStateDescription vmstate_isa_serial = { static Property serial_isa_properties[] = { DEFINE_PROP_UINT32("index", ISASerialState, index, -1), - DEFINE_PROP_HEX32("iobase", ISASerialState, iobase, -1), + DEFINE_PROP_UINT32("iobase", ISASerialState, iobase, -1), DEFINE_PROP_UINT32("irq", ISASerialState, isairq, -1), DEFINE_PROP_CHR("chardev", ISASerialState, state.chr), DEFINE_PROP_UINT32("wakeup", ISASerialState, state.wakeup, 0), diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c index 3f29b49ca4..5f5957ed8e 100644 --- a/hw/core/qdev-properties-system.c +++ b/hw/core/qdev-properties-system.c @@ -109,7 +109,8 @@ static void set_drive(Object *obj, Visitor *v, void *opaque, } PropertyInfo qdev_prop_drive = { - .name = "drive", + .name = "str", + .legacy_name = "drive", .get = get_drive, .set = set_drive, .release = release_drive, @@ -164,7 +165,8 @@ static void set_chr(Object *obj, Visitor *v, void *opaque, } PropertyInfo qdev_prop_chr = { - .name = "chr", + .name = "str", + .legacy_name = "chr", .get = get_chr, .set = set_chr, .release = release_chr, @@ -242,7 +244,8 @@ static void set_netdev(Object *obj, Visitor *v, void *opaque, } PropertyInfo qdev_prop_netdev = { - .name = "netdev", + .name = "str", + .legacy_name = "netdev", .get = get_netdev, .set = set_netdev, }; @@ -321,7 +324,8 @@ static void set_vlan(Object *obj, Visitor *v, void *opaque, } PropertyInfo qdev_prop_vlan = { - .name = "vlan", + .name = "int32", + .legacy_name = "vlan", .print = print_vlan, .get = get_vlan, .set = set_vlan, diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c index b949f0e42a..77d0c66635 100644 --- a/hw/core/qdev-properties.c +++ b/hw/core/qdev-properties.c @@ -74,13 +74,6 @@ static void bit_prop_set(DeviceState *dev, Property *props, bool val) } } -static int prop_print_bit(DeviceState *dev, Property *prop, char *dest, - size_t len) -{ - uint32_t *p = qdev_get_prop_ptr(dev, prop); - return snprintf(dest, len, (*p & qdev_get_prop_mask(prop)) ? "on" : "off"); -} - static void prop_get_bit(Object *obj, Visitor *v, void *opaque, const char *name, Error **errp) { @@ -114,9 +107,8 @@ static void prop_set_bit(Object *obj, Visitor *v, void *opaque, } PropertyInfo qdev_prop_bit = { - .name = "boolean", + .name = "bool", .legacy_name = "on/off", - .print = prop_print_bit, .get = prop_get_bit, .set = prop_set_bit, }; @@ -149,7 +141,7 @@ static void set_bool(Object *obj, Visitor *v, void *opaque, } PropertyInfo qdev_prop_bool = { - .name = "boolean", + .name = "bool", .get = get_bool, .set = set_bool, }; @@ -187,40 +179,6 @@ PropertyInfo qdev_prop_uint8 = { .set = set_uint8, }; -/* --- 8bit hex value --- */ - -static int parse_hex8(DeviceState *dev, Property *prop, const char *str) -{ - uint8_t *ptr = qdev_get_prop_ptr(dev, prop); - char *end; - - if (str[0] != '0' || str[1] != 'x') { - return -EINVAL; - } - - *ptr = strtoul(str, &end, 16); - if ((*end != '\0') || (end == str)) { - return -EINVAL; - } - - return 0; -} - -static int print_hex8(DeviceState *dev, Property *prop, char *dest, size_t len) -{ - uint8_t *ptr = qdev_get_prop_ptr(dev, prop); - return snprintf(dest, len, "0x%" PRIx8, *ptr); -} - -PropertyInfo qdev_prop_hex8 = { - .name = "uint8", - .legacy_name = "hex8", - .parse = parse_hex8, - .print = print_hex8, - .get = get_uint8, - .set = set_uint8, -}; - /* --- 16bit integer --- */ static void get_uint16(Object *obj, Visitor *v, void *opaque, @@ -318,40 +276,6 @@ PropertyInfo qdev_prop_int32 = { .set = set_int32, }; -/* --- 32bit hex value --- */ - -static int parse_hex32(DeviceState *dev, Property *prop, const char *str) -{ - uint32_t *ptr = qdev_get_prop_ptr(dev, prop); - char *end; - - if (str[0] != '0' || str[1] != 'x') { - return -EINVAL; - } - - *ptr = strtoul(str, &end, 16); - if ((*end != '\0') || (end == str)) { - return -EINVAL; - } - - return 0; -} - -static int print_hex32(DeviceState *dev, Property *prop, char *dest, size_t len) -{ - uint32_t *ptr = qdev_get_prop_ptr(dev, prop); - return snprintf(dest, len, "0x%" PRIx32, *ptr); -} - -PropertyInfo qdev_prop_hex32 = { - .name = "uint32", - .legacy_name = "hex32", - .parse = parse_hex32, - .print = print_hex32, - .get = get_uint32, - .set = set_uint32, -}; - /* --- 64bit integer --- */ static void get_uint64(Object *obj, Visitor *v, void *opaque, @@ -385,40 +309,6 @@ PropertyInfo qdev_prop_uint64 = { .set = set_uint64, }; -/* --- 64bit hex value --- */ - -static int parse_hex64(DeviceState *dev, Property *prop, const char *str) -{ - uint64_t *ptr = qdev_get_prop_ptr(dev, prop); - char *end; - - if (str[0] != '0' || str[1] != 'x') { - return -EINVAL; - } - - *ptr = strtoull(str, &end, 16); - if ((*end != '\0') || (end == str)) { - return -EINVAL; - } - - return 0; -} - -static int print_hex64(DeviceState *dev, Property *prop, char *dest, size_t len) -{ - uint64_t *ptr = qdev_get_prop_ptr(dev, prop); - return snprintf(dest, len, "0x%" PRIx64, *ptr); -} - -PropertyInfo qdev_prop_hex64 = { - .name = "uint64", - .legacy_name = "hex64", - .parse = parse_hex64, - .print = print_hex64, - .get = get_uint64, - .set = set_uint64, -}; - /* --- string --- */ static void release_string(Object *obj, const char *name, void *opaque) @@ -427,16 +317,6 @@ static void release_string(Object *obj, const char *name, void *opaque) g_free(*(char **)qdev_get_prop_ptr(DEVICE(obj), prop)); } -static int print_string(DeviceState *dev, Property *prop, char *dest, - size_t len) -{ - char **ptr = qdev_get_prop_ptr(dev, prop); - if (!*ptr) { - return snprintf(dest, len, "<null>"); - } - return snprintf(dest, len, "\"%s\"", *ptr); -} - static void get_string(Object *obj, Visitor *v, void *opaque, const char *name, Error **errp) { @@ -478,8 +358,7 @@ static void set_string(Object *obj, Visitor *v, void *opaque, } PropertyInfo qdev_prop_string = { - .name = "string", - .print = print_string, + .name = "str", .release = release_string, .get = get_string, .set = set_string, @@ -563,41 +442,31 @@ inval: } PropertyInfo qdev_prop_macaddr = { - .name = "macaddr", + .name = "str", + .legacy_name = "macaddr", .get = get_mac, .set = set_mac, }; /* --- lost tick policy --- */ -static const char *lost_tick_policy_table[LOST_TICK_MAX+1] = { - [LOST_TICK_DISCARD] = "discard", - [LOST_TICK_DELAY] = "delay", - [LOST_TICK_MERGE] = "merge", - [LOST_TICK_SLEW] = "slew", - [LOST_TICK_MAX] = NULL, -}; - QEMU_BUILD_BUG_ON(sizeof(LostTickPolicy) != sizeof(int)); PropertyInfo qdev_prop_losttickpolicy = { .name = "LostTickPolicy", - .enum_table = lost_tick_policy_table, + .enum_table = LostTickPolicy_lookup, .get = get_enum, .set = set_enum, }; /* --- BIOS CHS translation */ -static const char *bios_chs_trans_table[] = { - [BIOS_ATA_TRANSLATION_AUTO] = "auto", - [BIOS_ATA_TRANSLATION_NONE] = "none", - [BIOS_ATA_TRANSLATION_LBA] = "lba", -}; +QEMU_BUILD_BUG_ON(sizeof(BiosAtaTranslation) != sizeof(int)); PropertyInfo qdev_prop_bios_chs_trans = { - .name = "bios-chs-trans", - .enum_table = bios_chs_trans_table, + .name = "BiosAtaTranslation", + .legacy_name = "bios-chs-trans", + .enum_table = BiosAtaTranslation_lookup, .get = get_enum, .set = set_enum, }; @@ -715,7 +584,8 @@ static void set_blocksize(Object *obj, Visitor *v, void *opaque, } PropertyInfo qdev_prop_blocksize = { - .name = "blocksize", + .name = "uint16", + .legacy_name = "blocksize", .get = get_uint16, .set = set_blocksize, }; @@ -822,7 +692,8 @@ inval: } PropertyInfo qdev_prop_pci_host_devaddr = { - .name = "pci-host-devaddr", + .name = "str", + .legacy_name = "pci-host-devaddr", .get = get_pci_host_devaddr, .set = set_pci_host_devaddr, }; @@ -987,20 +858,6 @@ void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev, } } -void qdev_prop_parse(DeviceState *dev, const char *name, const char *value, - Error **errp) -{ - char *legacy_name; - - legacy_name = g_strdup_printf("legacy-%s", name); - if (object_property_get_type(OBJECT(dev), legacy_name, NULL)) { - object_property_parse(OBJECT(dev), value, legacy_name, errp); - } else { - object_property_parse(OBJECT(dev), value, name, errp); - } - g_free(legacy_name); -} - void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value) { object_property_set_bool(OBJECT(dev), value, name, &error_abort); @@ -1093,7 +950,7 @@ void qdev_prop_set_globals_for_type(DeviceState *dev, const char *typename, if (strcmp(typename, prop->driver) != 0) { continue; } - qdev_prop_parse(dev, prop->property, prop->value, &err); + object_property_parse(OBJECT(dev), prop->value, prop->property, &err); if (err != NULL) { error_propagate(errp, err); return; @@ -1140,39 +997,8 @@ static void set_size(Object *obj, Visitor *v, void *opaque, visit_type_size(v, ptr, name, errp); } -static int parse_size(DeviceState *dev, Property *prop, const char *str) -{ - uint64_t *ptr = qdev_get_prop_ptr(dev, prop); - - if (str != NULL) { - parse_option_size(prop->name, str, ptr, &error_abort); - } - return 0; -} - -static int print_size(DeviceState *dev, Property *prop, char *dest, size_t len) -{ - static const char suffixes[] = { 'B', 'K', 'M', 'G', 'T' }; - uint64_t div, val = *(uint64_t *)qdev_get_prop_ptr(dev, prop); - int i; - - /* Compute floor(log2(val)). */ - i = 64 - clz64(val); - - /* Find the power of 1024 that we'll display as the units. */ - i /= 10; - if (i >= ARRAY_SIZE(suffixes)) { - i = ARRAY_SIZE(suffixes) - 1; - } - div = 1ULL << (i * 10); - - return snprintf(dest, len, "%0.03f%c", (double)val/div, suffixes[i]); -} - PropertyInfo qdev_prop_size = { .name = "size", - .parse = parse_size, - .print = print_size, .get = get_size, .set = set_size, }; diff --git a/hw/core/qdev.c b/hw/core/qdev.c index 64b66e07ef..c0b857fbd4 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -588,31 +588,6 @@ static void qdev_get_legacy_property(Object *obj, Visitor *v, void *opaque, visit_type_str(v, &ptr, name, errp); } -static void qdev_set_legacy_property(Object *obj, Visitor *v, void *opaque, - const char *name, Error **errp) -{ - DeviceState *dev = DEVICE(obj); - Property *prop = opaque; - Error *local_err = NULL; - char *ptr = NULL; - int ret; - - if (dev->realized) { - qdev_prop_set_after_realize(dev, name, errp); - return; - } - - visit_type_str(v, &ptr, name, &local_err); - if (local_err) { - error_propagate(errp, local_err); - return; - } - - ret = prop->info->parse(dev, prop, ptr); - error_set_from_qdev_prop_error(errp, ret, dev, prop, ptr); - g_free(ptr); -} - /** * @qdev_add_legacy_property - adds a legacy property * @@ -625,25 +600,20 @@ static void qdev_set_legacy_property(Object *obj, Visitor *v, void *opaque, void qdev_property_add_legacy(DeviceState *dev, Property *prop, Error **errp) { - gchar *name, *type; + gchar *name; /* Register pointer properties as legacy properties */ - if (!prop->info->print && !prop->info->parse && - (prop->info->set || prop->info->get)) { + if (!prop->info->print && prop->info->get) { return; } name = g_strdup_printf("legacy-%s", prop->name); - type = g_strdup_printf("legacy<%s>", - prop->info->legacy_name ?: prop->info->name); - - object_property_add(OBJECT(dev), name, type, + object_property_add(OBJECT(dev), name, "str", prop->info->print ? qdev_get_legacy_property : prop->info->get, - prop->info->parse ? qdev_set_legacy_property : prop->info->set, + NULL, NULL, prop, errp); - g_free(type); g_free(name); } diff --git a/hw/display/g364fb.c b/hw/display/g364fb.c index 7082171b82..bc909bb3de 100644 --- a/hw/display/g364fb.c +++ b/hw/display/g364fb.c @@ -524,7 +524,7 @@ static void g364fb_sysbus_reset(DeviceState *d) } static Property g364fb_sysbus_properties[] = { - DEFINE_PROP_HEX32("vram_size", G364SysBusState, g364.vram_size, + DEFINE_PROP_UINT32("vram_size", G364SysBusState, g364.vram_size, 8 * 1024 * 1024), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/display/ssd0303.c b/hw/display/ssd0303.c index beea5bf22c..89804e108b 100644 --- a/hw/display/ssd0303.c +++ b/hw/display/ssd0303.c @@ -41,8 +41,12 @@ enum ssd0303_cmd { SSD0303_CMD_SKIP1 }; +#define TYPE_SSD0303 "ssd0303" +#define SSD0303(obj) OBJECT_CHECK(ssd0303_state, (obj), TYPE_SSD0303) + typedef struct { - I2CSlave i2c; + I2CSlave parent_obj; + QemuConsole *con; int row; int col; @@ -65,8 +69,9 @@ static int ssd0303_recv(I2CSlave *i2c) static int ssd0303_send(I2CSlave *i2c, uint8_t data) { - ssd0303_state *s = (ssd0303_state *)i2c; + ssd0303_state *s = SSD0303(i2c); enum ssd0303_cmd old_cmd_state; + switch (s->mode) { case SSD0303_IDLE: DPRINTF("byte 0x%02x\n", data); @@ -175,7 +180,8 @@ static int ssd0303_send(I2CSlave *i2c, uint8_t data) static void ssd0303_event(I2CSlave *i2c, enum i2c_event event) { - ssd0303_state *s = (ssd0303_state *)i2c; + ssd0303_state *s = SSD0303(i2c); + switch (event) { case I2C_FINISH: s->mode = SSD0303_IDLE; @@ -279,7 +285,7 @@ static const VMStateDescription vmstate_ssd0303 = { VMSTATE_UINT32(mode, ssd0303_state), VMSTATE_UINT32(cmd_state, ssd0303_state), VMSTATE_BUFFER(framebuffer, ssd0303_state), - VMSTATE_I2C_SLAVE(i2c, ssd0303_state), + VMSTATE_I2C_SLAVE(parent_obj, ssd0303_state), VMSTATE_END_OF_LIST() } }; @@ -291,7 +297,7 @@ static const GraphicHwOps ssd0303_ops = { static int ssd0303_init(I2CSlave *i2c) { - ssd0303_state *s = FROM_I2C_SLAVE(ssd0303_state, i2c); + ssd0303_state *s = SSD0303(i2c); s->con = graphic_console_init(DEVICE(i2c), &ssd0303_ops, s); qemu_console_resize(s->con, 96 * MAGNIFY, 16 * MAGNIFY); @@ -311,7 +317,7 @@ static void ssd0303_class_init(ObjectClass *klass, void *data) } static const TypeInfo ssd0303_info = { - .name = "ssd0303", + .name = TYPE_SSD0303, .parent = TYPE_I2C_SLAVE, .instance_size = sizeof(ssd0303_state), .class_init = ssd0303_class_init, diff --git a/hw/display/tcx.c b/hw/display/tcx.c index 873b82c8db..e60769c2c9 100644 --- a/hw/display/tcx.c +++ b/hw/display/tcx.c @@ -617,11 +617,11 @@ static int tcx_init1(SysBusDevice *dev) } static Property tcx_properties[] = { - DEFINE_PROP_HEX32("vram_size", TCXState, vram_size, -1), + DEFINE_PROP_UINT32("vram_size", TCXState, vram_size, -1), DEFINE_PROP_UINT16("width", TCXState, width, -1), DEFINE_PROP_UINT16("height", TCXState, height, -1), DEFINE_PROP_UINT16("depth", TCXState, depth, -1), - DEFINE_PROP_HEX64("prom_addr", TCXState, prom_addr, -1), + DEFINE_PROP_UINT64("prom_addr", TCXState, prom_addr, -1), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/dma/i82374.c b/hw/dma/i82374.c index a5b891f968..dc7a767ee2 100644 --- a/hw/dma/i82374.c +++ b/hw/dma/i82374.c @@ -149,7 +149,7 @@ static void i82374_isa_realize(DeviceState *dev, Error **errp) } static Property i82374_properties[] = { - DEFINE_PROP_HEX32("iobase", ISAi82374State, iobase, 0x400), + DEFINE_PROP_UINT32("iobase", ISAi82374State, iobase, 0x400), DEFINE_PROP_END_OF_LIST() }; diff --git a/hw/dma/sun4m_iommu.c b/hw/dma/sun4m_iommu.c index 723f66d8f2..899d454353 100644 --- a/hw/dma/sun4m_iommu.c +++ b/hw/dma/sun4m_iommu.c @@ -362,7 +362,7 @@ static int iommu_init1(SysBusDevice *dev) } static Property iommu_properties[] = { - DEFINE_PROP_HEX32("version", IOMMUState, version, 0), + DEFINE_PROP_UINT32("version", IOMMUState, version, 0), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/gpio/max7310.c b/hw/gpio/max7310.c index 59b287703e..cfcd89ca2b 100644 --- a/hw/gpio/max7310.c +++ b/hw/gpio/max7310.c @@ -9,8 +9,12 @@ #include "hw/i2c/i2c.h" -typedef struct { - I2CSlave i2c; +#define TYPE_MAX7310 "max7310" +#define MAX7310(obj) OBJECT_CHECK(MAX7310State, (obj), TYPE_MAX7310) + +typedef struct MAX7310State { + I2CSlave parent_obj; + int i2c_command_byte; int len; @@ -25,7 +29,8 @@ typedef struct { static void max7310_reset(DeviceState *dev) { - MAX7310State *s = FROM_I2C_SLAVE(MAX7310State, I2C_SLAVE(dev)); + MAX7310State *s = MAX7310(dev); + s->level &= s->direction; s->direction = 0xff; s->polarity = 0xf0; @@ -35,7 +40,7 @@ static void max7310_reset(DeviceState *dev) static int max7310_rx(I2CSlave *i2c) { - MAX7310State *s = (MAX7310State *) i2c; + MAX7310State *s = MAX7310(i2c); switch (s->command) { case 0x00: /* Input port */ @@ -70,7 +75,7 @@ static int max7310_rx(I2CSlave *i2c) static int max7310_tx(I2CSlave *i2c, uint8_t data) { - MAX7310State *s = (MAX7310State *) i2c; + MAX7310State *s = MAX7310(i2c); uint8_t diff; int line; @@ -125,7 +130,7 @@ static int max7310_tx(I2CSlave *i2c, uint8_t data) static void max7310_event(I2CSlave *i2c, enum i2c_event event) { - MAX7310State *s = (MAX7310State *) i2c; + MAX7310State *s = MAX7310(i2c); s->len = 0; switch (event) { @@ -156,7 +161,7 @@ static const VMStateDescription vmstate_max7310 = { VMSTATE_UINT8(polarity, MAX7310State), VMSTATE_UINT8(status, MAX7310State), VMSTATE_UINT8(command, MAX7310State), - VMSTATE_I2C_SLAVE(i2c, MAX7310State), + VMSTATE_I2C_SLAVE(parent_obj, MAX7310State), VMSTATE_END_OF_LIST() } }; @@ -177,7 +182,7 @@ static void max7310_gpio_set(void *opaque, int line, int level) * but also accepts sequences that are not SMBus so return an I2C device. */ static int max7310_init(I2CSlave *i2c) { - MAX7310State *s = FROM_I2C_SLAVE(MAX7310State, i2c); + MAX7310State *s = MAX7310(i2c); qdev_init_gpio_in(&i2c->qdev, max7310_gpio_set, 8); qdev_init_gpio_out(&i2c->qdev, s->handler, 8); @@ -199,7 +204,7 @@ static void max7310_class_init(ObjectClass *klass, void *data) } static const TypeInfo max7310_info = { - .name = "max7310", + .name = TYPE_MAX7310, .parent = TYPE_I2C_SLAVE, .instance_size = sizeof(MAX7310State), .class_init = max7310_class_init, diff --git a/hw/i2c/bitbang_i2c.c b/hw/i2c/bitbang_i2c.c index ca59456d16..6d1bb03d6c 100644 --- a/hw/i2c/bitbang_i2c.c +++ b/hw/i2c/bitbang_i2c.c @@ -46,7 +46,7 @@ typedef enum bitbang_i2c_state { } bitbang_i2c_state; struct bitbang_i2c_interface { - i2c_bus *bus; + I2CBus *bus; bitbang_i2c_state state; int last_data; int last_clock; @@ -170,7 +170,7 @@ int bitbang_i2c_set(bitbang_i2c_interface *i2c, int line, int level) abort(); } -bitbang_i2c_interface *bitbang_i2c_init(i2c_bus *bus) +bitbang_i2c_interface *bitbang_i2c_init(I2CBus *bus) { bitbang_i2c_interface *s; @@ -213,7 +213,7 @@ static int gpio_i2c_init(SysBusDevice *sbd) { DeviceState *dev = DEVICE(sbd); GPIOI2CState *s = GPIO_I2C(dev); - i2c_bus *bus; + I2CBus *bus; memory_region_init(&s->dummy_iomem, OBJECT(s), "gpio_i2c", 0); sysbus_init_mmio(sbd, &s->dummy_iomem); diff --git a/hw/i2c/bitbang_i2c.h b/hw/i2c/bitbang_i2c.h index 2866ac351b..3a7126d5de 100644 --- a/hw/i2c/bitbang_i2c.h +++ b/hw/i2c/bitbang_i2c.h @@ -8,7 +8,7 @@ typedef struct bitbang_i2c_interface bitbang_i2c_interface; #define BITBANG_I2C_SDA 0 #define BITBANG_I2C_SCL 1 -bitbang_i2c_interface *bitbang_i2c_init(i2c_bus *bus); +bitbang_i2c_interface *bitbang_i2c_init(I2CBus *bus); int bitbang_i2c_set(bitbang_i2c_interface *i2c, int line, int level); #endif diff --git a/hw/i2c/core.c b/hw/i2c/core.c index c97e7f7dc0..efd8b4fafb 100644 --- a/hw/i2c/core.c +++ b/hw/i2c/core.c @@ -9,7 +9,7 @@ #include "hw/i2c/i2c.h" -struct i2c_bus +struct I2CBus { BusState qbus; I2CSlave *current_dev; @@ -23,24 +23,24 @@ static Property i2c_props[] = { }; #define TYPE_I2C_BUS "i2c-bus" -#define I2C_BUS(obj) OBJECT_CHECK(i2c_bus, (obj), TYPE_I2C_BUS) +#define I2C_BUS(obj) OBJECT_CHECK(I2CBus, (obj), TYPE_I2C_BUS) static const TypeInfo i2c_bus_info = { .name = TYPE_I2C_BUS, .parent = TYPE_BUS, - .instance_size = sizeof(i2c_bus), + .instance_size = sizeof(I2CBus), }; static void i2c_bus_pre_save(void *opaque) { - i2c_bus *bus = opaque; + I2CBus *bus = opaque; bus->saved_address = bus->current_dev ? bus->current_dev->address : -1; } static int i2c_bus_post_load(void *opaque, int version_id) { - i2c_bus *bus = opaque; + I2CBus *bus = opaque; /* The bus is loaded before attached devices, so load and save the current device id. Devices will check themselves as loaded. */ @@ -56,15 +56,15 @@ static const VMStateDescription vmstate_i2c_bus = { .pre_save = i2c_bus_pre_save, .post_load = i2c_bus_post_load, .fields = (VMStateField []) { - VMSTATE_UINT8(saved_address, i2c_bus), + VMSTATE_UINT8(saved_address, I2CBus), VMSTATE_END_OF_LIST() } }; /* Create a new I2C bus. */ -i2c_bus *i2c_init_bus(DeviceState *parent, const char *name) +I2CBus *i2c_init_bus(DeviceState *parent, const char *name) { - i2c_bus *bus; + I2CBus *bus; bus = I2C_BUS(qbus_create(TYPE_I2C_BUS, parent, name)); vmstate_register(NULL, -1, &vmstate_i2c_bus, bus); @@ -77,14 +77,14 @@ void i2c_set_slave_address(I2CSlave *dev, uint8_t address) } /* Return nonzero if bus is busy. */ -int i2c_bus_busy(i2c_bus *bus) +int i2c_bus_busy(I2CBus *bus) { return bus->current_dev != NULL; } /* Returns non-zero if the address is not valid. */ /* TODO: Make this handle multiple masters. */ -int i2c_start_transfer(i2c_bus *bus, uint8_t address, int recv) +int i2c_start_transfer(I2CBus *bus, uint8_t address, int recv) { BusChild *kid; I2CSlave *slave = NULL; @@ -113,7 +113,7 @@ int i2c_start_transfer(i2c_bus *bus, uint8_t address, int recv) return 0; } -void i2c_end_transfer(i2c_bus *bus) +void i2c_end_transfer(I2CBus *bus) { I2CSlave *dev = bus->current_dev; I2CSlaveClass *sc; @@ -130,7 +130,7 @@ void i2c_end_transfer(i2c_bus *bus) bus->current_dev = NULL; } -int i2c_send(i2c_bus *bus, uint8_t data) +int i2c_send(I2CBus *bus, uint8_t data) { I2CSlave *dev = bus->current_dev; I2CSlaveClass *sc; @@ -147,7 +147,7 @@ int i2c_send(i2c_bus *bus, uint8_t data) return -1; } -int i2c_recv(i2c_bus *bus) +int i2c_recv(I2CBus *bus) { I2CSlave *dev = bus->current_dev; I2CSlaveClass *sc; @@ -164,7 +164,7 @@ int i2c_recv(i2c_bus *bus) return -1; } -void i2c_nack(i2c_bus *bus) +void i2c_nack(I2CBus *bus) { I2CSlave *dev = bus->current_dev; I2CSlaveClass *sc; @@ -182,7 +182,7 @@ void i2c_nack(i2c_bus *bus) static int i2c_slave_post_load(void *opaque, int version_id) { I2CSlave *dev = opaque; - i2c_bus *bus; + I2CBus *bus; bus = I2C_BUS(qdev_get_parent_bus(DEVICE(dev))); if (bus->saved_address == dev->address) { bus->current_dev = dev; @@ -210,7 +210,7 @@ static int i2c_slave_qdev_init(DeviceState *dev) return sc->init(s); } -DeviceState *i2c_create_slave(i2c_bus *bus, const char *name, uint8_t addr) +DeviceState *i2c_create_slave(I2CBus *bus, const char *name, uint8_t addr) { DeviceState *dev; diff --git a/hw/i2c/exynos4210_i2c.c b/hw/i2c/exynos4210_i2c.c index ce5f849c77..fb99dfda17 100644 --- a/hw/i2c/exynos4210_i2c.c +++ b/hw/i2c/exynos4210_i2c.c @@ -83,7 +83,7 @@ typedef struct Exynos4210I2CState { SysBusDevice parent_obj; MemoryRegion iomem; - i2c_bus *bus; + I2CBus *bus; qemu_irq irq; uint8_t i2ccon; diff --git a/hw/i2c/omap_i2c.c b/hw/i2c/omap_i2c.c index 2d8e2b7839..d63278dbde 100644 --- a/hw/i2c/omap_i2c.c +++ b/hw/i2c/omap_i2c.c @@ -30,7 +30,7 @@ typedef struct OMAPI2CState { MemoryRegion iomem; qemu_irq irq; qemu_irq drq[2]; - i2c_bus *bus; + I2CBus *bus; uint8_t revision; void *iclk; @@ -491,7 +491,7 @@ static void omap_i2c_register_types(void) type_register_static(&omap_i2c_info); } -i2c_bus *omap_i2c_bus(DeviceState *omap_i2c) +I2CBus *omap_i2c_bus(DeviceState *omap_i2c) { OMAPI2CState *s = OMAP_I2C(omap_i2c); return s->bus; diff --git a/hw/i2c/pm_smbus.c b/hw/i2c/pm_smbus.c index c98e447533..9f50067735 100644 --- a/hw/i2c/pm_smbus.c +++ b/hw/i2c/pm_smbus.c @@ -59,7 +59,7 @@ static void smb_transaction(PMSMBus *s) uint8_t read = s->smb_addr & 0x01; uint8_t cmd = s->smb_cmd; uint8_t addr = s->smb_addr >> 1; - i2c_bus *bus = s->smbus; + I2CBus *bus = s->smbus; SMBUS_DPRINTF("SMBus trans addr=0x%02x prot=0x%02x\n", addr, prot); /* Transaction isn't exec if STS_DEV_ERR bit set */ diff --git a/hw/i2c/smbus.c b/hw/i2c/smbus.c index 25d2d04163..3febf3c258 100644 --- a/hw/i2c/smbus.c +++ b/hw/i2c/smbus.c @@ -208,13 +208,13 @@ static int smbus_device_init(I2CSlave *i2c) } /* Master device commands. */ -void smbus_quick_command(i2c_bus *bus, uint8_t addr, int read) +void smbus_quick_command(I2CBus *bus, uint8_t addr, int read) { i2c_start_transfer(bus, addr, read); i2c_end_transfer(bus); } -uint8_t smbus_receive_byte(i2c_bus *bus, uint8_t addr) +uint8_t smbus_receive_byte(I2CBus *bus, uint8_t addr) { uint8_t data; @@ -225,14 +225,14 @@ uint8_t smbus_receive_byte(i2c_bus *bus, uint8_t addr) return data; } -void smbus_send_byte(i2c_bus *bus, uint8_t addr, uint8_t data) +void smbus_send_byte(I2CBus *bus, uint8_t addr, uint8_t data) { i2c_start_transfer(bus, addr, 0); i2c_send(bus, data); i2c_end_transfer(bus); } -uint8_t smbus_read_byte(i2c_bus *bus, uint8_t addr, uint8_t command) +uint8_t smbus_read_byte(I2CBus *bus, uint8_t addr, uint8_t command) { uint8_t data; i2c_start_transfer(bus, addr, 0); @@ -244,7 +244,7 @@ uint8_t smbus_read_byte(i2c_bus *bus, uint8_t addr, uint8_t command) return data; } -void smbus_write_byte(i2c_bus *bus, uint8_t addr, uint8_t command, uint8_t data) +void smbus_write_byte(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t data) { i2c_start_transfer(bus, addr, 0); i2c_send(bus, command); @@ -252,7 +252,7 @@ void smbus_write_byte(i2c_bus *bus, uint8_t addr, uint8_t command, uint8_t data) i2c_end_transfer(bus); } -uint16_t smbus_read_word(i2c_bus *bus, uint8_t addr, uint8_t command) +uint16_t smbus_read_word(I2CBus *bus, uint8_t addr, uint8_t command) { uint16_t data; i2c_start_transfer(bus, addr, 0); @@ -265,7 +265,7 @@ uint16_t smbus_read_word(i2c_bus *bus, uint8_t addr, uint8_t command) return data; } -void smbus_write_word(i2c_bus *bus, uint8_t addr, uint8_t command, uint16_t data) +void smbus_write_word(I2CBus *bus, uint8_t addr, uint8_t command, uint16_t data) { i2c_start_transfer(bus, addr, 0); i2c_send(bus, command); @@ -274,7 +274,7 @@ void smbus_write_word(i2c_bus *bus, uint8_t addr, uint8_t command, uint16_t data i2c_end_transfer(bus); } -int smbus_read_block(i2c_bus *bus, uint8_t addr, uint8_t command, uint8_t *data) +int smbus_read_block(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t *data) { int len; int i; @@ -292,7 +292,7 @@ int smbus_read_block(i2c_bus *bus, uint8_t addr, uint8_t command, uint8_t *data) return len; } -void smbus_write_block(i2c_bus *bus, uint8_t addr, uint8_t command, uint8_t *data, +void smbus_write_block(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t *data, int len) { int i; diff --git a/hw/i2c/smbus_eeprom.c b/hw/i2c/smbus_eeprom.c index 0218f8a0eb..86f35c11de 100644 --- a/hw/i2c/smbus_eeprom.c +++ b/hw/i2c/smbus_eeprom.c @@ -139,7 +139,7 @@ static void smbus_eeprom_register_types(void) type_init(smbus_eeprom_register_types) -void smbus_eeprom_init(i2c_bus *smbus, int nb_eeprom, +void smbus_eeprom_init(I2CBus *smbus, int nb_eeprom, const uint8_t *eeprom_spd, int eeprom_spd_size) { int i; diff --git a/hw/i2c/smbus_ich9.c b/hw/i2c/smbus_ich9.c index 8d47eaffc8..295b62ed29 100644 --- a/hw/i2c/smbus_ich9.c +++ b/hw/i2c/smbus_ich9.c @@ -108,7 +108,7 @@ static void ich9_smb_class_init(ObjectClass *klass, void *data) dc->cannot_instantiate_with_device_add_yet = true; } -i2c_bus *ich9_smb_init(PCIBus *bus, int devfn, uint32_t smb_io_base) +I2CBus *ich9_smb_init(PCIBus *bus, int devfn, uint32_t smb_io_base) { PCIDevice *d = pci_create_simple_multifunction(bus, devfn, true, TYPE_ICH9_SMB_DEVICE); diff --git a/hw/i2c/versatile_i2c.c b/hw/i2c/versatile_i2c.c index 02e9f171b9..3c0c2c1067 100644 --- a/hw/i2c/versatile_i2c.c +++ b/hw/i2c/versatile_i2c.c @@ -81,7 +81,7 @@ static int versatile_i2c_init(SysBusDevice *sbd) { DeviceState *dev = DEVICE(sbd); VersatileI2CState *s = VERSATILE_I2C(dev); - i2c_bus *bus; + I2CBus *bus; bus = i2c_init_bus(dev, "i2c"); s->bitbang = bitbang_i2c_init(bus); diff --git a/hw/i386/kvm/i8254.c b/hw/i386/kvm/i8254.c index 20b6457fbd..59373aaade 100644 --- a/hw/i386/kvm/i8254.c +++ b/hw/i386/kvm/i8254.c @@ -268,9 +268,9 @@ static void kvm_pit_realizefn(DeviceState *dev, Error **errp) return; } switch (s->lost_tick_policy) { - case LOST_TICK_DELAY: + case LOST_TICK_POLICY_DELAY: break; /* enabled by default */ - case LOST_TICK_DISCARD: + case LOST_TICK_POLICY_DISCARD: if (kvm_check_extension(kvm_state, KVM_CAP_REINJECT_CONTROL)) { struct kvm_reinject_control control = { .pit_reinject = 0 }; @@ -298,9 +298,9 @@ static void kvm_pit_realizefn(DeviceState *dev, Error **errp) } static Property kvm_pit_properties[] = { - DEFINE_PROP_HEX32("iobase", PITCommonState, iobase, -1), + DEFINE_PROP_UINT32("iobase", PITCommonState, iobase, -1), DEFINE_PROP_LOSTTICKPOLICY("lost_tick_policy", KVMPITState, - lost_tick_policy, LOST_TICK_DELAY), + lost_tick_policy, LOST_TICK_POLICY_DELAY), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index 1acd2b2a20..d5dc1ef336 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -236,7 +236,7 @@ static void pc_init1(QEMUMachineInitArgs *args, } if (pci_enabled && acpi_enabled) { - i2c_bus *smbus; + I2CBus *smbus; smi_irq = qemu_allocate_irqs(pc_acpi_smi_interrupt, first_cpu, 1); /* TODO: Populate SPD eeprom data. */ diff --git a/hw/ide/isa.c b/hw/ide/isa.c index afc24d4728..d2cabc142f 100644 --- a/hw/ide/isa.c +++ b/hw/ide/isa.c @@ -104,8 +104,8 @@ ISADevice *isa_ide_init(ISABus *bus, int iobase, int iobase2, int isairq, } static Property isa_ide_properties[] = { - DEFINE_PROP_HEX32("iobase", ISAIDEState, iobase, 0x1f0), - DEFINE_PROP_HEX32("iobase2", ISAIDEState, iobase2, 0x3f6), + DEFINE_PROP_UINT32("iobase", ISAIDEState, iobase, 0x1f0), + DEFINE_PROP_UINT32("iobase2", ISAIDEState, iobase2, 0x3f6), DEFINE_PROP_UINT32("irq", ISAIDEState, isairq, 14), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c index 18c4b7eca9..6e475e6970 100644 --- a/hw/ide/qdev.c +++ b/hw/ide/qdev.c @@ -206,7 +206,7 @@ static int ide_drive_initfn(IDEDevice *dev) #define DEFINE_IDE_DEV_PROPERTIES() \ DEFINE_BLOCK_PROPERTIES(IDEDrive, dev.conf), \ DEFINE_PROP_STRING("ver", IDEDrive, dev.version), \ - DEFINE_PROP_HEX64("wwn", IDEDrive, dev.wwn, 0), \ + DEFINE_PROP_UINT64("wwn", IDEDrive, dev.wwn, 0), \ DEFINE_PROP_STRING("serial", IDEDrive, dev.serial),\ DEFINE_PROP_STRING("model", IDEDrive, dev.model) diff --git a/hw/input/lm832x.c b/hw/input/lm832x.c index f583cf0279..4ae1cd9c80 100644 --- a/hw/input/lm832x.c +++ b/hw/input/lm832x.c @@ -23,8 +23,12 @@ #include "qemu/timer.h" #include "ui/console.h" +#define TYPE_LM8323 "lm8323" +#define LM8323(obj) OBJECT_CHECK(LM823KbdState, (obj), TYPE_LM8323) + typedef struct { - I2CSlave i2c; + I2CSlave parent_obj; + uint8_t i2c_dir; uint8_t i2c_cycle; uint8_t reg; @@ -380,7 +384,7 @@ static void lm_kbd_write(LM823KbdState *s, int reg, int byte, uint8_t value) static void lm_i2c_event(I2CSlave *i2c, enum i2c_event event) { - LM823KbdState *s = FROM_I2C_SLAVE(LM823KbdState, i2c); + LM823KbdState *s = LM8323(i2c); switch (event) { case I2C_START_RECV: @@ -396,14 +400,14 @@ static void lm_i2c_event(I2CSlave *i2c, enum i2c_event event) static int lm_i2c_rx(I2CSlave *i2c) { - LM823KbdState *s = FROM_I2C_SLAVE(LM823KbdState, i2c); + LM823KbdState *s = LM8323(i2c); return lm_kbd_read(s, s->reg, s->i2c_cycle ++); } static int lm_i2c_tx(I2CSlave *i2c, uint8_t data) { - LM823KbdState *s = (LM823KbdState *) i2c; + LM823KbdState *s = LM8323(i2c); if (!s->i2c_cycle) s->reg = data; @@ -431,7 +435,7 @@ static const VMStateDescription vmstate_lm_kbd = { .minimum_version_id_old = 0, .post_load = lm_kbd_post_load, .fields = (VMStateField []) { - VMSTATE_I2C_SLAVE(i2c, LM823KbdState), + VMSTATE_I2C_SLAVE(parent_obj, LM823KbdState), VMSTATE_UINT8(i2c_dir, LM823KbdState), VMSTATE_UINT8(i2c_cycle, LM823KbdState), VMSTATE_UINT8(reg, LM823KbdState), @@ -460,13 +464,13 @@ static const VMStateDescription vmstate_lm_kbd = { static int lm8323_init(I2CSlave *i2c) { - LM823KbdState *s = FROM_I2C_SLAVE(LM823KbdState, i2c); + LM823KbdState *s = LM8323(i2c); s->model = 0x8323; s->pwm.tm[0] = timer_new_ns(QEMU_CLOCK_VIRTUAL, lm_kbd_pwm0_tick, s); s->pwm.tm[1] = timer_new_ns(QEMU_CLOCK_VIRTUAL, lm_kbd_pwm1_tick, s); s->pwm.tm[2] = timer_new_ns(QEMU_CLOCK_VIRTUAL, lm_kbd_pwm2_tick, s); - qdev_init_gpio_out(&i2c->qdev, &s->nirq, 1); + qdev_init_gpio_out(DEVICE(i2c), &s->nirq, 1); lm_kbd_reset(s); @@ -476,7 +480,7 @@ static int lm8323_init(I2CSlave *i2c) void lm832x_key_event(DeviceState *dev, int key, int state) { - LM823KbdState *s = FROM_I2C_SLAVE(LM823KbdState, I2C_SLAVE(dev)); + LM823KbdState *s = LM8323(dev); if ((s->status & INT_ERROR) && (s->error & ERR_FIFOOVR)) return; @@ -507,7 +511,7 @@ static void lm8323_class_init(ObjectClass *klass, void *data) } static const TypeInfo lm8323_info = { - .name = "lm8323", + .name = TYPE_LM8323, .parent = TYPE_I2C_SLAVE, .instance_size = sizeof(LM823KbdState), .class_init = lm8323_class_init, diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c index 93eaa6b2fa..955b8d4945 100644 --- a/hw/intc/arm_gic.c +++ b/hw/intc/arm_gic.c @@ -189,7 +189,7 @@ uint32_t gic_acknowledge_irq(GICState *s, int cpu) } s->last_active[irq][cpu] = s->running_irq[cpu]; - if (s->revision == REV_11MPCORE) { + if (s->revision == REV_11MPCORE || s->revision == REV_NVIC) { /* Clear pending flags for both level and edge triggered interrupts. * Level triggered IRQs will be reasserted once they become inactive. */ diff --git a/hw/intc/i8259_common.c b/hw/intc/i8259_common.c index 9d293999be..61381c463d 100644 --- a/hw/intc/i8259_common.c +++ b/hw/intc/i8259_common.c @@ -123,9 +123,9 @@ static const VMStateDescription vmstate_pic_common = { }; static Property pic_properties_common[] = { - DEFINE_PROP_HEX32("iobase", PICCommonState, iobase, -1), - DEFINE_PROP_HEX32("elcr_addr", PICCommonState, elcr_addr, -1), - DEFINE_PROP_HEX8("elcr_mask", PICCommonState, elcr_mask, -1), + DEFINE_PROP_UINT32("iobase", PICCommonState, iobase, -1), + DEFINE_PROP_UINT32("elcr_addr", PICCommonState, elcr_addr, -1), + DEFINE_PROP_UINT8("elcr_mask", PICCommonState, elcr_mask, -1), DEFINE_PROP_BIT("master", PICCommonState, master, 0, false), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/ipack/Makefile.objs b/hw/ipack/Makefile.objs new file mode 100644 index 0000000000..8b9bdcb549 --- /dev/null +++ b/hw/ipack/Makefile.objs @@ -0,0 +1,2 @@ +common-obj-$(CONFIG_IPACK) += ipack.o +common-obj-$(CONFIG_IPACK) += tpci200.o diff --git a/hw/char/ipack.c b/hw/ipack/ipack.c index b7e45bedb2..ed63d2ac61 100644 --- a/hw/char/ipack.c +++ b/hw/ipack/ipack.c @@ -8,7 +8,7 @@ * later version. */ -#include "ipack.h" +#include "hw/ipack/ipack.h" IPackDevice *ipack_device_find(IPackBus *bus, int32_t slot) { @@ -34,37 +34,39 @@ void ipack_bus_new_inplace(IPackBus *bus, size_t bus_size, bus->set_irq = handler; } -static int ipack_device_dev_init(DeviceState *qdev) +static void ipack_device_realize(DeviceState *dev, Error **errp) { - IPackBus *bus = IPACK_BUS(qdev_get_parent_bus(qdev)); - IPackDevice *dev = IPACK_DEVICE(qdev); + IPackDevice *idev = IPACK_DEVICE(dev); + IPackBus *bus = IPACK_BUS(qdev_get_parent_bus(dev)); IPackDeviceClass *k = IPACK_DEVICE_GET_CLASS(dev); - if (dev->slot < 0) { - dev->slot = bus->free_slot; + if (idev->slot < 0) { + idev->slot = bus->free_slot; } - if (dev->slot >= bus->n_slots) { - return -1; + if (idev->slot >= bus->n_slots) { + error_setg(errp, "Only %" PRIu8 " slots available.", bus->n_slots); + return; } - bus->free_slot = dev->slot + 1; + bus->free_slot = idev->slot + 1; - dev->irq = qemu_allocate_irqs(bus->set_irq, dev, 2); + idev->irq = qemu_allocate_irqs(bus->set_irq, idev, 2); - return k->init(dev); + k->realize(dev, errp); } -static int ipack_device_dev_exit(DeviceState *qdev) +static void ipack_device_unrealize(DeviceState *dev, Error **errp) { - IPackDevice *dev = IPACK_DEVICE(qdev); + IPackDevice *idev = IPACK_DEVICE(dev); IPackDeviceClass *k = IPACK_DEVICE_GET_CLASS(dev); + Error *err = NULL; - if (k->exit) { - k->exit(dev); + if (k->unrealize) { + k->unrealize(dev, &err); + error_propagate(errp, err); + return; } - qemu_free_irqs(dev->irq); - - return 0; + qemu_free_irqs(idev->irq); } static Property ipack_device_props[] = { @@ -75,10 +77,11 @@ static Property ipack_device_props[] = { static void ipack_device_class_init(ObjectClass *klass, void *data) { DeviceClass *k = DEVICE_CLASS(klass); + set_bit(DEVICE_CATEGORY_INPUT, k->categories); k->bus_type = TYPE_IPACK_BUS; - k->init = ipack_device_dev_init; - k->exit = ipack_device_dev_exit; + k->realize = ipack_device_realize; + k->unrealize = ipack_device_unrealize; k->props = ipack_device_props; } diff --git a/hw/char/tpci200.c b/hw/ipack/tpci200.c index a49d2ed5c1..e1b69b4552 100644 --- a/hw/char/tpci200.c +++ b/hw/ipack/tpci200.c @@ -8,7 +8,7 @@ * later version. */ -#include "ipack.h" +#include "hw/ipack/ipack.h" #include "hw/pci/pci.h" #include "qemu/bitops.h" #include <stdio.h> diff --git a/hw/isa/pc87312.c b/hw/isa/pc87312.c index 46a23fb6b4..b352b491ac 100644 --- a/hw/isa/pc87312.c +++ b/hw/isa/pc87312.c @@ -369,7 +369,7 @@ static const VMStateDescription vmstate_pc87312 = { }; static Property pc87312_properties[] = { - DEFINE_PROP_HEX32("iobase", PC87312State, iobase, 0x398), + DEFINE_PROP_UINT32("iobase", PC87312State, iobase, 0x398), DEFINE_PROP_UINT8("config", PC87312State, config, 1), DEFINE_PROP_END_OF_LIST() }; diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c index e639357db3..1a93afda4f 100644 --- a/hw/isa/vt82c686.c +++ b/hw/isa/vt82c686.c @@ -369,8 +369,8 @@ static int vt82c686b_pm_initfn(PCIDevice *dev) return 0; } -i2c_bus *vt82c686b_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base, - qemu_irq sci_irq) +I2CBus *vt82c686b_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base, + qemu_irq sci_irq) { PCIDevice *dev; VT686PMState *s; diff --git a/hw/mips/mips_fulong2e.c b/hw/mips/mips_fulong2e.c index 9ef3a978e2..e1551aabe2 100644 --- a/hw/mips/mips_fulong2e.c +++ b/hw/mips/mips_fulong2e.c @@ -276,7 +276,7 @@ static void mips_fulong2e_init(QEMUMachineInitArgs *args) qemu_irq *cpu_exit_irq; PCIBus *pci_bus; ISABus *isa_bus; - i2c_bus *smbus; + I2CBus *smbus; int i; DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; MIPSCPU *cpu; diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c index 05c8771220..ac5ec44db0 100644 --- a/hw/mips/mips_malta.c +++ b/hw/mips/mips_malta.c @@ -900,7 +900,7 @@ void mips_malta_init(QEMUMachineInitArgs *args) qemu_irq *isa_irq; qemu_irq *cpu_exit_irq; int piix4_devfn; - i2c_bus *smbus; + I2CBus *smbus; int i; DriveInfo *dinfo; DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; diff --git a/hw/misc/applesmc.c b/hw/misc/applesmc.c index 627adb97c9..6a56b07c6b 100644 --- a/hw/misc/applesmc.c +++ b/hw/misc/applesmc.c @@ -249,7 +249,7 @@ static void applesmc_isa_realize(DeviceState *dev, Error **errp) } static Property applesmc_isa_properties[] = { - DEFINE_PROP_HEX32("iobase", AppleSMCState, iobase, + DEFINE_PROP_UINT32("iobase", AppleSMCState, iobase, APPLESMC_DEFAULT_IOBASE), DEFINE_PROP_STRING("osk", AppleSMCState, osk), DEFINE_PROP_END_OF_LIST(), diff --git a/hw/misc/debugexit.c b/hw/misc/debugexit.c index 9db5680015..69a1b004cb 100644 --- a/hw/misc/debugexit.c +++ b/hw/misc/debugexit.c @@ -47,8 +47,8 @@ static void debug_exit_realizefn(DeviceState *d, Error **errp) } static Property debug_exit_properties[] = { - DEFINE_PROP_HEX32("iobase", ISADebugExitState, iobase, 0x501), - DEFINE_PROP_HEX32("iosize", ISADebugExitState, iosize, 0x02), + DEFINE_PROP_UINT32("iobase", ISADebugExitState, iobase, 0x501), + DEFINE_PROP_UINT32("iosize", ISADebugExitState, iosize, 0x02), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/misc/eccmemctl.c b/hw/misc/eccmemctl.c index 96a69d4e5c..549431cb13 100644 --- a/hw/misc/eccmemctl.c +++ b/hw/misc/eccmemctl.c @@ -314,7 +314,7 @@ static int ecc_init1(SysBusDevice *dev) } static Property ecc_properties[] = { - DEFINE_PROP_HEX32("version", ECCState, version, -1), + DEFINE_PROP_UINT32("version", ECCState, version, -1), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/net/ne2000-isa.c b/hw/net/ne2000-isa.c index 26b83cef0d..c660e58335 100644 --- a/hw/net/ne2000-isa.c +++ b/hw/net/ne2000-isa.c @@ -86,7 +86,7 @@ static void isa_ne2000_realizefn(DeviceState *dev, Error **errp) } static Property ne2000_isa_properties[] = { - DEFINE_PROP_HEX32("iobase", ISANE2000State, iobase, 0x300), + DEFINE_PROP_UINT32("iobase", ISANE2000State, iobase, 0x300), DEFINE_PROP_UINT32("irq", ISANE2000State, isairq, 9), DEFINE_NIC_PROPERTIES(ISANE2000State, ne2000.c), DEFINE_PROP_END_OF_LIST(), diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c index ee96c1681b..cb36dc2d0c 100644 --- a/hw/nvram/fw_cfg.c +++ b/hw/nvram/fw_cfg.c @@ -584,8 +584,8 @@ static void fw_cfg_realize(DeviceState *dev, Error **errp) } static Property fw_cfg_properties[] = { - DEFINE_PROP_HEX32("ctl_iobase", FWCfgState, ctl_iobase, -1), - DEFINE_PROP_HEX32("data_iobase", FWCfgState, data_iobase, -1), + DEFINE_PROP_UINT32("ctl_iobase", FWCfgState, ctl_iobase, -1), + DEFINE_PROP_UINT32("data_iobase", FWCfgState, data_iobase, -1), DEFINE_PROP_END_OF_LIST(), }; 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/ppc/Makefile.objs b/hw/ppc/Makefile.objs index 2dd5284532..ea747f0a20 100644 --- a/hw/ppc/Makefile.objs +++ b/hw/ppc/Makefile.objs @@ -10,9 +10,9 @@ obj-y += ppc4xx_pci.o # PReP obj-$(CONFIG_PREP) += prep.o # OldWorld PowerMac -obj-y += mac_oldworld.o +obj-$(CONFIG_MAC) += mac_oldworld.o # NewWorld PowerMac -obj-y += mac_newworld.o +obj-$(CONFIG_MAC) += mac_newworld.o # e500 obj-$(CONFIG_E500) += e500.o mpc8544ds.o e500plat.o obj-$(CONFIG_E500) += mpc8544_guts.o ppce500_spin.o diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c index ec00300884..4c7c3aec12 100644 --- a/hw/ppc/spapr_pci.c +++ b/hw/ppc/spapr_pci.c @@ -651,14 +651,14 @@ static void spapr_phb_reset(DeviceState *qdev) static Property spapr_phb_properties[] = { DEFINE_PROP_INT32("index", sPAPRPHBState, index, -1), - DEFINE_PROP_HEX64("buid", sPAPRPHBState, buid, -1), - DEFINE_PROP_HEX32("liobn", sPAPRPHBState, dma_liobn, -1), - DEFINE_PROP_HEX64("mem_win_addr", sPAPRPHBState, mem_win_addr, -1), - DEFINE_PROP_HEX64("mem_win_size", sPAPRPHBState, mem_win_size, - SPAPR_PCI_MMIO_WIN_SIZE), - DEFINE_PROP_HEX64("io_win_addr", sPAPRPHBState, io_win_addr, -1), - DEFINE_PROP_HEX64("io_win_size", sPAPRPHBState, io_win_size, - SPAPR_PCI_IO_WIN_SIZE), + DEFINE_PROP_UINT64("buid", sPAPRPHBState, buid, -1), + DEFINE_PROP_UINT32("liobn", sPAPRPHBState, dma_liobn, -1), + DEFINE_PROP_UINT64("mem_win_addr", sPAPRPHBState, mem_win_addr, -1), + DEFINE_PROP_UINT64("mem_win_size", sPAPRPHBState, mem_win_size, + SPAPR_PCI_MMIO_WIN_SIZE), + DEFINE_PROP_UINT64("io_win_addr", sPAPRPHBState, io_win_addr, -1), + DEFINE_PROP_UINT64("io_win_size", sPAPRPHBState, io_win_size, + SPAPR_PCI_IO_WIN_SIZE), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c index 59570e2b2b..e6e1ffd1bb 100644 --- a/hw/scsi/megasas.c +++ b/hw/scsi/megasas.c @@ -2195,7 +2195,7 @@ static Property megasas_properties[] = { DEFINE_PROP_UINT32("max_cmds", MegasasState, fw_cmds, MEGASAS_DEFAULT_FRAMES), DEFINE_PROP_STRING("hba_serial", MegasasState, hba_serial), - DEFINE_PROP_HEX64("sas_address", MegasasState, sas_addr, 0), + DEFINE_PROP_UINT64("sas_address", MegasasState, sas_addr, 0), #ifdef USE_MSIX DEFINE_PROP_BIT("use_msix", MegasasState, flags, MEGASAS_FLAG_USE_MSIX, false), diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c index a8d0f15ebe..b4fadd2f24 100644 --- a/hw/scsi/scsi-disk.c +++ b/hw/scsi/scsi-disk.c @@ -2535,7 +2535,7 @@ static Property scsi_hd_properties[] = { SCSI_DISK_F_REMOVABLE, false), DEFINE_PROP_BIT("dpofua", SCSIDiskState, features, SCSI_DISK_F_DPOFUA, false), - DEFINE_PROP_HEX64("wwn", SCSIDiskState, wwn, 0), + DEFINE_PROP_UINT64("wwn", SCSIDiskState, wwn, 0), DEFINE_PROP_UINT64("max_unmap_size", SCSIDiskState, max_unmap_size, DEFAULT_MAX_UNMAP_SIZE), DEFINE_BLOCK_CHS_PROPERTIES(SCSIDiskState, qdev.conf), @@ -2583,7 +2583,7 @@ static const TypeInfo scsi_hd_info = { static Property scsi_cd_properties[] = { DEFINE_SCSI_DISK_PROPERTIES(), - DEFINE_PROP_HEX64("wwn", SCSIDiskState, wwn, 0), + DEFINE_PROP_UINT64("wwn", SCSIDiskState, wwn, 0), DEFINE_PROP_END_OF_LIST(), }; @@ -2646,7 +2646,7 @@ static Property scsi_disk_properties[] = { SCSI_DISK_F_REMOVABLE, false), DEFINE_PROP_BIT("dpofua", SCSIDiskState, features, SCSI_DISK_F_DPOFUA, false), - DEFINE_PROP_HEX64("wwn", SCSIDiskState, wwn, 0), + DEFINE_PROP_UINT64("wwn", SCSIDiskState, wwn, 0), DEFINE_PROP_UINT64("max_unmap_size", SCSIDiskState, max_unmap_size, DEFAULT_MAX_UNMAP_SIZE), DEFINE_PROP_END_OF_LIST(), diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c index a0b90baf6c..843e697bfe 100644 --- a/hw/sd/sdhci.c +++ b/hw/sd/sdhci.c @@ -1233,9 +1233,9 @@ const VMStateDescription sdhci_vmstate = { /* Capabilities registers provide information on supported features of this * specific host controller implementation */ static Property sdhci_properties[] = { - DEFINE_PROP_HEX32("capareg", SDHCIState, capareg, + DEFINE_PROP_UINT32("capareg", SDHCIState, capareg, SDHC_CAPAB_REG_DEFAULT), - DEFINE_PROP_HEX32("maxcurr", SDHCIState, maxcurr, 0), + DEFINE_PROP_UINT32("maxcurr", SDHCIState, maxcurr, 0), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/timer/ds1338.c b/hw/timer/ds1338.c index 8987cdc9e0..bb2f8ee8b3 100644 --- a/hw/timer/ds1338.c +++ b/hw/timer/ds1338.c @@ -23,8 +23,12 @@ #define HOURS_PM 0x20 #define CTRL_OSF 0x20 -typedef struct { - I2CSlave i2c; +#define TYPE_DS1338 "ds1338" +#define DS1338(obj) OBJECT_CHECK(DS1338State, (obj), TYPE_DS1338) + +typedef struct DS1338State { + I2CSlave parent_obj; + int64_t offset; uint8_t wday_offset; uint8_t nvram[NVRAM_SIZE]; @@ -38,7 +42,7 @@ static const VMStateDescription vmstate_ds1338 = { .minimum_version_id = 1, .minimum_version_id_old = 1, .fields = (VMStateField[]) { - VMSTATE_I2C_SLAVE(i2c, DS1338State), + VMSTATE_I2C_SLAVE(parent_obj, DS1338State), VMSTATE_INT64(offset, DS1338State), VMSTATE_UINT8_V(wday_offset, DS1338State, 2), VMSTATE_UINT8_ARRAY(nvram, DS1338State, NVRAM_SIZE), @@ -90,7 +94,7 @@ static void inc_regptr(DS1338State *s) static void ds1338_event(I2CSlave *i2c, enum i2c_event event) { - DS1338State *s = FROM_I2C_SLAVE(DS1338State, i2c); + DS1338State *s = DS1338(i2c); switch (event) { case I2C_START_RECV: @@ -111,7 +115,7 @@ static void ds1338_event(I2CSlave *i2c, enum i2c_event event) static int ds1338_recv(I2CSlave *i2c) { - DS1338State *s = FROM_I2C_SLAVE(DS1338State, i2c); + DS1338State *s = DS1338(i2c); uint8_t res; res = s->nvram[s->ptr]; @@ -121,7 +125,8 @@ static int ds1338_recv(I2CSlave *i2c) static int ds1338_send(I2CSlave *i2c, uint8_t data) { - DS1338State *s = FROM_I2C_SLAVE(DS1338State, i2c); + DS1338State *s = DS1338(i2c); + if (s->addr_byte) { s->ptr = data & (NVRAM_SIZE - 1); s->addr_byte = false; @@ -198,7 +203,7 @@ static int ds1338_init(I2CSlave *i2c) static void ds1338_reset(DeviceState *dev) { - DS1338State *s = FROM_I2C_SLAVE(DS1338State, I2C_SLAVE(dev)); + DS1338State *s = DS1338(dev); /* The clock is running and synchronized with the host */ s->offset = 0; @@ -222,7 +227,7 @@ static void ds1338_class_init(ObjectClass *klass, void *data) } static const TypeInfo ds1338_info = { - .name = "ds1338", + .name = TYPE_DS1338, .parent = TYPE_I2C_SLAVE, .instance_size = sizeof(DS1338State), .class_init = ds1338_class_init, diff --git a/hw/timer/i8254.c b/hw/timer/i8254.c index cdbf481951..28152d88ea 100644 --- a/hw/timer/i8254.c +++ b/hw/timer/i8254.c @@ -342,7 +342,7 @@ static void pit_realizefn(DeviceState *dev, Error **err) } static Property pit_properties[] = { - DEFINE_PROP_HEX32("iobase", PITCommonState, iobase, -1), + DEFINE_PROP_UINT32("iobase", PITCommonState, iobase, -1), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/timer/m48t59.c b/hw/timer/m48t59.c index 3cfb18a8b3..7cf868445f 100644 --- a/hw/timer/m48t59.c +++ b/hw/timer/m48t59.c @@ -741,7 +741,7 @@ static int m48t59_init1(SysBusDevice *dev) static Property m48t59_isa_properties[] = { DEFINE_PROP_UINT32("size", M48t59ISAState, state.size, -1), DEFINE_PROP_UINT32("model", M48t59ISAState, state.model, -1), - DEFINE_PROP_HEX32( "io_base", M48t59ISAState, state.io_base, 0), + DEFINE_PROP_UINT32("io_base", M48t59ISAState, state.io_base, 0), DEFINE_PROP_END_OF_LIST(), }; @@ -766,7 +766,7 @@ static const TypeInfo m48t59_isa_info = { static Property m48t59_properties[] = { DEFINE_PROP_UINT32("size", M48t59SysBusState, state.size, -1), DEFINE_PROP_UINT32("model", M48t59SysBusState, state.model, -1), - DEFINE_PROP_HEX32( "io_base", M48t59SysBusState, state.io_base, 0), + DEFINE_PROP_UINT32("io_base", M48t59SysBusState, state.io_base, 0), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c index 6fb124fead..8509309fa7 100644 --- a/hw/timer/mc146818rtc.c +++ b/hw/timer/mc146818rtc.c @@ -185,7 +185,7 @@ static void rtc_periodic_timer(void *opaque) if (s->cmos_data[RTC_REG_B] & REG_B_PIE) { s->cmos_data[RTC_REG_C] |= REG_C_IRQF; #ifdef TARGET_I386 - if (s->lost_tick_policy == LOST_TICK_SLEW) { + if (s->lost_tick_policy == LOST_TICK_POLICY_SLEW) { if (s->irq_reinject_on_ack_count >= RTC_REINJECT_ON_ACK_COUNT) s->irq_reinject_on_ack_count = 0; apic_reset_irq_delivered(); @@ -708,7 +708,7 @@ static int rtc_post_load(void *opaque, int version_id) #ifdef TARGET_I386 if (version_id >= 2) { - if (s->lost_tick_policy == LOST_TICK_SLEW) { + if (s->lost_tick_policy == LOST_TICK_POLICY_SLEW) { rtc_coalesced_timer_update(s); } } @@ -749,7 +749,7 @@ static void rtc_notify_clock_reset(Notifier *notifier, void *data) periodic_timer_update(s, now); check_update_timer(s); #ifdef TARGET_I386 - if (s->lost_tick_policy == LOST_TICK_SLEW) { + if (s->lost_tick_policy == LOST_TICK_POLICY_SLEW) { rtc_coalesced_timer_update(s); } #endif @@ -774,7 +774,7 @@ static void rtc_reset(void *opaque) qemu_irq_lower(s->irq); #ifdef TARGET_I386 - if (s->lost_tick_policy == LOST_TICK_SLEW) { + if (s->lost_tick_policy == LOST_TICK_POLICY_SLEW) { s->irq_coalesced = 0; } #endif @@ -835,11 +835,11 @@ static void rtc_realizefn(DeviceState *dev, Error **errp) #ifdef TARGET_I386 switch (s->lost_tick_policy) { - case LOST_TICK_SLEW: + case LOST_TICK_POLICY_SLEW: s->coalesced_timer = timer_new_ns(rtc_clock, rtc_coalesced_timer, s); break; - case LOST_TICK_DISCARD: + case LOST_TICK_POLICY_DISCARD: break; default: error_setg(errp, "Invalid lost tick policy."); @@ -890,7 +890,7 @@ ISADevice *rtc_init(ISABus *bus, int base_year, qemu_irq intercept_irq) static Property mc146818rtc_properties[] = { DEFINE_PROP_INT32("base_year", RTCState, base_year, 1980), DEFINE_PROP_LOSTTICKPOLICY("lost_tick_policy", RTCState, - lost_tick_policy, LOST_TICK_DISCARD), + lost_tick_policy, LOST_TICK_POLICY_DISCARD), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/timer/twl92230.c b/hw/timer/twl92230.c index f3ea36503c..85d59909da 100644 --- a/hw/timer/twl92230.c +++ b/hw/timer/twl92230.c @@ -27,8 +27,11 @@ #define VERBOSE 1 -typedef struct { - I2CSlave i2c; +#define TYPE_TWL92230 "twl92230" +#define TWL92230(obj) OBJECT_CHECK(MenelausState, (obj), TYPE_TWL92230) + +typedef struct MenelausState { + I2CSlave parent_obj; int firstbyte; uint8_t reg; @@ -127,7 +130,8 @@ static void menelaus_rtc_hz(void *opaque) static void menelaus_reset(I2CSlave *i2c) { - MenelausState *s = (MenelausState *) i2c; + MenelausState *s = TWL92230(i2c); + s->reg = 0x00; s->vcore[0] = 0x0c; /* XXX: X-loader needs 0x8c? check! */ @@ -492,8 +496,9 @@ static void menelaus_write(void *opaque, uint8_t addr, uint8_t value) break; case MENELAUS_DEVICE_OFF: - if (value & 1) - menelaus_reset(&s->i2c); + if (value & 1) { + menelaus_reset(I2C_SLAVE(s)); + } break; case MENELAUS_OSC_CTRL: @@ -708,7 +713,7 @@ static void menelaus_write(void *opaque, uint8_t addr, uint8_t value) static void menelaus_event(I2CSlave *i2c, enum i2c_event event) { - MenelausState *s = (MenelausState *) i2c; + MenelausState *s = TWL92230(i2c); if (event == I2C_START_SEND) s->firstbyte = 1; @@ -716,7 +721,8 @@ static void menelaus_event(I2CSlave *i2c, enum i2c_event event) static int menelaus_tx(I2CSlave *i2c, uint8_t data) { - MenelausState *s = (MenelausState *) i2c; + MenelausState *s = TWL92230(i2c); + /* Interpret register address byte */ if (s->firstbyte) { s->reg = data; @@ -729,7 +735,7 @@ static int menelaus_tx(I2CSlave *i2c, uint8_t data) static int menelaus_rx(I2CSlave *i2c) { - MenelausState *s = (MenelausState *) i2c; + MenelausState *s = TWL92230(i2c); return menelaus_read(s, s->reg ++); } @@ -834,23 +840,24 @@ static const VMStateDescription vmstate_menelaus = { VMSTATE_STRUCT(rtc.alm, MenelausState, 0, vmstate_menelaus_tm, struct tm), VMSTATE_UINT8(pwrbtn_state, MenelausState), - VMSTATE_I2C_SLAVE(i2c, MenelausState), + VMSTATE_I2C_SLAVE(parent_obj, MenelausState), VMSTATE_END_OF_LIST() } }; static int twl92230_init(I2CSlave *i2c) { - MenelausState *s = FROM_I2C_SLAVE(MenelausState, i2c); + DeviceState *dev = DEVICE(i2c); + MenelausState *s = TWL92230(i2c); s->rtc.hz_tm = timer_new_ms(rtc_clock, menelaus_rtc_hz, s); /* Three output pins plus one interrupt pin. */ - qdev_init_gpio_out(&i2c->qdev, s->out, 4); + qdev_init_gpio_out(dev, s->out, 4); /* Three input pins plus one power-button pin. */ - qdev_init_gpio_in(&i2c->qdev, menelaus_gpio_set, 4); + qdev_init_gpio_in(dev, menelaus_gpio_set, 4); - menelaus_reset(&s->i2c); + menelaus_reset(i2c); return 0; } @@ -868,7 +875,7 @@ static void twl92230_class_init(ObjectClass *klass, void *data) } static const TypeInfo twl92230_info = { - .name = "twl92230", + .name = TYPE_TWL92230, .parent = TYPE_I2C_SLAVE, .instance_size = sizeof(MenelausState), .class_init = twl92230_class_init, diff --git a/hw/usb/desc.c b/hw/usb/desc.c index f133ddb9db..ab48691363 100644 --- a/hw/usb/desc.c +++ b/hw/usb/desc.c @@ -759,7 +759,7 @@ int usb_desc_handle_control(USBDevice *dev, USBPacket *p, * We return the same value that a configured device would return if * it used the first configuration. */ - if (config->bmAttributes & 0x40) { + if (config->bmAttributes & USB_CFG_ATT_SELFPOWER) { data[0] |= 1 << USB_DEVICE_SELF_POWERED; } if (dev->remote_wakeup) { diff --git a/hw/usb/dev-audio.c b/hw/usb/dev-audio.c index c5420eb057..bfebfe90f3 100644 --- a/hw/usb/dev-audio.c +++ b/hw/usb/dev-audio.c @@ -224,7 +224,7 @@ static const USBDescDevice desc_device = { .bNumInterfaces = 2, .bConfigurationValue = DEV_CONFIG_VALUE, .iConfiguration = STRING_CONFIG, - .bmAttributes = 0xc0, + .bmAttributes = USB_CFG_ATT_ONE | USB_CFG_ATT_SELFPOWER, .bMaxPower = 0x32, .nif = ARRAY_SIZE(desc_iface), .ifs = desc_iface, diff --git a/hw/usb/dev-bluetooth.c b/hw/usb/dev-bluetooth.c index 7f292b1ae6..a9661d2801 100644 --- a/hw/usb/dev-bluetooth.c +++ b/hw/usb/dev-bluetooth.c @@ -229,7 +229,7 @@ static const USBDescDevice desc_device_bluetooth = { { .bNumInterfaces = 2, .bConfigurationValue = 1, - .bmAttributes = 0xc0, + .bmAttributes = USB_CFG_ATT_ONE | USB_CFG_ATT_SELFPOWER, .bMaxPower = 0, .nif = ARRAY_SIZE(desc_iface_bluetooth), .ifs = desc_iface_bluetooth, diff --git a/hw/usb/dev-hid.c b/hw/usb/dev-hid.c index 2966066682..f36e617632 100644 --- a/hw/usb/dev-hid.c +++ b/hw/usb/dev-hid.c @@ -202,7 +202,7 @@ static const USBDescDevice desc_device_mouse = { .bNumInterfaces = 1, .bConfigurationValue = 1, .iConfiguration = STR_CONFIG_MOUSE, - .bmAttributes = 0xa0, + .bmAttributes = USB_CFG_ATT_ONE | USB_CFG_ATT_WAKEUP, .bMaxPower = 50, .nif = 1, .ifs = &desc_iface_mouse, @@ -219,7 +219,7 @@ static const USBDescDevice desc_device_tablet = { .bNumInterfaces = 1, .bConfigurationValue = 1, .iConfiguration = STR_CONFIG_TABLET, - .bmAttributes = 0xa0, + .bmAttributes = USB_CFG_ATT_ONE | USB_CFG_ATT_WAKEUP, .bMaxPower = 50, .nif = 1, .ifs = &desc_iface_tablet, @@ -236,7 +236,7 @@ static const USBDescDevice desc_device_tablet2 = { .bNumInterfaces = 1, .bConfigurationValue = 1, .iConfiguration = STR_CONFIG_TABLET, - .bmAttributes = 0xa0, + .bmAttributes = USB_CFG_ATT_ONE | USB_CFG_ATT_WAKEUP, .bMaxPower = 50, .nif = 1, .ifs = &desc_iface_tablet2, @@ -253,7 +253,7 @@ static const USBDescDevice desc_device_keyboard = { .bNumInterfaces = 1, .bConfigurationValue = 1, .iConfiguration = STR_CONFIG_KEYBOARD, - .bmAttributes = 0xa0, + .bmAttributes = USB_CFG_ATT_ONE | USB_CFG_ATT_WAKEUP, .bMaxPower = 50, .nif = 1, .ifs = &desc_iface_keyboard, diff --git a/hw/usb/dev-hub.c b/hw/usb/dev-hub.c index 58647b4859..bc03531666 100644 --- a/hw/usb/dev-hub.c +++ b/hw/usb/dev-hub.c @@ -119,7 +119,8 @@ static const USBDescDevice desc_device_hub = { { .bNumInterfaces = 1, .bConfigurationValue = 1, - .bmAttributes = 0xe0, + .bmAttributes = USB_CFG_ATT_ONE | USB_CFG_ATT_SELFPOWER | + USB_CFG_ATT_WAKEUP, .nif = 1, .ifs = &desc_iface_hub, }, diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c index 4c532b7d6a..518d5366d1 100644 --- a/hw/usb/dev-network.c +++ b/hw/usb/dev-network.c @@ -266,7 +266,7 @@ static const USBDescDevice desc_device_net = { .bNumInterfaces = 2, .bConfigurationValue = DEV_RNDIS_CONFIG_VALUE, .iConfiguration = STRING_RNDIS, - .bmAttributes = 0xc0, + .bmAttributes = USB_CFG_ATT_ONE | USB_CFG_ATT_SELFPOWER, .bMaxPower = 0x32, .nif = ARRAY_SIZE(desc_iface_rndis), .ifs = desc_iface_rndis, @@ -274,7 +274,7 @@ static const USBDescDevice desc_device_net = { .bNumInterfaces = 2, .bConfigurationValue = DEV_CONFIG_VALUE, .iConfiguration = STRING_CDC, - .bmAttributes = 0xc0, + .bmAttributes = USB_CFG_ATT_ONE | USB_CFG_ATT_SELFPOWER, .bMaxPower = 0x32, .nif = ARRAY_SIZE(desc_iface_cdc), .ifs = desc_iface_cdc, @@ -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/dev-serial.c b/hw/usb/dev-serial.c index 0b150d43fb..d3606142c9 100644 --- a/hw/usb/dev-serial.c +++ b/hw/usb/dev-serial.c @@ -144,7 +144,7 @@ static const USBDescDevice desc_device = { { .bNumInterfaces = 1, .bConfigurationValue = 1, - .bmAttributes = 0x80, + .bmAttributes = USB_CFG_ATT_ONE, .bMaxPower = 50, .nif = 1, .ifs = &desc_iface0, diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c index 8c7a61ebe1..470e69ffc8 100644 --- a/hw/usb/dev-smartcard-reader.c +++ b/hw/usb/dev-smartcard-reader.c @@ -463,7 +463,8 @@ static const USBDescDevice desc_device = { { .bNumInterfaces = 1, .bConfigurationValue = 1, - .bmAttributes = 0xe0, + .bmAttributes = USB_CFG_ATT_ONE | USB_CFG_ATT_SELFPOWER | + USB_CFG_ATT_WAKEUP, .bMaxPower = 50, .nif = 1, .ifs = &desc_iface0, diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c index c434c5680f..2852669d57 100644 --- a/hw/usb/dev-storage.c +++ b/hw/usb/dev-storage.c @@ -117,7 +117,7 @@ static const USBDescDevice desc_device_full = { .bNumInterfaces = 1, .bConfigurationValue = 1, .iConfiguration = STR_CONFIG_FULL, - .bmAttributes = 0xc0, + .bmAttributes = USB_CFG_ATT_ONE | USB_CFG_ATT_SELFPOWER, .nif = 1, .ifs = &desc_iface_full, }, @@ -152,7 +152,7 @@ static const USBDescDevice desc_device_high = { .bNumInterfaces = 1, .bConfigurationValue = 1, .iConfiguration = STR_CONFIG_HIGH, - .bmAttributes = 0xc0, + .bmAttributes = USB_CFG_ATT_ONE | USB_CFG_ATT_SELFPOWER, .nif = 1, .ifs = &desc_iface_high, }, @@ -189,7 +189,7 @@ static const USBDescDevice desc_device_super = { .bNumInterfaces = 1, .bConfigurationValue = 1, .iConfiguration = STR_CONFIG_SUPER, - .bmAttributes = 0xc0, + .bmAttributes = USB_CFG_ATT_ONE | USB_CFG_ATT_SELFPOWER, .nif = 1, .ifs = &desc_iface_super, }, diff --git a/hw/usb/dev-uas.c b/hw/usb/dev-uas.c index 997b715952..9832385119 100644 --- a/hw/usb/dev-uas.c +++ b/hw/usb/dev-uas.c @@ -286,7 +286,7 @@ static const USBDescDevice desc_device_high = { .bNumInterfaces = 1, .bConfigurationValue = 1, .iConfiguration = STR_CONFIG_HIGH, - .bmAttributes = 0xc0, + .bmAttributes = USB_CFG_ATT_ONE | USB_CFG_ATT_SELFPOWER, .nif = 1, .ifs = &desc_iface_high, }, @@ -302,7 +302,7 @@ static const USBDescDevice desc_device_super = { .bNumInterfaces = 1, .bConfigurationValue = 1, .iConfiguration = STR_CONFIG_SUPER, - .bmAttributes = 0xc0, + .bmAttributes = USB_CFG_ATT_ONE | USB_CFG_ATT_SELFPOWER, .nif = 1, .ifs = &desc_iface_super, }, diff --git a/hw/usb/dev-wacom.c b/hw/usb/dev-wacom.c index 1b092358f9..1b73fd0aab 100644 --- a/hw/usb/dev-wacom.c +++ b/hw/usb/dev-wacom.c @@ -107,7 +107,7 @@ static const USBDescDevice desc_device_wacom = { { .bNumInterfaces = 1, .bConfigurationValue = 1, - .bmAttributes = 0x80, + .bmAttributes = USB_CFG_ATT_ONE, .bMaxPower = 40, .nif = 1, .ifs = &desc_iface_wacom, diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index ad814b58d4..0820244905 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -252,9 +252,11 @@ static bool uhci_queue_verify(UHCIQueue *queue, uint32_t qh_addr, UHCI_TD *td, uint32_t td_addr, bool queuing) { UHCIAsync *first = QTAILQ_FIRST(&queue->asyncs); + uint32_t queue_token_addr = (queue->token >> 8) & 0x7f; return queue->qh_addr == qh_addr && queue->token == uhci_queue_token(td) && + queue_token_addr == queue->ep->dev->addr && (queuing || !(td->ctrl & TD_CTRL_ACTIVE) || first == NULL || first->td_addr == td_addr); } diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index 0fa814ee09..ef3177aee9 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -807,7 +807,7 @@ static inline int xhci_running(XHCIState *xhci) static void xhci_die(XHCIState *xhci) { xhci->usbsts |= USBSTS_HCE; - fprintf(stderr, "xhci: asserted controller error\n"); + DPRINTF("xhci: asserted controller error\n"); } static void xhci_write_event(XHCIState *xhci, XHCIEvent *event, int v) @@ -854,8 +854,8 @@ static void xhci_events_update(XHCIState *xhci, int v) erdp = xhci_addr64(intr->erdp_low, intr->erdp_high); if (erdp < intr->er_start || erdp >= (intr->er_start + TRB_SIZE*intr->er_size)) { - fprintf(stderr, "xhci: ERDP out of bounds: "DMA_ADDR_FMT"\n", erdp); - fprintf(stderr, "xhci: ER[%d] at "DMA_ADDR_FMT" len %d\n", + DPRINTF("xhci: ERDP out of bounds: "DMA_ADDR_FMT"\n", erdp); + DPRINTF("xhci: ER[%d] at "DMA_ADDR_FMT" len %d\n", v, intr->er_start, intr->er_size); xhci_die(xhci); return; @@ -923,7 +923,7 @@ static void xhci_event(XHCIState *xhci, XHCIEvent *event, int v) if (intr->er_full) { DPRINTF("xhci_event(): ER full, queueing\n"); if (((intr->ev_buffer_put+1) % EV_QUEUE) == intr->ev_buffer_get) { - fprintf(stderr, "xhci: event queue full, dropping event!\n"); + DPRINTF("xhci: event queue full, dropping event!\n"); return; } intr->ev_buffer[intr->ev_buffer_put++] = *event; @@ -936,8 +936,8 @@ static void xhci_event(XHCIState *xhci, XHCIEvent *event, int v) erdp = xhci_addr64(intr->erdp_low, intr->erdp_high); if (erdp < intr->er_start || erdp >= (intr->er_start + TRB_SIZE*intr->er_size)) { - fprintf(stderr, "xhci: ERDP out of bounds: "DMA_ADDR_FMT"\n", erdp); - fprintf(stderr, "xhci: ER[%d] at "DMA_ADDR_FMT" len %d\n", + DPRINTF("xhci: ERDP out of bounds: "DMA_ADDR_FMT"\n", erdp); + DPRINTF("xhci: ER[%d] at "DMA_ADDR_FMT" len %d\n", v, intr->er_start, intr->er_size); xhci_die(xhci); return; @@ -954,7 +954,7 @@ static void xhci_event(XHCIState *xhci, XHCIEvent *event, int v) #endif intr->er_full = 1; if (((intr->ev_buffer_put+1) % EV_QUEUE) == intr->ev_buffer_get) { - fprintf(stderr, "xhci: event queue full, dropping event!\n"); + DPRINTF("xhci: event queue full, dropping event!\n"); return; } intr->ev_buffer[intr->ev_buffer_put++] = *event; @@ -1072,7 +1072,7 @@ static void xhci_er_reset(XHCIState *xhci, int v) } /* cache the (sole) event ring segment location */ if (intr->erstsz != 1) { - fprintf(stderr, "xhci: invalid value for ERSTSZ: %d\n", intr->erstsz); + DPRINTF("xhci: invalid value for ERSTSZ: %d\n", intr->erstsz); xhci_die(xhci); return; } @@ -1082,7 +1082,7 @@ static void xhci_er_reset(XHCIState *xhci, int v) le32_to_cpus(&seg.addr_high); le32_to_cpus(&seg.size); if (seg.size < 16 || seg.size > 4096) { - fprintf(stderr, "xhci: invalid value for segment size: %d\n", seg.size); + DPRINTF("xhci: invalid value for segment size: %d\n", seg.size); xhci_die(xhci); return; } @@ -1248,7 +1248,7 @@ static TRBCCode xhci_alloc_device_streams(XHCIState *xhci, unsigned int slotid, r = usb_device_alloc_streams(eps[0]->dev, eps, nr_eps, req_nr_streams); if (r != 0) { - fprintf(stderr, "xhci: alloc streams failed\n"); + DPRINTF("xhci: alloc streams failed\n"); return CC_RESOURCE_ERROR; } @@ -1532,7 +1532,7 @@ static TRBCCode xhci_stop_ep(XHCIState *xhci, unsigned int slotid, assert(slotid >= 1 && slotid <= xhci->numslots); if (epid < 1 || epid > 31) { - fprintf(stderr, "xhci: bad ep %d\n", epid); + DPRINTF("xhci: bad ep %d\n", epid); return CC_TRB_ERROR; } @@ -1544,7 +1544,7 @@ static TRBCCode xhci_stop_ep(XHCIState *xhci, unsigned int slotid, } if (xhci_ep_nuke_xfers(xhci, slotid, epid, CC_STOPPED) > 0) { - fprintf(stderr, "xhci: FIXME: endpoint stopped w/ xfers running, " + DPRINTF("xhci: FIXME: endpoint stopped w/ xfers running, " "data might be lost\n"); } @@ -1569,7 +1569,7 @@ static TRBCCode xhci_reset_ep(XHCIState *xhci, unsigned int slotid, assert(slotid >= 1 && slotid <= xhci->numslots); if (epid < 1 || epid > 31) { - fprintf(stderr, "xhci: bad ep %d\n", epid); + DPRINTF("xhci: bad ep %d\n", epid); return CC_TRB_ERROR; } @@ -1583,13 +1583,13 @@ static TRBCCode xhci_reset_ep(XHCIState *xhci, unsigned int slotid, epctx = slot->eps[epid-1]; if (epctx->state != EP_HALTED) { - fprintf(stderr, "xhci: reset EP while EP %d not halted (%d)\n", + DPRINTF("xhci: reset EP while EP %d not halted (%d)\n", epid, epctx->state); return CC_CONTEXT_STATE_ERROR; } if (xhci_ep_nuke_xfers(xhci, slotid, epid, 0) > 0) { - fprintf(stderr, "xhci: FIXME: endpoint reset w/ xfers running, " + DPRINTF("xhci: FIXME: endpoint reset w/ xfers running, " "data might be lost\n"); } @@ -1626,7 +1626,7 @@ static TRBCCode xhci_set_ep_dequeue(XHCIState *xhci, unsigned int slotid, assert(slotid >= 1 && slotid <= xhci->numslots); if (epid < 1 || epid > 31) { - fprintf(stderr, "xhci: bad ep %d\n", epid); + DPRINTF("xhci: bad ep %d\n", epid); return CC_TRB_ERROR; } @@ -1643,7 +1643,7 @@ static TRBCCode xhci_set_ep_dequeue(XHCIState *xhci, unsigned int slotid, epctx = slot->eps[epid-1]; if (epctx->state != EP_STOPPED) { - fprintf(stderr, "xhci: set EP dequeue pointer while EP %d not stopped\n", epid); + DPRINTF("xhci: set EP dequeue pointer while EP %d not stopped\n", epid); return CC_CONTEXT_STATE_ERROR; } @@ -1685,7 +1685,7 @@ static int xhci_xfer_create_sgl(XHCITransfer *xfer, int in_xfer) switch (TRB_TYPE(*trb)) { case TR_DATA: if ((!(trb->control & TRB_TR_DIR)) != (!in_xfer)) { - fprintf(stderr, "xhci: data direction mismatch for TR_DATA\n"); + DPRINTF("xhci: data direction mismatch for TR_DATA\n"); goto err; } /* fallthrough */ @@ -1695,7 +1695,7 @@ static int xhci_xfer_create_sgl(XHCITransfer *xfer, int in_xfer) chunk = trb->status & 0x1ffff; if (trb->control & TRB_TR_IDT) { if (chunk > 8 || in_xfer) { - fprintf(stderr, "xhci: invalid immediate data TRB\n"); + DPRINTF("xhci: invalid immediate data TRB\n"); goto err; } qemu_sglist_add(&xfer->sgl, trb->addr, chunk); @@ -1824,7 +1824,7 @@ static int xhci_setup_packet(XHCITransfer *xfer) } else { ep = xhci_epid_to_usbep(xhci, xfer->slotid, xfer->epid); if (!ep) { - fprintf(stderr, "xhci: slot %d has no device\n", + DPRINTF("xhci: slot %d has no device\n", xfer->slotid); return -1; } @@ -1887,7 +1887,7 @@ static int xhci_complete_packet(XHCITransfer *xfer) xhci_stall_ep(xfer); break; default: - fprintf(stderr, "%s: FIXME: status = %d\n", __func__, + DPRINTF("%s: FIXME: status = %d\n", __func__, xfer->packet.status); FIXME("unhandled USB_RET_*"); } @@ -1911,21 +1911,21 @@ static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer) /* do some sanity checks */ if (TRB_TYPE(*trb_setup) != TR_SETUP) { - fprintf(stderr, "xhci: ep0 first TD not SETUP: %d\n", + DPRINTF("xhci: ep0 first TD not SETUP: %d\n", TRB_TYPE(*trb_setup)); return -1; } if (TRB_TYPE(*trb_status) != TR_STATUS) { - fprintf(stderr, "xhci: ep0 last TD not STATUS: %d\n", + DPRINTF("xhci: ep0 last TD not STATUS: %d\n", TRB_TYPE(*trb_status)); return -1; } if (!(trb_setup->control & TRB_TR_IDT)) { - fprintf(stderr, "xhci: Setup TRB doesn't have IDT set\n"); + DPRINTF("xhci: Setup TRB doesn't have IDT set\n"); return -1; } if ((trb_setup->status & 0x1ffff) != 8) { - fprintf(stderr, "xhci: Setup TRB has bad length (%d)\n", + DPRINTF("xhci: Setup TRB has bad length (%d)\n", (trb_setup->status & 0x1ffff)); return -1; } @@ -1974,10 +1974,10 @@ static void xhci_calc_iso_kick(XHCIState *xhci, XHCITransfer *xfer, xfer->mfindex_kick = asap; } } else { - xfer->mfindex_kick = (xfer->trbs[0].control >> TRB_TR_FRAMEID_SHIFT) - & TRB_TR_FRAMEID_MASK; + xfer->mfindex_kick = ((xfer->trbs[0].control >> TRB_TR_FRAMEID_SHIFT) + & TRB_TR_FRAMEID_MASK) << 3; xfer->mfindex_kick |= mfindex & ~0x3fff; - if (xfer->mfindex_kick < mfindex) { + if (xfer->mfindex_kick + 0x100 < mfindex) { xfer->mfindex_kick += 0x4000; } } @@ -2038,9 +2038,7 @@ static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx } break; default: - fprintf(stderr, "xhci: unknown or unhandled EP " - "(type %d, in %d, ep %02x)\n", - epctx->type, xfer->in_xfer, xfer->epid); + trace_usb_xhci_unimplemented("endpoint type", epctx->type); return -1; } @@ -2078,12 +2076,12 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, assert(epid >= 1 && epid <= 31); if (!xhci->slots[slotid-1].enabled) { - fprintf(stderr, "xhci: xhci_kick_ep for disabled slot %d\n", slotid); + DPRINTF("xhci: xhci_kick_ep for disabled slot %d\n", slotid); return; } epctx = xhci->slots[slotid-1].eps[epid-1]; if (!epctx) { - fprintf(stderr, "xhci: xhci_kick_ep for disabled endpoint %d,%d\n", + DPRINTF("xhci: xhci_kick_ep for disabled endpoint %d,%d\n", epid, slotid); return; } @@ -2188,14 +2186,14 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, epctx->next_xfer = (epctx->next_xfer + 1) % TD_QUEUE; ep = xfer->packet.ep; } else { - fprintf(stderr, "xhci: error firing CTL transfer\n"); + DPRINTF("xhci: error firing CTL transfer\n"); } } else { if (xhci_fire_transfer(xhci, xfer, epctx) >= 0) { epctx->next_xfer = (epctx->next_xfer + 1) % TD_QUEUE; } else { if (!xfer->timed_xfer) { - fprintf(stderr, "xhci: error firing data transfer\n"); + DPRINTF("xhci: error firing data transfer\n"); } } } @@ -2298,7 +2296,7 @@ static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid, xhci_dma_read_u32s(xhci, ictx, ictl_ctx, sizeof(ictl_ctx)); if (ictl_ctx[0] != 0x0 || ictl_ctx[1] != 0x3) { - fprintf(stderr, "xhci: invalid input context control %08x %08x\n", + DPRINTF("xhci: invalid input context control %08x %08x\n", ictl_ctx[0], ictl_ctx[1]); return CC_TRB_ERROR; } @@ -2314,14 +2312,14 @@ static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid, uport = xhci_lookup_uport(xhci, slot_ctx); if (uport == NULL) { - fprintf(stderr, "xhci: port not found\n"); + DPRINTF("xhci: port not found\n"); return CC_TRB_ERROR; } trace_usb_xhci_slot_address(slotid, uport->path); dev = uport->dev; if (!dev || !dev->attached) { - fprintf(stderr, "xhci: port %s not connected\n", uport->path); + DPRINTF("xhci: port %s not connected\n", uport->path); return CC_USB_TRANSACTION_ERROR; } @@ -2330,7 +2328,7 @@ static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid, continue; } if (xhci->slots[i].uport == uport) { - fprintf(stderr, "xhci: port %s already assigned to slot %d\n", + DPRINTF("xhci: port %s already assigned to slot %d\n", uport->path, i+1); return CC_TRB_ERROR; } @@ -2414,7 +2412,7 @@ static TRBCCode xhci_configure_slot(XHCIState *xhci, unsigned int slotid, xhci_dma_read_u32s(xhci, ictx, ictl_ctx, sizeof(ictl_ctx)); if ((ictl_ctx[0] & 0x3) != 0x0 || (ictl_ctx[1] & 0x3) != 0x1) { - fprintf(stderr, "xhci: invalid input context control %08x %08x\n", + DPRINTF("xhci: invalid input context control %08x %08x\n", ictl_ctx[0], ictl_ctx[1]); return CC_TRB_ERROR; } @@ -2423,7 +2421,7 @@ static TRBCCode xhci_configure_slot(XHCIState *xhci, unsigned int slotid, xhci_dma_read_u32s(xhci, octx, slot_ctx, sizeof(slot_ctx)); if (SLOT_STATE(slot_ctx[3]) < SLOT_ADDRESSED) { - fprintf(stderr, "xhci: invalid slot state %08x\n", slot_ctx[3]); + DPRINTF("xhci: invalid slot state %08x\n", slot_ctx[3]); return CC_CONTEXT_STATE_ERROR; } @@ -2496,7 +2494,7 @@ static TRBCCode xhci_evaluate_slot(XHCIState *xhci, unsigned int slotid, xhci_dma_read_u32s(xhci, ictx, ictl_ctx, sizeof(ictl_ctx)); if (ictl_ctx[0] != 0x0 || ictl_ctx[1] & ~0x3) { - fprintf(stderr, "xhci: invalid input context control %08x %08x\n", + DPRINTF("xhci: invalid input context control %08x %08x\n", ictl_ctx[0], ictl_ctx[1]); return CC_TRB_ERROR; } @@ -2575,11 +2573,11 @@ static unsigned int xhci_get_slot(XHCIState *xhci, XHCIEvent *event, XHCITRB *tr unsigned int slotid; slotid = (trb->control >> TRB_CR_SLOTID_SHIFT) & TRB_CR_SLOTID_MASK; if (slotid < 1 || slotid > xhci->numslots) { - fprintf(stderr, "xhci: bad slot id %d\n", slotid); + DPRINTF("xhci: bad slot id %d\n", slotid); event->ccode = CC_TRB_ERROR; return 0; } else if (!xhci->slots[slotid-1].enabled) { - fprintf(stderr, "xhci: slot id %d not enabled\n", slotid); + DPRINTF("xhci: slot id %d not enabled\n", slotid); event->ccode = CC_SLOT_NOT_ENABLED_ERROR; return 0; } @@ -2695,7 +2693,7 @@ static void xhci_process_commands(XHCIState *xhci) } } if (i >= xhci->numslots) { - fprintf(stderr, "xhci: no device slots available\n"); + DPRINTF("xhci: no device slots available\n"); event.ccode = CC_NO_SLOTS_ERROR; } else { slotid = i+1; @@ -2887,7 +2885,7 @@ static void xhci_reset(DeviceState *dev) trace_usb_xhci_reset(); if (!(xhci->usbsts & USBSTS_HCH)) { - fprintf(stderr, "xhci: reset while running!\n"); + DPRINTF("xhci: reset while running!\n"); } xhci->usbcmd = 0; @@ -3065,7 +3063,7 @@ static void xhci_port_write(void *ptr, hwaddr reg, /* windows does this for some reason, don't spam stderr */ break; default: - fprintf(stderr, "%s: ignore pls write (old %d, new %d)\n", + DPRINTF("%s: ignore pls write (old %d, new %d)\n", __func__, old_pls, new_pls); break; } @@ -3316,7 +3314,7 @@ static void xhci_doorbell_write(void *ptr, hwaddr reg, trace_usb_xhci_doorbell_write(reg, val); if (!xhci_running(xhci)) { - fprintf(stderr, "xhci: wrote doorbell while xHC stopped or paused\n"); + DPRINTF("xhci: wrote doorbell while xHC stopped or paused\n"); return; } @@ -3326,16 +3324,16 @@ static void xhci_doorbell_write(void *ptr, hwaddr reg, if (val == 0) { xhci_process_commands(xhci); } else { - fprintf(stderr, "xhci: bad doorbell 0 write: 0x%x\n", + DPRINTF("xhci: bad doorbell 0 write: 0x%x\n", (uint32_t)val); } } else { epid = val & 0xff; streamid = (val >> 16) & 0xffff; if (reg > xhci->numslots) { - fprintf(stderr, "xhci: bad doorbell %d\n", (int)reg); + DPRINTF("xhci: bad doorbell %d\n", (int)reg); } else if (epid > 31) { - fprintf(stderr, "xhci: bad doorbell %d write: 0x%x\n", + DPRINTF("xhci: bad doorbell %d write: 0x%x\n", (int)reg, (uint32_t)val); } else { xhci_kick_ep(xhci, reg, epid, streamid); @@ -3636,7 +3634,7 @@ static int usb_xhci_post_load(void *opaque, int version_id) slot->uport = xhci_lookup_uport(xhci, slot_ctx); assert(slot->uport && slot->uport->dev); - for (epid = 1; epid <= 32; epid++) { + for (epid = 1; epid <= 31; epid++) { pctx = slot->ctx + 32 * epid; xhci_dma_read_u32s(xhci, pctx, ep_ctx, sizeof(ep_ctx)); state = ep_ctx[0] & EP_STATE_MASK; diff --git a/hw/usb/host-libusb.c b/hw/usb/host-libusb.c index fd320cd8aa..57bed09a1e 100644 --- a/hw/usb/host-libusb.c +++ b/hw/usb/host-libusb.c @@ -1324,8 +1324,8 @@ static Property usb_host_dev_properties[] = { DEFINE_PROP_UINT32("hostbus", USBHostDevice, match.bus_num, 0), DEFINE_PROP_UINT32("hostaddr", USBHostDevice, match.addr, 0), DEFINE_PROP_STRING("hostport", USBHostDevice, match.port), - DEFINE_PROP_HEX32("vendorid", USBHostDevice, match.vendor_id, 0), - DEFINE_PROP_HEX32("productid", USBHostDevice, match.product_id, 0), + DEFINE_PROP_UINT32("vendorid", USBHostDevice, match.vendor_id, 0), + DEFINE_PROP_UINT32("productid", USBHostDevice, match.product_id, 0), DEFINE_PROP_UINT32("isobufs", USBHostDevice, iso_urb_count, 4), DEFINE_PROP_UINT32("isobsize", USBHostDevice, iso_urb_frames, 32), DEFINE_PROP_INT32("bootindex", USBHostDevice, bootindex, -1), diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index 30c9f2b698..7b91841a1d 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -1063,7 +1063,7 @@ static const TypeInfo virtio_pci_info = { /* virtio-blk-pci */ static Property virtio_blk_pci_properties[] = { - DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0), + DEFINE_PROP_UINT32("class", VirtIOPCIProxy, class_code, 0), DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true), DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2), @@ -1275,7 +1275,7 @@ static void balloon_pci_stats_set_poll_interval(Object *obj, struct Visitor *v, static Property virtio_balloon_pci_properties[] = { DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features), - DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0), + DEFINE_PROP_UINT32("class", VirtIOPCIProxy, class_code, 0), DEFINE_PROP_END_OF_LIST(), }; @@ -1376,7 +1376,7 @@ static Property virtio_serial_pci_properties[] = { DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true), DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2), - DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0), + DEFINE_PROP_UINT32("class", VirtIOPCIProxy, class_code, 0), DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features), DEFINE_VIRTIO_SERIAL_PROPERTIES(VirtIOSerialPCI, vdev.serial), DEFINE_PROP_END_OF_LIST(), diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h index 806ae13780..4b4df88527 100644 --- a/include/fpu/softfloat.h +++ b/include/fpu/softfloat.h @@ -249,11 +249,14 @@ void float_raise( int8 flags STATUS_PARAM); | Using these differs from negating an input or output before calling | the muladd function in that this means that a NaN doesn't have its | sign bit inverted before it is propagated. +| We also support halving the result before rounding, as a special +| case to support the ARM fused-sqrt-step instruction FRSQRTS. *----------------------------------------------------------------------------*/ enum { float_muladd_negate_c = 1, float_muladd_negate_product = 2, float_muladd_negate_result = 4, + float_muladd_halve_result = 8, }; /*---------------------------------------------------------------------------- diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h index bb9a1dddc8..5c1820f883 100644 --- a/include/hw/arm/exynos4210.h +++ b/include/hw/arm/exynos4210.h @@ -97,7 +97,7 @@ typedef struct Exynos4210State { MemoryRegion dram1_mem; MemoryRegion boot_secondary; MemoryRegion bootreg_mem; - i2c_bus *i2c_if[EXYNOS4210_I2C_NUMBER]; + I2CBus *i2c_if[EXYNOS4210_I2C_NUMBER]; } Exynos4210State; void exynos4210_write_secondary(ARMCPU *cpu, diff --git a/include/hw/arm/omap.h b/include/hw/arm/omap.h index 188cda8771..b9655ee397 100644 --- a/include/hw/arm/omap.h +++ b/include/hw/arm/omap.h @@ -765,7 +765,7 @@ void omap_mmc_handlers(struct omap_mmc_s *s, qemu_irq ro, qemu_irq cover); void omap_mmc_enable(struct omap_mmc_s *s, int enable); /* omap_i2c.c */ -i2c_bus *omap_i2c_bus(DeviceState *omap_i2c); +I2CBus *omap_i2c_bus(DeviceState *omap_i2c); # define cpu_is_omap310(cpu) (cpu->mpu_model == omap310) # define cpu_is_omap1510(cpu) (cpu->mpu_model == omap1510) diff --git a/include/hw/arm/pxa.h b/include/hw/arm/pxa.h index 7ca330a61f..c5079067bb 100644 --- a/include/hw/arm/pxa.h +++ b/include/hw/arm/pxa.h @@ -116,7 +116,7 @@ void pxa27x_register_keypad(PXA2xxKeyPadState *kp, typedef struct PXA2xxI2CState PXA2xxI2CState; PXA2xxI2CState *pxa2xx_i2c_init(hwaddr base, qemu_irq irq, uint32_t page_size); -i2c_bus *pxa2xx_i2c_bus(PXA2xxI2CState *s); +I2CBus *pxa2xx_i2c_bus(PXA2xxI2CState *s); typedef struct PXA2xxI2SState PXA2xxI2SState; typedef struct PXA2xxFIrState PXA2xxFIrState; diff --git a/include/hw/block/block.h b/include/hw/block/block.h index dd115320c9..7c3d6c8178 100644 --- a/include/hw/block/block.h +++ b/include/hw/block/block.h @@ -65,12 +65,6 @@ int blkconf_geometry(BlockConf *conf, int *trans, /* Hard disk geometry */ -#define BIOS_ATA_TRANSLATION_AUTO 0 -#define BIOS_ATA_TRANSLATION_NONE 1 -#define BIOS_ATA_TRANSLATION_LBA 2 -#define BIOS_ATA_TRANSLATION_LARGE 3 -#define BIOS_ATA_TRANSLATION_RECHS 4 - void hd_geometry_guess(BlockDriverState *bs, uint32_t *pcyls, uint32_t *pheads, uint32_t *psecs, int *ptrans); diff --git a/include/hw/i2c/i2c.h b/include/hw/i2c/i2c.h index 461392f374..4986ebc73c 100644 --- a/include/hw/i2c/i2c.h +++ b/include/hw/i2c/i2c.h @@ -50,18 +50,16 @@ struct I2CSlave uint8_t address; }; -i2c_bus *i2c_init_bus(DeviceState *parent, const char *name); +I2CBus *i2c_init_bus(DeviceState *parent, const char *name); void i2c_set_slave_address(I2CSlave *dev, uint8_t address); -int i2c_bus_busy(i2c_bus *bus); -int i2c_start_transfer(i2c_bus *bus, uint8_t address, int recv); -void i2c_end_transfer(i2c_bus *bus); -void i2c_nack(i2c_bus *bus); -int i2c_send(i2c_bus *bus, uint8_t data); -int i2c_recv(i2c_bus *bus); - -#define FROM_I2C_SLAVE(type, dev) DO_UPCAST(type, i2c, dev) - -DeviceState *i2c_create_slave(i2c_bus *bus, const char *name, uint8_t addr); +int i2c_bus_busy(I2CBus *bus); +int i2c_start_transfer(I2CBus *bus, uint8_t address, int recv); +void i2c_end_transfer(I2CBus *bus); +void i2c_nack(I2CBus *bus); +int i2c_send(I2CBus *bus, uint8_t data); +int i2c_recv(I2CBus *bus); + +DeviceState *i2c_create_slave(I2CBus *bus, const char *name, uint8_t addr); /* wm8750.c */ void wm8750_data_req_set(DeviceState *dev, diff --git a/include/hw/i2c/pm_smbus.h b/include/hw/i2c/pm_smbus.h index e3069bf7d4..926603fdff 100644 --- a/include/hw/i2c/pm_smbus.h +++ b/include/hw/i2c/pm_smbus.h @@ -2,7 +2,7 @@ #define PM_SMBUS_H typedef struct PMSMBus { - i2c_bus *smbus; + I2CBus *smbus; MemoryRegion io; uint8_t smb_stat; diff --git a/include/hw/i2c/smbus.h b/include/hw/i2c/smbus.h index d764d759c4..63f0cc4788 100644 --- a/include/hw/i2c/smbus.h +++ b/include/hw/i2c/smbus.h @@ -66,18 +66,18 @@ struct SMBusDevice { }; /* Master device commands. */ -void smbus_quick_command(i2c_bus *bus, uint8_t addr, int read); -uint8_t smbus_receive_byte(i2c_bus *bus, uint8_t addr); -void smbus_send_byte(i2c_bus *bus, uint8_t addr, uint8_t data); -uint8_t smbus_read_byte(i2c_bus *bus, uint8_t addr, uint8_t command); -void smbus_write_byte(i2c_bus *bus, uint8_t addr, uint8_t command, uint8_t data); -uint16_t smbus_read_word(i2c_bus *bus, uint8_t addr, uint8_t command); -void smbus_write_word(i2c_bus *bus, uint8_t addr, uint8_t command, uint16_t data); -int smbus_read_block(i2c_bus *bus, uint8_t addr, uint8_t command, uint8_t *data); -void smbus_write_block(i2c_bus *bus, uint8_t addr, uint8_t command, uint8_t *data, +void smbus_quick_command(I2CBus *bus, uint8_t addr, int read); +uint8_t smbus_receive_byte(I2CBus *bus, uint8_t addr); +void smbus_send_byte(I2CBus *bus, uint8_t addr, uint8_t data); +uint8_t smbus_read_byte(I2CBus *bus, uint8_t addr, uint8_t command); +void smbus_write_byte(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t data); +uint16_t smbus_read_word(I2CBus *bus, uint8_t addr, uint8_t command); +void smbus_write_word(I2CBus *bus, uint8_t addr, uint8_t command, uint16_t data); +int smbus_read_block(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t *data); +void smbus_write_block(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t *data, int len); -void smbus_eeprom_init(i2c_bus *smbus, int nb_eeprom, +void smbus_eeprom_init(I2CBus *smbus, int nb_eeprom, const uint8_t *eeprom_spd, int size); #endif diff --git a/include/hw/i386/ich9.h b/include/hw/i386/ich9.h index 4a68b359a6..9e4a0e4b8d 100644 --- a/include/hw/i386/ich9.h +++ b/include/hw/i386/ich9.h @@ -20,7 +20,7 @@ int ich9_lpc_map_irq(PCIDevice *pci_dev, int intx); PCIINTxRoute ich9_route_intx_pin_to_irq(void *opaque, int pirq_pin); void ich9_lpc_pm_init(PCIDevice *pci_lpc); PCIBus *ich9_d2pbr_init(PCIBus *bus, int devfn, int sec_bus); -i2c_bus *ich9_smb_init(PCIBus *bus, int devfn, uint32_t smb_io_base); +I2CBus *ich9_smb_init(PCIBus *bus, int devfn, uint32_t smb_io_base); #define ICH9_CC_SIZE (16 * 1024) /* 16KB */ diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index 3e1e81b27b..9010246cb8 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -165,9 +165,9 @@ void ioapic_init_gsi(GSIState *gsi_state, const char *parent_name); /* acpi_piix.c */ -i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base, - qemu_irq sci_irq, qemu_irq smi_irq, - int kvm_enabled, FWCfgState *fw_cfg); +I2CBus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base, + qemu_irq sci_irq, qemu_irq smi_irq, + int kvm_enabled, FWCfgState *fw_cfg); void piix4_smbus_register_device(SMBusDevice *dev, uint8_t addr); /* hpet.c */ diff --git a/hw/char/ipack.h b/include/hw/ipack/ipack.h index f8dc0f242a..e95ffe820d 100644 --- a/hw/char/ipack.h +++ b/include/hw/ipack/ipack.h @@ -19,7 +19,9 @@ typedef struct IPackBus IPackBus; #define IPACK_BUS(obj) OBJECT_CHECK(IPackBus, (obj), TYPE_IPACK_BUS) struct IPackBus { - BusState qbus; + /*< private >*/ + BusState parent_obj; + /* All fields are private */ uint8_t n_slots; uint8_t free_slot; @@ -38,10 +40,12 @@ typedef struct IPackDeviceClass IPackDeviceClass; OBJECT_GET_CLASS(IPackDeviceClass, (obj), TYPE_IPACK_DEVICE) struct IPackDeviceClass { + /*< private >*/ DeviceClass parent_class; + /*< public >*/ - int (*init)(IPackDevice *dev); - int (*exit)(IPackDevice *dev); + DeviceRealize realize; + DeviceUnrealize unrealize; uint16_t (*io_read)(IPackDevice *dev, uint8_t addr); void (*io_write)(IPackDevice *dev, uint8_t addr, uint16_t val); @@ -60,7 +64,10 @@ struct IPackDeviceClass { }; struct IPackDevice { - DeviceState qdev; + /*< private >*/ + DeviceState parent_obj; + /*< public >*/ + int32_t slot; /* IRQ objects for the IndustryPack INT0# and INT1# */ qemu_irq *irq; diff --git a/include/hw/isa/vt82c686.h b/include/hw/isa/vt82c686.h index 6ef876d260..471b5e9e53 100644 --- a/include/hw/isa/vt82c686.h +++ b/include/hw/isa/vt82c686.h @@ -5,7 +5,7 @@ ISABus *vt82c686b_init(PCIBus * bus, int devfn); void vt82c686b_ac97_init(PCIBus *bus, int devfn); void vt82c686b_mc97_init(PCIBus *bus, int devfn); -i2c_bus *vt82c686b_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base, - qemu_irq sci_irq); +I2CBus *vt82c686b_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base, + qemu_irq sci_irq); #endif diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h index 08d329da71..276b336c09 100644 --- a/include/hw/qdev-core.h +++ b/include/hw/qdev-core.h @@ -217,7 +217,6 @@ struct PropertyInfo { const char *name; const char *legacy_name; const char **enum_table; - int (*parse)(DeviceState *dev, Property *prop, const char *str); int (*print)(DeviceState *dev, Property *prop, char *dest, size_t len); ObjectPropertyAccessor *get; ObjectPropertyAccessor *set; diff --git a/include/hw/qdev-dma.h b/include/hw/qdev-dma.h index 6812735e3d..8cfb0f348e 100644 --- a/include/hw/qdev-dma.h +++ b/include/hw/qdev-dma.h @@ -7,4 +7,4 @@ * See the COPYING file in the top-level directory. */ #define DEFINE_PROP_DMAADDR(_n, _s, _f, _d) \ - DEFINE_PROP_HEX64(_n, _s, _f, _d) + DEFINE_PROP_UINT64(_n, _s, _f, _d) diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h index 77c6f7c037..0c0babfa6a 100644 --- a/include/hw/qdev-properties.h +++ b/include/hw/qdev-properties.h @@ -12,9 +12,6 @@ extern PropertyInfo qdev_prop_uint16; extern PropertyInfo qdev_prop_uint32; extern PropertyInfo qdev_prop_int32; extern PropertyInfo qdev_prop_uint64; -extern PropertyInfo qdev_prop_hex8; -extern PropertyInfo qdev_prop_hex32; -extern PropertyInfo qdev_prop_hex64; extern PropertyInfo qdev_prop_size; extern PropertyInfo qdev_prop_string; extern PropertyInfo qdev_prop_chr; @@ -111,12 +108,6 @@ extern PropertyInfo qdev_prop_arraylen; DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_int32, int32_t) #define DEFINE_PROP_UINT64(_n, _s, _f, _d) \ DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_uint64, uint64_t) -#define DEFINE_PROP_HEX8(_n, _s, _f, _d) \ - DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_hex8, uint8_t) -#define DEFINE_PROP_HEX32(_n, _s, _f, _d) \ - DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_hex32, uint32_t) -#define DEFINE_PROP_HEX64(_n, _s, _f, _d) \ - DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_hex64, uint64_t) #define DEFINE_PROP_SIZE(_n, _s, _f, _d) \ DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_size, uint64_t) #define DEFINE_PROP_PCI_DEVFN(_n, _s, _f, _d) \ @@ -168,8 +159,6 @@ extern PropertyInfo qdev_prop_arraylen; /* Set properties between creation and init. */ void *qdev_get_prop_ptr(DeviceState *dev, Property *prop); -void qdev_prop_parse(DeviceState *dev, const char *name, const char *value, - Error **errp); void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value); void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value); void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value); diff --git a/include/hw/usb.h b/include/hw/usb.h index 3ef7af7413..1919bdc09d 100644 --- a/include/hw/usb.h +++ b/include/hw/usb.h @@ -157,6 +157,11 @@ #define USB_DEV_CAP_USB2_EXT 0x02 #define USB_DEV_CAP_SUPERSPEED 0x03 +#define USB_CFG_ATT_ONE (1 << 7) /* should always be set */ +#define USB_CFG_ATT_SELFPOWER (1 << 6) +#define USB_CFG_ATT_WAKEUP (1 << 5) +#define USB_CFG_ATT_BATTERY (1 << 4) + #define USB_ENDPOINT_XFER_CONTROL 0 #define USB_ENDPOINT_XFER_ISOC 1 #define USB_ENDPOINT_XFER_BULK 2 diff --git a/include/qapi/string-output-visitor.h b/include/qapi/string-output-visitor.h index ec81e42b60..d99717f650 100644 --- a/include/qapi/string-output-visitor.h +++ b/include/qapi/string-output-visitor.h @@ -17,7 +17,7 @@ typedef struct StringOutputVisitor StringOutputVisitor; -StringOutputVisitor *string_output_visitor_new(void); +StringOutputVisitor *string_output_visitor_new(bool human); void string_output_visitor_cleanup(StringOutputVisitor *v); char *string_output_get_string(StringOutputVisitor *v); diff --git a/include/qemu-common.h b/include/qemu-common.h index 17c2959b4f..46c2beacd2 100644 --- a/include/qemu-common.h +++ b/include/qemu-common.h @@ -261,14 +261,6 @@ typedef int (*DMA_transfer_handler) (void *opaque, int nchan, int pos, int size) typedef uint64_t pcibus_t; -typedef enum LostTickPolicy { - LOST_TICK_DISCARD, - LOST_TICK_DELAY, - LOST_TICK_MERGE, - LOST_TICK_SLEW, - LOST_TICK_MAX -} LostTickPolicy; - typedef struct PCIHostDeviceAddress { unsigned int domain; unsigned int bus; diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h index 5b4e333fc1..83c9b1675d 100644 --- a/include/qemu/typedefs.h +++ b/include/qemu/typedefs.h @@ -43,7 +43,7 @@ typedef struct QemuConsole QemuConsole; typedef struct CharDriverState CharDriverState; typedef struct MACAddr MACAddr; typedef struct NetClientState NetClientState; -typedef struct i2c_bus i2c_bus; +typedef struct I2CBus I2CBus; typedef struct ISABus ISABus; typedef struct ISADevice ISADevice; typedef struct SMBusDevice SMBusDevice; diff --git a/include/qom/object.h b/include/qom/object.h index e0ff212cb6..9c7c361d30 100644 --- a/include/qom/object.h +++ b/include/qom/object.h @@ -946,12 +946,13 @@ void object_property_parse(Object *obj, const char *string, * object_property_print: * @obj: the object * @name: the name of the property + * @human: if true, print for human consumption * @errp: returns an error if this function fails * * Returns a string representation of the value of the property. The * caller shall free the string. */ -char *object_property_print(Object *obj, const char *name, +char *object_property_print(Object *obj, const char *name, bool human, Error **errp); /** diff --git a/include/sysemu/qtest.h b/include/sysemu/qtest.h index 6aca8e4c1f..28f4875112 100644 --- a/include/sysemu/qtest.h +++ b/include/sysemu/qtest.h @@ -15,6 +15,7 @@ #define QTEST_H #include "qemu-common.h" +#include "qapi/error.h" extern bool qtest_allowed; @@ -26,7 +27,7 @@ static inline bool qtest_enabled(void) bool qtest_driver(void); int qtest_init_accel(void); -void qtest_init(const char *qtest_chrdev, const char *qtest_log); +void qtest_init(const char *qtest_chrdev, const char *qtest_log, Error **errp); static inline int qtest_available(void) { diff --git a/linux-user/alpha/syscall_nr.h b/linux-user/alpha/syscall_nr.h index d52d76e08e..625f301674 100644 --- a/linux-user/alpha/syscall_nr.h +++ b/linux-user/alpha/syscall_nr.h @@ -433,3 +433,10 @@ #define TARGET_NR_open_by_handle_at 498 #define TARGET_NR_clock_adjtime 499 #define TARGET_NR_syncfs 500 +#define TARGET_NR_setns 501 +#define TARGET_NR_accept4 502 +#define TARGET_NR_sendmmsg 503 +#define TARGET_NR_process_vm_readv 504 +#define TARGET_NR_process_vm_writev 505 +#define TARGET_NR_kcmp 506 +#define TARGET_NR_finit_module 507 diff --git a/linux-user/arm/syscall_nr.h b/linux-user/arm/syscall_nr.h index 42d68550dc..bef847cfae 100644 --- a/linux-user/arm/syscall_nr.h +++ b/linux-user/arm/syscall_nr.h @@ -378,3 +378,9 @@ #define TARGET_NR_open_by_handle_at (371) #define TARGET_NR_clock_adjtime (372) #define TARGET_NR_syncfs (373) +#define TARGET_NR_sendmmsg (374) +#define TARGET_NR_setns (375) +#define TARGET_NR_process_vm_readv (376) +#define TARGET_NR_process_vm_writev (377) +#define TARGET_NR_kcmp (378) +#define TARGET_NR_finit_module (379) diff --git a/linux-user/cris/syscall_nr.h b/linux-user/cris/syscall_nr.h index 98f1a0b415..694bd02fa5 100644 --- a/linux-user/cris/syscall_nr.h +++ b/linux-user/cris/syscall_nr.h @@ -335,3 +335,4 @@ #define TARGET_NR_inotify_init1 332 #define TARGET_NR_preadv 333 #define TARGET_NR_pwritev 334 +#define TARGET_NR_setns 335 diff --git a/linux-user/elfload.c b/linux-user/elfload.c index 5902f162b4..c0687e3b38 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -2636,6 +2636,16 @@ static void fill_thread_info(struct elf_note_info *info, const CPUArchState *env info->notes_size += note_size(&ets->notes[0]); } +static void init_note_info(struct elf_note_info *info) +{ + /* Initialize the elf_note_info structure so that it is at + * least safe to call free_note_info() on it. Must be + * called before calling fill_note_info(). + */ + memset(info, 0, sizeof (*info)); + QTAILQ_INIT(&info->thread_list); +} + static int fill_note_info(struct elf_note_info *info, long signr, const CPUArchState *env) { @@ -2644,10 +2654,6 @@ static int fill_note_info(struct elf_note_info *info, TaskState *ts = (TaskState *)env->opaque; int i; - (void) memset(info, 0, sizeof (*info)); - - QTAILQ_INIT(&info->thread_list); - info->notes = g_malloc0(NUMNOTES * sizeof (struct memelfnote)); if (info->notes == NULL) return (-ENOMEM); @@ -2781,6 +2787,8 @@ static int elf_core_dump(int signr, const CPUArchState *env) int segs = 0; int fd = -1; + init_note_info(&info); + errno = 0; getrlimit(RLIMIT_CORE, &dumpsize); if (dumpsize.rlim_cur == 0) diff --git a/linux-user/i386/syscall_nr.h b/linux-user/i386/syscall_nr.h index f0803050d8..c8f7302194 100644 --- a/linux-user/i386/syscall_nr.h +++ b/linux-user/i386/syscall_nr.h @@ -347,3 +347,9 @@ #define TARGET_NR_open_by_handle_at 342 #define TARGET_NR_clock_adjtime 343 #define TARGET_NR_syncfs 344 +#define TARGET_NR_sendmmsg 345 +#define TARGET_NR_setns 346 +#define TARGET_NR_process_vm_readv 347 +#define TARGET_NR_process_vm_writev 348 +#define TARGET_NR_kcmp 349 +#define TARGET_NR_finit_module 350 diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h index 7381012d3d..309fb21759 100644 --- a/linux-user/ioctls.h +++ b/linux-user/ioctls.h @@ -77,6 +77,7 @@ IOCTL(BLKRAGET, IOC_R, MK_PTR(TYPE_LONG)) IOCTL(BLKSSZGET, IOC_R, MK_PTR(TYPE_LONG)) IOCTL(BLKBSZGET, IOC_R, MK_PTR(TYPE_INT)) + IOCTL(BLKPG, IOC_W, MK_PTR(MK_STRUCT(STRUCT_blkpg_ioctl_arg))) #ifdef FIBMAP IOCTL(FIBMAP, IOC_W | IOC_R, MK_PTR(TYPE_LONG)) #endif diff --git a/linux-user/m68k/syscall_nr.h b/linux-user/m68k/syscall_nr.h index 4d0937e505..25f8521ec3 100644 --- a/linux-user/m68k/syscall_nr.h +++ b/linux-user/m68k/syscall_nr.h @@ -344,3 +344,8 @@ #define TARGET_NR_open_by_handle_at 341 #define TARGET_NR_clock_adjtime 342 #define TARGET_NR_syncfs 343 +#define TARGET_NR_setns 344 +#define TARGET_NR_process_vm_readv 345 +#define TARGET_NR_process_vm_writev 346 +#define TARGET_NR_kcmp 347 +#define TARGET_NR_finit_module 348 diff --git a/linux-user/main.c b/linux-user/main.c index cabc9e1a0e..919297736c 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -953,7 +953,8 @@ static int do_strex_a64(CPUARMState *env) goto finish; } } - val = env->xregs[rt]; + /* handle the zero register */ + val = rt == 31 ? 0 : env->xregs[rt]; switch (size) { case 0: segv = put_user_u8(val, addr); @@ -972,7 +973,8 @@ static int do_strex_a64(CPUARMState *env) goto error; } if (is_pair) { - val = env->xregs[rt2]; + /* handle the zero register */ + val = rt2 == 31 ? 0 : env->xregs[rt2]; if (size == 2) { segv = put_user_u32(val, addr + 4); } else { diff --git a/linux-user/microblaze/syscall_nr.h b/linux-user/microblaze/syscall_nr.h index f1fe0e7d8f..6f530f9d1e 100644 --- a/linux-user/microblaze/syscall_nr.h +++ b/linux-user/microblaze/syscall_nr.h @@ -376,4 +376,9 @@ #define TARGET_NR_open_by_handle_at 372 #define TARGET_NR_clock_adjtime 373 #define TARGET_NR_syncfs 374 - +#define TARGET_NR_setns 375 +#define TARGET_NR_sendmmsg 376 +#define TARGET_NR_process_vm_readv 377 +#define TARGET_NR_process_vm_writev 378 +#define TARGET_NR_kcmp 379 +#define TARGET_NR_finit_module 380 diff --git a/linux-user/mips/syscall_nr.h b/linux-user/mips/syscall_nr.h index fbdc348ffc..2d1a13ee2f 100644 --- a/linux-user/mips/syscall_nr.h +++ b/linux-user/mips/syscall_nr.h @@ -345,3 +345,9 @@ #define TARGET_NR_open_by_handle_at (TARGET_NR_Linux + 340) #define TARGET_NR_clock_adjtime (TARGET_NR_Linux + 341) #define TARGET_NR_syncfs (TARGET_NR_Linux + 342) +#define TARGET_NR_sendmmsg (TARGET_NR_Linux + 343) +#define TARGET_NR_setns (TARGET_NR_Linux + 344) +#define TARGET_NR_process_vm_readv (TARGET_NR_Linux + 345) +#define TARGET_NR_process_vm_writev (TARGET_NR_Linux + 346) +#define TARGET_NR_kcmp (TARGET_NR_Linux + 347) +#define TARGET_NR_finit_module (TARGET_NR_Linux + 348) diff --git a/linux-user/mips64/syscall_nr.h b/linux-user/mips64/syscall_nr.h index 0f4a6b107b..004232a8a2 100644 --- a/linux-user/mips64/syscall_nr.h +++ b/linux-user/mips64/syscall_nr.h @@ -310,6 +310,12 @@ #define TARGET_NR_open_by_handle_at (TARGET_NR_Linux + 304) #define TARGET_NR_clock_adjtime (TARGET_NR_Linux + 305) #define TARGET_NR_syncfs (TARGET_NR_Linux + 306) +#define TARGET_NR_sendmmsg (TARGET_NR_Linux + 307) +#define TARGET_NR_setns (TARGET_NR_Linux + 308) +#define TARGET_NR_process_vm_readv (TARGET_NR_Linux + 309) +#define TARGET_NR_process_vm_writev (TARGET_NR_Linux + 310) +#define TARGET_NR_kcmp (TARGET_NR_Linux + 311) +#define TARGET_NR_finit_module (TARGET_NR_Linux + 312) #else /* * Linux 64-bit syscalls are in the range from 5000 to 5999. @@ -617,4 +623,11 @@ #define TARGET_NR_open_by_handle_at (TARGET_NR_Linux + 299) #define TARGET_NR_clock_adjtime (TARGET_NR_Linux + 300) #define TARGET_NR_syncfs (TARGET_NR_Linux + 301) +#define TARGET_NR_sendmmsg (TARGET_NR_Linux + 302) +#define TARGET_NR_setns (TARGET_NR_Linux + 303) +#define TARGET_NR_process_vm_readv (TARGET_NR_Linux + 304) +#define TARGET_NR_process_vm_writev (TARGET_NR_Linux + 305) +#define TARGET_NR_kcmp (TARGET_NR_Linux + 306) +#define TARGET_NR_finit_module (TARGET_NR_Linux + 307) +#define TARGET_NR_getdents64 (TARGET_NR_Linux + 308) #endif diff --git a/linux-user/openrisc/syscall_nr.h b/linux-user/openrisc/syscall_nr.h index f4ac91ef71..4c386eae98 100644 --- a/linux-user/openrisc/syscall_nr.h +++ b/linux-user/openrisc/syscall_nr.h @@ -378,9 +378,13 @@ #define TARGET_NR_syncfs 267 #define TARGET_NR_setns 268 #define TARGET_NR_sendmmsg 269 +#define TARGET_NR_process_vm_readv 270 +#define TARGET_NR_process_vm_writev 271 +#define TARGET_NR_kcmp 272 +#define TARGET_NR_finit_module 273 #undef TARGET_NR_syscalls -#define TARGET_NR_syscalls 270 +#define TARGET_NR_syscalls 274 /* * All syscalls below here should go away really, diff --git a/linux-user/ppc/syscall_nr.h b/linux-user/ppc/syscall_nr.h index 0673b7d169..1e1736e11d 100644 --- a/linux-user/ppc/syscall_nr.h +++ b/linux-user/ppc/syscall_nr.h @@ -362,3 +362,9 @@ #define TARGET_NR_open_by_handle_at 346 #define TARGET_NR_clock_adjtime 347 #define TARGET_NR_syncfs 348 +#define TARGET_NR_sendmmsg 349 +#define TARGET_NR_setns 350 +#define TARGET_NR_process_vm_readv 351 +#define TARGET_NR_process_vm_writev 352 +#define TARGET_NR_finit_module 353 +#define TARGET_NR_kcmp 354 diff --git a/linux-user/s390x/syscall_nr.h b/linux-user/s390x/syscall_nr.h index d4529ac03c..7c0b8b2eaa 100644 --- a/linux-user/s390x/syscall_nr.h +++ b/linux-user/s390x/syscall_nr.h @@ -265,6 +265,12 @@ #define TARGET_NR_open_by_handle_at 336 #define TARGET_NR_clock_adjtime 337 #define TARGET_NR_syncfs 338 +#define TARGET_NR_setns 339 +#define TARGET_NR_process_vm_readv 340 +#define TARGET_NR_process_vm_writev 341 +#define TARGET_NR_s390_runtime_instr 342 +#define TARGET_NR_kcmp 343 +#define TARGET_NR_finit_module 344 /* * There are some system calls that are not present on 64 bit, some @@ -355,4 +361,3 @@ #define TARGET_NR_newfstatat 293 #endif - diff --git a/linux-user/sh4/syscall_nr.h b/linux-user/sh4/syscall_nr.h index 365db586c7..bdf8742c69 100644 --- a/linux-user/sh4/syscall_nr.h +++ b/linux-user/sh4/syscall_nr.h @@ -366,3 +366,9 @@ #define TARGET_NR_open_by_handle_at 360 #define TARGET_NR_clock_adjtime 361 #define TARGET_NR_syncfs 362 +#define TARGET_NR_sendmmsg 363 +#define TARGET_NR_setns 364 +#define TARGET_NR_process_vm_readv 365 +#define TARGET_NR_process_vm_writev 366 +#define TARGET_NR_kcmp 367 +#define TARGET_NR_finit_module 368 diff --git a/linux-user/signal.c b/linux-user/signal.c index 82e8592546..04638e2ead 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -420,6 +420,7 @@ static void QEMU_NORETURN force_sig(int target_sig) * it to arrive. */ sigfillset(&act.sa_mask); act.sa_handler = SIG_DFL; + act.sa_flags = 0; sigaction(host_sig, &act, NULL); /* For some reason raise(host_sig) doesn't send the signal when diff --git a/linux-user/sparc/syscall_nr.h b/linux-user/sparc/syscall_nr.h index 534e6e9963..181cd32653 100644 --- a/linux-user/sparc/syscall_nr.h +++ b/linux-user/sparc/syscall_nr.h @@ -302,3 +302,10 @@ #define TARGET_NR_open_by_handle_at 333 #define TARGET_NR_clock_adjtime 334 #define TARGET_NR_syncfs 335 +#define TARGET_NR_sendmmsg 336 +#define TARGET_NR_setns 337 +#define TARGET_NR_process_vm_readv 338 +#define TARGET_NR_process_vm_writev 339 +#define TARGET_NR_kern_features 340 +#define TARGET_NR_kcmp 341 +#define TARGET_NR_finit_module 342 diff --git a/linux-user/sparc64/syscall_nr.h b/linux-user/sparc64/syscall_nr.h index 70988b2ec9..34a984cc88 100644 --- a/linux-user/sparc64/syscall_nr.h +++ b/linux-user/sparc64/syscall_nr.h @@ -334,3 +334,10 @@ #define TARGET_NR_open_by_handle_at 333 #define TARGET_NR_clock_adjtime 334 #define TARGET_NR_syncfs 335 +#define TARGET_NR_sendmmsg 336 +#define TARGET_NR_setns 337 +#define TARGET_NR_process_vm_readv 338 +#define TARGET_NR_process_vm_writev 339 +#define TARGET_NR_kern_features 340 +#define TARGET_NR_kcmp 341 +#define TARGET_NR_finit_module 342 diff --git a/linux-user/syscall.c b/linux-user/syscall.c index f3700876a3..1407b7a546 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -107,6 +107,7 @@ int __clone2(int (*fn)(void *), void *child_stack_base, #include <linux/reboot.h> #include <linux/route.h> #include <linux/filter.h> +#include <linux/blkpg.h> #include "linux_loop.h" #include "cpu-uname.h" @@ -1707,6 +1708,7 @@ static struct iovec *lock_iovec(int type, abi_ulong target_addr, struct iovec *vec; abi_ulong total_len, max_len; int i; + int err = 0; if (count == 0) { errno = 0; @@ -1726,7 +1728,7 @@ static struct iovec *lock_iovec(int type, abi_ulong target_addr, target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1); if (target_vec == NULL) { - errno = EFAULT; + err = EFAULT; goto fail2; } @@ -1740,7 +1742,7 @@ static struct iovec *lock_iovec(int type, abi_ulong target_addr, abi_long len = tswapal(target_vec[i].iov_len); if (len < 0) { - errno = EINVAL; + err = EINVAL; goto fail; } else if (len == 0) { /* Zero length pointer is ignored. */ @@ -1748,7 +1750,7 @@ static struct iovec *lock_iovec(int type, abi_ulong target_addr, } else { vec[i].iov_base = lock_user(type, base, len, copy); if (!vec[i].iov_base) { - errno = EFAULT; + err = EFAULT; goto fail; } if (len > max_len - total_len) { @@ -1763,9 +1765,10 @@ static struct iovec *lock_iovec(int type, abi_ulong target_addr, return vec; fail: - free(vec); - fail2: unlock_user(target_vec, target_addr, 0); + fail2: + free(vec); + errno = err; return NULL; } @@ -2427,10 +2430,15 @@ static inline abi_long target_to_host_semarray(int semid, unsigned short **host_ nsems = semid_ds.sem_nsems; *host_array = malloc(nsems*sizeof(unsigned short)); + if (!*host_array) { + return -TARGET_ENOMEM; + } array = lock_user(VERIFY_READ, target_addr, nsems*sizeof(unsigned short), 1); - if (!array) + if (!array) { + free(*host_array); return -TARGET_EFAULT; + } for(i=0; i<nsems; i++) { __get_user((*host_array)[i], &array[i]); diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index ae30476217..3c8869e073 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -901,6 +901,7 @@ struct target_pollfd { #define TARGET_BLKSECTSET TARGET_IO(0x12,102)/* set max sectors per request (ll_rw_blk.c) */ #define TARGET_BLKSECTGET TARGET_IO(0x12,103)/* get max sectors per request (ll_rw_blk.c) */ #define TARGET_BLKSSZGET TARGET_IO(0x12,104)/* get block device sector size */ +#define TARGET_BLKPG TARGET_IO(0x12,105)/* Partition table and disk geometry handling */ /* A jump here: 108-111 have been used for various private purposes. */ #define TARGET_BLKBSZGET TARGET_IOR(0x12, 112, abi_ulong) #define TARGET_BLKBSZSET TARGET_IOW(0x12, 113, abi_ulong) diff --git a/linux-user/syscall_types.h b/linux-user/syscall_types.h index 44b6a58820..9d0c92d054 100644 --- a/linux-user/syscall_types.h +++ b/linux-user/syscall_types.h @@ -240,3 +240,16 @@ STRUCT(fiemap, TYPE_INT, /* fm_mapped_extents */ TYPE_INT, /* fm_extent_count */ TYPE_INT) /* fm_reserved */ + +STRUCT(blkpg_partition, + TYPE_LONGLONG, /* start */ + TYPE_LONGLONG, /* length */ + TYPE_INT, /* pno */ + MK_ARRAY(TYPE_CHAR, BLKPG_DEVNAMELTH), /* devname */ + MK_ARRAY(TYPE_CHAR, BLKPG_VOLNAMELTH)) /* volname */ + +STRUCT(blkpg_ioctl_arg, + TYPE_INT, /* op */ + TYPE_INT, /* flags */ + TYPE_INT, /* datalen */ + MK_PTR(MK_STRUCT(STRUCT_blkpg_partition))) /* data */ diff --git a/linux-user/x86_64/syscall_nr.h b/linux-user/x86_64/syscall_nr.h index 947e961ce4..7c59e3a09e 100644 --- a/linux-user/x86_64/syscall_nr.h +++ b/linux-user/x86_64/syscall_nr.h @@ -305,3 +305,10 @@ #define TARGET_NR_open_by_handle_at 304 #define TARGET_NR_clock_adjtime 305 #define TARGET_NR_syncfs 306 +#define TARGET_NR_sendmmsg 307 +#define TARGET_NR_setns 308 +#define TARGET_NR_getcpu 309 +#define TARGET_NR_process_vm_readv 310 +#define TARGET_NR_process_vm_writev 311 +#define TARGET_NR_kcmp 312 +#define TARGET_NR_finit_module 313 @@ -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/qapi-schema.json b/qapi-schema.json index 7cfb5e5d1e..473c096fa9 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -28,7 +28,65 @@ 'data': [ 'GenericError', 'CommandNotFound', 'DeviceEncrypted', 'DeviceNotActive', 'DeviceNotFound', 'KVMMissingCap' ] } + +## +# LostTickPolicy: +# +# Policy for handling lost ticks in timer devices. +# +# @discard: throw away the missed tick(s) and continue with future injection +# normally. Guest time may be delayed, unless the OS has explicit +# handling of lost ticks +# +# @delay: continue to deliver ticks at the normal rate. Guest time will be +# delayed due to the late tick +# +# @merge: merge the missed tick(s) into one tick and inject. Guest time +# may be delayed, depending on how the OS reacts to the merging +# of ticks +# +# @slew: deliver ticks at a higher rate to catch up with the missed tick. The +# guest time should not be delayed once catchup is complete. +# +# Since: 2.0 ## +{ 'enum': 'LostTickPolicy', + 'data': ['discard', 'delay', 'merge', 'slew' ] } + +## +# BiosAtaTranslation: +# +# Policy that BIOS should use to interpret cylinder/head/sector +# addresses. Note that Bochs BIOS and SeaBIOS will not actually +# translate logical CHS to physical; instead, they will use logical +# block addressing. +# +# @auto: If cylinder/heads/sizes are passed, choose between none and LBA +# depending on the size of the disk. If they are not passed, +# choose none if QEMU can guess that the disk had 16 or fewer +# heads, large if QEMU can guess that the disk had 131072 or +# fewer tracks across all heads (i.e. cylinders*heads<131072), +# otherwise LBA. +# +# @none: The physical disk geometry is equal to the logical geometry. +# +# @lba: Assume 63 sectors per track and one of 16, 32, 64, 128 or 255 +# heads (if fewer than 255 are enough to cover the whole disk +# with 1024 cylinders/head). The number of cylinders/head is +# then computed based on the number of sectors and heads. +# +# @large: The number of cylinders per head is scaled down to 1024 +# by correspondingly scaling up the number of heads. +# +# @rechs: Same as @large, but first convert a 16-head geometry to +# 15-head, by proportionally scaling up the number of +# cylinders/head. +# +# Since: 2.0 +## +{ 'enum': 'BiosAtaTranslation', + 'data': ['auto', 'none', 'lba', 'large', 'rechs']} + # @add_client # # Allow client connections for VNC, Spice and socket based @@ -437,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/qapi/string-input-visitor.c b/qapi/string-input-visitor.c index 8f1bc41333..793548ae3a 100644 --- a/qapi/string-input-visitor.c +++ b/qapi/string-input-visitor.c @@ -14,6 +14,7 @@ #include "qapi/string-input-visitor.h" #include "qapi/visitor-impl.h" #include "qapi/qmp/qerror.h" +#include "qemu/option.h" struct StringInputVisitor { @@ -41,6 +42,28 @@ static void parse_type_int(Visitor *v, int64_t *obj, const char *name, *obj = val; } +static void parse_type_size(Visitor *v, uint64_t *obj, const char *name, + Error **errp) +{ + StringInputVisitor *siv = DO_UPCAST(StringInputVisitor, visitor, v); + Error *err = NULL; + uint64_t val; + + if (siv->string) { + parse_option_size(name, siv->string, &val, &err); + } else { + error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null", + "size"); + return; + } + if (err) { + error_propagate(errp, err); + return; + } + + *obj = val; +} + static void parse_type_bool(Visitor *v, bool *obj, const char *name, Error **errp) { @@ -128,6 +151,7 @@ StringInputVisitor *string_input_visitor_new(const char *str) v->visitor.type_enum = input_type_enum; v->visitor.type_int = parse_type_int; + v->visitor.type_size = parse_type_size; v->visitor.type_bool = parse_type_bool; v->visitor.type_str = parse_type_str; v->visitor.type_number = parse_type_number; diff --git a/qapi/string-output-visitor.c b/qapi/string-output-visitor.c index 921653d425..fb1d2e806d 100644 --- a/qapi/string-output-visitor.c +++ b/qapi/string-output-visitor.c @@ -14,10 +14,13 @@ #include "qapi/string-output-visitor.h" #include "qapi/visitor-impl.h" #include "qapi/qmp/qerror.h" +#include "qemu/host-utils.h" +#include <math.h> struct StringOutputVisitor { Visitor visitor; + bool human; char *string; }; @@ -31,7 +34,45 @@ static void print_type_int(Visitor *v, int64_t *obj, const char *name, Error **errp) { StringOutputVisitor *sov = DO_UPCAST(StringOutputVisitor, visitor, v); - string_output_set(sov, g_strdup_printf("%lld", (long long) *obj)); + char *out; + + if (sov->human) { + out = g_strdup_printf("%lld (%#llx)", (long long) *obj, (long long) *obj); + } else { + out = g_strdup_printf("%lld", (long long) *obj); + } + string_output_set(sov, out); +} + +static void print_type_size(Visitor *v, uint64_t *obj, const char *name, + Error **errp) +{ + StringOutputVisitor *sov = DO_UPCAST(StringOutputVisitor, visitor, v); + static const char suffixes[] = { 'B', 'K', 'M', 'G', 'T', 'P', 'E' }; + uint64_t div, val; + char *out; + int i; + + if (!sov->human) { + out = g_strdup_printf("%"PRIu64, *obj); + string_output_set(sov, out); + return; + } + + val = *obj; + + /* The exponent (returned in i) minus one gives us + * floor(log2(val * 1024 / 1000). The correction makes us + * switch to the higher power when the integer part is >= 1000. + */ + frexp(val / (1000.0 / 1024.0), &i); + i = (i - 1) / 10; + assert(i < ARRAY_SIZE(suffixes)); + div = 1ULL << (i * 10); + + out = g_strdup_printf("%"PRIu64" (%0.3g %c%s)", val, + (double)val/div, suffixes[i], i ? "iB" : ""); + string_output_set(sov, out); } static void print_type_bool(Visitor *v, bool *obj, const char *name, @@ -45,7 +86,14 @@ static void print_type_str(Visitor *v, char **obj, const char *name, Error **errp) { StringOutputVisitor *sov = DO_UPCAST(StringOutputVisitor, visitor, v); - string_output_set(sov, g_strdup(*obj ? *obj : "")); + char *out; + + if (sov->human) { + out = *obj ? g_strdup_printf("\"%s\"", *obj) : g_strdup("<null>"); + } else { + out = g_strdup(*obj ? *obj : ""); + } + string_output_set(sov, out); } static void print_type_number(Visitor *v, double *obj, const char *name, @@ -73,14 +121,16 @@ void string_output_visitor_cleanup(StringOutputVisitor *sov) g_free(sov); } -StringOutputVisitor *string_output_visitor_new(void) +StringOutputVisitor *string_output_visitor_new(bool human) { StringOutputVisitor *v; v = g_malloc0(sizeof(*v)); + v->human = human; v->visitor.type_enum = output_type_enum; v->visitor.type_int = print_type_int; + v->visitor.type_size = print_type_size; v->visitor.type_bool = print_type_bool; v->visitor.type_str = print_type_str; v->visitor.type_number = print_type_number; diff --git a/qdev-monitor.c b/qdev-monitor.c index 1d3b68d40a..3a7dc0d428 100644 --- a/qdev-monitor.c +++ b/qdev-monitor.c @@ -145,7 +145,7 @@ static void qdev_print_devinfos(bool show_no_user) static int set_property(const char *name, const char *value, void *opaque) { - DeviceState *dev = opaque; + Object *obj = opaque; Error *err = NULL; if (strcmp(name, "driver") == 0) @@ -153,7 +153,7 @@ static int set_property(const char *name, const char *value, void *opaque) if (strcmp(name, "bus") == 0) return 0; - qdev_prop_parse(dev, name, value, &err); + object_property_parse(obj, value, name, &err); if (err != NULL) { qerror_report_err(err); error_free(err); @@ -577,7 +577,7 @@ static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props, if (object_property_get_type(OBJECT(dev), legacy_name, NULL)) { value = object_property_get_str(OBJECT(dev), legacy_name, &err); } else { - value = object_property_print(OBJECT(dev), props->name, &err); + value = object_property_print(OBJECT(dev), props->name, true, &err); } g_free(legacy_name); @@ -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 45fcddd47b..1e5eaf0ac8 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 ----------- diff --git a/qom/object.c b/qom/object.c index 62e7e415d9..660859c0e7 100644 --- a/qom/object.c +++ b/qom/object.c @@ -948,13 +948,13 @@ void object_property_parse(Object *obj, const char *string, string_input_visitor_cleanup(mi); } -char *object_property_print(Object *obj, const char *name, +char *object_property_print(Object *obj, const char *name, bool human, Error **errp) { StringOutputVisitor *mo; char *string; - mo = string_output_visitor_new(); + mo = string_output_visitor_new(human); object_property_get(obj, string_output_get_visitor(mo), name, errp); string = string_output_get_string(mo); string_output_visitor_cleanup(mo); @@ -507,12 +507,18 @@ int qtest_init_accel(void) return 0; } -void qtest_init(const char *qtest_chrdev, const char *qtest_log) +void qtest_init(const char *qtest_chrdev, const char *qtest_log, Error **errp) { CharDriverState *chr; chr = qemu_chr_new("qtest", qtest_chrdev, NULL); + if (chr == NULL) { + error_setg(errp, "Failed to initialize device for qtest: \"%s\"", + qtest_chrdev); + return; + } + qemu_chr_add_handlers(chr, qtest_can_read, qtest_read, qtest_event, chr); qemu_chr_fe_set_echo(chr, true); @@ -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/tracetool/backend/ust.py b/scripts/tracetool/backend/ust.py index ea36995092..41c1c75b7c 100644 --- a/scripts/tracetool/backend/ust.py +++ b/scripts/tracetool/backend/ust.py @@ -18,76 +18,65 @@ from tracetool import out PUBLIC = True - def c(events): - out('#include <ust/marker.h>', - '#undef mutex_lock', - '#undef mutex_unlock', - '#undef inline', - '#undef wmb', - '#include "trace.h"') + pass + +def h(events): + out('#include <lttng/tracepoint.h>', + '#include "trace/generated-ust-provider.h"', + '') for e in events: argnames = ", ".join(e.args.names()) if len(e.args) > 0: - argnames = ', ' + argnames - - out('DEFINE_TRACE(ust_%(name)s);', - '', - 'static void ust_%(name)s_probe(%(args)s)', - '{', - ' trace_mark(ust, %(name)s, %(fmt)s%(argnames)s);', - '}', - name = e.name, - args = e.args, - fmt = e.fmt, - argnames = argnames, - ) - - else: - out('DEFINE_TRACE(ust_%(name)s);', - '', - 'static void ust_%(name)s_probe(%(args)s)', - '{', - ' trace_mark(ust, %(name)s, UST_MARKER_NOARGS);', - '}', - name = e.name, - args = e.args, - ) - - # register probes - out('', - 'static void __attribute__((constructor)) trace_init(void)', - '{') + argnames = ", " + argnames - for e in events: - out(' register_trace_ust_%(name)s(ust_%(name)s_probe);', + out('static inline void trace_%(name)s(%(args)s)', + '{', + ' tracepoint(qemu, %(name)s%(tp_args)s);', + '}', + '', name = e.name, + args = e.args, + tp_args = argnames, ) - out('}') - - -def h(events): - out('#include <ust/tracepoint.h>', - '#undef mutex_lock', - '#undef mutex_unlock', - '#undef inline', - '#undef wmb') +def ust_events_c(events): + pass +def ust_events_h(events): for e in events: if len(e.args) > 0: - out('DECLARE_TRACE(ust_%(name)s, TP_PROTO(%(args)s), TP_ARGS(%(argnames)s));', - '#define trace_%(name)s trace_ust_%(name)s', + out('TRACEPOINT_EVENT(', + ' qemu,', + ' %(name)s,', + ' TP_ARGS(%(args)s),', + ' TP_FIELDS(', name = e.name, - args = e.args, - argnames = ", ".join(e.args.names()), + args = ", ".join(", ".join(i) for i in e.args), ) + for t,n in e.args: + if ('int' in t) or ('long' in t) or ('unsigned' in t) or ('size_t' in t): + out(' ctf_integer(' + t + ', ' + n + ', ' + n + ')') + elif ('double' in t) or ('float' in t): + out(' ctf_float(' + t + ', ' + n + ', ' + n + ')') + elif ('char *' in t) or ('char*' in t): + out(' ctf_string(' + n + ', ' + n + ')') + elif ('void *' in t) or ('void*' in t): + out(' ctf_integer_hex(unsigned long, ' + n + ', ' + n + ')') + + out(' )', + ')', + '') + else: - out('_DECLARE_TRACEPOINT_NOARGS(ust_%(name)s);', - '#define trace_%(name)s trace_ust_%(name)s', + out('TRACEPOINT_EVENT(', + ' qemu,', + ' %(name)s,', + ' TP_ARGS(void),', + ' TP_FIELDS()', + ')', + '', name = e.name, - ) - - out() + )
\ No newline at end of file diff --git a/scripts/tracetool/format/ust_events_c.py b/scripts/tracetool/format/ust_events_c.py new file mode 100644 index 0000000000..116e713225 --- /dev/null +++ b/scripts/tracetool/format/ust_events_c.py @@ -0,0 +1,30 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +""" +Generate .c for LTTng ust event description. +""" + +__author__ = "Mohamad Gebai <mohamad.gebai@polymtl.ca>" +__copyright__ = "Copyright 2012, Mohamad Gebai <mohamad.gebai@polymtl.ca>" +__license__ = "GPL version 2 or (at your option) any later version" + +__maintainer__ = "Stefan Hajnoczi" +__email__ = "stefanha@redhat.com" + + +from tracetool import out + + +def begin(events): + out('/* This file is autogenerated by tracetool, do not edit. */', + '', + '#define TRACEPOINT_DEFINE', + '#define TRACEPOINT_CREATE_PROBES', + '', + '/* If gcc version 4.7 or older is used, LTTng ust gives a warning when compiling with', + ' -Wredundant-decls.', + ' */', + '#pragma GCC diagnostic ignored "-Wredundant-decls"', + '', + '#include "generated-ust-provider.h"') diff --git a/scripts/tracetool/format/ust_events_h.py b/scripts/tracetool/format/ust_events_h.py new file mode 100644 index 0000000000..f206eca6ec --- /dev/null +++ b/scripts/tracetool/format/ust_events_h.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +""" +Generate .h for LTTng ust event description. +""" + +__author__ = "Mohamad Gebai <mohamad.gebai@polymtl.ca>" +__copyright__ = "Copyright 2012, Mohamad Gebai <mohamad.gebai@polymtl.ca>" +__license__ = "GPL version 2 or (at your option) any later version" + +__maintainer__ = "Stefan Hajnoczi" +__email__ = "stefanha@redhat.com" + + +from tracetool import out + + +def begin(events): + out('/* This file is autogenerated by tracetool, do not edit. */', + '', + '#undef TRACEPOINT_PROVIDER', + '#define TRACEPOINT_PROVIDER qemu', + '', + '#undef TRACEPOINT_INCLUDE_FILE', + '#define TRACEPOINT_INCLUDE_FILE ./generated-ust-provider.h', + '', + '#if !defined (TRACE__GENERATED_UST_H) || defined(TRACEPOINT_HEADER_MULTI_READ)', + '#define TRACE__GENERATED_UST_H', + '', + '#include "qemu-common.h"', + '#include <lttng/tracepoint.h>', + '', + '/*', + ' * LTTng ust 2.0 does not allow you to use TP_ARGS(void) for tracepoints', + ' * requiring no arguments. We define these macros introduced in more recent' + ' * versions of LTTng ust as a workaround', + ' */', + '#ifndef _TP_EXPROTO1', + '#define _TP_EXPROTO1(a) void', + '#endif', + '#ifndef _TP_EXDATA_PROTO1', + '#define _TP_EXDATA_PROTO1(a) void *__tp_data', + '#endif', + '#ifndef _TP_EXDATA_VAR1', + '#define _TP_EXDATA_VAR1(a) __tp_data', + '#endif', + '#ifndef _TP_EXVAR1', + '#define _TP_EXVAR1(a)', + '#endif', + '') + +def end(events): + out('#endif /* TRACE__GENERATED_UST_H */', + '', + '/* This part must be outside ifdef protection */', + '#include <lttng/tracepoint-event.h>') diff --git a/target-arm/cpu.c b/target-arm/cpu.c index 45ad7f0260..6e7ce8905e 100644 --- a/target-arm/cpu.c +++ b/target-arm/cpu.c @@ -128,7 +128,7 @@ static void arm_cpu_reset(CPUState *s) } } - if (env->cp15.c1_sys & (1 << 13)) { + if (env->cp15.c1_sys & SCTLR_V) { env->regs[15] = 0xFFFF0000; } @@ -681,14 +681,12 @@ static void cortex_a9_initfn(Object *obj) } #ifndef CONFIG_USER_ONLY -static int a15_l2ctlr_read(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t *value) +static uint64_t a15_l2ctlr_read(CPUARMState *env, const ARMCPRegInfo *ri) { /* Linux wants the number of processors from here. * Might as well set the interrupt-controller bit too. */ - *value = ((smp_cpus - 1) << 24) | (1 << 23); - return 0; + return ((smp_cpus - 1) << 24) | (1 << 23); } #endif diff --git a/target-arm/cpu.h b/target-arm/cpu.h index 383c58221e..3c8a2dba2f 100644 --- a/target-arm/cpu.h +++ b/target-arm/cpu.h @@ -217,11 +217,6 @@ typedef struct CPUARMState { uint32_t c15_power_control; /* power control */ } cp15; - /* System registers (AArch64) */ - struct { - uint64_t tpidr_el0; - } sr; - struct { uint32_t other_sp; uint32_t vecbase; @@ -337,6 +332,58 @@ int cpu_arm_handle_mmu_fault (CPUARMState *env, target_ulong address, int rw, int mmu_idx); #define cpu_handle_mmu_fault cpu_arm_handle_mmu_fault +/* SCTLR bit meanings. Several bits have been reused in newer + * versions of the architecture; in that case we define constants + * for both old and new bit meanings. Code which tests against those + * bits should probably check or otherwise arrange that the CPU + * is the architectural version it expects. + */ +#define SCTLR_M (1U << 0) +#define SCTLR_A (1U << 1) +#define SCTLR_C (1U << 2) +#define SCTLR_W (1U << 3) /* up to v6; RAO in v7 */ +#define SCTLR_SA (1U << 3) +#define SCTLR_P (1U << 4) /* up to v5; RAO in v6 and v7 */ +#define SCTLR_SA0 (1U << 4) /* v8 onward, AArch64 only */ +#define SCTLR_D (1U << 5) /* up to v5; RAO in v6 */ +#define SCTLR_CP15BEN (1U << 5) /* v7 onward */ +#define SCTLR_L (1U << 6) /* up to v5; RAO in v6 and v7; RAZ in v8 */ +#define SCTLR_B (1U << 7) /* up to v6; RAZ in v7 */ +#define SCTLR_ITD (1U << 7) /* v8 onward */ +#define SCTLR_S (1U << 8) /* up to v6; RAZ in v7 */ +#define SCTLR_SED (1U << 8) /* v8 onward */ +#define SCTLR_R (1U << 9) /* up to v6; RAZ in v7 */ +#define SCTLR_UMA (1U << 9) /* v8 onward, AArch64 only */ +#define SCTLR_F (1U << 10) /* up to v6 */ +#define SCTLR_SW (1U << 10) /* v7 onward */ +#define SCTLR_Z (1U << 11) +#define SCTLR_I (1U << 12) +#define SCTLR_V (1U << 13) +#define SCTLR_RR (1U << 14) /* up to v7 */ +#define SCTLR_DZE (1U << 14) /* v8 onward, AArch64 only */ +#define SCTLR_L4 (1U << 15) /* up to v6; RAZ in v7 */ +#define SCTLR_UCT (1U << 15) /* v8 onward, AArch64 only */ +#define SCTLR_DT (1U << 16) /* up to ??, RAO in v6 and v7 */ +#define SCTLR_nTWI (1U << 16) /* v8 onward */ +#define SCTLR_HA (1U << 17) +#define SCTLR_IT (1U << 18) /* up to ??, RAO in v6 and v7 */ +#define SCTLR_nTWE (1U << 18) /* v8 onward */ +#define SCTLR_WXN (1U << 19) +#define SCTLR_ST (1U << 20) /* up to ??, RAZ in v6 */ +#define SCTLR_UWXN (1U << 20) /* v7 onward */ +#define SCTLR_FI (1U << 21) +#define SCTLR_U (1U << 22) +#define SCTLR_XP (1U << 23) /* up to v6; v7 onward RAO */ +#define SCTLR_VE (1U << 24) /* up to v7 */ +#define SCTLR_E0E (1U << 24) /* v8 onward, AArch64 only */ +#define SCTLR_EE (1U << 25) +#define SCTLR_L2 (1U << 26) /* up to v6, RAZ in v7 */ +#define SCTLR_UCI (1U << 26) /* v8 onward, AArch64 only */ +#define SCTLR_NMFI (1U << 27) +#define SCTLR_TRE (1U << 28) +#define SCTLR_AFE (1U << 29) +#define SCTLR_TE (1U << 30) + #define CPSR_M (0x1fU) #define CPSR_T (1U << 5) #define CPSR_F (1U << 6) @@ -764,14 +811,30 @@ static inline int arm_current_pl(CPUARMState *env) typedef struct ARMCPRegInfo ARMCPRegInfo; -/* Access functions for coprocessor registers. These should return - * 0 on success, or one of the EXCP_* constants if access should cause - * an exception (in which case *value is not written). +typedef enum CPAccessResult { + /* Access is permitted */ + CP_ACCESS_OK = 0, + /* Access fails due to a configurable trap or enable which would + * result in a categorized exception syndrome giving information about + * the failing instruction (ie syndrome category 0x3, 0x4, 0x5, 0x6, + * 0xc or 0x18). + */ + CP_ACCESS_TRAP = 1, + /* Access fails and results in an exception syndrome 0x0 ("uncategorized"). + * Note that this is not a catch-all case -- the set of cases which may + * result in this failure is specifically defined by the architecture. + */ + CP_ACCESS_TRAP_UNCATEGORIZED = 2, +} CPAccessResult; + +/* Access functions for coprocessor registers. These cannot fail and + * may not raise exceptions. */ -typedef int CPReadFn(CPUARMState *env, const ARMCPRegInfo *opaque, - uint64_t *value); -typedef int CPWriteFn(CPUARMState *env, const ARMCPRegInfo *opaque, - uint64_t value); +typedef uint64_t CPReadFn(CPUARMState *env, const ARMCPRegInfo *opaque); +typedef void CPWriteFn(CPUARMState *env, const ARMCPRegInfo *opaque, + uint64_t value); +/* Access permission check functions for coprocessor registers. */ +typedef CPAccessResult CPAccessFn(CPUARMState *env, const ARMCPRegInfo *opaque); /* Hook function for register reset */ typedef void CPResetFn(CPUARMState *env, const ARMCPRegInfo *opaque); @@ -825,6 +888,12 @@ struct ARMCPRegInfo { * 2. both readfn and writefn are specified */ ptrdiff_t fieldoffset; /* offsetof(CPUARMState, field) */ + /* Function for making any access checks for this register in addition to + * those specified by the 'access' permissions bits. If NULL, no extra + * checks required. The access check is performed at runtime, not at + * translate time. + */ + CPAccessFn *accessfn; /* Function for handling reads of this register. If NULL, then reads * will be done by loading from the offset into CPUARMState specified * by fieldoffset. @@ -838,14 +907,14 @@ struct ARMCPRegInfo { /* Function for doing a "raw" read; used when we need to copy * coprocessor state to the kernel for KVM or out for * migration. This only needs to be provided if there is also a - * readfn and it makes an access permission check. + * readfn and it has side effects (for instance clear-on-read bits). */ CPReadFn *raw_readfn; /* Function for doing a "raw" write; used when we need to copy KVM * kernel coprocessor state into userspace, or for inbound * migration. This only needs to be provided if there is also a - * writefn and it makes an access permission check or masks out - * "unwritable" bits or has write-one-to-clear or similar behaviour. + * writefn and it masks out "unwritable" bits or has write-one-to-clear + * or similar behaviour. */ CPWriteFn *raw_writefn; /* Function for resetting the register. If NULL, then reset will be done @@ -880,10 +949,10 @@ static inline void define_one_arm_cp_reg(ARMCPU *cpu, const ARMCPRegInfo *regs) const ARMCPRegInfo *get_arm_cp_reginfo(GHashTable *cpregs, uint32_t encoded_cp); /* CPWriteFn that can be used to implement writes-ignored behaviour */ -int arm_cp_write_ignore(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value); +void arm_cp_write_ignore(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value); /* CPReadFn that can be used for read-as-zero behaviour */ -int arm_cp_read_zero(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t *value); +uint64_t arm_cp_read_zero(CPUARMState *env, const ARMCPRegInfo *ri); /* CPResetFn that does nothing, for use if no reset is required even * if fieldoffset is non zero. diff --git a/target-arm/helper-a64.c b/target-arm/helper-a64.c index 6ca958afb1..c2ce33ee88 100644 --- a/target-arm/helper-a64.c +++ b/target-arm/helper-a64.c @@ -123,6 +123,32 @@ uint64_t HELPER(vfp_cmped_a64)(float64 x, float64 y, void *fp_status) return float_rel_to_flags(float64_compare(x, y, fp_status)); } +float32 HELPER(vfp_mulxs)(float32 a, float32 b, void *fpstp) +{ + float_status *fpst = fpstp; + + if ((float32_is_zero(a) && float32_is_infinity(b)) || + (float32_is_infinity(a) && float32_is_zero(b))) { + /* 2.0 with the sign bit set to sign(A) XOR sign(B) */ + return make_float32((1U << 30) | + ((float32_val(a) ^ float32_val(b)) & (1U << 31))); + } + return float32_mul(a, b, fpst); +} + +float64 HELPER(vfp_mulxd)(float64 a, float64 b, void *fpstp) +{ + float_status *fpst = fpstp; + + if ((float64_is_zero(a) && float64_is_infinity(b)) || + (float64_is_infinity(a) && float64_is_zero(b))) { + /* 2.0 with the sign bit set to sign(A) XOR sign(B) */ + return make_float64((1ULL << 62) | + ((float64_val(a) ^ float64_val(b)) & (1ULL << 63))); + } + return float64_mul(a, b, fpst); +} + uint64_t HELPER(simd_tbl)(CPUARMState *env, uint64_t result, uint64_t indices, uint32_t rn, uint32_t numregs) { @@ -153,3 +179,82 @@ uint64_t HELPER(simd_tbl)(CPUARMState *env, uint64_t result, uint64_t indices, } return result; } + +/* 64bit/double versions of the neon float compare functions */ +uint64_t HELPER(neon_ceq_f64)(float64 a, float64 b, void *fpstp) +{ + float_status *fpst = fpstp; + return -float64_eq_quiet(a, b, fpst); +} + +uint64_t HELPER(neon_cge_f64)(float64 a, float64 b, void *fpstp) +{ + float_status *fpst = fpstp; + return -float64_le(b, a, fpst); +} + +uint64_t HELPER(neon_cgt_f64)(float64 a, float64 b, void *fpstp) +{ + float_status *fpst = fpstp; + return -float64_lt(b, a, fpst); +} + +/* Reciprocal step and sqrt step. Note that unlike the A32/T32 + * versions, these do a fully fused multiply-add or + * multiply-add-and-halve. + */ +#define float32_two make_float32(0x40000000) +#define float32_three make_float32(0x40400000) +#define float32_one_point_five make_float32(0x3fc00000) + +#define float64_two make_float64(0x4000000000000000ULL) +#define float64_three make_float64(0x4008000000000000ULL) +#define float64_one_point_five make_float64(0x3FF8000000000000ULL) + +float32 HELPER(recpsf_f32)(float32 a, float32 b, void *fpstp) +{ + float_status *fpst = fpstp; + + a = float32_chs(a); + if ((float32_is_infinity(a) && float32_is_zero(b)) || + (float32_is_infinity(b) && float32_is_zero(a))) { + return float32_two; + } + return float32_muladd(a, b, float32_two, 0, fpst); +} + +float64 HELPER(recpsf_f64)(float64 a, float64 b, void *fpstp) +{ + float_status *fpst = fpstp; + + a = float64_chs(a); + if ((float64_is_infinity(a) && float64_is_zero(b)) || + (float64_is_infinity(b) && float64_is_zero(a))) { + return float64_two; + } + return float64_muladd(a, b, float64_two, 0, fpst); +} + +float32 HELPER(rsqrtsf_f32)(float32 a, float32 b, void *fpstp) +{ + float_status *fpst = fpstp; + + a = float32_chs(a); + if ((float32_is_infinity(a) && float32_is_zero(b)) || + (float32_is_infinity(b) && float32_is_zero(a))) { + return float32_one_point_five; + } + return float32_muladd(a, b, float32_three, float_muladd_halve_result, fpst); +} + +float64 HELPER(rsqrtsf_f64)(float64 a, float64 b, void *fpstp) +{ + float_status *fpst = fpstp; + + a = float64_chs(a); + if ((float64_is_infinity(a) && float64_is_zero(b)) || + (float64_is_infinity(b) && float64_is_zero(a))) { + return float64_one_point_five; + } + return float64_muladd(a, b, float64_three, float_muladd_halve_result, fpst); +} diff --git a/target-arm/helper-a64.h b/target-arm/helper-a64.h index 99832ee55e..ab9933cab0 100644 --- a/target-arm/helper-a64.h +++ b/target-arm/helper-a64.h @@ -27,3 +27,12 @@ DEF_HELPER_3(vfp_cmpes_a64, i64, f32, f32, ptr) DEF_HELPER_3(vfp_cmpd_a64, i64, f64, f64, ptr) DEF_HELPER_3(vfp_cmped_a64, i64, f64, f64, ptr) DEF_HELPER_FLAGS_5(simd_tbl, TCG_CALL_NO_RWG_SE, i64, env, i64, i64, i32, i32) +DEF_HELPER_FLAGS_3(vfp_mulxs, TCG_CALL_NO_RWG, f32, f32, f32, ptr) +DEF_HELPER_FLAGS_3(vfp_mulxd, TCG_CALL_NO_RWG, f64, f64, f64, ptr) +DEF_HELPER_FLAGS_3(neon_ceq_f64, TCG_CALL_NO_RWG, i64, i64, i64, ptr) +DEF_HELPER_FLAGS_3(neon_cge_f64, TCG_CALL_NO_RWG, i64, i64, i64, ptr) +DEF_HELPER_FLAGS_3(neon_cgt_f64, TCG_CALL_NO_RWG, i64, i64, i64, ptr) +DEF_HELPER_FLAGS_3(recpsf_f32, TCG_CALL_NO_RWG, f32, f32, f32, ptr) +DEF_HELPER_FLAGS_3(recpsf_f64, TCG_CALL_NO_RWG, f64, f64, f64, ptr) +DEF_HELPER_FLAGS_3(rsqrtsf_f32, TCG_CALL_NO_RWG, f32, f32, f32, ptr) +DEF_HELPER_FLAGS_3(rsqrtsf_f64, TCG_CALL_NO_RWG, f64, f64, f64, ptr) diff --git a/target-arm/helper.c b/target-arm/helper.c index 5ae08c9ad1..1b111b6e85 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -107,65 +107,56 @@ static int aarch64_fpu_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg) } } -static int raw_read(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t *value) +static uint64_t raw_read(CPUARMState *env, const ARMCPRegInfo *ri) { if (ri->type & ARM_CP_64BIT) { - *value = CPREG_FIELD64(env, ri); + return CPREG_FIELD64(env, ri); } else { - *value = CPREG_FIELD32(env, ri); + return CPREG_FIELD32(env, ri); } - return 0; } -static int raw_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) +static void raw_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) { if (ri->type & ARM_CP_64BIT) { CPREG_FIELD64(env, ri) = value; } else { CPREG_FIELD32(env, ri) = value; } - return 0; } -static bool read_raw_cp_reg(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t *v) +static uint64_t read_raw_cp_reg(CPUARMState *env, const ARMCPRegInfo *ri) { - /* Raw read of a coprocessor register (as needed for migration, etc) - * return true on success, false if the read is impossible for some reason. - */ + /* Raw read of a coprocessor register (as needed for migration, etc). */ if (ri->type & ARM_CP_CONST) { - *v = ri->resetvalue; + return ri->resetvalue; } else if (ri->raw_readfn) { - return (ri->raw_readfn(env, ri, v) == 0); + return ri->raw_readfn(env, ri); } else if (ri->readfn) { - return (ri->readfn(env, ri, v) == 0); + return ri->readfn(env, ri); } else { - raw_read(env, ri, v); + return raw_read(env, ri); } - return true; } -static bool write_raw_cp_reg(CPUARMState *env, const ARMCPRegInfo *ri, - int64_t v) +static void write_raw_cp_reg(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t v) { /* Raw write of a coprocessor register (as needed for migration, etc). - * Return true on success, false if the write is impossible for some reason. * Note that constant registers are treated as write-ignored; the * caller should check for success by whether a readback gives the * value written. */ if (ri->type & ARM_CP_CONST) { - return true; + return; } else if (ri->raw_writefn) { - return (ri->raw_writefn(env, ri, v) == 0); + ri->raw_writefn(env, ri, v); } else if (ri->writefn) { - return (ri->writefn(env, ri, v) == 0); + ri->writefn(env, ri, v); } else { raw_write(env, ri, v); } - return true; } bool write_cpustate_to_list(ARMCPU *cpu) @@ -177,7 +168,7 @@ bool write_cpustate_to_list(ARMCPU *cpu) for (i = 0; i < cpu->cpreg_array_len; i++) { uint32_t regidx = kvm_to_cpreg_id(cpu->cpreg_indexes[i]); const ARMCPRegInfo *ri; - uint64_t v; + ri = get_arm_cp_reginfo(cpu->cp_regs, regidx); if (!ri) { ok = false; @@ -186,11 +177,7 @@ bool write_cpustate_to_list(ARMCPU *cpu) if (ri->type & ARM_CP_NO_MIGRATE) { continue; } - if (!read_raw_cp_reg(&cpu->env, ri, &v)) { - ok = false; - continue; - } - cpu->cpreg_values[i] = v; + cpu->cpreg_values[i] = read_raw_cp_reg(&cpu->env, ri); } return ok; } @@ -203,7 +190,6 @@ bool write_list_to_cpustate(ARMCPU *cpu) for (i = 0; i < cpu->cpreg_array_len; i++) { uint32_t regidx = kvm_to_cpreg_id(cpu->cpreg_indexes[i]); uint64_t v = cpu->cpreg_values[i]; - uint64_t readback; const ARMCPRegInfo *ri; ri = get_arm_cp_reginfo(cpu->cp_regs, regidx); @@ -218,9 +204,8 @@ bool write_list_to_cpustate(ARMCPU *cpu) * (to catch read-only registers and partially read-only * registers where the incoming migration value doesn't match) */ - if (!write_raw_cp_reg(&cpu->env, ri, v) || - !read_raw_cp_reg(&cpu->env, ri, &readback) || - readback != v) { + write_raw_cp_reg(&cpu->env, ri, v); + if (read_raw_cp_reg(&cpu->env, ri) != v) { ok = false; } } @@ -309,14 +294,13 @@ void init_cpreg_list(ARMCPU *cpu) g_list_free(keys); } -static int dacr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) +static void dacr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) { env->cp15.c3 = value; tlb_flush(env, 1); /* Flush TLB as domain not tracked in TLB */ - return 0; } -static int fcse_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) +static void fcse_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) { if (env->cp15.c13_fcse != value) { /* Unlike real hardware the qemu TLB uses virtual addresses, @@ -325,10 +309,10 @@ static int fcse_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) tlb_flush(env, 1); env->cp15.c13_fcse = value; } - return 0; } -static int contextidr_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) + +static void contextidr_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) { if (env->cp15.c13_context != value && !arm_feature(env, ARM_FEATURE_MPU)) { /* For VMSA (when not using the LPAE long descriptor page table @@ -338,39 +322,34 @@ static int contextidr_write(CPUARMState *env, const ARMCPRegInfo *ri, tlb_flush(env, 1); } env->cp15.c13_context = value; - return 0; } -static int tlbiall_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) +static void tlbiall_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) { /* Invalidate all (TLBIALL) */ tlb_flush(env, 1); - return 0; } -static int tlbimva_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) +static void tlbimva_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) { /* Invalidate single TLB entry by MVA and ASID (TLBIMVA) */ tlb_flush_page(env, value & TARGET_PAGE_MASK); - return 0; } -static int tlbiasid_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) +static void tlbiasid_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) { /* Invalidate by ASID (TLBIASID) */ tlb_flush(env, value == 0); - return 0; } -static int tlbimvaa_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) +static void tlbimvaa_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) { /* Invalidate single entry by MVA, all ASIDs (TLBIMVAA) */ tlb_flush_page(env, value & TARGET_PAGE_MASK); - return 0; } static const ARMCPRegInfo cp_reginfo[] = { @@ -450,14 +429,14 @@ static const ARMCPRegInfo not_v7_cp_reginfo[] = { REGINFO_SENTINEL }; -static int cpacr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) +static void cpacr_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) { if (env->cp15.c1_coproc != value) { env->cp15.c1_coproc = value; /* ??? Is this safe when called from within a TB? */ tb_flush(env); } - return 0; } static const ARMCPRegInfo v6_cp_reginfo[] = { @@ -485,118 +464,88 @@ static const ARMCPRegInfo v6_cp_reginfo[] = { REGINFO_SENTINEL }; - -static int pmreg_read(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t *value) +static CPAccessResult pmreg_access(CPUARMState *env, const ARMCPRegInfo *ri) { - /* Generic performance monitor register read function for where - * user access may be allowed by PMUSERENR. + /* Perfomance monitor registers user accessibility is controlled + * by PMUSERENR. */ if (arm_current_pl(env) == 0 && !env->cp15.c9_pmuserenr) { - return EXCP_UDEF; + return CP_ACCESS_TRAP; } - *value = CPREG_FIELD32(env, ri); - return 0; + return CP_ACCESS_OK; } -static int pmcr_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) +static void pmcr_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) { - if (arm_current_pl(env) == 0 && !env->cp15.c9_pmuserenr) { - return EXCP_UDEF; - } /* only the DP, X, D and E bits are writable */ env->cp15.c9_pmcr &= ~0x39; env->cp15.c9_pmcr |= (value & 0x39); - return 0; } -static int pmcntenset_write(CPUARMState *env, const ARMCPRegInfo *ri, +static void pmcntenset_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) { - if (arm_current_pl(env) == 0 && !env->cp15.c9_pmuserenr) { - return EXCP_UDEF; - } value &= (1 << 31); env->cp15.c9_pmcnten |= value; - return 0; } -static int pmcntenclr_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) +static void pmcntenclr_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) { - if (arm_current_pl(env) == 0 && !env->cp15.c9_pmuserenr) { - return EXCP_UDEF; - } value &= (1 << 31); env->cp15.c9_pmcnten &= ~value; - return 0; } -static int pmovsr_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) +static void pmovsr_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) { - if (arm_current_pl(env) == 0 && !env->cp15.c9_pmuserenr) { - return EXCP_UDEF; - } env->cp15.c9_pmovsr &= ~value; - return 0; } -static int pmxevtyper_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) +static void pmxevtyper_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) { - if (arm_current_pl(env) == 0 && !env->cp15.c9_pmuserenr) { - return EXCP_UDEF; - } env->cp15.c9_pmxevtyper = value & 0xff; - return 0; } -static int pmuserenr_write(CPUARMState *env, const ARMCPRegInfo *ri, +static void pmuserenr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) { env->cp15.c9_pmuserenr = value & 1; - return 0; } -static int pmintenset_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) +static void pmintenset_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) { /* We have no event counters so only the C bit can be changed */ value &= (1 << 31); env->cp15.c9_pminten |= value; - return 0; } -static int pmintenclr_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) +static void pmintenclr_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) { value &= (1 << 31); env->cp15.c9_pminten &= ~value; - return 0; } -static int vbar_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) +static void vbar_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) { env->cp15.c12_vbar = value & ~0x1Ful; - return 0; } -static int ccsidr_read(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t *value) +static uint64_t ccsidr_read(CPUARMState *env, const ARMCPRegInfo *ri) { ARMCPU *cpu = arm_env_get_cpu(env); - *value = cpu->ccsidr[env->cp15.c0_cssel]; - return 0; + return cpu->ccsidr[env->cp15.c0_cssel]; } -static int csselr_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) +static void csselr_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) { env->cp15.c0_cssel = value & 0xf; - return 0; } static const ARMCPRegInfo v7_cp_reginfo[] = { @@ -624,37 +573,41 @@ static const ARMCPRegInfo v7_cp_reginfo[] = { { .name = "PMCNTENSET", .cp = 15, .crn = 9, .crm = 12, .opc1 = 0, .opc2 = 1, .access = PL0_RW, .resetvalue = 0, .fieldoffset = offsetof(CPUARMState, cp15.c9_pmcnten), - .readfn = pmreg_read, .writefn = pmcntenset_write, - .raw_readfn = raw_read, .raw_writefn = raw_write }, + .writefn = pmcntenset_write, + .accessfn = pmreg_access, + .raw_writefn = raw_write }, { .name = "PMCNTENCLR", .cp = 15, .crn = 9, .crm = 12, .opc1 = 0, .opc2 = 2, .access = PL0_RW, .fieldoffset = offsetof(CPUARMState, cp15.c9_pmcnten), - .readfn = pmreg_read, .writefn = pmcntenclr_write, + .accessfn = pmreg_access, + .writefn = pmcntenclr_write, .type = ARM_CP_NO_MIGRATE }, { .name = "PMOVSR", .cp = 15, .crn = 9, .crm = 12, .opc1 = 0, .opc2 = 3, .access = PL0_RW, .fieldoffset = offsetof(CPUARMState, cp15.c9_pmovsr), - .readfn = pmreg_read, .writefn = pmovsr_write, - .raw_readfn = raw_read, .raw_writefn = raw_write }, - /* Unimplemented so WI. Strictly speaking write accesses in PL0 should - * respect PMUSERENR. - */ + .accessfn = pmreg_access, + .writefn = pmovsr_write, + .raw_writefn = raw_write }, + /* Unimplemented so WI. */ { .name = "PMSWINC", .cp = 15, .crn = 9, .crm = 12, .opc1 = 0, .opc2 = 4, - .access = PL0_W, .type = ARM_CP_NOP }, + .access = PL0_W, .accessfn = pmreg_access, .type = ARM_CP_NOP }, /* Since we don't implement any events, writing to PMSELR is UNPREDICTABLE. - * We choose to RAZ/WI. XXX should respect PMUSERENR. + * We choose to RAZ/WI. */ { .name = "PMSELR", .cp = 15, .crn = 9, .crm = 12, .opc1 = 0, .opc2 = 5, - .access = PL0_RW, .type = ARM_CP_CONST, .resetvalue = 0 }, - /* Unimplemented, RAZ/WI. XXX PMUSERENR */ + .access = PL0_RW, .type = ARM_CP_CONST, .resetvalue = 0, + .accessfn = pmreg_access }, + /* Unimplemented, RAZ/WI. */ { .name = "PMCCNTR", .cp = 15, .crn = 9, .crm = 13, .opc1 = 0, .opc2 = 0, - .access = PL0_RW, .type = ARM_CP_CONST, .resetvalue = 0 }, + .access = PL0_RW, .type = ARM_CP_CONST, .resetvalue = 0, + .accessfn = pmreg_access }, { .name = "PMXEVTYPER", .cp = 15, .crn = 9, .crm = 13, .opc1 = 0, .opc2 = 1, .access = PL0_RW, .fieldoffset = offsetof(CPUARMState, cp15.c9_pmxevtyper), - .readfn = pmreg_read, .writefn = pmxevtyper_write, - .raw_readfn = raw_read, .raw_writefn = raw_write }, - /* Unimplemented, RAZ/WI. XXX PMUSERENR */ + .accessfn = pmreg_access, .writefn = pmxevtyper_write, + .raw_writefn = raw_write }, + /* Unimplemented, RAZ/WI. */ { .name = "PMXEVCNTR", .cp = 15, .crn = 9, .crm = 13, .opc1 = 0, .opc2 = 2, - .access = PL0_RW, .type = ARM_CP_CONST, .resetvalue = 0 }, + .access = PL0_RW, .type = ARM_CP_CONST, .resetvalue = 0, + .accessfn = pmreg_access }, { .name = "PMUSERENR", .cp = 15, .crn = 9, .crm = 14, .opc1 = 0, .opc2 = 0, .access = PL0_R | PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.c9_pmuserenr), @@ -689,34 +642,19 @@ static const ARMCPRegInfo v7_cp_reginfo[] = { REGINFO_SENTINEL }; -static int teecr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) +static void teecr_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) { value &= 1; env->teecr = value; - return 0; } -static int teehbr_read(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t *value) +static CPAccessResult teehbr_access(CPUARMState *env, const ARMCPRegInfo *ri) { - /* This is a helper function because the user access rights - * depend on the value of the TEECR. - */ if (arm_current_pl(env) == 0 && (env->teecr & 1)) { - return EXCP_UDEF; + return CP_ACCESS_TRAP; } - *value = env->teehbr; - return 0; -} - -static int teehbr_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - if (arm_current_pl(env) == 0 && (env->teecr & 1)) { - return EXCP_UDEF; - } - env->teehbr = value; - return 0; + return CP_ACCESS_OK; } static const ARMCPRegInfo t2ee_cp_reginfo[] = { @@ -726,8 +664,7 @@ static const ARMCPRegInfo t2ee_cp_reginfo[] = { .writefn = teecr_write }, { .name = "TEEHBR", .cp = 14, .crn = 1, .crm = 0, .opc1 = 6, .opc2 = 0, .access = PL0_RW, .fieldoffset = offsetof(CPUARMState, teehbr), - .resetvalue = 0, .raw_readfn = raw_read, .raw_writefn = raw_write, - .readfn = teehbr_read, .writefn = teehbr_write }, + .accessfn = teehbr_access, .resetvalue = 0 }, REGINFO_SENTINEL }; @@ -757,6 +694,59 @@ static const ARMCPRegInfo v6k_cp_reginfo[] = { #ifndef CONFIG_USER_ONLY +static CPAccessResult gt_cntfrq_access(CPUARMState *env, const ARMCPRegInfo *ri) +{ + /* CNTFRQ: not visible from PL0 if both PL0PCTEN and PL0VCTEN are zero */ + if (arm_current_pl(env) == 0 && !extract32(env->cp15.c14_cntkctl, 0, 2)) { + return CP_ACCESS_TRAP; + } + return CP_ACCESS_OK; +} + +static CPAccessResult gt_counter_access(CPUARMState *env, int timeridx) +{ + /* CNT[PV]CT: not visible from PL0 if ELO[PV]CTEN is zero */ + if (arm_current_pl(env) == 0 && + !extract32(env->cp15.c14_cntkctl, timeridx, 1)) { + return CP_ACCESS_TRAP; + } + return CP_ACCESS_OK; +} + +static CPAccessResult gt_timer_access(CPUARMState *env, int timeridx) +{ + /* CNT[PV]_CVAL, CNT[PV]_CTL, CNT[PV]_TVAL: not visible from PL0 if + * EL0[PV]TEN is zero. + */ + if (arm_current_pl(env) == 0 && + !extract32(env->cp15.c14_cntkctl, 9 - timeridx, 1)) { + return CP_ACCESS_TRAP; + } + return CP_ACCESS_OK; +} + +static CPAccessResult gt_pct_access(CPUARMState *env, + const ARMCPRegInfo *ri) +{ + return gt_counter_access(env, GTIMER_PHYS); +} + +static CPAccessResult gt_vct_access(CPUARMState *env, + const ARMCPRegInfo *ri) +{ + return gt_counter_access(env, GTIMER_VIRT); +} + +static CPAccessResult gt_ptimer_access(CPUARMState *env, const ARMCPRegInfo *ri) +{ + return gt_timer_access(env, GTIMER_PHYS); +} + +static CPAccessResult gt_vtimer_access(CPUARMState *env, const ARMCPRegInfo *ri) +{ + return gt_timer_access(env, GTIMER_VIRT); +} + static uint64_t gt_get_countervalue(CPUARMState *env) { return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / GTIMER_SCALE; @@ -802,17 +792,6 @@ static void gt_recalc_timer(ARMCPU *cpu, int timeridx) } } -static int gt_cntfrq_read(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t *value) -{ - /* Not visible from PL0 if both PL0PCTEN and PL0VCTEN are zero */ - if (arm_current_pl(env) == 0 && !extract32(env->cp15.c14_cntkctl, 0, 2)) { - return EXCP_UDEF; - } - *value = env->cp15.c14_cntfrq; - return 0; -} - static void gt_cnt_reset(CPUARMState *env, const ARMCPRegInfo *ri) { ARMCPU *cpu = arm_env_get_cpu(env); @@ -821,81 +800,40 @@ static void gt_cnt_reset(CPUARMState *env, const ARMCPRegInfo *ri) timer_del(cpu->gt_timer[timeridx]); } -static int gt_cnt_read(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t *value) +static uint64_t gt_cnt_read(CPUARMState *env, const ARMCPRegInfo *ri) { - int timeridx = ri->opc1 & 1; - - if (arm_current_pl(env) == 0 && - !extract32(env->cp15.c14_cntkctl, timeridx, 1)) { - return EXCP_UDEF; - } - *value = gt_get_countervalue(env); - return 0; + return gt_get_countervalue(env); } -static int gt_cval_read(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t *value) -{ - int timeridx = ri->opc1 & 1; - - if (arm_current_pl(env) == 0 && - !extract32(env->cp15.c14_cntkctl, 9 - timeridx, 1)) { - return EXCP_UDEF; - } - *value = env->cp15.c14_timer[timeridx].cval; - return 0; -} - -static int gt_cval_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) +static void gt_cval_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) { int timeridx = ri->opc1 & 1; env->cp15.c14_timer[timeridx].cval = value; gt_recalc_timer(arm_env_get_cpu(env), timeridx); - return 0; } -static int gt_tval_read(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t *value) + +static uint64_t gt_tval_read(CPUARMState *env, const ARMCPRegInfo *ri) { int timeridx = ri->crm & 1; - if (arm_current_pl(env) == 0 && - !extract32(env->cp15.c14_cntkctl, 9 - timeridx, 1)) { - return EXCP_UDEF; - } - *value = (uint32_t)(env->cp15.c14_timer[timeridx].cval - - gt_get_countervalue(env)); - return 0; + return (uint32_t)(env->cp15.c14_timer[timeridx].cval - + gt_get_countervalue(env)); } -static int gt_tval_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) +static void gt_tval_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) { int timeridx = ri->crm & 1; env->cp15.c14_timer[timeridx].cval = gt_get_countervalue(env) + + sextract64(value, 0, 32); gt_recalc_timer(arm_env_get_cpu(env), timeridx); - return 0; } -static int gt_ctl_read(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t *value) -{ - int timeridx = ri->crm & 1; - - if (arm_current_pl(env) == 0 && - !extract32(env->cp15.c14_cntkctl, 9 - timeridx, 1)) { - return EXCP_UDEF; - } - *value = env->cp15.c14_timer[timeridx].ctl; - return 0; -} - -static int gt_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) +static void gt_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) { ARMCPU *cpu = arm_env_get_cpu(env); int timeridx = ri->crm & 1; @@ -912,7 +850,6 @@ static int gt_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri, qemu_set_irq(cpu->gt_timer_outputs[timeridx], (oldval & 4) && (value & 2)); } - return 0; } void arm_gt_ptimer_cb(void *opaque) @@ -938,7 +875,7 @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = { .access = PL1_RW | PL0_R, .fieldoffset = offsetof(CPUARMState, cp15.c14_cntfrq), .resetvalue = (1000 * 1000 * 1000) / GTIMER_SCALE, - .readfn = gt_cntfrq_read, .raw_readfn = raw_read, + .accessfn = gt_cntfrq_access, }, /* overall control: mostly access permissions */ { .name = "CNTKCTL", .cp = 15, .crn = 14, .crm = 1, .opc1 = 0, .opc2 = 0, @@ -951,32 +888,36 @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = { .type = ARM_CP_IO, .access = PL1_RW | PL0_R, .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_PHYS].ctl), .resetvalue = 0, - .readfn = gt_ctl_read, .writefn = gt_ctl_write, - .raw_readfn = raw_read, .raw_writefn = raw_write, + .accessfn = gt_ptimer_access, + .writefn = gt_ctl_write, .raw_writefn = raw_write, }, { .name = "CNTV_CTL", .cp = 15, .crn = 14, .crm = 3, .opc1 = 0, .opc2 = 1, .type = ARM_CP_IO, .access = PL1_RW | PL0_R, .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_VIRT].ctl), .resetvalue = 0, - .readfn = gt_ctl_read, .writefn = gt_ctl_write, - .raw_readfn = raw_read, .raw_writefn = raw_write, + .accessfn = gt_vtimer_access, + .writefn = gt_ctl_write, .raw_writefn = raw_write, }, /* TimerValue views: a 32 bit downcounting view of the underlying state */ { .name = "CNTP_TVAL", .cp = 15, .crn = 14, .crm = 2, .opc1 = 0, .opc2 = 0, .type = ARM_CP_NO_MIGRATE | ARM_CP_IO, .access = PL1_RW | PL0_R, + .accessfn = gt_ptimer_access, .readfn = gt_tval_read, .writefn = gt_tval_write, }, { .name = "CNTV_TVAL", .cp = 15, .crn = 14, .crm = 3, .opc1 = 0, .opc2 = 0, .type = ARM_CP_NO_MIGRATE | ARM_CP_IO, .access = PL1_RW | PL0_R, + .accessfn = gt_vtimer_access, .readfn = gt_tval_read, .writefn = gt_tval_write, }, /* The counter itself */ { .name = "CNTPCT", .cp = 15, .crm = 14, .opc1 = 0, .access = PL0_R, .type = ARM_CP_64BIT | ARM_CP_NO_MIGRATE | ARM_CP_IO, + .accessfn = gt_pct_access, .readfn = gt_cnt_read, .resetfn = gt_cnt_reset, }, { .name = "CNTVCT", .cp = 15, .crm = 14, .opc1 = 1, .access = PL0_R, .type = ARM_CP_64BIT | ARM_CP_NO_MIGRATE | ARM_CP_IO, + .accessfn = gt_vct_access, .readfn = gt_cnt_read, .resetfn = gt_cnt_reset, }, /* Comparison value, indicating when the timer goes off */ @@ -985,16 +926,16 @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = { .type = ARM_CP_64BIT | ARM_CP_IO, .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_PHYS].cval), .resetvalue = 0, - .readfn = gt_cval_read, .writefn = gt_cval_write, - .raw_readfn = raw_read, .raw_writefn = raw_write, + .accessfn = gt_ptimer_access, + .writefn = gt_cval_write, .raw_writefn = raw_write, }, { .name = "CNTV_CVAL", .cp = 15, .crm = 14, .opc1 = 3, .access = PL1_RW | PL0_R, .type = ARM_CP_64BIT | ARM_CP_IO, .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_VIRT].cval), .resetvalue = 0, - .readfn = gt_cval_read, .writefn = gt_cval_write, - .raw_readfn = raw_read, .raw_writefn = raw_write, + .accessfn = gt_vtimer_access, + .writefn = gt_cval_write, .raw_writefn = raw_write, }, REGINFO_SENTINEL }; @@ -1010,7 +951,7 @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = { #endif -static int par_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) +static void par_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) { if (arm_feature(env, ARM_FEATURE_LPAE)) { env->cp15.c7_par = value; @@ -1019,7 +960,6 @@ static int par_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) } else { env->cp15.c7_par = value & 0xfffff1ff; } - return 0; } #ifndef CONFIG_USER_ONLY @@ -1035,7 +975,20 @@ static inline bool extended_addresses_enabled(CPUARMState *env) && (env->cp15.c2_control & (1U << 31)); } -static int ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) +static CPAccessResult ats_access(CPUARMState *env, const ARMCPRegInfo *ri) +{ + if (ri->opc2 & 4) { + /* Other states are only available with TrustZone; in + * a non-TZ implementation these registers don't exist + * at all, which is an Uncategorized trap. This underdecoding + * is safe because the reginfo is NO_MIGRATE. + */ + return CP_ACCESS_TRAP_UNCATEGORIZED; + } + return CP_ACCESS_OK; +} + +static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) { hwaddr phys_addr; target_ulong page_size; @@ -1043,10 +996,6 @@ static int ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) int ret, is_user = ri->opc2 & 2; int access_type = ri->opc2 & 1; - if (ri->opc2 & 4) { - /* Other states are only available with TrustZone */ - return EXCP_UDEF; - } ret = get_phys_addr(env, value, access_type, is_user, &phys_addr, &prot, &page_size); if (extended_addresses_enabled(env)) { @@ -1088,7 +1037,6 @@ static int ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) } env->cp15.c7_par_hi = 0; } - return 0; } #endif @@ -1099,7 +1047,8 @@ static const ARMCPRegInfo vapa_cp_reginfo[] = { .writefn = par_write }, #ifndef CONFIG_USER_ONLY { .name = "ATS", .cp = 15, .crn = 7, .crm = 8, .opc1 = 0, .opc2 = CP_ANY, - .access = PL1_W, .writefn = ats_write, .type = ARM_CP_NO_MIGRATE }, + .access = PL1_W, .accessfn = ats_access, + .writefn = ats_write, .type = ARM_CP_NO_MIGRATE }, #endif REGINFO_SENTINEL }; @@ -1134,52 +1083,26 @@ static uint32_t extended_mpu_ap_bits(uint32_t val) return ret; } -static int pmsav5_data_ap_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) +static void pmsav5_data_ap_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) { env->cp15.c5_data = extended_mpu_ap_bits(value); - return 0; } -static int pmsav5_data_ap_read(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t *value) +static uint64_t pmsav5_data_ap_read(CPUARMState *env, const ARMCPRegInfo *ri) { - *value = simple_mpu_ap_bits(env->cp15.c5_data); - return 0; + return simple_mpu_ap_bits(env->cp15.c5_data); } -static int pmsav5_insn_ap_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) +static void pmsav5_insn_ap_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) { env->cp15.c5_insn = extended_mpu_ap_bits(value); - return 0; } -static int pmsav5_insn_ap_read(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t *value) +static uint64_t pmsav5_insn_ap_read(CPUARMState *env, const ARMCPRegInfo *ri) { - *value = simple_mpu_ap_bits(env->cp15.c5_insn); - return 0; -} - -static int arm946_prbs_read(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t *value) -{ - if (ri->crm >= 8) { - return EXCP_UDEF; - } - *value = env->cp15.c6_region[ri->crm]; - return 0; -} - -static int arm946_prbs_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - if (ri->crm >= 8) { - return EXCP_UDEF; - } - env->cp15.c6_region[ri->crm] = value; - return 0; + return simple_mpu_ap_bits(env->cp15.c5_insn); } static const ARMCPRegInfo pmsav5_cp_reginfo[] = { @@ -1204,14 +1127,35 @@ static const ARMCPRegInfo pmsav5_cp_reginfo[] = { .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.c2_insn), .resetvalue = 0, }, /* Protection region base and size registers */ - { .name = "946_PRBS", .cp = 15, .crn = 6, .crm = CP_ANY, .opc1 = 0, - .opc2 = CP_ANY, .access = PL1_RW, - .readfn = arm946_prbs_read, .writefn = arm946_prbs_write, }, + { .name = "946_PRBS0", .cp = 15, .crn = 6, .crm = 0, .opc1 = 0, + .opc2 = CP_ANY, .access = PL1_RW, .resetvalue = 0, + .fieldoffset = offsetof(CPUARMState, cp15.c6_region[0]) }, + { .name = "946_PRBS1", .cp = 15, .crn = 6, .crm = 1, .opc1 = 0, + .opc2 = CP_ANY, .access = PL1_RW, .resetvalue = 0, + .fieldoffset = offsetof(CPUARMState, cp15.c6_region[1]) }, + { .name = "946_PRBS2", .cp = 15, .crn = 6, .crm = 2, .opc1 = 0, + .opc2 = CP_ANY, .access = PL1_RW, .resetvalue = 0, + .fieldoffset = offsetof(CPUARMState, cp15.c6_region[2]) }, + { .name = "946_PRBS3", .cp = 15, .crn = 6, .crm = 3, .opc1 = 0, + .opc2 = CP_ANY, .access = PL1_RW, .resetvalue = 0, + .fieldoffset = offsetof(CPUARMState, cp15.c6_region[3]) }, + { .name = "946_PRBS4", .cp = 15, .crn = 6, .crm = 4, .opc1 = 0, + .opc2 = CP_ANY, .access = PL1_RW, .resetvalue = 0, + .fieldoffset = offsetof(CPUARMState, cp15.c6_region[4]) }, + { .name = "946_PRBS5", .cp = 15, .crn = 6, .crm = 5, .opc1 = 0, + .opc2 = CP_ANY, .access = PL1_RW, .resetvalue = 0, + .fieldoffset = offsetof(CPUARMState, cp15.c6_region[5]) }, + { .name = "946_PRBS6", .cp = 15, .crn = 6, .crm = 6, .opc1 = 0, + .opc2 = CP_ANY, .access = PL1_RW, .resetvalue = 0, + .fieldoffset = offsetof(CPUARMState, cp15.c6_region[6]) }, + { .name = "946_PRBS7", .cp = 15, .crn = 6, .crm = 7, .opc1 = 0, + .opc2 = CP_ANY, .access = PL1_RW, .resetvalue = 0, + .fieldoffset = offsetof(CPUARMState, cp15.c6_region[7]) }, REGINFO_SENTINEL }; -static int vmsa_ttbcr_raw_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) +static void vmsa_ttbcr_raw_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) { int maskshift = extract32(value, 0, 3); @@ -1228,11 +1172,10 @@ static int vmsa_ttbcr_raw_write(CPUARMState *env, const ARMCPRegInfo *ri, env->cp15.c2_control = value; env->cp15.c2_mask = ~(((uint32_t)0xffffffffu) >> maskshift); env->cp15.c2_base_mask = ~((uint32_t)0x3fffu >> maskshift); - return 0; } -static int vmsa_ttbcr_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) +static void vmsa_ttbcr_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) { if (arm_feature(env, ARM_FEATURE_LPAE)) { /* With LPAE the TTBCR could result in a change of ASID @@ -1240,7 +1183,7 @@ static int vmsa_ttbcr_write(CPUARMState *env, const ARMCPRegInfo *ri, */ tlb_flush(env, 1); } - return vmsa_ttbcr_raw_write(env, ri, value); + vmsa_ttbcr_raw_write(env, ri, value); } static void vmsa_ttbcr_reset(CPUARMState *env, const ARMCPRegInfo *ri) @@ -1273,40 +1216,36 @@ static const ARMCPRegInfo vmsa_cp_reginfo[] = { REGINFO_SENTINEL }; -static int omap_ticonfig_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) +static void omap_ticonfig_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) { env->cp15.c15_ticonfig = value & 0xe7; /* The OS_TYPE bit in this register changes the reported CPUID! */ env->cp15.c0_cpuid = (value & (1 << 5)) ? ARM_CPUID_TI915T : ARM_CPUID_TI925T; - return 0; } -static int omap_threadid_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) +static void omap_threadid_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) { env->cp15.c15_threadid = value & 0xffff; - return 0; } -static int omap_wfi_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) +static void omap_wfi_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) { /* Wait-for-interrupt (deprecated) */ cpu_interrupt(CPU(arm_env_get_cpu(env)), CPU_INTERRUPT_HALT); - return 0; } -static int omap_cachemaint_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) +static void omap_cachemaint_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) { /* On OMAP there are registers indicating the max/min index of dcache lines * containing a dirty line; cache flush operations have to reset these. */ env->cp15.c15_i_max = 0x000; env->cp15.c15_i_min = 0xff0; - return 0; } static const ARMCPRegInfo omap_cp_reginfo[] = { @@ -1348,8 +1287,8 @@ static const ARMCPRegInfo omap_cp_reginfo[] = { REGINFO_SENTINEL }; -static int xscale_cpar_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) +static void xscale_cpar_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) { value &= 0x3fff; if (env->cp15.c15_cpar != value) { @@ -1357,7 +1296,6 @@ static int xscale_cpar_write(CPUARMState *env, const ARMCPRegInfo *ri, tb_flush(env); env->cp15.c15_cpar = value; } - return 0; } static const ARMCPRegInfo xscale_cp_reginfo[] = { @@ -1437,8 +1375,7 @@ static const ARMCPRegInfo strongarm_cp_reginfo[] = { REGINFO_SENTINEL }; -static int mpidr_read(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t *value) +static uint64_t mpidr_read(CPUARMState *env, const ARMCPRegInfo *ri) { CPUState *cs = CPU(arm_env_get_cpu(env)); uint32_t mpidr = cs->cpu_index; @@ -1453,8 +1390,7 @@ static int mpidr_read(CPUARMState *env, const ARMCPRegInfo *ri, * not currently model any of those cores. */ } - *value = mpidr; - return 0; + return mpidr; } static const ARMCPRegInfo mpidr_cp_reginfo[] = { @@ -1463,17 +1399,16 @@ static const ARMCPRegInfo mpidr_cp_reginfo[] = { REGINFO_SENTINEL }; -static int par64_read(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t *value) +static uint64_t par64_read(CPUARMState *env, const ARMCPRegInfo *ri) { - *value = ((uint64_t)env->cp15.c7_par_hi << 32) | env->cp15.c7_par; - return 0; + return ((uint64_t)env->cp15.c7_par_hi << 32) | env->cp15.c7_par; } -static int par64_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) +static void par64_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) { env->cp15.c7_par_hi = value >> 32; env->cp15.c7_par = value; - return 0; } static void par64_reset(CPUARMState *env, const ARMCPRegInfo *ri) @@ -1482,27 +1417,24 @@ static void par64_reset(CPUARMState *env, const ARMCPRegInfo *ri) env->cp15.c7_par = 0; } -static int ttbr064_read(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t *value) +static uint64_t ttbr064_read(CPUARMState *env, const ARMCPRegInfo *ri) { - *value = ((uint64_t)env->cp15.c2_base0_hi << 32) | env->cp15.c2_base0; - return 0; + return ((uint64_t)env->cp15.c2_base0_hi << 32) | env->cp15.c2_base0; } -static int ttbr064_raw_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) +static void ttbr064_raw_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) { env->cp15.c2_base0_hi = value >> 32; env->cp15.c2_base0 = value; - return 0; } -static int ttbr064_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) +static void ttbr064_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) { /* Writes to the 64 bit format TTBRs may change the ASID */ tlb_flush(env, 1); - return ttbr064_raw_write(env, ri, value); + ttbr064_raw_write(env, ri, value); } static void ttbr064_reset(CPUARMState *env, const ARMCPRegInfo *ri) @@ -1511,19 +1443,16 @@ static void ttbr064_reset(CPUARMState *env, const ARMCPRegInfo *ri) env->cp15.c2_base0 = 0; } -static int ttbr164_read(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t *value) +static uint64_t ttbr164_read(CPUARMState *env, const ARMCPRegInfo *ri) { - *value = ((uint64_t)env->cp15.c2_base1_hi << 32) | env->cp15.c2_base1; - return 0; + return ((uint64_t)env->cp15.c2_base1_hi << 32) | env->cp15.c2_base1; } -static int ttbr164_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) +static void ttbr164_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) { env->cp15.c2_base1_hi = value >> 32; env->cp15.c2_base1 = value; - return 0; } static void ttbr164_reset(CPUARMState *env, const ARMCPRegInfo *ri) @@ -1560,32 +1489,26 @@ static const ARMCPRegInfo lpae_cp_reginfo[] = { REGINFO_SENTINEL }; -static int aa64_fpcr_read(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t *value) +static uint64_t aa64_fpcr_read(CPUARMState *env, const ARMCPRegInfo *ri) { - *value = vfp_get_fpcr(env); - return 0; + return vfp_get_fpcr(env); } -static int aa64_fpcr_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) +static void aa64_fpcr_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) { vfp_set_fpcr(env, value); - return 0; } -static int aa64_fpsr_read(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t *value) +static uint64_t aa64_fpsr_read(CPUARMState *env, const ARMCPRegInfo *ri) { - *value = vfp_get_fpsr(env); - return 0; + return vfp_get_fpsr(env); } -static int aa64_fpsr_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) +static void aa64_fpsr_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) { vfp_set_fpsr(env, value); - return 0; } static const ARMCPRegInfo v8_cp_reginfo[] = { @@ -1618,13 +1541,13 @@ static const ARMCPRegInfo v8_cp_reginfo[] = { REGINFO_SENTINEL }; -static int sctlr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) +static void sctlr_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) { env->cp15.c1_sys = value; /* ??? Lots of these bits are not implemented. */ /* This may enable/disable the MMU, so do a TLB flush. */ tlb_flush(env, 1); - return 0; } void register_cp_regs_for_features(ARMCPU *cpu) @@ -1707,8 +1630,8 @@ void register_cp_regs_for_features(ARMCPU *cpu) .name = "PMCR", .cp = 15, .crn = 9, .crm = 12, .opc1 = 0, .opc2 = 0, .access = PL0_RW, .resetvalue = cpu->midr & 0xff000000, .fieldoffset = offsetof(CPUARMState, cp15.c9_pmcr), - .readfn = pmreg_read, .writefn = pmcr_write, - .raw_readfn = raw_read, .raw_writefn = raw_write, + .accessfn = pmreg_access, .writefn = pmcr_write, + .raw_writefn = raw_write, }; ARMCPRegInfo clidr = { .name = "CLIDR", .cp = 15, .crn = 0, .crm = 0, .opc1 = 1, .opc2 = 1, @@ -2202,17 +2125,15 @@ const ARMCPRegInfo *get_arm_cp_reginfo(GHashTable *cpregs, uint32_t encoded_cp) return g_hash_table_lookup(cpregs, &encoded_cp); } -int arm_cp_write_ignore(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) +void arm_cp_write_ignore(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) { /* Helper coprocessor write function for write-ignore registers */ - return 0; } -int arm_cp_read_zero(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t *value) +uint64_t arm_cp_read_zero(CPUARMState *env, const ARMCPRegInfo *ri) { /* Helper coprocessor write function for read-as-zero registers */ - *value = 0; return 0; } @@ -2718,7 +2639,7 @@ void arm_cpu_do_interrupt(CPUState *cs) return; /* Never happens. Keep compiler happy. */ } /* High vectors. */ - if (env->cp15.c1_sys & (1 << 13)) { + if (env->cp15.c1_sys & SCTLR_V) { /* when enabled, base address cannot be remapped. */ addr += 0xffff0000; } else { @@ -2741,7 +2662,7 @@ void arm_cpu_do_interrupt(CPUState *cs) /* this is a lie, as the was no c1_sys on V4T/V5, but who cares * and we should just guard the thumb mode on V4 */ if (arm_feature(env, ARM_FEATURE_V4T)) { - env->thumb = (env->cp15.c1_sys & (1 << 30)) != 0; + env->thumb = (env->cp15.c1_sys & SCTLR_TE) != 0; } env->regs[14] = env->regs[15] + offset; env->regs[15] = addr; @@ -2767,12 +2688,15 @@ static inline int check_ap(CPUARMState *env, int ap, int domain_prot, switch (ap) { case 0: + if (arm_feature(env, ARM_FEATURE_V7)) { + return 0; + } if (access_type == 1) return 0; - switch ((env->cp15.c1_sys >> 8) & 3) { - case 1: + switch (env->cp15.c1_sys & (SCTLR_S | SCTLR_R)) { + case SCTLR_S: return is_user ? 0 : PAGE_READ; - case 2: + case SCTLR_R: return PAGE_READ; default: return 0; @@ -3003,7 +2927,7 @@ static int get_phys_addr_v6(CPUARMState *env, uint32_t address, int access_type, goto do_fault; /* The simplified model uses AP[0] as an access control bit. */ - if ((env->cp15.c1_sys & (1 << 29)) && (ap & 1) == 0) { + if ((env->cp15.c1_sys & SCTLR_AFE) && (ap & 1) == 0) { /* Access flag fault. */ code = (code == 15) ? 6 : 3; goto do_fault; @@ -3295,7 +3219,7 @@ static inline int get_phys_addr(CPUARMState *env, uint32_t address, if (address < 0x02000000) address += env->cp15.c13_fcse; - if ((env->cp15.c1_sys & 1) == 0) { + if ((env->cp15.c1_sys & SCTLR_M) == 0) { /* MMU/MPU disabled. */ *phys_ptr = address; *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; @@ -3308,7 +3232,7 @@ static inline int get_phys_addr(CPUARMState *env, uint32_t address, } else if (extended_addresses_enabled(env)) { return get_phys_addr_lpae(env, address, access_type, is_user, phys_ptr, prot, page_size); - } else if (env->cp15.c1_sys & (1 << 23)) { + } else if (env->cp15.c1_sys & SCTLR_XP) { return get_phys_addr_v6(env, address, access_type, is_user, phys_ptr, prot, page_size); } else { diff --git a/target-arm/helper.h b/target-arm/helper.h index 951e6ada07..19bd620532 100644 --- a/target-arm/helper.h +++ b/target-arm/helper.h @@ -57,6 +57,7 @@ DEF_HELPER_1(cpsr_read, i32, env) DEF_HELPER_3(v7m_msr, void, env, i32, i32) DEF_HELPER_2(v7m_mrs, i32, env, i32) +DEF_HELPER_2(access_check_cp_reg, void, env, ptr) DEF_HELPER_3(set_cp_reg, void, env, ptr, i32) DEF_HELPER_2(get_cp_reg, i32, env, ptr) DEF_HELPER_3(set_cp_reg64, void, env, ptr, i64) @@ -382,6 +383,8 @@ DEF_HELPER_3(neon_cge_f32, i32, i32, i32, ptr) DEF_HELPER_3(neon_cgt_f32, i32, i32, i32, ptr) DEF_HELPER_3(neon_acge_f32, i32, i32, i32, ptr) DEF_HELPER_3(neon_acgt_f32, i32, i32, i32, ptr) +DEF_HELPER_3(neon_acge_f64, i64, i64, i64, ptr) +DEF_HELPER_3(neon_acgt_f64, i64, i64, i64, ptr) /* iwmmxt_helper.c */ DEF_HELPER_2(iwmmxt_maddsq, i64, i64, i64) diff --git a/target-arm/kvm-consts.h b/target-arm/kvm-consts.h index 0e7f889cba..6009a33f10 100644 --- a/target-arm/kvm-consts.h +++ b/target-arm/kvm-consts.h @@ -50,15 +50,29 @@ MISMATCH_CHECK(PSCI_FN_CPU_OFF, KVM_PSCI_FN_CPU_OFF) MISMATCH_CHECK(PSCI_FN_CPU_ON, KVM_PSCI_FN_CPU_ON) MISMATCH_CHECK(PSCI_FN_MIGRATE, KVM_PSCI_FN_MIGRATE) +/* Note that KVM uses overlapping values for AArch32 and AArch64 + * target CPU numbers. AArch32 targets: + */ #define QEMU_KVM_ARM_TARGET_CORTEX_A15 0 +#define QEMU_KVM_ARM_TARGET_CORTEX_A7 1 + +/* AArch64 targets: */ +#define QEMU_KVM_ARM_TARGET_AEM_V8 0 +#define QEMU_KVM_ARM_TARGET_FOUNDATION_V8 1 +#define QEMU_KVM_ARM_TARGET_CORTEX_A57 2 /* There's no kernel define for this: sentinel value which * matches no KVM target value for either 64 or 32 bit */ #define QEMU_KVM_ARM_TARGET_NONE UINT_MAX -#ifndef TARGET_AARCH64 +#ifdef TARGET_AARCH64 +MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_AEM_V8, KVM_ARM_TARGET_AEM_V8) +MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_FOUNDATION_V8, KVM_ARM_TARGET_FOUNDATION_V8) +MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_CORTEX_A57, KVM_ARM_TARGET_CORTEX_A57) +#else MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_CORTEX_A15, KVM_ARM_TARGET_CORTEX_A15) +MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_CORTEX_A7, KVM_ARM_TARGET_CORTEX_A7) #endif #define CP_REG_ARM64 0x6000000000000000ULL diff --git a/target-arm/neon_helper.c b/target-arm/neon_helper.c index b4c86904f4..13752baf63 100644 --- a/target-arm/neon_helper.c +++ b/target-arm/neon_helper.c @@ -1823,6 +1823,22 @@ uint32_t HELPER(neon_acgt_f32)(uint32_t a, uint32_t b, void *fpstp) return -float32_lt(f1, f0, fpst); } +uint64_t HELPER(neon_acge_f64)(uint64_t a, uint64_t b, void *fpstp) +{ + float_status *fpst = fpstp; + float64 f0 = float64_abs(make_float64(a)); + float64 f1 = float64_abs(make_float64(b)); + return -float64_le(f1, f0, fpst); +} + +uint64_t HELPER(neon_acgt_f64)(uint64_t a, uint64_t b, void *fpstp) +{ + float_status *fpst = fpstp; + float64 f0 = float64_abs(make_float64(a)); + float64 f1 = float64_abs(make_float64(b)); + return -float64_lt(f1, f0, fpst); +} + #define ELEM(V, N, SIZE) (((V) >> ((N) * (SIZE))) & ((1ull << (SIZE)) - 1)) void HELPER(neon_qunzip8)(CPUARMState *env, uint32_t rd, uint32_t rm) diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c index a918e5b27a..eb0fccd98f 100644 --- a/target-arm/op_helper.c +++ b/target-arm/op_helper.c @@ -273,44 +273,50 @@ void HELPER(set_user_reg)(CPUARMState *env, uint32_t regno, uint32_t val) } } -void HELPER(set_cp_reg)(CPUARMState *env, void *rip, uint32_t value) +void HELPER(access_check_cp_reg)(CPUARMState *env, void *rip) { const ARMCPRegInfo *ri = rip; - int excp = ri->writefn(env, ri, value); - if (excp) { - raise_exception(env, excp); + switch (ri->accessfn(env, ri)) { + case CP_ACCESS_OK: + return; + case CP_ACCESS_TRAP: + case CP_ACCESS_TRAP_UNCATEGORIZED: + /* These cases will eventually need to generate different + * syndrome information. + */ + break; + default: + g_assert_not_reached(); } + raise_exception(env, EXCP_UDEF); +} + +void HELPER(set_cp_reg)(CPUARMState *env, void *rip, uint32_t value) +{ + const ARMCPRegInfo *ri = rip; + + ri->writefn(env, ri, value); } uint32_t HELPER(get_cp_reg)(CPUARMState *env, void *rip) { const ARMCPRegInfo *ri = rip; - uint64_t value; - int excp = ri->readfn(env, ri, &value); - if (excp) { - raise_exception(env, excp); - } - return value; + + return ri->readfn(env, ri); } void HELPER(set_cp_reg64)(CPUARMState *env, void *rip, uint64_t value) { const ARMCPRegInfo *ri = rip; - int excp = ri->writefn(env, ri, value); - if (excp) { - raise_exception(env, excp); - } + + ri->writefn(env, ri, value); } uint64_t HELPER(get_cp_reg64)(CPUARMState *env, void *rip) { const ARMCPRegInfo *ri = rip; - uint64_t value; - int excp = ri->readfn(env, ri, &value); - if (excp) { - raise_exception(env, excp); - } - return value; + + return ri->readfn(env, ri); } /* ??? Flag setting arithmetic is awkward because we need to do comparisons. diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c index d60223af8e..8752e7e16c 100644 --- a/target-arm/translate-a64.c +++ b/target-arm/translate-a64.c @@ -75,8 +75,12 @@ typedef struct AArch64DecodeTable { /* Function prototype for gen_ functions for calling Neon helpers */ typedef void NeonGenTwoOpFn(TCGv_i32, TCGv_i32, TCGv_i32); typedef void NeonGenTwoOpEnvFn(TCGv_i32, TCGv_ptr, TCGv_i32, TCGv_i32); +typedef void NeonGenTwo64OpFn(TCGv_i64, TCGv_i64, TCGv_i64); typedef void NeonGenNarrowFn(TCGv_i32, TCGv_i64); typedef void NeonGenNarrowEnvFn(TCGv_i32, TCGv_ptr, TCGv_i64); +typedef void NeonGenWidenFn(TCGv_i64, TCGv_i32); +typedef void NeonGenTwoSingleOPFn(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_ptr); +typedef void NeonGenTwoDoubleOPFn(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_ptr); /* initialize TCG globals. */ void a64_translate_init(void) @@ -614,20 +618,26 @@ static void gen_adc_CC(int sf, TCGv_i64 dest, TCGv_i64 t0, TCGv_i64 t1) */ /* - * Store from GPR register to memory + * Store from GPR register to memory. */ +static void do_gpr_st_memidx(DisasContext *s, TCGv_i64 source, + TCGv_i64 tcg_addr, int size, int memidx) +{ + g_assert(size <= 3); + tcg_gen_qemu_st_i64(source, tcg_addr, memidx, MO_TE + size); +} + static void do_gpr_st(DisasContext *s, TCGv_i64 source, TCGv_i64 tcg_addr, int size) { - g_assert(size <= 3); - tcg_gen_qemu_st_i64(source, tcg_addr, get_mem_index(s), MO_TE + size); + do_gpr_st_memidx(s, source, tcg_addr, size, get_mem_index(s)); } /* * Load from memory to GPR register */ -static void do_gpr_ld(DisasContext *s, TCGv_i64 dest, TCGv_i64 tcg_addr, - int size, bool is_signed, bool extend) +static void do_gpr_ld_memidx(DisasContext *s, TCGv_i64 dest, TCGv_i64 tcg_addr, + int size, bool is_signed, bool extend, int memidx) { TCGMemOp memop = MO_TE + size; @@ -637,7 +647,7 @@ static void do_gpr_ld(DisasContext *s, TCGv_i64 dest, TCGv_i64 tcg_addr, memop += MO_SIGN; } - tcg_gen_qemu_ld_i64(dest, tcg_addr, get_mem_index(s), memop); + tcg_gen_qemu_ld_i64(dest, tcg_addr, memidx, memop); if (extend && is_signed) { g_assert(size < 3); @@ -645,6 +655,13 @@ static void do_gpr_ld(DisasContext *s, TCGv_i64 dest, TCGv_i64 tcg_addr, } } +static void do_gpr_ld(DisasContext *s, TCGv_i64 dest, TCGv_i64 tcg_addr, + int size, bool is_signed, bool extend) +{ + do_gpr_ld_memidx(s, dest, tcg_addr, size, is_signed, extend, + get_mem_index(s)); +} + /* * Store from FP register to memory */ @@ -1175,7 +1192,12 @@ static void handle_sys(DisasContext *s, uint32_t insn, bool isread, crn, crm, op0, op1, op2)); if (!ri) { - /* Unknown register */ + /* Unknown register; this might be a guest error or a QEMU + * unimplemented feature. + */ + qemu_log_mask(LOG_UNIMP, "%s access to unsupported AArch64 " + "system register op0:%d op1:%d crn:%d crm:%d op2:%d\n", + isread ? "read" : "write", op0, op1, crn, crm, op2); unallocated_encoding(s); return; } @@ -1186,6 +1208,17 @@ static void handle_sys(DisasContext *s, uint32_t insn, bool isread, return; } + if (ri->accessfn) { + /* Emit code to perform further access permissions checks at + * runtime; this may result in an exception. + */ + TCGv_ptr tmpptr; + gen_a64_set_pc_im(s->pc - 4); + tmpptr = tcg_const_ptr(ri); + gen_helper_access_check_cp_reg(cpu_env, tmpptr); + tcg_temp_free_ptr(tmpptr); + } + /* Handle special cases first */ switch (ri->type & ~(ARM_CP_FLAG_MASK & ~ARM_CP_SPECIAL)) { case ARM_CP_NOP: @@ -1213,7 +1246,6 @@ static void handle_sys(DisasContext *s, uint32_t insn, bool isread, tcg_gen_movi_i64(tcg_rt, ri->resetvalue); } else if (ri->readfn) { TCGv_ptr tmpptr; - gen_a64_set_pc_im(s->pc - 4); tmpptr = tcg_const_ptr(ri); gen_helper_get_cp_reg64(tcg_rt, cpu_env, tmpptr); tcg_temp_free_ptr(tmpptr); @@ -1226,7 +1258,6 @@ static void handle_sys(DisasContext *s, uint32_t insn, bool isread, return; } else if (ri->writefn) { TCGv_ptr tmpptr; - gen_a64_set_pc_im(s->pc - 4); tmpptr = tcg_const_ptr(ri); gen_helper_set_cp_reg64(cpu_env, tmpptr, tcg_rt); tcg_temp_free_ptr(tmpptr); @@ -1471,12 +1502,68 @@ static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2, } #else static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2, - TCGv_i64 addr, int size, int is_pair) -{ - qemu_log_mask(LOG_UNIMP, - "%s:%d: system mode store_exclusive unsupported " - "at pc=%016" PRIx64 "\n", - __FILE__, __LINE__, s->pc - 4); + TCGv_i64 inaddr, int size, int is_pair) +{ + /* if (env->exclusive_addr == addr && env->exclusive_val == [addr] + * && (!is_pair || env->exclusive_high == [addr + datasize])) { + * [addr] = {Rt}; + * if (is_pair) { + * [addr + datasize] = {Rt2}; + * } + * {Rd} = 0; + * } else { + * {Rd} = 1; + * } + * env->exclusive_addr = -1; + */ + int fail_label = gen_new_label(); + int done_label = gen_new_label(); + TCGv_i64 addr = tcg_temp_local_new_i64(); + TCGv_i64 tmp; + + /* Copy input into a local temp so it is not trashed when the + * basic block ends at the branch insn. + */ + tcg_gen_mov_i64(addr, inaddr); + tcg_gen_brcond_i64(TCG_COND_NE, addr, cpu_exclusive_addr, fail_label); + + tmp = tcg_temp_new_i64(); + tcg_gen_qemu_ld_i64(tmp, addr, get_mem_index(s), MO_TE + size); + tcg_gen_brcond_i64(TCG_COND_NE, tmp, cpu_exclusive_val, fail_label); + tcg_temp_free_i64(tmp); + + if (is_pair) { + TCGv_i64 addrhi = tcg_temp_new_i64(); + TCGv_i64 tmphi = tcg_temp_new_i64(); + + tcg_gen_addi_i64(addrhi, addr, 1 << size); + tcg_gen_qemu_ld_i64(tmphi, addrhi, get_mem_index(s), MO_TE + size); + tcg_gen_brcond_i64(TCG_COND_NE, tmphi, cpu_exclusive_high, fail_label); + + tcg_temp_free_i64(tmphi); + tcg_temp_free_i64(addrhi); + } + + /* We seem to still have the exclusive monitor, so do the store */ + tcg_gen_qemu_st_i64(cpu_reg(s, rt), addr, get_mem_index(s), MO_TE + size); + if (is_pair) { + TCGv_i64 addrhi = tcg_temp_new_i64(); + + tcg_gen_addi_i64(addrhi, addr, 1 << size); + tcg_gen_qemu_st_i64(cpu_reg(s, rt2), addrhi, + get_mem_index(s), MO_TE + size); + tcg_temp_free_i64(addrhi); + } + + tcg_temp_free_i64(addr); + + tcg_gen_movi_i64(cpu_reg(s, rd), 0); + tcg_gen_br(done_label); + gen_set_label(fail_label); + tcg_gen_movi_i64(cpu_reg(s, rd), 1); + gen_set_label(done_label); + tcg_gen_movi_i64(cpu_exclusive_addr, -1); + } #endif @@ -1750,6 +1837,7 @@ static void disas_ldst_pair(DisasContext *s, uint32_t insn) * +----+-------+---+-----+-----+---+--------+-----+------+------+ * * idx = 01 -> post-indexed, 11 pre-indexed, 00 unscaled imm. (no writeback) + 10 -> unprivileged * V = 0 -> non-vector * size: 00 -> 8 bit, 01 -> 16 bit, 10 -> 32 bit, 11 -> 64bit * opc: 00 -> store, 01 -> loadu, 10 -> loads 64, 11 -> loads 32 @@ -1765,6 +1853,7 @@ static void disas_ldst_reg_imm9(DisasContext *s, uint32_t insn) bool is_signed = false; bool is_store = false; bool is_extended = false; + bool is_unpriv = (idx == 2); bool is_vector = extract32(insn, 26, 1); bool post_index; bool writeback; @@ -1773,7 +1862,7 @@ static void disas_ldst_reg_imm9(DisasContext *s, uint32_t insn) if (is_vector) { size |= (opc & 2) << 1; - if (size > 4) { + if (size > 4 || is_unpriv) { unallocated_encoding(s); return; } @@ -1781,6 +1870,10 @@ static void disas_ldst_reg_imm9(DisasContext *s, uint32_t insn) } else { if (size == 3 && opc == 2) { /* PRFM - prefetch */ + if (is_unpriv) { + unallocated_encoding(s); + return; + } return; } if (opc == 3 && size > 1) { @@ -1794,6 +1887,7 @@ static void disas_ldst_reg_imm9(DisasContext *s, uint32_t insn) switch (idx) { case 0: + case 2: post_index = false; writeback = false; break; @@ -1805,9 +1899,6 @@ static void disas_ldst_reg_imm9(DisasContext *s, uint32_t insn) post_index = false; writeback = true; break; - case 2: - g_assert(false); - break; } if (rn == 31) { @@ -1827,10 +1918,13 @@ static void disas_ldst_reg_imm9(DisasContext *s, uint32_t insn) } } else { TCGv_i64 tcg_rt = cpu_reg(s, rt); + int memidx = is_unpriv ? 1 : get_mem_index(s); + if (is_store) { - do_gpr_st(s, tcg_rt, tcg_addr, size); + do_gpr_st_memidx(s, tcg_rt, tcg_addr, size, memidx); } else { - do_gpr_ld(s, tcg_rt, tcg_addr, size, is_signed, is_extended); + do_gpr_ld_memidx(s, tcg_rt, tcg_addr, size, + is_signed, is_extended, memidx); } } @@ -2010,25 +2104,6 @@ static void disas_ldst_reg_unsigned_imm(DisasContext *s, uint32_t insn) } } -/* Load/store register (immediate forms) */ -static void disas_ldst_reg_imm(DisasContext *s, uint32_t insn) -{ - switch (extract32(insn, 10, 2)) { - case 0: case 1: case 3: - /* Load/store register (unscaled immediate) */ - /* Load/store immediate pre/post-indexed */ - disas_ldst_reg_imm9(s, insn); - break; - case 2: - /* Load/store register unprivileged */ - unsupported_encoding(s, insn); - break; - default: - unallocated_encoding(s); - break; - } -} - /* Load/store register (all forms) */ static void disas_ldst_reg(DisasContext *s, uint32_t insn) { @@ -2037,7 +2112,11 @@ static void disas_ldst_reg(DisasContext *s, uint32_t insn) if (extract32(insn, 21, 1) == 1 && extract32(insn, 10, 2) == 2) { disas_ldst_reg_roffset(s, insn); } else { - disas_ldst_reg_imm(s, insn); + /* Load/store register (unscaled immediate) + * Load/store immediate pre/post-indexed + * Load/store register unprivileged + */ + disas_ldst_reg_imm9(s, insn); } break; case 1: @@ -5838,7 +5917,100 @@ static void disas_simd_scalar_shift_imm(DisasContext *s, uint32_t insn) */ static void disas_simd_scalar_three_reg_diff(DisasContext *s, uint32_t insn) { - unsupported_encoding(s, insn); + bool is_u = extract32(insn, 29, 1); + int size = extract32(insn, 22, 2); + int opcode = extract32(insn, 12, 4); + int rm = extract32(insn, 16, 5); + int rn = extract32(insn, 5, 5); + int rd = extract32(insn, 0, 5); + + if (is_u) { + unallocated_encoding(s); + return; + } + + switch (opcode) { + case 0x9: /* SQDMLAL, SQDMLAL2 */ + case 0xb: /* SQDMLSL, SQDMLSL2 */ + case 0xd: /* SQDMULL, SQDMULL2 */ + if (size == 0 || size == 3) { + unallocated_encoding(s); + return; + } + break; + default: + unallocated_encoding(s); + return; + } + + if (size == 2) { + TCGv_i64 tcg_op1 = tcg_temp_new_i64(); + TCGv_i64 tcg_op2 = tcg_temp_new_i64(); + TCGv_i64 tcg_res = tcg_temp_new_i64(); + + read_vec_element(s, tcg_op1, rn, 0, MO_32 | MO_SIGN); + read_vec_element(s, tcg_op2, rm, 0, MO_32 | MO_SIGN); + + tcg_gen_mul_i64(tcg_res, tcg_op1, tcg_op2); + gen_helper_neon_addl_saturate_s64(tcg_res, cpu_env, tcg_res, tcg_res); + + switch (opcode) { + case 0xd: /* SQDMULL, SQDMULL2 */ + break; + case 0xb: /* SQDMLSL, SQDMLSL2 */ + tcg_gen_neg_i64(tcg_res, tcg_res); + /* fall through */ + case 0x9: /* SQDMLAL, SQDMLAL2 */ + read_vec_element(s, tcg_op1, rd, 0, MO_64); + gen_helper_neon_addl_saturate_s64(tcg_res, cpu_env, + tcg_res, tcg_op1); + break; + default: + g_assert_not_reached(); + } + + write_fp_dreg(s, rd, tcg_res); + + tcg_temp_free_i64(tcg_op1); + tcg_temp_free_i64(tcg_op2); + tcg_temp_free_i64(tcg_res); + } else { + TCGv_i32 tcg_op1 = tcg_temp_new_i32(); + TCGv_i32 tcg_op2 = tcg_temp_new_i32(); + TCGv_i64 tcg_res = tcg_temp_new_i64(); + + read_vec_element_i32(s, tcg_op1, rn, 0, MO_16); + read_vec_element_i32(s, tcg_op2, rm, 0, MO_16); + + gen_helper_neon_mull_s16(tcg_res, tcg_op1, tcg_op2); + gen_helper_neon_addl_saturate_s32(tcg_res, cpu_env, tcg_res, tcg_res); + + switch (opcode) { + case 0xd: /* SQDMULL, SQDMULL2 */ + break; + case 0xb: /* SQDMLSL, SQDMLSL2 */ + gen_helper_neon_negl_u32(tcg_res, tcg_res); + /* fall through */ + case 0x9: /* SQDMLAL, SQDMLAL2 */ + { + TCGv_i64 tcg_op3 = tcg_temp_new_i64(); + read_vec_element(s, tcg_op3, rd, 0, MO_32); + gen_helper_neon_addl_saturate_s32(tcg_res, cpu_env, + tcg_res, tcg_op3); + tcg_temp_free_i64(tcg_op3); + break; + } + default: + g_assert_not_reached(); + } + + tcg_gen_ext32u_i64(tcg_res, tcg_res); + write_fp_dreg(s, rd, tcg_res); + + tcg_temp_free_i32(tcg_op1); + tcg_temp_free_i32(tcg_op2); + tcg_temp_free_i64(tcg_res); + } } static void handle_3same_64(DisasContext *s, int opcode, bool u, @@ -5950,15 +6122,33 @@ static void handle_3same_float(DisasContext *s, int size, int elements, read_vec_element(s, tcg_op2, rm, pass, MO_64); switch (fpopcode) { + case 0x39: /* FMLS */ + /* As usual for ARM, separate negation for fused multiply-add */ + gen_helper_vfp_negd(tcg_op1, tcg_op1); + /* fall through */ + case 0x19: /* FMLA */ + read_vec_element(s, tcg_res, rd, pass, MO_64); + gen_helper_vfp_muladdd(tcg_res, tcg_op1, tcg_op2, + tcg_res, fpst); + break; case 0x18: /* FMAXNM */ gen_helper_vfp_maxnumd(tcg_res, tcg_op1, tcg_op2, fpst); break; case 0x1a: /* FADD */ gen_helper_vfp_addd(tcg_res, tcg_op1, tcg_op2, fpst); break; + case 0x1b: /* FMULX */ + gen_helper_vfp_mulxd(tcg_res, tcg_op1, tcg_op2, fpst); + break; + case 0x1c: /* FCMEQ */ + gen_helper_neon_ceq_f64(tcg_res, tcg_op1, tcg_op2, fpst); + break; case 0x1e: /* FMAX */ gen_helper_vfp_maxd(tcg_res, tcg_op1, tcg_op2, fpst); break; + case 0x1f: /* FRECPS */ + gen_helper_recpsf_f64(tcg_res, tcg_op1, tcg_op2, fpst); + break; case 0x38: /* FMINNM */ gen_helper_vfp_minnumd(tcg_res, tcg_op1, tcg_op2, fpst); break; @@ -5968,9 +6158,18 @@ static void handle_3same_float(DisasContext *s, int size, int elements, case 0x3e: /* FMIN */ gen_helper_vfp_mind(tcg_res, tcg_op1, tcg_op2, fpst); break; + case 0x3f: /* FRSQRTS */ + gen_helper_rsqrtsf_f64(tcg_res, tcg_op1, tcg_op2, fpst); + break; case 0x5b: /* FMUL */ gen_helper_vfp_muld(tcg_res, tcg_op1, tcg_op2, fpst); break; + case 0x5c: /* FCMGE */ + gen_helper_neon_cge_f64(tcg_res, tcg_op1, tcg_op2, fpst); + break; + case 0x5d: /* FACGE */ + gen_helper_neon_acge_f64(tcg_res, tcg_op1, tcg_op2, fpst); + break; case 0x5f: /* FDIV */ gen_helper_vfp_divd(tcg_res, tcg_op1, tcg_op2, fpst); break; @@ -5978,6 +6177,12 @@ static void handle_3same_float(DisasContext *s, int size, int elements, gen_helper_vfp_subd(tcg_res, tcg_op1, tcg_op2, fpst); gen_helper_vfp_absd(tcg_res, tcg_res); break; + case 0x7c: /* FCMGT */ + gen_helper_neon_cgt_f64(tcg_res, tcg_op1, tcg_op2, fpst); + break; + case 0x7d: /* FACGT */ + gen_helper_neon_acgt_f64(tcg_res, tcg_op1, tcg_op2, fpst); + break; default: g_assert_not_reached(); } @@ -5997,12 +6202,30 @@ static void handle_3same_float(DisasContext *s, int size, int elements, read_vec_element_i32(s, tcg_op2, rm, pass, MO_32); switch (fpopcode) { + case 0x39: /* FMLS */ + /* As usual for ARM, separate negation for fused multiply-add */ + gen_helper_vfp_negs(tcg_op1, tcg_op1); + /* fall through */ + case 0x19: /* FMLA */ + read_vec_element_i32(s, tcg_res, rd, pass, MO_32); + gen_helper_vfp_muladds(tcg_res, tcg_op1, tcg_op2, + tcg_res, fpst); + break; case 0x1a: /* FADD */ gen_helper_vfp_adds(tcg_res, tcg_op1, tcg_op2, fpst); break; + case 0x1b: /* FMULX */ + gen_helper_vfp_mulxs(tcg_res, tcg_op1, tcg_op2, fpst); + break; + case 0x1c: /* FCMEQ */ + gen_helper_neon_ceq_f32(tcg_res, tcg_op1, tcg_op2, fpst); + break; case 0x1e: /* FMAX */ gen_helper_vfp_maxs(tcg_res, tcg_op1, tcg_op2, fpst); break; + case 0x1f: /* FRECPS */ + gen_helper_recpsf_f32(tcg_res, tcg_op1, tcg_op2, fpst); + break; case 0x18: /* FMAXNM */ gen_helper_vfp_maxnums(tcg_res, tcg_op1, tcg_op2, fpst); break; @@ -6015,9 +6238,18 @@ static void handle_3same_float(DisasContext *s, int size, int elements, case 0x3e: /* FMIN */ gen_helper_vfp_mins(tcg_res, tcg_op1, tcg_op2, fpst); break; + case 0x3f: /* FRSQRTS */ + gen_helper_rsqrtsf_f32(tcg_res, tcg_op1, tcg_op2, fpst); + break; case 0x5b: /* FMUL */ gen_helper_vfp_muls(tcg_res, tcg_op1, tcg_op2, fpst); break; + case 0x5c: /* FCMGE */ + gen_helper_neon_cge_f32(tcg_res, tcg_op1, tcg_op2, fpst); + break; + case 0x5d: /* FACGE */ + gen_helper_neon_acge_f32(tcg_res, tcg_op1, tcg_op2, fpst); + break; case 0x5f: /* FDIV */ gen_helper_vfp_divs(tcg_res, tcg_op1, tcg_op2, fpst); break; @@ -6025,6 +6257,12 @@ static void handle_3same_float(DisasContext *s, int size, int elements, gen_helper_vfp_subs(tcg_res, tcg_op1, tcg_op2, fpst); gen_helper_vfp_abss(tcg_res, tcg_res); break; + case 0x7c: /* FCMGT */ + gen_helper_neon_cgt_f32(tcg_res, tcg_op1, tcg_op2, fpst); + break; + case 0x7d: /* FACGT */ + gen_helper_neon_acgt_f32(tcg_res, tcg_op1, tcg_op2, fpst); + break; default: g_assert_not_reached(); } @@ -6075,15 +6313,13 @@ static void disas_simd_scalar_three_reg_same(DisasContext *s, uint32_t insn) int fpopcode = opcode | (extract32(size, 1, 1) << 5) | (u << 6); switch (fpopcode) { case 0x1b: /* FMULX */ - case 0x1c: /* FCMEQ */ case 0x1f: /* FRECPS */ case 0x3f: /* FRSQRTS */ - case 0x5c: /* FCMGE */ case 0x5d: /* FACGE */ - case 0x7c: /* FCMGT */ case 0x7d: /* FACGT */ - unsupported_encoding(s, insn); - return; + case 0x1c: /* FCMEQ */ + case 0x5c: /* FCMGE */ + case 0x7c: /* FCMGT */ case 0x7a: /* FABD */ break; default: @@ -6268,6 +6504,115 @@ static void handle_2misc_64(DisasContext *s, int opcode, bool u, } } +static void handle_2misc_fcmp_zero(DisasContext *s, int opcode, + bool is_scalar, bool is_u, bool is_q, + int size, int rn, int rd) +{ + bool is_double = (size == 3); + TCGv_ptr fpst = get_fpstatus_ptr(); + + if (is_double) { + TCGv_i64 tcg_op = tcg_temp_new_i64(); + TCGv_i64 tcg_zero = tcg_const_i64(0); + TCGv_i64 tcg_res = tcg_temp_new_i64(); + NeonGenTwoDoubleOPFn *genfn; + bool swap = false; + int pass; + + switch (opcode) { + case 0x2e: /* FCMLT (zero) */ + swap = true; + /* fallthrough */ + case 0x2c: /* FCMGT (zero) */ + genfn = gen_helper_neon_cgt_f64; + break; + case 0x2d: /* FCMEQ (zero) */ + genfn = gen_helper_neon_ceq_f64; + break; + case 0x6d: /* FCMLE (zero) */ + swap = true; + /* fall through */ + case 0x6c: /* FCMGE (zero) */ + genfn = gen_helper_neon_cge_f64; + break; + default: + g_assert_not_reached(); + } + + for (pass = 0; pass < (is_scalar ? 1 : 2); pass++) { + read_vec_element(s, tcg_op, rn, pass, MO_64); + if (swap) { + genfn(tcg_res, tcg_zero, tcg_op, fpst); + } else { + genfn(tcg_res, tcg_op, tcg_zero, fpst); + } + write_vec_element(s, tcg_res, rd, pass, MO_64); + } + if (is_scalar) { + clear_vec_high(s, rd); + } + + tcg_temp_free_i64(tcg_res); + tcg_temp_free_i64(tcg_zero); + tcg_temp_free_i64(tcg_op); + } else { + TCGv_i32 tcg_op = tcg_temp_new_i32(); + TCGv_i32 tcg_zero = tcg_const_i32(0); + TCGv_i32 tcg_res = tcg_temp_new_i32(); + NeonGenTwoSingleOPFn *genfn; + bool swap = false; + int pass, maxpasses; + + switch (opcode) { + case 0x2e: /* FCMLT (zero) */ + swap = true; + /* fall through */ + case 0x2c: /* FCMGT (zero) */ + genfn = gen_helper_neon_cgt_f32; + break; + case 0x2d: /* FCMEQ (zero) */ + genfn = gen_helper_neon_ceq_f32; + break; + case 0x6d: /* FCMLE (zero) */ + swap = true; + /* fall through */ + case 0x6c: /* FCMGE (zero) */ + genfn = gen_helper_neon_cge_f32; + break; + default: + g_assert_not_reached(); + } + + if (is_scalar) { + maxpasses = 1; + } else { + maxpasses = is_q ? 4 : 2; + } + + for (pass = 0; pass < maxpasses; pass++) { + read_vec_element_i32(s, tcg_op, rn, pass, MO_32); + if (swap) { + genfn(tcg_res, tcg_zero, tcg_op, fpst); + } else { + genfn(tcg_res, tcg_op, tcg_zero, fpst); + } + if (is_scalar) { + write_fp_sreg(s, rd, tcg_res); + } else { + write_vec_element_i32(s, tcg_res, rd, pass, MO_32); + } + } + tcg_temp_free_i32(tcg_res); + tcg_temp_free_i32(tcg_zero); + tcg_temp_free_i32(tcg_op); + if (!is_q && !is_scalar) { + clear_vec_high(s, rd); + } + } + + tcg_temp_free_ptr(fpst); +} + /* C3.6.12 AdvSIMD scalar two reg misc * 31 30 29 28 24 23 22 21 17 16 12 11 10 9 5 4 0 * +-----+---+-----------+------+-----------+--------+-----+------+------+ @@ -6297,9 +6642,47 @@ static void disas_simd_scalar_two_reg_misc(DisasContext *s, uint32_t insn) return; } break; + case 0xc ... 0xf: + case 0x16 ... 0x1d: + case 0x1f: + /* Floating point: U, size[1] and opcode indicate operation; + * size[0] indicates single or double precision. + */ + opcode |= (extract32(size, 1, 1) << 5) | (u << 6); + size = extract32(size, 0, 1) ? 3 : 2; + switch (opcode) { + case 0x2c: /* FCMGT (zero) */ + case 0x2d: /* FCMEQ (zero) */ + case 0x2e: /* FCMLT (zero) */ + case 0x6c: /* FCMGE (zero) */ + case 0x6d: /* FCMLE (zero) */ + handle_2misc_fcmp_zero(s, opcode, true, u, true, size, rn, rd); + return; + case 0x1a: /* FCVTNS */ + case 0x1b: /* FCVTMS */ + case 0x1c: /* FCVTAS */ + case 0x1d: /* SCVTF */ + case 0x3a: /* FCVTPS */ + case 0x3b: /* FCVTZS */ + case 0x3d: /* FRECPE */ + case 0x3f: /* FRECPX */ + case 0x56: /* FCVTXN, FCVTXN2 */ + case 0x5a: /* FCVTNU */ + case 0x5b: /* FCVTMU */ + case 0x5c: /* FCVTAU */ + case 0x5d: /* UCVTF */ + case 0x7a: /* FCVTPU */ + case 0x7b: /* FCVTZU */ + case 0x7d: /* FRSQRTE */ + unsupported_encoding(s, insn); + return; + default: + unallocated_encoding(s); + return; + } + break; default: /* Other categories of encoding in this class: - * + floating point (single and double) * + SUQADD/USQADD/SQABS/SQNEG : size 8, 16, 32 or 64 * + SQXTN/SQXTN2/SQXTUN/SQXTUN2/UQXTN/UQXTN2: * narrowing saturate ops: size 64/32/16 -> 32/16/8 @@ -6322,17 +6705,6 @@ static void disas_simd_scalar_two_reg_misc(DisasContext *s, uint32_t insn) } } -/* C3.6.13 AdvSIMD scalar x indexed element - * 31 30 29 28 24 23 22 21 20 19 16 15 12 11 10 9 5 4 0 - * +-----+---+-----------+------+---+---+------+-----+---+---+------+------+ - * | 0 1 | U | 1 1 1 1 1 | size | L | M | Rm | opc | H | 0 | Rn | Rd | - * +-----+---+-----------+------+---+---+------+-----+---+---+------+------+ - */ -static void disas_simd_scalar_indexed(DisasContext *s, uint32_t insn) -{ - unsupported_encoding(s, insn); -} - /* SSHR[RA]/USHR[RA] - Vector shift right (optional rounding/accumulate) */ static void handle_vec_simd_shri(DisasContext *s, bool is_q, bool is_u, int immh, int immb, int opcode, int rn, int rd) @@ -6514,6 +6886,24 @@ static void disas_simd_shift_imm(DisasContext *s, uint32_t insn) } } +/* Generate code to do a "long" addition or subtraction, ie one done in + * TCGv_i64 on vector lanes twice the width specified by size. + */ +static void gen_neon_addl(int size, bool is_sub, TCGv_i64 tcg_res, + TCGv_i64 tcg_op1, TCGv_i64 tcg_op2) +{ + static NeonGenTwo64OpFn * const fns[3][2] = { + { gen_helper_neon_addl_u16, gen_helper_neon_subl_u16 }, + { gen_helper_neon_addl_u32, gen_helper_neon_subl_u32 }, + { tcg_gen_add_i64, tcg_gen_sub_i64 }, + }; + NeonGenTwo64OpFn *genfn; + assert(size < 3); + + genfn = fns[size][is_sub]; + genfn(tcg_res, tcg_op1, tcg_op2); +} + static void handle_3rd_widening(DisasContext *s, int is_q, int is_u, int size, int opcode, int rd, int rn, int rm) { @@ -6569,6 +6959,12 @@ static void handle_3rd_widening(DisasContext *s, int is_q, int is_u, int size, } switch (opcode) { + case 0: /* SADDL, SADDL2, UADDL, UADDL2 */ + tcg_gen_add_i64(tcg_passres, tcg_op1, tcg_op2); + break; + case 2: /* SSUBL, SSUBL2, USUBL, USUBL2 */ + tcg_gen_sub_i64(tcg_passres, tcg_op1, tcg_op2); + break; case 5: /* SABAL, SABAL2, UABAL, UABAL2 */ case 7: /* SABDL, SABDL2, UABDL, UABDL2 */ { @@ -6589,15 +6985,31 @@ static void handle_3rd_widening(DisasContext *s, int is_q, int is_u, int size, case 12: /* UMULL, UMULL2, SMULL, SMULL2 */ tcg_gen_mul_i64(tcg_passres, tcg_op1, tcg_op2); break; + case 9: /* SQDMLAL, SQDMLAL2 */ + case 11: /* SQDMLSL, SQDMLSL2 */ + case 13: /* SQDMULL, SQDMULL2 */ + tcg_gen_mul_i64(tcg_passres, tcg_op1, tcg_op2); + gen_helper_neon_addl_saturate_s64(tcg_passres, cpu_env, + tcg_passres, tcg_passres); + break; default: g_assert_not_reached(); } - if (accop > 0) { + if (opcode == 9 || opcode == 11) { + /* saturating accumulate ops */ + if (accop < 0) { + tcg_gen_neg_i64(tcg_passres, tcg_passres); + } + gen_helper_neon_addl_saturate_s64(tcg_res[pass], cpu_env, + tcg_res[pass], tcg_passres); + } else if (accop > 0) { tcg_gen_add_i64(tcg_res[pass], tcg_res[pass], tcg_passres); - tcg_temp_free_i64(tcg_passres); } else if (accop < 0) { tcg_gen_sub_i64(tcg_res[pass], tcg_res[pass], tcg_passres); + } + + if (accop != 0) { tcg_temp_free_i64(tcg_passres); } @@ -6622,6 +7034,23 @@ static void handle_3rd_widening(DisasContext *s, int is_q, int is_u, int size, } switch (opcode) { + case 0: /* SADDL, SADDL2, UADDL, UADDL2 */ + case 2: /* SSUBL, SSUBL2, USUBL, USUBL2 */ + { + TCGv_i64 tcg_op2_64 = tcg_temp_new_i64(); + static NeonGenWidenFn * const widenfns[2][2] = { + { gen_helper_neon_widen_s8, gen_helper_neon_widen_u8 }, + { gen_helper_neon_widen_s16, gen_helper_neon_widen_u16 }, + }; + NeonGenWidenFn *widenfn = widenfns[size][is_u]; + + widenfn(tcg_op2_64, tcg_op2); + widenfn(tcg_passres, tcg_op1); + gen_neon_addl(size, (opcode == 2), tcg_passres, + tcg_passres, tcg_op2_64); + tcg_temp_free_i64(tcg_op2_64); + break; + } case 5: /* SABAL, SABAL2, UABAL, UABAL2 */ case 7: /* SABDL, SABDL2, UABDL, UABDL2 */ if (size == 0) { @@ -6655,28 +7084,32 @@ static void handle_3rd_widening(DisasContext *s, int is_q, int is_u, int size, } } break; + case 9: /* SQDMLAL, SQDMLAL2 */ + case 11: /* SQDMLSL, SQDMLSL2 */ + case 13: /* SQDMULL, SQDMULL2 */ + assert(size == 1); + gen_helper_neon_mull_s16(tcg_passres, tcg_op1, tcg_op2); + gen_helper_neon_addl_saturate_s32(tcg_passres, cpu_env, + tcg_passres, tcg_passres); + break; default: g_assert_not_reached(); } tcg_temp_free_i32(tcg_op1); tcg_temp_free_i32(tcg_op2); - if (accop > 0) { - if (size == 0) { - gen_helper_neon_addl_u16(tcg_res[pass], tcg_res[pass], - tcg_passres); - } else { - gen_helper_neon_addl_u32(tcg_res[pass], tcg_res[pass], - tcg_passres); - } - tcg_temp_free_i64(tcg_passres); - } else if (accop < 0) { - if (size == 0) { - gen_helper_neon_subl_u16(tcg_res[pass], tcg_res[pass], - tcg_passres); + if (accop != 0) { + if (opcode == 9 || opcode == 11) { + /* saturating accumulate ops */ + if (accop < 0) { + gen_helper_neon_negl_u32(tcg_passres, tcg_passres); + } + gen_helper_neon_addl_saturate_s32(tcg_res[pass], cpu_env, + tcg_res[pass], + tcg_passres); } else { - gen_helper_neon_subl_u32(tcg_res[pass], tcg_res[pass], - tcg_passres); + gen_neon_addl(size, (accop < 0), tcg_res[pass], + tcg_res[pass], tcg_passres); } tcg_temp_free_i64(tcg_passres); } @@ -6689,6 +7122,95 @@ static void handle_3rd_widening(DisasContext *s, int is_q, int is_u, int size, tcg_temp_free_i64(tcg_res[1]); } +static void handle_3rd_wide(DisasContext *s, int is_q, int is_u, int size, + int opcode, int rd, int rn, int rm) +{ + TCGv_i64 tcg_res[2]; + int part = is_q ? 2 : 0; + int pass; + + for (pass = 0; pass < 2; pass++) { + TCGv_i64 tcg_op1 = tcg_temp_new_i64(); + TCGv_i32 tcg_op2 = tcg_temp_new_i32(); + TCGv_i64 tcg_op2_wide = tcg_temp_new_i64(); + static NeonGenWidenFn * const widenfns[3][2] = { + { gen_helper_neon_widen_s8, gen_helper_neon_widen_u8 }, + { gen_helper_neon_widen_s16, gen_helper_neon_widen_u16 }, + { tcg_gen_ext_i32_i64, tcg_gen_extu_i32_i64 }, + }; + NeonGenWidenFn *widenfn = widenfns[size][is_u]; + + read_vec_element(s, tcg_op1, rn, pass, MO_64); + read_vec_element_i32(s, tcg_op2, rm, part + pass, MO_32); + widenfn(tcg_op2_wide, tcg_op2); + tcg_temp_free_i32(tcg_op2); + tcg_res[pass] = tcg_temp_new_i64(); + gen_neon_addl(size, (opcode == 3), + tcg_res[pass], tcg_op1, tcg_op2_wide); + tcg_temp_free_i64(tcg_op1); + tcg_temp_free_i64(tcg_op2_wide); + } + + for (pass = 0; pass < 2; pass++) { + write_vec_element(s, tcg_res[pass], rd, pass, MO_64); + tcg_temp_free_i64(tcg_res[pass]); + } +} + +static void do_narrow_high_u32(TCGv_i32 res, TCGv_i64 in) +{ + tcg_gen_shri_i64(in, in, 32); + tcg_gen_trunc_i64_i32(res, in); +} + +static void do_narrow_round_high_u32(TCGv_i32 res, TCGv_i64 in) +{ + tcg_gen_addi_i64(in, in, 1U << 31); + do_narrow_high_u32(res, in); +} + +static void handle_3rd_narrowing(DisasContext *s, int is_q, int is_u, int size, + int opcode, int rd, int rn, int rm) +{ + TCGv_i32 tcg_res[2]; + int part = is_q ? 2 : 0; + int pass; + + for (pass = 0; pass < 2; pass++) { + TCGv_i64 tcg_op1 = tcg_temp_new_i64(); + TCGv_i64 tcg_op2 = tcg_temp_new_i64(); + TCGv_i64 tcg_wideres = tcg_temp_new_i64(); + static NeonGenNarrowFn * const narrowfns[3][2] = { + { gen_helper_neon_narrow_high_u8, + gen_helper_neon_narrow_round_high_u8 }, + { gen_helper_neon_narrow_high_u16, + gen_helper_neon_narrow_round_high_u16 }, + { do_narrow_high_u32, do_narrow_round_high_u32 }, + }; + NeonGenNarrowFn *gennarrow = narrowfns[size][is_u]; + + read_vec_element(s, tcg_op1, rn, pass, MO_64); + read_vec_element(s, tcg_op2, rm, pass, MO_64); + + gen_neon_addl(size, (opcode == 6), tcg_wideres, tcg_op1, tcg_op2); + + tcg_temp_free_i64(tcg_op1); + tcg_temp_free_i64(tcg_op2); + + tcg_res[pass] = tcg_temp_new_i32(); + gennarrow(tcg_res[pass], tcg_wideres); + tcg_temp_free_i64(tcg_wideres); + } + + for (pass = 0; pass < 2; pass++) { + write_vec_element_i32(s, tcg_res[pass], rd, pass + part, MO_32); + tcg_temp_free_i32(tcg_res[pass]); + } + if (!is_q) { + clear_vec_high(s, rd); + } +} + /* C3.6.15 AdvSIMD three different * 31 30 29 28 24 23 22 21 20 16 15 12 11 10 9 5 4 0 * +---+---+---+-----------+------+---+------+--------+-----+------+------+ @@ -6719,31 +7241,43 @@ static void disas_simd_three_reg_diff(DisasContext *s, uint32_t insn) case 1: /* SADDW, SADDW2, UADDW, UADDW2 */ case 3: /* SSUBW, SSUBW2, USUBW, USUBW2 */ /* 64 x 128 -> 128 */ - unsupported_encoding(s, insn); + if (size == 3) { + unallocated_encoding(s); + return; + } + handle_3rd_wide(s, is_q, is_u, size, opcode, rd, rn, rm); break; case 4: /* ADDHN, ADDHN2, RADDHN, RADDHN2 */ case 6: /* SUBHN, SUBHN2, RSUBHN, RSUBHN2 */ /* 128 x 128 -> 64 */ - unsupported_encoding(s, insn); + if (size == 3) { + unallocated_encoding(s); + return; + } + handle_3rd_narrowing(s, is_q, is_u, size, opcode, rd, rn, rm); break; - case 9: - case 11: - case 13: - case 14: - if (is_u) { + case 14: /* PMULL, PMULL2 */ + if (is_u || size == 1 || size == 2) { unallocated_encoding(s); return; } - /* fall through */ - case 0: - case 2: unsupported_encoding(s, insn); break; - case 5: - case 7: - case 8: - case 10: - case 12: + case 9: /* SQDMLAL, SQDMLAL2 */ + case 11: /* SQDMLSL, SQDMLSL2 */ + case 13: /* SQDMULL, SQDMULL2 */ + if (is_u || size == 0) { + unallocated_encoding(s); + return; + } + /* fall through */ + case 0: /* SADDL, SADDL2, UADDL, UADDL2 */ + case 2: /* SSUBL, SSUBL2, USUBL, USUBL2 */ + case 5: /* SABAL, SABAL2, UABAL, UABAL2 */ + case 7: /* SABDL, SABDL2, UABDL, UABDL2 */ + case 8: /* SMLAL, SMLAL2, UMLAL, UMLAL2 */ + case 10: /* SMLSL, SMLSL2, UMLSL, UMLSL2 */ + case 12: /* SMULL, SMULL2, UMULL, UMULL2 */ /* 64 x 64 -> 128 */ if (size == 3) { unallocated_encoding(s); @@ -6856,39 +7390,22 @@ static void gen_min_u32(TCGv_i32 res, TCGv_i32 op1, TCGv_i32 op2) tcg_gen_movcond_i32(TCG_COND_LEU, res, op1, op2, op1, op2); } -/* Pairwise op subgroup of C3.6.16. */ -static void disas_simd_3same_pair(DisasContext *s, uint32_t insn) +/* Pairwise op subgroup of C3.6.16. + * + * This is called directly or via the handle_3same_float for float pairwise + * operations where the opcode and size are calculated differently. + */ +static void handle_simd_3same_pair(DisasContext *s, int is_q, int u, int opcode, + int size, int rn, int rm, int rd) { - int is_q = extract32(insn, 30, 1); - int u = extract32(insn, 29, 1); - int size = extract32(insn, 22, 2); - int opcode = extract32(insn, 11, 5); - int rm = extract32(insn, 16, 5); - int rn = extract32(insn, 5, 5); - int rd = extract32(insn, 0, 5); + TCGv_ptr fpst; int pass; - if (size == 3 && !is_q) { - unallocated_encoding(s); - return; - } - - switch (opcode) { - case 0x14: /* SMAXP, UMAXP */ - case 0x15: /* SMINP, UMINP */ - if (size == 3) { - unallocated_encoding(s); - return; - } - break; - case 0x17: - if (u) { - unallocated_encoding(s); - return; - } - break; - default: - g_assert_not_reached(); + /* Floating point operations need fpst */ + if (opcode >= 0x58) { + fpst = get_fpstatus_ptr(); + } else { + TCGV_UNUSED_PTR(fpst); } /* These operations work on the concatenated rm:rn, with each pair of @@ -6906,9 +7423,28 @@ static void disas_simd_3same_pair(DisasContext *s, uint32_t insn) read_vec_element(s, tcg_op2, passreg, 1, MO_64); tcg_res[pass] = tcg_temp_new_i64(); - /* The only 64 bit pairwise integer op is ADDP */ - assert(opcode == 0x17); - tcg_gen_add_i64(tcg_res[pass], tcg_op1, tcg_op2); + switch (opcode) { + case 0x17: /* ADDP */ + tcg_gen_add_i64(tcg_res[pass], tcg_op1, tcg_op2); + break; + case 0x58: /* FMAXNMP */ + gen_helper_vfp_maxnumd(tcg_res[pass], tcg_op1, tcg_op2, fpst); + break; + case 0x5a: /* FADDP */ + gen_helper_vfp_addd(tcg_res[pass], tcg_op1, tcg_op2, fpst); + break; + case 0x5e: /* FMAXP */ + gen_helper_vfp_maxd(tcg_res[pass], tcg_op1, tcg_op2, fpst); + break; + case 0x78: /* FMINNMP */ + gen_helper_vfp_minnumd(tcg_res[pass], tcg_op1, tcg_op2, fpst); + break; + case 0x7e: /* FMINP */ + gen_helper_vfp_mind(tcg_res[pass], tcg_op1, tcg_op2, fpst); + break; + default: + g_assert_not_reached(); + } tcg_temp_free_i64(tcg_op1); tcg_temp_free_i64(tcg_op2); @@ -6925,7 +7461,7 @@ static void disas_simd_3same_pair(DisasContext *s, uint32_t insn) for (pass = 0; pass < maxpass; pass++) { TCGv_i32 tcg_op1 = tcg_temp_new_i32(); TCGv_i32 tcg_op2 = tcg_temp_new_i32(); - NeonGenTwoOpFn *genfn; + NeonGenTwoOpFn *genfn = NULL; int passreg = pass < (maxpass / 2) ? rn : rm; int passelt = (is_q && (pass & 1)) ? 2 : 0; @@ -6964,11 +7500,30 @@ static void disas_simd_3same_pair(DisasContext *s, uint32_t insn) genfn = fns[size][u]; break; } + /* The FP operations are all on single floats (32 bit) */ + case 0x58: /* FMAXNMP */ + gen_helper_vfp_maxnums(tcg_res[pass], tcg_op1, tcg_op2, fpst); + break; + case 0x5a: /* FADDP */ + gen_helper_vfp_adds(tcg_res[pass], tcg_op1, tcg_op2, fpst); + break; + case 0x5e: /* FMAXP */ + gen_helper_vfp_maxs(tcg_res[pass], tcg_op1, tcg_op2, fpst); + break; + case 0x78: /* FMINNMP */ + gen_helper_vfp_minnums(tcg_res[pass], tcg_op1, tcg_op2, fpst); + break; + case 0x7e: /* FMINP */ + gen_helper_vfp_mins(tcg_res[pass], tcg_op1, tcg_op2, fpst); + break; default: g_assert_not_reached(); } - genfn(tcg_res[pass], tcg_op1, tcg_op2); + /* FP ops called directly, otherwise call now */ + if (genfn) { + genfn(tcg_res[pass], tcg_op1, tcg_op2); + } tcg_temp_free_i32(tcg_op1); tcg_temp_free_i32(tcg_op2); @@ -6982,6 +7537,10 @@ static void disas_simd_3same_pair(DisasContext *s, uint32_t insn) clear_vec_high(s, rd); } } + + if (!TCGV_IS_UNUSED_PTR(fpst)) { + tcg_temp_free_ptr(fpst); + } } /* Floating point op subgroup of C3.6.16. */ @@ -7015,30 +7574,32 @@ static void disas_simd_3same_float(DisasContext *s, uint32_t insn) case 0x5e: /* FMAXP */ case 0x78: /* FMINNMP */ case 0x7e: /* FMINP */ - /* pairwise ops */ - unsupported_encoding(s, insn); + if (size && !is_q) { + unallocated_encoding(s); + return; + } + handle_simd_3same_pair(s, is_q, 0, fpopcode, size ? MO_64 : MO_32, + rn, rm, rd); return; case 0x1b: /* FMULX */ - case 0x1c: /* FCMEQ */ case 0x1f: /* FRECPS */ case 0x3f: /* FRSQRTS */ - case 0x5c: /* FCMGE */ case 0x5d: /* FACGE */ - case 0x7c: /* FCMGT */ case 0x7d: /* FACGT */ case 0x19: /* FMLA */ case 0x39: /* FMLS */ - unsupported_encoding(s, insn); - return; case 0x18: /* FMAXNM */ case 0x1a: /* FADD */ + case 0x1c: /* FCMEQ */ case 0x1e: /* FMAX */ case 0x38: /* FMINNM */ case 0x3a: /* FSUB */ case 0x3e: /* FMIN */ case 0x5b: /* FMUL */ + case 0x5c: /* FCMGE */ case 0x5f: /* FDIV */ case 0x7a: /* FABD */ + case 0x7c: /* FCMGT */ handle_3same_float(s, size, elements, fpopcode, rd, rn, rm); return; default: @@ -7366,9 +7927,28 @@ static void disas_simd_three_reg_same(DisasContext *s, uint32_t insn) case 0x17: /* ADDP */ case 0x14: /* SMAXP, UMAXP */ case 0x15: /* SMINP, UMINP */ + { /* Pairwise operations */ - disas_simd_3same_pair(s, insn); + int is_q = extract32(insn, 30, 1); + int u = extract32(insn, 29, 1); + int size = extract32(insn, 22, 2); + int rm = extract32(insn, 16, 5); + int rn = extract32(insn, 5, 5); + int rd = extract32(insn, 0, 5); + if (opcode == 0x17) { + if (u || (size == 3 && !is_q)) { + unallocated_encoding(s); + return; + } + } else { + if (size == 3) { + unallocated_encoding(s); + return; + } + } + handle_simd_3same_pair(s, is_q, u, opcode, size, rn, rm, rd); break; + } case 0x18 ... 0x31: /* floating point ops, sz[1] and U are part of opcode */ disas_simd_3same_float(s, insn); @@ -7618,6 +8198,17 @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn) return; } break; + case 0x2c: /* FCMGT (zero) */ + case 0x2d: /* FCMEQ (zero) */ + case 0x2e: /* FCMLT (zero) */ + case 0x6c: /* FCMGE (zero) */ + case 0x6d: /* FCMLE (zero) */ + if (size == 3 && !is_q) { + unallocated_encoding(s); + return; + } + handle_2misc_fcmp_zero(s, opcode, false, u, is_q, size, rn, rd); + return; case 0x16: /* FCVTN, FCVTN2 */ case 0x17: /* FCVTL, FCVTL2 */ case 0x18: /* FRINTN */ @@ -7626,9 +8217,6 @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn) case 0x1b: /* FCVTMS */ case 0x1c: /* FCVTAS */ case 0x1d: /* SCVTF */ - case 0x2c: /* FCMGT (zero) */ - case 0x2d: /* FCMEQ (zero) */ - case 0x2e: /* FCMLT (zero) */ case 0x38: /* FRINTP */ case 0x39: /* FRINTZ */ case 0x3a: /* FCVTPS */ @@ -7642,8 +8230,6 @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn) case 0x5b: /* FCVTMU */ case 0x5c: /* FCVTAU */ case 0x5d: /* UCVTF */ - case 0x6c: /* FCMGE (zero) */ - case 0x6d: /* FCMLE (zero) */ case 0x79: /* FRINTI */ case 0x7a: /* FCVTPU */ case 0x7b: /* FCVTZU */ @@ -7805,15 +8391,455 @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn) } } -/* C3.6.18 AdvSIMD vector x indexed element +/* C3.6.13 AdvSIMD scalar x indexed element + * 31 30 29 28 24 23 22 21 20 19 16 15 12 11 10 9 5 4 0 + * +-----+---+-----------+------+---+---+------+-----+---+---+------+------+ + * | 0 1 | U | 1 1 1 1 1 | size | L | M | Rm | opc | H | 0 | Rn | Rd | + * +-----+---+-----------+------+---+---+------+-----+---+---+------+------+ + * C3.6.18 AdvSIMD vector x indexed element * 31 30 29 28 24 23 22 21 20 19 16 15 12 11 10 9 5 4 0 * +---+---+---+-----------+------+---+---+------+-----+---+---+------+------+ * | 0 | Q | U | 0 1 1 1 1 | size | L | M | Rm | opc | H | 0 | Rn | Rd | * +---+---+---+-----------+------+---+---+------+-----+---+---+------+------+ */ -static void disas_simd_indexed_vector(DisasContext *s, uint32_t insn) -{ - unsupported_encoding(s, insn); +static void disas_simd_indexed(DisasContext *s, uint32_t insn) +{ + /* This encoding has two kinds of instruction: + * normal, where we perform elt x idxelt => elt for each + * element in the vector + * long, where we perform elt x idxelt and generate a result of + * double the width of the input element + * The long ops have a 'part' specifier (ie come in INSN, INSN2 pairs). + */ + bool is_scalar = extract32(insn, 28, 1); + bool is_q = extract32(insn, 30, 1); + bool u = extract32(insn, 29, 1); + int size = extract32(insn, 22, 2); + int l = extract32(insn, 21, 1); + int m = extract32(insn, 20, 1); + /* Note that the Rm field here is only 4 bits, not 5 as it usually is */ + int rm = extract32(insn, 16, 4); + int opcode = extract32(insn, 12, 4); + int h = extract32(insn, 11, 1); + int rn = extract32(insn, 5, 5); + int rd = extract32(insn, 0, 5); + bool is_long = false; + bool is_fp = false; + int index; + TCGv_ptr fpst; + + switch (opcode) { + case 0x0: /* MLA */ + case 0x4: /* MLS */ + if (!u || is_scalar) { + unallocated_encoding(s); + return; + } + break; + case 0x2: /* SMLAL, SMLAL2, UMLAL, UMLAL2 */ + case 0x6: /* SMLSL, SMLSL2, UMLSL, UMLSL2 */ + case 0xa: /* SMULL, SMULL2, UMULL, UMULL2 */ + if (is_scalar) { + unallocated_encoding(s); + return; + } + is_long = true; + break; + case 0x3: /* SQDMLAL, SQDMLAL2 */ + case 0x7: /* SQDMLSL, SQDMLSL2 */ + case 0xb: /* SQDMULL, SQDMULL2 */ + is_long = true; + /* fall through */ + case 0xc: /* SQDMULH */ + case 0xd: /* SQRDMULH */ + if (u) { + unallocated_encoding(s); + return; + } + break; + case 0x8: /* MUL */ + if (u || is_scalar) { + unallocated_encoding(s); + return; + } + break; + case 0x1: /* FMLA */ + case 0x5: /* FMLS */ + if (u) { + unallocated_encoding(s); + return; + } + /* fall through */ + case 0x9: /* FMUL, FMULX */ + if (!extract32(size, 1, 1)) { + unallocated_encoding(s); + return; + } + is_fp = true; + break; + default: + unallocated_encoding(s); + return; + } + + if (is_fp) { + /* low bit of size indicates single/double */ + size = extract32(size, 0, 1) ? 3 : 2; + if (size == 2) { + index = h << 1 | l; + } else { + if (l || !is_q) { + unallocated_encoding(s); + return; + } + index = h; + } + rm |= (m << 4); + } else { + switch (size) { + case 1: + index = h << 2 | l << 1 | m; + break; + case 2: + index = h << 1 | l; + rm |= (m << 4); + break; + default: + unallocated_encoding(s); + return; + } + } + + if (is_fp) { + fpst = get_fpstatus_ptr(); + } else { + TCGV_UNUSED_PTR(fpst); + } + + if (size == 3) { + TCGv_i64 tcg_idx = tcg_temp_new_i64(); + int pass; + + assert(is_fp && is_q && !is_long); + + read_vec_element(s, tcg_idx, rm, index, MO_64); + + for (pass = 0; pass < (is_scalar ? 1 : 2); pass++) { + TCGv_i64 tcg_op = tcg_temp_new_i64(); + TCGv_i64 tcg_res = tcg_temp_new_i64(); + + read_vec_element(s, tcg_op, rn, pass, MO_64); + + switch (opcode) { + case 0x5: /* FMLS */ + /* As usual for ARM, separate negation for fused multiply-add */ + gen_helper_vfp_negd(tcg_op, tcg_op); + /* fall through */ + case 0x1: /* FMLA */ + read_vec_element(s, tcg_res, rd, pass, MO_64); + gen_helper_vfp_muladdd(tcg_res, tcg_op, tcg_idx, tcg_res, fpst); + break; + case 0x9: /* FMUL, FMULX */ + if (u) { + gen_helper_vfp_mulxd(tcg_res, tcg_op, tcg_idx, fpst); + } else { + gen_helper_vfp_muld(tcg_res, tcg_op, tcg_idx, fpst); + } + break; + default: + g_assert_not_reached(); + } + + write_vec_element(s, tcg_res, rd, pass, MO_64); + tcg_temp_free_i64(tcg_op); + tcg_temp_free_i64(tcg_res); + } + + if (is_scalar) { + clear_vec_high(s, rd); + } + + tcg_temp_free_i64(tcg_idx); + } else if (!is_long) { + /* 32 bit floating point, or 16 or 32 bit integer. + * For the 16 bit scalar case we use the usual Neon helpers and + * rely on the fact that 0 op 0 == 0 with no side effects. + */ + TCGv_i32 tcg_idx = tcg_temp_new_i32(); + int pass, maxpasses; + + if (is_scalar) { + maxpasses = 1; + } else { + maxpasses = is_q ? 4 : 2; + } + + read_vec_element_i32(s, tcg_idx, rm, index, size); + + if (size == 1 && !is_scalar) { + /* The simplest way to handle the 16x16 indexed ops is to duplicate + * the index into both halves of the 32 bit tcg_idx and then use + * the usual Neon helpers. + */ + tcg_gen_deposit_i32(tcg_idx, tcg_idx, tcg_idx, 16, 16); + } + + for (pass = 0; pass < maxpasses; pass++) { + TCGv_i32 tcg_op = tcg_temp_new_i32(); + TCGv_i32 tcg_res = tcg_temp_new_i32(); + + read_vec_element_i32(s, tcg_op, rn, pass, is_scalar ? size : MO_32); + + switch (opcode) { + case 0x0: /* MLA */ + case 0x4: /* MLS */ + case 0x8: /* MUL */ + { + static NeonGenTwoOpFn * const fns[2][2] = { + { gen_helper_neon_add_u16, gen_helper_neon_sub_u16 }, + { tcg_gen_add_i32, tcg_gen_sub_i32 }, + }; + NeonGenTwoOpFn *genfn; + bool is_sub = opcode == 0x4; + + if (size == 1) { + gen_helper_neon_mul_u16(tcg_res, tcg_op, tcg_idx); + } else { + tcg_gen_mul_i32(tcg_res, tcg_op, tcg_idx); + } + if (opcode == 0x8) { + break; + } + read_vec_element_i32(s, tcg_op, rd, pass, MO_32); + genfn = fns[size - 1][is_sub]; + genfn(tcg_res, tcg_op, tcg_res); + break; + } + case 0x5: /* FMLS */ + /* As usual for ARM, separate negation for fused multiply-add */ + gen_helper_vfp_negs(tcg_op, tcg_op); + /* fall through */ + case 0x1: /* FMLA */ + read_vec_element_i32(s, tcg_res, rd, pass, MO_32); + gen_helper_vfp_muladds(tcg_res, tcg_op, tcg_idx, tcg_res, fpst); + break; + case 0x9: /* FMUL, FMULX */ + if (u) { + gen_helper_vfp_mulxs(tcg_res, tcg_op, tcg_idx, fpst); + } else { + gen_helper_vfp_muls(tcg_res, tcg_op, tcg_idx, fpst); + } + break; + case 0xc: /* SQDMULH */ + if (size == 1) { + gen_helper_neon_qdmulh_s16(tcg_res, cpu_env, + tcg_op, tcg_idx); + } else { + gen_helper_neon_qdmulh_s32(tcg_res, cpu_env, + tcg_op, tcg_idx); + } + break; + case 0xd: /* SQRDMULH */ + if (size == 1) { + gen_helper_neon_qrdmulh_s16(tcg_res, cpu_env, + tcg_op, tcg_idx); + } else { + gen_helper_neon_qrdmulh_s32(tcg_res, cpu_env, + tcg_op, tcg_idx); + } + break; + default: + g_assert_not_reached(); + } + + if (is_scalar) { + write_fp_sreg(s, rd, tcg_res); + } else { + write_vec_element_i32(s, tcg_res, rd, pass, MO_32); + } + + tcg_temp_free_i32(tcg_op); + tcg_temp_free_i32(tcg_res); + } + + tcg_temp_free_i32(tcg_idx); + + if (!is_q) { + clear_vec_high(s, rd); + } + } else { + /* long ops: 16x16->32 or 32x32->64 */ + TCGv_i64 tcg_res[2]; + int pass; + bool satop = extract32(opcode, 0, 1); + TCGMemOp memop = MO_32; + + if (satop || !u) { + memop |= MO_SIGN; + } + + if (size == 2) { + TCGv_i64 tcg_idx = tcg_temp_new_i64(); + + read_vec_element(s, tcg_idx, rm, index, memop); + + for (pass = 0; pass < (is_scalar ? 1 : 2); pass++) { + TCGv_i64 tcg_op = tcg_temp_new_i64(); + TCGv_i64 tcg_passres; + int passelt; + + if (is_scalar) { + passelt = 0; + } else { + passelt = pass + (is_q * 2); + } + + read_vec_element(s, tcg_op, rn, passelt, memop); + + tcg_res[pass] = tcg_temp_new_i64(); + + if (opcode == 0xa || opcode == 0xb) { + /* Non-accumulating ops */ + tcg_passres = tcg_res[pass]; + } else { + tcg_passres = tcg_temp_new_i64(); + } + + tcg_gen_mul_i64(tcg_passres, tcg_op, tcg_idx); + tcg_temp_free_i64(tcg_op); + + if (satop) { + /* saturating, doubling */ + gen_helper_neon_addl_saturate_s64(tcg_passres, cpu_env, + tcg_passres, tcg_passres); + } + + if (opcode == 0xa || opcode == 0xb) { + continue; + } + + /* Accumulating op: handle accumulate step */ + read_vec_element(s, tcg_res[pass], rd, pass, MO_64); + + switch (opcode) { + case 0x2: /* SMLAL, SMLAL2, UMLAL, UMLAL2 */ + tcg_gen_add_i64(tcg_res[pass], tcg_res[pass], tcg_passres); + break; + case 0x6: /* SMLSL, SMLSL2, UMLSL, UMLSL2 */ + tcg_gen_sub_i64(tcg_res[pass], tcg_res[pass], tcg_passres); + break; + case 0x7: /* SQDMLSL, SQDMLSL2 */ + tcg_gen_neg_i64(tcg_passres, tcg_passres); + /* fall through */ + case 0x3: /* SQDMLAL, SQDMLAL2 */ + gen_helper_neon_addl_saturate_s64(tcg_res[pass], cpu_env, + tcg_res[pass], + tcg_passres); + break; + default: + g_assert_not_reached(); + } + tcg_temp_free_i64(tcg_passres); + } + tcg_temp_free_i64(tcg_idx); + + if (is_scalar) { + clear_vec_high(s, rd); + } + } else { + TCGv_i32 tcg_idx = tcg_temp_new_i32(); + + assert(size == 1); + read_vec_element_i32(s, tcg_idx, rm, index, size); + + if (!is_scalar) { + /* The simplest way to handle the 16x16 indexed ops is to + * duplicate the index into both halves of the 32 bit tcg_idx + * and then use the usual Neon helpers. + */ + tcg_gen_deposit_i32(tcg_idx, tcg_idx, tcg_idx, 16, 16); + } + + for (pass = 0; pass < (is_scalar ? 1 : 2); pass++) { + TCGv_i32 tcg_op = tcg_temp_new_i32(); + TCGv_i64 tcg_passres; + + if (is_scalar) { + read_vec_element_i32(s, tcg_op, rn, pass, size); + } else { + read_vec_element_i32(s, tcg_op, rn, + pass + (is_q * 2), MO_32); + } + + tcg_res[pass] = tcg_temp_new_i64(); + + if (opcode == 0xa || opcode == 0xb) { + /* Non-accumulating ops */ + tcg_passres = tcg_res[pass]; + } else { + tcg_passres = tcg_temp_new_i64(); + } + + if (memop & MO_SIGN) { + gen_helper_neon_mull_s16(tcg_passres, tcg_op, tcg_idx); + } else { + gen_helper_neon_mull_u16(tcg_passres, tcg_op, tcg_idx); + } + if (satop) { + gen_helper_neon_addl_saturate_s32(tcg_passres, cpu_env, + tcg_passres, tcg_passres); + } + tcg_temp_free_i32(tcg_op); + + if (opcode == 0xa || opcode == 0xb) { + continue; + } + + /* Accumulating op: handle accumulate step */ + read_vec_element(s, tcg_res[pass], rd, pass, MO_64); + + switch (opcode) { + case 0x2: /* SMLAL, SMLAL2, UMLAL, UMLAL2 */ + gen_helper_neon_addl_u32(tcg_res[pass], tcg_res[pass], + tcg_passres); + break; + case 0x6: /* SMLSL, SMLSL2, UMLSL, UMLSL2 */ + gen_helper_neon_subl_u32(tcg_res[pass], tcg_res[pass], + tcg_passres); + break; + case 0x7: /* SQDMLSL, SQDMLSL2 */ + gen_helper_neon_negl_u32(tcg_passres, tcg_passres); + /* fall through */ + case 0x3: /* SQDMLAL, SQDMLAL2 */ + gen_helper_neon_addl_saturate_s32(tcg_res[pass], cpu_env, + tcg_res[pass], + tcg_passres); + break; + default: + g_assert_not_reached(); + } + tcg_temp_free_i64(tcg_passres); + } + tcg_temp_free_i32(tcg_idx); + + if (is_scalar) { + tcg_gen_ext32u_i64(tcg_res[0], tcg_res[0]); + } + } + + if (is_scalar) { + tcg_res[1] = tcg_const_i64(0); + } + + for (pass = 0; pass < 2; pass++) { + write_vec_element(s, tcg_res[pass], rd, pass, MO_64); + tcg_temp_free_i64(tcg_res[pass]); + } + } + + if (!TCGV_IS_UNUSED_PTR(fpst)) { + tcg_temp_free_ptr(fpst); + } } /* C3.6.19 Crypto AES @@ -7861,7 +8887,7 @@ static const AArch64DecodeTable data_proc_simd[] = { { 0x0e200800, 0x9f3e0c00, disas_simd_two_reg_misc }, { 0x0e300800, 0x9f3e0c00, disas_simd_across_lanes }, { 0x0e000400, 0x9fe08400, disas_simd_copy }, - { 0x0f000000, 0x9f000400, disas_simd_indexed_vector }, + { 0x0f000000, 0x9f000400, disas_simd_indexed }, /* vector indexed */ /* simd_mod_imm decode is a subset of simd_shift_imm, so must precede it */ { 0x0f000400, 0x9ff80400, disas_simd_mod_imm }, { 0x0f000400, 0x9f800400, disas_simd_shift_imm }, @@ -7873,7 +8899,7 @@ static const AArch64DecodeTable data_proc_simd[] = { { 0x5e200800, 0xdf3e0c00, disas_simd_scalar_two_reg_misc }, { 0x5e300800, 0xdf3e0c00, disas_simd_scalar_pairwise }, { 0x5e000400, 0xdfe08400, disas_simd_scalar_copy }, - { 0x5f000000, 0xdf000400, disas_simd_scalar_indexed }, + { 0x5f000000, 0xdf000400, disas_simd_indexed }, /* scalar indexed */ { 0x5f000400, 0xdf800400, disas_simd_scalar_shift_imm }, { 0x4e280800, 0xff3e0c00, disas_crypto_aes }, { 0x5e000000, 0xff208c00, disas_crypto_three_reg_sha }, diff --git a/target-arm/translate.c b/target-arm/translate.c index 782aab8b58..6ccf0ba482 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -6837,6 +6837,17 @@ static int disas_coproc_insn(CPUARMState * env, DisasContext *s, uint32_t insn) return 1; } + if (ri->accessfn) { + /* Emit code to perform further access permissions checks at + * runtime; this may result in an exception. + */ + TCGv_ptr tmpptr; + gen_set_pc_im(s, s->pc); + tmpptr = tcg_const_ptr(ri); + gen_helper_access_check_cp_reg(cpu_env, tmpptr); + tcg_temp_free_ptr(tmpptr); + } + /* Handle special cases first */ switch (ri->type & ~(ARM_CP_FLAG_MASK & ~ARM_CP_SPECIAL)) { case ARM_CP_NOP: @@ -6865,7 +6876,6 @@ static int disas_coproc_insn(CPUARMState * env, DisasContext *s, uint32_t insn) tmp64 = tcg_const_i64(ri->resetvalue); } else if (ri->readfn) { TCGv_ptr tmpptr; - gen_set_pc_im(s, s->pc); tmp64 = tcg_temp_new_i64(); tmpptr = tcg_const_ptr(ri); gen_helper_get_cp_reg64(tmp64, cpu_env, tmpptr); @@ -6888,7 +6898,6 @@ static int disas_coproc_insn(CPUARMState * env, DisasContext *s, uint32_t insn) tmp = tcg_const_i32(ri->resetvalue); } else if (ri->readfn) { TCGv_ptr tmpptr; - gen_set_pc_im(s, s->pc); tmp = tcg_temp_new_i32(); tmpptr = tcg_const_ptr(ri); gen_helper_get_cp_reg(tmp, cpu_env, tmpptr); @@ -6923,7 +6932,6 @@ static int disas_coproc_insn(CPUARMState * env, DisasContext *s, uint32_t insn) tcg_temp_free_i32(tmphi); if (ri->writefn) { TCGv_ptr tmpptr = tcg_const_ptr(ri); - gen_set_pc_im(s, s->pc); gen_helper_set_cp_reg64(cpu_env, tmpptr, tmp64); tcg_temp_free_ptr(tmpptr); } else { @@ -6934,7 +6942,6 @@ static int disas_coproc_insn(CPUARMState * env, DisasContext *s, uint32_t insn) if (ri->writefn) { TCGv_i32 tmp; TCGv_ptr tmpptr; - gen_set_pc_im(s, s->pc); tmp = load_reg(s, rt); tmpptr = tcg_const_ptr(ri); gen_helper_set_cp_reg(cpu_env, tmpptr, tmp); @@ -6962,6 +6969,19 @@ static int disas_coproc_insn(CPUARMState * env, DisasContext *s, uint32_t insn) return 0; } + /* Unknown register; this might be a guest error or a QEMU + * unimplemented feature. + */ + if (is64) { + qemu_log_mask(LOG_UNIMP, "%s access to unsupported AArch32 " + "64 bit system register cp:%d opc1: %d crm:%d\n", + isread ? "read" : "write", cpnum, opc1, crm); + } else { + qemu_log_mask(LOG_UNIMP, "%s access to unsupported AArch32 " + "system register cp:%d opc1:%d crn:%d crm:%d opc2:%d\n", + isread ? "read" : "write", cpnum, opc1, crn, crm, opc2); + } + return 1; } diff --git a/target-i386/translate.c b/target-i386/translate.c index b0f227915a..5dd2450798 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -6284,6 +6284,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, case 0xe5: ot = mo_b_d32(b, dflag); val = cpu_ldub_code(env, s->pc++); + tcg_gen_movi_tl(cpu_T[0], val); gen_check_io(s, ot, pc_start - s->cs_base, SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes)); if (use_icount) @@ -6300,6 +6301,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, case 0xe7: ot = mo_b_d32(b, dflag); val = cpu_ldub_code(env, s->pc++); + tcg_gen_movi_tl(cpu_T[0], val); gen_check_io(s, ot, pc_start - s->cs_base, svm_is_rep(prefixes)); gen_op_mov_v_reg(ot, cpu_T[1], R_EAX); diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c index c030a2032a..445c3606fe 100644 --- a/target-ppc/translate_init.c +++ b/target-ppc/translate_init.c @@ -7960,6 +7960,17 @@ static int ppc_fixup_cpu(PowerPCCPU *cpu) return 0; } +static inline bool ppc_cpu_is_valid(PowerPCCPUClass *pcc) +{ +#ifdef TARGET_PPCEMB + return pcc->mmu_model == POWERPC_MMU_BOOKE || + pcc->mmu_model == POWERPC_MMU_SOFT_4xx || + pcc->mmu_model == POWERPC_MMU_SOFT_4xx_Z; +#else + return true; +#endif +} + static void ppc_cpu_realizefn(DeviceState *dev, Error **errp) { CPUState *cs = CPU(dev); @@ -7991,8 +8002,8 @@ static void ppc_cpu_realizefn(DeviceState *dev, Error **errp) } #if defined(TARGET_PPCEMB) - if (pcc->mmu_model != POWERPC_MMU_BOOKE) { - error_setg(errp, "CPU does not possess a BookE MMU. " + if (!ppc_cpu_is_valid(pcc)) { + error_setg(errp, "CPU does not possess a BookE or 4xx MMU. " "Please use qemu-system-ppc or qemu-system-ppc64 instead " "or choose another CPU model."); return; @@ -8209,11 +8220,9 @@ static gint ppc_cpu_compare_class_pvr(gconstpointer a, gconstpointer b) return -1; } -#if defined(TARGET_PPCEMB) - if (pcc->mmu_model != POWERPC_MMU_BOOKE) { + if (!ppc_cpu_is_valid(pcc)) { return -1; } -#endif return pcc->pvr == pvr ? 0 : -1; } @@ -8246,11 +8255,10 @@ static gint ppc_cpu_compare_class_pvr_mask(gconstpointer a, gconstpointer b) return -1; } -#if defined(TARGET_PPCEMB) - if (pcc->mmu_model != POWERPC_MMU_BOOKE) { + if (!ppc_cpu_is_valid(pcc)) { return -1; } -#endif + ret = (((pcc->pvr & pcc->pvr_mask) == (pvr & pcc->pvr_mask)) ? 0 : -1); return ret; @@ -8275,14 +8283,10 @@ static gint ppc_cpu_compare_class_name(gconstpointer a, gconstpointer b) { ObjectClass *oc = (ObjectClass *)a; const char *name = b; -#if defined(TARGET_PPCEMB) PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc); -#endif if (strncasecmp(name, object_class_get_name(oc), strlen(name)) == 0 && -#if defined(TARGET_PPCEMB) - pcc->mmu_model == POWERPC_MMU_BOOKE && -#endif + ppc_cpu_is_valid(pcc) && strcmp(object_class_get_name(oc) + strlen(name), "-" TYPE_POWERPC_CPU) == 0) { return 0; @@ -8414,11 +8418,9 @@ static void ppc_cpu_list_entry(gpointer data, gpointer user_data) char *name; int i; -#if defined(TARGET_PPCEMB) - if (pcc->mmu_model != POWERPC_MMU_BOOKE) { + if (!ppc_cpu_is_valid(pcc)) { return; } -#endif if (unlikely(strcmp(typename, TYPE_HOST_POWERPC_CPU) == 0)) { return; } @@ -8466,13 +8468,11 @@ static void ppc_cpu_defs_entry(gpointer data, gpointer user_data) const char *typename; CpuDefinitionInfoList *entry; CpuDefinitionInfo *info; -#if defined(TARGET_PPCEMB) PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc); - if (pcc->mmu_model != POWERPC_MMU_BOOKE) { + if (!ppc_cpu_is_valid(pcc)) { return; } -#endif typename = object_class_get_name(oc); info = g_malloc0(sizeof(*info)); diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c index 82658a170c..c8884b31f4 100644 --- a/tcg/arm/tcg-target.c +++ b/tcg/arm/tcg-target.c @@ -1866,7 +1866,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, SHIFT_IMM_ROR((0x20 - args[2]) & 0x1f) : SHIFT_IMM_LSL(0)); } else { - tcg_out_dat_imm(s, COND_AL, ARITH_RSB, TCG_REG_TMP, args[1], 0x20); + tcg_out_dat_imm(s, COND_AL, ARITH_RSB, TCG_REG_TMP, args[2], 0x20); tcg_out_dat_reg(s, COND_AL, ARITH_MOV, args[0], 0, args[1], SHIFT_REG_ROR(TCG_REG_TMP)); } diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c index 5d4cf9386e..f832282d1a 100644 --- a/tcg/i386/tcg-target.c +++ b/tcg/i386/tcg-target.c @@ -88,6 +88,11 @@ static const int tcg_target_call_oarg_regs[] = { #endif }; +/* Constants we accept. */ +#define TCG_CT_CONST_S32 0x100 +#define TCG_CT_CONST_U32 0x200 +#define TCG_CT_CONST_I32 0x400 + /* Registers used with L constraint, which are the first argument registers on x86_64, and two random call clobbered registers on i386. */ @@ -110,7 +115,7 @@ static const int tcg_target_call_oarg_regs[] = { is available. */ #if TCG_TARGET_REG_BITS == 64 # define have_cmov 1 -#elif defined(CONFIG_CPUID_H) +#elif defined(CONFIG_CPUID_H) && defined(bit_CMOV) static bool have_cmov; #else # define have_cmov 0 @@ -124,6 +129,16 @@ static bool have_movbe; # define have_movbe 0 #endif +/* We need this symbol in tcg-target.h, and we can't properly conditionalize + it there. Therefore we always define the variable. */ +bool have_bmi1; + +#if defined(CONFIG_CPUID_H) && defined(bit_BMI2) +static bool have_bmi2; +#else +# define have_bmi2 0 +#endif + static uint8_t *tb_ret_addr; static void patch_reloc(uint8_t *code_ptr, int type, @@ -166,6 +181,7 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) tcg_regset_set_reg(ct->u.regs, TCG_REG_EBX); break; case 'c': + case_c: ct->ct |= TCG_CT_REG; tcg_regset_set_reg(ct->u.regs, TCG_REG_ECX); break; @@ -194,6 +210,7 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) tcg_regset_set32(ct->u.regs, 0, 0xf); break; case 'r': + case_r: ct->ct |= TCG_CT_REG; if (TCG_TARGET_REG_BITS == 64) { tcg_regset_set32(ct->u.regs, 0, 0xffff); @@ -201,6 +218,13 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) tcg_regset_set32(ct->u.regs, 0, 0xff); } break; + case 'C': + /* With SHRX et al, we need not use ECX as shift count register. */ + if (have_bmi2) { + goto case_r; + } else { + goto case_c; + } /* qemu_ld/st address constraint */ case 'L': @@ -220,6 +244,9 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) case 'Z': ct->ct |= TCG_CT_CONST_U32; break; + case 'I': + ct->ct |= TCG_CT_CONST_I32; + break; default: return -1; @@ -243,6 +270,9 @@ static inline int tcg_target_const_match(tcg_target_long val, if ((ct & TCG_CT_CONST_U32) && val == (uint32_t)val) { return 1; } + if ((ct & TCG_CT_CONST_I32) && ~val == (int32_t)~val) { + return 1; + } return 0; } @@ -268,10 +298,13 @@ static inline int tcg_target_const_match(tcg_target_long val, # define P_REXB_RM 0 # define P_GS 0 #endif +#define P_SIMDF3 0x10000 /* 0xf3 opcode prefix */ +#define P_SIMDF2 0x20000 /* 0xf2 opcode prefix */ #define OPC_ARITH_EvIz (0x81) #define OPC_ARITH_EvIb (0x83) #define OPC_ARITH_GvEv (0x03) /* ... plus (ARITH_FOO << 3) */ +#define OPC_ANDN (0xf2 | P_EXT38) #define OPC_ADD_GvEv (OPC_ARITH_GvEv | (ARITH_ADD << 3)) #define OPC_BSWAP (0xc8 | P_EXT) #define OPC_CALL_Jz (0xe8) @@ -309,6 +342,9 @@ static inline int tcg_target_const_match(tcg_target_long val, #define OPC_SHIFT_1 (0xd1) #define OPC_SHIFT_Ib (0xc1) #define OPC_SHIFT_cl (0xd3) +#define OPC_SARX (0xf7 | P_EXT38 | P_SIMDF3) +#define OPC_SHLX (0xf7 | P_EXT38 | P_DATA16) +#define OPC_SHRX (0xf7 | P_EXT38 | P_SIMDF2) #define OPC_TESTL (0x85) #define OPC_XCHG_ax_r32 (0x90) @@ -398,9 +434,9 @@ static void tcg_out_opc(TCGContext *s, int opc, int r, int rm, int x) rex = 0; rex |= (opc & P_REXW) ? 0x8 : 0x0; /* REX.W */ - rex |= (r & 8) >> 1; /* REX.R */ - rex |= (x & 8) >> 2; /* REX.X */ - rex |= (rm & 8) >> 3; /* REX.B */ + rex |= (r & 8) >> 1; /* REX.R */ + rex |= (x & 8) >> 2; /* REX.X */ + rex |= (rm & 8) >> 3; /* REX.B */ /* P_REXB_{R,RM} indicates that the given register is the low byte. For %[abcd]l we need no REX prefix, but for %{si,di,bp,sp}l we do, @@ -449,6 +485,48 @@ static void tcg_out_modrm(TCGContext *s, int opc, int r, int rm) tcg_out8(s, 0xc0 | (LOWREGMASK(r) << 3) | LOWREGMASK(rm)); } +static void tcg_out_vex_modrm(TCGContext *s, int opc, int r, int v, int rm) +{ + int tmp; + + if ((opc & (P_REXW | P_EXT | P_EXT38)) || (rm & 8)) { + /* Three byte VEX prefix. */ + tcg_out8(s, 0xc4); + + /* VEX.m-mmmm */ + if (opc & P_EXT38) { + tmp = 2; + } else if (opc & P_EXT) { + tmp = 1; + } else { + tcg_abort(); + } + tmp |= 0x40; /* VEX.X */ + tmp |= (r & 8 ? 0 : 0x80); /* VEX.R */ + tmp |= (rm & 8 ? 0 : 0x20); /* VEX.B */ + tcg_out8(s, tmp); + + tmp = (opc & P_REXW ? 0x80 : 0); /* VEX.W */ + } else { + /* Two byte VEX prefix. */ + tcg_out8(s, 0xc5); + + tmp = (r & 8 ? 0 : 0x80); /* VEX.R */ + } + /* VEX.pp */ + if (opc & P_DATA16) { + tmp |= 1; /* 0x66 */ + } else if (opc & P_SIMDF3) { + tmp |= 2; /* 0xf3 */ + } else if (opc & P_SIMDF2) { + tmp |= 3; /* 0xf2 */ + } + tmp |= (~v & 15) << 3; /* VEX.vvvv */ + tcg_out8(s, tmp); + tcg_out8(s, opc); + tcg_out8(s, 0xc0 | (LOWREGMASK(r) << 3) | LOWREGMASK(rm)); +} + /* Output an opcode with a full "rm + (index<<shift) + offset" address mode. We handle either RM and INDEX missing with a negative value. In 64-bit mode for absolute addresses, ~RM is the size of the immediate operand @@ -1638,7 +1716,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is64) static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args, const int *const_args) { - int c, rexw = 0; + int c, vexop, rexw = 0; #if TCG_TARGET_REG_BITS == 64 # define OP_32_64(x) \ @@ -1774,6 +1852,16 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, } break; + OP_32_64(andc): + if (const_args[2]) { + tcg_out_mov(s, rexw ? TCG_TYPE_I64 : TCG_TYPE_I32, + args[0], args[1]); + tgen_arithi(s, ARITH_AND + rexw, args[0], ~args[2], 0); + } else { + tcg_out_vex_modrm(s, OPC_ANDN + rexw, args[0], args[2], args[1]); + } + break; + OP_32_64(mul): if (const_args[2]) { int32_t val; @@ -1799,19 +1887,28 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, OP_32_64(shl): c = SHIFT_SHL; - goto gen_shift; + vexop = OPC_SHLX; + goto gen_shift_maybe_vex; OP_32_64(shr): c = SHIFT_SHR; - goto gen_shift; + vexop = OPC_SHRX; + goto gen_shift_maybe_vex; OP_32_64(sar): c = SHIFT_SAR; - goto gen_shift; + vexop = OPC_SARX; + goto gen_shift_maybe_vex; OP_32_64(rotl): c = SHIFT_ROL; goto gen_shift; OP_32_64(rotr): c = SHIFT_ROR; goto gen_shift; + gen_shift_maybe_vex: + if (have_bmi2 && !const_args[2]) { + tcg_out_vex_modrm(s, vexop + rexw, args[0], args[2], args[1]); + break; + } + /* FALLTHRU */ gen_shift: if (const_args[2]) { tcg_out_shifti(s, c + rexw, args[0], args[2]); @@ -2002,10 +2099,11 @@ static const TCGTargetOpDef x86_op_defs[] = { { INDEX_op_and_i32, { "r", "0", "ri" } }, { INDEX_op_or_i32, { "r", "0", "ri" } }, { INDEX_op_xor_i32, { "r", "0", "ri" } }, + { INDEX_op_andc_i32, { "r", "r", "ri" } }, - { INDEX_op_shl_i32, { "r", "0", "ci" } }, - { INDEX_op_shr_i32, { "r", "0", "ci" } }, - { INDEX_op_sar_i32, { "r", "0", "ci" } }, + { INDEX_op_shl_i32, { "r", "0", "Ci" } }, + { INDEX_op_shr_i32, { "r", "0", "Ci" } }, + { INDEX_op_sar_i32, { "r", "0", "Ci" } }, { INDEX_op_rotl_i32, { "r", "0", "ci" } }, { INDEX_op_rotr_i32, { "r", "0", "ci" } }, @@ -2059,10 +2157,11 @@ static const TCGTargetOpDef x86_op_defs[] = { { INDEX_op_and_i64, { "r", "0", "reZ" } }, { INDEX_op_or_i64, { "r", "0", "re" } }, { INDEX_op_xor_i64, { "r", "0", "re" } }, + { INDEX_op_andc_i64, { "r", "r", "rI" } }, - { INDEX_op_shl_i64, { "r", "0", "ci" } }, - { INDEX_op_shr_i64, { "r", "0", "ci" } }, - { INDEX_op_sar_i64, { "r", "0", "ci" } }, + { INDEX_op_shl_i64, { "r", "0", "Ci" } }, + { INDEX_op_shr_i64, { "r", "0", "Ci" } }, + { INDEX_op_sar_i64, { "r", "0", "Ci" } }, { INDEX_op_rotl_i64, { "r", "0", "ci" } }, { INDEX_op_rotr_i64, { "r", "0", "ci" } }, @@ -2196,23 +2295,34 @@ static void tcg_target_qemu_prologue(TCGContext *s) static void tcg_target_init(TCGContext *s) { -#if !(defined(have_cmov) && defined(have_movbe)) - { - unsigned a, b, c, d; - int ret = __get_cpuid(1, &a, &b, &c, &d); +#ifdef CONFIG_CPUID_H + unsigned a, b, c, d; + int max = __get_cpuid_max(0, 0); -# ifndef have_cmov + if (max >= 1) { + __cpuid(1, a, b, c, d); +#ifndef have_cmov /* For 32-bit, 99% certainty that we're running on hardware that supports cmov, but we still need to check. In case cmov is not available, we'll use a small forward branch. */ - have_cmov = ret && (d & bit_CMOV); -# endif - -# ifndef have_movbe + have_cmov = (d & bit_CMOV) != 0; +#endif +#ifndef have_movbe /* MOVBE is only available on Intel Atom and Haswell CPUs, so we need to probe for it. */ - have_movbe = ret && (c & bit_MOVBE); -# endif + have_movbe = (c & bit_MOVBE) != 0; +#endif + } + + if (max >= 7) { + /* BMI1 is available on AMD Piledriver and Intel Haswell CPUs. */ + __cpuid_count(7, 0, a, b, c, d); +#ifdef bit_BMI + have_bmi1 = (b & bit_BMI) != 0; +#endif +#ifndef have_bmi2 + have_bmi2 = (b & bit_BMI2) != 0; +#endif } #endif diff --git a/tcg/i386/tcg-target.h b/tcg/i386/tcg-target.h index 92c0fcd36d..bdf2222452 100644 --- a/tcg/i386/tcg-target.h +++ b/tcg/i386/tcg-target.h @@ -64,9 +64,6 @@ typedef enum { TCG_REG_RDI = TCG_REG_EDI, } TCGReg; -#define TCG_CT_CONST_S32 0x100 -#define TCG_CT_CONST_U32 0x200 - /* used for function call generation */ #define TCG_REG_CALL_STACK TCG_REG_ESP #define TCG_TARGET_STACK_ALIGN 16 @@ -76,6 +73,8 @@ typedef enum { #define TCG_TARGET_CALL_STACK_OFFSET 0 #endif +extern bool have_bmi1; + /* optional instructions */ #define TCG_TARGET_HAS_div2_i32 1 #define TCG_TARGET_HAS_rot_i32 1 @@ -87,7 +86,7 @@ typedef enum { #define TCG_TARGET_HAS_bswap32_i32 1 #define TCG_TARGET_HAS_neg_i32 1 #define TCG_TARGET_HAS_not_i32 1 -#define TCG_TARGET_HAS_andc_i32 0 +#define TCG_TARGET_HAS_andc_i32 have_bmi1 #define TCG_TARGET_HAS_orc_i32 0 #define TCG_TARGET_HAS_eqv_i32 0 #define TCG_TARGET_HAS_nand_i32 0 @@ -115,7 +114,7 @@ typedef enum { #define TCG_TARGET_HAS_bswap64_i64 1 #define TCG_TARGET_HAS_neg_i64 1 #define TCG_TARGET_HAS_not_i64 1 -#define TCG_TARGET_HAS_andc_i64 0 +#define TCG_TARGET_HAS_andc_i64 have_bmi1 #define TCG_TARGET_HAS_orc_i64 0 #define TCG_TARGET_HAS_eqv_i64 0 #define TCG_TARGET_HAS_nand_i64 0 diff --git a/tcg/optimize.c b/tcg/optimize.c index 89e2d6a3b3..7777743e88 100644 --- a/tcg/optimize.c +++ b/tcg/optimize.c @@ -655,11 +655,68 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, } } break; + CASE_OP_32_64(xor): + CASE_OP_32_64(nand): + if (temps[args[1]].state != TCG_TEMP_CONST + && temps[args[2]].state == TCG_TEMP_CONST + && temps[args[2]].val == -1) { + i = 1; + goto try_not; + } + break; + CASE_OP_32_64(nor): + if (temps[args[1]].state != TCG_TEMP_CONST + && temps[args[2]].state == TCG_TEMP_CONST + && temps[args[2]].val == 0) { + i = 1; + goto try_not; + } + break; + CASE_OP_32_64(andc): + if (temps[args[2]].state != TCG_TEMP_CONST + && temps[args[1]].state == TCG_TEMP_CONST + && temps[args[1]].val == -1) { + i = 2; + goto try_not; + } + break; + CASE_OP_32_64(orc): + CASE_OP_32_64(eqv): + if (temps[args[2]].state != TCG_TEMP_CONST + && temps[args[1]].state == TCG_TEMP_CONST + && temps[args[1]].val == 0) { + i = 2; + goto try_not; + } + break; + try_not: + { + TCGOpcode not_op; + bool have_not; + + if (def->flags & TCG_OPF_64BIT) { + not_op = INDEX_op_not_i64; + have_not = TCG_TARGET_HAS_not_i64; + } else { + not_op = INDEX_op_not_i32; + have_not = TCG_TARGET_HAS_not_i32; + } + if (!have_not) { + break; + } + s->gen_opc_buf[op_index] = not_op; + reset_temp(args[0]); + gen_args[0] = args[0]; + gen_args[1] = args[i]; + args += 3; + gen_args += 2; + continue; + } default: break; } - /* Simplify expression for "op r, a, 0 => mov r, a" cases */ + /* Simplify expression for "op r, a, const => mov r, a" cases */ switch (op) { CASE_OP_32_64(add): CASE_OP_32_64(sub): @@ -670,28 +727,38 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, CASE_OP_32_64(rotr): CASE_OP_32_64(or): CASE_OP_32_64(xor): - if (temps[args[1]].state == TCG_TEMP_CONST) { - /* Proceed with possible constant folding. */ - break; - } - if (temps[args[2]].state == TCG_TEMP_CONST + CASE_OP_32_64(andc): + if (temps[args[1]].state != TCG_TEMP_CONST + && temps[args[2]].state == TCG_TEMP_CONST && temps[args[2]].val == 0) { - if (temps_are_copies(args[0], args[1])) { - s->gen_opc_buf[op_index] = INDEX_op_nop; - } else { - s->gen_opc_buf[op_index] = op_to_mov(op); - tcg_opt_gen_mov(s, gen_args, args[0], args[1]); - gen_args += 2; - } - args += 3; - continue; + goto do_mov3; + } + break; + CASE_OP_32_64(and): + CASE_OP_32_64(orc): + CASE_OP_32_64(eqv): + if (temps[args[1]].state != TCG_TEMP_CONST + && temps[args[2]].state == TCG_TEMP_CONST + && temps[args[2]].val == -1) { + goto do_mov3; } break; + do_mov3: + if (temps_are_copies(args[0], args[1])) { + s->gen_opc_buf[op_index] = INDEX_op_nop; + } else { + s->gen_opc_buf[op_index] = op_to_mov(op); + tcg_opt_gen_mov(s, gen_args, args[0], args[1]); + gen_args += 2; + } + args += 3; + continue; default: break; } - /* Simplify using known-zero bits */ + /* Simplify using known-zero bits. Currently only ops with a single + output argument is supported. */ mask = -1; affected = -1; switch (op) { @@ -726,16 +793,36 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, mask = temps[args[1]].mask & mask; break; - CASE_OP_32_64(sar): + CASE_OP_32_64(andc): + /* Known-zeros does not imply known-ones. Therefore unless + args[2] is constant, we can't infer anything from it. */ if (temps[args[2]].state == TCG_TEMP_CONST) { - mask = ((tcg_target_long)temps[args[1]].mask - >> temps[args[2]].val); + mask = ~temps[args[2]].mask; + goto and_const; } + /* But we certainly know nothing outside args[1] may be set. */ + mask = temps[args[1]].mask; break; - CASE_OP_32_64(shr): + case INDEX_op_sar_i32: if (temps[args[2]].state == TCG_TEMP_CONST) { - mask = temps[args[1]].mask >> temps[args[2]].val; + mask = (int32_t)temps[args[1]].mask >> temps[args[2]].val; + } + break; + case INDEX_op_sar_i64: + if (temps[args[2]].state == TCG_TEMP_CONST) { + mask = (int64_t)temps[args[1]].mask >> temps[args[2]].val; + } + break; + + case INDEX_op_shr_i32: + if (temps[args[2]].state == TCG_TEMP_CONST) { + mask = (uint32_t)temps[args[1]].mask >> temps[args[2]].val; + } + break; + case INDEX_op_shr_i64: + if (temps[args[2]].state == TCG_TEMP_CONST) { + mask = (uint64_t)temps[args[1]].mask >> temps[args[2]].val; } break; @@ -769,10 +856,40 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, mask = temps[args[3]].mask | temps[args[4]].mask; break; + CASE_OP_32_64(ld8u): + case INDEX_op_qemu_ld8u: + mask = 0xff; + break; + CASE_OP_32_64(ld16u): + case INDEX_op_qemu_ld16u: + mask = 0xffff; + break; + case INDEX_op_ld32u_i64: +#if TCG_TARGET_REG_BITS == 64 + case INDEX_op_qemu_ld32u: +#endif + mask = 0xffffffffu; + break; + + CASE_OP_32_64(qemu_ld): + { + TCGMemOp mop = args[def->nb_oargs + def->nb_iargs]; + if (!(mop & MO_SIGN)) { + mask = (2ULL << ((8 << (mop & MO_SIZE)) - 1)) - 1; + } + } + break; + default: break; } + /* 32-bit ops (non 64-bit ops and non load/store ops) generate 32-bit + results */ + if (!(def->flags & (TCG_OPF_CALL_CLOBBER | TCG_OPF_64BIT))) { + mask &= 0xffffffffu; + } + if (mask == 0) { assert(def->nb_oargs == 1); s->gen_opc_buf[op_index] = op_to_movi(op); @@ -839,6 +956,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, /* Simplify expression for "op r, a, a => movi r, 0" cases */ switch (op) { + CASE_OP_32_64(andc): CASE_OP_32_64(sub): CASE_OP_32_64(xor): if (temps_are_copies(args[1], args[2])) { @@ -1140,6 +1258,11 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, } else { for (i = 0; i < def->nb_oargs; i++) { reset_temp(args[i]); + /* Save the corresponding known-zero bits mask for the + first output argument (only one supported so far). */ + if (i == 0) { + temps[args[i]].mask = mask; + } } } for (i = 0; i < def->nb_args; i++) { @@ -526,7 +526,7 @@ static inline int tcg_temp_new_internal(TCGType type, int temp_local) ts->temp_local = temp_local; ts->name = NULL; ts++; - ts->base_type = TCG_TYPE_I32; + ts->base_type = type; ts->type = TCG_TYPE_I32; ts->temp_allocated = 1; ts->temp_local = temp_local; diff --git a/tests/Makefile b/tests/Makefile index 9a7d2f1008..b17d41e4e2 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,5 +1,9 @@ export SRC_PATH +# Get the list of all supported sysemu targets +SYSEMU_TARGET_LIST := $(subst -softmmu.mak,,$(notdir \ + $(wildcard $(SRC_PATH)/default-configs/*-softmmu.mak))) + check-unit-y = tests/check-qdict$(EXESUF) gcov-files-check-qdict-y = qobject/qdict.c check-unit-y += tests/check-qfloat$(EXESUF) @@ -60,64 +64,78 @@ check-block-$(CONFIG_POSIX) += tests/qemu-iotests-quick.sh # All QTests for now are POSIX-only, but the dependencies are # really in libqtest, not in the testcases themselves. + +gcov-files-ipack-y += hw/ipack/ipack.c +check-qtest-ipack-y += tests/ipoctal232-test$(EXESUF) +gcov-files-ipack-y += hw/char/ipoctal232.c + +gcov-files-virtio-y += i386-softmmu/hw/virtio/virtio.c +check-qtest-virtio-y += tests/virtio-net-test$(EXESUF) +gcov-files-virtio-y += i386-softmmu/hw/net/virtio-net.c + +check-qtest-pci-y += tests/e1000-test$(EXESUF) +gcov-files-pci-y += hw/net/e1000.c +check-qtest-pci-y += tests/rtl8139-test$(EXESUF) +gcov-files-pci-y += hw/net/rtl8139.c +check-qtest-pci-y += tests/pcnet-test$(EXESUF) +gcov-files-pci-y += hw/net/pcnet.c +gcov-files-pci-y += hw/net/pcnet-pci.c +check-qtest-pci-y += tests/eepro100-test$(EXESUF) +gcov-files-pci-y += hw/net/eepro100.c +check-qtest-pci-y += tests/ne2000-test$(EXESUF) +gcov-files-pci-y += hw/net/ne2000.c +check-qtest-pci-y += $(check-qtest-virtio-y) +gcov-files-pci-y += $(gcov-files-virtio-y) hw/virtio/virtio-pci.c +check-qtest-pci-y += tests/tpci200-test$(EXESUF) +gcov-files-pci-y += hw/char/tpci200.c +check-qtest-pci-y += $(check-qtest-ipack-y) +gcov-files-pci-y += $(gcov-files-ipack-y) hw/ipack/tpci200.c + check-qtest-i386-y = tests/endianness-test$(EXESUF) check-qtest-i386-y += tests/fdc-test$(EXESUF) -gcov-files-i386-y = hw/fdc.c +gcov-files-i386-y = hw/block/fdc.c check-qtest-i386-y += tests/ide-test$(EXESUF) check-qtest-i386-y += tests/hd-geo-test$(EXESUF) -gcov-files-i386-y += hw/hd-geometry.c +gcov-files-i386-y += hw/block/hd-geometry.c check-qtest-i386-y += tests/boot-order-test$(EXESUF) check-qtest-i386-y += tests/acpi-test$(EXESUF) check-qtest-i386-y += tests/rtc-test$(EXESUF) check-qtest-i386-y += tests/i440fx-test$(EXESUF) check-qtest-i386-y += tests/fw_cfg-test$(EXESUF) -check-qtest-i386-y += tests/qom-test$(EXESUF) check-qtest-i386-y += tests/blockdev-test$(EXESUF) check-qtest-i386-y += tests/qdev-monitor-test$(EXESUF) +check-qtest-i386-y += $(check-qtest-pci-y) +gcov-files-i386-y += $(gcov-files-pci-y) +check-qtest-i386-y += tests/vmxnet3-test$(EXESUF) +gcov-files-i386-y += hw/net/vmxnet3.c +gcov-files-i386-y += hw/net/vmxnet_rx_pkt.c +gcov-files-i386-y += hw/net/vmxnet_tx_pkt.c check-qtest-x86_64-y = $(check-qtest-i386-y) -gcov-files-i386-y += i386-softmmu/hw/mc146818rtc.c +gcov-files-i386-y += i386-softmmu/hw/timer/mc146818rtc.c gcov-files-x86_64-y = $(subst i386-softmmu/,x86_64-softmmu/,$(gcov-files-i386-y)) check-qtest-mips-y = tests/endianness-test$(EXESUF) check-qtest-mips64-y = tests/endianness-test$(EXESUF) check-qtest-mips64el-y = tests/endianness-test$(EXESUF) -check-qtest-mips-y += tests/qom-test$(EXESUF) -check-qtest-mipsel-y += tests/qom-test$(EXESUF) -check-qtest-mips64-y += tests/qom-test$(EXESUF) -check-qtest-mips64el-y += tests/qom-test$(EXESUF) check-qtest-ppc-y = tests/endianness-test$(EXESUF) check-qtest-ppc64-y = tests/endianness-test$(EXESUF) check-qtest-sh4-y = tests/endianness-test$(EXESUF) check-qtest-sh4eb-y = tests/endianness-test$(EXESUF) -check-qtest-sh4-y += tests/qom-test$(EXESUF) -check-qtest-sh4eb-y += tests/qom-test$(EXESUF) check-qtest-sparc64-y = tests/endianness-test$(EXESUF) #check-qtest-sparc-y = tests/m48t59-test$(EXESUF) #check-qtest-sparc64-y += tests/m48t59-test$(EXESUF) -gcov-files-sparc-y += hw/m48t59.c -gcov-files-sparc64-y += hw/m48t59.c -check-qtest-sparc-y += tests/qom-test$(EXESUF) -check-qtest-sparc64-y += tests/qom-test$(EXESUF) +gcov-files-sparc-y += hw/timer/m48t59.c +gcov-files-sparc64-y += hw/timer/m48t59.c check-qtest-arm-y = tests/tmp105-test$(EXESUF) -gcov-files-arm-y += hw/tmp105.c -check-qtest-arm-y += tests/qom-test$(EXESUF) +gcov-files-arm-y += hw/misc/tmp105.c check-qtest-ppc-y += tests/boot-order-test$(EXESUF) check-qtest-ppc64-y += tests/boot-order-test$(EXESUF) -check-qtest-ppc-y += tests/qom-test$(EXESUF) -check-qtest-ppc64-y += tests/qom-test$(EXESUF) -check-qtest-ppcemb-y += tests/qom-test$(EXESUF) -check-qtest-alpha-y += tests/qom-test$(EXESUF) -check-qtest-cris-y += tests/qom-test$(EXESUF) -check-qtest-lm32-y += tests/qom-test$(EXESUF) -check-qtest-m68k-y += tests/qom-test$(EXESUF) -check-qtest-microblaze-y += tests/qom-test$(EXESUF) check-qtest-microblazeel-y = $(check-qtest-microblaze-y) -check-qtest-moxie-y += tests/qom-test$(EXESUF) -check-qtest-or32-y += tests/qom-test$(EXESUF) -check-qtest-s390x-y += tests/qom-test$(EXESUF) -check-qtest-unicore32-y += tests/qom-test$(EXESUF) -check-qtest-xtensa-y += tests/qom-test$(EXESUF) check-qtest-xtensaeb-y = $(check-qtest-xtensa-y) +# qom-test works for all sysemu architectures: +$(foreach target,$(SYSEMU_TARGET_LIST), \ + $(eval check-qtest-$(target)-y += tests/qom-test$(EXESUF))) + check-qapi-schema-y := $(addprefix tests/qapi-schema/, \ comments.json empty.json funny-char.json indented-expr.json \ missing-colon.json missing-comma-list.json \ @@ -211,6 +229,15 @@ tests/acpi-test$(EXESUF): tests/acpi-test.o $(libqos-obj-y) tests/tmp105-test$(EXESUF): tests/tmp105-test.o $(libqos-omap-obj-y) tests/i440fx-test$(EXESUF): tests/i440fx-test.o $(libqos-pc-obj-y) tests/fw_cfg-test$(EXESUF): tests/fw_cfg-test.o $(libqos-pc-obj-y) +tests/e1000-test$(EXESUF): tests/e1000-test.o +tests/rtl8139-test$(EXESUF): tests/rtl8139-test.o +tests/pcnet-test$(EXESUF): tests/pcnet-test.o +tests/eepro100-test$(EXESUF): tests/eepro100-test.o +tests/vmxnet3-test$(EXESUF): tests/vmxnet3-test.o +tests/ne2000-test$(EXESUF): tests/ne2000-test.o +tests/virtio-net-test$(EXESUF): tests/virtio-net-test.o +tests/tpci200-test$(EXESUF): tests/tpci200-test.o +tests/ipoctal232-test$(EXESUF): tests/ipoctal232-test.o tests/qom-test$(EXESUF): tests/qom-test.o tests/blockdev-test$(EXESUF): tests/blockdev-test.o $(libqos-pc-obj-y) tests/qdev-monitor-test$(EXESUF): tests/qdev-monitor-test.o $(libqos-pc-obj-y) diff --git a/tests/e1000-test.c b/tests/e1000-test.c new file mode 100644 index 0000000000..a8ba2fc0a8 --- /dev/null +++ b/tests/e1000-test.c @@ -0,0 +1,33 @@ +/* + * QTest testcase for e1000 NIC + * + * Copyright (c) 2013-2014 SUSE LINUX Products GmbH + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include <glib.h> +#include <string.h> +#include "libqtest.h" +#include "qemu/osdep.h" + +/* Tests only initialization so far. TODO: Replace with functional tests */ +static void nop(void) +{ +} + +int main(int argc, char **argv) +{ + int ret; + + g_test_init(&argc, &argv, NULL); + qtest_add_func("/e1000/nop", nop); + + qtest_start("-device e1000"); + ret = g_test_run(); + + qtest_end(); + + return ret; +} diff --git a/tests/eepro100-test.c b/tests/eepro100-test.c new file mode 100644 index 0000000000..bf8252627e --- /dev/null +++ b/tests/eepro100-test.c @@ -0,0 +1,63 @@ +/* + * QTest testcase for eepro100 NIC + * + * Copyright (c) 2013-2014 SUSE LINUX Products GmbH + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include <glib.h> +#include <string.h> +#include "libqtest.h" +#include "qemu/osdep.h" + +static void test_device(gconstpointer data) +{ + const char *model = data; + QTestState *s; + char *args; + + args = g_strdup_printf("-device %s", model); + s = qtest_start(args); + + /* Tests only initialization so far. TODO: Implement functional tests */ + + if (s) { + qtest_quit(s); + } + g_free(args); +} + +static const char *models[] = { + "i82550", + "i82551", + "i82557a", + "i82557b", + "i82557c", + "i82558a", + "i82558b", + "i82559a", + "i82559b", + "i82559c", + "i82559er", + "i82562", + "i82801", +}; + +int main(int argc, char **argv) +{ + int i; + + g_test_init(&argc, &argv, NULL); + + for (i = 0; i < ARRAY_SIZE(models); i++) { + char *path; + + path = g_strdup_printf("/%s/eepro100/%s", + qtest_get_arch(), models[i]); + g_test_add_data_func(path, models[i], test_device); + } + + return g_test_run(); +} diff --git a/tests/endianness-test.c b/tests/endianness-test.c index 646df7d8da..92e17d251a 100644 --- a/tests/endianness-test.c +++ b/tests/endianness-test.c @@ -10,7 +10,6 @@ * See the COPYING file in the top-level directory. * */ -#include "libqtest.h" #include <glib.h> #include <stdio.h> @@ -18,6 +17,7 @@ #include <stdlib.h> #include <unistd.h> +#include "libqtest.h" #include "qemu/bswap.h" typedef struct TestCase TestCase; diff --git a/tests/fw_cfg-test.c b/tests/fw_cfg-test.c index e4f355ce3f..5c8f8d6c24 100644 --- a/tests/fw_cfg-test.c +++ b/tests/fw_cfg-test.c @@ -10,15 +10,14 @@ * See the COPYING file in the top-level directory. */ -#define NO_QEMU_PROTOS +#include <string.h> +#include <glib.h> #include "libqtest.h" +#define NO_QEMU_PROTOS #include "hw/nvram/fw_cfg.h" #include "libqos/fw_cfg.h" -#include <string.h> -#include <glib.h> - static uint64_t ram_size = 128 << 20; static uint16_t nb_cpus = 1; static uint16_t max_cpus = 1; diff --git a/tests/i440fx-test.c b/tests/i440fx-test.c index bcd2181aca..ad232b561c 100644 --- a/tests/i440fx-test.c +++ b/tests/i440fx-test.c @@ -12,12 +12,6 @@ * See the COPYING file in the top-level directory. */ -#include "libqos/pci.h" -#include "libqos/pci-pc.h" -#include "libqtest.h" - -#include "hw/pci/pci_regs.h" - #include <glib.h> #include <string.h> #include <stdio.h> @@ -26,6 +20,11 @@ #include <sys/mman.h> #include <stdlib.h> +#include "libqtest.h" +#include "libqos/pci.h" +#include "libqos/pci-pc.h" +#include "hw/pci/pci_regs.h" + #define BROKEN 1 #define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0])) diff --git a/tests/ipoctal232-test.c b/tests/ipoctal232-test.c new file mode 100644 index 0000000000..3ac1714b48 --- /dev/null +++ b/tests/ipoctal232-test.c @@ -0,0 +1,33 @@ +/* + * QTest testcase for IndustryPack Octal-RS232 + * + * Copyright (c) 2014 SUSE LINUX Products GmbH + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include <glib.h> +#include <string.h> +#include "libqtest.h" +#include "qemu/osdep.h" + +/* Tests only initialization so far. TODO: Replace with functional tests */ +static void nop(void) +{ +} + +int main(int argc, char **argv) +{ + int ret; + + g_test_init(&argc, &argv, NULL); + qtest_add_func("/ipoctal232/tpci200/nop", nop); + + qtest_start("-device tpci200,id=ipack0 -device ipoctal232,bus=ipack0.0"); + ret = g_test_run(); + + qtest_end(); + + return ret; +} diff --git a/tests/libqtest.c b/tests/libqtest.c index c9a4f89451..f587d36176 100644 --- a/tests/libqtest.c +++ b/tests/libqtest.c @@ -43,8 +43,8 @@ struct QTestState int qmp_fd; bool irq_level[MAX_IRQ]; GString *rx; - int child_pid; /* Child process created to execute QEMU */ - pid_t qemu_pid; /* QEMU process spawned by our child */ + pid_t qemu_pid; /* our child QEMU process */ + struct sigaction sigact_old; /* restored on exit */ }; #define g_assert_no_errno(ret) do { \ @@ -89,20 +89,17 @@ static int socket_accept(int sock) return ret; } -static pid_t read_pid_file(const char *pid_file) +static void kill_qemu(QTestState *s) { - FILE *f; - char buffer[1024]; - pid_t pid = -1; - - f = fopen(pid_file, "r"); - if (f) { - if (fgets(buffer, sizeof(buffer), f)) { - pid = atoi(buffer); - } - fclose(f); + if (s->qemu_pid != -1) { + kill(s->qemu_pid, SIGTERM); + waitpid(s->qemu_pid, NULL, 0); } - return pid; +} + +static void sigabrt_handler(int signo) +{ + kill_qemu(global_qtest); } QTestState *qtest_init(const char *extra_args) @@ -111,10 +108,9 @@ QTestState *qtest_init(const char *extra_args) int sock, qmpsock, i; gchar *socket_path; gchar *qmp_socket_path; - gchar *pid_file; gchar *command; const char *qemu_binary; - pid_t pid; + struct sigaction sigact; qemu_binary = getenv("QTEST_QEMU_BINARY"); g_assert(qemu_binary != NULL); @@ -123,22 +119,28 @@ QTestState *qtest_init(const char *extra_args) socket_path = g_strdup_printf("/tmp/qtest-%d.sock", getpid()); qmp_socket_path = g_strdup_printf("/tmp/qtest-%d.qmp", getpid()); - pid_file = g_strdup_printf("/tmp/qtest-%d.pid", getpid()); sock = init_socket(socket_path); qmpsock = init_socket(qmp_socket_path); - pid = fork(); - if (pid == 0) { - command = g_strdup_printf("%s " + /* Catch SIGABRT to clean up on g_assert() failure */ + sigact = (struct sigaction){ + .sa_handler = sigabrt_handler, + .sa_flags = SA_RESETHAND, + }; + sigemptyset(&sigact.sa_mask); + sigaction(SIGABRT, &sigact, &s->sigact_old); + + s->qemu_pid = fork(); + if (s->qemu_pid == 0) { + command = g_strdup_printf("exec %s " "-qtest unix:%s,nowait " "-qtest-log /dev/null " "-qmp unix:%s,nowait " - "-pidfile %s " "-machine accel=qtest " "-display none " "%s", qemu_binary, socket_path, - qmp_socket_path, pid_file, + qmp_socket_path, extra_args ?: ""); execlp("/bin/sh", "sh", "-c", command, NULL); exit(1); @@ -152,7 +154,6 @@ QTestState *qtest_init(const char *extra_args) g_free(qmp_socket_path); s->rx = g_string_new(""); - s->child_pid = pid; for (i = 0; i < MAX_IRQ; i++) { s->irq_level[i] = false; } @@ -161,10 +162,6 @@ QTestState *qtest_init(const char *extra_args) qtest_qmp_discard_response(s, ""); qtest_qmp_discard_response(s, "{ 'execute': 'qmp_capabilities' }"); - s->qemu_pid = read_pid_file(pid_file); - unlink(pid_file); - g_free(pid_file); - if (getenv("QTEST_STOP")) { kill(s->qemu_pid, SIGSTOP); } @@ -174,13 +171,9 @@ QTestState *qtest_init(const char *extra_args) void qtest_quit(QTestState *s) { - int status; - - if (s->qemu_pid != -1) { - kill(s->qemu_pid, SIGTERM); - waitpid(s->qemu_pid, &status, 0); - } + sigaction(SIGABRT, &s->sigact_old, NULL); + kill_qemu(s); close(s->fd); close(s->qmp_fd); g_string_free(s->rx, true); diff --git a/tests/m48t59-test.c b/tests/m48t59-test.c index 6abc4c8bf0..71b4f28052 100644 --- a/tests/m48t59-test.c +++ b/tests/m48t59-test.c @@ -11,7 +11,6 @@ * See the COPYING file in the top-level directory. * */ -#include "libqtest.h" #include <glib.h> #include <stdio.h> @@ -19,6 +18,8 @@ #include <stdlib.h> #include <unistd.h> +#include "libqtest.h" + #define RTC_SECONDS 0x9 #define RTC_MINUTES 0xa #define RTC_HOURS 0xb diff --git a/tests/ne2000-test.c b/tests/ne2000-test.c new file mode 100644 index 0000000000..61a678ad30 --- /dev/null +++ b/tests/ne2000-test.c @@ -0,0 +1,33 @@ +/* + * QTest testcase for ne2000 NIC + * + * Copyright (c) 2014 SUSE LINUX Products GmbH + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include <glib.h> +#include <string.h> +#include "libqtest.h" +#include "qemu/osdep.h" + +/* Tests only initialization so far. TODO: Replace with functional tests */ +static void pci_nop(void) +{ +} + +int main(int argc, char **argv) +{ + int ret; + + g_test_init(&argc, &argv, NULL); + qtest_add_func("/ne2000/pci/nop", pci_nop); + + qtest_start("-device ne2k_pci"); + ret = g_test_run(); + + qtest_end(); + + return ret; +} diff --git a/tests/pcnet-test.c b/tests/pcnet-test.c new file mode 100644 index 0000000000..84af4f327a --- /dev/null +++ b/tests/pcnet-test.c @@ -0,0 +1,33 @@ +/* + * QTest testcase for PC-Net NIC + * + * Copyright (c) 2013-2014 SUSE LINUX Products GmbH + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include <glib.h> +#include <string.h> +#include "libqtest.h" +#include "qemu/osdep.h" + +/* Tests only initialization so far. TODO: Replace with functional tests */ +static void pci_nop(void) +{ +} + +int main(int argc, char **argv) +{ + int ret; + + g_test_init(&argc, &argv, NULL); + qtest_add_func("/pcnet/pci/nop", pci_nop); + + qtest_start("-device pcnet"); + ret = g_test_run(); + + qtest_end(); + + return ret; +} diff --git a/tests/qom-test.c b/tests/qom-test.c index 5e5af7a50f..b6671fbec3 100644 --- a/tests/qom-test.c +++ b/tests/qom-test.c @@ -6,250 +6,94 @@ * 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 "libqtest.h" #include <glib.h> #include <string.h> + +#include "libqtest.h" #include "qemu/osdep.h" +#include "qapi/qmp/types.h" + +static const char *blacklist_x86[] = { + "xenfv", "xenpv", NULL +}; + +static const struct { + const char *arch; + const char **machine; +} blacklists[] = { + { "i386", blacklist_x86 }, + { "x86_64", blacklist_x86 }, +}; -static void test_nop(gconstpointer data) +static bool is_blacklisted(const char *arch, const char *mach) +{ + int i; + const char **p; + + for (i = 0; i < ARRAY_SIZE(blacklists); i++) { + if (!strcmp(blacklists[i].arch, arch)) { + for (p = blacklists[i].machine; *p; p++) { + if (!strcmp(*p, mach)) { + return true; + } + } + } + } + return false; +} + +static void test_machine(gconstpointer data) { - QTestState *s; const char *machine = data; char *args; + QDict *response; args = g_strdup_printf("-machine %s", machine); - s = qtest_start(args); - if (s) { - qtest_quit(s); - } + qtest_start(args); + response = qmp("{ 'execute': 'quit' }"); + g_assert(qdict_haskey(response, "return")); + qtest_end(); g_free(args); } -static const char *x86_machines[] = { - "pc", - "isapc", - "q35", -}; - -static const char *alpha_machines[] = { - "clipper", -}; - -static const char *arm_machines[] = { - "integratorcp", - "versatilepb", - "versatileab", - "lm3s811evb", - "lm3s6965evb", - "collie", - "akita", - "spitz", - "borzoi", - "terrier", - "tosa", - "cheetah", - "sx1-v1", - "sx1", - "realview-eb", - "realview-eb-mpcore", - "realview-pb-a8", - "realview-pbx-a9", - "musicpal", - "mainstone", - "connex", - "verdex", - "z2", - "n800", - "n810", - "kzm", - "vexpress-a9", - "vexpress-a15", - "smdkc210", - "nuri", - "xilinx-zynq-a9", - "highbank", - "midway", - "canon-a1100", - "cubieboard", -}; - -static const char *cris_machines[] = { - "axis-dev88", -}; - -static const char *lm32_machines[] = { - "lm32-evr", - "lm32-uclinux", - "milkymist", -}; - -static const char *m68k_machines[] = { - "mcf5208evb", - "an5206", - "dummy", -}; - -static const char *microblaze_machines[] = { - "petalogix-ml605", - "petalogix-s3adsp1800", -}; - -static const char *mips_machines[] = { - "malta", - "magnum", - "mips", - "mipssim", - "pica61", -}; - -static const char *moxie_machines[] = { - "moxiesim", -}; - -static const char *openrisc_machines[] = { - "or32-sim", -}; - -static const char *ppc_machines[] = { - "g3beige", - "mac99", - "prep", - "mpc8544ds", - "ppce500", -}; - -static const char *ppc64_machines[] = { - "pseries", -}; - -static const char *ppc405_machines[] = { - "ref405ep", - "taihu", -}; - -static const char *ppc440_machines[] = { - "bamboo", - "virtex-ml507", -}; - -static const char *s390_machines[] = { - "s390-virtio", - "s390-ccw-virtio", -}; - -static const char *superh_machines[] = { - "r2d", - "shix", -}; - -static const char *sparc_machines[] = { - "SS-4", - "SS-5", - "SS-10", - "SS-20", - "SS-600MP", - "LX", - "SPARCClassic", - "SPARCbook", - "leon3_generic", -}; - -static const char *sparc64_machines[] = { - "sun4u", - "sun4v", - "Niagara", -}; - -static const char *unicore32_machines[] = { - "puv3", -}; - -static const char *xtensa_machines[] = { - "sim", - "lx60", - "lx200", -}; - -static void add_test_cases(const char *arch, const char *machine) +static void add_machine_test_cases(void) { - char *path; - path = g_strdup_printf("/%s/qom/%s", arch, machine); - g_test_add_data_func(path, machine, test_nop); + const char *arch = qtest_get_arch(); + QDict *response, *minfo; + QList *list; + const QListEntry *p; + QObject *qobj; + QString *qstr; + const char *mname, *path; + + qtest_start("-machine none"); + response = qmp("{ 'execute': 'query-machines' }"); + g_assert(response); + list = qdict_get_qlist(response, "return"); + g_assert(list); + + for (p = qlist_first(list); p; p = qlist_next(p)) { + minfo = qobject_to_qdict(qlist_entry_obj(p)); + g_assert(minfo); + qobj = qdict_get(minfo, "name"); + g_assert(qobj); + qstr = qobject_to_qstring(qobj); + g_assert(qstr); + mname = qstring_get_str(qstr); + if (!is_blacklisted(arch, mname)) { + path = g_strdup_printf("/%s/qom/%s", arch, mname); + g_test_add_data_func(path, mname, test_machine); + } + } + qtest_end(); } -#define ADD_MACHINE_TESTS(arch, array) do { \ - int i; \ - for (i = 0; i < ARRAY_SIZE(array); i++) { \ - add_test_cases((arch), (array)[i]); \ - } \ -} while (false) - int main(int argc, char **argv) { - const char *arch = qtest_get_arch(); - g_test_init(&argc, &argv, NULL); - add_test_cases(arch, "none"); - - if (strcmp(arch, "i386") == 0 || - strcmp(arch, "x86_64") == 0) { - ADD_MACHINE_TESTS(arch, x86_machines); - } else if (strcmp(arch, "alpha") == 0) { - ADD_MACHINE_TESTS(arch, alpha_machines); - } else if (strcmp(arch, "arm") == 0) { - ADD_MACHINE_TESTS(arch, arm_machines); - } else if (strcmp(arch, "cris") == 0) { - ADD_MACHINE_TESTS(arch, cris_machines); - } else if (strcmp(arch, "lm32") == 0) { - ADD_MACHINE_TESTS(arch, lm32_machines); - } else if (strcmp(arch, "m68k") == 0) { - ADD_MACHINE_TESTS(arch, m68k_machines); - } else if (strcmp(arch, "microblaze") == 0 || - strcmp(arch, "microblazeel") == 0) { - ADD_MACHINE_TESTS(arch, microblaze_machines); - } else if (strcmp(arch, "mips") == 0 || - strcmp(arch, "mipsel") == 0 || - strcmp(arch, "mips64") == 0) { - ADD_MACHINE_TESTS(arch, mips_machines); - } else if (strcmp(arch, "mips64el") == 0) { - ADD_MACHINE_TESTS(arch, mips_machines); - add_test_cases(arch, "fulong2e"); - } else if (strcmp(arch, "moxie") == 0) { - ADD_MACHINE_TESTS(arch, moxie_machines); - } else if (strcmp(arch, "or32") == 0) { - ADD_MACHINE_TESTS(arch, openrisc_machines); - } else if (strcmp(arch, "ppcemb") == 0) { -#if 0 - /* XXX Available in ppcemb but don't work */ - ADD_MACHINE_TESTS(arch, ppc405_machines); -#endif - ADD_MACHINE_TESTS(arch, ppc440_machines); - } else if (strcmp(arch, "ppc") == 0) { - ADD_MACHINE_TESTS(arch, ppc405_machines); - ADD_MACHINE_TESTS(arch, ppc440_machines); - ADD_MACHINE_TESTS(arch, ppc_machines); - } else if (strcmp(arch, "ppc64") == 0) { - ADD_MACHINE_TESTS(arch, ppc405_machines); - ADD_MACHINE_TESTS(arch, ppc440_machines); - ADD_MACHINE_TESTS(arch, ppc_machines); - ADD_MACHINE_TESTS(arch, ppc64_machines); - } else if (strcmp(arch, "s390x") == 0) { - ADD_MACHINE_TESTS(arch, s390_machines); - } else if (strcmp(arch, "sh4") == 0 || - strcmp(arch, "sh4eb") == 0) { - ADD_MACHINE_TESTS(arch, superh_machines); - } else if (strcmp(arch, "sparc") == 0) { - ADD_MACHINE_TESTS(arch, sparc_machines); - } else if (strcmp(arch, "sparc64") == 0) { - ADD_MACHINE_TESTS(arch, sparc64_machines); - } else if (strcmp(arch, "unicore32") == 0) { - ADD_MACHINE_TESTS(arch, unicore32_machines); - } else if (strcmp(arch, "xtensa") == 0 || - strcmp(arch, "xtensaeb") == 0) { - ADD_MACHINE_TESTS(arch, xtensa_machines); - } + add_machine_test_cases(); return g_test_run(); } diff --git a/tests/rtc-test.c b/tests/rtc-test.c index f1b123fae1..4243624de6 100644 --- a/tests/rtc-test.c +++ b/tests/rtc-test.c @@ -10,8 +10,6 @@ * See the COPYING file in the top-level directory. * */ -#include "libqtest.h" -#include "hw/timer/mc146818rtc_regs.h" #include <glib.h> #include <stdio.h> @@ -19,6 +17,9 @@ #include <stdlib.h> #include <unistd.h> +#include "libqtest.h" +#include "hw/timer/mc146818rtc_regs.h" + static uint8_t base = 0x70; static int bcd2dec(int value) diff --git a/tests/rtl8139-test.c b/tests/rtl8139-test.c new file mode 100644 index 0000000000..f6a1be3fac --- /dev/null +++ b/tests/rtl8139-test.c @@ -0,0 +1,33 @@ +/* + * QTest testcase for Realtek 8139 NIC + * + * Copyright (c) 2013-2014 SUSE LINUX Products GmbH + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include <glib.h> +#include <string.h> +#include "libqtest.h" +#include "qemu/osdep.h" + +/* Tests only initialization so far. TODO: Replace with functional tests */ +static void nop(void) +{ +} + +int main(int argc, char **argv) +{ + int ret; + + g_test_init(&argc, &argv, NULL); + qtest_add_func("/rtl8139/nop", nop); + + qtest_start("-device rtl8139"); + ret = g_test_run(); + + qtest_end(); + + return ret; +} 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 79d815f888..22363d100f 100644 --- a/tests/test-string-output-visitor.c +++ b/tests/test-string-output-visitor.c @@ -26,7 +26,7 @@ typedef struct TestOutputVisitorData { static void visitor_output_setup(TestOutputVisitorData *data, const void *unused) { - data->sov = string_output_visitor_new(); + data->sov = string_output_visitor_new(false); g_assert(data->sov != NULL); data->ov = string_output_get_visitor(data->sov); @@ -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); } } diff --git a/tests/test-visitor-serialization.c b/tests/test-visitor-serialization.c index 9aaa5872e5..6bff950eb6 100644 --- a/tests/test-visitor-serialization.c +++ b/tests/test-visitor-serialization.c @@ -1083,7 +1083,7 @@ static void string_serialize(void *native_in, void **datap, { StringSerializeData *d = g_malloc0(sizeof(*d)); - d->sov = string_output_visitor_new(); + d->sov = string_output_visitor_new(false); visit(string_output_get_visitor(d->sov), &native_in, errp); *datap = d; } diff --git a/tests/tmp105-test.c b/tests/tmp105-test.c index 5ac48e2f5c..0834219e35 100644 --- a/tests/tmp105-test.c +++ b/tests/tmp105-test.c @@ -6,12 +6,13 @@ * This work is licensed under the terms of the GNU GPL, version 2 or later. * See the COPYING file in the top-level directory. */ + +#include <glib.h> + #include "libqtest.h" #include "libqos/i2c.h" #include "hw/misc/tmp105_regs.h" -#include <glib.h> - #define OMAP2_I2C_1_BASE 0x48070000 #define N8X0_ADDR 0x48 diff --git a/tests/tpci200-test.c b/tests/tpci200-test.c new file mode 100644 index 0000000000..9ae01277ee --- /dev/null +++ b/tests/tpci200-test.c @@ -0,0 +1,33 @@ +/* + * QTest testcase for tpci200 PCI-IndustryPack bridge + * + * Copyright (c) 2014 SUSE LINUX Products GmbH + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include <glib.h> +#include <string.h> +#include "libqtest.h" +#include "qemu/osdep.h" + +/* Tests only initialization so far. TODO: Replace with functional tests */ +static void nop(void) +{ +} + +int main(int argc, char **argv) +{ + int ret; + + g_test_init(&argc, &argv, NULL); + qtest_add_func("/tpci200/nop", nop); + + qtest_start("-device tpci200"); + ret = g_test_run(); + + qtest_end(); + + return ret; +} diff --git a/tests/virtio-net-test.c b/tests/virtio-net-test.c new file mode 100644 index 0000000000..df99343238 --- /dev/null +++ b/tests/virtio-net-test.c @@ -0,0 +1,33 @@ +/* + * QTest testcase for VirtIO NIC + * + * Copyright (c) 2014 SUSE LINUX Products GmbH + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include <glib.h> +#include <string.h> +#include "libqtest.h" +#include "qemu/osdep.h" + +/* Tests only initialization so far. TODO: Replace with functional tests */ +static void pci_nop(void) +{ +} + +int main(int argc, char **argv) +{ + int ret; + + g_test_init(&argc, &argv, NULL); + qtest_add_func("/virtio/net/pci/nop", pci_nop); + + qtest_start("-device virtio-net-pci"); + ret = g_test_run(); + + qtest_end(); + + return ret; +} diff --git a/tests/vmxnet3-test.c b/tests/vmxnet3-test.c new file mode 100644 index 0000000000..a2ebed39cc --- /dev/null +++ b/tests/vmxnet3-test.c @@ -0,0 +1,33 @@ +/* + * QTest testcase for vmxnet3 NIC + * + * Copyright (c) 2013-2014 SUSE LINUX Products GmbH + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include <glib.h> +#include <string.h> +#include "libqtest.h" +#include "qemu/osdep.h" + +/* Tests only initialization so far. TODO: Replace with functional tests */ +static void nop(void) +{ +} + +int main(int argc, char **argv) +{ + int ret; + + g_test_init(&argc, &argv, NULL); + qtest_add_func("/vmxnet3/nop", nop); + + qtest_start("-device vmxnet3"); + ret = g_test_run(); + + qtest_end(); + + return ret; +} @@ -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/trace-events b/trace-events index ab11f9721d..37130638ff 100644 --- a/trace-events +++ b/trace-events @@ -495,10 +495,10 @@ qcow2_writev_done_part(void *co, int cur_nr_sectors) "co %p cur_nr_sectors %d" qcow2_writev_data(void *co, uint64_t offset) "co %p offset %" PRIx64 # block/qcow2-cluster.c -qcow2_alloc_clusters_offset(void *co, uint64_t offset, int num) "co %p offet %" PRIx64 " num %d" -qcow2_handle_copied(void *co, uint64_t guest_offset, uint64_t host_offset, uint64_t bytes) "co %p guest_offet %" PRIx64 " host_offset %" PRIx64 " bytes %" PRIx64 -qcow2_handle_alloc(void *co, uint64_t guest_offset, uint64_t host_offset, uint64_t bytes) "co %p guest_offet %" PRIx64 " host_offset %" PRIx64 " bytes %" PRIx64 -qcow2_do_alloc_clusters_offset(void *co, uint64_t guest_offset, uint64_t host_offset, int nb_clusters) "co %p guest_offet %" PRIx64 " host_offset %" PRIx64 " nb_clusters %d" +qcow2_alloc_clusters_offset(void *co, uint64_t offset, int num) "co %p offset %" PRIx64 " num %d" +qcow2_handle_copied(void *co, uint64_t guest_offset, uint64_t host_offset, uint64_t bytes) "co %p guest_offset %" PRIx64 " host_offset %" PRIx64 " bytes %" PRIx64 +qcow2_handle_alloc(void *co, uint64_t guest_offset, uint64_t host_offset, uint64_t bytes) "co %p guest_offset %" PRIx64 " host_offset %" PRIx64 " bytes %" PRIx64 +qcow2_do_alloc_clusters_offset(void *co, uint64_t guest_offset, uint64_t host_offset, int nb_clusters) "co %p guest_offset %" PRIx64 " host_offset %" PRIx64 " nb_clusters %d" qcow2_cluster_alloc_phys(void *co) "co %p" qcow2_cluster_link_l2(void *co, int nb_clusters) "co %p nb_clusters %d" diff --git a/trace/Makefile.objs b/trace/Makefile.objs index 3b88e498b5..d321946d38 100644 --- a/trace/Makefile.objs +++ b/trace/Makefile.objs @@ -1,6 +1,30 @@ # -*- mode: makefile -*- ###################################################################### +# Auto-generated event descriptions for LTTng ust code + +ifeq ($(TRACE_BACKEND),ust) +$(obj)/generated-ust-provider.h: $(obj)/generated-ust-provider.h-timestamp +$(obj)/generated-ust-provider.h-timestamp: $(SRC_PATH)/trace-events + $(call quiet-command,$(TRACETOOL) \ + --format=ust-events-h \ + --backend=$(TRACE_BACKEND) \ + < $< > $@," GEN $(patsubst %-timestamp,%,$@)") + @cmp -s $@ $(patsubst %-timestamp,%,$@) || cp $@ $(patsubst %-timestamp,%,$@) + +$(obj)/generated-ust.c: $(obj)/generated-ust.c-timestamp $(BUILD_DIR)/config-host.mak +$(obj)/generated-ust.c-timestamp: $(SRC_PATH)/trace-events + $(call quiet-command,$(TRACETOOL) \ + --format=ust-events-c \ + --backend=$(TRACE_BACKEND) \ + < $< > $@," GEN $(patsubst %-timestamp,%,$@)") + @cmp -s $@ $(patsubst %-timestamp,%,$@) || cp $@ $(patsubst %-timestamp,%,$@) + +$(obj)/generated-events.h: $(obj)/generated-ust-provider.h +$(obj)/generated-events.c: $(obj)/generated-ust.c +endif + +###################################################################### # Auto-generated event descriptions $(obj)/generated-events.h: $(obj)/generated-events.h-timestamp @@ -77,5 +101,6 @@ util-obj-$(CONFIG_TRACE_DEFAULT) += default.o util-obj-$(CONFIG_TRACE_SIMPLE) += simple.o util-obj-$(CONFIG_TRACE_STDERR) += stderr.o util-obj-$(CONFIG_TRACE_FTRACE) += ftrace.o +util-obj-$(CONFIG_TRACE_UST) += generated-ust.o util-obj-y += control.o util-obj-y += generated-tracers.o 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; } @@ -2268,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; @@ -3021,14 +3021,19 @@ int main(int argc, char **argv, char **envp) goto chs_fail; if (*p == ',') { p++; - if (!strcmp(p, "none")) + if (!strcmp(p, "large")) { + translation = BIOS_ATA_TRANSLATION_LARGE; + } else if (!strcmp(p, "rechs")) { + translation = BIOS_ATA_TRANSLATION_RECHS; + } else if (!strcmp(p, "none")) { translation = BIOS_ATA_TRANSLATION_NONE; - else if (!strcmp(p, "lba")) + } else if (!strcmp(p, "lba")) { translation = BIOS_ATA_TRANSLATION_LBA; - else if (!strcmp(p, "auto")) + } else if (!strcmp(p, "auto")) { translation = BIOS_ATA_TRANSLATION_AUTO; - else + } else { goto chs_fail; + } } else if (*p != '\0') { chs_fail: fprintf(stderr, "qemu: invalid physical CHS format\n"); @@ -3042,10 +3047,15 @@ int main(int argc, char **argv, char **envp) qemu_opt_set(hda_opts, "heads", num); snprintf(num, sizeof(num), "%d", secs); qemu_opt_set(hda_opts, "secs", num); - if (translation == BIOS_ATA_TRANSLATION_LBA) + if (translation == BIOS_ATA_TRANSLATION_LARGE) { + qemu_opt_set(hda_opts, "trans", "large"); + } else if (translation == BIOS_ATA_TRANSLATION_RECHS) { + qemu_opt_set(hda_opts, "trans", "rechs"); + } else if (translation == BIOS_ATA_TRANSLATION_LBA) { qemu_opt_set(hda_opts, "trans", "lba"); - if (translation == BIOS_ATA_TRANSLATION_NONE) + } else if (translation == BIOS_ATA_TRANSLATION_NONE) { qemu_opt_set(hda_opts, "trans", "none"); + } } } break; @@ -4026,7 +4036,13 @@ int main(int argc, char **argv, char **envp) configure_accelerator(); if (qtest_chrdev) { - qtest_init(qtest_chrdev, qtest_log); + Error *local_err = NULL; + qtest_init(qtest_chrdev, qtest_log, &local_err); + if (local_err) { + error_report("%s", error_get_pretty(local_err)); + error_free(local_err); + exit(1); + } } machine_opts = qemu_get_machine_opts(); |