diff options
157 files changed, 1804 insertions, 1252 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 314411332c..fc8abe8dd3 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -81,6 +81,7 @@ F: disas/alpha.c ARM M: Peter Maydell <peter.maydell@linaro.org> +L: qemu-arm@nongnu.org S: Maintained F: target-arm/ F: hw/arm/ @@ -216,6 +217,7 @@ F: */kvm.* ARM M: Peter Maydell <peter.maydell@linaro.org> +L: qemu-arm@nongnu.org S: Maintained F: target-arm/kvm.c @@ -287,6 +289,7 @@ ARM Machines ------------ Allwinner-a10 M: Beniamino Galvani <b.galvani@gmail.com> +L: qemu-arm@nongnu.org S: Maintained F: hw/*/allwinner* F: include/hw/*/allwinner* @@ -294,6 +297,7 @@ F: hw/arm/cubieboard.c ARM PrimeCell M: Peter Maydell <peter.maydell@linaro.org> +L: qemu-arm@nongnu.org S: Maintained F: hw/char/pl011.c F: hw/display/pl110* @@ -308,6 +312,7 @@ F: include/hw/arm/primecell.h ARM cores M: Peter Maydell <peter.maydell@linaro.org> +L: qemu-arm@nongnu.org S: Maintained F: hw/intc/arm* F: hw/intc/gic_internal.h @@ -327,54 +332,64 @@ M: Evgeny Voevodin <e.voevodin@samsung.com> M: Maksim Kozlov <m.kozlov@samsung.com> M: Igor Mitsyanko <i.mitsyanko@gmail.com> M: Dmitry Solodkiy <d.solodkiy@samsung.com> +L: qemu-arm@nongnu.org S: Maintained F: hw/*/exynos* Calxeda Highbank M: Rob Herring <robh@kernel.org> +L: qemu-arm@nongnu.org S: Maintained F: hw/arm/highbank.c F: hw/net/xgmac.c Canon DIGIC M: Antony Pavlov <antonynpavlov@gmail.com> +L: qemu-arm@nongnu.org S: Maintained F: include/hw/arm/digic.h F: hw/*/digic* Gumstix L: qemu-devel@nongnu.org +L: qemu-arm@nongnu.org S: Orphan F: hw/arm/gumstix.c i.MX31 M: Peter Chubb <peter.chubb@nicta.com.au> +L: qemu-arm@nongnu.org S: Odd fixes F: hw/*/imx* F: hw/arm/kzm.c Integrator CP M: Peter Maydell <peter.maydell@linaro.org> +L: qemu-arm@nongnu.org S: Maintained F: hw/arm/integratorcp.c Musicpal M: Jan Kiszka <jan.kiszka@web.de> +L: qemu-arm@nongnu.org S: Maintained F: hw/arm/musicpal.c nSeries M: Andrzej Zaborowski <balrogg@gmail.com> +L: qemu-arm@nongnu.org S: Maintained F: hw/arm/nseries.c Palm M: Andrzej Zaborowski <balrogg@gmail.com> +L: qemu-arm@nongnu.org S: Maintained F: hw/arm/palm.c Real View M: Peter Maydell <peter.maydell@linaro.org> +L: qemu-arm@nongnu.org S: Maintained F: hw/arm/realview* F: hw/intc/realview_gic.c @@ -382,6 +397,7 @@ F: include/hw/intc/realview_gic.h PXA2XX M: Andrzej Zaborowski <balrogg@gmail.com> +L: qemu-arm@nongnu.org S: Maintained F: hw/arm/mainstone.c F: hw/arm/spitz.c @@ -391,17 +407,20 @@ F: hw/*/pxa2xx* Stellaris M: Peter Maydell <peter.maydell@linaro.org> +L: qemu-arm@nongnu.org S: Maintained F: hw/*/stellaris* Versatile PB M: Peter Maydell <peter.maydell@linaro.org> +L: qemu-arm@nongnu.org S: Maintained F: hw/*/versatile* Xilinx Zynq M: Alistair Francis <alistair.francis@xilinx.com> M: Peter Crosthwaite <crosthwaite.peter@gmail.com> +L: qemu-arm@nongnu.org S: Maintained F: hw/arm/xilinx_zynq.c F: hw/misc/zynq_slcr.c @@ -411,6 +430,7 @@ F: hw/ssi/xilinx_spips.c Xilinx ZynqMP M: Alistair Francis <alistair.francis@xilinx.com> M: Peter Crosthwaite <crosthwaite.peter@gmail.com> +L: qemu-arm@nongnu.org S: Maintained F: hw/arm/xlnx-zynqmp.c F: hw/arm/xlnx-ep108.c @@ -419,6 +439,7 @@ F: include/hw/arm/xlnx-zynqmp.h ARM ACPI Subsystem M: Shannon Zhao <zhaoshenglong@huawei.com> M: Shannon Zhao <shannon.zhao@linaro.org> +L: qemu-arm@nongnu.org S: Maintained F: hw/arm/virt-acpi-build.c F: include/hw/arm/virt-acpi-build.h @@ -1235,6 +1256,7 @@ AArch64 target M: Claudio Fontana <claudio.fontana@huawei.com> M: Claudio Fontana <claudio.fontana@gmail.com> S: Maintained +L: qemu-arm@nongnu.org F: tcg/aarch64/ F: disas/arm-a64.cc F: disas/libvixl/ @@ -1242,6 +1264,7 @@ F: disas/libvixl/ ARM target M: Andrzej Zaborowski <balrogg@gmail.com> S: Maintained +L: qemu-arm@nongnu.org F: tcg/arm/ F: disas/arm.c diff --git a/block/io.c b/block/io.c index 5ac6256ad3..8dcad3b3fe 100644 --- a/block/io.c +++ b/block/io.c @@ -216,6 +216,8 @@ void bdrv_disable_copy_on_read(BlockDriverState *bs) /* Check if any requests are in-flight (including throttled requests) */ bool bdrv_requests_pending(BlockDriverState *bs) { + BdrvChild *child; + if (!QLIST_EMPTY(&bs->tracked_requests)) { return true; } @@ -225,12 +227,13 @@ bool bdrv_requests_pending(BlockDriverState *bs) if (!qemu_co_queue_empty(&bs->throttled_reqs[1])) { return true; } - if (bs->file && bdrv_requests_pending(bs->file->bs)) { - return true; - } - if (bs->backing && bdrv_requests_pending(bs->backing->bs)) { - return true; + + QLIST_FOREACH(child, &bs->children, next) { + if (bdrv_requests_pending(child->bs)) { + return true; + } } + return false; } diff --git a/block/nbd.c b/block/nbd.c index c2a87e99bb..cd6a587776 100644 --- a/block/nbd.c +++ b/block/nbd.c @@ -206,24 +206,24 @@ static SocketAddress *nbd_config(BDRVNBDState *s, QDict *options, char **export, saddr = g_new0(SocketAddress, 1); if (qdict_haskey(options, "path")) { - saddr->kind = SOCKET_ADDRESS_KIND_UNIX; - saddr->q_unix = g_new0(UnixSocketAddress, 1); - saddr->q_unix->path = g_strdup(qdict_get_str(options, "path")); + saddr->type = SOCKET_ADDRESS_KIND_UNIX; + saddr->u.q_unix = g_new0(UnixSocketAddress, 1); + saddr->u.q_unix->path = g_strdup(qdict_get_str(options, "path")); qdict_del(options, "path"); } else { - saddr->kind = SOCKET_ADDRESS_KIND_INET; - saddr->inet = g_new0(InetSocketAddress, 1); - saddr->inet->host = g_strdup(qdict_get_str(options, "host")); + saddr->type = SOCKET_ADDRESS_KIND_INET; + saddr->u.inet = g_new0(InetSocketAddress, 1); + saddr->u.inet->host = g_strdup(qdict_get_str(options, "host")); if (!qdict_get_try_str(options, "port")) { - saddr->inet->port = g_strdup_printf("%d", NBD_DEFAULT_PORT); + saddr->u.inet->port = g_strdup_printf("%d", NBD_DEFAULT_PORT); } else { - saddr->inet->port = g_strdup(qdict_get_str(options, "port")); + saddr->u.inet->port = g_strdup(qdict_get_str(options, "port")); } qdict_del(options, "host"); qdict_del(options, "port"); } - s->client.is_unix = saddr->kind == SOCKET_ADDRESS_KIND_UNIX; + s->client.is_unix = saddr->type == SOCKET_ADDRESS_KIND_UNIX; *export = g_strdup(qdict_get_try_str(options, "export")); if (*export) { diff --git a/block/qcow2.c b/block/qcow2.c index bacc4f2e11..88f56c8868 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -2738,18 +2738,16 @@ static ImageInfoSpecific *qcow2_get_specific_info(BlockDriverState *bs) ImageInfoSpecific *spec_info = g_new(ImageInfoSpecific, 1); *spec_info = (ImageInfoSpecific){ - .kind = IMAGE_INFO_SPECIFIC_KIND_QCOW2, - { - .qcow2 = g_new(ImageInfoSpecificQCow2, 1), - }, + .type = IMAGE_INFO_SPECIFIC_KIND_QCOW2, + .u.qcow2 = g_new(ImageInfoSpecificQCow2, 1), }; if (s->qcow_version == 2) { - *spec_info->qcow2 = (ImageInfoSpecificQCow2){ + *spec_info->u.qcow2 = (ImageInfoSpecificQCow2){ .compat = g_strdup("0.10"), .refcount_bits = s->refcount_bits, }; } else if (s->qcow_version == 3) { - *spec_info->qcow2 = (ImageInfoSpecificQCow2){ + *spec_info->u.qcow2 = (ImageInfoSpecificQCow2){ .compat = g_strdup("1.1"), .lazy_refcounts = s->compatible_features & QCOW2_COMPAT_LAZY_REFCOUNTS, diff --git a/block/vmdk.c b/block/vmdk.c index 0effb7d91c..6f819e413f 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -2161,19 +2161,19 @@ static ImageInfoSpecific *vmdk_get_specific_info(BlockDriverState *bs) ImageInfoList **next; *spec_info = (ImageInfoSpecific){ - .kind = IMAGE_INFO_SPECIFIC_KIND_VMDK, + .type = IMAGE_INFO_SPECIFIC_KIND_VMDK, { .vmdk = g_new0(ImageInfoSpecificVmdk, 1), }, }; - *spec_info->vmdk = (ImageInfoSpecificVmdk) { + *spec_info->u.vmdk = (ImageInfoSpecificVmdk) { .create_type = g_strdup(s->create_type), .cid = s->cid, .parent_cid = s->parent_cid, }; - next = &spec_info->vmdk->extents; + next = &spec_info->u.vmdk->extents; for (i = 0; i < s->num_extents; i++) { *next = g_new0(ImageInfoList, 1); (*next)->value = vmdk_get_extent_info(&s->extents[i]); diff --git a/blockdev.c b/blockdev.c index 18712d25cc..8b8bfa992c 100644 --- a/blockdev.c +++ b/blockdev.c @@ -1137,13 +1137,14 @@ void hmp_commit(Monitor *mon, const QDict *qdict) } } -static void blockdev_do_action(int kind, void *data, Error **errp) +static void blockdev_do_action(TransactionActionKind type, void *data, + Error **errp) { TransactionAction action; TransactionActionList list; - action.kind = kind; - action.data = data; + action.type = type; + action.u.data = data; list.value = &action; list.next = NULL; qmp_transaction(&list, errp); @@ -1388,9 +1389,9 @@ static void internal_snapshot_prepare(BlkTransactionState *common, InternalSnapshotState *state; int ret1; - g_assert(common->action->kind == + g_assert(common->action->type == TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_INTERNAL_SYNC); - internal = common->action->blockdev_snapshot_internal_sync; + internal = common->action->u.blockdev_snapshot_internal_sync; state = DO_UPCAST(InternalSnapshotState, common, common); /* 1. parse input */ @@ -1536,22 +1537,22 @@ static void external_snapshot_prepare(BlkTransactionState *common, TransactionAction *action = common->action; /* get parameters */ - g_assert(action->kind == TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC); + g_assert(action->type == TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC); - has_device = action->blockdev_snapshot_sync->has_device; - device = action->blockdev_snapshot_sync->device; - has_node_name = action->blockdev_snapshot_sync->has_node_name; - node_name = action->blockdev_snapshot_sync->node_name; + has_device = action->u.blockdev_snapshot_sync->has_device; + device = action->u.blockdev_snapshot_sync->device; + has_node_name = action->u.blockdev_snapshot_sync->has_node_name; + node_name = action->u.blockdev_snapshot_sync->node_name; has_snapshot_node_name = - action->blockdev_snapshot_sync->has_snapshot_node_name; - snapshot_node_name = action->blockdev_snapshot_sync->snapshot_node_name; + action->u.blockdev_snapshot_sync->has_snapshot_node_name; + snapshot_node_name = action->u.blockdev_snapshot_sync->snapshot_node_name; - new_image_file = action->blockdev_snapshot_sync->snapshot_file; - if (action->blockdev_snapshot_sync->has_format) { - format = action->blockdev_snapshot_sync->format; + new_image_file = action->u.blockdev_snapshot_sync->snapshot_file; + if (action->u.blockdev_snapshot_sync->has_format) { + format = action->u.blockdev_snapshot_sync->format; } - if (action->blockdev_snapshot_sync->has_mode) { - mode = action->blockdev_snapshot_sync->mode; + if (action->u.blockdev_snapshot_sync->has_mode) { + mode = action->u.blockdev_snapshot_sync->mode; } /* start processing */ @@ -1681,8 +1682,8 @@ static void drive_backup_prepare(BlkTransactionState *common, Error **errp) DriveBackup *backup; Error *local_err = NULL; - assert(common->action->kind == TRANSACTION_ACTION_KIND_DRIVE_BACKUP); - backup = common->action->drive_backup; + assert(common->action->type == TRANSACTION_ACTION_KIND_DRIVE_BACKUP); + backup = common->action->u.drive_backup; blk = blk_by_name(backup->device); if (!blk) { @@ -1754,8 +1755,8 @@ static void blockdev_backup_prepare(BlkTransactionState *common, Error **errp) BlockBackend *blk, *target; Error *local_err = NULL; - assert(common->action->kind == TRANSACTION_ACTION_KIND_BLOCKDEV_BACKUP); - backup = common->action->blockdev_backup; + assert(common->action->type == TRANSACTION_ACTION_KIND_BLOCKDEV_BACKUP); + backup = common->action->u.blockdev_backup; blk = blk_by_name(backup->device); if (!blk) { @@ -1887,9 +1888,9 @@ void qmp_transaction(TransactionActionList *dev_list, Error **errp) dev_info = dev_entry->value; dev_entry = dev_entry->next; - assert(dev_info->kind < ARRAY_SIZE(actions)); + assert(dev_info->type < ARRAY_SIZE(actions)); - ops = &actions[dev_info->kind]; + ops = &actions[dev_info->type]; assert(ops->instance_size > 0); state = g_malloc0(ops->instance_size); @@ -3291,25 +3291,11 @@ fi libs_softmmu="$libs_softmmu $fdt_libs" ########################################## -# opengl probe (for sdl2, milkymist-tmu2) - -# GLX probe, used by milkymist-tmu2 -# this is temporary, code will be switched to egl mid-term. -cat > $TMPC << EOF -#include <X11/Xlib.h> -#include <GL/gl.h> -#include <GL/glx.h> -int main(void) { glBegin(0); glXQueryVersion(0,0,0); return 0; } -EOF -if compile_prog "" "-lGL -lX11" ; then - have_glx=yes -else - have_glx=no -fi +# opengl probe (for sdl2, gtk, milkymist-tmu2) if test "$opengl" != "no" ; then - opengl_pkgs="gl glesv2 epoxy egl" - if $pkg_config $opengl_pkgs x11 && test "$have_glx" = "yes"; then + opengl_pkgs="epoxy" + if $pkg_config $opengl_pkgs x11; then opengl_cflags="$($pkg_config --cflags $opengl_pkgs) $x11_cflags" opengl_libs="$($pkg_config --libs $opengl_pkgs) $x11_libs" opengl=yes diff --git a/docs/qapi-code-gen.txt b/docs/qapi-code-gen.txt index 2afab20f55..4d8c2fcf02 100644 --- a/docs/qapi-code-gen.txt +++ b/docs/qapi-code-gen.txt @@ -106,12 +106,15 @@ Types, commands, and events share a common namespace. Therefore, generally speaking, type definitions should always use CamelCase for user-defined type names, while built-in types are lowercase. Type definitions should not end in 'Kind', as this namespace is used for -creating implicit C enums for visiting union types. Command names, +creating implicit C enums for visiting union types, or in 'List', as +this namespace is used for creating array types. Command names, and field names within a type, should be all lower case with words separated by a hyphen. However, some existing older commands and complex types use underscore; when extending such expressions, consistency is preferred over blindly avoiding underscore. Event -names should be ALL_CAPS with words separated by underscore. +names should be ALL_CAPS with words separated by underscore. Field +names cannot start with 'has-' or 'has_', as this is reserved for +tracking optional fields. Any name (command, event, type, field, or enum value) beginning with "x-" is marked experimental, and may be withdrawn or changed @@ -122,9 +125,10 @@ vendor), even if the rest of the name uses dash (example: __com.redhat_drive-mirror). Other than downstream extensions (with leading underscore and the use of dots), all names should begin with a letter, and contain only ASCII letters, digits, dash, and underscore. -It is okay to reuse names that match C keywords; the generator will -rename a field named "default" in the QAPI to "q_default" in the -generated C code. +Names beginning with 'q_' are reserved for the generator: QMP names +that resemble C keywords or other problematic strings will be munged +in C to use this prefix. For example, a field named "default" in +qapi becomes "q_default" in the generated C code. In the rest of this document, usage lines are given for each expression type, with literal strings written in lower case and diff --git a/docs/qmp-events.txt b/docs/qmp-events.txt index d92cc4833b..d2f1ce497e 100644 --- a/docs/qmp-events.txt +++ b/docs/qmp-events.txt @@ -28,6 +28,8 @@ Example: "data": { "actual": 944766976 }, "timestamp": { "seconds": 1267020223, "microseconds": 435656 } } +Note: this event is rate-limited. + BLOCK_IMAGE_CORRUPTED --------------------- @@ -296,6 +298,8 @@ Example: "data": { "reference": "usr1", "sector-num": 345435, "sectors-count": 5 }, "timestamp": { "seconds": 1344522075, "microseconds": 745528 } } +Note: this event is rate-limited. + QUORUM_REPORT_BAD ----------------- @@ -318,6 +322,8 @@ Example: "data": { "node-name": "1.raw", "sector-num": 345435, "sectors-count": 5 }, "timestamp": { "seconds": 1344522075, "microseconds": 745528 } } +Note: this event is rate-limited. + RESET ----- @@ -358,6 +364,8 @@ Example: "data": { "offset": 78 }, "timestamp": { "seconds": 1267020223, "microseconds": 435656 } } +Note: this event is rate-limited. + SHUTDOWN -------- @@ -632,6 +640,8 @@ Example: "data": { "id": "channel0", "open": true }, "timestamp": { "seconds": 1401385907, "microseconds": 422329 } } +Note: this event is rate-limited separately for each "id". + WAKEUP ------ @@ -662,3 +672,5 @@ Example: Note: If action is "reset", "shutdown", or "pause" the WATCHDOG event is followed respectively by the RESET, SHUTDOWN, or STOP events. + +Note: this event is rate-limited. diff --git a/docs/qmp-spec.txt b/docs/qmp-spec.txt index 4c28cd9438..4fb10a5d6b 100644 --- a/docs/qmp-spec.txt +++ b/docs/qmp-spec.txt @@ -175,6 +175,11 @@ The format of asynchronous events is: For a listing of supported asynchronous events, please, refer to the qmp-events.txt file. +Some events are rate-limited to at most one per second. If additional +"similar" events arrive within one second, all but the last one are +dropped, and the last one is delayed. "Similar" normally means same +event type. See qmp-events.txt for details. + 2.5 QGA Synchronization ----------------------- @@ -569,8 +569,8 @@ void hmp_info_vnc(Monitor *mon, const QDict *qdict) for (client = info->clients; client; client = client->next) { monitor_printf(mon, "Client:\n"); monitor_printf(mon, " address: %s:%s\n", - client->value->base->host, - client->value->base->service); + client->value->host, + client->value->service); monitor_printf(mon, " x509_dname: %s\n", client->value->x509_dname ? client->value->x509_dname : "none"); @@ -638,7 +638,7 @@ void hmp_info_spice(Monitor *mon, const QDict *qdict) for (chan = info->channels; chan; chan = chan->next) { monitor_printf(mon, "Channel:\n"); monitor_printf(mon, " address: %s:%s%s\n", - chan->value->base->host, chan->value->base->port, + chan->value->host, chan->value->port, chan->value->tls ? " [tls]" : ""); monitor_printf(mon, " session: %" PRId64 "\n", chan->value->connection_id); @@ -841,11 +841,11 @@ void hmp_info_tpm(Monitor *mon, const QDict *qdict) c, TpmModel_lookup[ti->model]); monitor_printf(mon, " \\ %s: type=%s", - ti->id, TpmTypeOptionsKind_lookup[ti->options->kind]); + ti->id, TpmTypeOptionsKind_lookup[ti->options->type]); - switch (ti->options->kind) { + switch (ti->options->type) { case TPM_TYPE_OPTIONS_KIND_PASSTHROUGH: - tpo = ti->options->passthrough; + tpo = ti->options->u.passthrough; monitor_printf(mon, "%s%s%s%s", tpo->has_path ? ",path=" : "", tpo->has_path ? tpo->path : "", @@ -1735,15 +1735,15 @@ void hmp_sendkey(Monitor *mon, const QDict *qdict) if (*endp != '\0') { goto err_out; } - keylist->value->kind = KEY_VALUE_KIND_NUMBER; - keylist->value->number = value; + keylist->value->type = KEY_VALUE_KIND_NUMBER; + keylist->value->u.number = value; } else { int idx = index_from_key(keyname_buf); if (idx == Q_KEY_CODE_MAX) { goto err_out; } - keylist->value->kind = KEY_VALUE_KIND_QCODE; - keylist->value->qcode = idx; + keylist->value->type = KEY_VALUE_KIND_QCODE; + keylist->value->u.qcode = idx; } if (!separator) { @@ -1958,12 +1958,12 @@ void hmp_info_memory_devices(Monitor *mon, const QDict *qdict) value = info->value; if (value) { - switch (value->kind) { + switch (value->type) { case MEMORY_DEVICE_INFO_KIND_DIMM: - di = value->dimm; + di = value->u.dimm; monitor_printf(mon, "Memory device [%s]: \"%s\"\n", - MemoryDeviceInfoKind_lookup[value->kind], + MemoryDeviceInfoKind_lookup[value->type], di->id ? di->id : ""); monitor_printf(mon, " addr: 0x%" PRIx64 "\n", di->addr); monitor_printf(mon, " slot: %" PRId64 "\n", di->slot); diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c index eb214db443..a80d2ad29c 100644 --- a/hw/arm/armv7m.c +++ b/hw/arm/armv7m.c @@ -166,17 +166,15 @@ static void armv7m_reset(void *opaque) mem_size is in bytes. Returns the NVIC array. */ -qemu_irq *armv7m_init(MemoryRegion *system_memory, int mem_size, int num_irq, +DeviceState *armv7m_init(MemoryRegion *system_memory, int mem_size, int num_irq, const char *kernel_filename, const char *cpu_model) { ARMCPU *cpu; CPUARMState *env; DeviceState *nvic; - qemu_irq *pic = g_new(qemu_irq, num_irq); int image_size; uint64_t entry; uint64_t lowaddr; - int i; int big_endian; MemoryRegion *hack = g_new(MemoryRegion, 1); @@ -198,9 +196,6 @@ qemu_irq *armv7m_init(MemoryRegion *system_memory, int mem_size, int num_irq, qdev_init_nofail(nvic); sysbus_connect_irq(SYS_BUS_DEVICE(nvic), 0, qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ)); - for (i = 0; i < num_irq; i++) { - pic[i] = qdev_get_gpio_in(nvic, i); - } #ifdef TARGET_WORDS_BIGENDIAN big_endian = 1; @@ -234,7 +229,7 @@ qemu_irq *armv7m_init(MemoryRegion *system_memory, int mem_size, int num_irq, memory_region_add_subregion(system_memory, 0xfffff000, hack); qemu_register_reset(armv7m_reset, cpu); - return pic; + return nvic; } static Property bitband_properties[] = { diff --git a/hw/arm/boot.c b/hw/arm/boot.c index bef451b3b2..b0879a5e76 100644 --- a/hw/arm/boot.c +++ b/hw/arm/boot.c @@ -28,14 +28,15 @@ #define KERNEL64_LOAD_ADDR 0x00080000 typedef enum { - FIXUP_NONE = 0, /* do nothing */ - FIXUP_TERMINATOR, /* end of insns */ - FIXUP_BOARDID, /* overwrite with board ID number */ - FIXUP_ARGPTR, /* overwrite with pointer to kernel args */ - FIXUP_ENTRYPOINT, /* overwrite with kernel entry point */ - FIXUP_GIC_CPU_IF, /* overwrite with GIC CPU interface address */ - FIXUP_BOOTREG, /* overwrite with boot register address */ - FIXUP_DSB, /* overwrite with correct DSB insn for cpu */ + FIXUP_NONE = 0, /* do nothing */ + FIXUP_TERMINATOR, /* end of insns */ + FIXUP_BOARDID, /* overwrite with board ID number */ + FIXUP_BOARD_SETUP, /* overwrite with board specific setup code address */ + FIXUP_ARGPTR, /* overwrite with pointer to kernel args */ + FIXUP_ENTRYPOINT, /* overwrite with kernel entry point */ + FIXUP_GIC_CPU_IF, /* overwrite with GIC CPU interface address */ + FIXUP_BOOTREG, /* overwrite with boot register address */ + FIXUP_DSB, /* overwrite with correct DSB insn for cpu */ FIXUP_MAX, } FixupType; @@ -58,8 +59,17 @@ static const ARMInsnFixup bootloader_aarch64[] = { { 0, FIXUP_TERMINATOR } }; -/* The worlds second smallest bootloader. Set r0-r2, then jump to kernel. */ +/* A very small bootloader: call the board-setup code (if needed), + * set r0-r2, then jump to the kernel. + * If we're not calling boot setup code then we don't copy across + * the first BOOTLOADER_NO_BOARD_SETUP_OFFSET insns in this array. + */ + static const ARMInsnFixup bootloader[] = { + { 0xe28fe008 }, /* add lr, pc, #8 */ + { 0xe51ff004 }, /* ldr pc, [pc, #-4] */ + { 0, FIXUP_BOARD_SETUP }, +#define BOOTLOADER_NO_BOARD_SETUP_OFFSET 3 { 0xe3a00000 }, /* mov r0, #0 */ { 0xe59f1004 }, /* ldr r1, [pc, #4] */ { 0xe59f2004 }, /* ldr r2, [pc, #4] */ @@ -131,6 +141,7 @@ static void write_bootloader(const char *name, hwaddr addr, case FIXUP_NONE: break; case FIXUP_BOARDID: + case FIXUP_BOARD_SETUP: case FIXUP_ARGPTR: case FIXUP_ENTRYPOINT: case FIXUP_GIC_CPU_IF: @@ -640,6 +651,9 @@ static void arm_load_kernel_notify(Notifier *notifier, void *data) elf_machine = EM_AARCH64; } else { primary_loader = bootloader; + if (!info->write_board_setup) { + primary_loader += BOOTLOADER_NO_BOARD_SETUP_OFFSET; + } kernel_load_offset = KERNEL_LOAD_ADDR; elf_machine = EM_ARM; } @@ -745,6 +759,7 @@ static void arm_load_kernel_notify(Notifier *notifier, void *data) info->initrd_size = initrd_size; fixupcontext[FIXUP_BOARDID] = info->board_id; + fixupcontext[FIXUP_BOARD_SETUP] = info->board_setup_addr; /* for device tree boot, we pass the DTB directly in r2. Otherwise * we point to the kernel args. @@ -793,6 +808,9 @@ static void arm_load_kernel_notify(Notifier *notifier, void *data) if (info->nb_cpus > 1) { info->write_secondary_boot(cpu, info); } + if (info->write_board_setup) { + info->write_board_setup(cpu, info); + } /* Notify devices which need to fake up firmware initialization * that we're doing a direct kernel boot. diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c index 3d6486fcf5..0114e0a7f8 100644 --- a/hw/arm/stellaris.c +++ b/hw/arm/stellaris.c @@ -16,6 +16,7 @@ #include "net/net.h" #include "hw/boards.h" #include "exec/address-spaces.h" +#include "sysemu/sysemu.h" #define GPIO_A 0 #define GPIO_B 1 @@ -1176,6 +1177,14 @@ static int stellaris_adc_init(SysBusDevice *sbd) return 0; } +static +void do_sys_reset(void *opaque, int n, int level) +{ + if (level) { + qemu_system_reset_request(); + } +} + /* Board init. */ static stellaris_board_info stellaris_boards[] = { { "LM3S811EVB", @@ -1210,8 +1219,7 @@ static void stellaris_init(const char *kernel_filename, const char *cpu_model, 0x40024000, 0x40025000, 0x40026000}; static const int gpio_irq[7] = {0, 1, 2, 3, 4, 30, 31}; - qemu_irq *pic; - DeviceState *gpio_dev[7]; + DeviceState *gpio_dev[7], *nvic; qemu_irq gpio_in[7][8]; qemu_irq gpio_out[7][8]; qemu_irq adc; @@ -1241,12 +1249,19 @@ static void stellaris_init(const char *kernel_filename, const char *cpu_model, vmstate_register_ram_global(sram); memory_region_add_subregion(system_memory, 0x20000000, sram); - pic = armv7m_init(system_memory, flash_size, NUM_IRQ_LINES, + nvic = armv7m_init(system_memory, flash_size, NUM_IRQ_LINES, kernel_filename, cpu_model); + qdev_connect_gpio_out_named(nvic, "SYSRESETREQ", 0, + qemu_allocate_irq(&do_sys_reset, NULL, 0)); + if (board->dc1 & (1 << 16)) { dev = sysbus_create_varargs(TYPE_STELLARIS_ADC, 0x40038000, - pic[14], pic[15], pic[16], pic[17], NULL); + qdev_get_gpio_in(nvic, 14), + qdev_get_gpio_in(nvic, 15), + qdev_get_gpio_in(nvic, 16), + qdev_get_gpio_in(nvic, 17), + NULL); adc = qdev_get_gpio_in(dev, 0); } else { adc = NULL; @@ -1255,19 +1270,21 @@ static void stellaris_init(const char *kernel_filename, const char *cpu_model, if (board->dc2 & (0x10000 << i)) { dev = sysbus_create_simple(TYPE_STELLARIS_GPTM, 0x40030000 + i * 0x1000, - pic[timer_irq[i]]); + qdev_get_gpio_in(nvic, timer_irq[i])); /* TODO: This is incorrect, but we get away with it because the ADC output is only ever pulsed. */ qdev_connect_gpio_out(dev, 0, adc); } } - stellaris_sys_init(0x400fe000, pic[28], board, nd_table[0].macaddr.a); + stellaris_sys_init(0x400fe000, qdev_get_gpio_in(nvic, 28), + board, nd_table[0].macaddr.a); for (i = 0; i < 7; i++) { if (board->dc4 & (1 << i)) { gpio_dev[i] = sysbus_create_simple("pl061_luminary", gpio_addr[i], - pic[gpio_irq[i]]); + qdev_get_gpio_in(nvic, + gpio_irq[i])); for (j = 0; j < 8; j++) { gpio_in[i][j] = qdev_get_gpio_in(gpio_dev[i], j); gpio_out[i][j] = NULL; @@ -1276,7 +1293,8 @@ 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]); + dev = sysbus_create_simple(TYPE_STELLARIS_I2C, 0x40020000, + qdev_get_gpio_in(nvic, 8)); i2c = (I2CBus *)qdev_get_child_bus(dev, "i2c"); if (board->peripherals & BP_OLED_I2C) { i2c_create_slave(i2c, "ssd0303", 0x3d); @@ -1286,11 +1304,12 @@ static void stellaris_init(const char *kernel_filename, const char *cpu_model, for (i = 0; i < 4; i++) { if (board->dc2 & (1 << i)) { sysbus_create_simple("pl011_luminary", 0x4000c000 + i * 0x1000, - pic[uart_irq[i]]); + qdev_get_gpio_in(nvic, uart_irq[i])); } } if (board->dc2 & (1 << 4)) { - dev = sysbus_create_simple("pl022", 0x40008000, pic[7]); + dev = sysbus_create_simple("pl022", 0x40008000, + qdev_get_gpio_in(nvic, 7)); if (board->peripherals & BP_OLED_SSI) { void *bus; DeviceState *sddev; @@ -1326,7 +1345,7 @@ static void stellaris_init(const char *kernel_filename, const char *cpu_model, qdev_set_nic_properties(enet, &nd_table[0]); qdev_init_nofail(enet); sysbus_mmio_map(SYS_BUS_DEVICE(enet), 0, 0x40048000); - sysbus_connect_irq(SYS_BUS_DEVICE(enet), 0, pic[42]); + sysbus_connect_irq(SYS_BUS_DEVICE(enet), 0, qdev_get_gpio_in(nvic, 42)); } if (board->peripherals & BP_GAMEPAD) { qemu_irq gpad_irq[5]; diff --git a/hw/arm/stm32f205_soc.c b/hw/arm/stm32f205_soc.c index 4d26a7ed91..3f993406dd 100644 --- a/hw/arm/stm32f205_soc.c +++ b/hw/arm/stm32f205_soc.c @@ -59,9 +59,8 @@ static void stm32f205_soc_initfn(Object *obj) static void stm32f205_soc_realize(DeviceState *dev_soc, Error **errp) { STM32F205State *s = STM32F205_SOC(dev_soc); - DeviceState *syscfgdev, *usartdev, *timerdev; + DeviceState *syscfgdev, *usartdev, *timerdev, *nvic; SysBusDevice *syscfgbusdev, *usartbusdev, *timerbusdev; - qemu_irq *pic; Error *err = NULL; int i; @@ -88,8 +87,8 @@ static void stm32f205_soc_realize(DeviceState *dev_soc, Error **errp) vmstate_register_ram_global(sram); memory_region_add_subregion(system_memory, SRAM_BASE_ADDRESS, sram); - pic = armv7m_init(get_system_memory(), FLASH_SIZE, 96, - s->kernel_filename, s->cpu_model); + nvic = armv7m_init(get_system_memory(), FLASH_SIZE, 96, + s->kernel_filename, s->cpu_model); /* System configuration controller */ syscfgdev = DEVICE(&s->syscfg); @@ -100,7 +99,7 @@ static void stm32f205_soc_realize(DeviceState *dev_soc, Error **errp) } syscfgbusdev = SYS_BUS_DEVICE(syscfgdev); sysbus_mmio_map(syscfgbusdev, 0, 0x40013800); - sysbus_connect_irq(syscfgbusdev, 0, pic[71]); + sysbus_connect_irq(syscfgbusdev, 0, qdev_get_gpio_in(nvic, 71)); /* Attach UART (uses USART registers) and USART controllers */ for (i = 0; i < STM_NUM_USARTS; i++) { @@ -112,7 +111,8 @@ static void stm32f205_soc_realize(DeviceState *dev_soc, Error **errp) } usartbusdev = SYS_BUS_DEVICE(usartdev); sysbus_mmio_map(usartbusdev, 0, usart_addr[i]); - sysbus_connect_irq(usartbusdev, 0, pic[usart_irq[i]]); + sysbus_connect_irq(usartbusdev, 0, + qdev_get_gpio_in(nvic, usart_irq[i])); } /* Timer 2 to 5 */ @@ -126,7 +126,8 @@ static void stm32f205_soc_realize(DeviceState *dev_soc, Error **errp) } timerbusdev = SYS_BUS_DEVICE(timerdev); sysbus_mmio_map(timerbusdev, 0, timer_addr[i]); - sysbus_connect_irq(timerbusdev, 0, pic[timer_irq[i]]); + sysbus_connect_irq(timerbusdev, 0, + qdev_get_gpio_in(nvic, timer_irq[i])); } } diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index 1aaff1f662..3c2c5d6bfa 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -180,6 +180,7 @@ static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap, int irq, aml_append(dev, aml_name_decl("_ADR", aml_int(0))); aml_append(dev, aml_name_decl("_UID", aml_string("PCI0"))); aml_append(dev, aml_name_decl("_STR", aml_unicode("PCIe 0 Device"))); + aml_append(dev, aml_name_decl("_CCA", aml_int(1))); /* Declare the PCI Routing Table. */ Aml *rt_pkg = aml_package(nr_pcie_buses * PCI_NUM_PINS); @@ -448,6 +449,24 @@ build_madt(GArray *table_data, GArray *linker, VirtGuestInfo *guest_info, gicd->length = sizeof(*gicd); gicd->base_address = memmap[VIRT_GIC_DIST].base; + for (i = 0; i < guest_info->smp_cpus; i++) { + AcpiMadtGenericInterrupt *gicc = acpi_data_push(table_data, + sizeof *gicc); + ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(i)); + + gicc->type = ACPI_APIC_GENERIC_INTERRUPT; + gicc->length = sizeof(*gicc); + if (guest_info->gic_version == 2) { + gicc->base_address = memmap[VIRT_GIC_CPU].base; + } + gicc->cpu_interface_number = i; + gicc->arm_mpidr = armcpu->mp_affinity; + gicc->uid = i; + if (test_bit(i, cpuinfo->found_cpus)) { + gicc->flags = cpu_to_le32(ACPI_GICC_ENABLED); + } + } + if (guest_info->gic_version == 3) { AcpiMadtGenericRedistributor *gicr = acpi_data_push(table_data, sizeof *gicr); @@ -457,20 +476,6 @@ build_madt(GArray *table_data, GArray *linker, VirtGuestInfo *guest_info, gicr->base_address = cpu_to_le64(memmap[VIRT_GIC_REDIST].base); gicr->range_length = cpu_to_le32(memmap[VIRT_GIC_REDIST].size); } else { - for (i = 0; i < guest_info->smp_cpus; i++) { - AcpiMadtGenericInterrupt *gicc = acpi_data_push(table_data, - sizeof *gicc); - gicc->type = ACPI_APIC_GENERIC_INTERRUPT; - gicc->length = sizeof(*gicc); - gicc->base_address = memmap[VIRT_GIC_CPU].base; - gicc->cpu_interface_number = i; - gicc->arm_mpidr = i; - gicc->uid = i; - if (test_bit(i, cpuinfo->found_cpus)) { - gicc->flags = cpu_to_le32(ACPI_GICC_ENABLED); - } - } - gic_msi = acpi_data_push(table_data, sizeof *gic_msi); gic_msi->type = ACPI_APIC_GENERIC_MSI_FRAME; gic_msi->length = sizeof(*gic_msi); diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c index 9f89483d6a..82a9db8120 100644 --- a/hw/arm/xilinx_zynq.c +++ b/hw/arm/xilinx_zynq.c @@ -43,6 +43,45 @@ static const int dma_irqs[8] = { 46, 47, 48, 49, 72, 73, 74, 75 }; +#define BOARD_SETUP_ADDR 0x100 + +#define SLCR_LOCK_OFFSET 0x004 +#define SLCR_UNLOCK_OFFSET 0x008 +#define SLCR_ARM_PLL_OFFSET 0x100 + +#define SLCR_XILINX_UNLOCK_KEY 0xdf0d +#define SLCR_XILINX_LOCK_KEY 0x767b + +#define ARMV7_IMM16(x) (extract32((x), 0, 12) | \ + extract32((x), 12, 4) << 16) + +/* Write immediate val to address r0 + addr. r0 should contain base offset + * of the SLCR block. Clobbers r1. + */ + +#define SLCR_WRITE(addr, val) \ + 0xe3001000 + ARMV7_IMM16(extract32((val), 0, 16)), /* movw r1 ... */ \ + 0xe3401000 + ARMV7_IMM16(extract32((val), 16, 16)), /* movt r1 ... */ \ + 0xe5801000 + (addr) + +static void zynq_write_board_setup(ARMCPU *cpu, + const struct arm_boot_info *info) +{ + int n; + uint32_t board_setup_blob[] = { + 0xe3a004f8, /* mov r0, #0xf8000000 */ + SLCR_WRITE(SLCR_UNLOCK_OFFSET, SLCR_XILINX_UNLOCK_KEY), + SLCR_WRITE(SLCR_ARM_PLL_OFFSET, 0x00014008), + SLCR_WRITE(SLCR_LOCK_OFFSET, SLCR_XILINX_LOCK_KEY), + 0xe12fff1e, /* bx lr */ + }; + for (n = 0; n < ARRAY_SIZE(board_setup_blob); n++) { + board_setup_blob[n] = tswap32(board_setup_blob[n]); + } + rom_add_blob_fixed("board-setup", board_setup_blob, + sizeof(board_setup_blob), BOARD_SETUP_ADDR); +} + static struct arm_boot_info zynq_binfo = {}; static void gem_init(NICInfo *nd, uint32_t base, qemu_irq irq) @@ -252,6 +291,9 @@ static void zynq_init(MachineState *machine) zynq_binfo.nb_cpus = 1; zynq_binfo.board_id = 0xd32; zynq_binfo.loader_start = 0; + zynq_binfo.board_setup_addr = BOARD_SETUP_ADDR; + zynq_binfo.write_board_setup = zynq_write_board_setup; + arm_load_kernel(ARM_CPU(first_cpu), &zynq_binfo); } diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c index b36ca3da74..87553bbc60 100644 --- a/hw/arm/xlnx-zynqmp.c +++ b/hw/arm/xlnx-zynqmp.c @@ -48,6 +48,14 @@ static const int uart_intr[XLNX_ZYNQMP_NUM_UARTS] = { 21, 22, }; +static const uint64_t sdhci_addr[XLNX_ZYNQMP_NUM_SDHCI] = { + 0xFF160000, 0xFF170000, +}; + +static const int sdhci_intr[XLNX_ZYNQMP_NUM_SDHCI] = { + 48, 49, +}; + typedef struct XlnxZynqMPGICRegion { int region_index; uint32_t address; @@ -97,6 +105,13 @@ static void xlnx_zynqmp_init(Object *obj) object_initialize(&s->sata, sizeof(s->sata), TYPE_SYSBUS_AHCI); qdev_set_parent_bus(DEVICE(&s->sata), sysbus_get_default()); + + for (i = 0; i < XLNX_ZYNQMP_NUM_SDHCI; i++) { + object_initialize(&s->sdhci[i], sizeof(s->sdhci[i]), + TYPE_SYSBUS_SDHCI); + qdev_set_parent_bus(DEVICE(&s->sdhci[i]), + sysbus_get_default()); + } } static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp) @@ -258,6 +273,19 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp) sysbus_mmio_map(SYS_BUS_DEVICE(&s->sata), 0, SATA_ADDR); sysbus_connect_irq(SYS_BUS_DEVICE(&s->sata), 0, gic_spi[SATA_INTR]); + + for (i = 0; i < XLNX_ZYNQMP_NUM_SDHCI; i++) { + object_property_set_bool(OBJECT(&s->sdhci[i]), true, + "realized", &err); + if (err) { + error_propagate(errp, err); + return; + } + sysbus_mmio_map(SYS_BUS_DEVICE(&s->sdhci[i]), 0, + sdhci_addr[i]); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->sdhci[i]), 0, + gic_spi[sdhci_intr[i]]); + } } static Property xlnx_zynqmp_props[] = { diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c index 3e230debb8..093e475dc9 100644 --- a/hw/block/virtio-blk.c +++ b/hw/block/virtio-blk.c @@ -798,6 +798,11 @@ static void virtio_blk_set_status(VirtIODevice *vdev, uint8_t status) static void virtio_blk_save(QEMUFile *f, void *opaque) { VirtIODevice *vdev = VIRTIO_DEVICE(opaque); + VirtIOBlock *s = VIRTIO_BLK(vdev); + + if (s->dataplane) { + virtio_blk_data_plane_stop(s->dataplane); + } virtio_save(vdev, f); } @@ -972,7 +977,7 @@ static Property virtio_blk_properties[] = { DEFINE_PROP_STRING("serial", VirtIOBlock, conf.serial), DEFINE_PROP_BIT("config-wce", VirtIOBlock, conf.config_wce, 0, true), #ifdef __linux__ - DEFINE_PROP_BIT("scsi", VirtIOBlock, conf.scsi, 0, true), + DEFINE_PROP_BIT("scsi", VirtIOBlock, conf.scsi, 0, false), #endif DEFINE_PROP_BIT("request-merging", VirtIOBlock, conf.request_merging, 0, true), diff --git a/hw/char/escc.c b/hw/char/escc.c index 9816154206..c9840e11da 100644 --- a/hw/char/escc.c +++ b/hw/char/escc.c @@ -842,13 +842,13 @@ static void sunkbd_handle_event(DeviceState *dev, QemuConsole *src, ChannelState *s = (ChannelState *)dev; int qcode, keycode; - assert(evt->kind == INPUT_EVENT_KIND_KEY); - qcode = qemu_input_key_value_to_qcode(evt->key->key); + assert(evt->type == INPUT_EVENT_KIND_KEY); + qcode = qemu_input_key_value_to_qcode(evt->u.key->key); trace_escc_sunkbd_event_in(qcode, QKeyCode_lookup[qcode], - evt->key->down); + evt->u.key->down); if (qcode == Q_KEY_CODE_CAPS_LOCK) { - if (evt->key->down) { + if (evt->u.key->down) { s->caps_lock_mode ^= 1; if (s->caps_lock_mode == 2) { return; /* Drop second press */ @@ -862,7 +862,7 @@ static void sunkbd_handle_event(DeviceState *dev, QemuConsole *src, } if (qcode == Q_KEY_CODE_NUM_LOCK) { - if (evt->key->down) { + if (evt->u.key->down) { s->num_lock_mode ^= 1; if (s->num_lock_mode == 2) { return; /* Drop second press */ @@ -876,7 +876,7 @@ static void sunkbd_handle_event(DeviceState *dev, QemuConsole *src, } keycode = qcode_to_keycode[qcode]; - if (!evt->key->down) { + if (!evt->u.key->down) { keycode |= 0x80; } trace_escc_sunkbd_event_out(keycode); diff --git a/hw/display/milkymist-tmu2.c b/hw/display/milkymist-tmu2.c index 3e1d0b9c20..e2de281768 100644 --- a/hw/display/milkymist-tmu2.c +++ b/hw/display/milkymist-tmu2.c @@ -30,8 +30,8 @@ #include "qemu/error-report.h" #include <X11/Xlib.h> -#include <GL/gl.h> -#include <GL/glx.h> +#include <epoxy/gl.h> +#include <epoxy/glx.h> enum { R_CTL = 0, diff --git a/hw/input/hid.c b/hw/input/hid.c index 21ebd9e718..e39269fc7a 100644 --- a/hw/input/hid.c +++ b/hw/input/hid.c @@ -119,33 +119,33 @@ static void hid_pointer_event(DeviceState *dev, QemuConsole *src, assert(hs->n < QUEUE_LENGTH); e = &hs->ptr.queue[(hs->head + hs->n) & QUEUE_MASK]; - switch (evt->kind) { + switch (evt->type) { case INPUT_EVENT_KIND_REL: - if (evt->rel->axis == INPUT_AXIS_X) { - e->xdx += evt->rel->value; - } else if (evt->rel->axis == INPUT_AXIS_Y) { - e->ydy += evt->rel->value; + if (evt->u.rel->axis == INPUT_AXIS_X) { + e->xdx += evt->u.rel->value; + } else if (evt->u.rel->axis == INPUT_AXIS_Y) { + e->ydy += evt->u.rel->value; } break; case INPUT_EVENT_KIND_ABS: - if (evt->rel->axis == INPUT_AXIS_X) { - e->xdx = evt->rel->value; - } else if (evt->rel->axis == INPUT_AXIS_Y) { - e->ydy = evt->rel->value; + if (evt->u.rel->axis == INPUT_AXIS_X) { + e->xdx = evt->u.rel->value; + } else if (evt->u.rel->axis == INPUT_AXIS_Y) { + e->ydy = evt->u.rel->value; } break; case INPUT_EVENT_KIND_BTN: - if (evt->btn->down) { - e->buttons_state |= bmap[evt->btn->button]; - if (evt->btn->button == INPUT_BUTTON_WHEEL_UP) { + if (evt->u.btn->down) { + e->buttons_state |= bmap[evt->u.btn->button]; + if (evt->u.btn->button == INPUT_BUTTON_WHEEL_UP) { e->dz--; - } else if (evt->btn->button == INPUT_BUTTON_WHEEL_DOWN) { + } else if (evt->u.btn->button == INPUT_BUTTON_WHEEL_DOWN) { e->dz++; } } else { - e->buttons_state &= ~bmap[evt->btn->button]; + e->buttons_state &= ~bmap[evt->u.btn->button]; } break; @@ -223,8 +223,8 @@ static void hid_keyboard_event(DeviceState *dev, QemuConsole *src, int scancodes[3], i, count; int slot; - count = qemu_input_key_value_to_scancode(evt->key->key, - evt->key->down, + count = qemu_input_key_value_to_scancode(evt->u.key->key, + evt->u.key->down, scancodes); if (hs->n + count > QUEUE_LENGTH) { fprintf(stderr, "usb-kbd: warning: key event queue full\n"); diff --git a/hw/input/ps2.c b/hw/input/ps2.c index fdbe565e62..3d6d4961db 100644 --- a/hw/input/ps2.c +++ b/hw/input/ps2.c @@ -183,8 +183,8 @@ static void ps2_keyboard_event(DeviceState *dev, QemuConsole *src, int scancodes[3], i, count; qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER); - count = qemu_input_key_value_to_scancode(evt->key->key, - evt->key->down, + count = qemu_input_key_value_to_scancode(evt->u.key->key, + evt->u.key->down, scancodes); for (i = 0; i < count; i++) { ps2_put_keycode(s, scancodes[i]); @@ -393,25 +393,25 @@ static void ps2_mouse_event(DeviceState *dev, QemuConsole *src, if (!(s->mouse_status & MOUSE_STATUS_ENABLED)) return; - switch (evt->kind) { + switch (evt->type) { case INPUT_EVENT_KIND_REL: - if (evt->rel->axis == INPUT_AXIS_X) { - s->mouse_dx += evt->rel->value; - } else if (evt->rel->axis == INPUT_AXIS_Y) { - s->mouse_dy -= evt->rel->value; + if (evt->u.rel->axis == INPUT_AXIS_X) { + s->mouse_dx += evt->u.rel->value; + } else if (evt->u.rel->axis == INPUT_AXIS_Y) { + s->mouse_dy -= evt->u.rel->value; } break; case INPUT_EVENT_KIND_BTN: - if (evt->btn->down) { - s->mouse_buttons |= bmap[evt->btn->button]; - if (evt->btn->button == INPUT_BUTTON_WHEEL_UP) { + if (evt->u.btn->down) { + s->mouse_buttons |= bmap[evt->u.btn->button]; + if (evt->u.btn->button == INPUT_BUTTON_WHEEL_UP) { s->mouse_dz--; - } else if (evt->btn->button == INPUT_BUTTON_WHEEL_DOWN) { + } else if (evt->u.btn->button == INPUT_BUTTON_WHEEL_DOWN) { s->mouse_dz++; } } else { - s->mouse_buttons &= ~bmap[evt->btn->button]; + s->mouse_buttons &= ~bmap[evt->u.btn->button]; } break; diff --git a/hw/input/virtio-input-hid.c b/hw/input/virtio-input-hid.c index 4d85dad4d1..bdd479cd0a 100644 --- a/hw/input/virtio-input-hid.c +++ b/hw/input/virtio-input-hid.c @@ -191,44 +191,45 @@ static void virtio_input_handle_event(DeviceState *dev, QemuConsole *src, virtio_input_event event; int qcode; - switch (evt->kind) { + switch (evt->type) { case INPUT_EVENT_KIND_KEY: - qcode = qemu_input_key_value_to_qcode(evt->key->key); + qcode = qemu_input_key_value_to_qcode(evt->u.key->key); if (qcode && keymap_qcode[qcode]) { event.type = cpu_to_le16(EV_KEY); event.code = cpu_to_le16(keymap_qcode[qcode]); - event.value = cpu_to_le32(evt->key->down ? 1 : 0); + event.value = cpu_to_le32(evt->u.key->down ? 1 : 0); virtio_input_send(vinput, &event); } else { - if (evt->key->down) { + if (evt->u.key->down) { fprintf(stderr, "%s: unmapped key: %d [%s]\n", __func__, qcode, QKeyCode_lookup[qcode]); } } break; case INPUT_EVENT_KIND_BTN: - if (keymap_button[evt->btn->button]) { + if (keymap_button[evt->u.btn->button]) { event.type = cpu_to_le16(EV_KEY); - event.code = cpu_to_le16(keymap_button[evt->btn->button]); - event.value = cpu_to_le32(evt->btn->down ? 1 : 0); + event.code = cpu_to_le16(keymap_button[evt->u.btn->button]); + event.value = cpu_to_le32(evt->u.btn->down ? 1 : 0); virtio_input_send(vinput, &event); } else { - if (evt->btn->down) { + if (evt->u.btn->down) { fprintf(stderr, "%s: unmapped button: %d [%s]\n", __func__, - evt->btn->button, InputButton_lookup[evt->btn->button]); + evt->u.btn->button, + InputButton_lookup[evt->u.btn->button]); } } break; case INPUT_EVENT_KIND_REL: event.type = cpu_to_le16(EV_REL); - event.code = cpu_to_le16(axismap_rel[evt->rel->axis]); - event.value = cpu_to_le32(evt->rel->value); + event.code = cpu_to_le16(axismap_rel[evt->u.rel->axis]); + event.value = cpu_to_le32(evt->u.rel->value); virtio_input_send(vinput, &event); break; case INPUT_EVENT_KIND_ABS: event.type = cpu_to_le16(EV_ABS); - event.code = cpu_to_le16(axismap_abs[evt->abs->axis]); - event.value = cpu_to_le32(evt->abs->value); + event.code = cpu_to_le16(axismap_abs[evt->u.abs->axis]); + event.value = cpu_to_le32(evt->u.abs->value); virtio_input_send(vinput, &event); break; default: diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c index 3ec8408618..6fc167e230 100644 --- a/hw/intc/armv7m_nvic.c +++ b/hw/intc/armv7m_nvic.c @@ -28,6 +28,7 @@ typedef struct { MemoryRegion gic_iomem_alias; MemoryRegion container; uint32_t num_irq; + qemu_irq sysresetreq; } nvic_state; #define TYPE_NVIC "armv7m_nvic" @@ -348,10 +349,13 @@ static void nvic_writel(nvic_state *s, uint32_t offset, uint32_t value) break; case 0xd0c: /* Application Interrupt/Reset Control. */ if ((value >> 16) == 0x05fa) { + if (value & 4) { + qemu_irq_pulse(s->sysresetreq); + } if (value & 2) { qemu_log_mask(LOG_UNIMP, "VECTCLRACTIVE unimplemented\n"); } - if (value & 5) { + if (value & 1) { qemu_log_mask(LOG_UNIMP, "AIRCR system reset unimplemented\n"); } if (value & 0x700) { @@ -535,11 +539,14 @@ static void armv7m_nvic_instance_init(Object *obj) * value in the GICState struct. */ GICState *s = ARM_GIC_COMMON(obj); + DeviceState *dev = DEVICE(obj); + nvic_state *nvic = NVIC(obj); /* The ARM v7m may have anything from 0 to 496 external interrupt * IRQ lines. We default to 64. Other boards may differ and should * set the num-irq property appropriately. */ s->num_irq = 64; + qdev_init_gpio_out_named(dev, &nvic->sysresetreq, "SYSRESETREQ", 1); } static void armv7m_nvic_class_init(ObjectClass *klass, void *data) diff --git a/hw/lm32/milkymist-hw.h b/hw/lm32/milkymist-hw.h index 8d20cac1db..c8dfb4d2d4 100644 --- a/hw/lm32/milkymist-hw.h +++ b/hw/lm32/milkymist-hw.h @@ -88,7 +88,8 @@ static inline DeviceState *milkymist_pfpu_create(hwaddr base, #ifdef CONFIG_OPENGL #include <X11/Xlib.h> -#include <GL/glx.h> +#include <epoxy/gl.h> +#include <epoxy/glx.h> static const int glx_fbconfig_attr[] = { GLX_GREEN_SIZE, 5, GLX_GREEN_SIZE, 6, diff --git a/hw/mem/pc-dimm.c b/hw/mem/pc-dimm.c index 80f424b442..d5cdab2707 100644 --- a/hw/mem/pc-dimm.c +++ b/hw/mem/pc-dimm.c @@ -179,7 +179,7 @@ int qmp_pc_dimm_device_list(Object *obj, void *opaque) NULL); di->memdev = object_get_canonical_path(OBJECT(dimm->hostmem)); - info->dimm = di; + info->u.dimm = di; elem->value = info; elem->next = NULL; **prev = elem; @@ -203,9 +203,9 @@ ram_addr_t get_current_ram_size(void) MemoryDeviceInfo *value = info->value; if (value) { - switch (value->kind) { + switch (value->type) { case MEMORY_DEVICE_INFO_KIND_DIMM: - size += value->dimm->size; + size += value->u.dimm->size; break; default: break; diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c index c1f570a79f..91c36baa55 100644 --- a/hw/mips/mips_malta.c +++ b/hw/mips/mips_malta.c @@ -901,7 +901,7 @@ static void main_cpu_reset(void *opaque) if (kvm_enabled()) { /* Start running from the bootloader we wrote to end of RAM */ - env->active_tc.PC = 0x40000000 + loaderparams.ram_size; + env->active_tc.PC = 0x40000000 + loaderparams.ram_low_size; } } diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 288b57e24f..0ed8527969 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -2285,7 +2285,11 @@ static const TypeInfo spapr_machine_info = { }, }; +#define SPAPR_COMPAT_2_4 \ + HW_COMPAT_2_4 + #define SPAPR_COMPAT_2_3 \ + SPAPR_COMPAT_2_4 \ HW_COMPAT_2_3 \ {\ .driver = "spapr-pci-host-bridge",\ @@ -2399,11 +2403,16 @@ static const TypeInfo spapr_machine_2_3_info = { static void spapr_machine_2_4_class_init(ObjectClass *oc, void *data) { + static GlobalProperty compat_props[] = { + SPAPR_COMPAT_2_4 + { /* end of list */ } + }; MachineClass *mc = MACHINE_CLASS(oc); mc->desc = "pSeries Logical Partition (PAPR compliant) v2.4"; mc->alias = "pseries"; mc->is_default = 0; + mc->compat_props = compat_props; } static const TypeInfo spapr_machine_2_4_info = { diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c index faba773592..84221f4f57 100644 --- a/hw/s390x/s390-virtio-ccw.c +++ b/hw/s390x/s390-virtio-ccw.c @@ -20,6 +20,7 @@ #include "qemu/config-file.h" #include "s390-pci-bus.h" #include "hw/s390x/storage-keys.h" +#include "hw/compat.h" #define TYPE_S390_CCW_MACHINE "s390-ccw-machine" @@ -236,6 +237,7 @@ static const TypeInfo ccw_machine_info = { }; #define CCW_COMPAT_2_4 \ + HW_COMPAT_2_4 \ {\ .driver = TYPE_S390_SKEYS,\ .property = "migration-enabled",\ diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c index 46553e1e68..76554011cb 100644 --- a/hw/scsi/virtio-scsi.c +++ b/hw/scsi/virtio-scsi.c @@ -653,6 +653,11 @@ static void virtio_scsi_reset(VirtIODevice *vdev) static void virtio_scsi_save(QEMUFile *f, void *opaque) { VirtIODevice *vdev = VIRTIO_DEVICE(opaque); + VirtIOSCSI *s = VIRTIO_SCSI(vdev); + + if (s->dataplane_started) { + virtio_scsi_dataplane_stop(s); + } virtio_save(vdev, f); } diff --git a/hw/sd/milkymist-memcard.c b/hw/sd/milkymist-memcard.c index 2209ef1d52..b430d56687 100644 --- a/hw/sd/milkymist-memcard.c +++ b/hw/sd/milkymist-memcard.c @@ -28,7 +28,7 @@ #include "qemu/error-report.h" #include "sysemu/block-backend.h" #include "sysemu/blockdev.h" -#include "hw/sd.h" +#include "hw/sd/sd.h" enum { ENABLE_CMD_TX = (1<<0), diff --git a/hw/sd/omap_mmc.c b/hw/sd/omap_mmc.c index 35d8033402..5bc47193f9 100644 --- a/hw/sd/omap_mmc.c +++ b/hw/sd/omap_mmc.c @@ -18,7 +18,7 @@ */ #include "hw/hw.h" #include "hw/arm/omap.h" -#include "hw/sd.h" +#include "hw/sd/sd.h" struct omap_mmc_s { qemu_irq irq; diff --git a/hw/sd/pl181.c b/hw/sd/pl181.c index 5242176a33..326c53ad92 100644 --- a/hw/sd/pl181.c +++ b/hw/sd/pl181.c @@ -10,7 +10,7 @@ #include "sysemu/block-backend.h" #include "sysemu/blockdev.h" #include "hw/sysbus.h" -#include "hw/sd.h" +#include "hw/sd/sd.h" //#define DEBUG_PL181 1 diff --git a/hw/sd/pxa2xx_mmci.c b/hw/sd/pxa2xx_mmci.c index d1fe6d58e8..b217080075 100644 --- a/hw/sd/pxa2xx_mmci.c +++ b/hw/sd/pxa2xx_mmci.c @@ -12,7 +12,7 @@ #include "hw/hw.h" #include "hw/arm/pxa.h" -#include "hw/sd.h" +#include "hw/sd/sd.h" #include "hw/qdev.h" struct PXA2xxMMCIState { diff --git a/hw/sd/sd.c b/hw/sd/sd.c index 393a75c0bc..ce4d44be91 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -31,7 +31,7 @@ #include "hw/hw.h" #include "sysemu/block-backend.h" -#include "hw/sd.h" +#include "hw/sd/sd.h" #include "qemu/bitmap.h" //#define DEBUG_SD 1 diff --git a/hw/sd/sdhci.h b/hw/sd/sdhci-internal.h index e2de92d553..c712daf4ee 100644 --- a/hw/sd/sdhci.h +++ b/hw/sd/sdhci-internal.h @@ -21,15 +21,10 @@ * You should have received a copy of the GNU General Public License along * with this program; if not, see <http://www.gnu.org/licenses/>. */ +#ifndef SDHCI_INTERNAL_H +#define SDHCI_INTERNAL_H -#ifndef SDHCI_H -#define SDHCI_H - -#include "qemu-common.h" -#include "hw/block/block.h" -#include "hw/pci/pci.h" -#include "hw/sysbus.h" -#include "hw/sd.h" +#include "hw/sd/sdhci.h" /* R/W SDMA System Address register 0x0 */ #define SDHC_SYSAD 0x00 @@ -232,66 +227,6 @@ enum { sdhc_gap_write = 2 /* SDHC stopped at block gap during write operation */ }; -/* SD/MMC host controller state */ -typedef struct SDHCIState { - union { - PCIDevice pcidev; - SysBusDevice busdev; - }; - SDState *card; - MemoryRegion iomem; - BlockConf conf; - - QEMUTimer *insert_timer; /* timer for 'changing' sd card. */ - QEMUTimer *transfer_timer; - qemu_irq eject_cb; - qemu_irq ro_cb; - qemu_irq irq; - - uint32_t sdmasysad; /* SDMA System Address register */ - uint16_t blksize; /* Host DMA Buff Boundary and Transfer BlkSize Reg */ - uint16_t blkcnt; /* Blocks count for current transfer */ - uint32_t argument; /* Command Argument Register */ - uint16_t trnmod; /* Transfer Mode Setting Register */ - uint16_t cmdreg; /* Command Register */ - uint32_t rspreg[4]; /* Response Registers 0-3 */ - uint32_t prnsts; /* Present State Register */ - uint8_t hostctl; /* Host Control Register */ - uint8_t pwrcon; /* Power control Register */ - uint8_t blkgap; /* Block Gap Control Register */ - uint8_t wakcon; /* WakeUp Control Register */ - uint16_t clkcon; /* Clock control Register */ - uint8_t timeoutcon; /* Timeout Control Register */ - uint8_t admaerr; /* ADMA Error Status Register */ - uint16_t norintsts; /* Normal Interrupt Status Register */ - uint16_t errintsts; /* Error Interrupt Status Register */ - uint16_t norintstsen; /* Normal Interrupt Status Enable Register */ - uint16_t errintstsen; /* Error Interrupt Status Enable Register */ - uint16_t norintsigen; /* Normal Interrupt Signal Enable Register */ - uint16_t errintsigen; /* Error Interrupt Signal Enable Register */ - uint16_t acmd12errsts; /* Auto CMD12 error status register */ - uint64_t admasysaddr; /* ADMA System Address Register */ - - uint32_t capareg; /* Capabilities Register */ - uint32_t maxcurr; /* Maximum Current Capabilities Register */ - uint8_t *fifo_buffer; /* SD host i/o FIFO buffer */ - uint32_t buf_maxsz; - uint16_t data_count; /* current element in FIFO buffer */ - uint8_t stopped_state;/* Current SDHC state */ - /* Buffer Data Port Register - virtual access point to R and W buffers */ - /* Software Reset Register - always reads as 0 */ - /* Force Event Auto CMD12 Error Interrupt Reg - write only */ - /* Force Event Error Interrupt Register- write only */ - /* RO Host Controller Version Register always reads as 0x2401 */ -} SDHCIState; - extern const VMStateDescription sdhci_vmstate; -#define TYPE_PCI_SDHCI "sdhci-pci" -#define PCI_SDHCI(obj) OBJECT_CHECK(SDHCIState, (obj), TYPE_PCI_SDHCI) - -#define TYPE_SYSBUS_SDHCI "generic-sdhci" -#define SYSBUS_SDHCI(obj) \ - OBJECT_CHECK(SDHCIState, (obj), TYPE_SYSBUS_SDHCI) - -#endif /* SDHCI_H */ +#endif diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c index 7f73527d44..d70d1a6ab9 100644 --- a/hw/sd/sdhci.c +++ b/hw/sd/sdhci.c @@ -29,8 +29,7 @@ #include "sysemu/dma.h" #include "qemu/timer.h" #include "qemu/bitops.h" - -#include "sdhci.h" +#include "sdhci-internal.h" /* host controller debug messages */ #ifndef SDHC_DEBUG diff --git a/hw/sd/ssi-sd.c b/hw/sd/ssi-sd.c index e4b2d4f83b..c49ff62f56 100644 --- a/hw/sd/ssi-sd.c +++ b/hw/sd/ssi-sd.c @@ -13,7 +13,7 @@ #include "sysemu/block-backend.h" #include "sysemu/blockdev.h" #include "hw/ssi.h" -#include "hw/sd.h" +#include "hw/sd/sd.h" //#define DEBUG_SSI_SD 1 diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index 64a54c6e84..4e2161b5a7 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -726,7 +726,7 @@ static void ehci_detach(USBPort *port) ehci_queues_rip_device(s, port->dev, 0); ehci_queues_rip_device(s, port->dev, 1); - *portsc &= ~(PORTSC_CONNECT|PORTSC_PED); + *portsc &= ~(PORTSC_CONNECT|PORTSC_PED|PORTSC_SUSPEND); *portsc |= PORTSC_CSC; ehci_raise_irq(s, USBSTS_PCD); diff --git a/hw/usb/host-libusb.c b/hw/usb/host-libusb.c index 7695a97143..3f8e540bd2 100644 --- a/hw/usb/host-libusb.c +++ b/hw/usb/host-libusb.c @@ -1240,7 +1240,7 @@ static void usb_host_handle_control(USBDevice *udev, USBPacket *p, /* Fix up USB-3 ep0 maxpacket size to allow superspeed connected devices * to work redirected to a not superspeed capable hcd */ - if (udev->speed == USB_SPEED_SUPER && + if ((udev->speedmask & USB_SPEED_MASK_SUPER) && !(udev->port->speedmask & USB_SPEED_MASK_SUPER) && request == 0x8006 && value == 0x100 && index == 0) { r->usb3ep0quirk = true; diff --git a/include/glib-compat.h b/include/glib-compat.h index fb25f437b4..03d8b12675 100644 --- a/include/glib-compat.h +++ b/include/glib-compat.h @@ -165,6 +165,14 @@ static inline GThread *g_thread_new(const char *name, #define CompatGCond GCond #endif /* glib 2.31 */ +#if !GLIB_CHECK_VERSION(2, 32, 0) +/* Beware, function returns gboolean since 2.39.2, see GLib commit 9101915 */ +static inline void g_hash_table_add(GHashTable *hash_table, gpointer key) +{ + g_hash_table_replace(hash_table, key, key); +} +#endif + #ifndef g_assert_true #define g_assert_true(expr) \ do { \ diff --git a/include/hw/arm/arm.h b/include/hw/arm/arm.h index 4dcd4f9b63..67ba7db3bb 100644 --- a/include/hw/arm/arm.h +++ b/include/hw/arm/arm.h @@ -17,7 +17,7 @@ #include "cpu.h" /* armv7m.c */ -qemu_irq *armv7m_init(MemoryRegion *system_memory, int mem_size, int num_irq, +DeviceState *armv7m_init(MemoryRegion *system_memory, int mem_size, int num_irq, const char *kernel_filename, const char *cpu_model); /* @@ -87,6 +87,16 @@ struct arm_boot_info { * -pflash. It also implies that fw_cfg_find() will succeed. */ bool firmware_loaded; + + /* Address at which board specific loader/setup code exists. If enabled, + * this code-blob will run before anything else. It must return to the + * caller via the link register. There is no stack set up. Enabled by + * defining write_board_setup, which is responsible for loading the blob + * to the specified address. + */ + hwaddr board_setup_addr; + void (*write_board_setup)(ARMCPU *cpu, + const struct arm_boot_info *info); }; /** diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h index 4005a9960b..d1160920cc 100644 --- a/include/hw/arm/xlnx-zynqmp.h +++ b/include/hw/arm/xlnx-zynqmp.h @@ -24,6 +24,7 @@ #include "hw/char/cadence_uart.h" #include "hw/ide/pci.h" #include "hw/ide/ahci.h" +#include "hw/sd/sdhci.h" #define TYPE_XLNX_ZYNQMP "xlnx,zynqmp" #define XLNX_ZYNQMP(obj) OBJECT_CHECK(XlnxZynqMPState, (obj), \ @@ -33,6 +34,7 @@ #define XLNX_ZYNQMP_NUM_RPU_CPUS 2 #define XLNX_ZYNQMP_NUM_GEMS 4 #define XLNX_ZYNQMP_NUM_UARTS 2 +#define XLNX_ZYNQMP_NUM_SDHCI 2 #define XLNX_ZYNQMP_NUM_OCM_BANKS 4 #define XLNX_ZYNQMP_OCM_RAM_0_ADDRESS 0xFFFC0000 @@ -63,6 +65,7 @@ typedef struct XlnxZynqMPState { CadenceGEMState gem[XLNX_ZYNQMP_NUM_GEMS]; CadenceUARTState uart[XLNX_ZYNQMP_NUM_UARTS]; SysbusAHCIState sata; + SDHCIState sdhci[XLNX_ZYNQMP_NUM_SDHCI]; char *boot_cpu; ARMCPU *boot_cpu_ptr; diff --git a/include/hw/compat.h b/include/hw/compat.h index 095de5d12f..93e71afb4a 100644 --- a/include/hw/compat.h +++ b/include/hw/compat.h @@ -2,7 +2,11 @@ #define HW_COMPAT_H #define HW_COMPAT_2_4 \ - /* empty */ + {\ + .driver = "virtio-blk-device",\ + .property = "scsi",\ + .value = "true",\ + }, #define HW_COMPAT_2_3 \ {\ diff --git a/include/hw/sd.h b/include/hw/sd/sd.h index 79adb5bb48..79adb5bb48 100644 --- a/include/hw/sd.h +++ b/include/hw/sd/sd.h diff --git a/include/hw/sd/sdhci.h b/include/hw/sd/sdhci.h new file mode 100644 index 0000000000..9b3031fb81 --- /dev/null +++ b/include/hw/sd/sdhci.h @@ -0,0 +1,94 @@ +/* + * SD Association Host Standard Specification v2.0 controller emulation + * + * Copyright (c) 2011 Samsung Electronics Co., Ltd. + * Mitsyanko Igor <i.mitsyanko@samsung.com> + * Peter A.G. Crosthwaite <peter.crosthwaite@petalogix.com> + * + * Based on MMC controller for Samsung S5PC1xx-based board emulation + * by Alexey Merkulov and Vladimir Monakhov. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU _General Public License along + * with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef SDHCI_H +#define SDHCI_H + +#include "qemu-common.h" +#include "hw/block/block.h" +#include "hw/pci/pci.h" +#include "hw/sysbus.h" +#include "hw/sd/sd.h" + +/* SD/MMC host controller state */ +typedef struct SDHCIState { + union { + PCIDevice pcidev; + SysBusDevice busdev; + }; + SDState *card; + MemoryRegion iomem; + BlockConf conf; + + QEMUTimer *insert_timer; /* timer for 'changing' sd card. */ + QEMUTimer *transfer_timer; + qemu_irq eject_cb; + qemu_irq ro_cb; + qemu_irq irq; + + uint32_t sdmasysad; /* SDMA System Address register */ + uint16_t blksize; /* Host DMA Buff Boundary and Transfer BlkSize Reg */ + uint16_t blkcnt; /* Blocks count for current transfer */ + uint32_t argument; /* Command Argument Register */ + uint16_t trnmod; /* Transfer Mode Setting Register */ + uint16_t cmdreg; /* Command Register */ + uint32_t rspreg[4]; /* Response Registers 0-3 */ + uint32_t prnsts; /* Present State Register */ + uint8_t hostctl; /* Host Control Register */ + uint8_t pwrcon; /* Power control Register */ + uint8_t blkgap; /* Block Gap Control Register */ + uint8_t wakcon; /* WakeUp Control Register */ + uint16_t clkcon; /* Clock control Register */ + uint8_t timeoutcon; /* Timeout Control Register */ + uint8_t admaerr; /* ADMA Error Status Register */ + uint16_t norintsts; /* Normal Interrupt Status Register */ + uint16_t errintsts; /* Error Interrupt Status Register */ + uint16_t norintstsen; /* Normal Interrupt Status Enable Register */ + uint16_t errintstsen; /* Error Interrupt Status Enable Register */ + uint16_t norintsigen; /* Normal Interrupt Signal Enable Register */ + uint16_t errintsigen; /* Error Interrupt Signal Enable Register */ + uint16_t acmd12errsts; /* Auto CMD12 error status register */ + uint64_t admasysaddr; /* ADMA System Address Register */ + + uint32_t capareg; /* Capabilities Register */ + uint32_t maxcurr; /* Maximum Current Capabilities Register */ + uint8_t *fifo_buffer; /* SD host i/o FIFO buffer */ + uint32_t buf_maxsz; + uint16_t data_count; /* current element in FIFO buffer */ + uint8_t stopped_state;/* Current SDHC state */ + /* Buffer Data Port Register - virtual access point to R and W buffers */ + /* Software Reset Register - always reads as 0 */ + /* Force Event Auto CMD12 Error Interrupt Reg - write only */ + /* Force Event Error Interrupt Register- write only */ + /* RO Host Controller Version Register always reads as 0x2401 */ +} SDHCIState; + +#define TYPE_PCI_SDHCI "sdhci-pci" +#define PCI_SDHCI(obj) OBJECT_CHECK(SDHCIState, (obj), TYPE_PCI_SDHCI) + +#define TYPE_SYSBUS_SDHCI "generic-sdhci" +#define SYSBUS_SDHCI(obj) \ + OBJECT_CHECK(SDHCIState, (obj), TYPE_SYSBUS_SDHCI) + +#endif /* SDHCI_H */ diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h index 9a65522da1..d173b565f5 100644 --- a/include/migration/vmstate.h +++ b/include/migration/vmstate.h @@ -39,7 +39,7 @@ typedef struct SaveVMHandlers { void (*set_params)(const MigrationParams *params, void * opaque); SaveStateHandler *save_state; - void (*cancel)(void *opaque); + void (*cleanup)(void *opaque); int (*save_live_complete)(QEMUFile *f, void *opaque); /* This runs both outside and inside the iothread lock. */ diff --git a/include/qapi/qmp/qbool.h b/include/qapi/qmp/qbool.h index 4aa6be3b33..d9256e4268 100644 --- a/include/qapi/qmp/qbool.h +++ b/include/qapi/qmp/qbool.h @@ -18,7 +18,7 @@ #include "qapi/qmp/qobject.h" typedef struct QBool { - QObject_HEAD; + QObject base; bool value; } QBool; diff --git a/include/qapi/qmp/qdict.h b/include/qapi/qmp/qdict.h index a37f4c1567..787c658967 100644 --- a/include/qapi/qmp/qdict.h +++ b/include/qapi/qmp/qdict.h @@ -28,7 +28,7 @@ typedef struct QDictEntry { } QDictEntry; typedef struct QDict { - QObject_HEAD; + QObject base; size_t size; QLIST_HEAD(,QDictEntry) table[QDICT_BUCKET_MAX]; } QDict; diff --git a/include/qapi/qmp/qfloat.h b/include/qapi/qmp/qfloat.h index a8658443dc..46745e50d1 100644 --- a/include/qapi/qmp/qfloat.h +++ b/include/qapi/qmp/qfloat.h @@ -18,7 +18,7 @@ #include "qapi/qmp/qobject.h" typedef struct QFloat { - QObject_HEAD; + QObject base; double value; } QFloat; diff --git a/include/qapi/qmp/qint.h b/include/qapi/qmp/qint.h index 48a41b0f2a..339a9abb8f 100644 --- a/include/qapi/qmp/qint.h +++ b/include/qapi/qmp/qint.h @@ -17,7 +17,7 @@ #include "qapi/qmp/qobject.h" typedef struct QInt { - QObject_HEAD; + QObject base; int64_t value; } QInt; diff --git a/include/qapi/qmp/qlist.h b/include/qapi/qmp/qlist.h index 6cc4831df3..b1bf7852c5 100644 --- a/include/qapi/qmp/qlist.h +++ b/include/qapi/qmp/qlist.h @@ -22,7 +22,7 @@ typedef struct QListEntry { } QListEntry; typedef struct QList { - QObject_HEAD; + QObject base; QTAILQ_HEAD(,QListEntry) head; } QList; diff --git a/include/qapi/qmp/qobject.h b/include/qapi/qmp/qobject.h index 260d2ed3cc..c856f553b7 100644 --- a/include/qapi/qmp/qobject.h +++ b/include/qapi/qmp/qobject.h @@ -59,10 +59,6 @@ typedef struct QObject { size_t refcnt; } QObject; -/* Objects definitions must include this */ -#define QObject_HEAD \ - QObject base - /* Get the 'base' part of an object */ #define QOBJECT(obj) (&(obj)->base) diff --git a/include/qapi/qmp/qstring.h b/include/qapi/qmp/qstring.h index 1bc3666107..34675a7fc0 100644 --- a/include/qapi/qmp/qstring.h +++ b/include/qapi/qmp/qstring.h @@ -17,7 +17,7 @@ #include "qapi/qmp/qobject.h" typedef struct QString { - QObject_HEAD; + QObject base; char *string; size_t length; size_t capacity; diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h index c439975139..5cb0f05068 100644 --- a/include/sysemu/sysemu.h +++ b/include/sysemu/sysemu.h @@ -89,7 +89,7 @@ void qemu_savevm_state_begin(QEMUFile *f, void qemu_savevm_state_header(QEMUFile *f); int qemu_savevm_state_iterate(QEMUFile *f); void qemu_savevm_state_complete(QEMUFile *f); -void qemu_savevm_state_cancel(void); +void qemu_savevm_state_cleanup(void); uint64_t qemu_savevm_state_pending(QEMUFile *f, uint64_t max_size); int qemu_loadvm_state(QEMUFile *f); diff --git a/include/ui/console.h b/include/ui/console.h index d887f911f3..c249db4f7c 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -321,13 +321,23 @@ static inline pixman_format_code_t surface_format(DisplaySurface *s) #ifdef CONFIG_CURSES #include <curses.h> typedef chtype console_ch_t; +extern chtype vga_to_curses[]; #else typedef unsigned long console_ch_t; #endif static inline void console_write_ch(console_ch_t *dest, uint32_t ch) { - if (!(ch & 0xff)) + uint8_t c = ch; +#ifdef CONFIG_CURSES + if (vga_to_curses[c]) { + ch &= ~(console_ch_t)0xff; + ch |= vga_to_curses[c]; + } +#else + if (c == '\0') { ch |= ' '; + } +#endif *dest = ch; } diff --git a/migration/block.c b/migration/block.c index f7bb1e0126..cf9d9f8999 100644 --- a/migration/block.c +++ b/migration/block.c @@ -591,7 +591,7 @@ static int64_t get_remaining_dirty(void) /* Called with iothread lock taken. */ -static void blk_mig_cleanup(void) +static void block_migration_cleanup(void *opaque) { BlkMigDevState *bmds; BlkMigBlock *blk; @@ -618,11 +618,6 @@ static void blk_mig_cleanup(void) blk_mig_unlock(); } -static void block_migration_cancel(void *opaque) -{ - blk_mig_cleanup(); -} - static int block_save_setup(QEMUFile *f, void *opaque) { int ret; @@ -750,7 +745,6 @@ static int block_save_complete(QEMUFile *f, void *opaque) qemu_put_be64(f, BLK_MIG_FLAG_EOS); - blk_mig_cleanup(); return 0; } @@ -885,7 +879,7 @@ static SaveVMHandlers savevm_block_handlers = { .save_live_complete = block_save_complete, .save_live_pending = block_save_pending, .load_state = block_load, - .cancel = block_migration_cancel, + .cleanup = block_migration_cleanup, .is_active = block_is_active, }; diff --git a/migration/migration.c b/migration/migration.c index b092f386b4..f99d3eabf7 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -613,12 +613,9 @@ static void migrate_fd_cleanup(void *opaque) assert(s->state != MIGRATION_STATUS_ACTIVE); - if (s->state != MIGRATION_STATUS_COMPLETED) { - qemu_savevm_state_cancel(); - if (s->state == MIGRATION_STATUS_CANCELLING) { - migrate_set_state(s, MIGRATION_STATUS_CANCELLING, - MIGRATION_STATUS_CANCELLED); - } + if (s->state == MIGRATION_STATUS_CANCELLING) { + migrate_set_state(s, MIGRATION_STATUS_CANCELLING, + MIGRATION_STATUS_CANCELLED); } notifier_list_notify(&migration_state_notifiers, s); @@ -1028,6 +1025,7 @@ static void *migration_thread(void *opaque) int64_t initial_bytes = 0; int64_t max_size = 0; int64_t start_time = initial_time; + int64_t end_time; bool old_vm_running = false; rcu_register_thread(); @@ -1089,10 +1087,11 @@ static void *migration_thread(void *opaque) /* If we enabled cpu throttling for auto-converge, turn it off. */ cpu_throttle_stop(); + end_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME); qemu_mutex_lock_iothread(); + qemu_savevm_state_cleanup(); if (s->state == MIGRATION_STATUS_COMPLETED) { - int64_t end_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME); uint64_t transferred_bytes = qemu_ftell(s->file); s->total_time = end_time - s->total_time; s->downtime = end_time - start_time; diff --git a/migration/ram.c b/migration/ram.c index a25bcc7db1..df3df9e3bf 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -1100,7 +1100,7 @@ static void migration_bitmap_free(struct BitmapRcu *bmap) g_free(bmap); } -static void migration_end(void) +static void ram_migration_cleanup(void *opaque) { /* caller have hold iothread lock or is in a bh, so there is * no writing race against this migration_bitmap @@ -1124,11 +1124,6 @@ static void migration_end(void) XBZRLE_cache_unlock(); } -static void ram_migration_cancel(void *opaque) -{ - migration_end(); -} - static void reset_ram_globals(void) { last_seen_block = NULL; @@ -1344,7 +1339,6 @@ static int ram_save_complete(QEMUFile *f, void *opaque) rcu_read_unlock(); - migration_end(); qemu_put_be64(f, RAM_SAVE_FLAG_EOS); return 0; @@ -1686,7 +1680,7 @@ static SaveVMHandlers savevm_ram_handlers = { .save_live_complete = ram_save_complete, .save_live_pending = ram_save_pending, .load_state = ram_load, - .cancel = ram_migration_cancel, + .cleanup = ram_migration_cleanup, }; void ram_mig_init(void) diff --git a/migration/savevm.c b/migration/savevm.c index dbcc39a617..e05158d7ba 100644 --- a/migration/savevm.c +++ b/migration/savevm.c @@ -902,14 +902,14 @@ uint64_t qemu_savevm_state_pending(QEMUFile *f, uint64_t max_size) return ret; } -void qemu_savevm_state_cancel(void) +void qemu_savevm_state_cleanup(void) { SaveStateEntry *se; - trace_savevm_state_cancel(); + trace_savevm_state_cleanup(); QTAILQ_FOREACH(se, &savevm_state.handlers, entry) { - if (se->ops && se->ops->cancel) { - se->ops->cancel(se->opaque); + if (se->ops && se->ops->cleanup) { + se->ops->cleanup(se->opaque); } } } @@ -943,7 +943,7 @@ static int qemu_savevm_state(QEMUFile *f, Error **errp) ret = qemu_file_get_error(f); } if (ret != 0) { - qemu_savevm_state_cancel(); + qemu_savevm_state_cleanup(); error_setg_errno(errp, -ret, "Error while writing VM state"); } return ret; @@ -181,13 +181,16 @@ typedef struct { * instance. */ typedef struct MonitorQAPIEventState { - QAPIEvent event; /* Event being tracked */ - int64_t rate; /* Minimum time (in ns) between two events */ - int64_t last; /* QEMU_CLOCK_REALTIME value at last emission */ + QAPIEvent event; /* Throttling state for this event type and... */ + QDict *data; /* ... data, see qapi_event_throttle_equal() */ QEMUTimer *timer; /* Timer for handling delayed events */ - QObject *data; /* Event pending delayed dispatch */ + QDict *qdict; /* Delayed event (if any) */ } MonitorQAPIEventState; +typedef struct { + int64_t rate; /* Minimum time (in ns) between two events */ +} MonitorQAPIEventConf; + struct Monitor { CharDriverState *chr; int reset_seen; @@ -438,132 +441,161 @@ static void monitor_protocol_emitter(Monitor *mon, QObject *data, } -static MonitorQAPIEventState monitor_qapi_event_state[QAPI_EVENT_MAX]; +static MonitorQAPIEventConf monitor_qapi_event_conf[QAPI_EVENT_MAX] = { + /* Limit guest-triggerable events to 1 per second */ + [QAPI_EVENT_RTC_CHANGE] = { 1000 * SCALE_MS }, + [QAPI_EVENT_WATCHDOG] = { 1000 * SCALE_MS }, + [QAPI_EVENT_BALLOON_CHANGE] = { 1000 * SCALE_MS }, + [QAPI_EVENT_QUORUM_REPORT_BAD] = { 1000 * SCALE_MS }, + [QAPI_EVENT_QUORUM_FAILURE] = { 1000 * SCALE_MS }, + [QAPI_EVENT_VSERPORT_CHANGE] = { 1000 * SCALE_MS }, +}; + +GHashTable *monitor_qapi_event_state; /* * Emits the event to every monitor instance, @event is only used for trace * Called with monitor_lock held. */ -static void monitor_qapi_event_emit(QAPIEvent event, QObject *data) +static void monitor_qapi_event_emit(QAPIEvent event, QDict *qdict) { Monitor *mon; - trace_monitor_protocol_event_emit(event, data); + trace_monitor_protocol_event_emit(event, qdict); QLIST_FOREACH(mon, &mon_list, entry) { if (monitor_is_qmp(mon) && mon->qmp.in_command_mode) { - monitor_json_emitter(mon, data); + monitor_json_emitter(mon, QOBJECT(qdict)); } } } +static void monitor_qapi_event_handler(void *opaque); + /* * Queue a new event for emission to Monitor instances, * applying any rate limiting if required. */ static void -monitor_qapi_event_queue(QAPIEvent event, QDict *data, Error **errp) +monitor_qapi_event_queue(QAPIEvent event, QDict *qdict, Error **errp) { + MonitorQAPIEventConf *evconf; MonitorQAPIEventState *evstate; - assert(event < QAPI_EVENT_MAX); - int64_t now = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); - evstate = &(monitor_qapi_event_state[event]); - trace_monitor_protocol_event_queue(event, - data, - evstate->rate, - evstate->last, - now); + assert(event < QAPI_EVENT_MAX); + evconf = &monitor_qapi_event_conf[event]; + trace_monitor_protocol_event_queue(event, qdict, evconf->rate); - /* Rate limit of 0 indicates no throttling */ qemu_mutex_lock(&monitor_lock); - if (!evstate->rate) { - monitor_qapi_event_emit(event, QOBJECT(data)); - evstate->last = now; + + if (!evconf->rate) { + /* Unthrottled event */ + monitor_qapi_event_emit(event, qdict); } else { - int64_t delta = now - evstate->last; - if (evstate->data || - delta < evstate->rate) { - /* If there's an existing event pending, replace - * it with the new event, otherwise schedule a - * timer for delayed emission + QDict *data = qobject_to_qdict(qdict_get(qdict, "data")); + MonitorQAPIEventState key = { .event = event, .data = data }; + + evstate = g_hash_table_lookup(monitor_qapi_event_state, &key); + assert(!evstate || timer_pending(evstate->timer)); + + if (evstate) { + /* + * Timer is pending for (at least) evconf->rate ns after + * last send. Store event for sending when timer fires, + * replacing a prior stored event if any. */ - if (evstate->data) { - qobject_decref(evstate->data); - } else { - int64_t then = evstate->last + evstate->rate; - timer_mod_ns(evstate->timer, then); - } - evstate->data = QOBJECT(data); - qobject_incref(evstate->data); + QDECREF(evstate->qdict); + evstate->qdict = qdict; + QINCREF(evstate->qdict); } else { - monitor_qapi_event_emit(event, QOBJECT(data)); - evstate->last = now; + /* + * Last send was (at least) evconf->rate ns ago. + * Send immediately, and arm the timer to call + * monitor_qapi_event_handler() in evconf->rate ns. Any + * events arriving before then will be delayed until then. + */ + int64_t now = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); + + monitor_qapi_event_emit(event, qdict); + + evstate = g_new(MonitorQAPIEventState, 1); + evstate->event = event; + evstate->data = data; + QINCREF(evstate->data); + evstate->qdict = NULL; + evstate->timer = timer_new_ns(QEMU_CLOCK_REALTIME, + monitor_qapi_event_handler, + evstate); + g_hash_table_add(monitor_qapi_event_state, evstate); + timer_mod_ns(evstate->timer, now + evconf->rate); } } + qemu_mutex_unlock(&monitor_lock); } /* - * The callback invoked by QemuTimer when a delayed - * event is ready to be emitted + * This function runs evconf->rate ns after sending a throttled + * event. + * If another event has since been stored, send it. */ static void monitor_qapi_event_handler(void *opaque) { MonitorQAPIEventState *evstate = opaque; - int64_t now = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); + MonitorQAPIEventConf *evconf = &monitor_qapi_event_conf[evstate->event]; - trace_monitor_protocol_event_handler(evstate->event, - evstate->data, - evstate->last, - now); + trace_monitor_protocol_event_handler(evstate->event, evstate->qdict); qemu_mutex_lock(&monitor_lock); - if (evstate->data) { - monitor_qapi_event_emit(evstate->event, evstate->data); - qobject_decref(evstate->data); - evstate->data = NULL; + + if (evstate->qdict) { + int64_t now = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); + + monitor_qapi_event_emit(evstate->event, evstate->qdict); + QDECREF(evstate->qdict); + evstate->qdict = NULL; + timer_mod_ns(evstate->timer, now + evconf->rate); + } else { + g_hash_table_remove(monitor_qapi_event_state, evstate); + QDECREF(evstate->data); + timer_free(evstate->timer); + g_free(evstate); } - evstate->last = now; + qemu_mutex_unlock(&monitor_lock); } -/* - * @event: the event ID to be limited - * @rate: the rate limit in milliseconds - * - * Sets a rate limit on a particular event, so no - * more than 1 event will be emitted within @rate - * milliseconds - */ -static void -monitor_qapi_event_throttle(QAPIEvent event, int64_t rate) +static unsigned int qapi_event_throttle_hash(const void *key) { - MonitorQAPIEventState *evstate; - assert(event < QAPI_EVENT_MAX); + const MonitorQAPIEventState *evstate = key; + unsigned int hash = evstate->event * 255; + + if (evstate->event == QAPI_EVENT_VSERPORT_CHANGE) { + hash += g_str_hash(qdict_get_str(evstate->data, "id")); + } + + return hash; +} + +static gboolean qapi_event_throttle_equal(const void *a, const void *b) +{ + const MonitorQAPIEventState *eva = a; + const MonitorQAPIEventState *evb = b; - evstate = &(monitor_qapi_event_state[event]); + if (eva->event != evb->event) { + return FALSE; + } + + if (eva->event == QAPI_EVENT_VSERPORT_CHANGE) { + return !strcmp(qdict_get_str(eva->data, "id"), + qdict_get_str(evb->data, "id")); + } - trace_monitor_protocol_event_throttle(event, rate); - evstate->event = event; - assert(rate * SCALE_MS <= INT64_MAX); - evstate->rate = rate * SCALE_MS; - evstate->last = 0; - evstate->data = NULL; - evstate->timer = timer_new(QEMU_CLOCK_REALTIME, - SCALE_MS, - monitor_qapi_event_handler, - evstate); + return TRUE; } static void monitor_qapi_event_init(void) { - /* Limit guest-triggerable events to 1 per second */ - monitor_qapi_event_throttle(QAPI_EVENT_RTC_CHANGE, 1000); - monitor_qapi_event_throttle(QAPI_EVENT_WATCHDOG, 1000); - monitor_qapi_event_throttle(QAPI_EVENT_BALLOON_CHANGE, 1000); - monitor_qapi_event_throttle(QAPI_EVENT_QUORUM_REPORT_BAD, 1000); - monitor_qapi_event_throttle(QAPI_EVENT_QUORUM_FAILURE, 1000); - monitor_qapi_event_throttle(QAPI_EVENT_VSERPORT_CHANGE, 1000); - + monitor_qapi_event_state = g_hash_table_new(qapi_event_throttle_hash, + qapi_event_throttle_equal); qmp_event_set_func_emit(monitor_qapi_event_queue); } diff --git a/net/dump.c b/net/dump.c index dd0555f8bd..ce16a4b0e3 100644 --- a/net/dump.c +++ b/net/dump.c @@ -187,8 +187,8 @@ int net_init_dump(const NetClientOptions *opts, const char *name, NetClientState *nc; DumpNetClient *dnc; - assert(opts->kind == NET_CLIENT_OPTIONS_KIND_DUMP); - dump = opts->dump; + assert(opts->type == NET_CLIENT_OPTIONS_KIND_DUMP); + dump = opts->u.dump; assert(peer); @@ -285,9 +285,9 @@ int net_init_hubport(const NetClientOptions *opts, const char *name, { const NetdevHubPortOptions *hubport; - assert(opts->kind == NET_CLIENT_OPTIONS_KIND_HUBPORT); + assert(opts->type == NET_CLIENT_OPTIONS_KIND_HUBPORT); assert(!peer); - hubport = opts->hubport; + hubport = opts->u.hubport; net_hub_add_port(hubport->hubid, name); return 0; diff --git a/net/l2tpv3.c b/net/l2tpv3.c index 4f9bceecc9..8e68e540ec 100644 --- a/net/l2tpv3.c +++ b/net/l2tpv3.c @@ -545,8 +545,8 @@ int net_init_l2tpv3(const NetClientOptions *opts, s->queue_tail = 0; s->header_mismatch = false; - assert(opts->kind == NET_CLIENT_OPTIONS_KIND_L2TPV3); - l2tpv3 = opts->l2tpv3; + assert(opts->type == NET_CLIENT_OPTIONS_KIND_L2TPV3); + l2tpv3 = opts->u.l2tpv3; if (l2tpv3->has_ipv6 && l2tpv3->ipv6) { s->ipv6 = l2tpv3->ipv6; @@ -882,8 +882,8 @@ static int net_init_nic(const NetClientOptions *opts, const char *name, NICInfo *nd; const NetLegacyNicOptions *nic; - assert(opts->kind == NET_CLIENT_OPTIONS_KIND_NIC); - nic = opts->nic; + assert(opts->type == NET_CLIENT_OPTIONS_KIND_NIC); + nic = opts->u.nic; idx = nic_get_free_idx(); if (idx == -1 || nb_nics >= MAX_NICS) { @@ -984,9 +984,9 @@ static int net_client_init1(const void *object, int is_netdev, Error **errp) opts = netdev->opts; name = netdev->id; - if (opts->kind == NET_CLIENT_OPTIONS_KIND_DUMP || - opts->kind == NET_CLIENT_OPTIONS_KIND_NIC || - !net_client_init_fun[opts->kind]) { + if (opts->type == NET_CLIENT_OPTIONS_KIND_DUMP || + opts->type == NET_CLIENT_OPTIONS_KIND_NIC || + !net_client_init_fun[opts->type]) { error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "type", "a netdev backend type"); return -1; @@ -997,16 +997,16 @@ static int net_client_init1(const void *object, int is_netdev, Error **errp) /* missing optional values have been initialized to "all bits zero" */ name = net->has_id ? net->id : net->name; - if (opts->kind == NET_CLIENT_OPTIONS_KIND_NONE) { + if (opts->type == NET_CLIENT_OPTIONS_KIND_NONE) { return 0; /* nothing to do */ } - if (opts->kind == NET_CLIENT_OPTIONS_KIND_HUBPORT) { + if (opts->type == NET_CLIENT_OPTIONS_KIND_HUBPORT) { error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "type", "a net type"); return -1; } - if (!net_client_init_fun[opts->kind]) { + if (!net_client_init_fun[opts->type]) { error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "type", "a net backend type (maybe it is not compiled " "into this binary)"); @@ -1014,17 +1014,17 @@ static int net_client_init1(const void *object, int is_netdev, Error **errp) } /* Do not add to a vlan if it's a nic with a netdev= parameter. */ - if (opts->kind != NET_CLIENT_OPTIONS_KIND_NIC || - !opts->nic->has_netdev) { + if (opts->type != NET_CLIENT_OPTIONS_KIND_NIC || + !opts->u.nic->has_netdev) { peer = net_hub_add_port(net->has_vlan ? net->vlan : 0, NULL); } } - if (net_client_init_fun[opts->kind](opts, name, peer, errp) < 0) { + if (net_client_init_fun[opts->type](opts, name, peer, errp) < 0) { /* FIXME drop when all init functions store an Error */ if (errp && !*errp) { error_setg(errp, QERR_DEVICE_INIT_FAILED, - NetClientOptionsKind_lookup[opts->kind]); + NetClientOptionsKind_lookup[opts->type]); } return -1; } diff --git a/net/slirp.c b/net/slirp.c index 7657b38fdf..f505570adb 100644 --- a/net/slirp.c +++ b/net/slirp.c @@ -746,8 +746,8 @@ int net_init_slirp(const NetClientOptions *opts, const char *name, const NetdevUserOptions *user; const char **dnssearch; - assert(opts->kind == NET_CLIENT_OPTIONS_KIND_USER); - user = opts->user; + assert(opts->type == NET_CLIENT_OPTIONS_KIND_USER); + user = opts->u.user; vnet = user->has_net ? g_strdup(user->net) : user->has_ip ? g_strdup_printf("%s/24", user->ip) : diff --git a/net/socket.c b/net/socket.c index b1e3b1c8d9..e8605d4ded 100644 --- a/net/socket.c +++ b/net/socket.c @@ -706,8 +706,8 @@ int net_init_socket(const NetClientOptions *opts, const char *name, Error *err = NULL; const NetdevSocketOptions *sock; - assert(opts->kind == NET_CLIENT_OPTIONS_KIND_SOCKET); - sock = opts->socket; + assert(opts->type == NET_CLIENT_OPTIONS_KIND_SOCKET); + sock = opts->u.socket; if (sock->has_fd + sock->has_listen + sock->has_connect + sock->has_mcast + sock->has_udp != 1) { diff --git a/net/tap-win32.c b/net/tap-win32.c index 625d53c64b..4e2fa55006 100644 --- a/net/tap-win32.c +++ b/net/tap-win32.c @@ -767,8 +767,8 @@ int net_init_tap(const NetClientOptions *opts, const char *name, /* FIXME error_setg(errp, ...) on failure */ const NetdevTapOptions *tap; - assert(opts->kind == NET_CLIENT_OPTIONS_KIND_TAP); - tap = opts->tap; + assert(opts->type == NET_CLIENT_OPTIONS_KIND_TAP); + tap = opts->u.tap; if (!tap->has_ifname) { error_report("tap: no interface name"); @@ -565,8 +565,8 @@ int net_init_bridge(const NetClientOptions *opts, const char *name, TAPState *s; int fd, vnet_hdr; - assert(opts->kind == NET_CLIENT_OPTIONS_KIND_BRIDGE); - bridge = opts->bridge; + assert(opts->type == NET_CLIENT_OPTIONS_KIND_BRIDGE); + bridge = opts->u.bridge; helper = bridge->has_helper ? bridge->helper : DEFAULT_BRIDGE_HELPER; br = bridge->has_br ? bridge->br : DEFAULT_BRIDGE_INTERFACE; @@ -728,8 +728,8 @@ int net_init_tap(const NetClientOptions *opts, const char *name, const char *vhostfdname; char ifname[128]; - assert(opts->kind == NET_CLIENT_OPTIONS_KIND_TAP); - tap = opts->tap; + assert(opts->type == NET_CLIENT_OPTIONS_KIND_TAP); + tap = opts->u.tap; queues = tap->has_queues ? tap->queues : 1; vhostfdname = tap->has_vhostfd ? tap->vhostfd : NULL; @@ -115,8 +115,8 @@ int net_init_vde(const NetClientOptions *opts, const char *name, /* FIXME error_setg(errp, ...) on failure */ const NetdevVdeOptions *vde; - assert(opts->kind == NET_CLIENT_OPTIONS_KIND_VDE); - vde = opts->vde; + assert(opts->type == NET_CLIENT_OPTIONS_KIND_VDE); + vde = opts->u.vde; /* missing optional values have been initialized to "all bits zero" */ if (net_vde_init(peer, "vde", name, vde->sock, vde->port, vde->group, diff --git a/net/vhost-user.c b/net/vhost-user.c index 17b5c2a722..0ebd7df528 100644 --- a/net/vhost-user.c +++ b/net/vhost-user.c @@ -301,8 +301,8 @@ int net_init_vhost_user(const NetClientOptions *opts, const char *name, const NetdevVhostUserOptions *vhost_user_opts; CharDriverState *chr; - assert(opts->kind == NET_CLIENT_OPTIONS_KIND_VHOST_USER); - vhost_user_opts = opts->vhost_user; + assert(opts->type == NET_CLIENT_OPTIONS_KIND_VHOST_USER); + vhost_user_opts = opts->u.vhost_user; chr = net_vhost_parse_chardev(vhost_user_opts, errp); if (!chr) { @@ -226,9 +226,9 @@ static int parse_numa(void *opaque, QemuOpts *opts, Error **errp) goto error; } - switch (object->kind) { + switch (object->type) { case NUMA_OPTIONS_KIND_NODE: - numa_node_parse(object->node, opts, &err); + numa_node_parse(object->u.node, opts, &err); if (err) { goto error; } @@ -487,9 +487,9 @@ static void numa_stat_memory_devices(uint64_t node_mem[]) MemoryDeviceInfo *value = info->value; if (value) { - switch (value->kind) { + switch (value->type) { case MEMORY_DEVICE_INFO_KIND_DIMM: - node_mem[value->dimm->node] += value->dimm->size; + node_mem[value->u.dimm->node] += value->u.dimm->size; break; default: break; diff --git a/qapi-schema.json b/qapi-schema.json index f60be2950c..702b7b5dbd 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -2614,9 +2614,7 @@ # # @host: host part of the address # -# @port: port part of the address, or lowest port if @to is present. -# Kernel selects a free port if omitted for listener addresses. -# #optional +# @port: port part of the address, or lowest port if @to is present # # @to: highest port to try # @@ -2631,7 +2629,7 @@ { 'struct': 'InetSocketAddress', 'data': { 'host': 'str', - '*port': 'str', + 'port': 'str', '*to': 'uint16', '*ipv4': 'bool', '*ipv6': 'bool' } } diff --git a/qapi/qmp-input-visitor.c b/qapi/qmp-input-visitor.c index 5dd9ed5ce5..eb6e110300 100644 --- a/qapi/qmp-input-visitor.c +++ b/qapi/qmp-input-visitor.c @@ -225,45 +225,45 @@ static void qmp_input_type_int(Visitor *v, int64_t *obj, const char *name, Error **errp) { QmpInputVisitor *qiv = to_qiv(v); - QObject *qobj = qmp_input_get_object(qiv, name, true); + QInt *qint = qobject_to_qint(qmp_input_get_object(qiv, name, true)); - if (!qobj || qobject_type(qobj) != QTYPE_QINT) { + if (!qint) { error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null", "integer"); return; } - *obj = qint_get_int(qobject_to_qint(qobj)); + *obj = qint_get_int(qint); } static void qmp_input_type_bool(Visitor *v, bool *obj, const char *name, Error **errp) { QmpInputVisitor *qiv = to_qiv(v); - QObject *qobj = qmp_input_get_object(qiv, name, true); + QBool *qbool = qobject_to_qbool(qmp_input_get_object(qiv, name, true)); - if (!qobj || qobject_type(qobj) != QTYPE_QBOOL) { + if (!qbool) { error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null", "boolean"); return; } - *obj = qbool_get_bool(qobject_to_qbool(qobj)); + *obj = qbool_get_bool(qbool); } static void qmp_input_type_str(Visitor *v, char **obj, const char *name, Error **errp) { QmpInputVisitor *qiv = to_qiv(v); - QObject *qobj = qmp_input_get_object(qiv, name, true); + QString *qstr = qobject_to_qstring(qmp_input_get_object(qiv, name, true)); - if (!qobj || qobject_type(qobj) != QTYPE_QSTRING) { + if (!qstr) { error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null", "string"); return; } - *obj = g_strdup(qstring_get_str(qobject_to_qstring(qobj))); + *obj = g_strdup(qstring_get_str(qstr)); } static void qmp_input_type_number(Visitor *v, double *obj, const char *name, @@ -271,19 +271,23 @@ static void qmp_input_type_number(Visitor *v, double *obj, const char *name, { QmpInputVisitor *qiv = to_qiv(v); QObject *qobj = qmp_input_get_object(qiv, name, true); + QInt *qint; + QFloat *qfloat; - if (!qobj || (qobject_type(qobj) != QTYPE_QFLOAT && - qobject_type(qobj) != QTYPE_QINT)) { - error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null", - "number"); + qint = qobject_to_qint(qobj); + if (qint) { + *obj = qint_get_int(qobject_to_qint(qobj)); return; } - if (qobject_type(qobj) == QTYPE_QINT) { - *obj = qint_get_int(qobject_to_qint(qobj)); - } else { + qfloat = qobject_to_qfloat(qobj); + if (qfloat) { *obj = qfloat_get_double(qobject_to_qfloat(qobj)); + return; } + + error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null", + "number"); } static void qmp_input_type_any(Visitor *v, QObject **obj, const char *name, diff --git a/qemu-char.c b/qemu-char.c index c4eb4eea31..5448b0f30b 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -97,18 +97,18 @@ static int SocketAddress_to_str(char *dest, int max_len, const char *prefix, SocketAddress *addr, bool is_listen, bool is_telnet) { - switch (addr->kind) { + switch (addr->type) { case SOCKET_ADDRESS_KIND_INET: return snprintf(dest, max_len, "%s%s:%s:%s%s", prefix, - is_telnet ? "telnet" : "tcp", addr->inet->host, - addr->inet->port, is_listen ? ",server" : ""); + is_telnet ? "telnet" : "tcp", addr->u.inet->host, + addr->u.inet->port, is_listen ? ",server" : ""); break; case SOCKET_ADDRESS_KIND_UNIX: return snprintf(dest, max_len, "%sunix:%s%s", prefix, - addr->q_unix->path, is_listen ? ",server" : ""); + addr->u.q_unix->path, is_listen ? ",server" : ""); break; case SOCKET_ADDRESS_KIND_FD: - return snprintf(dest, max_len, "%sfd:%s%s", prefix, addr->fd->str, + return snprintf(dest, max_len, "%sfd:%s%s", prefix, addr->u.fd->str, is_listen ? ",server" : ""); break; default: @@ -661,7 +661,7 @@ static CharDriverState *qemu_chr_open_mux(const char *id, ChardevBackend *backend, ChardevReturn *ret, Error **errp) { - ChardevMux *mux = backend->mux; + ChardevMux *mux = backend->u.mux; CharDriverState *chr, *drv; MuxDriver *d; @@ -1070,7 +1070,7 @@ static CharDriverState *qemu_chr_open_pipe(const char *id, ChardevReturn *ret, Error **errp) { - ChardevHostdev *opts = backend->pipe; + ChardevHostdev *opts = backend->u.pipe; int fd_in, fd_out; char filename_in[CHR_MAX_FILENAME_SIZE]; char filename_out[CHR_MAX_FILENAME_SIZE]; @@ -1148,7 +1148,7 @@ static CharDriverState *qemu_chr_open_stdio(const char *id, ChardevReturn *ret, Error **errp) { - ChardevStdio *opts = backend->stdio; + ChardevStdio *opts = backend->u.stdio; CharDriverState *chr; struct sigaction act; @@ -2147,7 +2147,7 @@ static CharDriverState *qemu_chr_open_pipe(const char *id, ChardevReturn *ret, Error **errp) { - ChardevHostdev *opts = backend->pipe; + ChardevHostdev *opts = backend->u.pipe; const char *filename = opts->device; CharDriverState *chr; WinCharState *s; @@ -3202,7 +3202,7 @@ static CharDriverState *qemu_chr_open_ringbuf(const char *id, ChardevReturn *ret, Error **errp) { - ChardevRingbuf *opts = backend->ringbuf; + ChardevRingbuf *opts = backend->u.ringbuf; CharDriverState *chr; RingBufCharDriver *d; @@ -3477,16 +3477,16 @@ static void qemu_chr_parse_file_out(QemuOpts *opts, ChardevBackend *backend, error_setg(errp, "chardev: file: no filename given"); return; } - backend->file = g_new0(ChardevFile, 1); - backend->file->out = g_strdup(path); + backend->u.file = g_new0(ChardevFile, 1); + backend->u.file->out = g_strdup(path); } static void qemu_chr_parse_stdio(QemuOpts *opts, ChardevBackend *backend, Error **errp) { - backend->stdio = g_new0(ChardevStdio, 1); - backend->stdio->has_signal = true; - backend->stdio->signal = qemu_opt_get_bool(opts, "signal", true); + backend->u.stdio = g_new0(ChardevStdio, 1); + backend->u.stdio->has_signal = true; + backend->u.stdio->signal = qemu_opt_get_bool(opts, "signal", true); } #ifdef HAVE_CHARDEV_SERIAL @@ -3499,8 +3499,8 @@ static void qemu_chr_parse_serial(QemuOpts *opts, ChardevBackend *backend, error_setg(errp, "chardev: serial/tty: no device path given"); return; } - backend->serial = g_new0(ChardevHostdev, 1); - backend->serial->device = g_strdup(device); + backend->u.serial = g_new0(ChardevHostdev, 1); + backend->u.serial->device = g_strdup(device); } #endif @@ -3514,8 +3514,8 @@ static void qemu_chr_parse_parallel(QemuOpts *opts, ChardevBackend *backend, error_setg(errp, "chardev: parallel: no device path given"); return; } - backend->parallel = g_new0(ChardevHostdev, 1); - backend->parallel->device = g_strdup(device); + backend->u.parallel = g_new0(ChardevHostdev, 1); + backend->u.parallel->device = g_strdup(device); } #endif @@ -3528,8 +3528,8 @@ static void qemu_chr_parse_pipe(QemuOpts *opts, ChardevBackend *backend, error_setg(errp, "chardev: pipe: no device path given"); return; } - backend->pipe = g_new0(ChardevHostdev, 1); - backend->pipe->device = g_strdup(device); + backend->u.pipe = g_new0(ChardevHostdev, 1); + backend->u.pipe->device = g_strdup(device); } static void qemu_chr_parse_ringbuf(QemuOpts *opts, ChardevBackend *backend, @@ -3537,12 +3537,12 @@ static void qemu_chr_parse_ringbuf(QemuOpts *opts, ChardevBackend *backend, { int val; - backend->ringbuf = g_new0(ChardevRingbuf, 1); + backend->u.ringbuf = g_new0(ChardevRingbuf, 1); val = qemu_opt_get_size(opts, "size", 0); if (val != 0) { - backend->ringbuf->has_size = true; - backend->ringbuf->size = val; + backend->u.ringbuf->has_size = true; + backend->u.ringbuf->size = val; } } @@ -3555,8 +3555,8 @@ static void qemu_chr_parse_mux(QemuOpts *opts, ChardevBackend *backend, error_setg(errp, "chardev: mux: no chardev given"); return; } - backend->mux = g_new0(ChardevMux, 1); - backend->mux->chardev = g_strdup(chardev); + backend->u.mux = g_new0(ChardevMux, 1); + backend->u.mux->chardev = g_strdup(chardev); } static void qemu_chr_parse_socket(QemuOpts *opts, ChardevBackend *backend, @@ -3583,37 +3583,37 @@ static void qemu_chr_parse_socket(QemuOpts *opts, ChardevBackend *backend, } } - backend->socket = g_new0(ChardevSocket, 1); + backend->u.socket = g_new0(ChardevSocket, 1); - backend->socket->has_nodelay = true; - backend->socket->nodelay = do_nodelay; - backend->socket->has_server = true; - backend->socket->server = is_listen; - backend->socket->has_telnet = true; - backend->socket->telnet = is_telnet; - backend->socket->has_wait = true; - backend->socket->wait = is_waitconnect; - backend->socket->has_reconnect = true; - backend->socket->reconnect = reconnect; + backend->u.socket->has_nodelay = true; + backend->u.socket->nodelay = do_nodelay; + backend->u.socket->has_server = true; + backend->u.socket->server = is_listen; + backend->u.socket->has_telnet = true; + backend->u.socket->telnet = is_telnet; + backend->u.socket->has_wait = true; + backend->u.socket->wait = is_waitconnect; + backend->u.socket->has_reconnect = true; + backend->u.socket->reconnect = reconnect; addr = g_new0(SocketAddress, 1); if (path) { - addr->kind = SOCKET_ADDRESS_KIND_UNIX; - addr->q_unix = g_new0(UnixSocketAddress, 1); - addr->q_unix->path = g_strdup(path); + addr->type = SOCKET_ADDRESS_KIND_UNIX; + addr->u.q_unix = g_new0(UnixSocketAddress, 1); + addr->u.q_unix->path = g_strdup(path); } else { - addr->kind = SOCKET_ADDRESS_KIND_INET; - addr->inet = g_new0(InetSocketAddress, 1); - addr->inet->host = g_strdup(host); - addr->inet->port = g_strdup(port); - addr->inet->has_to = qemu_opt_get(opts, "to"); - addr->inet->to = qemu_opt_get_number(opts, "to", 0); - addr->inet->has_ipv4 = qemu_opt_get(opts, "ipv4"); - addr->inet->ipv4 = qemu_opt_get_bool(opts, "ipv4", 0); - addr->inet->has_ipv6 = qemu_opt_get(opts, "ipv6"); - addr->inet->ipv6 = qemu_opt_get_bool(opts, "ipv6", 0); + addr->type = SOCKET_ADDRESS_KIND_INET; + addr->u.inet = g_new0(InetSocketAddress, 1); + addr->u.inet->host = g_strdup(host); + addr->u.inet->port = g_strdup(port); + addr->u.inet->has_to = qemu_opt_get(opts, "to"); + addr->u.inet->to = qemu_opt_get_number(opts, "to", 0); + addr->u.inet->has_ipv4 = qemu_opt_get(opts, "ipv4"); + addr->u.inet->ipv4 = qemu_opt_get_bool(opts, "ipv4", 0); + addr->u.inet->has_ipv6 = qemu_opt_get(opts, "ipv6"); + addr->u.inet->ipv6 = qemu_opt_get_bool(opts, "ipv6", 0); } - backend->socket->addr = addr; + backend->u.socket->addr = addr; } static void qemu_chr_parse_udp(QemuOpts *opts, ChardevBackend *backend, @@ -3644,27 +3644,27 @@ static void qemu_chr_parse_udp(QemuOpts *opts, ChardevBackend *backend, has_local = true; } - backend->udp = g_new0(ChardevUdp, 1); + backend->u.udp = g_new0(ChardevUdp, 1); addr = g_new0(SocketAddress, 1); - addr->kind = SOCKET_ADDRESS_KIND_INET; - addr->inet = g_new0(InetSocketAddress, 1); - addr->inet->host = g_strdup(host); - addr->inet->port = g_strdup(port); - addr->inet->has_ipv4 = qemu_opt_get(opts, "ipv4"); - addr->inet->ipv4 = qemu_opt_get_bool(opts, "ipv4", 0); - addr->inet->has_ipv6 = qemu_opt_get(opts, "ipv6"); - addr->inet->ipv6 = qemu_opt_get_bool(opts, "ipv6", 0); - backend->udp->remote = addr; + addr->type = SOCKET_ADDRESS_KIND_INET; + addr->u.inet = g_new0(InetSocketAddress, 1); + addr->u.inet->host = g_strdup(host); + addr->u.inet->port = g_strdup(port); + addr->u.inet->has_ipv4 = qemu_opt_get(opts, "ipv4"); + addr->u.inet->ipv4 = qemu_opt_get_bool(opts, "ipv4", 0); + addr->u.inet->has_ipv6 = qemu_opt_get(opts, "ipv6"); + addr->u.inet->ipv6 = qemu_opt_get_bool(opts, "ipv6", 0); + backend->u.udp->remote = addr; if (has_local) { - backend->udp->has_local = true; + backend->u.udp->has_local = true; addr = g_new0(SocketAddress, 1); - addr->kind = SOCKET_ADDRESS_KIND_INET; - addr->inet = g_new0(InetSocketAddress, 1); - addr->inet->host = g_strdup(localaddr); - addr->inet->port = g_strdup(localport); - backend->udp->local = addr; + addr->type = SOCKET_ADDRESS_KIND_INET; + addr->u.inet = g_new0(InetSocketAddress, 1); + addr->u.inet->host = g_strdup(localaddr); + addr->u.inet->port = g_strdup(localport); + backend->u.udp->local = addr; } } @@ -3737,7 +3737,7 @@ CharDriverState *qemu_chr_new_from_opts(QemuOpts *opts, } chr = NULL; - backend->kind = cd->kind; + backend->type = cd->kind; if (cd->parse) { cd->parse(opts, backend, &local_err); if (local_err) { @@ -3754,9 +3754,9 @@ CharDriverState *qemu_chr_new_from_opts(QemuOpts *opts, qapi_free_ChardevBackend(backend); qapi_free_ChardevReturn(ret); backend = g_new0(ChardevBackend, 1); - backend->mux = g_new0(ChardevMux, 1); - backend->kind = CHARDEV_BACKEND_KIND_MUX; - backend->mux->chardev = g_strdup(bid); + backend->u.mux = g_new0(ChardevMux, 1); + backend->type = CHARDEV_BACKEND_KIND_MUX; + backend->u.mux->chardev = g_strdup(bid); ret = qmp_chardev_add(id, backend, errp); if (!ret) { chr = qemu_chr_find(bid); @@ -4048,7 +4048,7 @@ static CharDriverState *qmp_chardev_open_file(const char *id, ChardevReturn *ret, Error **errp) { - ChardevFile *file = backend->file; + ChardevFile *file = backend->u.file; HANDLE out; if (file->has_in) { @@ -4070,7 +4070,7 @@ static CharDriverState *qmp_chardev_open_serial(const char *id, ChardevReturn *ret, Error **errp) { - ChardevHostdev *serial = backend->serial; + ChardevHostdev *serial = backend->u.serial; return qemu_chr_open_win_path(serial->device, errp); } @@ -4093,7 +4093,7 @@ static CharDriverState *qmp_chardev_open_file(const char *id, ChardevReturn *ret, Error **errp) { - ChardevFile *file = backend->file; + ChardevFile *file = backend->u.file; int flags, in = -1, out; flags = O_WRONLY | O_TRUNC | O_CREAT | O_BINARY; @@ -4120,7 +4120,7 @@ static CharDriverState *qmp_chardev_open_serial(const char *id, ChardevReturn *ret, Error **errp) { - ChardevHostdev *serial = backend->serial; + ChardevHostdev *serial = backend->u.serial; int fd; fd = qmp_chardev_open_file_source(serial->device, O_RDWR, errp); @@ -4138,7 +4138,7 @@ static CharDriverState *qmp_chardev_open_parallel(const char *id, ChardevReturn *ret, Error **errp) { - ChardevHostdev *parallel = backend->parallel; + ChardevHostdev *parallel = backend->u.parallel; int fd; fd = qmp_chardev_open_file_source(parallel->device, O_RDWR, errp); @@ -4183,7 +4183,7 @@ static CharDriverState *qmp_chardev_open_socket(const char *id, { CharDriverState *chr; TCPCharDriver *s; - ChardevSocket *sock = backend->socket; + ChardevSocket *sock = backend->u.socket; SocketAddress *addr = sock->addr; bool do_nodelay = sock->has_nodelay ? sock->nodelay : false; bool is_listen = sock->has_server ? sock->server : true; @@ -4196,7 +4196,7 @@ static CharDriverState *qmp_chardev_open_socket(const char *id, s->fd = -1; s->listen_fd = -1; - s->is_unix = addr->kind == SOCKET_ADDRESS_KIND_UNIX; + s->is_unix = addr->type == SOCKET_ADDRESS_KIND_UNIX; s->is_listen = is_listen; s->is_telnet = is_telnet; s->do_nodelay = do_nodelay; @@ -4250,7 +4250,7 @@ static CharDriverState *qmp_chardev_open_udp(const char *id, ChardevReturn *ret, Error **errp) { - ChardevUdp *udp = backend->udp; + ChardevUdp *udp = backend->u.udp; int fd; fd = socket_dgram(udp->remote, udp->local, errp); @@ -4279,7 +4279,7 @@ ChardevReturn *qmp_chardev_add(const char *id, ChardevBackend *backend, for (i = backends; i; i = i->next) { cd = i->data; - if (cd->kind == backend->kind) { + if (cd->kind == backend->type) { chr = cd->create(id, backend, ret, &local_err); if (local_err) { error_propagate(errp, local_err); @@ -4297,9 +4297,9 @@ ChardevReturn *qmp_chardev_add(const char *id, ChardevBackend *backend, chr->label = g_strdup(id); chr->avail_connections = - (backend->kind == CHARDEV_BACKEND_KIND_MUX) ? MAX_MUX : 1; + (backend->type == CHARDEV_BACKEND_KIND_MUX) ? MAX_MUX : 1; if (!chr->filename) { - chr->filename = g_strdup(ChardevBackendKind_lookup[backend->kind]); + chr->filename = g_strdup(ChardevBackendKind_lookup[backend->type]); } if (!chr->explicit_be_open) { qemu_chr_be_event(chr, CHR_EVENT_OPENED); diff --git a/qemu-nbd.c b/qemu-nbd.c index 422a607bdd..3afec76504 100644 --- a/qemu-nbd.c +++ b/qemu-nbd.c @@ -362,17 +362,17 @@ static SocketAddress *nbd_build_socket_address(const char *sockpath, saddr = g_new0(SocketAddress, 1); if (sockpath) { - saddr->kind = SOCKET_ADDRESS_KIND_UNIX; - saddr->q_unix = g_new0(UnixSocketAddress, 1); - saddr->q_unix->path = g_strdup(sockpath); + saddr->type = SOCKET_ADDRESS_KIND_UNIX; + saddr->u.q_unix = g_new0(UnixSocketAddress, 1); + saddr->u.q_unix->path = g_strdup(sockpath); } else { - saddr->kind = SOCKET_ADDRESS_KIND_INET; - saddr->inet = g_new0(InetSocketAddress, 1); - saddr->inet->host = g_strdup(bindto); + saddr->type = SOCKET_ADDRESS_KIND_INET; + saddr->u.inet = g_new0(InetSocketAddress, 1); + saddr->u.inet->host = g_strdup(bindto); if (port) { - saddr->inet->port = g_strdup(port); + saddr->u.inet->port = g_strdup(port); } else { - saddr->inet->port = g_strdup_printf("%d", NBD_DEFAULT_PORT); + saddr->u.inet->port = g_strdup_printf("%d", NBD_DEFAULT_PORT); } } diff --git a/qga/commands-posix.c b/qga/commands-posix.c index 67a173af4f..0ebd47336a 100644 --- a/qga/commands-posix.c +++ b/qga/commands-posix.c @@ -28,6 +28,7 @@ #include "qapi/qmp/qerror.h" #include "qemu/queue.h" #include "qemu/host-utils.h" +#include "qemu/sockets.h" #ifndef CONFIG_HAS_ENVIRON #ifdef __APPLE__ @@ -385,27 +386,6 @@ safe_open_or_create(const char *path, const char *mode, Error **errp) return NULL; } -static int guest_file_toggle_flags(int fd, int flags, bool set, Error **err) -{ - int ret, old_flags; - - old_flags = fcntl(fd, F_GETFL); - if (old_flags == -1) { - error_setg_errno(err, errno, QERR_QGA_COMMAND_FAILED, - "failed to fetch filehandle flags"); - return -1; - } - - ret = fcntl(fd, F_SETFL, set ? (old_flags | flags) : (old_flags & ~flags)); - if (ret == -1) { - error_setg_errno(err, errno, QERR_QGA_COMMAND_FAILED, - "failed to set filehandle flags"); - return -1; - } - - return ret; -} - int64_t qmp_guest_file_open(const char *path, bool has_mode, const char *mode, Error **errp) { @@ -426,10 +406,7 @@ int64_t qmp_guest_file_open(const char *path, bool has_mode, const char *mode, /* set fd non-blocking to avoid common use cases (like reading from a * named pipe) from hanging the agent */ - if (guest_file_toggle_flags(fileno(fh), O_NONBLOCK, true, errp) < 0) { - fclose(fh); - return -1; - } + qemu_set_nonblock(fileno(fh)); handle = guest_file_handle_add(fh, errp); if (handle < 0) { diff --git a/qga/commands-win32.c b/qga/commands-win32.c index d9de23bbb8..a5306e76b0 100644 --- a/qga/commands-win32.c +++ b/qga/commands-win32.c @@ -128,6 +128,28 @@ static GuestFileHandle *guest_file_handle_find(int64_t id, Error **errp) return NULL; } +static void handle_set_nonblocking(HANDLE fh) +{ + DWORD file_type, pipe_state; + file_type = GetFileType(fh); + if (file_type != FILE_TYPE_PIPE) { + return; + } + /* If file_type == FILE_TYPE_PIPE, according to MSDN + * the specified file is socket or named pipe */ + if (!GetNamedPipeHandleState(fh, &pipe_state, NULL, + NULL, NULL, NULL, 0)) { + return; + } + /* The fd is named pipe fd */ + if (pipe_state & PIPE_NOWAIT) { + return; + } + + pipe_state |= PIPE_NOWAIT; + SetNamedPipeHandleState(fh, &pipe_state, NULL, NULL); +} + int64_t qmp_guest_file_open(const char *path, bool has_mode, const char *mode, Error **errp) { @@ -158,9 +180,14 @@ int64_t qmp_guest_file_open(const char *path, bool has_mode, return -1; } + /* set fd non-blocking to avoid common use cases (like reading from a + * named pipe) from hanging the agent + */ + handle_set_nonblocking(fh); + fd = guest_file_handle_add(fh, errp); if (fd < 0) { - CloseHandle(&fh); + CloseHandle(fh); error_setg(errp, "failed to add handle to qmp handle table"); return -1; } diff --git a/qga/main.c b/qga/main.c index 068169fcbc..d2a0ffc807 100644 --- a/qga/main.c +++ b/qga/main.c @@ -573,7 +573,6 @@ static void process_command(GAState *s, QDict *req) static void process_event(JSONMessageParser *parser, QList *tokens) { GAState *s = container_of(parser, GAState, parser); - QObject *obj; QDict *qdict; Error *err = NULL; int ret; @@ -581,9 +580,9 @@ static void process_event(JSONMessageParser *parser, QList *tokens) g_assert(s && parser); g_debug("process_event: called"); - obj = json_parser_parse_err(tokens, NULL, &err); - if (err || !obj || qobject_type(obj) != QTYPE_QDICT) { - qobject_decref(obj); + qdict = qobject_to_qdict(json_parser_parse_err(tokens, NULL, &err)); + if (err || !qdict) { + QDECREF(qdict); qdict = qdict_new(); if (!err) { g_warning("failed to parse event: unknown error"); @@ -593,12 +592,8 @@ static void process_event(JSONMessageParser *parser, QList *tokens) } qdict_put_obj(qdict, "error", qmp_build_error_object(err)); error_free(err); - } else { - qdict = qobject_to_qdict(obj); } - g_assert(qdict); - /* handle host->guest commands */ if (qdict_haskey(qdict, "execute")) { process_command(s, qdict); diff --git a/qobject/qbool.c b/qobject/qbool.c index 5ff69f0b2d..bc6535fa49 100644 --- a/qobject/qbool.c +++ b/qobject/qbool.c @@ -51,9 +51,9 @@ bool qbool_get_bool(const QBool *qb) */ QBool *qobject_to_qbool(const QObject *obj) { - if (qobject_type(obj) != QTYPE_QBOOL) + if (!obj || qobject_type(obj) != QTYPE_QBOOL) { return NULL; - + } return container_of(obj, QBool, base); } diff --git a/qobject/qdict.c b/qobject/qdict.c index 67b1a58abf..2d67bf1579 100644 --- a/qobject/qdict.c +++ b/qobject/qdict.c @@ -46,9 +46,9 @@ QDict *qdict_new(void) */ QDict *qobject_to_qdict(const QObject *obj) { - if (qobject_type(obj) != QTYPE_QDICT) + if (!obj || qobject_type(obj) != QTYPE_QDICT) { return NULL; - + } return container_of(obj, QDict, base); } @@ -229,8 +229,7 @@ double qdict_get_double(const QDict *qdict, const char *key) */ int64_t qdict_get_int(const QDict *qdict, const char *key) { - QObject *obj = qdict_get_obj(qdict, key, QTYPE_QINT); - return qint_get_int(qobject_to_qint(obj)); + return qint_get_int(qobject_to_qint(qdict_get(qdict, key))); } /** @@ -243,8 +242,7 @@ int64_t qdict_get_int(const QDict *qdict, const char *key) */ bool qdict_get_bool(const QDict *qdict, const char *key) { - QObject *obj = qdict_get_obj(qdict, key, QTYPE_QBOOL); - return qbool_get_bool(qobject_to_qbool(obj)); + return qbool_get_bool(qobject_to_qbool(qdict_get(qdict, key))); } /** @@ -270,7 +268,7 @@ QList *qdict_get_qlist(const QDict *qdict, const char *key) */ QDict *qdict_get_qdict(const QDict *qdict, const char *key) { - return qobject_to_qdict(qdict_get_obj(qdict, key, QTYPE_QDICT)); + return qobject_to_qdict(qdict_get(qdict, key)); } /** @@ -284,8 +282,7 @@ QDict *qdict_get_qdict(const QDict *qdict, const char *key) */ const char *qdict_get_str(const QDict *qdict, const char *key) { - QObject *obj = qdict_get_obj(qdict, key, QTYPE_QSTRING); - return qstring_get_str(qobject_to_qstring(obj)); + return qstring_get_str(qobject_to_qstring(qdict_get(qdict, key))); } /** @@ -298,13 +295,9 @@ const char *qdict_get_str(const QDict *qdict, const char *key) int64_t qdict_get_try_int(const QDict *qdict, const char *key, int64_t def_value) { - QObject *obj; + QInt *qint = qobject_to_qint(qdict_get(qdict, key)); - obj = qdict_get(qdict, key); - if (!obj || qobject_type(obj) != QTYPE_QINT) - return def_value; - - return qint_get_int(qobject_to_qint(obj)); + return qint ? qint_get_int(qint) : def_value; } /** @@ -316,13 +309,9 @@ int64_t qdict_get_try_int(const QDict *qdict, const char *key, */ bool qdict_get_try_bool(const QDict *qdict, const char *key, bool def_value) { - QObject *obj; + QBool *qbool = qobject_to_qbool(qdict_get(qdict, key)); - obj = qdict_get(qdict, key); - if (!obj || qobject_type(obj) != QTYPE_QBOOL) - return def_value; - - return qbool_get_bool(qobject_to_qbool(obj)); + return qbool ? qbool_get_bool(qbool) : def_value; } /** @@ -335,13 +324,9 @@ bool qdict_get_try_bool(const QDict *qdict, const char *key, bool def_value) */ const char *qdict_get_try_str(const QDict *qdict, const char *key) { - QObject *obj; - - obj = qdict_get(qdict, key); - if (!obj || qobject_type(obj) != QTYPE_QSTRING) - return NULL; + QString *qstr = qobject_to_qstring(qdict_get(qdict, key)); - return qstring_get_str(qobject_to_qstring(obj)); + return qstr ? qstring_get_str(qstr) : NULL; } /** diff --git a/qobject/qfloat.c b/qobject/qfloat.c index 7de0992dba..c86516327f 100644 --- a/qobject/qfloat.c +++ b/qobject/qfloat.c @@ -51,9 +51,9 @@ double qfloat_get_double(const QFloat *qf) */ QFloat *qobject_to_qfloat(const QObject *obj) { - if (qobject_type(obj) != QTYPE_QFLOAT) + if (!obj || qobject_type(obj) != QTYPE_QFLOAT) { return NULL; - + } return container_of(obj, QFloat, base); } diff --git a/qobject/qint.c b/qobject/qint.c index 86b9b04f0b..999688e9ce 100644 --- a/qobject/qint.c +++ b/qobject/qint.c @@ -50,9 +50,9 @@ int64_t qint_get_int(const QInt *qi) */ QInt *qobject_to_qint(const QObject *obj) { - if (qobject_type(obj) != QTYPE_QINT) + if (!obj || qobject_type(obj) != QTYPE_QINT) { return NULL; - + } return container_of(obj, QInt, base); } diff --git a/qobject/qlist.c b/qobject/qlist.c index 1ced0de58e..298003aaf7 100644 --- a/qobject/qlist.c +++ b/qobject/qlist.c @@ -142,10 +142,9 @@ size_t qlist_size(const QList *qlist) */ QList *qobject_to_qlist(const QObject *obj) { - if (qobject_type(obj) != QTYPE_QLIST) { + if (!obj || qobject_type(obj) != QTYPE_QLIST) { return NULL; } - return container_of(obj, QList, base); } diff --git a/qobject/qstring.c b/qobject/qstring.c index 607b7a142c..cb72dfbfc8 100644 --- a/qobject/qstring.c +++ b/qobject/qstring.c @@ -117,9 +117,9 @@ void qstring_append_chr(QString *qstring, int c) */ QString *qobject_to_qstring(const QObject *obj) { - if (qobject_type(obj) != QTYPE_QSTRING) + if (!obj || qobject_type(obj) != QTYPE_QSTRING) { return NULL; - + } return container_of(obj, QString, base); } diff --git a/scripts/analyze-migration.py b/scripts/analyze-migration.py index f6894bece9..14553876a2 100755 --- a/scripts/analyze-migration.py +++ b/scripts/analyze-migration.py @@ -252,6 +252,15 @@ class HTABSection(object): def getDict(self): return "" + +class ConfigurationSection(object): + def __init__(self, file): + self.file = file + + def read(self): + name_len = self.file.read32() + name = self.file.readstr(len = name_len) + class VMSDFieldGeneric(object): def __init__(self, desc, file): self.file = file @@ -474,6 +483,7 @@ class MigrationDump(object): QEMU_VM_SECTION_FULL = 0x04 QEMU_VM_SUBSECTION = 0x05 QEMU_VM_VMDESCRIPTION = 0x06 + QEMU_VM_CONFIGURATION = 0x07 QEMU_VM_SECTION_FOOTER= 0x7e def __init__(self, filename): @@ -514,6 +524,9 @@ class MigrationDump(object): section_type = file.read8() if section_type == self.QEMU_VM_EOF: break + elif section_type == self.QEMU_VM_CONFIGURATION: + section = ConfigurationSection(file) + section.read() elif section_type == self.QEMU_VM_SECTION_START or section_type == self.QEMU_VM_SECTION_FULL: section_id = file.read32() name = file.readstr() diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py index 43a893b4eb..561e47a42b 100644 --- a/scripts/qapi-commands.py +++ b/scripts/qapi-commands.py @@ -175,7 +175,9 @@ def gen_marshal(name, arg_type, ret_type): ret += gen_marshal_input_visit(arg_type) ret += gen_call(name, arg_type, ret_type) - if re.search('^ *goto out;', ret, re.MULTILINE): + # 'goto out' produced by gen_marshal_input_visit->gen_visit_fields() + # for each arg_type member, and by gen_call() for ret_type + if (arg_type and arg_type.members) or ret_type: ret += mcgen(''' out: diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py index 4fe618ef3c..b37900f6fc 100644 --- a/scripts/qapi-types.py +++ b/scripts/qapi-types.py @@ -36,26 +36,37 @@ struct %(c_name)s { c_name=c_name(name), c_type=element_type.c_type()) -def gen_struct_field(name, typ, optional): +def gen_struct_field(member): ret = '' - if optional: + if member.optional: ret += mcgen(''' bool has_%(c_name)s; ''', - c_name=c_name(name)) + c_name=c_name(member.name)) ret += mcgen(''' %(c_type)s %(c_name)s; ''', - c_type=typ.c_type(), c_name=c_name(name)) + c_type=member.type.c_type(), c_name=c_name(member.name)) return ret -def gen_struct_fields(members): +def gen_struct_fields(local_members, base=None): ret = '' - for memb in members: - ret += gen_struct_field(memb.name, memb.type, memb.optional) + if base: + ret += mcgen(''' + /* Members inherited from %(c_name)s: */ +''', + c_name=base.c_name()) + for memb in base.members: + ret += gen_struct_field(memb) + ret += mcgen(''' + /* Own members: */ +''') + + for memb in local_members: + ret += gen_struct_field(memb) return ret @@ -66,16 +77,13 @@ struct %(c_name)s { ''', c_name=c_name(name)) - if base: - ret += gen_struct_field('base', base, False) - - ret += gen_struct_fields(members) + ret += gen_struct_fields(members, base) # Make sure that all structs have at least one field; this avoids # potential issues with attempting to malloc space for zero-length # structs in C, and also incompatibility with C++ (where an empty # struct is size 1). - if not base and not members: + if not (base and base.members) and not members: ret += mcgen(''' char qapi_dummy_field_for_empty_struct; ''') @@ -87,6 +95,19 @@ struct %(c_name)s { return ret +def gen_upcast(name, base): + # C makes const-correctness ugly. We have to cast away const to let + # this function work for both const and non-const obj. + return mcgen(''' + +static inline %(base)s *qapi_%(c_name)s_base(const %(c_name)s *obj) +{ + return (%(base)s *)obj; +} +''', + c_name=c_name(name), base=base.c_name()) + + def gen_alternate_qtypes_decl(name): return mcgen(''' @@ -126,19 +147,9 @@ struct %(c_name)s { ''', c_name=c_name(name)) if base: - ret += mcgen(''' - /* Members inherited from %(c_name)s: */ -''', - c_name=c_name(base.name)) - ret += gen_struct_fields(base.members) - ret += mcgen(''' - /* Own members: */ -''') + ret += gen_struct_fields([], base) else: - ret += mcgen(''' - %(c_type)s kind; -''', - c_type=c_name(variants.tag_member.type.name)) + ret += gen_struct_field(variants.tag_member) # FIXME: What purpose does data serve, besides preventing a union that # has a branch named 'data'? We use it in qapi-visit.py to decide @@ -152,10 +163,7 @@ struct %(c_name)s { union { /* union tag is @%(c_name)s */ void *data; ''', - # TODO ugly special case for simple union - # Use same tag name in C as on the wire to get rid of - # it, then: c_name=c_name(variants.tag_member.name) - c_name=c_name(variants.tag_name or 'kind')) + c_name=c_name(variants.tag_member.name)) for var in variants.variants: # Ugly special case for simple union TODO get rid of it @@ -167,7 +175,7 @@ struct %(c_name)s { c_name=c_name(var.name)) ret += mcgen(''' - }; + } u; }; ''') @@ -265,6 +273,8 @@ class QAPISchemaGenTypeVisitor(QAPISchemaVisitor): self.decl += gen_union(name, base, variants) else: self.decl += gen_struct(name, base, members) + if base: + self.decl += gen_upcast(name, base) self._gen_type_cleanup(name) def visit_alternate_type(self, name, info, variants): diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py index d0759d739a..f40c3c792f 100644 --- a/scripts/qapi-visit.py +++ b/scripts/qapi-visit.py @@ -15,7 +15,12 @@ from qapi import * import re +# visit_type_FOO_implicit() is emitted as needed; track if it has already +# been output. implicit_structs_seen = set() + +# visit_type_FOO_fields() is always emitted; track if a forward declaration +# or implementation has already been output. struct_fields_seen = set() @@ -29,19 +34,24 @@ void visit_type_%(c_name)s(Visitor *v, %(c_type)sobj, const char *name, Error ** c_name=c_name(name), c_type=c_type) -def gen_visit_implicit_struct(typ): - if typ in implicit_structs_seen: - return '' - implicit_structs_seen.add(typ) - +def gen_visit_fields_decl(typ): ret = '' if typ.name not in struct_fields_seen: - # Need a forward declaration ret += mcgen(''' static void visit_type_%(c_type)s_fields(Visitor *v, %(c_type)s **obj, Error **errp); ''', c_type=typ.c_name()) + struct_fields_seen.add(typ.name) + return ret + + +def gen_visit_implicit_struct(typ): + if typ in implicit_structs_seen: + return '' + implicit_structs_seen.add(typ) + + ret = gen_visit_fields_decl(typ) ret += mcgen(''' @@ -62,13 +72,12 @@ static void visit_type_implicit_%(c_type)s(Visitor *v, %(c_type)s **obj, Error * def gen_visit_struct_fields(name, base, members): - struct_fields_seen.add(name) - ret = '' if base: - ret += gen_visit_implicit_struct(base) + ret += gen_visit_fields_decl(base) + struct_fields_seen.add(name) ret += mcgen(''' static void visit_type_%(c_name)s_fields(Visitor *v, %(c_name)s **obj, Error **errp) @@ -80,14 +89,15 @@ static void visit_type_%(c_name)s_fields(Visitor *v, %(c_name)s **obj, Error **e if base: ret += mcgen(''' - visit_type_implicit_%(c_type)s(v, &(*obj)->%(c_name)s, &err); + visit_type_%(c_type)s_fields(v, (%(c_type)s **)obj, &err); ''', - c_type=base.c_name(), c_name=c_name('base')) + c_type=base.c_name()) ret += gen_err_check() ret += gen_visit_fields(members, prefix='(*obj)->') - if re.search('^ *goto out;', ret, re.MULTILINE): + # 'goto out' produced for base, and by gen_visit_fields() for each member + if base or members: ret += mcgen(''' out: @@ -179,18 +189,18 @@ void visit_type_%(c_name)s(Visitor *v, %(c_name)s **obj, const char *name, Error if (err) { goto out; } - visit_get_next_type(v, (int*) &(*obj)->kind, %(c_name)s_qtypes, name, &err); + visit_get_next_type(v, (int*) &(*obj)->type, %(c_name)s_qtypes, name, &err); if (err) { goto out_obj; } - switch ((*obj)->kind) { + switch ((*obj)->type) { ''', c_name=c_name(name)) for var in variants.variants: ret += mcgen(''' case %(case)s: - visit_type_%(c_type)s(v, &(*obj)->%(c_name)s, name, &err); + visit_type_%(c_type)s(v, &(*obj)->u.%(c_name)s, name, &err); break; ''', case=c_enum_const(variants.tag_member.type.name, @@ -218,8 +228,7 @@ def gen_visit_union(name, base, variants): ret = '' if base: - members = [m for m in base.members if m != variants.tag_member] - ret += gen_visit_struct_fields(name, None, members) + ret += gen_visit_fields_decl(base) for var in variants.variants: # Ugly special case for simple union TODO get rid of it @@ -244,31 +253,24 @@ void visit_type_%(c_name)s(Visitor *v, %(c_name)s **obj, const char *name, Error if base: ret += mcgen(''' - visit_type_%(c_name)s_fields(v, obj, &err); + visit_type_%(c_name)s_fields(v, (%(c_name)s **)obj, &err); ''', - c_name=c_name(name)) - ret += gen_err_check(label='out_obj') - - tag_key = variants.tag_member.name - if not variants.tag_name: - # we pointlessly use a different key for simple unions - tag_key = 'type' - ret += mcgen(''' + c_name=base.c_name()) + else: + ret += mcgen(''' visit_type_%(c_type)s(v, &(*obj)->%(c_name)s, "%(name)s", &err); - if (err) { - goto out_obj; - } - if (!visit_start_union(v, !!(*obj)->data, &err) || err) { +''', + c_type=variants.tag_member.type.c_name(), + c_name=c_name(variants.tag_member.name), + name=variants.tag_member.name) + ret += gen_err_check(label='out_obj') + ret += mcgen(''' + if (!visit_start_union(v, !!(*obj)->u.data, &err) || err) { goto out_obj; } switch ((*obj)->%(c_name)s) { ''', - c_type=variants.tag_member.type.c_name(), - # TODO ugly special case for simple union - # Use same tag name in C as on the wire to get rid of - # it, then: c_name=c_name(variants.tag_member.name) - c_name=c_name(variants.tag_name or 'kind'), - name=tag_key) + c_name=c_name(variants.tag_member.name)) for var in variants.variants: # TODO ugly special case for simple union @@ -280,13 +282,13 @@ void visit_type_%(c_name)s(Visitor *v, %(c_name)s **obj, const char *name, Error var.name)) if simple_union_type: ret += mcgen(''' - visit_type_%(c_type)s(v, &(*obj)->%(c_name)s, "data", &err); + visit_type_%(c_type)s(v, &(*obj)->u.%(c_name)s, "data", &err); ''', c_type=simple_union_type.c_name(), c_name=c_name(var.name)) else: ret += mcgen(''' - visit_type_implicit_%(c_type)s(v, &(*obj)->%(c_name)s, &err); + visit_type_implicit_%(c_type)s(v, &(*obj)->u.%(c_name)s, &err); ''', c_type=var.type.c_name(), c_name=c_name(var.name)) @@ -302,7 +304,7 @@ out_obj: error_propagate(errp, err); err = NULL; if (*obj) { - visit_end_union(v, !!(*obj)->data, &err); + visit_end_union(v, !!(*obj)->u.data, &err); } error_propagate(errp, err); err = NULL; diff --git a/scripts/qapi.py b/scripts/qapi.py index 9d53255320..7c50cc4c87 100644 --- a/scripts/qapi.py +++ b/scripts/qapi.py @@ -172,7 +172,7 @@ class QAPISchemaParser(object): if self.tok == '#': self.cursor = self.src.find('\n', self.cursor) - elif self.tok in ['{', '}', ':', ',', '[', ']']: + elif self.tok in "{}:,[]": return elif self.tok == "'": string = '' @@ -376,7 +376,9 @@ def check_name(expr_info, source, name, allow_optional=False, # code always prefixes it with the enum name if enum_member: membername = '_' + membername - if not valid_name.match(membername): + # Reserve the entire 'q_' namespace for c_name() + if not valid_name.match(membername) or \ + c_name(membername, False).startswith('q_'): raise QAPIExprError(expr_info, "%s uses invalid name '%s'" % (source, name)) @@ -390,10 +392,10 @@ def add_name(name, info, meta, implicit=False): raise QAPIExprError(info, "%s '%s' is already defined" % (all_names[name], name)) - if not implicit and name[-4:] == 'Kind': + if not implicit and (name.endswith('Kind') or name.endswith('List')): raise QAPIExprError(info, - "%s '%s' should not end in 'Kind'" - % (meta, name)) + "%s '%s' should not end in '%s'" + % (meta, name, name[-4:])) all_names[name] = meta @@ -488,6 +490,10 @@ def check_type(expr_info, source, value, allow_array=False, for (key, arg) in value.items(): check_name(expr_info, "Member of %s" % source, key, allow_optional=allow_optional) + if c_name(key, False) == 'u' or c_name(key, False).startswith('has_'): + raise QAPIExprError(expr_info, + "Member of %s uses reserved name '%s'" + % (source, key)) # Todo: allow dictionaries to represent default values of # an optional argument. check_type(expr_info, "Member '%s' of %s" % (key, source), arg, @@ -542,7 +548,8 @@ def check_union(expr, expr_info): base = expr.get('base') discriminator = expr.get('discriminator') members = expr['data'] - values = {'MAX': '(automatic)', 'KIND': '(automatic)'} + values = {'MAX': '(automatic)', 'KIND': '(automatic)', + 'TYPE': '(automatic)'} # Two types of unions, determined by discriminator. @@ -910,7 +917,7 @@ class QAPISchemaEnumType(QAPISchemaType): def is_implicit(self): # See QAPISchema._make_implicit_enum_type() - return self.name[-4:] == 'Kind' + return self.name.endswith('Kind') def c_type(self, is_param=False): return c_name(self.name) @@ -1196,9 +1203,7 @@ class QAPISchema(object): return name def _make_array_type(self, element_type, info): - # TODO fooList namespace is not reserved; user can create collisions, - # or abuse our type system with ['fooList'] for 2D array - name = element_type + 'List' + name = element_type + 'List' # Use namespace reserved by add_name() if not self.lookup_type(name): self._def_entity(QAPISchemaArrayType(name, info, element_type)) return name diff --git a/scripts/qemu-gdb.py b/scripts/qemu-gdb.py index d6f2e5a903..b3f8e04f77 100644 --- a/scripts/qemu-gdb.py +++ b/scripts/qemu-gdb.py @@ -26,7 +26,7 @@ import os, sys sys.path.append(os.path.dirname(__file__)) -from qemugdb import mtree, coroutine +from qemugdb import aio, mtree, coroutine class QemuCommand(gdb.Command): '''Prefix for QEMU debug support commands''' @@ -37,6 +37,10 @@ class QemuCommand(gdb.Command): QemuCommand() coroutine.CoroutineCommand() mtree.MtreeCommand() +aio.HandlersCommand() + +coroutine.CoroutineSPFunction() +coroutine.CoroutinePCFunction() # Default to silently passing through SIGUSR1, because QEMU sends it # to itself a lot. diff --git a/scripts/qemugdb/aio.py b/scripts/qemugdb/aio.py new file mode 100644 index 0000000000..2ba00c4444 --- /dev/null +++ b/scripts/qemugdb/aio.py @@ -0,0 +1,58 @@ +#!/usr/bin/python + +# GDB debugging support: aio/iohandler debug +# +# Copyright (c) 2015 Red Hat, Inc. +# +# Author: Dr. David Alan Gilbert <dgilbert@redhat.com> +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. +# + +import gdb +from qemugdb import coroutine + +def isnull(ptr): + return ptr == gdb.Value(0).cast(ptr.type) + +def dump_aiocontext(context, verbose): + '''Display a dump and backtrace for an aiocontext''' + cur = context['aio_handlers']['lh_first'] + # Get pointers to functions we're going to process specially + sym_fd_coroutine_enter = gdb.parse_and_eval('fd_coroutine_enter') + + while not isnull(cur): + entry = cur.dereference() + gdb.write('----\n%s\n' % entry) + if verbose and cur['io_read'] == sym_fd_coroutine_enter: + coptr = (cur['opaque'].cast(gdb.lookup_type('FDYieldUntilData').pointer()))['co'] + coptr = coptr.cast(gdb.lookup_type('CoroutineUContext').pointer()) + coroutine.bt_jmpbuf(coptr['env']['__jmpbuf']) + cur = cur['node']['le_next']; + + gdb.write('----\n') + +class HandlersCommand(gdb.Command): + '''Display aio handlers''' + def __init__(self): + gdb.Command.__init__(self, 'qemu handlers', gdb.COMMAND_DATA, + gdb.COMPLETE_NONE) + + def invoke(self, arg, from_tty): + verbose = False + argv = gdb.string_to_argv(arg) + + if len(argv) > 0 and argv[0] == '--verbose': + verbose = True + argv.pop(0) + + if len(argv) > 1: + gdb.write('usage: qemu handlers [--verbose] [handler]\n') + return + + if len(argv) == 1: + handlers_name = argv[0] + else: + handlers_name = 'qemu_aio_context' + dump_aiocontext(gdb.parse_and_eval(handlers_name), verbose) diff --git a/scripts/qemugdb/coroutine.py b/scripts/qemugdb/coroutine.py index 3c54918b5d..ab699794ab 100644 --- a/scripts/qemugdb/coroutine.py +++ b/scripts/qemugdb/coroutine.py @@ -15,8 +15,11 @@ import gdb +VOID_PTR = gdb.lookup_type('void').pointer() + def get_fs_base(): - '''Fetch %fs base value using arch_prctl(ARCH_GET_FS)''' + '''Fetch %fs base value using arch_prctl(ARCH_GET_FS). This is + pthread_self().''' # %rsp - 120 is scratch space according to the SystemV ABI old = gdb.parse_and_eval('*(uint64_t*)($rsp - 120)') gdb.execute('call arch_prctl(0x1003, $rsp - 120)', False, True) @@ -24,17 +27,29 @@ def get_fs_base(): gdb.execute('set *(uint64_t*)($rsp - 120) = %s' % old, False, True) return fs_base +def pthread_self(): + '''Fetch pthread_self() from the glibc start_thread function.''' + f = gdb.newest_frame() + while f.name() != 'start_thread': + f = f.older() + if f is None: + return get_fs_base() + + try: + return f.read_var("arg") + except ValueError: + return get_fs_base() + def get_glibc_pointer_guard(): '''Fetch glibc pointer guard value''' - fs_base = get_fs_base() + fs_base = pthread_self() return gdb.parse_and_eval('*(uint64_t*)((uint64_t)%s + 0x30)' % fs_base) def glibc_ptr_demangle(val, pointer_guard): '''Undo effect of glibc's PTR_MANGLE()''' return gdb.parse_and_eval('(((uint64_t)%s >> 0x11) | ((uint64_t)%s << (64 - 0x11))) ^ (uint64_t)%s' % (val, val, pointer_guard)) -def bt_jmpbuf(jmpbuf): - '''Backtrace a jmpbuf''' +def get_jmpbuf_regs(jmpbuf): JB_RBX = 0 JB_RBP = 1 JB_R12 = 2 @@ -44,35 +59,35 @@ def bt_jmpbuf(jmpbuf): JB_RSP = 6 JB_PC = 7 - old_rbx = gdb.parse_and_eval('(uint64_t)$rbx') - old_rbp = gdb.parse_and_eval('(uint64_t)$rbp') - old_rsp = gdb.parse_and_eval('(uint64_t)$rsp') - old_r12 = gdb.parse_and_eval('(uint64_t)$r12') - old_r13 = gdb.parse_and_eval('(uint64_t)$r13') - old_r14 = gdb.parse_and_eval('(uint64_t)$r14') - old_r15 = gdb.parse_and_eval('(uint64_t)$r15') - old_rip = gdb.parse_and_eval('(uint64_t)$rip') - pointer_guard = get_glibc_pointer_guard() - gdb.execute('set $rbx = %s' % jmpbuf[JB_RBX]) - gdb.execute('set $rbp = %s' % glibc_ptr_demangle(jmpbuf[JB_RBP], pointer_guard)) - gdb.execute('set $rsp = %s' % glibc_ptr_demangle(jmpbuf[JB_RSP], pointer_guard)) - gdb.execute('set $r12 = %s' % jmpbuf[JB_R12]) - gdb.execute('set $r13 = %s' % jmpbuf[JB_R13]) - gdb.execute('set $r14 = %s' % jmpbuf[JB_R14]) - gdb.execute('set $r15 = %s' % jmpbuf[JB_R15]) - gdb.execute('set $rip = %s' % glibc_ptr_demangle(jmpbuf[JB_PC], pointer_guard)) + return {'rbx': jmpbuf[JB_RBX], + 'rbp': glibc_ptr_demangle(jmpbuf[JB_RBP], pointer_guard), + 'rsp': glibc_ptr_demangle(jmpbuf[JB_RSP], pointer_guard), + 'r12': jmpbuf[JB_R12], + 'r13': jmpbuf[JB_R13], + 'r14': jmpbuf[JB_R14], + 'r15': jmpbuf[JB_R15], + 'rip': glibc_ptr_demangle(jmpbuf[JB_PC], pointer_guard) } + +def bt_jmpbuf(jmpbuf): + '''Backtrace a jmpbuf''' + regs = get_jmpbuf_regs(jmpbuf) + old = dict() + + for i in regs: + old[i] = gdb.parse_and_eval('(uint64_t)$%s' % i) + + for i in regs: + gdb.execute('set $%s = %s' % (i, regs[i])) gdb.execute('bt') - gdb.execute('set $rbx = %s' % old_rbx) - gdb.execute('set $rbp = %s' % old_rbp) - gdb.execute('set $rsp = %s' % old_rsp) - gdb.execute('set $r12 = %s' % old_r12) - gdb.execute('set $r13 = %s' % old_r13) - gdb.execute('set $r14 = %s' % old_r14) - gdb.execute('set $r15 = %s' % old_r15) - gdb.execute('set $rip = %s' % old_rip) + for i in regs: + gdb.execute('set $%s = %s' % (i, old[i])) + +def coroutine_to_jmpbuf(co): + coroutine_pointer = co.cast(gdb.lookup_type('CoroutineUContext').pointer()) + return coroutine_pointer['env']['__jmpbuf'] class CoroutineCommand(gdb.Command): @@ -87,5 +102,18 @@ class CoroutineCommand(gdb.Command): gdb.write('usage: qemu coroutine <coroutine-pointer>\n') return - coroutine_pointer = gdb.parse_and_eval(argv[0]).cast(gdb.lookup_type('CoroutineUContext').pointer()) - bt_jmpbuf(coroutine_pointer['env']['__jmpbuf']) + bt_jmpbuf(coroutine_to_jmpbuf(gdb.parse_and_eval(argv[0]))) + +class CoroutineSPFunction(gdb.Function): + def __init__(self): + gdb.Function.__init__(self, 'qemu_coroutine_sp') + + def invoke(self, addr): + return get_jmpbuf_regs(coroutine_to_jmpbuf(addr))['rsp'].cast(VOID_PTR) + +class CoroutinePCFunction(gdb.Function): + def __init__(self): + gdb.Function.__init__(self, 'qemu_coroutine_pc') + + def invoke(self, addr): + return get_jmpbuf_regs(coroutine_to_jmpbuf(addr))['rip'].cast(VOID_PTR) diff --git a/spice-qemu-char.c b/spice-qemu-char.c index a20fb5c90c..e70e0f7366 100644 --- a/spice-qemu-char.c +++ b/spice-qemu-char.c @@ -301,7 +301,7 @@ static CharDriverState *qemu_chr_open_spice_vmc(const char *id, ChardevReturn *ret, Error **errp) { - const char *type = backend->spicevmc->type; + const char *type = backend->u.spicevmc->type; const char **psubtype = spice_server_char_device_recognized_subtypes(); for (; *psubtype != NULL; ++psubtype) { @@ -324,7 +324,7 @@ static CharDriverState *qemu_chr_open_spice_port(const char *id, ChardevReturn *ret, Error **errp) { - const char *name = backend->spiceport->fqdn; + const char *name = backend->u.spiceport->fqdn; CharDriverState *chr; SpiceCharDriver *s; @@ -362,8 +362,8 @@ static void qemu_chr_parse_spice_vmc(QemuOpts *opts, ChardevBackend *backend, error_setg(errp, "chardev: spice channel: no name given"); return; } - backend->spicevmc = g_new0(ChardevSpiceChannel, 1); - backend->spicevmc->type = g_strdup(name); + backend->u.spicevmc = g_new0(ChardevSpiceChannel, 1); + backend->u.spicevmc->type = g_strdup(name); } static void qemu_chr_parse_spice_port(QemuOpts *opts, ChardevBackend *backend, @@ -375,8 +375,8 @@ static void qemu_chr_parse_spice_port(QemuOpts *opts, ChardevBackend *backend, error_setg(errp, "chardev: spice port: no name given"); return; } - backend->spiceport = g_new0(ChardevSpicePort, 1); - backend->spiceport->fqdn = g_strdup(name); + backend->u.spiceport = g_new0(ChardevSpicePort, 1); + backend->u.spiceport->fqdn = g_strdup(name); } static void register_types(void) diff --git a/target-arm/helper.c b/target-arm/helper.c index 1966f9c045..4ecae61197 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -3130,7 +3130,8 @@ static const ARMCPRegInfo v8_cp_reginfo[] = { { .name = "SPSR_EL1", .state = ARM_CP_STATE_AA64, .type = ARM_CP_ALIAS, .opc0 = 3, .opc1 = 0, .crn = 4, .crm = 0, .opc2 = 0, - .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, banked_spsr[1]) }, + .access = PL1_RW, + .fieldoffset = offsetof(CPUARMState, banked_spsr[BANK_SVC]) }, /* We rely on the access checks not allowing the guest to write to the * state field when SPSel indicates that it's being used as the stack * pointer. @@ -3299,23 +3300,28 @@ static const ARMCPRegInfo el2_cp_reginfo[] = { { .name = "SPSR_EL2", .state = ARM_CP_STATE_AA64, .type = ARM_CP_ALIAS, .opc0 = 3, .opc1 = 4, .crn = 4, .crm = 0, .opc2 = 0, - .access = PL2_RW, .fieldoffset = offsetof(CPUARMState, banked_spsr[6]) }, + .access = PL2_RW, + .fieldoffset = offsetof(CPUARMState, banked_spsr[BANK_HYP]) }, { .name = "SPSR_IRQ", .state = ARM_CP_STATE_AA64, .type = ARM_CP_ALIAS, .opc0 = 3, .opc1 = 4, .crn = 4, .crm = 3, .opc2 = 0, - .access = PL2_RW, .fieldoffset = offsetof(CPUARMState, banked_spsr[4]) }, + .access = PL2_RW, + .fieldoffset = offsetof(CPUARMState, banked_spsr[BANK_IRQ]) }, { .name = "SPSR_ABT", .state = ARM_CP_STATE_AA64, .type = ARM_CP_ALIAS, .opc0 = 3, .opc1 = 4, .crn = 4, .crm = 3, .opc2 = 1, - .access = PL2_RW, .fieldoffset = offsetof(CPUARMState, banked_spsr[2]) }, + .access = PL2_RW, + .fieldoffset = offsetof(CPUARMState, banked_spsr[BANK_ABT]) }, { .name = "SPSR_UND", .state = ARM_CP_STATE_AA64, .type = ARM_CP_ALIAS, .opc0 = 3, .opc1 = 4, .crn = 4, .crm = 3, .opc2 = 2, - .access = PL2_RW, .fieldoffset = offsetof(CPUARMState, banked_spsr[3]) }, + .access = PL2_RW, + .fieldoffset = offsetof(CPUARMState, banked_spsr[BANK_UND]) }, { .name = "SPSR_FIQ", .state = ARM_CP_STATE_AA64, .type = ARM_CP_ALIAS, .opc0 = 3, .opc1 = 4, .crn = 4, .crm = 3, .opc2 = 3, - .access = PL2_RW, .fieldoffset = offsetof(CPUARMState, banked_spsr[5]) }, + .access = PL2_RW, + .fieldoffset = offsetof(CPUARMState, banked_spsr[BANK_FIQ]) }, { .name = "VBAR_EL2", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 4, .crn = 12, .crm = 0, .opc2 = 0, .access = PL2_RW, .writefn = vbar_write, @@ -3552,7 +3558,8 @@ static const ARMCPRegInfo el3_cp_reginfo[] = { { .name = "SPSR_EL3", .state = ARM_CP_STATE_AA64, .type = ARM_CP_ALIAS, .opc0 = 3, .opc1 = 6, .crn = 4, .crm = 0, .opc2 = 0, - .access = PL3_RW, .fieldoffset = offsetof(CPUARMState, banked_spsr[7]) }, + .access = PL3_RW, + .fieldoffset = offsetof(CPUARMState, banked_spsr[BANK_MON]) }, { .name = "VBAR_EL3", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 6, .crn = 12, .crm = 0, .opc2 = 0, .access = PL3_RW, .writefn = vbar_write, @@ -5183,21 +5190,21 @@ int bank_number(int mode) switch (mode) { case ARM_CPU_MODE_USR: case ARM_CPU_MODE_SYS: - return 0; + return BANK_USRSYS; case ARM_CPU_MODE_SVC: - return 1; + return BANK_SVC; case ARM_CPU_MODE_ABT: - return 2; + return BANK_ABT; case ARM_CPU_MODE_UND: - return 3; + return BANK_UND; case ARM_CPU_MODE_IRQ: - return 4; + return BANK_IRQ; case ARM_CPU_MODE_FIQ: - return 5; + return BANK_FIQ; case ARM_CPU_MODE_HYP: - return 6; + return BANK_HYP; case ARM_CPU_MODE_MON: - return 7; + return BANK_MON; } g_assert_not_reached(); } diff --git a/target-arm/internals.h b/target-arm/internals.h index 412827bcbf..347998c8be 100644 --- a/target-arm/internals.h +++ b/target-arm/internals.h @@ -25,6 +25,16 @@ #ifndef TARGET_ARM_INTERNALS_H #define TARGET_ARM_INTERNALS_H +/* register banks for CPU modes */ +#define BANK_USRSYS 0 +#define BANK_SVC 1 +#define BANK_ABT 2 +#define BANK_UND 3 +#define BANK_IRQ 4 +#define BANK_FIQ 5 +#define BANK_HYP 6 +#define BANK_MON 7 + static inline bool excp_is_internal(int excp) { /* Return true if this exception number represents a QEMU-internal @@ -91,9 +101,9 @@ static inline void arm_log_exception(int idx) static inline unsigned int aarch64_banked_spsr_index(unsigned int el) { static const unsigned int map[4] = { - [1] = 1, /* EL1. */ - [2] = 6, /* EL2. */ - [3] = 7, /* EL3. */ + [1] = BANK_SVC, /* EL1. */ + [2] = BANK_HYP, /* EL2. */ + [3] = BANK_MON, /* EL3. */ }; assert(el >= 1 && el <= 3); return map[el]; diff --git a/target-arm/kvm32.c b/target-arm/kvm32.c index 3ae57a6d68..df1e2b0ebf 100644 --- a/target-arm/kvm32.c +++ b/target-arm/kvm32.c @@ -280,30 +280,30 @@ static const Reg regs[] = { COREREG(usr_regs.uregs[10], usr_regs[2]), COREREG(usr_regs.uregs[11], usr_regs[3]), COREREG(usr_regs.uregs[12], usr_regs[4]), - COREREG(usr_regs.uregs[13], banked_r13[0]), - COREREG(usr_regs.uregs[14], banked_r14[0]), + COREREG(usr_regs.uregs[13], banked_r13[BANK_USRSYS]), + COREREG(usr_regs.uregs[14], banked_r14[BANK_USRSYS]), /* R13, R14, SPSR for SVC, ABT, UND, IRQ banks */ - COREREG(svc_regs[0], banked_r13[1]), - COREREG(svc_regs[1], banked_r14[1]), - COREREG64(svc_regs[2], banked_spsr[1]), - COREREG(abt_regs[0], banked_r13[2]), - COREREG(abt_regs[1], banked_r14[2]), - COREREG64(abt_regs[2], banked_spsr[2]), - COREREG(und_regs[0], banked_r13[3]), - COREREG(und_regs[1], banked_r14[3]), - COREREG64(und_regs[2], banked_spsr[3]), - COREREG(irq_regs[0], banked_r13[4]), - COREREG(irq_regs[1], banked_r14[4]), - COREREG64(irq_regs[2], banked_spsr[4]), + COREREG(svc_regs[0], banked_r13[BANK_SVC]), + COREREG(svc_regs[1], banked_r14[BANK_SVC]), + COREREG64(svc_regs[2], banked_spsr[BANK_SVC]), + COREREG(abt_regs[0], banked_r13[BANK_ABT]), + COREREG(abt_regs[1], banked_r14[BANK_ABT]), + COREREG64(abt_regs[2], banked_spsr[BANK_ABT]), + COREREG(und_regs[0], banked_r13[BANK_UND]), + COREREG(und_regs[1], banked_r14[BANK_UND]), + COREREG64(und_regs[2], banked_spsr[BANK_UND]), + COREREG(irq_regs[0], banked_r13[BANK_IRQ]), + COREREG(irq_regs[1], banked_r14[BANK_IRQ]), + COREREG64(irq_regs[2], banked_spsr[BANK_IRQ]), /* R8_fiq .. R14_fiq and SPSR_fiq */ COREREG(fiq_regs[0], fiq_regs[0]), COREREG(fiq_regs[1], fiq_regs[1]), COREREG(fiq_regs[2], fiq_regs[2]), COREREG(fiq_regs[3], fiq_regs[3]), COREREG(fiq_regs[4], fiq_regs[4]), - COREREG(fiq_regs[5], banked_r13[5]), - COREREG(fiq_regs[6], banked_r14[5]), - COREREG64(fiq_regs[7], banked_spsr[5]), + COREREG(fiq_regs[5], banked_r13[BANK_FIQ]), + COREREG(fiq_regs[6], banked_r14[BANK_FIQ]), + COREREG64(fiq_regs[7], banked_spsr[BANK_FIQ]), /* R15 */ COREREG(usr_regs.uregs[15], regs[15]), /* VFP system registers */ diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c index a4c4ebf9cd..b5db345ccd 100644 --- a/target-arm/op_helper.c +++ b/target-arm/op_helper.c @@ -392,9 +392,9 @@ uint32_t HELPER(get_user_reg)(CPUARMState *env, uint32_t regno) uint32_t val; if (regno == 13) { - val = env->banked_r13[0]; + val = env->banked_r13[BANK_USRSYS]; } else if (regno == 14) { - val = env->banked_r14[0]; + val = env->banked_r14[BANK_USRSYS]; } else if (regno >= 8 && (env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_FIQ) { val = env->usr_regs[regno - 8]; @@ -407,9 +407,9 @@ uint32_t HELPER(get_user_reg)(CPUARMState *env, uint32_t regno) void HELPER(set_user_reg)(CPUARMState *env, uint32_t regno, uint32_t val) { if (regno == 13) { - env->banked_r13[0] = val; + env->banked_r13[BANK_USRSYS] = val; } else if (regno == 14) { - env->banked_r14[0] = val; + env->banked_r14[BANK_USRSYS] = val; } else if (regno >= 8 && (env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_FIQ) { env->usr_regs[regno - 8] = val; diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c index 83b8376210..d7e09549c0 100644 --- a/target-arm/translate-a64.c +++ b/target-arm/translate-a64.c @@ -126,6 +126,8 @@ void aarch64_cpu_dump_state(CPUState *cs, FILE *f, CPUARMState *env = &cpu->env; uint32_t psr = pstate_read(env); int i; + int el = arm_current_el(env); + const char *ns_status; cpu_fprintf(f, "PC=%016"PRIx64" SP=%016"PRIx64"\n", env->pc, env->xregs[31]); @@ -137,13 +139,22 @@ void aarch64_cpu_dump_state(CPUState *cs, FILE *f, cpu_fprintf(f, " "); } } - cpu_fprintf(f, "PSTATE=%08x (flags %c%c%c%c)\n", + + if (arm_feature(env, ARM_FEATURE_EL3) && el != 3) { + ns_status = env->cp15.scr_el3 & SCR_NS ? "NS " : "S "; + } else { + ns_status = ""; + } + + cpu_fprintf(f, "\nPSTATE=%08x %c%c%c%c %sEL%d%c\n", psr, psr & PSTATE_N ? 'N' : '-', psr & PSTATE_Z ? 'Z' : '-', psr & PSTATE_C ? 'C' : '-', - psr & PSTATE_V ? 'V' : '-'); - cpu_fprintf(f, "\n"); + psr & PSTATE_V ? 'V' : '-', + ns_status, + el, + psr & PSTATE_SP ? 'h' : 't'); if (flags & CPU_DUMP_FPU) { int numvfpregs = 32; diff --git a/target-arm/translate.c b/target-arm/translate.c index b10a455e70..ff262a2572 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -11602,6 +11602,7 @@ void arm_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf, CPUARMState *env = &cpu->env; int i; uint32_t psr; + const char *ns_status; if (is_a64(env)) { aarch64_cpu_dump_state(cs, f, cpu_fprintf, flags); @@ -11616,13 +11617,22 @@ void arm_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf, cpu_fprintf(f, " "); } psr = cpsr_read(env); - cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%d\n", + + if (arm_feature(env, ARM_FEATURE_EL3) && + (psr & CPSR_M) != ARM_CPU_MODE_MON) { + ns_status = env->cp15.scr_el3 & SCR_NS ? "NS " : "S "; + } else { + ns_status = ""; + } + + cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%s%d\n", psr, psr & (1 << 31) ? 'N' : '-', psr & (1 << 30) ? 'Z' : '-', psr & (1 << 29) ? 'C' : '-', psr & (1 << 28) ? 'V' : '-', psr & CPSR_T ? 'T' : 'A', + ns_status, cpu_mode_names[psr & 0xf], (psr & 0x10) ? 32 : 26); if (flags & CPU_DUMP_FPU) { diff --git a/target-mips/cpu.c b/target-mips/cpu.c index 37880d20e0..639a24b362 100644 --- a/target-mips/cpu.c +++ b/target-mips/cpu.c @@ -53,12 +53,15 @@ static bool mips_cpu_has_work(CPUState *cs) CPUMIPSState *env = &cpu->env; bool has_work = false; - /* It is implementation dependent if non-enabled interrupts - wake-up the CPU, however most of the implementations only + /* Prior to MIPS Release 6 it is implementation dependent if non-enabled + interrupts wake-up the CPU, however most of the implementations only check for interrupts that can be taken. */ if ((cs->interrupt_request & CPU_INTERRUPT_HARD) && cpu_mips_hw_interrupts_pending(env)) { - has_work = true; + if (cpu_mips_hw_interrupts_enabled(env) || + (env->insn_flags & ISA_MIPS32R6)) { + has_work = true; + } } /* MIPS-MT has the ability to halt the CPU. */ diff --git a/target-mips/cpu.h b/target-mips/cpu.h index f32a0fd737..fa919c1a13 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -469,6 +469,7 @@ struct CPUMIPSState { #define CP0C5_CV 29 #define CP0C5_EVA 28 #define CP0C5_MSAEn 27 +#define CP0C5_XNP 13 #define CP0C5_UFE 9 #define CP0C5_FRE 8 #define CP0C5_SBRI 6 @@ -637,23 +638,24 @@ static inline int cpu_mmu_index (CPUMIPSState *env, bool ifetch) return env->hflags & MIPS_HFLAG_KSU; } -static inline int cpu_mips_hw_interrupts_pending(CPUMIPSState *env) +static inline bool cpu_mips_hw_interrupts_enabled(CPUMIPSState *env) { - int32_t pending; - int32_t status; - int r; - - if (!(env->CP0_Status & (1 << CP0St_IE)) || - (env->CP0_Status & (1 << CP0St_EXL)) || - (env->CP0_Status & (1 << CP0St_ERL)) || + return (env->CP0_Status & (1 << CP0St_IE)) && + !(env->CP0_Status & (1 << CP0St_EXL)) && + !(env->CP0_Status & (1 << CP0St_ERL)) && + !(env->hflags & MIPS_HFLAG_DM) && /* Note that the TCStatus IXMT field is initialized to zero, and only MT capable cores can set it to one. So we don't need to check for MT capabilities here. */ - (env->active_tc.CP0_TCStatus & (1 << CP0TCSt_IXMT)) || - (env->hflags & MIPS_HFLAG_DM)) { - /* Interrupts are disabled */ - return 0; - } + !(env->active_tc.CP0_TCStatus & (1 << CP0TCSt_IXMT)); +} + +/* Check if there is pending and not masked out interrupt */ +static inline bool cpu_mips_hw_interrupts_pending(CPUMIPSState *env) +{ + int32_t pending; + int32_t status; + bool r; pending = env->CP0_Cause & CP0Ca_IP_mask; status = env->CP0_Status & CP0Ca_IP_mask; @@ -667,7 +669,7 @@ static inline int cpu_mips_hw_interrupts_pending(CPUMIPSState *env) /* A MIPS configured with compatibility or VInt (Vectored Interrupts) treats the pending lines as individual interrupt lines, the status lines are individual masks. */ - r = pending & status; + r = (pending & status) != 0; } return r; } @@ -1000,7 +1002,12 @@ static inline void cpu_mips_store_status(CPUMIPSState *env, target_ulong val) if (env->insn_flags & ISA_MIPS32R6) { bool has_supervisor = extract32(mask, CP0St_KSU, 2) == 0x3; - +#if defined(TARGET_MIPS64) + uint32_t ksux = (1 << CP0St_KX) & val; + ksux |= (ksux >> 1) & val; /* KX = 0 forces SX to be 0 */ + ksux |= (ksux >> 1) & val; /* SX = 0 forces UX to be 0 */ + val = (val & ~(7 << CP0St_UX)) | ksux; +#endif if (has_supervisor && extract32(val, CP0St_KSU, 2) == 0x3) { mask &= ~(3 << CP0St_KSU); } diff --git a/target-mips/helper.c b/target-mips/helper.c index 01c4461573..b3fe816fec 100644 --- a/target-mips/helper.c +++ b/target-mips/helper.c @@ -293,9 +293,10 @@ static void raise_mmu_exception(CPUMIPSState *env, target_ulong address, (env->CP0_EntryHi & 0xFF) | (address & (TARGET_PAGE_MASK << 1)); #if defined(TARGET_MIPS64) env->CP0_EntryHi &= env->SEGMask; - env->CP0_XContext = (env->CP0_XContext & ((~0ULL) << (env->SEGBITS - 7))) | - ((address & 0xC00000000000ULL) >> (55 - env->SEGBITS)) | - ((address & ((1ULL << env->SEGBITS) - 1) & 0xFFFFFFFFFFFFE000ULL) >> 9); + env->CP0_XContext = + /* PTEBase */ (env->CP0_XContext & ((~0ULL) << (env->SEGBITS - 7))) | + /* R */ (extract64(address, 62, 2) << (env->SEGBITS - 9)) | + /* BadVPN2 */ (extract64(address, 13, env->SEGBITS - 13) << 4); #endif cs->exception_index = exception; env->error_code = error_code; @@ -759,7 +760,8 @@ bool mips_cpu_exec_interrupt(CPUState *cs, int interrupt_request) MIPSCPU *cpu = MIPS_CPU(cs); CPUMIPSState *env = &cpu->env; - if (cpu_mips_hw_interrupts_pending(env)) { + if (cpu_mips_hw_interrupts_enabled(env) && + cpu_mips_hw_interrupts_pending(env)) { /* Raise it */ cs->exception_index = EXCP_EXT_INTERRUPT; env->error_code = 0; diff --git a/target-mips/helper.h b/target-mips/helper.h index d8cc766bdf..95b9149d89 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -358,6 +358,8 @@ DEF_HELPER_1(rdhwr_cpunum, tl, env) DEF_HELPER_1(rdhwr_synci_step, tl, env) DEF_HELPER_1(rdhwr_cc, tl, env) DEF_HELPER_1(rdhwr_ccres, tl, env) +DEF_HELPER_1(rdhwr_performance, tl, env) +DEF_HELPER_1(rdhwr_xnp, tl, env) DEF_HELPER_2(pmon, void, env, int) DEF_HELPER_1(wait, void, env) diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index 6739fff216..056d53b9ef 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -1357,6 +1357,13 @@ void helper_mtc0_hwrena(CPUMIPSState *env, target_ulong arg1) { uint32_t mask = 0x0000000F; + if ((env->CP0_Config1 & (1 << CP0C1_PC)) && + (env->insn_flags & ISA_MIPS32R6)) { + mask |= (1 << 4); + } + if (env->insn_flags & ISA_MIPS32R6) { + mask |= (1 << 5); + } if (env->CP0_Config3 & (1 << CP0C3_ULRI)) { mask |= (1 << 29); @@ -2185,53 +2192,52 @@ void helper_deret(CPUMIPSState *env) } #endif /* !CONFIG_USER_ONLY */ -target_ulong helper_rdhwr_cpunum(CPUMIPSState *env) +static inline void check_hwrena(CPUMIPSState *env, int reg) { - if ((env->hflags & MIPS_HFLAG_CP0) || - (env->CP0_HWREna & (1 << 0))) - return env->CP0_EBase & 0x3ff; - else - do_raise_exception(env, EXCP_RI, GETPC()); + if ((env->hflags & MIPS_HFLAG_CP0) || (env->CP0_HWREna & (1 << reg))) { + return; + } + do_raise_exception(env, EXCP_RI, GETPC()); +} - return 0; +target_ulong helper_rdhwr_cpunum(CPUMIPSState *env) +{ + check_hwrena(env, 0); + return env->CP0_EBase & 0x3ff; } target_ulong helper_rdhwr_synci_step(CPUMIPSState *env) { - if ((env->hflags & MIPS_HFLAG_CP0) || - (env->CP0_HWREna & (1 << 1))) - return env->SYNCI_Step; - else - do_raise_exception(env, EXCP_RI, GETPC()); - - return 0; + check_hwrena(env, 1); + return env->SYNCI_Step; } target_ulong helper_rdhwr_cc(CPUMIPSState *env) { - if ((env->hflags & MIPS_HFLAG_CP0) || - (env->CP0_HWREna & (1 << 2))) { + check_hwrena(env, 2); #ifdef CONFIG_USER_ONLY - return env->CP0_Count; + return env->CP0_Count; #else - return (int32_t)cpu_mips_get_count(env); + return (int32_t)cpu_mips_get_count(env); #endif - } else { - do_raise_exception(env, EXCP_RI, GETPC()); - } - - return 0; } target_ulong helper_rdhwr_ccres(CPUMIPSState *env) { - if ((env->hflags & MIPS_HFLAG_CP0) || - (env->CP0_HWREna & (1 << 3))) - return env->CCRes; - else - do_raise_exception(env, EXCP_RI, GETPC()); + check_hwrena(env, 3); + return env->CCRes; +} - return 0; +target_ulong helper_rdhwr_performance(CPUMIPSState *env) +{ + check_hwrena(env, 4); + return env->CP0_Performance0; +} + +target_ulong helper_rdhwr_xnp(CPUMIPSState *env) +{ + check_hwrena(env, 5); + return (env->CP0_Config5 >> CP0C5_XNP) & 1; } void helper_pmon(CPUMIPSState *env, int function) diff --git a/target-mips/translate.c b/target-mips/translate.c index a10bfa3a79..56266471c1 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -323,6 +323,7 @@ enum { OPC_TLTIU = (0x0B << 16) | OPC_REGIMM, OPC_TEQI = (0x0C << 16) | OPC_REGIMM, OPC_TNEI = (0x0E << 16) | OPC_REGIMM, + OPC_SIGRIE = (0x17 << 16) | OPC_REGIMM, OPC_SYNCI = (0x1F << 16) | OPC_REGIMM, OPC_DAHI = (0x06 << 16) | OPC_REGIMM, @@ -10333,7 +10334,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, } } -static void gen_rdhwr(DisasContext *ctx, int rt, int rd) +static void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel) { TCGv t0; @@ -10361,6 +10362,22 @@ static void gen_rdhwr(DisasContext *ctx, int rt, int rd) gen_helper_rdhwr_ccres(t0, cpu_env); gen_store_gpr(t0, rt); break; + case 4: + check_insn(ctx, ISA_MIPS32R6); + if (sel != 0) { + /* Performance counter registers are not implemented other than + * control register 0. + */ + generate_exception(ctx, EXCP_RI); + } + gen_helper_rdhwr_performance(t0, cpu_env); + gen_store_gpr(t0, rt); + break; + case 5: + check_insn(ctx, ISA_MIPS32R6); + gen_helper_rdhwr_xnp(t0, cpu_env); + gen_store_gpr(t0, rt); + break; case 29: #if defined(CONFIG_USER_ONLY) tcg_gen_ld_tl(t0, cpu_env, @@ -11979,6 +11996,7 @@ enum { ROTR = 0x3, SELEQZ = 0x5, SELNEZ = 0x6, + R6_RDHWR = 0x7, SLLV = 0x0, SRLV = 0x1, @@ -12009,11 +12027,13 @@ enum { MODU = 0x7, /* The following can be distinguished by their lower 6 bits. */ + BREAK32 = 0x07, INS = 0x0c, LSA = 0x0f, ALIGN = 0x1f, EXT = 0x2c, - POOL32AXF = 0x3c + POOL32AXF = 0x3c, + SIGRIE = 0x3f }; /* POOL32AXF encoding of minor opcode field extension */ @@ -12931,7 +12951,8 @@ static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs) gen_cl(ctx, mips32_op, rt, rs); break; case RDHWR: - gen_rdhwr(ctx, rt, rs); + check_insn_opc_removed(ctx, ISA_MIPS32R6); + gen_rdhwr(ctx, rt, rs, 0); break; case WSBH: gen_bshfl(ctx, OPC_WSBH, rs, rt); @@ -13486,6 +13507,10 @@ static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx) check_insn(ctx, ISA_MIPS32R6); gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt); break; + case R6_RDHWR: + check_insn(ctx, ISA_MIPS32R6); + gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3)); + break; default: goto pool32a_invalid; } @@ -13629,9 +13654,13 @@ static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx) case POOL32AXF: gen_pool32axf(env, ctx, rt, rs); break; - case 0x07: + case BREAK32: generate_exception_end(ctx, EXCP_BREAK); break; + case SIGRIE: + check_insn(ctx, ISA_MIPS32R6); + generate_exception_end(ctx, EXCP_RI); + break; default: pool32a_invalid: MIPS_INVAL("pool32a"); @@ -17732,7 +17761,7 @@ static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx) break; #endif case OPC_RDHWR: - gen_rdhwr(ctx, rt, rd); + gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3)); break; case OPC_FORK: check_insn(ctx, ASE_MT); @@ -18950,6 +18979,10 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx) check_insn_opc_removed(ctx, ISA_MIPS32R6); gen_trap(ctx, op1, rs, -1, imm); break; + case OPC_SIGRIE: + check_insn(ctx, ISA_MIPS32R6); + generate_exception_end(ctx, EXCP_RI); + break; case OPC_SYNCI: check_insn(ctx, ISA_MIPS32R2); /* Break the TB to be able to sync copied instructions diff --git a/target-mips/translate_init.c b/target-mips/translate_init.c index 1b45884e9b..bb33c7cfeb 100644 --- a/target-mips/translate_init.c +++ b/target-mips/translate_init.c @@ -447,7 +447,7 @@ static const mips_def_t mips_defs[] = (1 << CP0C3_RXI) | (1U << CP0C3_M), .CP0_Config4 = MIPS_CONFIG4 | (0xfc << CP0C4_KScrExist) | (3 << CP0C4_IE) | (1U << CP0C4_M), - .CP0_Config5 = MIPS_CONFIG5 | (1 << CP0C5_LLB), + .CP0_Config5 = MIPS_CONFIG5 | (1 << CP0C5_XNP) | (1 << CP0C5_LLB), .CP0_Config5_rw_bitmask = (1 << CP0C5_SBRI) | (1 << CP0C5_FRE) | (1 << CP0C5_UFE), .CP0_LLAddr_rw_bitmask = 0, @@ -665,7 +665,7 @@ static const mips_def_t mips_defs[] = (1 << CP0C3_RXI) | (1 << CP0C3_LPA), .CP0_Config4 = MIPS_CONFIG4 | (1U << CP0C4_M) | (3 << CP0C4_IE) | (0xfc << CP0C4_KScrExist), - .CP0_Config5 = MIPS_CONFIG5 | (1 << CP0C5_LLB), + .CP0_Config5 = MIPS_CONFIG5 | (1 << CP0C5_XNP) | (1 << CP0C5_LLB), .CP0_Config5_rw_bitmask = (1 << CP0C5_MSAEn) | (1 << CP0C5_SBRI) | (1 << CP0C5_FRE) | (1 << CP0C5_UFE), .CP0_LLAddr_rw_bitmask = 0, diff --git a/target-tilegx/translate.c b/target-tilegx/translate.c index 34d45f87b9..354f25a52b 100644 --- a/target-tilegx/translate.c +++ b/target-tilegx/translate.c @@ -2105,38 +2105,44 @@ static TileExcp decode_y2(DisasContext *dc, tilegx_bundle_bits bundle) unsigned srcbdest = get_SrcBDest_Y2(bundle); const char *mnemonic; TCGMemOp memop; + bool prefetch_nofault = false; switch (OEY2(opc, mode)) { case OEY2(LD1S_OPCODE_Y2, MODE_OPCODE_YA2): memop = MO_SB; - mnemonic = "ld1s"; + mnemonic = "ld1s"; /* prefetch_l1_fault */ goto do_load; case OEY2(LD1U_OPCODE_Y2, MODE_OPCODE_YA2): memop = MO_UB; - mnemonic = "ld1u"; + mnemonic = "ld1u"; /* prefetch, prefetch_l1 */ + prefetch_nofault = (srcbdest == TILEGX_R_ZERO); goto do_load; case OEY2(LD2S_OPCODE_Y2, MODE_OPCODE_YA2): memop = MO_TESW; - mnemonic = "ld2s"; + mnemonic = "ld2s"; /* prefetch_l2_fault */ goto do_load; case OEY2(LD2U_OPCODE_Y2, MODE_OPCODE_YA2): memop = MO_TEUW; - mnemonic = "ld2u"; + mnemonic = "ld2u"; /* prefetch_l2 */ + prefetch_nofault = (srcbdest == TILEGX_R_ZERO); goto do_load; case OEY2(LD4S_OPCODE_Y2, MODE_OPCODE_YB2): memop = MO_TESL; - mnemonic = "ld4s"; + mnemonic = "ld4s"; /* prefetch_l3_fault */ goto do_load; case OEY2(LD4U_OPCODE_Y2, MODE_OPCODE_YB2): memop = MO_TEUL; - mnemonic = "ld4u"; + mnemonic = "ld4u"; /* prefetch_l3 */ + prefetch_nofault = (srcbdest == TILEGX_R_ZERO); goto do_load; case OEY2(LD_OPCODE_Y2, MODE_OPCODE_YB2): memop = MO_TEQ; mnemonic = "ld"; do_load: - tcg_gen_qemu_ld_tl(dest_gr(dc, srcbdest), load_gr(dc, srca), - dc->mmuidx, memop); + if (!prefetch_nofault) { + tcg_gen_qemu_ld_tl(dest_gr(dc, srcbdest), load_gr(dc, srca), + dc->mmuidx, memop); + } qemu_log_mask(CPU_LOG_TB_IN_ASM, "%s %s, %s", mnemonic, reg_names[srcbdest], reg_names[srca]); return TILEGX_EXCP_NONE; diff --git a/tests/Makefile b/tests/Makefile index 0739bfe1bf..92969e8288 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -265,7 +265,6 @@ qapi-schema += enum-dict-member.json qapi-schema += enum-int-member.json qapi-schema += enum-max-member.json qapi-schema += enum-missing-data.json -qapi-schema += enum-union-clash.json qapi-schema += enum-wrong-data.json qapi-schema += escape-outside-string.json qapi-schema += escape-too-big.json @@ -316,12 +315,17 @@ qapi-schema += redefined-builtin.json qapi-schema += redefined-command.json qapi-schema += redefined-event.json qapi-schema += redefined-type.json +qapi-schema += reserved-command-q.json +qapi-schema += reserved-member-has.json +qapi-schema += reserved-member-q.json +qapi-schema += reserved-member-u.json +qapi-schema += reserved-type-kind.json +qapi-schema += reserved-type-list.json qapi-schema += returns-alternate.json qapi-schema += returns-array-bad.json qapi-schema += returns-dict.json qapi-schema += returns-unknown.json qapi-schema += returns-whitelist.json -qapi-schema += struct-base-clash-base.json qapi-schema += struct-base-clash-deep.json qapi-schema += struct-base-clash.json qapi-schema += struct-data-invalid.json diff --git a/tests/qapi-schema/enum-union-clash.err b/tests/qapi-schema/enum-union-clash.err deleted file mode 100644 index c04e1a8064..0000000000 --- a/tests/qapi-schema/enum-union-clash.err +++ /dev/null @@ -1 +0,0 @@ -tests/qapi-schema/enum-union-clash.json:2: enum 'UnionKind' should not end in 'Kind' diff --git a/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qapi-schema-test.json index 4e2d7c2063..48e104ba13 100644 --- a/tests/qapi-schema/qapi-schema-test.json +++ b/tests/qapi-schema/qapi-schema-test.json @@ -11,6 +11,10 @@ # An empty enum, although unusual, is currently acceptable { 'enum': 'MyEnum', 'data': [ ] } +# Likewise for an empty struct, including an empty base +{ 'struct': 'Empty1', 'data': { } } +{ 'struct': 'Empty2', 'base': 'Empty1', 'data': { } } + # for testing override of default naming heuristic { 'enum': 'QEnumTwo', 'prefix': 'QENUM_TWO', diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qapi-schema-test.out index a6c80e04d7..a7e9aabec0 100644 --- a/tests/qapi-schema/qapi-schema-test.out +++ b/tests/qapi-schema/qapi-schema-test.out @@ -81,6 +81,9 @@ event EVENT_A None event EVENT_B None event EVENT_C :obj-EVENT_C-arg event EVENT_D :obj-EVENT_D-arg +object Empty1 +object Empty2 + base Empty1 enum EnumOne ['value1', 'value2', 'value3'] object EventStructOne member struct1: UserDefOne optional=False diff --git a/tests/qapi-schema/reserved-command-q.err b/tests/qapi-schema/reserved-command-q.err new file mode 100644 index 0000000000..f939e044eb --- /dev/null +++ b/tests/qapi-schema/reserved-command-q.err @@ -0,0 +1 @@ +tests/qapi-schema/reserved-command-q.json:5: 'command' uses invalid name 'q-unix' diff --git a/tests/qapi-schema/enum-union-clash.exit b/tests/qapi-schema/reserved-command-q.exit index d00491fd7e..d00491fd7e 100644 --- a/tests/qapi-schema/enum-union-clash.exit +++ b/tests/qapi-schema/reserved-command-q.exit diff --git a/tests/qapi-schema/reserved-command-q.json b/tests/qapi-schema/reserved-command-q.json new file mode 100644 index 0000000000..99f8aae314 --- /dev/null +++ b/tests/qapi-schema/reserved-command-q.json @@ -0,0 +1,5 @@ +# C entity name collision +# We reject names like 'q-unix', because they can collide with the mangled +# name for 'unix' in generated C. +{ 'command': 'unix' } +{ 'command': 'q-unix' } diff --git a/tests/qapi-schema/enum-union-clash.out b/tests/qapi-schema/reserved-command-q.out index e69de29bb2..e69de29bb2 100644 --- a/tests/qapi-schema/enum-union-clash.out +++ b/tests/qapi-schema/reserved-command-q.out diff --git a/tests/qapi-schema/reserved-member-has.err b/tests/qapi-schema/reserved-member-has.err new file mode 100644 index 0000000000..e755771446 --- /dev/null +++ b/tests/qapi-schema/reserved-member-has.err @@ -0,0 +1 @@ +tests/qapi-schema/reserved-member-has.json:5: Member of 'data' for command 'oops' uses reserved name 'has-a' diff --git a/tests/qapi-schema/reserved-member-has.exit b/tests/qapi-schema/reserved-member-has.exit new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/tests/qapi-schema/reserved-member-has.exit @@ -0,0 +1 @@ +1 diff --git a/tests/qapi-schema/reserved-member-has.json b/tests/qapi-schema/reserved-member-has.json new file mode 100644 index 0000000000..45b9109bdc --- /dev/null +++ b/tests/qapi-schema/reserved-member-has.json @@ -0,0 +1,5 @@ +# C member name collision +# We reject names like 'has-a', because they can collide with the flag +# for an optional 'a' in generated C. +# TODO we could munge the optional flag name to avoid the collision. +{ 'command': 'oops', 'data': { '*a': 'str', 'has-a': 'str' } } diff --git a/tests/qapi-schema/struct-base-clash-base.err b/tests/qapi-schema/reserved-member-has.out index e69de29bb2..e69de29bb2 100644 --- a/tests/qapi-schema/struct-base-clash-base.err +++ b/tests/qapi-schema/reserved-member-has.out diff --git a/tests/qapi-schema/reserved-member-q.err b/tests/qapi-schema/reserved-member-q.err new file mode 100644 index 0000000000..f3d5dd7818 --- /dev/null +++ b/tests/qapi-schema/reserved-member-q.err @@ -0,0 +1 @@ +tests/qapi-schema/reserved-member-q.json:4: Member of 'data' for struct 'Foo' uses invalid name 'q-unix' diff --git a/tests/qapi-schema/reserved-member-q.exit b/tests/qapi-schema/reserved-member-q.exit new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/tests/qapi-schema/reserved-member-q.exit @@ -0,0 +1 @@ +1 diff --git a/tests/qapi-schema/reserved-member-q.json b/tests/qapi-schema/reserved-member-q.json new file mode 100644 index 0000000000..62fed8fddf --- /dev/null +++ b/tests/qapi-schema/reserved-member-q.json @@ -0,0 +1,4 @@ +# C member name collision +# We reject names like 'q-unix', because they can collide with the mangled +# name for 'unix' in generated C. +{ 'struct': 'Foo', 'data': { 'unix':'int', 'q-unix':'bool' } } diff --git a/tests/qapi-schema/reserved-member-q.out b/tests/qapi-schema/reserved-member-q.out new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/qapi-schema/reserved-member-q.out diff --git a/tests/qapi-schema/reserved-member-u.err b/tests/qapi-schema/reserved-member-u.err new file mode 100644 index 0000000000..87d42296cc --- /dev/null +++ b/tests/qapi-schema/reserved-member-u.err @@ -0,0 +1 @@ +tests/qapi-schema/reserved-member-u.json:7: Member of 'data' for struct 'Oops' uses reserved name 'u' diff --git a/tests/qapi-schema/reserved-member-u.exit b/tests/qapi-schema/reserved-member-u.exit new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/tests/qapi-schema/reserved-member-u.exit @@ -0,0 +1 @@ +1 diff --git a/tests/qapi-schema/reserved-member-u.json b/tests/qapi-schema/reserved-member-u.json new file mode 100644 index 0000000000..1eaf0f301c --- /dev/null +++ b/tests/qapi-schema/reserved-member-u.json @@ -0,0 +1,7 @@ +# Potential C member name collision +# We reject use of 'u' as a member name, to allow it for internal use in +# putting union branch members in a separate namespace from QMP members. +# This is true even for non-unions, because it is possible to convert a +# struct to flat union while remaining backwards compatible in QMP. +# TODO - we could munge the member name to 'q_u' to avoid the collision +{ 'struct': 'Oops', 'data': { 'u': 'str' } } diff --git a/tests/qapi-schema/reserved-member-u.out b/tests/qapi-schema/reserved-member-u.out new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/qapi-schema/reserved-member-u.out diff --git a/tests/qapi-schema/reserved-type-kind.err b/tests/qapi-schema/reserved-type-kind.err new file mode 100644 index 0000000000..0a38efaad8 --- /dev/null +++ b/tests/qapi-schema/reserved-type-kind.err @@ -0,0 +1 @@ +tests/qapi-schema/reserved-type-kind.json:2: enum 'UnionKind' should not end in 'Kind' diff --git a/tests/qapi-schema/reserved-type-kind.exit b/tests/qapi-schema/reserved-type-kind.exit new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/tests/qapi-schema/reserved-type-kind.exit @@ -0,0 +1 @@ +1 diff --git a/tests/qapi-schema/enum-union-clash.json b/tests/qapi-schema/reserved-type-kind.json index 593282b6cf..9ecaba12bc 100644 --- a/tests/qapi-schema/enum-union-clash.json +++ b/tests/qapi-schema/reserved-type-kind.json @@ -1,4 +1,2 @@ # we reject types that would conflict with implicit union enum { 'enum': 'UnionKind', 'data': [ 'oops' ] } -{ 'union': 'Union', - 'data': { 'a': 'int' } } diff --git a/tests/qapi-schema/reserved-type-kind.out b/tests/qapi-schema/reserved-type-kind.out new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/qapi-schema/reserved-type-kind.out diff --git a/tests/qapi-schema/reserved-type-list.err b/tests/qapi-schema/reserved-type-list.err new file mode 100644 index 0000000000..4510fa6d90 --- /dev/null +++ b/tests/qapi-schema/reserved-type-list.err @@ -0,0 +1 @@ +tests/qapi-schema/reserved-type-list.json:5: struct 'FooList' should not end in 'List' diff --git a/tests/qapi-schema/reserved-type-list.exit b/tests/qapi-schema/reserved-type-list.exit new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/tests/qapi-schema/reserved-type-list.exit @@ -0,0 +1 @@ +1 diff --git a/tests/qapi-schema/reserved-type-list.json b/tests/qapi-schema/reserved-type-list.json new file mode 100644 index 0000000000..98d53bf808 --- /dev/null +++ b/tests/qapi-schema/reserved-type-list.json @@ -0,0 +1,5 @@ +# Potential C name collision +# We reserve names ending in 'List' for use by array types. +# TODO - we could choose array names to avoid collision with user types, +# in order to let this compile +{ 'struct': 'FooList', 'data': { 's': 'str' } } diff --git a/tests/qapi-schema/reserved-type-list.out b/tests/qapi-schema/reserved-type-list.out new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/qapi-schema/reserved-type-list.out diff --git a/tests/qapi-schema/struct-base-clash-base.exit b/tests/qapi-schema/struct-base-clash-base.exit deleted file mode 100644 index 573541ac97..0000000000 --- a/tests/qapi-schema/struct-base-clash-base.exit +++ /dev/null @@ -1 +0,0 @@ -0 diff --git a/tests/qapi-schema/struct-base-clash-base.json b/tests/qapi-schema/struct-base-clash-base.json deleted file mode 100644 index 0c840258c9..0000000000 --- a/tests/qapi-schema/struct-base-clash-base.json +++ /dev/null @@ -1,9 +0,0 @@ -# Struct member 'base' -# FIXME: this parses, but then fails to compile due to a duplicate 'base' -# (one explicit in QMP, the other used to box the base class members). -# We should either reject the collision at parse time, or change the -# generated struct to allow this to compile. -{ 'struct': 'Base', 'data': {} } -{ 'struct': 'Sub', - 'base': 'Base', - 'data': { 'base': 'str' } } diff --git a/tests/qapi-schema/struct-base-clash-base.out b/tests/qapi-schema/struct-base-clash-base.out deleted file mode 100644 index e69a416560..0000000000 --- a/tests/qapi-schema/struct-base-clash-base.out +++ /dev/null @@ -1,5 +0,0 @@ -object :empty -object Base -object Sub - base Base - member base: str optional=False diff --git a/tests/test-qmp-commands.c b/tests/test-qmp-commands.c index bc59835835..f23d8eaf2a 100644 --- a/tests/test-qmp-commands.c +++ b/tests/test-qmp-commands.c @@ -25,11 +25,9 @@ UserDefTwo *qmp_user_def_cmd2(UserDefOne *ud1a, UserDefOne *ud1d = g_malloc0(sizeof(UserDefOne)); ud1c->string = strdup(ud1a->string); - ud1c->base = g_new0(UserDefZero, 1); - ud1c->base->integer = ud1a->base->integer; + ud1c->integer = ud1a->integer; ud1d->string = strdup(has_udb1 ? ud1b->string : "blah0"); - ud1d->base = g_new0(UserDefZero, 1); - ud1d->base->integer = has_udb1 ? ud1b->base->integer : 0; + ud1d->integer = has_udb1 ? ud1b->integer : 0; ret = g_new0(UserDefTwo, 1); ret->string0 = strdup("blah1"); @@ -64,8 +62,8 @@ __org_qemu_x_Union1 *qmp___org_qemu_x_command(__org_qemu_x_EnumList *a, { __org_qemu_x_Union1 *ret = g_new0(__org_qemu_x_Union1, 1); - ret->kind = ORG_QEMU_X_UNION1_KIND___ORG_QEMU_X_BRANCH; - ret->__org_qemu_x_branch = strdup("blah1"); + ret->type = ORG_QEMU_X_UNION1_KIND___ORG_QEMU_X_BRANCH; + ret->u.__org_qemu_x_branch = strdup("blah1"); return ret; } @@ -176,20 +174,17 @@ static void test_dealloc_types(void) UserDefOneList *ud1list; ud1test = g_malloc0(sizeof(UserDefOne)); - ud1test->base = g_new0(UserDefZero, 1); - ud1test->base->integer = 42; + ud1test->integer = 42; ud1test->string = g_strdup("hi there 42"); qapi_free_UserDefOne(ud1test); ud1a = g_malloc0(sizeof(UserDefOne)); - ud1a->base = g_new0(UserDefZero, 1); - ud1a->base->integer = 43; + ud1a->integer = 43; ud1a->string = g_strdup("hi there 43"); ud1b = g_malloc0(sizeof(UserDefOne)); - ud1b->base = g_new0(UserDefZero, 1); - ud1b->base->integer = 44; + ud1b->integer = 44; ud1b->string = g_strdup("hi there 44"); ud1list = g_malloc0(sizeof(UserDefOneList)); diff --git a/tests/test-qmp-event.c b/tests/test-qmp-event.c index 28f146d4b7..035c65cfdf 100644 --- a/tests/test-qmp-event.c +++ b/tests/test-qmp-event.c @@ -179,9 +179,7 @@ static void test_event_c(TestEventData *data, QDict *d, *d_data, *d_b; UserDefOne b; - UserDefZero z; - z.integer = 2; - b.base = &z; + b.integer = 2; b.string = g_strdup("test1"); b.has_enum1 = false; @@ -209,11 +207,9 @@ static void test_event_d(TestEventData *data, { UserDefOne struct1; EventStructOne a; - UserDefZero z; QDict *d, *d_data, *d_a, *d_struct1; - z.integer = 2; - struct1.base = &z; + struct1.integer = 2; struct1.string = g_strdup("test1"); struct1.has_enum1 = true; struct1.enum1 = ENUM_ONE_VALUE1; diff --git a/tests/test-qmp-input-visitor.c b/tests/test-qmp-input-visitor.c index 8941963c8d..de65982d47 100644 --- a/tests/test-qmp-input-visitor.c +++ b/tests/test-qmp-input-visitor.c @@ -262,7 +262,7 @@ static void test_visitor_in_struct_nested(TestInputVisitorData *data, check_and_free_str(udp->string0, "string0"); check_and_free_str(udp->dict1->string1, "string1"); - g_assert_cmpint(udp->dict1->dict2->userdef->base->integer, ==, 42); + g_assert_cmpint(udp->dict1->dict2->userdef->integer, ==, 42); check_and_free_str(udp->dict1->dict2->userdef->string, "string"); check_and_free_str(udp->dict1->dict2->string, "string2"); g_assert(udp->dict1->has_dict3 == false); @@ -292,7 +292,7 @@ static void test_visitor_in_list(TestInputVisitorData *data, snprintf(string, sizeof(string), "string%d", i); g_assert_cmpstr(item->value->string, ==, string); - g_assert_cmpint(item->value->base->integer, ==, 42 + i); + g_assert_cmpint(item->value->integer, ==, 42 + i); } qapi_free_UserDefOneList(head); @@ -347,6 +347,7 @@ static void test_visitor_in_union_flat(TestInputVisitorData *data, Visitor *v; Error *err = NULL; UserDefFlatUnion *tmp; + UserDefUnionBase *base; v = visitor_input_test_init(data, "{ 'enum1': 'value1', " @@ -359,7 +360,11 @@ static void test_visitor_in_union_flat(TestInputVisitorData *data, g_assert_cmpint(tmp->enum1, ==, ENUM_ONE_VALUE1); g_assert_cmpstr(tmp->string, ==, "str"); g_assert_cmpint(tmp->integer, ==, 41); - g_assert_cmpint(tmp->value1->boolean, ==, true); + g_assert_cmpint(tmp->u.value1->boolean, ==, true); + + base = qapi_UserDefFlatUnion_base(tmp); + g_assert(&base->enum1 == &tmp->enum1); + qapi_free_UserDefFlatUnion(tmp); } @@ -372,15 +377,15 @@ static void test_visitor_in_alternate(TestInputVisitorData *data, v = visitor_input_test_init(data, "42"); visit_type_UserDefAlternate(v, &tmp, NULL, &error_abort); - g_assert_cmpint(tmp->kind, ==, USER_DEF_ALTERNATE_KIND_I); - g_assert_cmpint(tmp->i, ==, 42); + g_assert_cmpint(tmp->type, ==, USER_DEF_ALTERNATE_KIND_I); + g_assert_cmpint(tmp->u.i, ==, 42); qapi_free_UserDefAlternate(tmp); visitor_input_teardown(data, NULL); v = visitor_input_test_init(data, "'string'"); visit_type_UserDefAlternate(v, &tmp, NULL, &error_abort); - g_assert_cmpint(tmp->kind, ==, USER_DEF_ALTERNATE_KIND_S); - g_assert_cmpstr(tmp->s, ==, "string"); + g_assert_cmpint(tmp->type, ==, USER_DEF_ALTERNATE_KIND_S); + g_assert_cmpstr(tmp->u.s, ==, "string"); qapi_free_UserDefAlternate(tmp); visitor_input_teardown(data, NULL); @@ -419,8 +424,8 @@ static void test_visitor_in_alternate_number(TestInputVisitorData *data, * parse the same as ans */ v = visitor_input_test_init(data, "42"); visit_type_AltStrNum(v, &asn, NULL, &err); - /* FIXME g_assert_cmpint(asn->kind, == ALT_STR_NUM_KIND_N); */ - /* FIXME g_assert_cmpfloat(asn->n, ==, 42); */ + /* FIXME g_assert_cmpint(asn->type, == ALT_STR_NUM_KIND_N); */ + /* FIXME g_assert_cmpfloat(asn->u.n, ==, 42); */ g_assert(err); error_free(err); err = NULL; @@ -429,29 +434,29 @@ static void test_visitor_in_alternate_number(TestInputVisitorData *data, v = visitor_input_test_init(data, "42"); visit_type_AltNumStr(v, &ans, NULL, &error_abort); - g_assert_cmpint(ans->kind, ==, ALT_NUM_STR_KIND_N); - g_assert_cmpfloat(ans->n, ==, 42); + g_assert_cmpint(ans->type, ==, ALT_NUM_STR_KIND_N); + g_assert_cmpfloat(ans->u.n, ==, 42); qapi_free_AltNumStr(ans); visitor_input_teardown(data, NULL); v = visitor_input_test_init(data, "42"); visit_type_AltStrInt(v, &asi, NULL, &error_abort); - g_assert_cmpint(asi->kind, ==, ALT_STR_INT_KIND_I); - g_assert_cmpint(asi->i, ==, 42); + g_assert_cmpint(asi->type, ==, ALT_STR_INT_KIND_I); + g_assert_cmpint(asi->u.i, ==, 42); qapi_free_AltStrInt(asi); visitor_input_teardown(data, NULL); v = visitor_input_test_init(data, "42"); visit_type_AltIntNum(v, &ain, NULL, &error_abort); - g_assert_cmpint(ain->kind, ==, ALT_INT_NUM_KIND_I); - g_assert_cmpint(ain->i, ==, 42); + g_assert_cmpint(ain->type, ==, ALT_INT_NUM_KIND_I); + g_assert_cmpint(ain->u.i, ==, 42); qapi_free_AltIntNum(ain); visitor_input_teardown(data, NULL); v = visitor_input_test_init(data, "42"); visit_type_AltNumInt(v, &ani, NULL, &error_abort); - g_assert_cmpint(ani->kind, ==, ALT_NUM_INT_KIND_I); - g_assert_cmpint(ani->i, ==, 42); + g_assert_cmpint(ani->type, ==, ALT_NUM_INT_KIND_I); + g_assert_cmpint(ani->u.i, ==, 42); qapi_free_AltNumInt(ani); visitor_input_teardown(data, NULL); @@ -467,15 +472,15 @@ static void test_visitor_in_alternate_number(TestInputVisitorData *data, v = visitor_input_test_init(data, "42.5"); visit_type_AltStrNum(v, &asn, NULL, &error_abort); - g_assert_cmpint(asn->kind, ==, ALT_STR_NUM_KIND_N); - g_assert_cmpfloat(asn->n, ==, 42.5); + g_assert_cmpint(asn->type, ==, ALT_STR_NUM_KIND_N); + g_assert_cmpfloat(asn->u.n, ==, 42.5); qapi_free_AltStrNum(asn); visitor_input_teardown(data, NULL); v = visitor_input_test_init(data, "42.5"); visit_type_AltNumStr(v, &ans, NULL, &error_abort); - g_assert_cmpint(ans->kind, ==, ALT_NUM_STR_KIND_N); - g_assert_cmpfloat(ans->n, ==, 42.5); + g_assert_cmpint(ans->type, ==, ALT_NUM_STR_KIND_N); + g_assert_cmpfloat(ans->u.n, ==, 42.5); qapi_free_AltNumStr(ans); visitor_input_teardown(data, NULL); @@ -489,15 +494,15 @@ static void test_visitor_in_alternate_number(TestInputVisitorData *data, v = visitor_input_test_init(data, "42.5"); visit_type_AltIntNum(v, &ain, NULL, &error_abort); - g_assert_cmpint(ain->kind, ==, ALT_INT_NUM_KIND_N); - g_assert_cmpfloat(ain->n, ==, 42.5); + g_assert_cmpint(ain->type, ==, ALT_INT_NUM_KIND_N); + g_assert_cmpfloat(ain->u.n, ==, 42.5); qapi_free_AltIntNum(ain); visitor_input_teardown(data, NULL); v = visitor_input_test_init(data, "42.5"); visit_type_AltNumInt(v, &ani, NULL, &error_abort); - g_assert_cmpint(ani->kind, ==, ALT_NUM_INT_KIND_N); - g_assert_cmpfloat(ani->n, ==, 42.5); + g_assert_cmpint(ani->type, ==, ALT_NUM_INT_KIND_N); + g_assert_cmpfloat(ani->u.n, ==, 42.5); qapi_free_AltNumInt(ani); visitor_input_teardown(data, NULL); } @@ -527,68 +532,68 @@ static void test_native_list_integer_helper(TestInputVisitorData *data, visit_type_UserDefNativeListUnion(v, &cvalue, NULL, &err); g_assert(err == NULL); g_assert(cvalue != NULL); - g_assert_cmpint(cvalue->kind, ==, kind); + g_assert_cmpint(cvalue->type, ==, kind); switch (kind) { case USER_DEF_NATIVE_LIST_UNION_KIND_INTEGER: { intList *elem = NULL; - for (i = 0, elem = cvalue->integer; elem; elem = elem->next, i++) { + for (i = 0, elem = cvalue->u.integer; elem; elem = elem->next, i++) { g_assert_cmpint(elem->value, ==, i); } break; } case USER_DEF_NATIVE_LIST_UNION_KIND_S8: { int8List *elem = NULL; - for (i = 0, elem = cvalue->s8; elem; elem = elem->next, i++) { + for (i = 0, elem = cvalue->u.s8; elem; elem = elem->next, i++) { g_assert_cmpint(elem->value, ==, i); } break; } case USER_DEF_NATIVE_LIST_UNION_KIND_S16: { int16List *elem = NULL; - for (i = 0, elem = cvalue->s16; elem; elem = elem->next, i++) { + for (i = 0, elem = cvalue->u.s16; elem; elem = elem->next, i++) { g_assert_cmpint(elem->value, ==, i); } break; } case USER_DEF_NATIVE_LIST_UNION_KIND_S32: { int32List *elem = NULL; - for (i = 0, elem = cvalue->s32; elem; elem = elem->next, i++) { + for (i = 0, elem = cvalue->u.s32; elem; elem = elem->next, i++) { g_assert_cmpint(elem->value, ==, i); } break; } case USER_DEF_NATIVE_LIST_UNION_KIND_S64: { int64List *elem = NULL; - for (i = 0, elem = cvalue->s64; elem; elem = elem->next, i++) { + for (i = 0, elem = cvalue->u.s64; elem; elem = elem->next, i++) { g_assert_cmpint(elem->value, ==, i); } break; } case USER_DEF_NATIVE_LIST_UNION_KIND_U8: { uint8List *elem = NULL; - for (i = 0, elem = cvalue->u8; elem; elem = elem->next, i++) { + for (i = 0, elem = cvalue->u.u8; elem; elem = elem->next, i++) { g_assert_cmpint(elem->value, ==, i); } break; } case USER_DEF_NATIVE_LIST_UNION_KIND_U16: { uint16List *elem = NULL; - for (i = 0, elem = cvalue->u16; elem; elem = elem->next, i++) { + for (i = 0, elem = cvalue->u.u16; elem; elem = elem->next, i++) { g_assert_cmpint(elem->value, ==, i); } break; } case USER_DEF_NATIVE_LIST_UNION_KIND_U32: { uint32List *elem = NULL; - for (i = 0, elem = cvalue->u32; elem; elem = elem->next, i++) { + for (i = 0, elem = cvalue->u.u32; elem; elem = elem->next, i++) { g_assert_cmpint(elem->value, ==, i); } break; } case USER_DEF_NATIVE_LIST_UNION_KIND_U64: { uint64List *elem = NULL; - for (i = 0, elem = cvalue->u64; elem; elem = elem->next, i++) { + for (i = 0, elem = cvalue->u.u64; elem; elem = elem->next, i++) { g_assert_cmpint(elem->value, ==, i); } break; @@ -690,9 +695,9 @@ static void test_visitor_in_native_list_bool(TestInputVisitorData *data, visit_type_UserDefNativeListUnion(v, &cvalue, NULL, &err); g_assert(err == NULL); g_assert(cvalue != NULL); - g_assert_cmpint(cvalue->kind, ==, USER_DEF_NATIVE_LIST_UNION_KIND_BOOLEAN); + g_assert_cmpint(cvalue->type, ==, USER_DEF_NATIVE_LIST_UNION_KIND_BOOLEAN); - for (i = 0, elem = cvalue->boolean; elem; elem = elem->next, i++) { + for (i = 0, elem = cvalue->u.boolean; elem; elem = elem->next, i++) { g_assert_cmpint(elem->value, ==, (i % 3 == 0) ? 1 : 0); } @@ -725,9 +730,9 @@ static void test_visitor_in_native_list_string(TestInputVisitorData *data, visit_type_UserDefNativeListUnion(v, &cvalue, NULL, &err); g_assert(err == NULL); g_assert(cvalue != NULL); - g_assert_cmpint(cvalue->kind, ==, USER_DEF_NATIVE_LIST_UNION_KIND_STRING); + g_assert_cmpint(cvalue->type, ==, USER_DEF_NATIVE_LIST_UNION_KIND_STRING); - for (i = 0, elem = cvalue->string; elem; elem = elem->next, i++) { + for (i = 0, elem = cvalue->u.string; elem; elem = elem->next, i++) { gchar str[8]; sprintf(str, "%d", i); g_assert_cmpstr(elem->value, ==, str); @@ -764,9 +769,9 @@ static void test_visitor_in_native_list_number(TestInputVisitorData *data, visit_type_UserDefNativeListUnion(v, &cvalue, NULL, &err); g_assert(err == NULL); g_assert(cvalue != NULL); - g_assert_cmpint(cvalue->kind, ==, USER_DEF_NATIVE_LIST_UNION_KIND_NUMBER); + g_assert_cmpint(cvalue->type, ==, USER_DEF_NATIVE_LIST_UNION_KIND_NUMBER); - for (i = 0, elem = cvalue->number; elem; elem = elem->next, i++) { + for (i = 0, elem = cvalue->u.number; elem; elem = elem->next, i++) { GString *double_expected = g_string_new(""); GString *double_actual = g_string_new(""); diff --git a/tests/test-qmp-output-visitor.c b/tests/test-qmp-output-visitor.c index c84002e2f2..09d0dd81f0 100644 --- a/tests/test-qmp-output-visitor.c +++ b/tests/test-qmp-output-visitor.c @@ -250,16 +250,14 @@ static void test_visitor_out_struct_nested(TestOutputVisitorData *data, ud2->dict1->dict2 = g_malloc0(sizeof(*ud2->dict1->dict2)); ud2->dict1->dict2->userdef = g_new0(UserDefOne, 1); ud2->dict1->dict2->userdef->string = g_strdup(string); - ud2->dict1->dict2->userdef->base = g_new0(UserDefZero, 1); - ud2->dict1->dict2->userdef->base->integer = value; + ud2->dict1->dict2->userdef->integer = value; ud2->dict1->dict2->string = g_strdup(strings[2]); ud2->dict1->dict3 = g_malloc0(sizeof(*ud2->dict1->dict3)); ud2->dict1->has_dict3 = true; ud2->dict1->dict3->userdef = g_new0(UserDefOne, 1); ud2->dict1->dict3->userdef->string = g_strdup(string); - ud2->dict1->dict3->userdef->base = g_new0(UserDefZero, 1); - ud2->dict1->dict3->userdef->base->integer = value; + ud2->dict1->dict3->userdef->integer = value; ud2->dict1->dict3->string = g_strdup(strings[3]); visit_type_UserDefTwo(data->ov, &ud2, "unused", &err); @@ -301,8 +299,8 @@ static void test_visitor_out_struct_errors(TestOutputVisitorData *data, const void *unused) { EnumOne bad_values[] = { ENUM_ONE_MAX, -1 }; - UserDefZero b; - UserDefOne u = { .base = &b }, *pu = &u; + UserDefOne u = {0}; + UserDefOne *pu = &u; Error *err; int i; @@ -416,8 +414,7 @@ static void test_visitor_out_list_qapi_free(TestOutputVisitorData *data, p->value->dict1->dict2 = g_new0(UserDefTwoDictDict, 1); p->value->dict1->dict2->userdef = g_new0(UserDefOne, 1); p->value->dict1->dict2->userdef->string = g_strdup(string); - p->value->dict1->dict2->userdef->base = g_new0(UserDefZero, 1); - p->value->dict1->dict2->userdef->base->integer = 42; + p->value->dict1->dict2->userdef->integer = 42; p->value->dict1->dict2->string = g_strdup(string); p->value->dict1->has_dict3 = false; @@ -490,9 +487,9 @@ static void test_visitor_out_union_flat(TestOutputVisitorData *data, UserDefFlatUnion *tmp = g_malloc0(sizeof(UserDefFlatUnion)); tmp->enum1 = ENUM_ONE_VALUE1; tmp->string = g_strdup("str"); - tmp->value1 = g_malloc0(sizeof(UserDefA)); - /* TODO when generator bug is fixed: tmp->integer = 41; */ - tmp->value1->boolean = true; + tmp->u.value1 = g_malloc0(sizeof(UserDefA)); + tmp->integer = 41; + tmp->u.value1->boolean = true; visit_type_UserDefFlatUnion(data->ov, &tmp, NULL, &err); g_assert(err == NULL); @@ -503,7 +500,7 @@ static void test_visitor_out_union_flat(TestOutputVisitorData *data, g_assert_cmpstr(qdict_get_str(qdict, "enum1"), ==, "value1"); g_assert_cmpstr(qdict_get_str(qdict, "string"), ==, "str"); - /* TODO g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, 41); */ + g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, 41); g_assert_cmpint(qdict_get_bool(qdict, "boolean"), ==, true); qapi_free_UserDefFlatUnion(tmp); @@ -517,8 +514,8 @@ static void test_visitor_out_alternate(TestOutputVisitorData *data, Error *err = NULL; UserDefAlternate *tmp = g_malloc0(sizeof(UserDefAlternate)); - tmp->kind = USER_DEF_ALTERNATE_KIND_I; - tmp->i = 42; + tmp->type = USER_DEF_ALTERNATE_KIND_I; + tmp->u.i = 42; visit_type_UserDefAlternate(data->ov, &tmp, NULL, &err); g_assert(err == NULL); @@ -543,9 +540,9 @@ static void test_visitor_out_empty(TestOutputVisitorData *data, static void init_native_list(UserDefNativeListUnion *cvalue) { int i; - switch (cvalue->kind) { + switch (cvalue->type) { case USER_DEF_NATIVE_LIST_UNION_KIND_INTEGER: { - intList **list = &cvalue->integer; + intList **list = &cvalue->u.integer; for (i = 0; i < 32; i++) { *list = g_new0(intList, 1); (*list)->value = i; @@ -555,7 +552,7 @@ static void init_native_list(UserDefNativeListUnion *cvalue) break; } case USER_DEF_NATIVE_LIST_UNION_KIND_S8: { - int8List **list = &cvalue->s8; + int8List **list = &cvalue->u.s8; for (i = 0; i < 32; i++) { *list = g_new0(int8List, 1); (*list)->value = i; @@ -565,7 +562,7 @@ static void init_native_list(UserDefNativeListUnion *cvalue) break; } case USER_DEF_NATIVE_LIST_UNION_KIND_S16: { - int16List **list = &cvalue->s16; + int16List **list = &cvalue->u.s16; for (i = 0; i < 32; i++) { *list = g_new0(int16List, 1); (*list)->value = i; @@ -575,7 +572,7 @@ static void init_native_list(UserDefNativeListUnion *cvalue) break; } case USER_DEF_NATIVE_LIST_UNION_KIND_S32: { - int32List **list = &cvalue->s32; + int32List **list = &cvalue->u.s32; for (i = 0; i < 32; i++) { *list = g_new0(int32List, 1); (*list)->value = i; @@ -585,7 +582,7 @@ static void init_native_list(UserDefNativeListUnion *cvalue) break; } case USER_DEF_NATIVE_LIST_UNION_KIND_S64: { - int64List **list = &cvalue->s64; + int64List **list = &cvalue->u.s64; for (i = 0; i < 32; i++) { *list = g_new0(int64List, 1); (*list)->value = i; @@ -595,7 +592,7 @@ static void init_native_list(UserDefNativeListUnion *cvalue) break; } case USER_DEF_NATIVE_LIST_UNION_KIND_U8: { - uint8List **list = &cvalue->u8; + uint8List **list = &cvalue->u.u8; for (i = 0; i < 32; i++) { *list = g_new0(uint8List, 1); (*list)->value = i; @@ -605,7 +602,7 @@ static void init_native_list(UserDefNativeListUnion *cvalue) break; } case USER_DEF_NATIVE_LIST_UNION_KIND_U16: { - uint16List **list = &cvalue->u16; + uint16List **list = &cvalue->u.u16; for (i = 0; i < 32; i++) { *list = g_new0(uint16List, 1); (*list)->value = i; @@ -615,7 +612,7 @@ static void init_native_list(UserDefNativeListUnion *cvalue) break; } case USER_DEF_NATIVE_LIST_UNION_KIND_U32: { - uint32List **list = &cvalue->u32; + uint32List **list = &cvalue->u.u32; for (i = 0; i < 32; i++) { *list = g_new0(uint32List, 1); (*list)->value = i; @@ -625,7 +622,7 @@ static void init_native_list(UserDefNativeListUnion *cvalue) break; } case USER_DEF_NATIVE_LIST_UNION_KIND_U64: { - uint64List **list = &cvalue->u64; + uint64List **list = &cvalue->u.u64; for (i = 0; i < 32; i++) { *list = g_new0(uint64List, 1); (*list)->value = i; @@ -635,7 +632,7 @@ static void init_native_list(UserDefNativeListUnion *cvalue) break; } case USER_DEF_NATIVE_LIST_UNION_KIND_BOOLEAN: { - boolList **list = &cvalue->boolean; + boolList **list = &cvalue->u.boolean; for (i = 0; i < 32; i++) { *list = g_new0(boolList, 1); (*list)->value = (i % 3 == 0); @@ -645,7 +642,7 @@ static void init_native_list(UserDefNativeListUnion *cvalue) break; } case USER_DEF_NATIVE_LIST_UNION_KIND_STRING: { - strList **list = &cvalue->string; + strList **list = &cvalue->u.string; for (i = 0; i < 32; i++) { *list = g_new0(strList, 1); (*list)->value = g_strdup_printf("%d", i); @@ -655,7 +652,7 @@ static void init_native_list(UserDefNativeListUnion *cvalue) break; } case USER_DEF_NATIVE_LIST_UNION_KIND_NUMBER: { - numberList **list = &cvalue->number; + numberList **list = &cvalue->u.number; for (i = 0; i < 32; i++) { *list = g_new0(numberList, 1); (*list)->value = (double)i / 3; @@ -764,14 +761,14 @@ static void test_native_list(TestOutputVisitorData *data, Error *err = NULL; QObject *obj; - cvalue->kind = kind; + cvalue->type = kind; init_native_list(cvalue); visit_type_UserDefNativeListUnion(data->ov, &cvalue, NULL, &err); g_assert(err == NULL); obj = qmp_output_get_qobject(data->qov); - check_native_list(obj, cvalue->kind); + check_native_list(obj, cvalue->type); qapi_free_UserDefNativeListUnion(cvalue); qobject_decref(obj); } diff --git a/tests/test-visitor-serialization.c b/tests/test-visitor-serialization.c index fa86cae88a..634563bae4 100644 --- a/tests/test-visitor-serialization.c +++ b/tests/test-visitor-serialization.c @@ -258,15 +258,13 @@ static UserDefTwo *nested_struct_create(void) udnp->dict1->string1 = strdup("test_string1"); udnp->dict1->dict2 = g_malloc0(sizeof(*udnp->dict1->dict2)); udnp->dict1->dict2->userdef = g_new0(UserDefOne, 1); - udnp->dict1->dict2->userdef->base = g_new0(UserDefZero, 1); - udnp->dict1->dict2->userdef->base->integer = 42; + udnp->dict1->dict2->userdef->integer = 42; udnp->dict1->dict2->userdef->string = strdup("test_string"); udnp->dict1->dict2->string = strdup("test_string2"); udnp->dict1->dict3 = g_malloc0(sizeof(*udnp->dict1->dict3)); udnp->dict1->has_dict3 = true; udnp->dict1->dict3->userdef = g_new0(UserDefOne, 1); - udnp->dict1->dict3->userdef->base = g_new0(UserDefZero, 1); - udnp->dict1->dict3->userdef->base->integer = 43; + udnp->dict1->dict3->userdef->integer = 43; udnp->dict1->dict3->userdef->string = strdup("test_string"); udnp->dict1->dict3->string = strdup("test_string3"); return udnp; @@ -278,15 +276,15 @@ static void nested_struct_compare(UserDefTwo *udnp1, UserDefTwo *udnp2) g_assert(udnp2); g_assert_cmpstr(udnp1->string0, ==, udnp2->string0); g_assert_cmpstr(udnp1->dict1->string1, ==, udnp2->dict1->string1); - g_assert_cmpint(udnp1->dict1->dict2->userdef->base->integer, ==, - udnp2->dict1->dict2->userdef->base->integer); + g_assert_cmpint(udnp1->dict1->dict2->userdef->integer, ==, + udnp2->dict1->dict2->userdef->integer); g_assert_cmpstr(udnp1->dict1->dict2->userdef->string, ==, udnp2->dict1->dict2->userdef->string); g_assert_cmpstr(udnp1->dict1->dict2->string, ==, udnp2->dict1->dict2->string); g_assert(udnp1->dict1->has_dict3 == udnp2->dict1->has_dict3); - g_assert_cmpint(udnp1->dict1->dict3->userdef->base->integer, ==, - udnp2->dict1->dict3->userdef->base->integer); + g_assert_cmpint(udnp1->dict1->dict3->userdef->integer, ==, + udnp2->dict1->dict3->userdef->integer); g_assert_cmpstr(udnp1->dict1->dict3->userdef->string, ==, udnp2->dict1->dict3->userdef->string); g_assert_cmpstr(udnp1->dict1->dict3->string, ==, @@ -260,9 +260,9 @@ static TPMInfo *qmp_query_tpm_inst(TPMBackend *drv) switch (drv->ops->type) { case TPM_TYPE_PASSTHROUGH: - res->options->kind = TPM_TYPE_OPTIONS_KIND_PASSTHROUGH; + res->options->type = TPM_TYPE_OPTIONS_KIND_PASSTHROUGH; tpo = g_new0(TPMPassthroughOptions, 1); - res->options->passthrough = tpo; + res->options->u.passthrough = tpo; if (drv->path) { tpo->path = g_strdup(drv->path); tpo->has_path = true; diff --git a/trace-events b/trace-events index 89b38aa1e4..ea2d32e362 100644 --- a/trace-events +++ b/trace-events @@ -1031,9 +1031,9 @@ esp_pci_sbac_write(uint32_t reg, uint32_t val) "sbac: 0x%8.8x -> 0x%8.8x" # monitor.c handle_qmp_command(void *mon, const char *cmd_name) "mon %p cmd_name \"%s\"" monitor_protocol_emitter(void *mon) "mon %p" -monitor_protocol_event_handler(uint32_t event, void *data, uint64_t last, uint64_t now) "event=%d data=%p last=%" PRId64 " now=%" PRId64 +monitor_protocol_event_handler(uint32_t event, void *qdict) "event=%d data=%p" monitor_protocol_event_emit(uint32_t event, void *data) "event=%d data=%p" -monitor_protocol_event_queue(uint32_t event, void *data, uint64_t rate, uint64_t last, uint64_t now) "event=%d data=%p rate=%" PRId64 " last=%" PRId64 " now=%" PRId64 +monitor_protocol_event_queue(uint32_t event, void *qdict, uint64_t rate) "event=%d data=%p rate=%" PRId64 monitor_protocol_event_throttle(uint32_t event, uint64_t rate) "event=%d rate=%" PRId64 # hw/net/opencores_eth.c @@ -1211,7 +1211,7 @@ savevm_state_begin(void) "" savevm_state_header(void) "" savevm_state_iterate(void) "" savevm_state_complete(void) "" -savevm_state_cancel(void) "" +savevm_state_cleanup(void) "" vmstate_save(const char *idstr, const char *vmsd_name) "%s, %s" vmstate_load(const char *idstr, const char *vmsd_name) "%s, %s" qemu_announce_self_iter(const char *mac) "%s" diff --git a/ui/console.c b/ui/console.c index cf649b2612..f26544eb26 100644 --- a/ui/console.c +++ b/ui/console.c @@ -2016,7 +2016,7 @@ static VcHandler *vc_handler = text_console_init; static CharDriverState *vc_init(const char *id, ChardevBackend *backend, ChardevReturn *ret, Error **errp) { - return vc_handler(backend->vc, errp); + return vc_handler(backend->u.vc, errp); } void register_vc_handler(VcHandler *handler) @@ -2057,30 +2057,30 @@ static void qemu_chr_parse_vc(QemuOpts *opts, ChardevBackend *backend, { int val; - backend->vc = g_new0(ChardevVC, 1); + backend->u.vc = g_new0(ChardevVC, 1); val = qemu_opt_get_number(opts, "width", 0); if (val != 0) { - backend->vc->has_width = true; - backend->vc->width = val; + backend->u.vc->has_width = true; + backend->u.vc->width = val; } val = qemu_opt_get_number(opts, "height", 0); if (val != 0) { - backend->vc->has_height = true; - backend->vc->height = val; + backend->u.vc->has_height = true; + backend->u.vc->height = val; } val = qemu_opt_get_number(opts, "cols", 0); if (val != 0) { - backend->vc->has_cols = true; - backend->vc->cols = val; + backend->u.vc->has_cols = true; + backend->u.vc->cols = val; } val = qemu_opt_get_number(opts, "rows", 0); if (val != 0) { - backend->vc->has_rows = true; - backend->vc->rows = val; + backend->u.vc->has_rows = true; + backend->u.vc->rows = val; } } diff --git a/ui/curses.c b/ui/curses.c index 8edb038bb3..266260a401 100644 --- a/ui/curses.c +++ b/ui/curses.c @@ -42,6 +42,8 @@ static WINDOW *screenpad = NULL; static int width, height, gwidth, gheight, invalidate; static int px, py, sminx, sminy, smaxx, smaxy; +chtype vga_to_curses[256]; + static void curses_update(DisplayChangeListener *dcl, int x, int y, int w, int h) { @@ -341,8 +343,55 @@ static void curses_setup(void) nodelay(stdscr, TRUE); nonl(); keypad(stdscr, TRUE); start_color(); raw(); scrollok(stdscr, FALSE); - for (i = 0; i < 64; i ++) + for (i = 0; i < 64; i++) { init_pair(i, colour_default[i & 7], colour_default[i >> 3]); + } + /* Set default color for more than 64. (monitor uses 0x74xx for example) */ + for (i = 64; i < COLOR_PAIRS; i++) { + init_pair(i, COLOR_WHITE, COLOR_BLACK); + } + + /* + * Setup mapping for vga to curses line graphics. + * FIXME: for better font, have to use ncursesw and setlocale() + */ +#if 0 + /* FIXME: map from where? */ + ACS_S1; + ACS_S3; + ACS_S7; + ACS_S9; +#endif + /* ACS_* is not constant. So, we can't initialize statically. */ + vga_to_curses['\0'] = ' '; + vga_to_curses[0x04] = ACS_DIAMOND; + vga_to_curses[0x0a] = ACS_RARROW; + vga_to_curses[0x0b] = ACS_LARROW; + vga_to_curses[0x18] = ACS_UARROW; + vga_to_curses[0x19] = ACS_DARROW; + vga_to_curses[0x9c] = ACS_STERLING; + vga_to_curses[0xb0] = ACS_BOARD; + vga_to_curses[0xb1] = ACS_CKBOARD; + vga_to_curses[0xb3] = ACS_VLINE; + vga_to_curses[0xb4] = ACS_RTEE; + vga_to_curses[0xbf] = ACS_URCORNER; + vga_to_curses[0xc0] = ACS_LLCORNER; + vga_to_curses[0xc1] = ACS_BTEE; + vga_to_curses[0xc2] = ACS_TTEE; + vga_to_curses[0xc3] = ACS_LTEE; + vga_to_curses[0xc4] = ACS_HLINE; + vga_to_curses[0xc5] = ACS_PLUS; + vga_to_curses[0xce] = ACS_LANTERN; + vga_to_curses[0xd8] = ACS_NEQUAL; + vga_to_curses[0xd9] = ACS_LRCORNER; + vga_to_curses[0xda] = ACS_ULCORNER; + vga_to_curses[0xdb] = ACS_BLOCK; + vga_to_curses[0xe3] = ACS_PI; + vga_to_curses[0xf1] = ACS_PLMINUS; + vga_to_curses[0xf2] = ACS_GEQUAL; + vga_to_curses[0xf3] = ACS_LEQUAL; + vga_to_curses[0xf8] = ACS_DEGREE; + vga_to_curses[0xfe] = ACS_BULLET; } static void curses_keyboard_setup(void) diff --git a/ui/curses_keys.h b/ui/curses_keys.h index 18ce6dceee..f7467449b9 100644 --- a/ui/curses_keys.h +++ b/ui/curses_keys.h @@ -29,8 +29,7 @@ #include "keymaps.h" -#define KEY_RELEASE 0x80 -#define KEY_MASK 0x7f +#define KEY_MASK SCANCODE_KEYMASK #define GREY_CODE 0xe0 #define GREY SCANCODE_GREY #define SHIFT_CODE 0x2a @@ -60,6 +59,8 @@ static const int curses2keysym[CURSES_KEYS] = { ['\n'] = KEY_ENTER, [27] = 27, [KEY_BTAB] = '\t' | KEYSYM_SHIFT, + [KEY_SPREVIOUS] = KEY_PPAGE | KEYSYM_SHIFT, + [KEY_SNEXT] = KEY_NPAGE | KEYSYM_SHIFT, }; static const int curses2keycode[CURSES_KEYS] = { @@ -149,6 +150,9 @@ static const int curses2keycode[CURSES_KEYS] = { [KEY_IC] = 82 | GREY, /* Insert */ [KEY_DC] = 83 | GREY, /* Delete */ + [KEY_SPREVIOUS] = 73 | GREY | SHIFT, /* Shift + Page Up */ + [KEY_SNEXT] = 81 | GREY | SHIFT, /* Shift + Page Down */ + ['!'] = 2 | SHIFT, ['@'] = 3 | SHIFT, ['#'] = 4 | SHIFT, diff --git a/ui/input-keymap.c b/ui/input-keymap.c index 7635cb0dc4..d36be4b60d 100644 --- a/ui/input-keymap.c +++ b/ui/input-keymap.c @@ -139,11 +139,11 @@ static int number_to_qcode[0x100]; int qemu_input_key_value_to_number(const KeyValue *value) { - if (value->kind == KEY_VALUE_KIND_QCODE) { - return qcode_to_number[value->qcode]; + if (value->type == KEY_VALUE_KIND_QCODE) { + return qcode_to_number[value->u.qcode]; } else { - assert(value->kind == KEY_VALUE_KIND_NUMBER); - return value->number; + assert(value->type == KEY_VALUE_KIND_NUMBER); + return value->u.number; } } @@ -166,11 +166,11 @@ int qemu_input_key_number_to_qcode(uint8_t nr) int qemu_input_key_value_to_qcode(const KeyValue *value) { - if (value->kind == KEY_VALUE_KIND_QCODE) { - return value->qcode; + if (value->type == KEY_VALUE_KIND_QCODE) { + return value->u.qcode; } else { - assert(value->kind == KEY_VALUE_KIND_NUMBER); - return qemu_input_key_number_to_qcode(value->number); + assert(value->type == KEY_VALUE_KIND_NUMBER); + return qemu_input_key_number_to_qcode(value->u.number); } } @@ -180,8 +180,8 @@ int qemu_input_key_value_to_scancode(const KeyValue *value, bool down, int keycode = qemu_input_key_value_to_number(value); int count = 0; - if (value->kind == KEY_VALUE_KIND_QCODE && - value->qcode == Q_KEY_CODE_PAUSE) { + if (value->type == KEY_VALUE_KIND_QCODE && + value->u.qcode == Q_KEY_CODE_PAUSE) { /* specific case */ int v = down ? 0 : 0x80; codes[count++] = 0xe1; diff --git a/ui/input-legacy.c b/ui/input-legacy.c index e50f2968e1..a67ed329ce 100644 --- a/ui/input-legacy.c +++ b/ui/input-legacy.c @@ -113,8 +113,8 @@ static void legacy_kbd_event(DeviceState *dev, QemuConsole *src, if (!entry || !entry->put_kbd) { return; } - count = qemu_input_key_value_to_scancode(evt->key->key, - evt->key->down, + count = qemu_input_key_value_to_scancode(evt->u.key->key, + evt->u.key->down, scancodes); for (i = 0; i < count; i++) { entry->put_kbd(entry->opaque, scancodes[i]); @@ -150,21 +150,22 @@ static void legacy_mouse_event(DeviceState *dev, QemuConsole *src, }; QEMUPutMouseEntry *s = (QEMUPutMouseEntry *)dev; - switch (evt->kind) { + switch (evt->type) { case INPUT_EVENT_KIND_BTN: - if (evt->btn->down) { - s->buttons |= bmap[evt->btn->button]; + if (evt->u.btn->down) { + s->buttons |= bmap[evt->u.btn->button]; } else { - s->buttons &= ~bmap[evt->btn->button]; + s->buttons &= ~bmap[evt->u.btn->button]; } - if (evt->btn->down && evt->btn->button == INPUT_BUTTON_WHEEL_UP) { + if (evt->u.btn->down && evt->u.btn->button == INPUT_BUTTON_WHEEL_UP) { s->qemu_put_mouse_event(s->qemu_put_mouse_event_opaque, s->axis[INPUT_AXIS_X], s->axis[INPUT_AXIS_Y], -1, s->buttons); } - if (evt->btn->down && evt->btn->button == INPUT_BUTTON_WHEEL_DOWN) { + if (evt->u.btn->down && + evt->u.btn->button == INPUT_BUTTON_WHEEL_DOWN) { s->qemu_put_mouse_event(s->qemu_put_mouse_event_opaque, s->axis[INPUT_AXIS_X], s->axis[INPUT_AXIS_Y], @@ -173,10 +174,10 @@ static void legacy_mouse_event(DeviceState *dev, QemuConsole *src, } break; case INPUT_EVENT_KIND_ABS: - s->axis[evt->abs->axis] = evt->abs->value; + s->axis[evt->u.abs->axis] = evt->u.abs->value; break; case INPUT_EVENT_KIND_REL: - s->axis[evt->rel->axis] += evt->rel->value; + s->axis[evt->u.rel->axis] += evt->u.rel->value; break; default: break; diff --git a/ui/input.c b/ui/input.c index 1a552d1de1..643f885edf 100644 --- a/ui/input.c +++ b/ui/input.c @@ -147,10 +147,10 @@ void qmp_x_input_send_event(bool has_console, int64_t console, for (e = events; e != NULL; e = e->next) { InputEvent *event = e->value; - if (!qemu_input_find_handler(1 << event->kind, con)) { + if (!qemu_input_find_handler(1 << event->type, con)) { error_setg(errp, "Input handler not found for " "event type %s", - InputEventKind_lookup[event->kind]); + InputEventKind_lookup[event->type]); return; } } @@ -168,22 +168,22 @@ static void qemu_input_transform_abs_rotate(InputEvent *evt) { switch (graphic_rotate) { case 90: - if (evt->abs->axis == INPUT_AXIS_X) { - evt->abs->axis = INPUT_AXIS_Y; - } else if (evt->abs->axis == INPUT_AXIS_Y) { - evt->abs->axis = INPUT_AXIS_X; - evt->abs->value = INPUT_EVENT_ABS_SIZE - 1 - evt->abs->value; + if (evt->u.abs->axis == INPUT_AXIS_X) { + evt->u.abs->axis = INPUT_AXIS_Y; + } else if (evt->u.abs->axis == INPUT_AXIS_Y) { + evt->u.abs->axis = INPUT_AXIS_X; + evt->u.abs->value = INPUT_EVENT_ABS_SIZE - 1 - evt->u.abs->value; } break; case 180: - evt->abs->value = INPUT_EVENT_ABS_SIZE - 1 - evt->abs->value; + evt->u.abs->value = INPUT_EVENT_ABS_SIZE - 1 - evt->u.abs->value; break; case 270: - if (evt->abs->axis == INPUT_AXIS_X) { - evt->abs->axis = INPUT_AXIS_Y; - evt->abs->value = INPUT_EVENT_ABS_SIZE - 1 - evt->abs->value; - } else if (evt->abs->axis == INPUT_AXIS_Y) { - evt->abs->axis = INPUT_AXIS_X; + if (evt->u.abs->axis == INPUT_AXIS_X) { + evt->u.abs->axis = INPUT_AXIS_Y; + evt->u.abs->value = INPUT_EVENT_ABS_SIZE - 1 - evt->u.abs->value; + } else if (evt->u.abs->axis == INPUT_AXIS_Y) { + evt->u.abs->axis = INPUT_AXIS_X; } break; } @@ -197,18 +197,18 @@ static void qemu_input_event_trace(QemuConsole *src, InputEvent *evt) if (src) { idx = qemu_console_get_index(src); } - switch (evt->kind) { + switch (evt->type) { case INPUT_EVENT_KIND_KEY: - switch (evt->key->key->kind) { + switch (evt->u.key->key->type) { case KEY_VALUE_KIND_NUMBER: - qcode = qemu_input_key_number_to_qcode(evt->key->key->number); + qcode = qemu_input_key_number_to_qcode(evt->u.key->key->u.number); name = QKeyCode_lookup[qcode]; - trace_input_event_key_number(idx, evt->key->key->number, - name, evt->key->down); + trace_input_event_key_number(idx, evt->u.key->key->u.number, + name, evt->u.key->down); break; case KEY_VALUE_KIND_QCODE: - name = QKeyCode_lookup[evt->key->key->qcode]; - trace_input_event_key_qcode(idx, name, evt->key->down); + name = QKeyCode_lookup[evt->u.key->key->u.qcode]; + trace_input_event_key_qcode(idx, name, evt->u.key->down); break; case KEY_VALUE_KIND_MAX: /* keep gcc happy */ @@ -216,16 +216,16 @@ static void qemu_input_event_trace(QemuConsole *src, InputEvent *evt) } break; case INPUT_EVENT_KIND_BTN: - name = InputButton_lookup[evt->btn->button]; - trace_input_event_btn(idx, name, evt->btn->down); + name = InputButton_lookup[evt->u.btn->button]; + trace_input_event_btn(idx, name, evt->u.btn->down); break; case INPUT_EVENT_KIND_REL: - name = InputAxis_lookup[evt->rel->axis]; - trace_input_event_rel(idx, name, evt->rel->value); + name = InputAxis_lookup[evt->u.rel->axis]; + trace_input_event_rel(idx, name, evt->u.rel->value); break; case INPUT_EVENT_KIND_ABS: - name = InputAxis_lookup[evt->abs->axis]; - trace_input_event_abs(idx, name, evt->abs->value); + name = InputAxis_lookup[evt->u.abs->axis]; + trace_input_event_abs(idx, name, evt->u.abs->value); break; case INPUT_EVENT_KIND_MAX: /* keep gcc happy */ @@ -311,12 +311,12 @@ void qemu_input_event_send(QemuConsole *src, InputEvent *evt) qemu_input_event_trace(src, evt); /* pre processing */ - if (graphic_rotate && (evt->kind == INPUT_EVENT_KIND_ABS)) { + if (graphic_rotate && (evt->type == INPUT_EVENT_KIND_ABS)) { qemu_input_transform_abs_rotate(evt); } /* send event */ - s = qemu_input_find_handler(1 << evt->kind, src); + s = qemu_input_find_handler(1 << evt->type, src); if (!s) { return; } @@ -348,10 +348,10 @@ void qemu_input_event_sync(void) InputEvent *qemu_input_event_new_key(KeyValue *key, bool down) { InputEvent *evt = g_new0(InputEvent, 1); - evt->key = g_new0(InputKeyEvent, 1); - evt->kind = INPUT_EVENT_KIND_KEY; - evt->key->key = key; - evt->key->down = down; + evt->u.key = g_new0(InputKeyEvent, 1); + evt->type = INPUT_EVENT_KIND_KEY; + evt->u.key->key = key; + evt->u.key->down = down; return evt; } @@ -372,16 +372,16 @@ void qemu_input_event_send_key(QemuConsole *src, KeyValue *key, bool down) void qemu_input_event_send_key_number(QemuConsole *src, int num, bool down) { KeyValue *key = g_new0(KeyValue, 1); - key->kind = KEY_VALUE_KIND_NUMBER; - key->number = num; + key->type = KEY_VALUE_KIND_NUMBER; + key->u.number = num; qemu_input_event_send_key(src, key, down); } void qemu_input_event_send_key_qcode(QemuConsole *src, QKeyCode q, bool down) { KeyValue *key = g_new0(KeyValue, 1); - key->kind = KEY_VALUE_KIND_QCODE; - key->qcode = q; + key->type = KEY_VALUE_KIND_QCODE; + key->u.qcode = q; qemu_input_event_send_key(src, key, down); } @@ -398,10 +398,10 @@ void qemu_input_event_send_key_delay(uint32_t delay_ms) InputEvent *qemu_input_event_new_btn(InputButton btn, bool down) { InputEvent *evt = g_new0(InputEvent, 1); - evt->btn = g_new0(InputBtnEvent, 1); - evt->kind = INPUT_EVENT_KIND_BTN; - evt->btn->button = btn; - evt->btn->down = down; + evt->u.btn = g_new0(InputBtnEvent, 1); + evt->type = INPUT_EVENT_KIND_BTN; + evt->u.btn->button = btn; + evt->u.btn->down = down; return evt; } @@ -451,8 +451,8 @@ InputEvent *qemu_input_event_new_move(InputEventKind kind, InputEvent *evt = g_new0(InputEvent, 1); InputMoveEvent *move = g_new0(InputMoveEvent, 1); - evt->kind = kind; - evt->data = move; + evt->type = kind; + evt->u.data = move; move->axis = axis; move->value = value; return evt; diff --git a/ui/spice-core.c b/ui/spice-core.c index bf4fd07499..6a62d712fe 100644 --- a/ui/spice-core.c +++ b/ui/spice-core.c @@ -200,8 +200,6 @@ static void channel_event(int event, SpiceChannelEventInfo *info) { SpiceServerInfo *server = g_malloc0(sizeof(*server)); SpiceChannel *client = g_malloc0(sizeof(*client)); - server->base = g_malloc0(sizeof(*server->base)); - client->base = g_malloc0(sizeof(*client->base)); /* * Spice server might have called us from spice worker thread @@ -218,9 +216,11 @@ static void channel_event(int event, SpiceChannelEventInfo *info) } if (info->flags & SPICE_CHANNEL_EVENT_FLAG_ADDR_EXT) { - add_addr_info(client->base, (struct sockaddr *)&info->paddr_ext, + add_addr_info(qapi_SpiceChannel_base(client), + (struct sockaddr *)&info->paddr_ext, info->plen_ext); - add_addr_info(server->base, (struct sockaddr *)&info->laddr_ext, + add_addr_info(qapi_SpiceServerInfo_base(server), + (struct sockaddr *)&info->laddr_ext, info->llen_ext); } else { error_report("spice: %s, extended address is expected", @@ -229,7 +229,9 @@ static void channel_event(int event, SpiceChannelEventInfo *info) switch (event) { case SPICE_CHANNEL_EVENT_CONNECTED: - qapi_event_send_spice_connected(server->base, client->base, &error_abort); + qapi_event_send_spice_connected(qapi_SpiceServerInfo_base(server), + qapi_SpiceChannel_base(client), + &error_abort); break; case SPICE_CHANNEL_EVENT_INITIALIZED: if (auth) { @@ -242,7 +244,9 @@ static void channel_event(int event, SpiceChannelEventInfo *info) break; case SPICE_CHANNEL_EVENT_DISCONNECTED: channel_list_del(info); - qapi_event_send_spice_disconnected(server->base, client->base, &error_abort); + qapi_event_send_spice_disconnected(qapi_SpiceServerInfo_base(server), + qapi_SpiceChannel_base(client), + &error_abort); break; default: break; @@ -378,16 +382,15 @@ static SpiceChannelList *qmp_query_spice_channels(void) chan = g_malloc0(sizeof(*chan)); chan->value = g_malloc0(sizeof(*chan->value)); - chan->value->base = g_malloc0(sizeof(*chan->value->base)); paddr = (struct sockaddr *)&item->info->paddr_ext; plen = item->info->plen_ext; getnameinfo(paddr, plen, host, sizeof(host), port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV); - chan->value->base->host = g_strdup(host); - chan->value->base->port = g_strdup(port); - chan->value->base->family = inet_netfamily(paddr->sa_family); + chan->value->host = g_strdup(host); + chan->value->port = g_strdup(port); + chan->value->family = inet_netfamily(paddr->sa_family); chan->value->connection_id = item->info->connection_id; chan->value->channel_type = item->info->type; @@ -156,10 +156,11 @@ char *vnc_socket_remote_addr(const char *format, int fd) { return addr_to_string(format, &sa, salen); } -static VncBasicInfo *vnc_basic_info_get(struct sockaddr_storage *sa, - socklen_t salen) +static void vnc_init_basic_info(struct sockaddr_storage *sa, + socklen_t salen, + VncBasicInfo *info, + Error **errp) { - VncBasicInfo *info; char host[NI_MAXHOST]; char serv[NI_MAXSERV]; int err; @@ -168,42 +169,44 @@ static VncBasicInfo *vnc_basic_info_get(struct sockaddr_storage *sa, host, sizeof(host), serv, sizeof(serv), NI_NUMERICHOST | NI_NUMERICSERV)) != 0) { - VNC_DEBUG("Cannot resolve address %d: %s\n", - err, gai_strerror(err)); - return NULL; + error_setg(errp, "Cannot resolve address: %s", + gai_strerror(err)); + return; } - info = g_malloc0(sizeof(VncBasicInfo)); info->host = g_strdup(host); info->service = g_strdup(serv); info->family = inet_netfamily(sa->ss_family); - return info; } -static VncBasicInfo *vnc_basic_info_get_from_server_addr(int fd) +static void vnc_init_basic_info_from_server_addr(int fd, VncBasicInfo *info, + Error **errp) { struct sockaddr_storage sa; socklen_t salen; salen = sizeof(sa); if (getsockname(fd, (struct sockaddr*)&sa, &salen) < 0) { - return NULL; + error_setg_errno(errp, errno, "getsockname failed"); + return; } - return vnc_basic_info_get(&sa, salen); + vnc_init_basic_info(&sa, salen, info, errp); } -static VncBasicInfo *vnc_basic_info_get_from_remote_addr(int fd) +static void vnc_init_basic_info_from_remote_addr(int fd, VncBasicInfo *info, + Error **errp) { struct sockaddr_storage sa; socklen_t salen; salen = sizeof(sa); if (getpeername(fd, (struct sockaddr*)&sa, &salen) < 0) { - return NULL; + error_setg_errno(errp, errno, "getpeername failed"); + return; } - return vnc_basic_info_get(&sa, salen); + vnc_init_basic_info(&sa, salen, info, errp); } static const char *vnc_auth_name(VncDisplay *vd) { @@ -256,15 +259,18 @@ static const char *vnc_auth_name(VncDisplay *vd) { static VncServerInfo *vnc_server_info_get(VncDisplay *vd) { VncServerInfo *info; - VncBasicInfo *bi = vnc_basic_info_get_from_server_addr(vd->lsock); - if (!bi) { - return NULL; - } + Error *err = NULL; info = g_malloc(sizeof(*info)); - info->base = bi; + vnc_init_basic_info_from_server_addr(vd->lsock, + qapi_VncServerInfo_base(info), &err); info->has_auth = true; info->auth = g_strdup(vnc_auth_name(vd)); + if (err) { + qapi_free_VncServerInfo(info); + info = NULL; + error_free(err); + } return info; } @@ -291,11 +297,16 @@ static void vnc_client_cache_auth(VncState *client) static void vnc_client_cache_addr(VncState *client) { - VncBasicInfo *bi = vnc_basic_info_get_from_remote_addr(client->csock); + Error *err = NULL; - if (bi) { - client->info = g_malloc0(sizeof(*client->info)); - client->info->base = bi; + client->info = g_malloc0(sizeof(*client->info)); + vnc_init_basic_info_from_remote_addr(client->csock, + qapi_VncClientInfo_base(client->info), + &err); + if (err) { + qapi_free_VncClientInfo(client->info); + client->info = NULL; + error_free(err); } } @@ -306,7 +317,6 @@ static void vnc_qmp_event(VncState *vs, QAPIEvent event) if (!vs->info) { return; } - g_assert(vs->info->base); si = vnc_server_info_get(vs->vd); if (!si) { @@ -315,7 +325,8 @@ static void vnc_qmp_event(VncState *vs, QAPIEvent event) switch (event) { case QAPI_EVENT_VNC_CONNECTED: - qapi_event_send_vnc_connected(si, vs->info->base, &error_abort); + qapi_event_send_vnc_connected(si, qapi_VncClientInfo_base(vs->info), + &error_abort); break; case QAPI_EVENT_VNC_INITIALIZED: qapi_event_send_vnc_initialized(si, vs->info, &error_abort); @@ -350,11 +361,10 @@ static VncClientInfo *qmp_query_vnc_client(const VncState *client) } info = g_malloc0(sizeof(*info)); - info->base = g_malloc0(sizeof(*info->base)); - info->base->host = g_strdup(host); - info->base->service = g_strdup(serv); - info->base->family = inet_netfamily(sa.ss_family); - info->base->websocket = client->websocket; + info->host = g_strdup(host); + info->service = g_strdup(serv); + info->family = inet_netfamily(sa.ss_family); + info->websocket = client->websocket; if (client->tls) { info->x509_dname = qcrypto_tls_session_get_peer_name(client->tls); @@ -830,6 +840,8 @@ int vnc_raw_send_framebuffer_update(VncState *vs, int x, int y, int w, int h) int vnc_send_framebuffer_update(VncState *vs, int x, int y, int w, int h) { int n = 0; + bool encode_raw = false; + size_t saved_offs = vs->output.offset; switch(vs->vnc_encoding) { case VNC_ENCODING_ZLIB: @@ -852,10 +864,24 @@ int vnc_send_framebuffer_update(VncState *vs, int x, int y, int w, int h) n = vnc_zywrle_send_framebuffer_update(vs, x, y, w, h); break; default: - vnc_framebuffer_update(vs, x, y, w, h, VNC_ENCODING_RAW); - n = vnc_raw_send_framebuffer_update(vs, x, y, w, h); + encode_raw = true; break; } + + /* If the client has the same pixel format as our internal buffer and + * a RAW encoding would need less space fall back to RAW encoding to + * save bandwidth and processing power in the client. */ + if (!encode_raw && vs->write_pixels == vnc_write_pixels_copy && + 12 + h * w * VNC_SERVER_FB_BYTES <= (vs->output.offset - saved_offs)) { + vs->output.offset = saved_offs; + encode_raw = true; + } + + if (encode_raw) { + vnc_framebuffer_update(vs, x, y, w, h, VNC_ENCODING_RAW); + n = vnc_raw_send_framebuffer_update(vs, x, y, w, h); + } + return n; } @@ -3514,9 +3540,9 @@ void vnc_display_open(const char *id, Error **errp) } if (strncmp(vnc, "unix:", 5) == 0) { - saddr->kind = SOCKET_ADDRESS_KIND_UNIX; - saddr->q_unix = g_new0(UnixSocketAddress, 1); - saddr->q_unix->path = g_strdup(vnc + 5); + saddr->type = SOCKET_ADDRESS_KIND_UNIX; + saddr->u.q_unix = g_new0(UnixSocketAddress, 1); + saddr->u.q_unix->path = g_strdup(vnc + 5); if (vs->ws_enabled) { error_setg(errp, "UNIX sockets not supported with websock"); @@ -3524,12 +3550,12 @@ void vnc_display_open(const char *id, Error **errp) } } else { unsigned long long baseport; - saddr->kind = SOCKET_ADDRESS_KIND_INET; - saddr->inet = g_new0(InetSocketAddress, 1); + saddr->type = SOCKET_ADDRESS_KIND_INET; + saddr->u.inet = g_new0(InetSocketAddress, 1); if (vnc[0] == '[' && vnc[hlen - 1] == ']') { - saddr->inet->host = g_strndup(vnc + 1, hlen - 2); + saddr->u.inet->host = g_strndup(vnc + 1, hlen - 2); } else { - saddr->inet->host = g_strndup(vnc, hlen); + saddr->u.inet->host = g_strndup(vnc, hlen); } if (parse_uint_full(h + 1, &baseport, 10) < 0) { error_setg(errp, "can't convert to a number: %s", h + 1); @@ -3540,28 +3566,30 @@ void vnc_display_open(const char *id, Error **errp) error_setg(errp, "port %s out of range", h + 1); goto fail; } - saddr->inet->port = g_strdup_printf( + saddr->u.inet->port = g_strdup_printf( "%d", (int)baseport + 5900); if (to) { - saddr->inet->has_to = true; - saddr->inet->to = to; + saddr->u.inet->has_to = true; + saddr->u.inet->to = to; + saddr->u.inet->has_to = true; + saddr->u.inet->to = to + 5900; } - saddr->inet->ipv4 = saddr->inet->has_ipv4 = has_ipv4; - saddr->inet->ipv6 = saddr->inet->has_ipv6 = has_ipv6; + saddr->u.inet->ipv4 = saddr->u.inet->has_ipv4 = has_ipv4; + saddr->u.inet->ipv6 = saddr->u.inet->has_ipv6 = has_ipv6; if (vs->ws_enabled) { - wsaddr->kind = SOCKET_ADDRESS_KIND_INET; - wsaddr->inet = g_new0(InetSocketAddress, 1); - wsaddr->inet->host = g_strdup(saddr->inet->host); - wsaddr->inet->port = g_strdup(websocket); + wsaddr->type = SOCKET_ADDRESS_KIND_INET; + wsaddr->u.inet = g_new0(InetSocketAddress, 1); + wsaddr->u.inet->host = g_strdup(saddr->u.inet->host); + wsaddr->u.inet->port = g_strdup(websocket); if (to) { - wsaddr->inet->has_to = true; - wsaddr->inet->to = to; + wsaddr->u.inet->has_to = true; + wsaddr->u.inet->to = to; } - wsaddr->inet->ipv4 = wsaddr->inet->has_ipv4 = has_ipv4; - wsaddr->inet->ipv6 = wsaddr->inet->has_ipv6 = has_ipv6; + wsaddr->u.inet->ipv4 = wsaddr->u.inet->has_ipv4 = has_ipv4; + wsaddr->u.inet->ipv6 = wsaddr->u.inet->has_ipv6 = has_ipv6; } } } else { @@ -3760,7 +3788,7 @@ void vnc_display_open(const char *id, Error **errp) if (csock < 0) { goto fail; } - vs->is_unix = saddr->kind == SOCKET_ADDRESS_KIND_UNIX; + vs->is_unix = saddr->type == SOCKET_ADDRESS_KIND_UNIX; vnc_connect(vs, csock, false, false); } else { /* listen for connects */ @@ -3768,7 +3796,7 @@ void vnc_display_open(const char *id, Error **errp) if (vs->lsock < 0) { goto fail; } - vs->is_unix = saddr->kind == SOCKET_ADDRESS_KIND_UNIX; + vs->is_unix = saddr->type == SOCKET_ADDRESS_KIND_UNIX; if (vs->ws_enabled) { vs->lwebsock = socket_listen(wsaddr, errp); if (vs->lwebsock < 0) { diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c index 9142917be5..dfe45875f8 100644 --- a/util/qemu-sockets.c +++ b/util/qemu-sockets.c @@ -918,23 +918,23 @@ SocketAddress *socket_parse(const char *str, Error **errp) error_setg(errp, "invalid Unix socket address"); goto fail; } else { - addr->kind = SOCKET_ADDRESS_KIND_UNIX; - addr->q_unix = g_new(UnixSocketAddress, 1); - addr->q_unix->path = g_strdup(str + 5); + addr->type = SOCKET_ADDRESS_KIND_UNIX; + addr->u.q_unix = g_new(UnixSocketAddress, 1); + addr->u.q_unix->path = g_strdup(str + 5); } } else if (strstart(str, "fd:", NULL)) { if (str[3] == '\0') { error_setg(errp, "invalid file descriptor address"); goto fail; } else { - addr->kind = SOCKET_ADDRESS_KIND_FD; - addr->fd = g_new(String, 1); - addr->fd->str = g_strdup(str + 3); + addr->type = SOCKET_ADDRESS_KIND_FD; + addr->u.fd = g_new(String, 1); + addr->u.fd->str = g_strdup(str + 3); } } else { - addr->kind = SOCKET_ADDRESS_KIND_INET; - addr->inet = inet_parse(str, errp); - if (addr->inet == NULL) { + addr->type = SOCKET_ADDRESS_KIND_INET; + addr->u.inet = inet_parse(str, errp); + if (addr->u.inet == NULL) { goto fail; } } @@ -952,19 +952,19 @@ int socket_connect(SocketAddress *addr, Error **errp, int fd; opts = qemu_opts_create(&socket_optslist, NULL, 0, &error_abort); - switch (addr->kind) { + switch (addr->type) { case SOCKET_ADDRESS_KIND_INET: - inet_addr_to_opts(opts, addr->inet); + inet_addr_to_opts(opts, addr->u.inet); fd = inet_connect_opts(opts, errp, callback, opaque); break; case SOCKET_ADDRESS_KIND_UNIX: - qemu_opt_set(opts, "path", addr->q_unix->path, &error_abort); + qemu_opt_set(opts, "path", addr->u.q_unix->path, &error_abort); fd = unix_connect_opts(opts, errp, callback, opaque); break; case SOCKET_ADDRESS_KIND_FD: - fd = monitor_get_fd(cur_mon, addr->fd->str, errp); + fd = monitor_get_fd(cur_mon, addr->u.fd->str, errp); if (fd >= 0 && callback) { qemu_set_nonblock(fd); callback(fd, NULL, opaque); @@ -984,19 +984,19 @@ int socket_listen(SocketAddress *addr, Error **errp) int fd; opts = qemu_opts_create(&socket_optslist, NULL, 0, &error_abort); - switch (addr->kind) { + switch (addr->type) { case SOCKET_ADDRESS_KIND_INET: - inet_addr_to_opts(opts, addr->inet); + inet_addr_to_opts(opts, addr->u.inet); fd = inet_listen_opts(opts, 0, errp); break; case SOCKET_ADDRESS_KIND_UNIX: - qemu_opt_set(opts, "path", addr->q_unix->path, &error_abort); + qemu_opt_set(opts, "path", addr->u.q_unix->path, &error_abort); fd = unix_listen_opts(opts, errp); break; case SOCKET_ADDRESS_KIND_FD: - fd = monitor_get_fd(cur_mon, addr->fd->str, errp); + fd = monitor_get_fd(cur_mon, addr->u.fd->str, errp); break; default: @@ -1012,12 +1012,12 @@ int socket_dgram(SocketAddress *remote, SocketAddress *local, Error **errp) int fd; opts = qemu_opts_create(&socket_optslist, NULL, 0, &error_abort); - switch (remote->kind) { + switch (remote->type) { case SOCKET_ADDRESS_KIND_INET: - inet_addr_to_opts(opts, remote->inet); + inet_addr_to_opts(opts, remote->u.inet); if (local) { - qemu_opt_set(opts, "localaddr", local->inet->host, &error_abort); - qemu_opt_set(opts, "localport", local->inet->port, &error_abort); + qemu_opt_set(opts, "localaddr", local->u.inet->host, &error_abort); + qemu_opt_set(opts, "localport", local->u.inet->port, &error_abort); } fd = inet_dgram_opts(opts, errp); break; @@ -1052,14 +1052,14 @@ socket_sockaddr_to_address_inet(struct sockaddr_storage *sa, } addr = g_new0(SocketAddress, 1); - addr->kind = SOCKET_ADDRESS_KIND_INET; - addr->inet = g_new0(InetSocketAddress, 1); - addr->inet->host = g_strdup(host); - addr->inet->port = g_strdup(serv); + addr->type = SOCKET_ADDRESS_KIND_INET; + addr->u.inet = g_new0(InetSocketAddress, 1); + addr->u.inet->host = g_strdup(host); + addr->u.inet->port = g_strdup(serv); if (sa->ss_family == AF_INET) { - addr->inet->has_ipv4 = addr->inet->ipv4 = true; + addr->u.inet->has_ipv4 = addr->u.inet->ipv4 = true; } else { - addr->inet->has_ipv6 = addr->inet->ipv6 = true; + addr->u.inet->has_ipv6 = addr->u.inet->ipv6 = true; } return addr; @@ -1076,11 +1076,11 @@ socket_sockaddr_to_address_unix(struct sockaddr_storage *sa, struct sockaddr_un *su = (struct sockaddr_un *)sa; addr = g_new0(SocketAddress, 1); - addr->kind = SOCKET_ADDRESS_KIND_UNIX; - addr->q_unix = g_new0(UnixSocketAddress, 1); + addr->type = SOCKET_ADDRESS_KIND_UNIX; + addr->u.q_unix = g_new0(UnixSocketAddress, 1); if (su->sun_path[0]) { - addr->q_unix->path = g_strndup(su->sun_path, - sizeof(su->sun_path)); + addr->u.q_unix->path = g_strndup(su->sun_path, + sizeof(su->sun_path)); } return addr; @@ -674,9 +674,9 @@ void runstate_set(RunState new_state) assert(new_state < RUN_STATE_MAX); if (!runstate_valid_transitions[current_run_state][new_state]) { - fprintf(stderr, "ERROR: invalid runstate transition: '%s' -> '%s'\n", - RunState_lookup[current_run_state], - RunState_lookup[new_state]); + error_report("invalid runstate transition: '%s' -> '%s'", + RunState_lookup[current_run_state], + RunState_lookup[new_state]); abort(); } trace_runstate_set(new_state); @@ -828,8 +828,9 @@ static void configure_rtc_date_offset(const char *startdate, int legacy) rtc_start_date = mktimegm(&tm); if (rtc_start_date == -1) { date_fail: - fprintf(stderr, "Invalid date format. Valid formats are:\n" - "'2006-06-17T16:01:21' or '2006-06-17'\n"); + error_report("invalid date format"); + error_printf("valid formats: " + "'2006-06-17T16:01:21' or '2006-06-17'\n"); exit(1); } rtc_date_offset = qemu_time() - rtc_start_date; @@ -859,7 +860,7 @@ static void configure_rtc(QemuOpts *opts) } else if (!strcmp(value, "vm")) { rtc_clock = QEMU_CLOCK_VIRTUAL; } else { - fprintf(stderr, "qemu: invalid option value '%s'\n", value); + error_report("invalid option value '%s'", value); exit(1); } } @@ -879,7 +880,7 @@ static void configure_rtc(QemuOpts *opts) } else if (!strcmp(value, "none")) { /* discard is default */ } else { - fprintf(stderr, "qemu: invalid option value '%s'\n", value); + error_report("invalid option value '%s'", value); exit(1); } } @@ -905,7 +906,7 @@ static int bt_hci_parse(const char *str) bdaddr_t bdaddr; if (nb_hcis >= MAX_NICS) { - fprintf(stderr, "qemu: Too many bluetooth HCIs (max %i).\n", MAX_NICS); + error_report("too many bluetooth HCIs (max %i)", MAX_NICS); return -1; } @@ -931,8 +932,8 @@ static void bt_vhci_add(int vlan_id) struct bt_scatternet_s *vlan = qemu_find_bt_vlan(vlan_id); if (!vlan->slave) - fprintf(stderr, "qemu: warning: adding a VHCI to " - "an empty scatternet %i\n", vlan_id); + error_report("warning: adding a VHCI to an empty scatternet %i", + vlan_id); bt_vhci_init(bt_new_hci(vlan)); } @@ -950,7 +951,7 @@ static struct bt_device_s *bt_device_add(const char *opt) if (endp) { vlan_id = strtol(endp + 6, &endp, 0); if (*endp) { - fprintf(stderr, "qemu: unrecognised bluetooth vlan Id\n"); + error_report("unrecognised bluetooth vlan Id"); return 0; } } @@ -958,13 +959,13 @@ static struct bt_device_s *bt_device_add(const char *opt) vlan = qemu_find_bt_vlan(vlan_id); if (!vlan->slave) - fprintf(stderr, "qemu: warning: adding a slave device to " - "an empty scatternet %i\n", vlan_id); + error_report("warning: adding a slave device to an empty scatternet %i", + vlan_id); if (!strcmp(devname, "keyboard")) return bt_keyboard_init(vlan); - fprintf(stderr, "qemu: unsupported bluetooth device `%s'\n", devname); + error_report("unsupported bluetooth device '%s'", devname); return 0; } @@ -987,11 +988,11 @@ static int bt_parse(const char *opt) if (strstart(endp, ",vlan=", &p)) { vlan = strtol(p, (char **) &endp, 0); if (*endp) { - fprintf(stderr, "qemu: bad scatternet '%s'\n", p); + error_report("bad scatternet '%s'", p); return 1; } } else { - fprintf(stderr, "qemu: bad parameter '%s'\n", endp + 1); + error_report("bad parameter '%s'", endp + 1); return 1; } } else @@ -1003,7 +1004,7 @@ static int bt_parse(const char *opt) } else if (strstart(opt, "device:", &endp)) return !bt_device_add(endp); - fprintf(stderr, "qemu: bad bluetooth parameter '%s'\n", opt); + error_report("bad bluetooth parameter '%s'", opt); return 1; } @@ -1018,8 +1019,7 @@ static int parse_sandbox(void *opaque, QemuOpts *opts, Error **errp) return -1; } #else - error_report("sandboxing request but seccomp is not compiled " - "into this build"); + error_report("seccomp support is disabled"); return -1; #endif } @@ -1100,7 +1100,7 @@ static int parse_add_fd(void *opaque, QemuOpts *opts, Error **errp) } #endif if (dupfd == -1) { - error_report("Error duplicating fd: %s", strerror(errno)); + error_report("error duplicating fd: %s", strerror(errno)); return -1; } @@ -1220,18 +1220,19 @@ static void smp_parse(QemuOpts *opts) } else if (threads == 0) { threads = cpus / (cores * sockets); } else if (sockets * cores * threads < cpus) { - fprintf(stderr, "cpu topology: error: " - "sockets (%u) * cores (%u) * threads (%u) < " - "smp_cpus (%u)\n", - sockets, cores, threads, cpus); + error_report("cpu topology: " + "sockets (%u) * cores (%u) * threads (%u) < " + "smp_cpus (%u)", + sockets, cores, threads, cpus); exit(1); } max_cpus = qemu_opt_get_number(opts, "maxcpus", cpus); if (sockets * cores * threads > max_cpus) { - fprintf(stderr, "cpu topology: error: " - "sockets (%u) * cores (%u) * threads (%u) > maxcpus (%u)\n", - sockets, cores, threads, max_cpus); + error_report("cpu topology: " + "sockets (%u) * cores (%u) * threads (%u) > " + "maxcpus (%u)", + sockets, cores, threads, max_cpus); exit(1); } @@ -1246,11 +1247,11 @@ static void smp_parse(QemuOpts *opts) } if (max_cpus > MAX_CPUMASK_BITS) { - fprintf(stderr, "Unsupported number of maxcpus\n"); + error_report("unsupported number of maxcpus"); exit(1); } if (max_cpus < smp_cpus) { - fprintf(stderr, "maxcpus must be equal to or greater than smp\n"); + error_report("maxcpus must be equal to or greater than smp"); exit(1); } @@ -1260,7 +1261,7 @@ static void realtime_init(void) { if (enable_mlock) { if (os_mlock() < 0) { - fprintf(stderr, "qemu: locking memory failed\n"); + error_report("locking memory failed"); exit(1); } } @@ -1414,7 +1415,7 @@ static int usb_parse(const char *cmdline) int r; r = usb_device_add(cmdline); if (r < 0) { - fprintf(stderr, "qemu: could not add USB device '%s'\n", cmdline); + error_report("could not add USB device '%s'", cmdline); } return r; } @@ -1624,14 +1625,14 @@ static int qemu_shutdown_requested(void) static void qemu_kill_report(void) { if (!qtest_driver() && shutdown_signal != -1) { - fprintf(stderr, "qemu: terminating on signal %d", shutdown_signal); if (shutdown_pid == 0) { /* This happens for eg ^C at the terminal, so it's worth * avoiding printing an odd message in that case. */ - fputc('\n', stderr); + error_report("terminating on signal %d", shutdown_signal); } else { - fprintf(stderr, " from pid " FMT_pid "\n", shutdown_pid); + error_report("terminating on signal %d from pid " FMT_pid, + shutdown_signal, shutdown_pid); } shutdown_signal = -1; } @@ -1980,28 +1981,28 @@ static void select_vgahw (const char *p) if (vga_available()) { vga_interface_type = VGA_STD; } else { - fprintf(stderr, "Error: standard VGA not available\n"); + error_report("standard VGA not available"); exit(0); } } else if (strstart(p, "cirrus", &opts)) { if (cirrus_vga_available()) { vga_interface_type = VGA_CIRRUS; } else { - fprintf(stderr, "Error: Cirrus VGA not available\n"); + error_report("Cirrus VGA not available"); exit(0); } } else if (strstart(p, "vmware", &opts)) { if (vmware_vga_available()) { vga_interface_type = VGA_VMWARE; } else { - fprintf(stderr, "Error: VMWare SVGA not available\n"); + error_report("VMWare SVGA not available"); exit(0); } } else if (strstart(p, "virtio", &opts)) { if (virtio_vga_available()) { vga_interface_type = VGA_VIRTIO; } else { - fprintf(stderr, "Error: Virtio VGA not available\n"); + error_report("Virtio VGA not available"); exit(0); } } else if (strstart(p, "xenfb", &opts)) { @@ -2010,26 +2011,26 @@ static void select_vgahw (const char *p) if (qxl_vga_available()) { vga_interface_type = VGA_QXL; } else { - fprintf(stderr, "Error: QXL VGA not available\n"); + error_report("QXL VGA not available"); exit(0); } } else if (strstart(p, "tcx", &opts)) { if (tcx_vga_available()) { vga_interface_type = VGA_TCX; } else { - fprintf(stderr, "Error: TCX framebuffer not available\n"); + error_report("TCX framebuffer not available"); exit(0); } } else if (strstart(p, "cg3", &opts)) { if (cg3_vga_available()) { vga_interface_type = VGA_CG3; } else { - fprintf(stderr, "Error: CG3 framebuffer not available\n"); + error_report("CG3 framebuffer not available"); exit(0); } } else if (!strstart(p, "none", &opts)) { invalid_vga: - fprintf(stderr, "Unknown vga type: %s\n", p); + error_report("unknown vga type: %s", p); exit(1); } while (*opts) { @@ -2105,7 +2106,7 @@ static DisplayType select_display(const char *p) } } else { invalid_sdl_args: - error_report("Invalid SDL option string"); + error_report("invalid SDL option string"); exit(1); } opts = nextopt; @@ -2134,7 +2135,7 @@ static DisplayType select_display(const char *p) #ifdef CONFIG_CURSES display = DT_CURSES; #else - error_report("Curses support is disabled"); + error_report("curses support is disabled"); exit(1); #endif } else if (strstart(p, "gtk", &opts)) { @@ -2163,7 +2164,7 @@ static DisplayType select_display(const char *p) } } else { invalid_gtk_args: - error_report("Invalid GTK option string"); + error_report("invalid GTK option string"); exit(1); } opts = nextopt; @@ -2175,7 +2176,7 @@ static DisplayType select_display(const char *p) } else if (strstart(p, "none", &opts)) { display = DT_NONE; } else { - error_report("Unknown display type"); + error_report("unknown display type"); exit(1); } @@ -2276,8 +2277,8 @@ static int parse_fw_cfg(void *opaque, QemuOpts *opts, Error **errp) return -1; } if (strncmp(name, "opt/", 4) != 0) { - error_report("WARNING: externally provided fw_cfg item names " - "should be prefixed with \"opt/\"!"); + error_report("warning: externally provided fw_cfg item names " + "should be prefixed with \"opt/\""); } if (nonempty_str(str)) { size = strlen(str); /* NUL terminator NOT included in fw_cfg blob */ @@ -2349,7 +2350,7 @@ static int mon_init_func(void *opaque, QemuOpts *opts, Error **errp) } else if (strcmp(mode, "control") == 0) { flags = MONITOR_USE_CONTROL; } else { - fprintf(stderr, "unknown monitor mode \"%s\"\n", mode); + error_report("unknown monitor mode \"%s\"", mode); exit(1); } @@ -2362,7 +2363,7 @@ static int mon_init_func(void *opaque, QemuOpts *opts, Error **errp) chardev = qemu_opt_get(opts, "chardev"); chr = qemu_chr_find(chardev); if (chr == NULL) { - fprintf(stderr, "chardev \"%s\" not found\n", chardev); + error_report("chardev \"%s\" not found", chardev); exit(1); } @@ -2390,7 +2391,7 @@ static void monitor_parse(const char *optarg, const char *mode, bool pretty) } opts = qemu_chr_parse_compat(label, optarg); if (!opts) { - fprintf(stderr, "parse error: %s\n", optarg); + error_report("parse error: %s", optarg); exit(1); } } @@ -2464,14 +2465,14 @@ static int serial_parse(const char *devname) if (strcmp(devname, "none") == 0) return 0; if (index == MAX_SERIAL_PORTS) { - fprintf(stderr, "qemu: too many serial ports\n"); + error_report("too many serial ports"); exit(1); } snprintf(label, sizeof(label), "serial%d", index); serial_hds[index] = qemu_chr_new(label, devname, NULL); if (!serial_hds[index]) { - fprintf(stderr, "qemu: could not connect serial device" - " to character backend '%s'\n", devname); + error_report("could not connect serial device" + " to character backend '%s'", devname); return -1; } index++; @@ -2486,14 +2487,14 @@ static int parallel_parse(const char *devname) if (strcmp(devname, "none") == 0) return 0; if (index == MAX_PARALLEL_PORTS) { - fprintf(stderr, "qemu: too many parallel ports\n"); + error_report("too many parallel ports"); exit(1); } snprintf(label, sizeof(label), "parallel%d", index); parallel_hds[index] = qemu_chr_new(label, devname, NULL); if (!parallel_hds[index]) { - fprintf(stderr, "qemu: could not connect parallel device" - " to character backend '%s'\n", devname); + error_report("could not connect parallel device" + " to character backend '%s'", devname); return -1; } index++; @@ -2510,7 +2511,7 @@ static int virtcon_parse(const char *devname) if (strcmp(devname, "none") == 0) return 0; if (index == MAX_VIRTIO_CONSOLES) { - fprintf(stderr, "qemu: too many virtio consoles\n"); + error_report("too many virtio consoles"); exit(1); } @@ -2527,8 +2528,8 @@ static int virtcon_parse(const char *devname) snprintf(label, sizeof(label), "virtcon%d", index); virtcon_hds[index] = qemu_chr_new(label, devname, NULL); if (!virtcon_hds[index]) { - fprintf(stderr, "qemu: could not connect virtio console" - " to character backend '%s'\n", devname); + error_report("could not connect virtio console" + " to character backend '%s'", devname); return -1; } qemu_opt_set(dev_opts, "chardev", label, &error_abort); @@ -2548,7 +2549,7 @@ static int sclp_parse(const char *devname) return 0; } if (index == MAX_SCLP_CONSOLES) { - fprintf(stderr, "qemu: too many sclp consoles\n"); + error_report("too many sclp consoles"); exit(1); } @@ -2560,8 +2561,8 @@ static int sclp_parse(const char *devname) snprintf(label, sizeof(label), "sclpcon%d", index); sclp_hds[index] = qemu_chr_new(label, devname, NULL); if (!sclp_hds[index]) { - fprintf(stderr, "qemu: could not connect sclp console" - " to character backend '%s'\n", devname); + error_report("could not connect sclp console" + " to character backend '%s'", devname); return -1; } qemu_opt_set(dev_opts, "chardev", label, &error_abort); @@ -2579,7 +2580,7 @@ static int debugcon_parse(const char *devname) } opts = qemu_opts_create(qemu_find_opts("device"), "debugcon", 1, NULL); if (!opts) { - fprintf(stderr, "qemu: already have a debugcon device\n"); + error_report("already have a debugcon device"); exit(1); } qemu_opt_set(opts, "driver", "isa-debugcon", &error_abort); @@ -2634,8 +2635,8 @@ static gint machine_class_cmp(gconstpointer a, gconstpointer b) return mc; } if (name && !is_help_option(name)) { - error_report("Unsupported machine type"); - error_printf("Use -machine help to list supported machines!\n"); + error_report("unsupported machine type"); + error_printf("Use -machine help to list supported machines\n"); } else { printf("Supported machines are:\n"); machines = g_slist_sort(machines, machine_class_cmp); @@ -3010,8 +3011,7 @@ int main(int argc, char **argv, char **envp) runstate_init(); if (qcrypto_init(&err) < 0) { - fprintf(stderr, "Cannot initialize crypto: %s\n", - error_get_pretty(err)); + error_report("cannot initialize crypto: %s", error_get_pretty(err)); exit(1); } rtc_clock = QEMU_CLOCK_HOST; @@ -3169,7 +3169,7 @@ int main(int argc, char **argv, char **envp) } } else if (*p != '\0') { chs_fail: - fprintf(stderr, "qemu: invalid physical CHS format\n"); + error_report("invalid physical CHS format"); exit(1); } if (hda_opts != NULL) { @@ -3212,7 +3212,7 @@ int main(int argc, char **argv, char **envp) #ifdef CONFIG_CURSES display_type = DT_CURSES; #else - fprintf(stderr, "Curses support is disabled\n"); + error_report("curses support is disabled"); exit(1); #endif break; @@ -3223,8 +3223,7 @@ int main(int argc, char **argv, char **envp) graphic_rotate = strtol(optarg, (char **) &optarg, 10); if (graphic_rotate != 0 && graphic_rotate != 90 && graphic_rotate != 180 && graphic_rotate != 270) { - fprintf(stderr, - "qemu: only 90, 180, 270 deg rotation is available\n"); + error_report("only 90, 180, 270 deg rotation is available"); exit(1); } break; @@ -3375,7 +3374,7 @@ int main(int argc, char **argv, char **envp) w = strtol(p, (char **)&p, 10); if (w <= 0) { graphic_error: - fprintf(stderr, "qemu: invalid resolution or depth\n"); + error_report("invalid resolution or depth"); exit(1); } if (*p != 'x') @@ -3441,7 +3440,7 @@ int main(int argc, char **argv, char **envp) case QEMU_OPTION_fsdev: olist = qemu_find_opts("fsdev"); if (!olist) { - fprintf(stderr, "fsdev is not supported by this qemu build.\n"); + error_report("fsdev support is disabled"); exit(1); } opts = qemu_opts_parse_noisily(olist, optarg, true); @@ -3456,7 +3455,7 @@ int main(int argc, char **argv, char **envp) olist = qemu_find_opts("virtfs"); if (!olist) { - fprintf(stderr, "virtfs is not supported by this qemu build.\n"); + error_report("virtfs support is disabled"); exit(1); } opts = qemu_opts_parse_noisily(olist, optarg, true); @@ -3466,15 +3465,15 @@ int main(int argc, char **argv, char **envp) if (qemu_opt_get(opts, "fsdriver") == NULL || qemu_opt_get(opts, "mount_tag") == NULL) { - fprintf(stderr, "Usage: -virtfs fsdriver,mount_tag=tag.\n"); + error_report("Usage: -virtfs fsdriver,mount_tag=tag"); exit(1); } fsdev = qemu_opts_create(qemu_find_opts("fsdev"), qemu_opt_get(opts, "mount_tag"), 1, NULL); if (!fsdev) { - fprintf(stderr, "duplicate fsdev id: %s\n", - qemu_opt_get(opts, "mount_tag")); + error_report("duplicate fsdev id: %s", + qemu_opt_get(opts, "mount_tag")); exit(1); } @@ -3483,8 +3482,8 @@ int main(int argc, char **argv, char **envp) #ifdef CONFIG_SYNC_FILE_RANGE qemu_opt_set(fsdev, "writeout", writeout, &error_abort); #else - fprintf(stderr, "writeout=immediate not supported on " - "this platform\n"); + error_report("writeout=immediate not supported " + "on this platform"); exit(1); #endif } @@ -3523,7 +3522,7 @@ int main(int argc, char **argv, char **envp) fsdev = qemu_opts_create(qemu_find_opts("fsdev"), "v_synth", 1, NULL); if (!fsdev) { - fprintf(stderr, "duplicate option: %s\n", "virtfs_synth"); + error_report("duplicate option: %s", "virtfs_synth"); exit(1); } qemu_opt_set(fsdev, "fsdriver", "synth", &error_abort); @@ -3544,15 +3543,14 @@ int main(int argc, char **argv, char **envp) break; case QEMU_OPTION_watchdog: if (watchdog) { - fprintf(stderr, - "qemu: only one watchdog option may be given\n"); + error_report("only one watchdog option may be given"); return 1; } watchdog = optarg; break; case QEMU_OPTION_watchdog_action: if (select_watchdog_action(optarg) == -1) { - fprintf(stderr, "Unknown -watchdog-action parameter\n"); + error_report("unknown -watchdog-action parameter"); exit(1); } break; @@ -3596,7 +3594,7 @@ int main(int argc, char **argv, char **envp) display_type = DT_SDL; break; #else - fprintf(stderr, "SDL support is disabled\n"); + error_report("SDL support is disabled"); exit(1); #endif case QEMU_OPTION_pidfile: @@ -3658,8 +3656,7 @@ int main(int argc, char **argv, char **envp) qemu_opts_parse_noisily(olist, "accel=tcg", false); break; case QEMU_OPTION_no_kvm_pit: { - fprintf(stderr, "Warning: KVM PIT can no longer be disabled " - "separately.\n"); + error_report("warning: ignoring deprecated option"); break; } case QEMU_OPTION_no_kvm_pit_reinjection: { @@ -3672,8 +3669,8 @@ int main(int argc, char **argv, char **envp) { /* end of list */ } }; - fprintf(stderr, "Warning: option deprecated, use " - "lost_tick_policy property of kvm-pit instead.\n"); + error_report("warning: deprecated, replaced by " + "-global kvm-pit.lost_tick_policy=discard"); qdev_prop_register_global_list(kvm_pit_lost_tick_policy); break; } @@ -3708,7 +3705,7 @@ int main(int argc, char **argv, char **envp) exit(1); } #else - fprintf(stderr, "VNC support is disabled\n"); + error_report("VNC support is disabled"); exit(1); #endif break; @@ -3721,7 +3718,7 @@ int main(int argc, char **argv, char **envp) break; case QEMU_OPTION_balloon: if (balloon_parse(optarg) < 0) { - fprintf(stderr, "Unknown -balloon argument %s\n", optarg); + error_report("unknown -balloon argument %s", optarg); exit(1); } break; @@ -3736,15 +3733,14 @@ int main(int argc, char **argv, char **envp) break; case QEMU_OPTION_uuid: if(qemu_uuid_parse(optarg, qemu_uuid) < 0) { - fprintf(stderr, "Fail to parse UUID string." - " Wrong format.\n"); + error_report("failed to parse UUID string: wrong format"); exit(1); } qemu_uuid_set = true; break; case QEMU_OPTION_option_rom: if (nb_option_roms >= MAX_OPTION_ROMS) { - fprintf(stderr, "Too many option ROMs\n"); + error_report("too many option ROMs"); exit(1); } opts = qemu_opts_parse_noisily(qemu_find_opts("option-rom"), @@ -3756,7 +3752,7 @@ int main(int argc, char **argv, char **envp) option_rom[nb_option_roms].bootindex = qemu_opt_get_number(opts, "bootindex", -1); if (!option_rom[nb_option_roms].name) { - fprintf(stderr, "Option ROM file is not specified\n"); + error_report("Option ROM file is not specified"); exit(1); } nb_option_roms++; @@ -3781,9 +3777,8 @@ int main(int argc, char **argv, char **envp) } else if (strcmp("auto", target) == 0) { semihosting.target = SEMIHOSTING_TARGET_AUTO; } else { - fprintf(stderr, "Unsupported semihosting-config" - " %s\n", - optarg); + error_report("unsupported semihosting-config %s", + optarg); exit(1); } } else { @@ -3793,14 +3788,12 @@ int main(int argc, char **argv, char **envp) qemu_opt_foreach(opts, add_semihosting_arg, &semihosting, NULL); } else { - fprintf(stderr, "Unsupported semihosting-config %s\n", - optarg); + error_report("unsupported semihosting-config %s", optarg); exit(1); } break; case QEMU_OPTION_tdf: - fprintf(stderr, "Warning: user space PIT time drift fix " - "is no longer supported.\n"); + error_report("warning: ignoring deprecated option"); break; case QEMU_OPTION_name: opts = qemu_opts_parse_noisily(qemu_find_opts("name"), @@ -3811,7 +3804,7 @@ int main(int argc, char **argv, char **envp) break; case QEMU_OPTION_prom_env: if (nb_prom_envs >= MAX_PROM_ENVS) { - fprintf(stderr, "Too many prom variables\n"); + error_report("too many prom variables"); exit(1); } prom_envs[nb_prom_envs] = optarg; @@ -3894,8 +3887,8 @@ int main(int argc, char **argv, char **envp) { int ret = qemu_read_config_file(optarg); if (ret < 0) { - fprintf(stderr, "read config %s: %s\n", optarg, - strerror(-ret)); + error_report("read config %s: %s", optarg, + strerror(-ret)); exit(1); } break; @@ -3903,7 +3896,7 @@ int main(int argc, char **argv, char **envp) case QEMU_OPTION_spice: olist = qemu_find_opts("spice"); if (!olist) { - fprintf(stderr, "spice is not supported by this qemu build.\n"); + error_report("spice support is disabled"); exit(1); } opts = qemu_opts_parse_noisily(olist, optarg, false); @@ -3920,7 +3913,8 @@ int main(int argc, char **argv, char **envp) } else { fp = fopen(optarg, "w"); if (fp == NULL) { - fprintf(stderr, "open %s: %s\n", optarg, strerror(errno)); + error_report("open %s: %s", optarg, + strerror(errno)); exit(1); } } @@ -3981,13 +3975,13 @@ int main(int argc, char **argv, char **envp) break; case QEMU_OPTION_dump_vmstate: if (vmstate_dump_file) { - fprintf(stderr, "qemu: only one '-dump-vmstate' " - "option may be given\n"); + error_report("only one '-dump-vmstate' " + "option may be given"); exit(1); } vmstate_dump_file = fopen(optarg, "w"); if (vmstate_dump_file == NULL) { - fprintf(stderr, "open %s: %s\n", optarg, strerror(errno)); + error_report("open %s: %s", optarg, strerror(errno)); exit(1); } break; @@ -4004,8 +3998,8 @@ int main(int argc, char **argv, char **envp) } if (machine_class == NULL) { - fprintf(stderr, "No machine specified, and there is no default.\n" - "Use -machine help to list supported machines!\n"); + error_report("No machine specified, and there is no default"); + error_printf("Use -machine help to list supported machines\n"); exit(1); } @@ -4106,9 +4100,9 @@ int main(int argc, char **argv, char **envp) machine_class->max_cpus = machine_class->max_cpus ?: 1; /* Default to UP */ if (max_cpus > machine_class->max_cpus) { - fprintf(stderr, "Number of SMP CPUs requested (%d) exceeds max CPUs " - "supported by machine '%s' (%d)\n", max_cpus, - machine_class->name, machine_class->max_cpus); + error_report("Number of SMP CPUs requested (%d) exceeds max CPUs " + "supported by machine '%s' (%d)", max_cpus, + machine_class->name, machine_class->max_cpus); exit(1); } @@ -4169,12 +4163,12 @@ int main(int argc, char **argv, char **envp) if (display_type == DT_NOGRAPHIC && (default_parallel || default_serial || default_monitor || default_virtcon)) { - fprintf(stderr, "-nographic can not be used with -daemonize\n"); + error_report("-nographic cannot be used with -daemonize"); exit(1); } #ifdef CONFIG_CURSES if (display_type == DT_CURSES) { - fprintf(stderr, "curses display can not be used with -daemonize\n"); + error_report("curses display cannot be used with -daemonize"); exit(1); } #endif @@ -4233,12 +4227,12 @@ int main(int argc, char **argv, char **envp) } if ((no_frame || alt_grab || ctrl_grab) && display_type != DT_SDL) { - fprintf(stderr, "-no-frame, -alt-grab and -ctrl-grab are only valid " - "for SDL, ignoring option\n"); + error_report("-no-frame, -alt-grab and -ctrl-grab are only valid " + "for SDL, ignoring option"); } if (no_quit && (display_type != DT_GTK && display_type != DT_SDL)) { - fprintf(stderr, "-no-quit is only valid for GTK and SDL, " - "ignoring option\n"); + error_report("-no-quit is only valid for GTK and SDL, " + "ignoring option"); } #if defined(CONFIG_GTK) @@ -4253,9 +4247,9 @@ int main(int argc, char **argv, char **envp) #endif if (request_opengl == 1 && display_opengl == 0) { #if defined(CONFIG_OPENGL) - fprintf(stderr, "OpenGL is not supported by the display.\n"); + error_report("OpenGL is not supported by the display"); #else - fprintf(stderr, "QEMU was built without opengl support.\n"); + error_report("OpenGL support is disabled"); #endif exit(1); } @@ -4281,7 +4275,7 @@ int main(int argc, char **argv, char **envp) #endif if (pid_file && qemu_create_pidfile(pid_file) != 0) { - fprintf(stderr, "Could not acquire pid file: %s\n", strerror(errno)); + error_report("could not acquire pid file: %s", strerror(errno)); exit(1); } @@ -4352,17 +4346,17 @@ int main(int argc, char **argv, char **envp) linux_boot = (kernel_filename != NULL); if (!linux_boot && *kernel_cmdline != '\0') { - fprintf(stderr, "-append only allowed with -kernel option\n"); + error_report("-append only allowed with -kernel option"); exit(1); } if (!linux_boot && initrd_filename != NULL) { - fprintf(stderr, "-initrd only allowed with -kernel option\n"); + error_report("-initrd only allowed with -kernel option"); exit(1); } if (!linux_boot && qemu_opt_get(machine_opts, "dtb")) { - fprintf(stderr, "-dtb only allowed with -kernel option\n"); + error_report("-dtb only allowed with -kernel option"); exit(1); } @@ -4381,7 +4375,7 @@ int main(int argc, char **argv, char **envp) cpu_ticks_init(); if (icount_opts) { if (kvm_enabled() || xen_enabled()) { - fprintf(stderr, "-icount is not allowed with kvm or xen\n"); + error_report("-icount is not allowed with kvm or xen"); exit(1); } configure_icount(icount_opts, &error_abort); @@ -4414,7 +4408,7 @@ int main(int argc, char **argv, char **envp) if (!xen_enabled()) { /* On 32-bit hosts, QEMU is limited by virtual address space */ if (ram_size > (2047 << 20) && HOST_LONG_BITS == 32) { - fprintf(stderr, "qemu: at most 2047 MB RAM can be simulated\n"); + error_report("at most 2047 MB RAM can be simulated"); exit(1); } } @@ -4579,7 +4573,7 @@ int main(int argc, char **argv, char **envp) vnc_init_func, NULL, NULL); if (show_vnc_port) { char *ret = vnc_display_local_addr("default"); - printf("VNC server running on `%s'\n", ret); + printf("VNC server running on '%s'\n", ret); g_free(ret); } #endif @@ -4601,7 +4595,7 @@ int main(int argc, char **argv, char **envp) qemu_run_machine_init_done_notifiers(); if (rom_check_and_register_reset() != 0) { - fprintf(stderr, "rom check and register reset failed\n"); + error_report("rom check and register reset failed"); exit(1); } |