diff options
413 files changed, 2837 insertions, 3861 deletions
diff --git a/.gitignore b/.gitignore index 2849d756cc..55a001e3b8 100644 --- a/.gitignore +++ b/.gitignore @@ -99,15 +99,15 @@ /pc-bios/optionrom/kvmvapic.img /pc-bios/s390-ccw/s390-ccw.elf /pc-bios/s390-ccw/s390-ccw.img +/docs/qemu-ga-qapi.texi /docs/qemu-ga-ref.html +/docs/qemu-ga-ref.info* /docs/qemu-ga-ref.txt +/docs/qemu-qmp-qapi.texi /docs/qemu-qmp-ref.html +/docs/qemu-qmp-ref.info* /docs/qemu-qmp-ref.txt -docs/qemu-ga-ref.info* -docs/qemu-qmp-ref.info* -/qemu-ga-qapi.texi -/qemu-qapi.texi -/version.texi +/docs/version.texi *.tps .stgit-* cscope.* diff --git a/MAINTAINERS b/MAINTAINERS index e3edd04982..bf1aafb1c5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1674,14 +1674,6 @@ S: Supported F: block/ssh.c T: git git://github.com/codyprime/qemu-kvm-jtc.git block -ARCHIPELAGO -M: Chrysostomos Nanakos <chris@include.gr> -M: Jeff Cody <jcody@redhat.com> -L: qemu-block@nongnu.org -S: Maintained -F: block/archipelago.c -T: git git://github.com/codyprime/qemu-kvm-jtc.git block - CURL M: Jeff Cody <jcody@redhat.com> L: qemu-block@nongnu.org @@ -50,24 +50,24 @@ endif include $(SRC_PATH)/rules.mak -GENERATED_HEADERS = qemu-version.h config-host.h qemu-options.def -GENERATED_HEADERS += qmp-commands.h qapi-types.h qapi-visit.h qapi-event.h -GENERATED_SOURCES += qmp-marshal.c qapi-types.c qapi-visit.c qapi-event.c -GENERATED_HEADERS += qmp-introspect.h -GENERATED_SOURCES += qmp-introspect.c +GENERATED_FILES = qemu-version.h config-host.h qemu-options.def +GENERATED_FILES += qmp-commands.h qapi-types.h qapi-visit.h qapi-event.h +GENERATED_FILES += qmp-marshal.c qapi-types.c qapi-visit.c qapi-event.c +GENERATED_FILES += qmp-introspect.h +GENERATED_FILES += qmp-introspect.c -GENERATED_HEADERS += trace/generated-tcg-tracers.h +GENERATED_FILES += trace/generated-tcg-tracers.h -GENERATED_HEADERS += trace/generated-helpers-wrappers.h -GENERATED_HEADERS += trace/generated-helpers.h -GENERATED_SOURCES += trace/generated-helpers.c +GENERATED_FILES += trace/generated-helpers-wrappers.h +GENERATED_FILES += trace/generated-helpers.h +GENERATED_FILES += trace/generated-helpers.c ifdef CONFIG_TRACE_UST -GENERATED_HEADERS += trace-ust-all.h -GENERATED_SOURCES += trace-ust-all.c +GENERATED_FILES += trace-ust-all.h +GENERATED_FILES += trace-ust-all.c endif -GENERATED_HEADERS += module_block.h +GENERATED_FILES += module_block.h TRACE_HEADERS = trace-root.h $(trace-events-subdirs:%=%/trace.h) TRACE_SOURCES = trace-root.c $(trace-events-subdirs:%=%/trace.c) @@ -80,11 +80,15 @@ ifdef CONFIG_TRACE_UST TRACE_HEADERS += trace-ust-root.h $(trace-events-subdirs:%=%/trace-ust.h) endif -GENERATED_HEADERS += $(TRACE_HEADERS) -GENERATED_SOURCES += $(TRACE_SOURCES) +GENERATED_FILES += $(TRACE_HEADERS) +GENERATED_FILES += $(TRACE_SOURCES) +GENERATED_FILES += $(BUILD_DIR)/trace-events-all trace-group-name = $(shell dirname $1 | sed -e 's/[^a-zA-Z0-9]/_/g') +tracetool-y = $(SRC_PATH)/scripts/tracetool.py +tracetool-y += $(shell find $(SRC_PATH)/scripts/tracetool -name "*.py") + %/trace.h: %/trace.h-timestamp @cmp $< $@ >/dev/null 2>&1 || cp $< $@ %/trace.h-timestamp: $(SRC_PATH)/%/trace-events $(tracetool-y) @@ -485,11 +489,10 @@ clean: rm -f fsdev/*.pod rm -f qemu-img-cmds.h rm -f ui/shader/*-vert.h ui/shader/*-frag.h - @# May not be present in GENERATED_HEADERS + @# May not be present in GENERATED_FILES rm -f trace/generated-tracers-dtrace.dtrace* rm -f trace/generated-tracers-dtrace.h* - rm -f $(foreach f,$(GENERATED_HEADERS),$(f) $(f)-timestamp) - rm -f $(foreach f,$(GENERATED_SOURCES),$(f) $(f)-timestamp) + rm -f $(foreach f,$(GENERATED_FILES),$(f) $(f)-timestamp) rm -rf qapi-generated rm -rf qga/qapi-generated for d in $(ALL_SUBDIRS); do \ @@ -516,7 +519,7 @@ distclean: clean rm -f qemu-doc.vr qemu-doc.txt rm -f config.log rm -f linux-headers/asm - rm -f qemu-ga-qapi.texi qemu-qapi.texi version.texi + rm -f docs/qemu-ga-qapi.texi docs/qemu-qmp-qapi.texi docs/version.texi rm -f docs/qemu-qmp-ref.7 docs/qemu-ga-ref.7 rm -f docs/qemu-qmp-ref.txt docs/qemu-ga-ref.txt rm -f docs/qemu-qmp-ref.pdf docs/qemu-ga-ref.pdf @@ -593,8 +596,7 @@ endif endif -install: all $(if $(BUILD_DOCS),install-doc) $(BUILD_DIR)/trace-events-all \ -install-datadir install-localstatedir +install: all $(if $(BUILD_DOCS),install-doc) install-datadir install-localstatedir ifneq ($(TOOLS),) $(call install-prog,$(subst qemu-ga,qemu-ga$(EXESUF),$(TOOLS)),$(DESTDIR)$(bindir)) endif @@ -663,25 +665,28 @@ ui/console-gl.o: $(SRC_PATH)/ui/console-gl.c \ # documentation MAKEINFO=makeinfo -MAKEINFOFLAGS=--no-split --number-sections +MAKEINFOFLAGS=--no-split --number-sections -I docs TEXIFLAG=$(if $(V),,--quiet) -version.texi: $(SRC_PATH)/VERSION +docs/version.texi: $(SRC_PATH)/VERSION $(call quiet-command,echo "@set VERSION $(VERSION)" > $@,"GEN","$@") -%.html: %.texi version.texi +%.html: %.texi $(call quiet-command,LC_ALL=C $(MAKEINFO) $(MAKEINFOFLAGS) --no-headers \ --html $< -o $@,"GEN","$@") -%.info: %.texi version.texi +%.info: %.texi $(call quiet-command,$(MAKEINFO) $(MAKEINFOFLAGS) $< -o $@,"GEN","$@") -%.txt: %.texi version.texi +%.txt: %.texi $(call quiet-command,LC_ALL=C $(MAKEINFO) $(MAKEINFOFLAGS) --no-headers \ --plaintext $< -o $@,"GEN","$@") -%.pdf: %.texi version.texi - $(call quiet-command,texi2pdf $(TEXIFLAG) -I $(SRC_PATH) -I . $< -o $@,"GEN","$@") +%.pdf: %.texi + $(call quiet-command,texi2pdf $(TEXIFLAG) -I $(SRC_PATH) -I docs $< -o $@,"GEN","$@") + +docs/qemu-ga-ref.html docs/qemu-ga-ref.info docs/qemu-ga-ref.txt docs/qemu-ga-ref.pdf docs/qemu-ga-ref.7.pod: docs/version.texi +docs/qemu-qmp-ref.html docs/qemu-qmp-ref.info docs/qemu-qmp-ref.txt docs/qemu-qmp-ref.pdf docs/qemu-qmp-ref.pod: docs/version.texi qemu-options.texi: $(SRC_PATH)/qemu-options.hx $(SRC_PATH)/scripts/hxtool $(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -t < $< > $@,"GEN","$@") @@ -695,10 +700,10 @@ qemu-monitor-info.texi: $(SRC_PATH)/hmp-commands-info.hx $(SRC_PATH)/scripts/hxt qemu-img-cmds.texi: $(SRC_PATH)/qemu-img-cmds.hx $(SRC_PATH)/scripts/hxtool $(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -t < $< > $@,"GEN","$@") -qemu-qapi.texi: $(qapi-modules) $(qapi-py) +docs/qemu-qmp-qapi.texi: $(qapi-modules) $(qapi-py) $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi2texi.py $< > $@,"GEN","$@") -qemu-ga-qapi.texi: $(SRC_PATH)/qga/qapi-schema.json $(qapi-py) +docs/qemu-ga-qapi.texi: $(SRC_PATH)/qga/qapi-schema.json $(qapi-py) $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi2texi.py $< > $@,"GEN","$@") qemu.1: qemu-doc.texi qemu-options.texi qemu-monitor.texi qemu-monitor-info.texi @@ -719,10 +724,10 @@ qemu-doc.html qemu-doc.info qemu-doc.pdf qemu-doc.txt: \ qemu-monitor-info.texi docs/qemu-ga-ref.dvi docs/qemu-ga-ref.html docs/qemu-ga-ref.info docs/qemu-ga-ref.pdf docs/qemu-ga-ref.txt docs/qemu-ga-ref.7: \ -docs/qemu-ga-ref.texi qemu-ga-qapi.texi +docs/qemu-ga-ref.texi docs/qemu-ga-qapi.texi docs/qemu-qmp-ref.dvi docs/qemu-qmp-ref.html docs/qemu-qmp-ref.info docs/qemu-qmp-ref.pdf docs/qemu-qmp-ref.txt docs/qemu-qmp-ref.7: \ -docs/qemu-qmp-ref.texi qemu-qapi.texi +docs/qemu-qmp-ref.texi docs/qemu-qmp-qapi.texi ifdef CONFIG_WIN32 @@ -784,7 +789,7 @@ endif # CONFIG_WIN # Add a dependency on the generated files, so that they are always # rebuilt before other object files ifneq ($(filter-out $(UNCHECKED_GOALS),$(MAKECMDGOALS)),$(if $(MAKECMDGOALS),,fail)) -Makefile: $(GENERATED_HEADERS) +Makefile: $(GENERATED_FILES) endif .SECONDARY: $(TRACE_HEADERS) $(TRACE_HEADERS:%=%-timestamp) \ diff --git a/Makefile.target b/Makefile.target index 924304c9e6..7df2b8c149 100644 --- a/Makefile.target +++ b/Makefile.target @@ -162,7 +162,7 @@ else obj-y += hw/$(TARGET_BASE_ARCH)/ endif -GENERATED_HEADERS += hmp-commands.h hmp-commands-info.h +GENERATED_FILES += hmp-commands.h hmp-commands-info.h endif # CONFIG_SOFTMMU @@ -238,5 +238,5 @@ ifdef CONFIG_TRACE_SYSTEMTAP $(INSTALL_DATA) $(QEMU_PROG)-simpletrace.stp "$(DESTDIR)$(qemu_datadir)/../systemtap/tapset/$(QEMU_PROG)-simpletrace.stp" endif -GENERATED_HEADERS += config-target.h -Makefile: $(GENERATED_HEADERS) +GENERATED_FILES += config-target.h +Makefile: $(GENERATED_FILES) @@ -1 +1 @@ -2.8.50 +2.8.90 diff --git a/backends/hostmem.c b/backends/hostmem.c index 7f5de70609..162c2187d8 100644 --- a/backends/hostmem.c +++ b/backends/hostmem.c @@ -224,7 +224,7 @@ static void host_memory_backend_set_prealloc(Object *obj, bool value, void *ptr = memory_region_get_ram_ptr(&backend->mr); uint64_t sz = memory_region_size(&backend->mr); - os_mem_prealloc(fd, ptr, sz, &local_err); + os_mem_prealloc(fd, ptr, sz, smp_cpus, &local_err); if (local_err) { error_propagate(errp, local_err); return; @@ -328,7 +328,7 @@ host_memory_backend_memory_complete(UserCreatable *uc, Error **errp) */ if (backend->prealloc) { os_mem_prealloc(memory_region_get_fd(&backend->mr), ptr, sz, - &local_err); + smp_cpus, &local_err); if (local_err) { goto out; } @@ -1393,6 +1393,11 @@ static int bdrv_fill_options(QDict **options, const char *filename, return 0; } +static int bdrv_child_check_perm(BdrvChild *c, uint64_t perm, uint64_t shared, + GSList *ignore_children, Error **errp); +static void bdrv_child_abort_perm_update(BdrvChild *c); +static void bdrv_child_set_perm(BdrvChild *c, uint64_t perm, uint64_t shared); + /* * Check whether permissions on this node can be changed in a way that * @cumulative_perms and @cumulative_shared_perms are the new cumulative @@ -1615,8 +1620,8 @@ static int bdrv_check_update_perm(BlockDriverState *bs, uint64_t new_used_perm, /* Needs to be followed by a call to either bdrv_child_set_perm() or * bdrv_child_abort_perm_update(). */ -int bdrv_child_check_perm(BdrvChild *c, uint64_t perm, uint64_t shared, - GSList *ignore_children, Error **errp) +static int bdrv_child_check_perm(BdrvChild *c, uint64_t perm, uint64_t shared, + GSList *ignore_children, Error **errp) { int ret; @@ -1627,7 +1632,7 @@ int bdrv_child_check_perm(BdrvChild *c, uint64_t perm, uint64_t shared, return ret; } -void bdrv_child_set_perm(BdrvChild *c, uint64_t perm, uint64_t shared) +static void bdrv_child_set_perm(BdrvChild *c, uint64_t perm, uint64_t shared) { uint64_t cumulative_perms, cumulative_shared_perms; @@ -1639,7 +1644,7 @@ void bdrv_child_set_perm(BdrvChild *c, uint64_t perm, uint64_t shared) bdrv_set_perm(c->bs, cumulative_perms, cumulative_shared_perms); } -void bdrv_child_abort_perm_update(BdrvChild *c) +static void bdrv_child_abort_perm_update(BdrvChild *c) { bdrv_abort_perm_update(c->bs); } @@ -1756,8 +1761,18 @@ static void bdrv_replace_child_noperm(BdrvChild *child, } } -static void bdrv_replace_child(BdrvChild *child, BlockDriverState *new_bs, - bool check_new_perm) +/* + * Updates @child to change its reference to point to @new_bs, including + * checking and applying the necessary permisson updates both to the old node + * and to @new_bs. + * + * NULL is passed as @new_bs for removing the reference before freeing @child. + * + * If @new_bs is not NULL, bdrv_check_perm() must be called beforehand, as this + * function uses bdrv_set_perm() to update the permissions according to the new + * reference that @new_bs gets. + */ +static void bdrv_replace_child(BdrvChild *child, BlockDriverState *new_bs) { BlockDriverState *old_bs = child->bs; uint64_t perm, shared_perm; @@ -1775,9 +1790,6 @@ static void bdrv_replace_child(BdrvChild *child, BlockDriverState *new_bs, if (new_bs) { bdrv_get_cumulative_perm(new_bs, &perm, &shared_perm); - if (check_new_perm) { - bdrv_check_perm(new_bs, perm, shared_perm, NULL, &error_abort); - } bdrv_set_perm(new_bs, perm, shared_perm); } } @@ -1808,7 +1820,7 @@ BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs, }; /* This performs the matching bdrv_set_perm() for the above check. */ - bdrv_replace_child(child, child_bs, false); + bdrv_replace_child(child, child_bs); return child; } @@ -1845,7 +1857,7 @@ static void bdrv_detach_child(BdrvChild *child) child->next.le_prev = NULL; } - bdrv_replace_child(child, NULL, false); + bdrv_replace_child(child, NULL); g_free(child->name); g_free(child); @@ -1931,6 +1943,8 @@ void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd, bdrv_unref(backing_hd); } + bdrv_refresh_filename(bs); + out: bdrv_refresh_limits(bs, NULL); } @@ -2016,6 +2030,7 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options, bdrv_set_backing_hd(bs, backing_hd, &local_err); bdrv_unref(backing_hd); if (local_err) { + error_propagate(errp, local_err); ret = -EINVAL; goto free_exit; } @@ -4335,8 +4350,15 @@ void bdrv_attach_aio_context(BlockDriverState *bs, void bdrv_set_aio_context(BlockDriverState *bs, AioContext *new_context) { + AioContext *ctx; + bdrv_drain(bs); /* ensure there are no in-flight requests */ + ctx = bdrv_get_aio_context(bs); + while (aio_poll(ctx, false)) { + /* wait for all bottom halves to execute */ + } + bdrv_detach_aio_context(bs); /* This function executes in the old AioContext so acquire the new one in diff --git a/block/Makefile.objs b/block/Makefile.objs index c6bd14e883..de96f8ee80 100644 --- a/block/Makefile.objs +++ b/block/Makefile.objs @@ -19,7 +19,6 @@ block-obj-$(CONFIG_LIBNFS) += nfs.o block-obj-$(CONFIG_CURL) += curl.o block-obj-$(CONFIG_RBD) += rbd.o block-obj-$(CONFIG_GLUSTERFS) += gluster.o -block-obj-$(CONFIG_ARCHIPELAGO) += archipelago.o block-obj-$(CONFIG_LIBSSH2) += ssh.o block-obj-y += accounting.o dirty-bitmap.o block-obj-y += write-threshold.o @@ -41,7 +40,6 @@ gluster.o-cflags := $(GLUSTERFS_CFLAGS) gluster.o-libs := $(GLUSTERFS_LIBS) ssh.o-cflags := $(LIBSSH2_CFLAGS) ssh.o-libs := $(LIBSSH2_LIBS) -archipelago.o-libs := $(ARCHIPELAGO_LIBS) block-obj-$(if $(CONFIG_BZIP2),m,n) += dmg-bz2.o dmg-bz2.o-libs := $(BZIP2_LIBS) qcow.o-libs := -lz diff --git a/block/archipelago.c b/block/archipelago.c deleted file mode 100644 index 2449cfc702..0000000000 --- a/block/archipelago.c +++ /dev/null @@ -1,1079 +0,0 @@ -/* - * QEMU Block driver for Archipelago - * - * Copyright (C) 2014 Chrysostomos Nanakos <cnanakos@grnet.gr> - * - * This work is licensed under the terms of the GNU GPL, version 2 or later. - * See the COPYING file in the top-level directory. - * - */ - -/* - * VM Image on Archipelago volume is specified like this: - * - * file.driver=archipelago,file.volume=<volumename> - * [,file.mport=<mapperd_port>[,file.vport=<vlmcd_port>] - * [,file.segment=<segment_name>]] - * - * or - * - * file=archipelago:<volumename>[/mport=<mapperd_port>[:vport=<vlmcd_port>][: - * segment=<segment_name>]] - * - * 'archipelago' is the protocol. - * - * 'mport' is the port number on which mapperd is listening. This is optional - * and if not specified, QEMU will make Archipelago to use the default port. - * - * 'vport' is the port number on which vlmcd is listening. This is optional - * and if not specified, QEMU will make Archipelago to use the default port. - * - * 'segment' is the name of the shared memory segment Archipelago stack - * is using. This is optional and if not specified, QEMU will make Archipelago - * to use the default value, 'archipelago'. - * - * Examples: - * - * file.driver=archipelago,file.volume=my_vm_volume - * file.driver=archipelago,file.volume=my_vm_volume,file.mport=123 - * file.driver=archipelago,file.volume=my_vm_volume,file.mport=123, - * file.vport=1234 - * file.driver=archipelago,file.volume=my_vm_volume,file.mport=123, - * file.vport=1234,file.segment=my_segment - * - * or - * - * file=archipelago:my_vm_volume - * file=archipelago:my_vm_volume/mport=123 - * file=archipelago:my_vm_volume/mport=123:vport=1234 - * file=archipelago:my_vm_volume/mport=123:vport=1234:segment=my_segment - * - */ - -#include "qemu/osdep.h" -#include "qemu/cutils.h" -#include "block/block_int.h" -#include "qemu/error-report.h" -#include "qemu/thread.h" -#include "qapi/qmp/qint.h" -#include "qapi/qmp/qstring.h" -#include "qapi/qmp/qjson.h" -#include "qemu/atomic.h" - -#include <xseg/xseg.h> -#include <xseg/protocol.h> - -#define MAX_REQUEST_SIZE 524288 - -#define ARCHIPELAGO_OPT_VOLUME "volume" -#define ARCHIPELAGO_OPT_SEGMENT "segment" -#define ARCHIPELAGO_OPT_MPORT "mport" -#define ARCHIPELAGO_OPT_VPORT "vport" -#define ARCHIPELAGO_DFL_MPORT 1001 -#define ARCHIPELAGO_DFL_VPORT 501 - -#define archipelagolog(fmt, ...) \ - do { \ - fprintf(stderr, "archipelago\t%-24s: " fmt, __func__, ##__VA_ARGS__); \ - } while (0) - -typedef enum { - ARCHIP_OP_READ, - ARCHIP_OP_WRITE, - ARCHIP_OP_FLUSH, - ARCHIP_OP_VOLINFO, - ARCHIP_OP_TRUNCATE, -} ARCHIPCmd; - -typedef struct ArchipelagoAIOCB { - BlockAIOCB common; - struct BDRVArchipelagoState *s; - QEMUIOVector *qiov; - ARCHIPCmd cmd; - int status; - int64_t size; - int64_t ret; -} ArchipelagoAIOCB; - -typedef struct BDRVArchipelagoState { - ArchipelagoAIOCB *event_acb; - char *volname; - char *segment_name; - uint64_t size; - /* Archipelago specific */ - struct xseg *xseg; - struct xseg_port *port; - xport srcport; - xport sport; - xport mportno; - xport vportno; - QemuMutex archip_mutex; - QemuCond archip_cond; - bool is_signaled; - /* Request handler specific */ - QemuThread request_th; - QemuCond request_cond; - QemuMutex request_mutex; - bool th_is_signaled; - bool stopping; -} BDRVArchipelagoState; - -typedef struct ArchipelagoSegmentedRequest { - size_t count; - size_t total; - int ref; - int failed; -} ArchipelagoSegmentedRequest; - -typedef struct AIORequestData { - const char *volname; - off_t offset; - size_t size; - uint64_t bufidx; - int ret; - int op; - ArchipelagoAIOCB *aio_cb; - ArchipelagoSegmentedRequest *segreq; -} AIORequestData; - -static void qemu_archipelago_complete_aio(void *opaque); - -static void init_local_signal(struct xseg *xseg, xport sport, xport srcport) -{ - if (xseg && (sport != srcport)) { - xseg_init_local_signal(xseg, srcport); - sport = srcport; - } -} - -static void archipelago_finish_aiocb(AIORequestData *reqdata) -{ - if (reqdata->aio_cb->ret != reqdata->segreq->total) { - reqdata->aio_cb->ret = -EIO; - } else if (reqdata->aio_cb->ret == reqdata->segreq->total) { - reqdata->aio_cb->ret = 0; - } - aio_bh_schedule_oneshot( - bdrv_get_aio_context(reqdata->aio_cb->common.bs), - qemu_archipelago_complete_aio, reqdata - ); -} - -static int wait_reply(struct xseg *xseg, xport srcport, struct xseg_port *port, - struct xseg_request *expected_req) -{ - struct xseg_request *req; - xseg_prepare_wait(xseg, srcport); - void *psd = xseg_get_signal_desc(xseg, port); - while (1) { - req = xseg_receive(xseg, srcport, X_NONBLOCK); - if (req) { - if (req != expected_req) { - archipelagolog("Unknown received request\n"); - xseg_put_request(xseg, req, srcport); - } else if (!(req->state & XS_SERVED)) { - return -1; - } else { - break; - } - } - xseg_wait_signal(xseg, psd, 100000UL); - } - xseg_cancel_wait(xseg, srcport); - return 0; -} - -static void xseg_request_handler(void *state) -{ - BDRVArchipelagoState *s = (BDRVArchipelagoState *) state; - void *psd = xseg_get_signal_desc(s->xseg, s->port); - qemu_mutex_lock(&s->request_mutex); - - while (!s->stopping) { - struct xseg_request *req; - void *data; - xseg_prepare_wait(s->xseg, s->srcport); - req = xseg_receive(s->xseg, s->srcport, X_NONBLOCK); - if (req) { - AIORequestData *reqdata; - ArchipelagoSegmentedRequest *segreq; - xseg_get_req_data(s->xseg, req, (void **)&reqdata); - - switch (reqdata->op) { - case ARCHIP_OP_READ: - data = xseg_get_data(s->xseg, req); - segreq = reqdata->segreq; - segreq->count += req->serviced; - - qemu_iovec_from_buf(reqdata->aio_cb->qiov, reqdata->bufidx, - data, - req->serviced); - - xseg_put_request(s->xseg, req, s->srcport); - - if (atomic_fetch_dec(&segreq->ref) == 1) { - if (!segreq->failed) { - reqdata->aio_cb->ret = segreq->count; - archipelago_finish_aiocb(reqdata); - g_free(segreq); - } else { - g_free(segreq); - g_free(reqdata); - } - } else { - g_free(reqdata); - } - break; - case ARCHIP_OP_WRITE: - case ARCHIP_OP_FLUSH: - segreq = reqdata->segreq; - segreq->count += req->serviced; - xseg_put_request(s->xseg, req, s->srcport); - - if (atomic_fetch_dec(&segreq->ref) == 1) { - if (!segreq->failed) { - reqdata->aio_cb->ret = segreq->count; - archipelago_finish_aiocb(reqdata); - g_free(segreq); - } else { - g_free(segreq); - g_free(reqdata); - } - } else { - g_free(reqdata); - } - break; - case ARCHIP_OP_VOLINFO: - case ARCHIP_OP_TRUNCATE: - s->is_signaled = true; - qemu_cond_signal(&s->archip_cond); - break; - } - } else { - xseg_wait_signal(s->xseg, psd, 100000UL); - } - xseg_cancel_wait(s->xseg, s->srcport); - } - - s->th_is_signaled = true; - qemu_cond_signal(&s->request_cond); - qemu_mutex_unlock(&s->request_mutex); - qemu_thread_exit(NULL); -} - -static int qemu_archipelago_xseg_init(BDRVArchipelagoState *s) -{ - if (xseg_initialize()) { - archipelagolog("Cannot initialize XSEG\n"); - goto err_exit; - } - - s->xseg = xseg_join("posix", s->segment_name, - "posixfd", NULL); - if (!s->xseg) { - archipelagolog("Cannot join XSEG shared memory segment\n"); - goto err_exit; - } - s->port = xseg_bind_dynport(s->xseg); - s->srcport = s->port->portno; - init_local_signal(s->xseg, s->sport, s->srcport); - return 0; - -err_exit: - return -1; -} - -static int qemu_archipelago_init(BDRVArchipelagoState *s) -{ - int ret; - - ret = qemu_archipelago_xseg_init(s); - if (ret < 0) { - error_report("Cannot initialize XSEG. Aborting..."); - goto err_exit; - } - - qemu_cond_init(&s->archip_cond); - qemu_mutex_init(&s->archip_mutex); - qemu_cond_init(&s->request_cond); - qemu_mutex_init(&s->request_mutex); - s->th_is_signaled = false; - qemu_thread_create(&s->request_th, "xseg_io_th", - (void *) xseg_request_handler, - (void *) s, QEMU_THREAD_JOINABLE); - -err_exit: - return ret; -} - -static void qemu_archipelago_complete_aio(void *opaque) -{ - AIORequestData *reqdata = (AIORequestData *) opaque; - ArchipelagoAIOCB *aio_cb = (ArchipelagoAIOCB *) reqdata->aio_cb; - - aio_cb->common.cb(aio_cb->common.opaque, aio_cb->ret); - aio_cb->status = 0; - - qemu_aio_unref(aio_cb); - g_free(reqdata); -} - -static void xseg_find_port(char *pstr, const char *needle, xport *aport) -{ - const char *a; - char *endptr = NULL; - unsigned long port; - if (strstart(pstr, needle, &a)) { - if (strlen(a) > 0) { - port = strtoul(a, &endptr, 10); - if (strlen(endptr)) { - *aport = -2; - return; - } - *aport = (xport) port; - } - } -} - -static void xseg_find_segment(char *pstr, const char *needle, - char **segment_name) -{ - const char *a; - if (strstart(pstr, needle, &a)) { - if (strlen(a) > 0) { - *segment_name = g_strdup(a); - } - } -} - -static void parse_filename_opts(const char *filename, Error **errp, - char **volume, char **segment_name, - xport *mport, xport *vport) -{ - const char *start; - char *tokens[4], *ds; - int idx; - xport lmport = NoPort, lvport = NoPort; - - strstart(filename, "archipelago:", &start); - - ds = g_strdup(start); - tokens[0] = strtok(ds, "/"); - tokens[1] = strtok(NULL, ":"); - tokens[2] = strtok(NULL, ":"); - tokens[3] = strtok(NULL, "\0"); - - if (!strlen(tokens[0])) { - error_setg(errp, "volume name must be specified first"); - g_free(ds); - return; - } - - for (idx = 1; idx < 4; idx++) { - if (tokens[idx] != NULL) { - if (strstart(tokens[idx], "mport=", NULL)) { - xseg_find_port(tokens[idx], "mport=", &lmport); - } - if (strstart(tokens[idx], "vport=", NULL)) { - xseg_find_port(tokens[idx], "vport=", &lvport); - } - if (strstart(tokens[idx], "segment=", NULL)) { - xseg_find_segment(tokens[idx], "segment=", segment_name); - } - } - } - - if ((lmport == -2) || (lvport == -2)) { - error_setg(errp, "mport and/or vport must be set"); - g_free(ds); - return; - } - *volume = g_strdup(tokens[0]); - *mport = lmport; - *vport = lvport; - g_free(ds); -} - -static void archipelago_parse_filename(const char *filename, QDict *options, - Error **errp) -{ - const char *start; - char *volume = NULL, *segment_name = NULL; - xport mport = NoPort, vport = NoPort; - - if (qdict_haskey(options, ARCHIPELAGO_OPT_VOLUME) - || qdict_haskey(options, ARCHIPELAGO_OPT_SEGMENT) - || qdict_haskey(options, ARCHIPELAGO_OPT_MPORT) - || qdict_haskey(options, ARCHIPELAGO_OPT_VPORT)) { - error_setg(errp, "volume/mport/vport/segment and a file name may not" - " be specified at the same time"); - return; - } - - if (!strstart(filename, "archipelago:", &start)) { - error_setg(errp, "File name must start with 'archipelago:'"); - return; - } - - if (!strlen(start) || strstart(start, "/", NULL)) { - error_setg(errp, "volume name must be specified"); - return; - } - - parse_filename_opts(filename, errp, &volume, &segment_name, &mport, &vport); - - if (volume) { - qdict_put(options, ARCHIPELAGO_OPT_VOLUME, qstring_from_str(volume)); - g_free(volume); - } - if (segment_name) { - qdict_put(options, ARCHIPELAGO_OPT_SEGMENT, - qstring_from_str(segment_name)); - g_free(segment_name); - } - if (mport != NoPort) { - qdict_put(options, ARCHIPELAGO_OPT_MPORT, qint_from_int(mport)); - } - if (vport != NoPort) { - qdict_put(options, ARCHIPELAGO_OPT_VPORT, qint_from_int(vport)); - } -} - -static QemuOptsList archipelago_runtime_opts = { - .name = "archipelago", - .head = QTAILQ_HEAD_INITIALIZER(archipelago_runtime_opts.head), - .desc = { - { - .name = ARCHIPELAGO_OPT_VOLUME, - .type = QEMU_OPT_STRING, - .help = "Name of the volume image", - }, - { - .name = ARCHIPELAGO_OPT_SEGMENT, - .type = QEMU_OPT_STRING, - .help = "Name of the Archipelago shared memory segment", - }, - { - .name = ARCHIPELAGO_OPT_MPORT, - .type = QEMU_OPT_NUMBER, - .help = "Archipelago mapperd port number" - }, - { - .name = ARCHIPELAGO_OPT_VPORT, - .type = QEMU_OPT_NUMBER, - .help = "Archipelago vlmcd port number" - - }, - { /* end of list */ } - }, -}; - -static int qemu_archipelago_open(BlockDriverState *bs, - QDict *options, - int bdrv_flags, - Error **errp) -{ - int ret = 0; - const char *volume, *segment_name; - QemuOpts *opts; - Error *local_err = NULL; - BDRVArchipelagoState *s = bs->opaque; - - opts = qemu_opts_create(&archipelago_runtime_opts, NULL, 0, &error_abort); - qemu_opts_absorb_qdict(opts, options, &local_err); - if (local_err) { - error_propagate(errp, local_err); - ret = -EINVAL; - goto err_exit; - } - - s->mportno = qemu_opt_get_number(opts, ARCHIPELAGO_OPT_MPORT, - ARCHIPELAGO_DFL_MPORT); - s->vportno = qemu_opt_get_number(opts, ARCHIPELAGO_OPT_VPORT, - ARCHIPELAGO_DFL_VPORT); - - segment_name = qemu_opt_get(opts, ARCHIPELAGO_OPT_SEGMENT); - if (segment_name == NULL) { - s->segment_name = g_strdup("archipelago"); - } else { - s->segment_name = g_strdup(segment_name); - } - - volume = qemu_opt_get(opts, ARCHIPELAGO_OPT_VOLUME); - if (volume == NULL) { - error_setg(errp, "archipelago block driver requires the 'volume'" - " option"); - ret = -EINVAL; - goto err_exit; - } - s->volname = g_strdup(volume); - - /* Initialize XSEG, join shared memory segment */ - ret = qemu_archipelago_init(s); - if (ret < 0) { - error_setg(errp, "cannot initialize XSEG and join shared " - "memory segment"); - goto err_exit; - } - - qemu_opts_del(opts); - return 0; - -err_exit: - g_free(s->volname); - g_free(s->segment_name); - qemu_opts_del(opts); - return ret; -} - -static void qemu_archipelago_close(BlockDriverState *bs) -{ - int r, targetlen; - char *target; - struct xseg_request *req; - BDRVArchipelagoState *s = bs->opaque; - - s->stopping = true; - - qemu_mutex_lock(&s->request_mutex); - while (!s->th_is_signaled) { - qemu_cond_wait(&s->request_cond, - &s->request_mutex); - } - qemu_mutex_unlock(&s->request_mutex); - qemu_thread_join(&s->request_th); - qemu_cond_destroy(&s->request_cond); - qemu_mutex_destroy(&s->request_mutex); - - qemu_cond_destroy(&s->archip_cond); - qemu_mutex_destroy(&s->archip_mutex); - - targetlen = strlen(s->volname); - req = xseg_get_request(s->xseg, s->srcport, s->vportno, X_ALLOC); - if (!req) { - archipelagolog("Cannot get XSEG request\n"); - goto err_exit; - } - r = xseg_prep_request(s->xseg, req, targetlen, 0); - if (r < 0) { - xseg_put_request(s->xseg, req, s->srcport); - archipelagolog("Cannot prepare XSEG close request\n"); - goto err_exit; - } - - target = xseg_get_target(s->xseg, req); - memcpy(target, s->volname, targetlen); - req->size = req->datalen; - req->offset = 0; - req->op = X_CLOSE; - - xport p = xseg_submit(s->xseg, req, s->srcport, X_ALLOC); - if (p == NoPort) { - xseg_put_request(s->xseg, req, s->srcport); - archipelagolog("Cannot submit XSEG close request\n"); - goto err_exit; - } - - xseg_signal(s->xseg, p); - wait_reply(s->xseg, s->srcport, s->port, req); - - xseg_put_request(s->xseg, req, s->srcport); - -err_exit: - g_free(s->volname); - g_free(s->segment_name); - xseg_quit_local_signal(s->xseg, s->srcport); - xseg_leave_dynport(s->xseg, s->port); - xseg_leave(s->xseg); -} - -static int qemu_archipelago_create_volume(Error **errp, const char *volname, - char *segment_name, - uint64_t size, xport mportno, - xport vportno) -{ - int ret, targetlen; - struct xseg *xseg = NULL; - struct xseg_request *req; - struct xseg_request_clone *xclone; - struct xseg_port *port; - xport srcport = NoPort, sport = NoPort; - char *target; - - /* Try default values if none has been set */ - if (mportno == (xport) -1) { - mportno = ARCHIPELAGO_DFL_MPORT; - } - - if (vportno == (xport) -1) { - vportno = ARCHIPELAGO_DFL_VPORT; - } - - if (xseg_initialize()) { - error_setg(errp, "Cannot initialize XSEG"); - return -1; - } - - xseg = xseg_join("posix", segment_name, - "posixfd", NULL); - - if (!xseg) { - error_setg(errp, "Cannot join XSEG shared memory segment"); - return -1; - } - - port = xseg_bind_dynport(xseg); - srcport = port->portno; - init_local_signal(xseg, sport, srcport); - - req = xseg_get_request(xseg, srcport, mportno, X_ALLOC); - if (!req) { - error_setg(errp, "Cannot get XSEG request"); - return -1; - } - - targetlen = strlen(volname); - ret = xseg_prep_request(xseg, req, targetlen, - sizeof(struct xseg_request_clone)); - if (ret < 0) { - error_setg(errp, "Cannot prepare XSEG request"); - goto err_exit; - } - - target = xseg_get_target(xseg, req); - if (!target) { - error_setg(errp, "Cannot get XSEG target."); - goto err_exit; - } - memcpy(target, volname, targetlen); - xclone = (struct xseg_request_clone *) xseg_get_data(xseg, req); - memset(xclone->target, 0 , XSEG_MAX_TARGETLEN); - xclone->targetlen = 0; - xclone->size = size; - req->offset = 0; - req->size = req->datalen; - req->op = X_CLONE; - - xport p = xseg_submit(xseg, req, srcport, X_ALLOC); - if (p == NoPort) { - error_setg(errp, "Could not submit XSEG request"); - goto err_exit; - } - xseg_signal(xseg, p); - - ret = wait_reply(xseg, srcport, port, req); - if (ret < 0) { - error_setg(errp, "wait_reply() error."); - } - - xseg_put_request(xseg, req, srcport); - xseg_quit_local_signal(xseg, srcport); - xseg_leave_dynport(xseg, port); - xseg_leave(xseg); - return ret; - -err_exit: - xseg_put_request(xseg, req, srcport); - xseg_quit_local_signal(xseg, srcport); - xseg_leave_dynport(xseg, port); - xseg_leave(xseg); - return -1; -} - -static int qemu_archipelago_create(const char *filename, - QemuOpts *options, - Error **errp) -{ - int ret = 0; - uint64_t total_size = 0; - char *volname = NULL, *segment_name = NULL; - const char *start; - xport mport = NoPort, vport = NoPort; - - if (!strstart(filename, "archipelago:", &start)) { - error_setg(errp, "File name must start with 'archipelago:'"); - return -1; - } - - if (!strlen(start) || strstart(start, "/", NULL)) { - error_setg(errp, "volume name must be specified"); - return -1; - } - - parse_filename_opts(filename, errp, &volname, &segment_name, &mport, - &vport); - total_size = ROUND_UP(qemu_opt_get_size_del(options, BLOCK_OPT_SIZE, 0), - BDRV_SECTOR_SIZE); - - if (segment_name == NULL) { - segment_name = g_strdup("archipelago"); - } - - /* Create an Archipelago volume */ - ret = qemu_archipelago_create_volume(errp, volname, segment_name, - total_size, mport, - vport); - - g_free(volname); - g_free(segment_name); - return ret; -} - -static const AIOCBInfo archipelago_aiocb_info = { - .aiocb_size = sizeof(ArchipelagoAIOCB), -}; - -static int archipelago_submit_request(BDRVArchipelagoState *s, - uint64_t bufidx, - size_t count, - off_t offset, - ArchipelagoAIOCB *aio_cb, - ArchipelagoSegmentedRequest *segreq, - int op) -{ - int ret, targetlen; - char *target; - void *data = NULL; - struct xseg_request *req; - AIORequestData *reqdata = g_new(AIORequestData, 1); - - targetlen = strlen(s->volname); - req = xseg_get_request(s->xseg, s->srcport, s->vportno, X_ALLOC); - if (!req) { - archipelagolog("Cannot get XSEG request\n"); - goto err_exit2; - } - ret = xseg_prep_request(s->xseg, req, targetlen, count); - if (ret < 0) { - archipelagolog("Cannot prepare XSEG request\n"); - goto err_exit; - } - target = xseg_get_target(s->xseg, req); - if (!target) { - archipelagolog("Cannot get XSEG target\n"); - goto err_exit; - } - memcpy(target, s->volname, targetlen); - req->size = count; - req->offset = offset; - - switch (op) { - case ARCHIP_OP_READ: - req->op = X_READ; - break; - case ARCHIP_OP_WRITE: - req->op = X_WRITE; - break; - case ARCHIP_OP_FLUSH: - req->op = X_FLUSH; - break; - } - reqdata->volname = s->volname; - reqdata->offset = offset; - reqdata->size = count; - reqdata->bufidx = bufidx; - reqdata->aio_cb = aio_cb; - reqdata->segreq = segreq; - reqdata->op = op; - - xseg_set_req_data(s->xseg, req, reqdata); - if (op == ARCHIP_OP_WRITE) { - data = xseg_get_data(s->xseg, req); - if (!data) { - archipelagolog("Cannot get XSEG data\n"); - goto err_exit; - } - qemu_iovec_to_buf(aio_cb->qiov, bufidx, data, count); - } - - xport p = xseg_submit(s->xseg, req, s->srcport, X_ALLOC); - if (p == NoPort) { - archipelagolog("Could not submit XSEG request\n"); - goto err_exit; - } - xseg_signal(s->xseg, p); - return 0; - -err_exit: - g_free(reqdata); - xseg_put_request(s->xseg, req, s->srcport); - return -EIO; -err_exit2: - g_free(reqdata); - return -EIO; -} - -static int archipelago_aio_segmented_rw(BDRVArchipelagoState *s, - size_t count, - off_t offset, - ArchipelagoAIOCB *aio_cb, - int op) -{ - int ret, segments_nr; - size_t pos = 0; - ArchipelagoSegmentedRequest *segreq; - - segreq = g_new0(ArchipelagoSegmentedRequest, 1); - - if (op == ARCHIP_OP_FLUSH) { - segments_nr = 1; - } else { - segments_nr = (int)(count / MAX_REQUEST_SIZE) + \ - ((count % MAX_REQUEST_SIZE) ? 1 : 0); - } - segreq->total = count; - atomic_mb_set(&segreq->ref, segments_nr); - - while (segments_nr > 1) { - ret = archipelago_submit_request(s, pos, - MAX_REQUEST_SIZE, - offset + pos, - aio_cb, segreq, op); - - if (ret < 0) { - goto err_exit; - } - count -= MAX_REQUEST_SIZE; - pos += MAX_REQUEST_SIZE; - segments_nr--; - } - ret = archipelago_submit_request(s, pos, count, offset + pos, - aio_cb, segreq, op); - - if (ret < 0) { - goto err_exit; - } - return 0; - -err_exit: - segreq->failed = 1; - if (atomic_fetch_sub(&segreq->ref, segments_nr) == segments_nr) { - g_free(segreq); - } - return ret; -} - -static BlockAIOCB *qemu_archipelago_aio_rw(BlockDriverState *bs, - int64_t sector_num, - QEMUIOVector *qiov, - int nb_sectors, - BlockCompletionFunc *cb, - void *opaque, - int op) -{ - ArchipelagoAIOCB *aio_cb; - BDRVArchipelagoState *s = bs->opaque; - int64_t size, off; - int ret; - - aio_cb = qemu_aio_get(&archipelago_aiocb_info, bs, cb, opaque); - aio_cb->cmd = op; - aio_cb->qiov = qiov; - - aio_cb->ret = 0; - aio_cb->s = s; - aio_cb->status = -EINPROGRESS; - - off = sector_num * BDRV_SECTOR_SIZE; - size = nb_sectors * BDRV_SECTOR_SIZE; - aio_cb->size = size; - - ret = archipelago_aio_segmented_rw(s, size, off, - aio_cb, op); - if (ret < 0) { - goto err_exit; - } - return &aio_cb->common; - -err_exit: - error_report("qemu_archipelago_aio_rw(): I/O Error"); - qemu_aio_unref(aio_cb); - return NULL; -} - -static BlockAIOCB *qemu_archipelago_aio_readv(BlockDriverState *bs, - int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, - BlockCompletionFunc *cb, void *opaque) -{ - return qemu_archipelago_aio_rw(bs, sector_num, qiov, nb_sectors, cb, - opaque, ARCHIP_OP_READ); -} - -static BlockAIOCB *qemu_archipelago_aio_writev(BlockDriverState *bs, - int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, - BlockCompletionFunc *cb, void *opaque) -{ - return qemu_archipelago_aio_rw(bs, sector_num, qiov, nb_sectors, cb, - opaque, ARCHIP_OP_WRITE); -} - -static int64_t archipelago_volume_info(BDRVArchipelagoState *s) -{ - uint64_t size; - int ret, targetlen; - struct xseg_request *req; - struct xseg_reply_info *xinfo; - AIORequestData *reqdata = g_new(AIORequestData, 1); - - const char *volname = s->volname; - targetlen = strlen(volname); - req = xseg_get_request(s->xseg, s->srcport, s->mportno, X_ALLOC); - if (!req) { - archipelagolog("Cannot get XSEG request\n"); - goto err_exit2; - } - ret = xseg_prep_request(s->xseg, req, targetlen, - sizeof(struct xseg_reply_info)); - if (ret < 0) { - archipelagolog("Cannot prepare XSEG request\n"); - goto err_exit; - } - char *target = xseg_get_target(s->xseg, req); - if (!target) { - archipelagolog("Cannot get XSEG target\n"); - goto err_exit; - } - memcpy(target, volname, targetlen); - req->size = req->datalen; - req->offset = 0; - req->op = X_INFO; - - reqdata->op = ARCHIP_OP_VOLINFO; - reqdata->volname = volname; - xseg_set_req_data(s->xseg, req, reqdata); - - xport p = xseg_submit(s->xseg, req, s->srcport, X_ALLOC); - if (p == NoPort) { - archipelagolog("Cannot submit XSEG request\n"); - goto err_exit; - } - xseg_signal(s->xseg, p); - qemu_mutex_lock(&s->archip_mutex); - while (!s->is_signaled) { - qemu_cond_wait(&s->archip_cond, &s->archip_mutex); - } - s->is_signaled = false; - qemu_mutex_unlock(&s->archip_mutex); - - xinfo = (struct xseg_reply_info *) xseg_get_data(s->xseg, req); - size = xinfo->size; - xseg_put_request(s->xseg, req, s->srcport); - g_free(reqdata); - s->size = size; - return size; - -err_exit: - xseg_put_request(s->xseg, req, s->srcport); -err_exit2: - g_free(reqdata); - return -EIO; -} - -static int64_t qemu_archipelago_getlength(BlockDriverState *bs) -{ - BDRVArchipelagoState *s = bs->opaque; - - return archipelago_volume_info(s); -} - -static int qemu_archipelago_truncate(BlockDriverState *bs, int64_t offset) -{ - int ret, targetlen; - struct xseg_request *req; - BDRVArchipelagoState *s = bs->opaque; - AIORequestData *reqdata = g_new(AIORequestData, 1); - - const char *volname = s->volname; - targetlen = strlen(volname); - req = xseg_get_request(s->xseg, s->srcport, s->mportno, X_ALLOC); - if (!req) { - archipelagolog("Cannot get XSEG request\n"); - goto err_exit2; - } - - ret = xseg_prep_request(s->xseg, req, targetlen, 0); - if (ret < 0) { - archipelagolog("Cannot prepare XSEG request\n"); - goto err_exit; - } - char *target = xseg_get_target(s->xseg, req); - if (!target) { - archipelagolog("Cannot get XSEG target\n"); - goto err_exit; - } - memcpy(target, volname, targetlen); - req->offset = offset; - req->op = X_TRUNCATE; - - reqdata->op = ARCHIP_OP_TRUNCATE; - reqdata->volname = volname; - - xseg_set_req_data(s->xseg, req, reqdata); - - xport p = xseg_submit(s->xseg, req, s->srcport, X_ALLOC); - if (p == NoPort) { - archipelagolog("Cannot submit XSEG request\n"); - goto err_exit; - } - - xseg_signal(s->xseg, p); - qemu_mutex_lock(&s->archip_mutex); - while (!s->is_signaled) { - qemu_cond_wait(&s->archip_cond, &s->archip_mutex); - } - s->is_signaled = false; - qemu_mutex_unlock(&s->archip_mutex); - xseg_put_request(s->xseg, req, s->srcport); - g_free(reqdata); - return 0; - -err_exit: - xseg_put_request(s->xseg, req, s->srcport); -err_exit2: - g_free(reqdata); - return -EIO; -} - -static QemuOptsList qemu_archipelago_create_opts = { - .name = "archipelago-create-opts", - .head = QTAILQ_HEAD_INITIALIZER(qemu_archipelago_create_opts.head), - .desc = { - { - .name = BLOCK_OPT_SIZE, - .type = QEMU_OPT_SIZE, - .help = "Virtual disk size" - }, - { /* end of list */ } - } -}; - -static BlockAIOCB *qemu_archipelago_aio_flush(BlockDriverState *bs, - BlockCompletionFunc *cb, void *opaque) -{ - return qemu_archipelago_aio_rw(bs, 0, NULL, 0, cb, opaque, - ARCHIP_OP_FLUSH); -} - -static BlockDriver bdrv_archipelago = { - .format_name = "archipelago", - .protocol_name = "archipelago", - .instance_size = sizeof(BDRVArchipelagoState), - .bdrv_parse_filename = archipelago_parse_filename, - .bdrv_file_open = qemu_archipelago_open, - .bdrv_close = qemu_archipelago_close, - .bdrv_create = qemu_archipelago_create, - .bdrv_getlength = qemu_archipelago_getlength, - .bdrv_truncate = qemu_archipelago_truncate, - .bdrv_aio_readv = qemu_archipelago_aio_readv, - .bdrv_aio_writev = qemu_archipelago_aio_writev, - .bdrv_aio_flush = qemu_archipelago_aio_flush, - .bdrv_has_zero_init = bdrv_has_zero_init_1, - .create_opts = &qemu_archipelago_create_opts, -}; - -static void bdrv_archipelago_init(void) -{ - bdrv_register(&bdrv_archipelago); -} - -block_init(bdrv_archipelago_init); diff --git a/block/backup.c b/block/backup.c index d1ab617c7e..a4fb2884f9 100644 --- a/block/backup.c +++ b/block/backup.c @@ -24,6 +24,7 @@ #include "qemu/cutils.h" #include "sysemu/block-backend.h" #include "qemu/bitmap.h" +#include "qemu/error-report.h" #define BACKUP_CLUSTER_SIZE_DEFAULT (1 << 16) #define SLICE_TIME 100000000ULL /* ns */ @@ -467,13 +468,14 @@ static void coroutine_fn backup_run(void *opaque) /* Both FULL and TOP SYNC_MODE's require copying.. */ for (; start < end; start++) { bool error_is_read; + int alloced = 0; + if (yield_and_check(job)) { break; } if (job->sync_mode == MIRROR_SYNC_MODE_TOP) { int i, n; - int alloced = 0; /* Check to see if these blocks are already in the * backing file. */ @@ -491,7 +493,7 @@ static void coroutine_fn backup_run(void *opaque) sectors_per_cluster - i, &n); i += n; - if (alloced == 1 || n == 0) { + if (alloced || n == 0) { break; } } @@ -503,8 +505,13 @@ static void coroutine_fn backup_run(void *opaque) } } /* FULL sync mode we copy the whole drive. */ - ret = backup_do_cow(job, start * sectors_per_cluster, - sectors_per_cluster, &error_is_read, false); + if (alloced < 0) { + ret = alloced; + } else { + ret = backup_do_cow(job, start * sectors_per_cluster, + sectors_per_cluster, &error_is_read, + false); + } if (ret < 0) { /* Depending on error action, fail now or retry cluster */ BlockErrorAction action = @@ -648,7 +655,16 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs, * backup cluster size is smaller than the target cluster size. Even for * targets with a backing file, try to avoid COW if possible. */ ret = bdrv_get_info(target, &bdi); - if (ret < 0 && !target->backing) { + if (ret == -ENOTSUP && !target->backing) { + /* Cluster size is not defined */ + error_report("WARNING: The target block device doesn't provide " + "information about the block size and it doesn't have a " + "backing file. The default block size of %u bytes is " + "used. If the actual block size of the target exceeds " + "this default, the backup may be unusable", + BACKUP_CLUSTER_SIZE_DEFAULT); + job->cluster_size = BACKUP_CLUSTER_SIZE_DEFAULT; + } else if (ret < 0 && !target->backing) { error_setg_errno(errp, -ret, "Couldn't determine the cluster size of the target image, " "which has no backing file"); diff --git a/block/commit.c b/block/commit.c index 9c4198837f..28324820a4 100644 --- a/block/commit.c +++ b/block/commit.c @@ -13,6 +13,7 @@ */ #include "qemu/osdep.h" +#include "qemu/cutils.h" #include "trace.h" #include "block/block_int.h" #include "block/blockjob_int.h" @@ -232,6 +233,23 @@ static int coroutine_fn bdrv_commit_top_preadv(BlockDriverState *bs, return bdrv_co_preadv(bs->backing, offset, bytes, qiov, flags); } +static int64_t coroutine_fn bdrv_commit_top_get_block_status( + BlockDriverState *bs, int64_t sector_num, int nb_sectors, int *pnum, + BlockDriverState **file) +{ + *pnum = nb_sectors; + *file = bs->backing->bs; + return BDRV_BLOCK_RAW | BDRV_BLOCK_OFFSET_VALID | BDRV_BLOCK_DATA | + (sector_num << BDRV_SECTOR_BITS); +} + +static void bdrv_commit_top_refresh_filename(BlockDriverState *bs, QDict *opts) +{ + bdrv_refresh_filename(bs->backing->bs); + pstrcpy(bs->exact_filename, sizeof(bs->exact_filename), + bs->backing->bs->filename); +} + static void bdrv_commit_top_close(BlockDriverState *bs) { } @@ -248,10 +266,12 @@ static void bdrv_commit_top_child_perm(BlockDriverState *bs, BdrvChild *c, /* Dummy node that provides consistent read to its users without requiring it * from its backing file and that allows writes on the backing file chain. */ static BlockDriver bdrv_commit_top = { - .format_name = "commit_top", - .bdrv_co_preadv = bdrv_commit_top_preadv, - .bdrv_close = bdrv_commit_top_close, - .bdrv_child_perm = bdrv_commit_top_child_perm, + .format_name = "commit_top", + .bdrv_co_preadv = bdrv_commit_top_preadv, + .bdrv_co_get_block_status = bdrv_commit_top_get_block_status, + .bdrv_refresh_filename = bdrv_commit_top_refresh_filename, + .bdrv_close = bdrv_commit_top_close, + .bdrv_child_perm = bdrv_commit_top_child_perm, }; void commit_start(const char *job_id, BlockDriverState *bs, diff --git a/block/curl.c b/block/curl.c index e83dcd8f50..34dbd335f4 100644 --- a/block/curl.c +++ b/block/curl.c @@ -377,7 +377,7 @@ static void curl_multi_check_completion(BDRVCURLState *s) } qemu_mutex_unlock(&s->mutex); - acb->common.cb(acb->common.opaque, -EPROTO); + acb->common.cb(acb->common.opaque, -EIO); qemu_mutex_lock(&s->mutex); qemu_aio_unref(acb); state->acb[i] = NULL; diff --git a/block/file-posix.c b/block/file-posix.c index 4de1abd023..53febd3767 100644 --- a/block/file-posix.c +++ b/block/file-posix.c @@ -668,6 +668,51 @@ static int hdev_get_max_transfer_length(BlockDriverState *bs, int fd) #endif } +static int hdev_get_max_segments(const struct stat *st) +{ +#ifdef CONFIG_LINUX + char buf[32]; + const char *end; + char *sysfspath; + int ret; + int fd = -1; + long max_segments; + + sysfspath = g_strdup_printf("/sys/dev/block/%u:%u/queue/max_segments", + major(st->st_rdev), minor(st->st_rdev)); + fd = open(sysfspath, O_RDONLY); + if (fd == -1) { + ret = -errno; + goto out; + } + do { + ret = read(fd, buf, sizeof(buf) - 1); + } while (ret == -1 && errno == EINTR); + if (ret < 0) { + ret = -errno; + goto out; + } else if (ret == 0) { + ret = -EIO; + goto out; + } + buf[ret] = 0; + /* The file is ended with '\n', pass 'end' to accept that. */ + ret = qemu_strtol(buf, &end, 10, &max_segments); + if (ret == 0 && end && *end == '\n') { + ret = max_segments; + } + +out: + if (fd != -1) { + close(fd); + } + g_free(sysfspath); + return ret; +#else + return -ENOTSUP; +#endif +} + static void raw_refresh_limits(BlockDriverState *bs, Error **errp) { BDRVRawState *s = bs->opaque; @@ -679,6 +724,11 @@ static void raw_refresh_limits(BlockDriverState *bs, Error **errp) if (ret > 0 && ret <= BDRV_REQUEST_MAX_BYTES) { bs->bl.max_transfer = pow2floor(ret); } + ret = hdev_get_max_segments(&st); + if (ret > 0) { + bs->bl.max_transfer = MIN(bs->bl.max_transfer, + ret * getpagesize()); + } } } diff --git a/block/io.c b/block/io.c index 8f38d46de0..2709a7007f 100644 --- a/block/io.c +++ b/block/io.c @@ -1760,7 +1760,7 @@ static int64_t coroutine_fn bdrv_co_get_block_status(BlockDriverState *bs, if (ret & BDRV_BLOCK_RAW) { assert(ret & BDRV_BLOCK_OFFSET_VALID); - ret = bdrv_get_block_status(bs->file->bs, ret >> BDRV_SECTOR_BITS, + ret = bdrv_get_block_status(*file, ret >> BDRV_SECTOR_BITS, *pnum, pnum, file); goto out; } diff --git a/block/mirror.c b/block/mirror.c index a5d30ee575..ca4baa510a 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -12,6 +12,7 @@ */ #include "qemu/osdep.h" +#include "qemu/cutils.h" #include "trace.h" #include "block/blockjob_int.h" #include "block/block_int.h" @@ -573,7 +574,8 @@ static void mirror_exit(BlockJob *job, void *opaque) * valid. Also give up permissions on mirror_top_bs->backing, which might * block the removal. */ block_job_remove_all_bdrv(job); - bdrv_child_set_perm(mirror_top_bs->backing, 0, BLK_PERM_ALL); + bdrv_child_try_set_perm(mirror_top_bs->backing, 0, BLK_PERM_ALL, + &error_abort); bdrv_replace_node(mirror_top_bs, backing_bs(mirror_top_bs), &error_abort); /* We just changed the BDS the job BB refers to (with either or both of the @@ -1060,6 +1062,13 @@ static int coroutine_fn bdrv_mirror_top_pdiscard(BlockDriverState *bs, return bdrv_co_pdiscard(bs->backing->bs, offset, count); } +static void bdrv_mirror_top_refresh_filename(BlockDriverState *bs, QDict *opts) +{ + bdrv_refresh_filename(bs->backing->bs); + pstrcpy(bs->exact_filename, sizeof(bs->exact_filename), + bs->backing->bs->filename); +} + static void bdrv_mirror_top_close(BlockDriverState *bs) { } @@ -1088,6 +1097,7 @@ static BlockDriver bdrv_mirror_top = { .bdrv_co_pdiscard = bdrv_mirror_top_pdiscard, .bdrv_co_flush = bdrv_mirror_top_flush, .bdrv_co_get_block_status = bdrv_mirror_top_get_block_status, + .bdrv_refresh_filename = bdrv_mirror_top_refresh_filename, .bdrv_close = bdrv_mirror_top_close, .bdrv_child_perm = bdrv_mirror_top_child_perm, }; @@ -1236,7 +1246,8 @@ fail: block_job_unref(&s->common); } - bdrv_child_set_perm(mirror_top_bs->backing, 0, BLK_PERM_ALL); + bdrv_child_try_set_perm(mirror_top_bs->backing, 0, BLK_PERM_ALL, + &error_abort); bdrv_replace_node(mirror_top_bs, backing_bs(mirror_top_bs), &error_abort); } diff --git a/block/replication.c b/block/replication.c index 22f170fd33..bf3c395eb4 100644 --- a/block/replication.c +++ b/block/replication.c @@ -155,6 +155,18 @@ static void replication_close(BlockDriverState *bs) replication_remove(s->rs); } +static void replication_child_perm(BlockDriverState *bs, BdrvChild *c, + const BdrvChildRole *role, + uint64_t perm, uint64_t shared, + uint64_t *nperm, uint64_t *nshared) +{ + *nperm = *nshared = BLK_PERM_CONSISTENT_READ \ + | BLK_PERM_WRITE \ + | BLK_PERM_WRITE_UNCHANGED; + + return; +} + static int64_t replication_getlength(BlockDriverState *bs) { return bdrv_getlength(bs->file->bs); @@ -660,7 +672,7 @@ BlockDriver bdrv_replication = { .bdrv_open = replication_open, .bdrv_close = replication_close, - .bdrv_child_perm = bdrv_filter_default_perms, + .bdrv_child_perm = replication_child_perm, .bdrv_getlength = replication_getlength, .bdrv_co_readv = replication_co_readv, diff --git a/block/vvfat.c b/block/vvfat.c index aa61c329e7..af5153d27d 100644 --- a/block/vvfat.c +++ b/block/vvfat.c @@ -1394,7 +1394,13 @@ static int vvfat_read(BlockDriverState *bs, int64_t sector_num, return -1; if (s->qcow) { int n; - if (bdrv_is_allocated(s->qcow->bs, sector_num, nb_sectors-i, &n)) { + int ret; + ret = bdrv_is_allocated(s->qcow->bs, sector_num, + nb_sectors - i, &n); + if (ret < 0) { + return ret; + } + if (ret) { DLOG(fprintf(stderr, "sectors %d+%d allocated\n", (int)sector_num, n)); if (bdrv_read(s->qcow, sector_num, buf + i * 0x200, n)) { @@ -1668,7 +1674,8 @@ static inline uint32_t modified_fat_get(BDRVVVFATState* s, } } -static inline int cluster_was_modified(BDRVVVFATState* s, uint32_t cluster_num) +static inline bool cluster_was_modified(BDRVVVFATState *s, + uint32_t cluster_num) { int was_modified = 0; int i, dummy; @@ -1683,7 +1690,13 @@ static inline int cluster_was_modified(BDRVVVFATState* s, uint32_t cluster_num) 1, &dummy); } - return was_modified; + /* + * Note that this treats failures to learn allocation status the + * same as if an allocation has occurred. It's as safe as + * anything else, given that a failure to learn allocation status + * will probably result in more failures. + */ + return !!was_modified; } static const char* get_basename(const char* path) @@ -1833,6 +1846,9 @@ static uint32_t get_cluster_count_for_direntry(BDRVVVFATState* s, int res; res = bdrv_is_allocated(s->qcow->bs, offset + i, 1, &dummy); + if (res < 0) { + return -1; + } if (!res) { res = vvfat_read(s->bs, offset, s->cluster_buffer, 1); if (res) { diff --git a/blockdev.c b/blockdev.c index f1f49bd3ca..c5b2c2c209 100644 --- a/blockdev.c +++ b/blockdev.c @@ -2047,7 +2047,9 @@ static void block_dirty_bitmap_clear_abort(BlkActionState *common) BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState, common, common); - bdrv_undo_clear_dirty_bitmap(state->bitmap, state->backup); + if (state->backup) { + bdrv_undo_clear_dirty_bitmap(state->bitmap, state->backup); + } } static void block_dirty_bitmap_clear_commit(BlkActionState *common) @@ -301,7 +301,6 @@ glusterfs="" glusterfs_xlator_opt="no" glusterfs_discard="no" glusterfs_zerofill="no" -archipelago="no" gtk="" gtkabi="" gtk_gl="no" @@ -1101,10 +1100,6 @@ for opt do ;; --enable-glusterfs) glusterfs="yes" ;; - --disable-archipelago) archipelago="no" - ;; - --enable-archipelago) archipelago="yes" - ;; --disable-virtio-blk-data-plane|--enable-virtio-blk-data-plane) echo "$0: $opt is obsolete, virtio-blk data-plane is always on" >&2 ;; @@ -1335,6 +1330,12 @@ Advanced options (experts only): --with-vss-sdk=SDK-path enable Windows VSS support in QEMU Guest Agent --with-win-sdk=SDK-path path to Windows Platform SDK (to build VSS .tlb) --tls-priority default TLS protocol/cipher priority string + --enable-gprof QEMU profiling with gprof + --enable-profiler profiler support + --enable-xen-pv-domain-build + xen pv domain builder + --enable-debug-stack-usage + track the maximum stack usage of stacks created by qemu_alloc_stack Optional features, enabled with --enable-FEATURE and disabled with --disable-FEATURE, default is enabled if available: @@ -1396,13 +1397,18 @@ disabled with --disable-FEATURE, default is enabled if available: seccomp seccomp support coroutine-pool coroutine freelist (better performance) glusterfs GlusterFS backend - archipelago Archipelago backend tpm TPM support libssh2 ssh block device support numa libnuma support tcmalloc tcmalloc support jemalloc jemalloc support replication replication support + vhost-vsock virtio sockets device support + opengl opengl support + virglrenderer virgl rendering support + xfsctl xfsctl support + qom-cast-debug cast debugging support + tools build qemu-io, qemu-nbd and qemu-image tools NOTE: The object files are built at the place where configure is launched EOF @@ -3466,37 +3472,6 @@ EOF fi fi -########################################## -# archipelago probe -if test "$archipelago" != "no" ; then - cat > $TMPC <<EOF -#include <stdio.h> -#include <xseg/xseg.h> -#include <xseg/protocol.h> -int main(void) { - xseg_initialize(); - return 0; -} -EOF - archipelago_libs=-lxseg - if compile_prog "" "$archipelago_libs"; then - archipelago="yes" - libs_tools="$archipelago_libs $libs_tools" - libs_softmmu="$archipelago_libs $libs_softmmu" - - echo "WARNING: Please check the licenses of QEMU and libxseg carefully." - echo "GPLv3 versions of libxseg may not be compatible with QEMU's" - echo "license and therefore prevent redistribution." - echo - echo "To disable Archipelago, use --disable-archipelago" - else - if test "$archipelago" = "yes" ; then - feature_not_found "Archipelago backend support" "Install libxseg devel" - fi - archipelago="no" - fi -fi - ########################################## # glusterfs probe @@ -4748,6 +4723,20 @@ if test "$modules" = "yes" && test "$LD_REL_FLAGS" = ""; then fi ########################################## +# check for sysmacros.h + +have_sysmacros=no +cat > $TMPC << EOF +#include <sys/sysmacros.h> +int main(void) { + return makedev(0, 0); +} +EOF +if compile_prog "" "" ; then + have_sysmacros=yes +fi + +########################################## # End of CC checks # After here, no more $cc or $ld runs @@ -5099,7 +5088,6 @@ echo "coroutine backend $coroutine" echo "coroutine pool $coroutine_pool" echo "debug stack usage $debug_stack_usage" echo "GlusterFS support $glusterfs" -echo "Archipelago support $archipelago" echo "gcov $gcov_tool" echo "gcov enabled $gcov" echo "TPM support $tpm" @@ -5640,11 +5628,6 @@ if test "$glusterfs_zerofill" = "yes" ; then echo "CONFIG_GLUSTERFS_ZEROFILL=y" >> $config_host_mak fi -if test "$archipelago" = "yes" ; then - echo "CONFIG_ARCHIPELAGO=m" >> $config_host_mak - echo "ARCHIPELAGO_LIBS=$archipelago_libs" >> $config_host_mak -fi - if test "$libssh2" = "yes" ; then echo "CONFIG_LIBSSH2=m" >> $config_host_mak echo "LIBSSH2_CFLAGS=$libssh2_cflags" >> $config_host_mak @@ -5719,6 +5702,10 @@ if test "$have_af_vsock" = "yes" ; then echo "CONFIG_AF_VSOCK=y" >> $config_host_mak fi +if test "$have_sysmacros" = "yes" ; then + echo "CONFIG_SYSMACROS=y" >> $config_host_mak +fi + # Hold two types of flag: # CONFIG_THREAD_SETNAME_BYTHREAD - we've got a way of setting the name on # a thread we have a handle to diff --git a/cpu-exec.c b/cpu-exec.c index d04dd91ebd..748cb66bca 100644 --- a/cpu-exec.c +++ b/cpu-exec.c @@ -33,6 +33,7 @@ #if defined(TARGET_I386) && !defined(CONFIG_USER_ONLY) #include "hw/i386/apic.h" #endif +#include "sysemu/cpus.h" #include "sysemu/replay.h" /* -icount align implementation. */ @@ -181,10 +181,7 @@ static bool check_tcg_memory_orders_compatible(void) static bool default_mttcg_enabled(void) { - QemuOpts *icount_opts = qemu_find_opts_singleton("icount"); - const char *rr = qemu_opt_get(icount_opts, "rr"); - - if (rr || TCG_OVERSIZED_GUEST) { + if (use_icount || TCG_OVERSIZED_GUEST) { return false; } else { #ifdef TARGET_SUPPORTS_MTTCG @@ -202,7 +199,13 @@ void qemu_tcg_configure(QemuOpts *opts, Error **errp) if (strcmp(t, "multi") == 0) { if (TCG_OVERSIZED_GUEST) { error_setg(errp, "No MTTCG when guest word size > hosts"); + } else if (use_icount) { + error_setg(errp, "No MTTCG when icount is enabled"); } else { +#ifndef TARGET_SUPPORT_MTTCG + error_report("Guest not yet converted to MTTCG - " + "you may get unexpected results"); +#endif if (!check_tcg_memory_orders_compatible()) { error_report("Guest expects a stronger memory ordering " "than the host provides"); @@ -797,6 +800,27 @@ static void qemu_cpu_kick_rr_cpu(void) } while (cpu != atomic_mb_read(&tcg_current_rr_cpu)); } +static void do_nothing(CPUState *cpu, run_on_cpu_data unused) +{ +} + +void qemu_timer_notify_cb(void *opaque, QEMUClockType type) +{ + if (!use_icount || type != QEMU_CLOCK_VIRTUAL) { + qemu_notify_event(); + return; + } + + if (!qemu_in_vcpu_thread() && first_cpu) { + /* qemu_cpu_kick is not enough to kick a halted CPU out of + * qemu_tcg_wait_io_event. async_run_on_cpu, instead, + * causes cpu_thread_is_idle to return false. This way, + * handle_icount_deadline can run. + */ + async_run_on_cpu(first_cpu, do_nothing, RUN_ON_CPU_NULL); + } +} + static void kick_tcg_thread(void *opaque) { timer_mod(tcg_kick_vcpu_timer, qemu_tcg_next_kick()); @@ -1142,12 +1166,15 @@ static int64_t tcg_get_icount_limit(void) static void handle_icount_deadline(void) { + assert(qemu_in_vcpu_thread()); if (use_icount) { int64_t deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL); if (deadline == 0) { + /* Wake up other AioContexts. */ qemu_clock_notify(QEMU_CLOCK_VIRTUAL); + qemu_clock_run_timers(QEMU_CLOCK_VIRTUAL); } } } @@ -1260,6 +1287,11 @@ static void *qemu_tcg_rr_cpu_thread_fn(void *arg) /* Account partial waits to QEMU_CLOCK_VIRTUAL. */ qemu_account_warp_timer(); + /* Run the timers here. This is much more efficient than + * waking up the I/O thread and waiting for completion. + */ + handle_icount_deadline(); + if (!cpu) { cpu = first_cpu; } @@ -1301,8 +1333,6 @@ static void *qemu_tcg_rr_cpu_thread_fn(void *arg) atomic_mb_set(&cpu->exit_request, 0); } - handle_icount_deadline(); - qemu_tcg_wait_io_event(cpu ? cpu : QTAILQ_FIRST(&cpus)); deal_with_unplugged_cpus(); } diff --git a/docs/bootindex.txt b/docs/bootindex.txt index f84fac7200..b9a8ba122f 100644 --- a/docs/bootindex.txt +++ b/docs/bootindex.txt @@ -41,3 +41,12 @@ has three bootable devices target1, target3, target5 connected to it, the option ROM will have a boot method for each of them, but it is not possible to map from boot method back to a specific target. This is a shortcoming of the PC BIOS boot specification. + +== Mixing bootindex and boot order parameters == + +Note that it does not make sense to use the bootindex property together +with the "-boot order=..." (or "-boot once=...") parameter. The guest +firmware implementations normally either support the one or the other, +but not both parameters at the same time. Mixing them will result in +undefined behavior, and thus the guest firmware will likely not boot +from the expected devices. diff --git a/docs/qapi-code-gen.txt b/docs/qapi-code-gen.txt index 9514d936ad..52e3874efe 100644 --- a/docs/qapi-code-gen.txt +++ b/docs/qapi-code-gen.txt @@ -117,10 +117,13 @@ Example: ==== Expression documentation ==== -Each expression that isn't an include directive must be preceded by a +Each expression that isn't an include directive may be preceded by a documentation block. Such blocks are called expression documentation blocks. +When documentation is required (see pragma 'doc-required'), expression +documentation blocks are mandatory. + The documentation block consists of a first line naming the expression, an optional overview, a description of each argument (for commands and events) or member (for structs, unions and alternates), @@ -128,10 +131,8 @@ and optional tagged sections. FIXME: the parser accepts these things in almost any order. -Optional arguments / members are tagged with the phrase '#optional', -often with their default value; and extensions added after the -expression was first released are also given a '(since x.y.z)' -comment. +Extensions added after the expression was first released carry a +'(since x.y.z)' comment. A tagged section starts with one of the following words: "Note:"/"Notes:", "Since:", "Example"/"Examples", "Returns:", "TODO:". @@ -147,10 +148,10 @@ For example: # # Statistics of a virtual block device or a block backing device. # -# @device: #optional If the stats are for a virtual block device, the name +# @device: If the stats are for a virtual block device, the name # corresponding to the virtual block device. # -# @node-name: #optional The node name of the device. (since 2.3) +# @node-name: The node name of the device. (since 2.3) # # ... more members ... # @@ -165,7 +166,7 @@ For example: # # Query the @BlockStats for all virtual block devices. # -# @query-nodes: #optional If true, the command will query all the +# @query-nodes: If true, the command will query all the # block nodes ... explain, explain ... (since 2.3) # # Returns: A list of @BlockStats for each virtual block devices. @@ -204,17 +205,17 @@ once. It is permissible for the schema to contain additional types not used by any commands or events in the Client JSON Protocol, for the side effect of generated C code used internally. -There are seven top-level expressions recognized by the parser: -'include', 'command', 'struct', 'enum', 'union', 'alternate', and -'event'. There are several groups of types: simple types (a number of -built-in types, such as 'int' and 'str'; as well as enumerations), -complex types (structs and two flavors of unions), and alternate types -(a choice between other types). The 'command' and 'event' expressions -can refer to existing types by name, or list an anonymous type as a -dictionary. Listing a type name inside an array refers to a -single-dimension array of that type; multi-dimension arrays are not -directly supported (although an array of a complex struct that -contains an array member is possible). +There are eight top-level expressions recognized by the parser: +'include', 'pragma', 'command', 'struct', 'enum', 'union', +'alternate', and 'event'. There are several groups of types: simple +types (a number of built-in types, such as 'int' and 'str'; as well as +enumerations), complex types (structs and two flavors of unions), and +alternate types (a choice between other types). The 'command' and +'event' expressions can refer to existing types by name, or list an +anonymous type as a dictionary. Listing a type name inside an array +refers to a single-dimension array of that type; multi-dimension +arrays are not directly supported (although an array of a complex +struct that contains an array member is possible). All names must begin with a letter, and contain only ASCII letters, digits, hyphen, and underscore. There are two exceptions: enum values @@ -249,6 +250,9 @@ Any name (command, event, type, member, or enum value) beginning with "x-" is marked experimental, and may be withdrawn or changed incompatibly in a future release. +Pragma 'name-case-whitelist' lets you violate the rules on use of +upper and lower case. Use for new code is strongly discouraged. + In the rest of this document, usage lines are given for each expression type, with literal strings written in lower case and placeholders written in capitals. If a literal string includes a @@ -282,7 +286,7 @@ The following types are predefined, and map to C as follows: QType QType JSON string matching enum QType values -=== Includes === +=== Include directives === Usage: { 'include': STRING } @@ -302,6 +306,26 @@ an outer file. The parser may be made stricter in the future to prevent incomplete include files. +=== Pragma directives === + +Usage: { 'pragma': DICT } + +The pragma directive lets you control optional generator behavior. +The dictionary's entries are pragma names and values. + +Pragma's scope is currently the complete schema. Setting the same +pragma to different values in parts of the schema doesn't work. + +Pragma 'doc-required' takes a boolean value. If true, documentation +is required. Default is false. + +Pragma 'returns-whitelist' takes a list of command names that may +violate the rules on permitted return types. Default is none. + +Pragma 'name-case-whitelist' takes a list of names that may violate +rules on use of upper- vs. lower-case letters. Default is none. + + === Struct types === Usage: { 'struct': STRING, 'data': DICT, '*base': STRUCT-NAME } @@ -541,22 +565,18 @@ The 'data' argument maps to the "arguments" dictionary passed in as part of a Client JSON Protocol command. The 'data' member is optional and defaults to {} (an empty dictionary). If present, it must be the string name of a complex type, or a dictionary that declares an -anonymous type with the same semantics as a 'struct' expression, with -one exception noted below when 'gen' is used. +anonymous type with the same semantics as a 'struct' expression. The 'returns' member describes what will appear in the "return" member of a Client JSON Protocol reply on successful completion of a command. The member is optional from the command declaration; if absent, the "return" member will be an empty dictionary. If 'returns' is present, it must be the string name of a complex or built-in type, a -one-element array containing the name of a complex or built-in type, -with one exception noted below when 'gen' is used. Although it is -permitted to have the 'returns' member name a built-in type or an -array of built-in types, any command that does this cannot be extended -to return additional information in the future; thus, new commands -should strongly consider returning a dictionary-based type or an array -of dictionaries, even if the dictionary only contains one member at the -present. +one-element array containing the name of a complex or built-in type. +To return anything else, you have to list the command in pragma +'returns-whitelist'. If you do this, the command cannot be extended +to return additional information in the future. Use of +'returns-whitelist' for new commands is strongly discouraged. All commands in Client JSON Protocol use a dictionary to report failure, with no way to specify that in QAPI. Where the error return diff --git a/docs/qemu-qmp-ref.texi b/docs/qemu-qmp-ref.texi index 0a0056930a..bb25758bd0 100644 --- a/docs/qemu-qmp-ref.texi +++ b/docs/qemu-qmp-ref.texi @@ -65,7 +65,7 @@ along with this manual. If not, see http://www.gnu.org/licenses/. @c for texi2pod: @c man begin DESCRIPTION -@include qemu-qapi.texi +@include qemu-qmp-qapi.texi @c man end diff --git a/docs/writing-qmp-commands.txt b/docs/writing-qmp-commands.txt index 44c14db418..1e6375495b 100644 --- a/docs/writing-qmp-commands.txt +++ b/docs/writing-qmp-commands.txt @@ -252,7 +252,7 @@ here goes "hello-world"'s new entry for the qapi-schema.json file: # # Print a client provided string to the standard output stream. # -# @message: #optional string to be printed +# @message: string to be printed # # Returns: Nothing on success. # @@ -358,7 +358,7 @@ The best way to return that data is to create a new QAPI type, as shown below: # # @clock-name: The alarm clock method's name. # -# @next-deadline: #optional The time (in nanoseconds) the next alarm will fire. +# @next-deadline: The time (in nanoseconds) the next alarm will fire. # # Since: 1.0 ## diff --git a/dtc b/dtc -Subproject fa8bc7f928ac25f23532afc8beb2073efc8fb06 +Subproject 558cd81bdd432769b59bff01240c44f82cfb1a9 @@ -43,6 +43,7 @@ #include "exec/ioport.h" #include "sysemu/dma.h" #include "sysemu/numa.h" +#include "sysemu/hw_accel.h" #include "exec/address-spaces.h" #include "sysemu/xen-mapcache.h" #include "trace-root.h" @@ -1467,7 +1468,7 @@ static void *file_ram_alloc(RAMBlock *block, } if (mem_prealloc) { - os_mem_prealloc(fd, area, memory, errp); + os_mem_prealloc(fd, area, memory, smp_cpus, errp); if (errp && *errp) { goto error; } @@ -1560,6 +1561,11 @@ const char *qemu_ram_get_idstr(RAMBlock *rb) return rb->idstr; } +bool qemu_ram_is_shared(RAMBlock *rb) +{ + return rb->flags & RAM_SHARED; +} + /* Called with iothread lock held. */ void qemu_ram_set_idstr(RAMBlock *new_block, const char *name, DeviceState *dev) { @@ -3309,6 +3315,7 @@ int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr, hwaddr phys_addr; target_ulong page; + cpu_synchronize_state(cpu); while (len > 0) { int asidx; MemTxAttrs attrs; @@ -2608,9 +2608,11 @@ void hmp_hotpluggable_cpus(Monitor *mon, const QDict *qdict) void hmp_info_vm_generation_id(Monitor *mon, const QDict *qdict) { - GuidInfo *info = qmp_query_vm_generation_id(NULL); + Error *err = NULL; + GuidInfo *info = qmp_query_vm_generation_id(&err); if (info) { monitor_printf(mon, "%s\n", info->guid); } + hmp_handle_error(mon, &err); qapi_free_GuidInfo(info); } diff --git a/hw/acpi/vmgenid.c b/hw/acpi/vmgenid.c index 744f2847da..7a3ad17d66 100644 --- a/hw/acpi/vmgenid.c +++ b/hw/acpi/vmgenid.c @@ -248,6 +248,7 @@ GuidInfo *qmp_query_vm_generation_id(Error **errp) Object *obj = find_vmgenid_dev(); if (!obj) { + error_setg(errp, "VM Generation ID device not found"); return NULL; } vms = VMGENID(obj); diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c index d544cd91c0..d797a6796e 100644 --- a/hw/char/virtio-serial-bus.c +++ b/hw/char/virtio-serial-bus.c @@ -724,6 +724,7 @@ static void virtio_serial_post_load_timer_cb(void *opaque) } } g_free(s->post_load->connected); + timer_del(s->post_load->timer); timer_free(s->post_load->timer); g_free(s->post_load); s->post_load = NULL; diff --git a/hw/core/machine.c b/hw/core/machine.c index 0699750336..0d92672203 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -585,11 +585,31 @@ static void machine_class_finalize(ObjectClass *klass, void *data) g_free(mc->name); } +static void register_compat_prop(const char *driver, + const char *property, + const char *value) +{ + GlobalProperty *p = g_new0(GlobalProperty, 1); + /* Machine compat_props must never cause errors: */ + p->errp = &error_abort; + p->driver = driver; + p->property = property; + p->value = value; + qdev_prop_register_global(p); +} + +static void machine_register_compat_for_subclass(ObjectClass *oc, void *opaque) +{ + GlobalProperty *p = opaque; + register_compat_prop(object_class_get_name(oc), p->property, p->value); +} + void machine_register_compat_props(MachineState *machine) { MachineClass *mc = MACHINE_GET_CLASS(machine); int i; GlobalProperty *p; + ObjectClass *oc; if (!mc->compat_props) { return; @@ -597,9 +617,22 @@ void machine_register_compat_props(MachineState *machine) for (i = 0; i < mc->compat_props->len; i++) { p = g_array_index(mc->compat_props, GlobalProperty *, i); - /* Machine compat_props must never cause errors: */ - p->errp = &error_abort; - qdev_prop_register_global(p); + oc = object_class_by_name(p->driver); + if (oc && object_class_is_abstract(oc)) { + /* temporary hack to make sure we do not override + * globals set explicitly on -global: if an abstract class + * is on compat_props, register globals for all its + * non-abstract subtypes instead. + * + * This doesn't solve the problem for cases where + * a non-abstract typename mentioned on compat_props + * has subclasses, like spapr-pci-host-bridge. + */ + object_class_foreach(machine_register_compat_for_subclass, + p->driver, false, p); + } else { + register_compat_prop(p->driver, p->property, p->value); + } } } diff --git a/hw/core/ptimer.c b/hw/core/ptimer.c index 59ccb00550..7221c68a98 100644 --- a/hw/core/ptimer.c +++ b/hw/core/ptimer.c @@ -13,6 +13,7 @@ #include "sysemu/replay.h" #include "sysemu/qtest.h" #include "block/aio.h" +#include "sysemu/cpus.h" #define DELTA_ADJUST 1 #define DELTA_NO_ADJUST -1 diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c index b9e7cb1df1..afc290ab91 100644 --- a/hw/display/cirrus_vga.c +++ b/hw/display/cirrus_vga.c @@ -178,11 +178,12 @@ struct CirrusVGAState; typedef void (*cirrus_bitblt_rop_t) (struct CirrusVGAState *s, - uint8_t * dst, const uint8_t * src, + uint32_t dstaddr, uint32_t srcaddr, int dstpitch, int srcpitch, int bltwidth, int bltheight); typedef void (*cirrus_fill_t)(struct CirrusVGAState *s, - uint8_t *dst, int dst_pitch, int width, int height); + uint32_t dstaddr, int dst_pitch, + int width, int height); typedef struct CirrusVGAState { VGACommonState vga; @@ -205,6 +206,7 @@ typedef struct CirrusVGAState { uint32_t cirrus_bank_base[2]; uint32_t cirrus_bank_limit[2]; uint8_t cirrus_hidden_palette[48]; + bool enable_blitter; int cirrus_blt_pixelwidth; int cirrus_blt_width; int cirrus_blt_height; @@ -320,18 +322,57 @@ static bool blit_is_unsafe(struct CirrusVGAState *s, bool dst_only) } static void cirrus_bitblt_rop_nop(CirrusVGAState *s, - uint8_t *dst,const uint8_t *src, + uint32_t dstaddr, uint32_t srcaddr, int dstpitch,int srcpitch, int bltwidth,int bltheight) { } static void cirrus_bitblt_fill_nop(CirrusVGAState *s, - uint8_t *dst, + uint32_t dstaddr, int dstpitch, int bltwidth,int bltheight) { } +static inline uint8_t cirrus_src(CirrusVGAState *s, uint32_t srcaddr) +{ + if (s->cirrus_srccounter) { + /* cputovideo */ + return s->cirrus_bltbuf[srcaddr & (CIRRUS_BLTBUFSIZE - 1)]; + } else { + /* videotovideo */ + return s->vga.vram_ptr[srcaddr & s->cirrus_addr_mask]; + } +} + +static inline uint16_t cirrus_src16(CirrusVGAState *s, uint32_t srcaddr) +{ + uint16_t *src; + + if (s->cirrus_srccounter) { + /* cputovideo */ + src = (void *)&s->cirrus_bltbuf[srcaddr & (CIRRUS_BLTBUFSIZE - 1) & ~1]; + } else { + /* videotovideo */ + src = (void *)&s->vga.vram_ptr[srcaddr & s->cirrus_addr_mask & ~1]; + } + return *src; +} + +static inline uint32_t cirrus_src32(CirrusVGAState *s, uint32_t srcaddr) +{ + uint32_t *src; + + if (s->cirrus_srccounter) { + /* cputovideo */ + src = (void *)&s->cirrus_bltbuf[srcaddr & (CIRRUS_BLTBUFSIZE - 1) & ~3]; + } else { + /* videotovideo */ + src = (void *)&s->vga.vram_ptr[srcaddr & s->cirrus_addr_mask & ~3]; + } + return *src; +} + #define ROP_NAME 0 #define ROP_FN(d, s) 0 #include "cirrus_vga_rop.h" @@ -666,21 +707,18 @@ static void cirrus_invalidate_region(CirrusVGAState * s, int off_begin, } for (y = 0; y < lines; y++) { - off_cur = off_begin; - off_cur_end = (off_cur + bytesperline) & s->cirrus_addr_mask; + off_cur = off_begin; + off_cur_end = ((off_cur + bytesperline - 1) & s->cirrus_addr_mask) + 1; assert(off_cur_end >= off_cur); memory_region_set_dirty(&s->vga.vram, off_cur, off_cur_end - off_cur); - off_begin += off_pitch; + off_begin += off_pitch; } } -static int cirrus_bitblt_common_patterncopy(CirrusVGAState *s, bool videosrc) +static int cirrus_bitblt_common_patterncopy(CirrusVGAState *s) { uint32_t patternsize; - uint8_t *dst; - uint8_t *src; - - dst = s->vga.vram_ptr + s->cirrus_blt_dstaddr; + bool videosrc = !s->cirrus_srccounter; if (videosrc) { switch (s->vga.get_bpp(&s->vga)) { @@ -701,16 +739,14 @@ static int cirrus_bitblt_common_patterncopy(CirrusVGAState *s, bool videosrc) if (s->cirrus_blt_srcaddr + patternsize > s->vga.vram_size) { return 0; } - src = s->vga.vram_ptr + s->cirrus_blt_srcaddr; - } else { - src = s->cirrus_bltbuf; } if (blit_is_unsafe(s, true)) { return 0; } - (*s->cirrus_rop) (s, dst, src, + (*s->cirrus_rop) (s, s->cirrus_blt_dstaddr, + videosrc ? s->cirrus_blt_srcaddr : 0, s->cirrus_blt_dstpitch, 0, s->cirrus_blt_width, s->cirrus_blt_height); cirrus_invalidate_region(s, s->cirrus_blt_dstaddr, @@ -729,7 +765,7 @@ static int cirrus_bitblt_solidfill(CirrusVGAState *s, int blt_rop) return 0; } rop_func = cirrus_fill[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1]; - rop_func(s, s->vga.vram_ptr + s->cirrus_blt_dstaddr, + rop_func(s, s->cirrus_blt_dstaddr, s->cirrus_blt_dstpitch, s->cirrus_blt_width, s->cirrus_blt_height); cirrus_invalidate_region(s, s->cirrus_blt_dstaddr, @@ -747,7 +783,7 @@ static int cirrus_bitblt_solidfill(CirrusVGAState *s, int blt_rop) static int cirrus_bitblt_videotovideo_patterncopy(CirrusVGAState * s) { - return cirrus_bitblt_common_patterncopy(s, true); + return cirrus_bitblt_common_patterncopy(s); } static int cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h) @@ -796,21 +832,15 @@ static int cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h) } } - /* we have to flush all pending changes so that the copy - is generated at the appropriate moment in time */ - if (notify) - graphic_hw_update(s->vga.con); - - (*s->cirrus_rop) (s, s->vga.vram_ptr + s->cirrus_blt_dstaddr, - s->vga.vram_ptr + s->cirrus_blt_srcaddr, + (*s->cirrus_rop) (s, s->cirrus_blt_dstaddr, + s->cirrus_blt_srcaddr, s->cirrus_blt_dstpitch, s->cirrus_blt_srcpitch, s->cirrus_blt_width, s->cirrus_blt_height); if (notify) { - qemu_console_copy(s->vga.con, - sx, sy, dx, dy, - s->cirrus_blt_width / depth, - s->cirrus_blt_height); + dpy_gfx_update(s->vga.con, dx, dy, + s->cirrus_blt_width / depth, + s->cirrus_blt_height); } /* we don't have to notify the display that this portion has @@ -846,15 +876,15 @@ static void cirrus_bitblt_cputovideo_next(CirrusVGAState * s) if (s->cirrus_srccounter > 0) { if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) { - cirrus_bitblt_common_patterncopy(s, false); + cirrus_bitblt_common_patterncopy(s); the_end: s->cirrus_srccounter = 0; cirrus_bitblt_reset(s); } else { /* at least one scan line */ do { - (*s->cirrus_rop)(s, s->vga.vram_ptr + s->cirrus_blt_dstaddr, - s->cirrus_bltbuf, 0, 0, s->cirrus_blt_width, 1); + (*s->cirrus_rop)(s, s->cirrus_blt_dstaddr, + 0, 0, 0, s->cirrus_blt_width, 1); cirrus_invalidate_region(s, s->cirrus_blt_dstaddr, 0, s->cirrus_blt_width, 1); s->cirrus_blt_dstaddr += s->cirrus_blt_dstpitch; @@ -966,6 +996,10 @@ static void cirrus_bitblt_start(CirrusVGAState * s) { uint8_t blt_rop; + if (!s->enable_blitter) { + goto bitblt_ignore; + } + s->vga.gr[0x31] |= CIRRUS_BLT_BUSY; s->cirrus_blt_width = (s->vga.gr[0x20] | (s->vga.gr[0x21] << 8)) + 1; @@ -3029,7 +3063,9 @@ static void isa_cirrus_vga_realizefn(DeviceState *dev, Error **errp) static Property isa_cirrus_vga_properties[] = { DEFINE_PROP_UINT32("vgamem_mb", struct ISACirrusVGAState, - cirrus_vga.vga.vram_size_mb, 8), + cirrus_vga.vga.vram_size_mb, 4), + DEFINE_PROP_BOOL("blitter", struct ISACirrusVGAState, + cirrus_vga.enable_blitter, true), DEFINE_PROP_END_OF_LIST(), }; @@ -3098,7 +3134,9 @@ static void pci_cirrus_vga_realize(PCIDevice *dev, Error **errp) static Property pci_vga_cirrus_properties[] = { DEFINE_PROP_UINT32("vgamem_mb", struct PCICirrusVGAState, - cirrus_vga.vga.vram_size_mb, 8), + cirrus_vga.vga.vram_size_mb, 4), + DEFINE_PROP_BOOL("blitter", struct PCICirrusVGAState, + cirrus_vga.enable_blitter, true), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/display/cirrus_vga_rop.h b/hw/display/cirrus_vga_rop.h index 0925a009fe..c61a677353 100644 --- a/hw/display/cirrus_vga_rop.h +++ b/hw/display/cirrus_vga_rop.h @@ -22,31 +22,65 @@ * THE SOFTWARE. */ -static inline void glue(rop_8_,ROP_NAME)(uint8_t *dst, uint8_t src) +static inline void glue(rop_8_, ROP_NAME)(CirrusVGAState *s, + uint32_t dstaddr, uint8_t src) { + uint8_t *dst = &s->vga.vram_ptr[dstaddr & s->cirrus_addr_mask]; *dst = ROP_FN(*dst, src); } -static inline void glue(rop_16_,ROP_NAME)(uint16_t *dst, uint16_t src) +static inline void glue(rop_tr_8_, ROP_NAME)(CirrusVGAState *s, + uint32_t dstaddr, uint8_t src, + uint8_t transp) { + uint8_t *dst = &s->vga.vram_ptr[dstaddr & s->cirrus_addr_mask]; + uint8_t pixel = ROP_FN(*dst, src); + if (pixel != transp) { + *dst = pixel; + } +} + +static inline void glue(rop_16_, ROP_NAME)(CirrusVGAState *s, + uint32_t dstaddr, uint16_t src) +{ + uint16_t *dst = (uint16_t *) + (&s->vga.vram_ptr[dstaddr & s->cirrus_addr_mask & ~1]); *dst = ROP_FN(*dst, src); } -static inline void glue(rop_32_,ROP_NAME)(uint32_t *dst, uint32_t src) +static inline void glue(rop_tr_16_, ROP_NAME)(CirrusVGAState *s, + uint32_t dstaddr, uint16_t src, + uint16_t transp) { + uint16_t *dst = (uint16_t *) + (&s->vga.vram_ptr[dstaddr & s->cirrus_addr_mask & ~1]); + uint16_t pixel = ROP_FN(*dst, src); + if (pixel != transp) { + *dst = pixel; + } +} + +static inline void glue(rop_32_, ROP_NAME)(CirrusVGAState *s, + uint32_t dstaddr, uint32_t src) +{ + uint32_t *dst = (uint32_t *) + (&s->vga.vram_ptr[dstaddr & s->cirrus_addr_mask & ~3]); *dst = ROP_FN(*dst, src); } -#define ROP_OP(d, s) glue(rop_8_,ROP_NAME)(d, s) -#define ROP_OP_16(d, s) glue(rop_16_,ROP_NAME)(d, s) -#define ROP_OP_32(d, s) glue(rop_32_,ROP_NAME)(d, s) +#define ROP_OP(st, d, s) glue(rop_8_, ROP_NAME)(st, d, s) +#define ROP_OP_TR(st, d, s, t) glue(rop_tr_8_, ROP_NAME)(st, d, s, t) +#define ROP_OP_16(st, d, s) glue(rop_16_, ROP_NAME)(st, d, s) +#define ROP_OP_TR_16(st, d, s, t) glue(rop_tr_16_, ROP_NAME)(st, d, s, t) +#define ROP_OP_32(st, d, s) glue(rop_32_, ROP_NAME)(st, d, s) #undef ROP_FN static void glue(cirrus_bitblt_rop_fwd_, ROP_NAME)(CirrusVGAState *s, - uint8_t *dst,const uint8_t *src, - int dstpitch,int srcpitch, - int bltwidth,int bltheight) + uint32_t dstaddr, + uint32_t srcaddr, + int dstpitch, int srcpitch, + int bltwidth, int bltheight) { int x,y; dstpitch -= bltwidth; @@ -58,134 +92,139 @@ glue(cirrus_bitblt_rop_fwd_, ROP_NAME)(CirrusVGAState *s, for (y = 0; y < bltheight; y++) { for (x = 0; x < bltwidth; x++) { - ROP_OP(dst, *src); - dst++; - src++; + ROP_OP(s, dstaddr, cirrus_src(s, srcaddr)); + dstaddr++; + srcaddr++; } - dst += dstpitch; - src += srcpitch; + dstaddr += dstpitch; + srcaddr += srcpitch; } } static void glue(cirrus_bitblt_rop_bkwd_, ROP_NAME)(CirrusVGAState *s, - uint8_t *dst,const uint8_t *src, - int dstpitch,int srcpitch, - int bltwidth,int bltheight) + uint32_t dstaddr, + uint32_t srcaddr, + int dstpitch, int srcpitch, + int bltwidth, int bltheight) { int x,y; dstpitch += bltwidth; srcpitch += bltwidth; for (y = 0; y < bltheight; y++) { for (x = 0; x < bltwidth; x++) { - ROP_OP(dst, *src); - dst--; - src--; + ROP_OP(s, dstaddr, cirrus_src(s, srcaddr)); + dstaddr--; + srcaddr--; } - dst += dstpitch; - src += srcpitch; + dstaddr += dstpitch; + srcaddr += srcpitch; } } static void glue(glue(cirrus_bitblt_rop_fwd_transp_, ROP_NAME),_8)(CirrusVGAState *s, - uint8_t *dst,const uint8_t *src, - int dstpitch,int srcpitch, - int bltwidth,int bltheight) + uint32_t dstaddr, + uint32_t srcaddr, + int dstpitch, + int srcpitch, + int bltwidth, + int bltheight) { int x,y; - uint8_t p; + uint8_t transp = s->vga.gr[0x34]; dstpitch -= bltwidth; srcpitch -= bltwidth; + + if (bltheight > 1 && (dstpitch < 0 || srcpitch < 0)) { + return; + } + for (y = 0; y < bltheight; y++) { for (x = 0; x < bltwidth; x++) { - p = *dst; - ROP_OP(&p, *src); - if (p != s->vga.gr[0x34]) *dst = p; - dst++; - src++; + ROP_OP_TR(s, dstaddr, cirrus_src(s, srcaddr), transp); + dstaddr++; + srcaddr++; } - dst += dstpitch; - src += srcpitch; + dstaddr += dstpitch; + srcaddr += srcpitch; } } static void glue(glue(cirrus_bitblt_rop_bkwd_transp_, ROP_NAME),_8)(CirrusVGAState *s, - uint8_t *dst,const uint8_t *src, - int dstpitch,int srcpitch, - int bltwidth,int bltheight) + uint32_t dstaddr, + uint32_t srcaddr, + int dstpitch, + int srcpitch, + int bltwidth, + int bltheight) { int x,y; - uint8_t p; + uint8_t transp = s->vga.gr[0x34]; dstpitch += bltwidth; srcpitch += bltwidth; for (y = 0; y < bltheight; y++) { for (x = 0; x < bltwidth; x++) { - p = *dst; - ROP_OP(&p, *src); - if (p != s->vga.gr[0x34]) *dst = p; - dst--; - src--; + ROP_OP_TR(s, dstaddr, cirrus_src(s, srcaddr), transp); + dstaddr--; + srcaddr--; } - dst += dstpitch; - src += srcpitch; + dstaddr += dstpitch; + srcaddr += srcpitch; } } static void glue(glue(cirrus_bitblt_rop_fwd_transp_, ROP_NAME),_16)(CirrusVGAState *s, - uint8_t *dst,const uint8_t *src, - int dstpitch,int srcpitch, - int bltwidth,int bltheight) + uint32_t dstaddr, + uint32_t srcaddr, + int dstpitch, + int srcpitch, + int bltwidth, + int bltheight) { int x,y; - uint8_t p1, p2; + uint16_t transp = s->vga.gr[0x34] | (uint16_t)s->vga.gr[0x35] << 8; dstpitch -= bltwidth; srcpitch -= bltwidth; + + if (bltheight > 1 && (dstpitch < 0 || srcpitch < 0)) { + return; + } + for (y = 0; y < bltheight; y++) { for (x = 0; x < bltwidth; x+=2) { - p1 = *dst; - p2 = *(dst+1); - ROP_OP(&p1, *src); - ROP_OP(&p2, *(src + 1)); - if ((p1 != s->vga.gr[0x34]) || (p2 != s->vga.gr[0x35])) { - *dst = p1; - *(dst+1) = p2; - } - dst+=2; - src+=2; + ROP_OP_TR_16(s, dstaddr, cirrus_src16(s, srcaddr), transp); + dstaddr += 2; + srcaddr += 2; } - dst += dstpitch; - src += srcpitch; + dstaddr += dstpitch; + srcaddr += srcpitch; } } static void glue(glue(cirrus_bitblt_rop_bkwd_transp_, ROP_NAME),_16)(CirrusVGAState *s, - uint8_t *dst,const uint8_t *src, - int dstpitch,int srcpitch, - int bltwidth,int bltheight) + uint32_t dstaddr, + uint32_t srcaddr, + int dstpitch, + int srcpitch, + int bltwidth, + int bltheight) { int x,y; - uint8_t p1, p2; + uint16_t transp = s->vga.gr[0x34] | (uint16_t)s->vga.gr[0x35] << 8; dstpitch += bltwidth; srcpitch += bltwidth; for (y = 0; y < bltheight; y++) { for (x = 0; x < bltwidth; x+=2) { - p1 = *(dst-1); - p2 = *dst; - ROP_OP(&p1, *(src - 1)); - ROP_OP(&p2, *src); - if ((p1 != s->vga.gr[0x34]) || (p2 != s->vga.gr[0x35])) { - *(dst-1) = p1; - *dst = p2; - } - dst-=2; - src-=2; + ROP_OP_TR_16(s, dstaddr, cirrus_src16(s, srcaddr), transp); + dstaddr -= 2; + srcaddr -= 2; } - dst += dstpitch; - src += srcpitch; + dstaddr += dstpitch; + srcaddr += srcpitch; } } diff --git a/hw/display/cirrus_vga_rop2.h b/hw/display/cirrus_vga_rop2.h index d28bcc6f25..b86bcd6e09 100644 --- a/hw/display/cirrus_vga_rop2.h +++ b/hw/display/cirrus_vga_rop2.h @@ -23,30 +23,32 @@ */ #if DEPTH == 8 -#define PUTPIXEL() ROP_OP(&d[0], col) +#define PUTPIXEL(s, a, c) ROP_OP(s, a, c) #elif DEPTH == 16 -#define PUTPIXEL() ROP_OP_16((uint16_t *)&d[0], col) +#define PUTPIXEL(s, a, c) ROP_OP_16(s, a, c) #elif DEPTH == 24 -#define PUTPIXEL() ROP_OP(&d[0], col); \ - ROP_OP(&d[1], (col >> 8)); \ - ROP_OP(&d[2], (col >> 16)) +#define PUTPIXEL(s, a, c) do { \ + ROP_OP(s, a, c); \ + ROP_OP(s, a + 1, (col >> 8)); \ + ROP_OP(s, a + 2, (col >> 16)); \ + } while (0) #elif DEPTH == 32 -#define PUTPIXEL() ROP_OP_32(((uint32_t *)&d[0]), col) +#define PUTPIXEL(s, a, c) ROP_OP_32(s, a, c) #else #error unsupported DEPTH #endif static void glue(glue(glue(cirrus_patternfill_, ROP_NAME), _),DEPTH) - (CirrusVGAState * s, uint8_t * dst, - const uint8_t * src, + (CirrusVGAState *s, uint32_t dstaddr, + uint32_t srcaddr, int dstpitch, int srcpitch, int bltwidth, int bltheight) { - uint8_t *d; + uint32_t addr; int x, y, pattern_y, pattern_pitch, pattern_x; unsigned int col; - const uint8_t *src1; + uint32_t src1addr; #if DEPTH == 24 int skipleft = s->vga.gr[0x2f] & 0x1f; #else @@ -63,42 +65,44 @@ glue(glue(glue(cirrus_patternfill_, ROP_NAME), _),DEPTH) pattern_y = s->cirrus_blt_srcaddr & 7; for(y = 0; y < bltheight; y++) { pattern_x = skipleft; - d = dst + skipleft; - src1 = src + pattern_y * pattern_pitch; + addr = dstaddr + skipleft; + src1addr = srcaddr + pattern_y * pattern_pitch; for (x = skipleft; x < bltwidth; x += (DEPTH / 8)) { #if DEPTH == 8 - col = src1[pattern_x]; + col = cirrus_src(s, src1addr + pattern_x); pattern_x = (pattern_x + 1) & 7; #elif DEPTH == 16 - col = ((uint16_t *)(src1 + pattern_x))[0]; + col = cirrus_src16(s, src1addr + pattern_x); pattern_x = (pattern_x + 2) & 15; #elif DEPTH == 24 { - const uint8_t *src2 = src1 + pattern_x * 3; - col = src2[0] | (src2[1] << 8) | (src2[2] << 16); + uint32_t src2addr = src1addr + pattern_x * 3; + col = cirrus_src(s, src2addr) | + (cirrus_src(s, src2addr + 1) << 8) | + (cirrus_src(s, src2addr + 2) << 16); pattern_x = (pattern_x + 1) & 7; } #else - col = ((uint32_t *)(src1 + pattern_x))[0]; + col = cirrus_src32(s, src1addr + pattern_x); pattern_x = (pattern_x + 4) & 31; #endif - PUTPIXEL(); - d += (DEPTH / 8); + PUTPIXEL(s, addr, col); + addr += (DEPTH / 8); } pattern_y = (pattern_y + 1) & 7; - dst += dstpitch; + dstaddr += dstpitch; } } /* NOTE: srcpitch is ignored */ static void glue(glue(glue(cirrus_colorexpand_transp_, ROP_NAME), _),DEPTH) - (CirrusVGAState * s, uint8_t * dst, - const uint8_t * src, + (CirrusVGAState *s, uint32_t dstaddr, + uint32_t srcaddr, int dstpitch, int srcpitch, int bltwidth, int bltheight) { - uint8_t *d; + uint32_t addr; int x, y; unsigned bits, bits_xor; unsigned int col; @@ -122,33 +126,33 @@ glue(glue(glue(cirrus_colorexpand_transp_, ROP_NAME), _),DEPTH) for(y = 0; y < bltheight; y++) { bitmask = 0x80 >> srcskipleft; - bits = *src++ ^ bits_xor; - d = dst + dstskipleft; + bits = cirrus_src(s, srcaddr++) ^ bits_xor; + addr = dstaddr + dstskipleft; for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) { if ((bitmask & 0xff) == 0) { bitmask = 0x80; - bits = *src++ ^ bits_xor; + bits = cirrus_src(s, srcaddr++) ^ bits_xor; } index = (bits & bitmask); if (index) { - PUTPIXEL(); + PUTPIXEL(s, addr, col); } - d += (DEPTH / 8); + addr += (DEPTH / 8); bitmask >>= 1; } - dst += dstpitch; + dstaddr += dstpitch; } } static void glue(glue(glue(cirrus_colorexpand_, ROP_NAME), _),DEPTH) - (CirrusVGAState * s, uint8_t * dst, - const uint8_t * src, + (CirrusVGAState *s, uint32_t dstaddr, + uint32_t srcaddr, int dstpitch, int srcpitch, int bltwidth, int bltheight) { uint32_t colors[2]; - uint8_t *d; + uint32_t addr; int x, y; unsigned bits; unsigned int col; @@ -160,30 +164,30 @@ glue(glue(glue(cirrus_colorexpand_, ROP_NAME), _),DEPTH) colors[1] = s->cirrus_blt_fgcol; for(y = 0; y < bltheight; y++) { bitmask = 0x80 >> srcskipleft; - bits = *src++; - d = dst + dstskipleft; + bits = cirrus_src(s, srcaddr++); + addr = dstaddr + dstskipleft; for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) { if ((bitmask & 0xff) == 0) { bitmask = 0x80; - bits = *src++; + bits = cirrus_src(s, srcaddr++); } col = colors[!!(bits & bitmask)]; - PUTPIXEL(); - d += (DEPTH / 8); + PUTPIXEL(s, addr, col); + addr += (DEPTH / 8); bitmask >>= 1; } - dst += dstpitch; + dstaddr += dstpitch; } } static void glue(glue(glue(cirrus_colorexpand_pattern_transp_, ROP_NAME), _),DEPTH) - (CirrusVGAState * s, uint8_t * dst, - const uint8_t * src, + (CirrusVGAState *s, uint32_t dstaddr, + uint32_t srcaddr, int dstpitch, int srcpitch, int bltwidth, int bltheight) { - uint8_t *d; + uint32_t addr; int x, y, bitpos, pattern_y; unsigned int bits, bits_xor; unsigned int col; @@ -205,30 +209,30 @@ glue(glue(glue(cirrus_colorexpand_pattern_transp_, ROP_NAME), _),DEPTH) pattern_y = s->cirrus_blt_srcaddr & 7; for(y = 0; y < bltheight; y++) { - bits = src[pattern_y] ^ bits_xor; + bits = cirrus_src(s, srcaddr + pattern_y) ^ bits_xor; bitpos = 7 - srcskipleft; - d = dst + dstskipleft; + addr = dstaddr + dstskipleft; for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) { if ((bits >> bitpos) & 1) { - PUTPIXEL(); + PUTPIXEL(s, addr, col); } - d += (DEPTH / 8); + addr += (DEPTH / 8); bitpos = (bitpos - 1) & 7; } pattern_y = (pattern_y + 1) & 7; - dst += dstpitch; + dstaddr += dstpitch; } } static void glue(glue(glue(cirrus_colorexpand_pattern_, ROP_NAME), _),DEPTH) - (CirrusVGAState * s, uint8_t * dst, - const uint8_t * src, + (CirrusVGAState *s, uint32_t dstaddr, + uint32_t srcaddr, int dstpitch, int srcpitch, int bltwidth, int bltheight) { uint32_t colors[2]; - uint8_t *d; + uint32_t addr; int x, y, bitpos, pattern_y; unsigned int bits; unsigned int col; @@ -240,40 +244,39 @@ glue(glue(glue(cirrus_colorexpand_pattern_, ROP_NAME), _),DEPTH) pattern_y = s->cirrus_blt_srcaddr & 7; for(y = 0; y < bltheight; y++) { - bits = src[pattern_y]; + bits = cirrus_src(s, srcaddr + pattern_y); bitpos = 7 - srcskipleft; - d = dst + dstskipleft; + addr = dstaddr + dstskipleft; for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) { col = colors[(bits >> bitpos) & 1]; - PUTPIXEL(); - d += (DEPTH / 8); + PUTPIXEL(s, addr, col); + addr += (DEPTH / 8); bitpos = (bitpos - 1) & 7; } pattern_y = (pattern_y + 1) & 7; - dst += dstpitch; + dstaddr += dstpitch; } } static void glue(glue(glue(cirrus_fill_, ROP_NAME), _),DEPTH) (CirrusVGAState *s, - uint8_t *dst, int dst_pitch, + uint32_t dstaddr, int dst_pitch, int width, int height) { - uint8_t *d, *d1; + uint32_t addr; uint32_t col; int x, y; col = s->cirrus_blt_fgcol; - d1 = dst; for(y = 0; y < height; y++) { - d = d1; + addr = dstaddr; for(x = 0; x < width; x += (DEPTH / 8)) { - PUTPIXEL(); - d += (DEPTH / 8); + PUTPIXEL(s, addr, col); + addr += (DEPTH / 8); } - d1 += dst_pitch; + dstaddr += dst_pitch; } } diff --git a/hw/i386/kvm/clock.c b/hw/i386/kvm/clock.c index ef9d560f9c..13eca374cd 100644 --- a/hw/i386/kvm/clock.c +++ b/hw/i386/kvm/clock.c @@ -22,6 +22,7 @@ #include "kvm_i386.h" #include "hw/sysbus.h" #include "hw/kvm/clock.h" +#include "qapi/error.h" #include <linux/kvm.h> #include <linux/kvm_para.h> @@ -208,6 +209,11 @@ static void kvmclock_realize(DeviceState *dev, Error **errp) { KVMClockState *s = KVM_CLOCK(dev); + if (!kvm_enabled()) { + error_setg(errp, "kvmclock device requires KVM"); + return; + } + kvm_update_clock(s); qemu_add_vm_change_state_handler(kvmclock_vm_state_change, s); diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index 6a17acf639..f60826d6e0 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -1485,6 +1485,18 @@ void ahci_realize(AHCIState *s, DeviceState *qdev, AddressSpace *as, int ports) void ahci_uninit(AHCIState *s) { + int i, j; + + for (i = 0; i < s->ports; i++) { + AHCIDevice *ad = &s->dev[i]; + + for (j = 0; j < 2; j++) { + IDEState *s = &ad->port.ifs[j]; + + ide_exit(s); + } + } + g_free(s->dev); } diff --git a/hw/ide/core.c b/hw/ide/core.c index db509b3e15..0b48b64d3a 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -2603,6 +2603,14 @@ void ide_init2(IDEBus *bus, qemu_irq irq) bus->dma = &ide_dma_nop; } +void ide_exit(IDEState *s) +{ + timer_del(s->sector_write_timer); + timer_free(s->sector_write_timer); + qemu_vfree(s->smart_selftest_data); + qemu_vfree(s->io_buffer); +} + static const MemoryRegionPortio ide_portio_list[] = { { 0, 8, 1, .read = ide_ioport_read, .write = ide_ioport_write }, { 0, 1, 2, .read = ide_data_readw, .write = ide_data_writew }, diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c index 4383cd111d..299e592fa2 100644 --- a/hw/ide/qdev.c +++ b/hw/ide/qdev.c @@ -31,7 +31,7 @@ /* --------------------------------- */ static char *idebus_get_fw_dev_path(DeviceState *dev); -static void idebus_unrealize(DeviceState *qdev, Error **errp); +static void idebus_unrealize(BusState *qdev, Error **errp); static Property ide_props[] = { DEFINE_PROP_UINT32("unit", IDEDevice, unit, -1), @@ -43,14 +43,15 @@ static void ide_bus_class_init(ObjectClass *klass, void *data) BusClass *k = BUS_CLASS(klass); k->get_fw_dev_path = idebus_get_fw_dev_path; + k->unrealize = idebus_unrealize; } -static void idebus_unrealize(DeviceState *qdev, Error **errp) +static void idebus_unrealize(BusState *bus, Error **errp) { - IDEBus *bus = DO_UPCAST(IDEBus, qbus, qdev->parent_bus); + IDEBus *ibus = IDE_BUS(bus); - if (bus->vmstate) { - qemu_del_vm_change_state_handler(bus->vmstate); + if (ibus->vmstate) { + qemu_del_vm_change_state_handler(ibus->vmstate); } } @@ -370,7 +371,6 @@ static void ide_device_class_init(ObjectClass *klass, void *data) k->init = ide_qdev_init; set_bit(DEVICE_CATEGORY_STORAGE, k->categories); k->bus_type = TYPE_IDE_BUS; - k->unrealize = idebus_unrealize; k->props = ide_props; } diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c index 8e5a9d8a3e..b305d9032a 100644 --- a/hw/intc/arm_gic.c +++ b/hw/intc/arm_gic.c @@ -26,15 +26,20 @@ #include "qemu/log.h" #include "trace.h" -//#define DEBUG_GIC +/* #define DEBUG_GIC */ #ifdef DEBUG_GIC -#define DPRINTF(fmt, ...) \ -do { fprintf(stderr, "arm_gic: " fmt , ## __VA_ARGS__); } while (0) +#define DEBUG_GIC_GATE 1 #else -#define DPRINTF(fmt, ...) do {} while(0) +#define DEBUG_GIC_GATE 0 #endif +#define DPRINTF(fmt, ...) do { \ + if (DEBUG_GIC_GATE) { \ + fprintf(stderr, "%s: " fmt, __func__, ## __VA_ARGS__); \ + } \ + } while (0) + static const uint8_t gic_id_11mpcore[] = { 0x00, 0x00, 0x00, 0x00, 0x90, 0x13, 0x04, 0x00, 0x0d, 0xf0, 0x05, 0xb1 }; diff --git a/hw/misc/imx6_src.c b/hw/misc/imx6_src.c index edbb756c36..cfb08710fb 100644 --- a/hw/misc/imx6_src.c +++ b/hw/misc/imx6_src.c @@ -143,13 +143,17 @@ static void imx6_defer_clear_reset_bit(int cpuid, unsigned long reset_shift) { struct SRCSCRResetInfo *ri; + CPUState *cpu = arm_get_cpu_by_id(cpuid); + + if (!cpu) { + return; + } ri = g_malloc(sizeof(struct SRCSCRResetInfo)); ri->s = s; ri->reset_bit = reset_shift; - async_run_on_cpu(arm_get_cpu_by_id(cpuid), imx6_clear_reset_bit, - RUN_ON_CPU_HOST_PTR(ri)); + async_run_on_cpu(cpu, imx6_clear_reset_bit, RUN_ON_CPU_HOST_PTR(ri)); } diff --git a/hw/net/e1000e.c b/hw/net/e1000e.c index b0f429b8e5..6e234938db 100644 --- a/hw/net/e1000e.c +++ b/hw/net/e1000e.c @@ -306,7 +306,7 @@ e1000e_init_msix(E1000EState *s) static void e1000e_cleanup_msix(E1000EState *s) { - if (msix_enabled(PCI_DEVICE(s))) { + if (msix_present(PCI_DEVICE(s))) { e1000e_unuse_msix_vectors(s, E1000E_MSIX_VEC_NUM); msix_uninit(PCI_DEVICE(s), &s->msix, &s->msix); } diff --git a/hw/net/mcf_fec.c b/hw/net/mcf_fec.c index a3eca7e0f5..bfa6b4bcce 100644 --- a/hw/net/mcf_fec.c +++ b/hw/net/mcf_fec.c @@ -27,6 +27,7 @@ do { printf("mcf_fec: " fmt , ## __VA_ARGS__); } while (0) #define FEC_MAX_DESC 1024 #define FEC_MAX_FRAME_SIZE 2032 +#define FEC_MIB_SIZE 64 typedef struct { SysBusDevice parent_obj; @@ -51,6 +52,7 @@ typedef struct { uint32_t erdsr; uint32_t etdsr; uint32_t emrbr; + uint32_t mib[FEC_MIB_SIZE]; } mcf_fec_state; #define FEC_INT_HB 0x80000000 @@ -111,6 +113,63 @@ typedef struct { #define FEC_BD_OV 0x0002 #define FEC_BD_TR 0x0001 +#define MIB_RMON_T_DROP 0 +#define MIB_RMON_T_PACKETS 1 +#define MIB_RMON_T_BC_PKT 2 +#define MIB_RMON_T_MC_PKT 3 +#define MIB_RMON_T_CRC_ALIGN 4 +#define MIB_RMON_T_UNDERSIZE 5 +#define MIB_RMON_T_OVERSIZE 6 +#define MIB_RMON_T_FRAG 7 +#define MIB_RMON_T_JAB 8 +#define MIB_RMON_T_COL 9 +#define MIB_RMON_T_P64 10 +#define MIB_RMON_T_P65TO127 11 +#define MIB_RMON_T_P128TO255 12 +#define MIB_RMON_T_P256TO511 13 +#define MIB_RMON_T_P512TO1023 14 +#define MIB_RMON_T_P1024TO2047 15 +#define MIB_RMON_T_P_GTE2048 16 +#define MIB_RMON_T_OCTETS 17 +#define MIB_IEEE_T_DROP 18 +#define MIB_IEEE_T_FRAME_OK 19 +#define MIB_IEEE_T_1COL 20 +#define MIB_IEEE_T_MCOL 21 +#define MIB_IEEE_T_DEF 22 +#define MIB_IEEE_T_LCOL 23 +#define MIB_IEEE_T_EXCOL 24 +#define MIB_IEEE_T_MACERR 25 +#define MIB_IEEE_T_CSERR 26 +#define MIB_IEEE_T_SQE 27 +#define MIB_IEEE_T_FDXFC 28 +#define MIB_IEEE_T_OCTETS_OK 29 + +#define MIB_RMON_R_DROP 32 +#define MIB_RMON_R_PACKETS 33 +#define MIB_RMON_R_BC_PKT 34 +#define MIB_RMON_R_MC_PKT 35 +#define MIB_RMON_R_CRC_ALIGN 36 +#define MIB_RMON_R_UNDERSIZE 37 +#define MIB_RMON_R_OVERSIZE 38 +#define MIB_RMON_R_FRAG 39 +#define MIB_RMON_R_JAB 40 +#define MIB_RMON_R_RESVD_0 41 +#define MIB_RMON_R_P64 42 +#define MIB_RMON_R_P65TO127 43 +#define MIB_RMON_R_P128TO255 44 +#define MIB_RMON_R_P256TO511 45 +#define MIB_RMON_R_P512TO1023 46 +#define MIB_RMON_R_P1024TO2047 47 +#define MIB_RMON_R_P_GTE2048 48 +#define MIB_RMON_R_OCTETS 49 +#define MIB_IEEE_R_DROP 50 +#define MIB_IEEE_R_FRAME_OK 51 +#define MIB_IEEE_R_CRC 52 +#define MIB_IEEE_R_ALIGN 53 +#define MIB_IEEE_R_MACERR 54 +#define MIB_IEEE_R_FDXFC 55 +#define MIB_IEEE_R_OCTETS_OK 56 + static void mcf_fec_read_bd(mcf_fec_bd *bd, uint32_t addr) { cpu_physical_memory_read(addr, bd, sizeof(*bd)); @@ -147,6 +206,31 @@ static void mcf_fec_update(mcf_fec_state *s) s->irq_state = active; } +static void mcf_fec_tx_stats(mcf_fec_state *s, int size) +{ + s->mib[MIB_RMON_T_PACKETS]++; + s->mib[MIB_RMON_T_OCTETS] += size; + if (size < 64) { + s->mib[MIB_RMON_T_FRAG]++; + } else if (size == 64) { + s->mib[MIB_RMON_T_P64]++; + } else if (size < 128) { + s->mib[MIB_RMON_T_P65TO127]++; + } else if (size < 256) { + s->mib[MIB_RMON_T_P128TO255]++; + } else if (size < 512) { + s->mib[MIB_RMON_T_P256TO511]++; + } else if (size < 1024) { + s->mib[MIB_RMON_T_P512TO1023]++; + } else if (size < 2048) { + s->mib[MIB_RMON_T_P1024TO2047]++; + } else { + s->mib[MIB_RMON_T_P_GTE2048]++; + } + s->mib[MIB_IEEE_T_FRAME_OK]++; + s->mib[MIB_IEEE_T_OCTETS_OK] += size; +} + static void mcf_fec_do_tx(mcf_fec_state *s) { uint32_t addr; @@ -180,6 +264,7 @@ static void mcf_fec_do_tx(mcf_fec_state *s) /* Last buffer in frame. */ DPRINTF("Sending packet\n"); qemu_send_packet(qemu_get_queue(s->nic), frame, frame_size); + mcf_fec_tx_stats(s, frame_size); ptr = frame; frame_size = 0; s->eir |= FEC_INT_TXF; @@ -302,6 +387,7 @@ static uint64_t mcf_fec_read(void *opaque, hwaddr addr, case 0x180: return s->erdsr; case 0x184: return s->etdsr; case 0x188: return s->emrbr; + case 0x200 ... 0x2e0: return s->mib[(addr & 0x1ff) / 4]; default: hw_error("mcf_fec_read: Bad address 0x%x\n", (int)addr); return 0; @@ -399,12 +485,40 @@ static void mcf_fec_write(void *opaque, hwaddr addr, case 0x188: s->emrbr = value > 0 ? value & 0x7F0 : 0x7F0; break; + case 0x200 ... 0x2e0: + s->mib[(addr & 0x1ff) / 4] = value; + break; default: hw_error("mcf_fec_write Bad address 0x%x\n", (int)addr); } mcf_fec_update(s); } +static void mcf_fec_rx_stats(mcf_fec_state *s, int size) +{ + s->mib[MIB_RMON_R_PACKETS]++; + s->mib[MIB_RMON_R_OCTETS] += size; + if (size < 64) { + s->mib[MIB_RMON_R_FRAG]++; + } else if (size == 64) { + s->mib[MIB_RMON_R_P64]++; + } else if (size < 128) { + s->mib[MIB_RMON_R_P65TO127]++; + } else if (size < 256) { + s->mib[MIB_RMON_R_P128TO255]++; + } else if (size < 512) { + s->mib[MIB_RMON_R_P256TO511]++; + } else if (size < 1024) { + s->mib[MIB_RMON_R_P512TO1023]++; + } else if (size < 2048) { + s->mib[MIB_RMON_R_P1024TO2047]++; + } else { + s->mib[MIB_RMON_R_P_GTE2048]++; + } + s->mib[MIB_IEEE_R_FRAME_OK]++; + s->mib[MIB_IEEE_R_OCTETS_OK] += size; +} + static int mcf_fec_have_receive_space(mcf_fec_state *s, size_t want) { mcf_fec_bd bd; @@ -500,6 +614,7 @@ static ssize_t mcf_fec_receive(NetClientState *nc, const uint8_t *buf, size_t si } } s->rx_descriptor = addr; + mcf_fec_rx_stats(s, retsize); mcf_fec_enable_rx(s); mcf_fec_update(s); return retsize; diff --git a/hw/pci/pci.c b/hw/pci/pci.c index 273f1e4602..e6b08e1988 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -64,6 +64,8 @@ static Property pci_props[] = { QEMU_PCI_CAP_SERR_BITNR, true), DEFINE_PROP_BIT("x-pcie-lnksta-dllla", PCIDevice, cap_present, QEMU_PCIE_LNKSTA_DLLLA_BITNR, true), + DEFINE_PROP_BIT("x-pcie-extcap-init", PCIDevice, cap_present, + QEMU_PCIE_EXTCAP_INIT_BITNR, true), DEFINE_PROP_END_OF_LIST() }; @@ -88,8 +90,8 @@ static void pci_init_bus_master(PCIDevice *pci_dev) OBJECT(pci_dev), "bus master", dma_as->root, 0, memory_region_size(dma_as->root)); memory_region_set_enabled(&pci_dev->bus_master_enable_region, false); - address_space_init(&pci_dev->bus_master_as, - &pci_dev->bus_master_enable_region, pci_dev->name); + memory_region_add_subregion(&pci_dev->bus_master_container_region, 0, + &pci_dev->bus_master_enable_region); } static void pcibus_machine_done(Notifier *notifier, void *data) @@ -995,6 +997,11 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus, pci_dev->devfn = devfn; pci_dev->requester_id_cache = pci_req_id_cache_get(pci_dev); + memory_region_init(&pci_dev->bus_master_container_region, OBJECT(pci_dev), + "bus master container", UINT64_MAX); + address_space_init(&pci_dev->bus_master_as, + &pci_dev->bus_master_container_region, pci_dev->name); + if (qdev_hotplug) { pci_init_bus_master(pci_dev); } diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c index fc54bfd53d..18e634f577 100644 --- a/hw/pci/pcie.c +++ b/hw/pci/pcie.c @@ -109,6 +109,12 @@ int pcie_cap_init(PCIDevice *dev, uint8_t offset, uint8_t type, uint8_t port) PCI_EXP_DEVCAP2_EFF | PCI_EXP_DEVCAP2_EETLPP); pci_set_word(dev->wmask + pos + PCI_EXP_DEVCTL2, PCI_EXP_DEVCTL2_EETLPPB); + + if (dev->cap_present & QEMU_PCIE_EXTCAP_INIT) { + /* read-only to behave like a 'NULL' Extended Capability Header */ + pci_set_long(dev->wmask + PCI_CONFIG_SPACE_SIZE, 0); + } + return pos; } @@ -217,6 +223,20 @@ void pcie_cap_deverr_reset(PCIDevice *dev) PCI_EXP_DEVCTL_FERE | PCI_EXP_DEVCTL_URRE); } +void pcie_cap_lnkctl_init(PCIDevice *dev) +{ + uint32_t pos = dev->exp.exp_cap; + pci_long_test_and_set_mask(dev->wmask + pos + PCI_EXP_LNKCTL, + PCI_EXP_LNKCTL_CCC | PCI_EXP_LNKCTL_ES); +} + +void pcie_cap_lnkctl_reset(PCIDevice *dev) +{ + uint8_t *lnkctl = dev->config + dev->exp.exp_cap + PCI_EXP_LNKCTL; + pci_long_test_and_clear_mask(lnkctl, + PCI_EXP_LNKCTL_CCC | PCI_EXP_LNKCTL_ES); +} + static void hotplug_event_update_event_status(PCIDevice *dev) { uint32_t pos = dev->exp.exp_cap; diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index 09f0d22def..3fa722af82 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -21,6 +21,7 @@ #include "qapi/error.h" #include "sysemu/sysemu.h" #include "sysemu/numa.h" +#include "sysemu/cpus.h" #include "hw/hw.h" #include "target/ppc/cpu.h" #include "qemu/log.h" diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index c3bb991605..6ee566d658 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -3163,8 +3163,13 @@ DEFINE_SPAPR_MACHINE(2_9, "2.9", true); /* * pseries-2.8 */ -#define SPAPR_COMPAT_2_8 \ - HW_COMPAT_2_8 +#define SPAPR_COMPAT_2_8 \ + HW_COMPAT_2_8 \ + { \ + .driver = TYPE_SPAPR_PCI_HOST_BRIDGE, \ + .property = "pcie-extended-configuration-space", \ + .value = "off", \ + }, static void spapr_machine_2_8_instance_options(MachineState *machine) { diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c index 919d3c2c59..98c52e411f 100644 --- a/hw/ppc/spapr_pci.c +++ b/hw/ppc/spapr_pci.c @@ -1321,7 +1321,7 @@ static int spapr_populate_pci_child_dt(PCIDevice *dev, void *fdt, int offset, _FDT(fdt_setprop(fdt, offset, "assigned-addresses", (uint8_t *)rp.assigned, rp.assigned_len)); - if (pci_is_express(dev)) { + if (sphb->pcie_ecs && pci_is_express(dev)) { _FDT(fdt_setprop_cell(fdt, offset, "ibm,pci-config-space-type", 0x1)); } @@ -1858,6 +1858,8 @@ static Property spapr_phb_properties[] = { DEFINE_PROP_UINT32("numa_node", sPAPRPHBState, numa_node, -1), DEFINE_PROP_BOOL("pre-2.8-migration", sPAPRPHBState, pre_2_8_migration, false), + DEFINE_PROP_BOOL("pcie-extended-configuration-space", sPAPRPHBState, + pcie_ecs, true), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/scsi/mptsas.c b/hw/scsi/mptsas.c index 2e091c0156..765ab53c34 100644 --- a/hw/scsi/mptsas.c +++ b/hw/scsi/mptsas.c @@ -756,7 +756,7 @@ static void mptsas_fetch_request(MPTSASState *s) /* Read the message header from the guest first. */ addr = s->host_mfa_high_addr | MPTSAS_FIFO_GET(s, request_post); - pci_dma_read(pci, addr, req, sizeof(hdr)); + pci_dma_read(pci, addr, req, sizeof(*hdr)); if (hdr->Function < ARRAY_SIZE(mpi_request_sizes) && mpi_request_sizes[hdr->Function]) { @@ -766,8 +766,8 @@ static void mptsas_fetch_request(MPTSASState *s) */ size = mpi_request_sizes[hdr->Function]; assert(size <= MPTSAS_MAX_REQUEST_SIZE); - pci_dma_read(pci, addr + sizeof(hdr), &req[sizeof(hdr)], - size - sizeof(hdr)); + pci_dma_read(pci, addr + sizeof(*hdr), &req[sizeof(*hdr)], + size - sizeof(*hdr)); } if (hdr->Function == MPI_FUNCTION_SCSI_IO_REQUEST) { diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c index 61416a6426..873cd7df9a 100644 --- a/hw/sparc/sun4m.c +++ b/hw/sparc/sun4m.c @@ -142,6 +142,9 @@ void cpu_check_irqs(CPUSPARCState *env) { CPUState *cs; + /* We should be holding the BQL before we mess with IRQs */ + g_assert(qemu_mutex_iothread_locked()); + if (env->pil_in && (env->interrupt_index == 0 || (env->interrupt_index & ~15) == TT_EXTINT)) { unsigned int i; diff --git a/hw/sparc64/sparc64.c b/hw/sparc64/sparc64.c index b3d219c769..4e4fdab065 100644 --- a/hw/sparc64/sparc64.c +++ b/hw/sparc64/sparc64.c @@ -55,6 +55,9 @@ void cpu_check_irqs(CPUSPARCState *env) uint32_t pil = env->pil_in | (env->softint & ~(SOFTINT_TIMER | SOFTINT_STIMER)); + /* We should be holding the BQL before we mess with IRQs */ + g_assert(qemu_mutex_iothread_locked()); + /* TT_IVEC has a higher priority (16) than TT_EXTINT (31..17) */ if (env->ivec_status & 0x20) { return; diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index b76f3f62a0..f9b7244808 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -1153,7 +1153,7 @@ static AddressSpace *virtio_pci_get_dma_as(DeviceState *d) VirtIOPCIProxy *proxy = VIRTIO_PCI(d); PCIDevice *dev = &proxy->pci_dev; - return pci_device_iommu_address_space(dev); + return pci_get_address_space(dev); } static int virtio_pci_add_mem_cap(VirtIOPCIProxy *proxy, @@ -1812,6 +1812,7 @@ static void virtio_pci_realize(PCIDevice *pci_dev, Error **errp) pos = pci_add_capability(pci_dev, PCI_CAP_ID_PM, 0, PCI_PM_SIZEOF); assert(pos > 0); + pci_dev->exp.pm_cap = pos; /* * Indicates that this function complies with revision 1.2 of the @@ -1819,6 +1820,22 @@ static void virtio_pci_realize(PCIDevice *pci_dev, Error **errp) */ pci_set_word(pci_dev->config + pos + PCI_PM_PMC, 0x3); + if (proxy->flags & VIRTIO_PCI_FLAG_INIT_DEVERR) { + /* Init error enabling flags */ + pcie_cap_deverr_init(pci_dev); + } + + if (proxy->flags & VIRTIO_PCI_FLAG_INIT_LNKCTL) { + /* Init Link Control Register */ + pcie_cap_lnkctl_init(pci_dev); + } + + if (proxy->flags & VIRTIO_PCI_FLAG_INIT_PM) { + /* Init Power Management Control Register */ + pci_set_word(pci_dev->wmask + pos + PCI_PM_CTRL, + PCI_PM_CTRL_STATE_MASK); + } + if (proxy->flags & VIRTIO_PCI_FLAG_ATS) { pcie_ats_init(pci_dev, 256); } @@ -1849,6 +1866,7 @@ static void virtio_pci_reset(DeviceState *qdev) { VirtIOPCIProxy *proxy = VIRTIO_PCI(qdev); VirtioBusState *bus = VIRTIO_BUS(&proxy->bus); + PCIDevice *dev = PCI_DEVICE(qdev); int i; virtio_pci_stop_ioeventfd(proxy); @@ -1857,6 +1875,17 @@ static void virtio_pci_reset(DeviceState *qdev) for (i = 0; i < VIRTIO_QUEUE_MAX; i++) { proxy->vqs[i].enabled = 0; + proxy->vqs[i].num = 0; + proxy->vqs[i].desc[0] = proxy->vqs[i].desc[1] = 0; + proxy->vqs[i].avail[0] = proxy->vqs[i].avail[1] = 0; + proxy->vqs[i].used[0] = proxy->vqs[i].used[1] = 0; + } + + if (pci_is_express(dev)) { + pcie_cap_deverr_reset(dev); + pcie_cap_lnkctl_reset(dev); + + pci_set_word(dev->config + dev->exp.pm_cap + PCI_PM_CTRL, 0); } } @@ -1878,6 +1907,12 @@ static Property virtio_pci_properties[] = { ignore_backend_features, false), DEFINE_PROP_BIT("ats", VirtIOPCIProxy, flags, VIRTIO_PCI_FLAG_ATS_BIT, false), + DEFINE_PROP_BIT("x-pcie-deverr-init", VirtIOPCIProxy, flags, + VIRTIO_PCI_FLAG_INIT_DEVERR_BIT, true), + DEFINE_PROP_BIT("x-pcie-lnkctl-init", VirtIOPCIProxy, flags, + VIRTIO_PCI_FLAG_INIT_LNKCTL_BIT, true), + DEFINE_PROP_BIT("x-pcie-pm-init", VirtIOPCIProxy, flags, + VIRTIO_PCI_FLAG_INIT_PM_BIT, true), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/virtio/virtio-pci.h b/hw/virtio/virtio-pci.h index d00064cc0c..b095dfc6d9 100644 --- a/hw/virtio/virtio-pci.h +++ b/hw/virtio/virtio-pci.h @@ -73,6 +73,9 @@ enum { VIRTIO_PCI_FLAG_DISABLE_PCIE_BIT, VIRTIO_PCI_FLAG_PAGE_PER_VQ_BIT, VIRTIO_PCI_FLAG_ATS_BIT, + VIRTIO_PCI_FLAG_INIT_DEVERR_BIT, + VIRTIO_PCI_FLAG_INIT_LNKCTL_BIT, + VIRTIO_PCI_FLAG_INIT_PM_BIT, }; /* Need to activate work-arounds for buggy guests at vmstate load. */ @@ -100,6 +103,15 @@ enum { /* address space translation service */ #define VIRTIO_PCI_FLAG_ATS (1 << VIRTIO_PCI_FLAG_ATS_BIT) +/* Init error enabling flags */ +#define VIRTIO_PCI_FLAG_INIT_DEVERR (1 << VIRTIO_PCI_FLAG_INIT_DEVERR_BIT) + +/* Init Link Control register */ +#define VIRTIO_PCI_FLAG_INIT_LNKCTL (1 << VIRTIO_PCI_FLAG_INIT_LNKCTL_BIT) + +/* Init Power Management */ +#define VIRTIO_PCI_FLAG_INIT_PM (1 << VIRTIO_PCI_FLAG_INIT_PM_BIT) + typedef struct { MSIMessage msg; int virq; diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index efce4b343a..82b6060b2a 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -131,6 +131,7 @@ static void virtio_init_region_cache(VirtIODevice *vdev, int n) VRingMemoryRegionCaches *new; hwaddr addr, size; int event_size; + int64_t len; event_size = virtio_vdev_has_feature(vq->vdev, VIRTIO_RING_F_EVENT_IDX) ? 2 : 0; @@ -140,21 +141,41 @@ static void virtio_init_region_cache(VirtIODevice *vdev, int n) } new = g_new0(VRingMemoryRegionCaches, 1); size = virtio_queue_get_desc_size(vdev, n); - address_space_cache_init(&new->desc, vdev->dma_as, - addr, size, false); + len = address_space_cache_init(&new->desc, vdev->dma_as, + addr, size, false); + if (len < size) { + virtio_error(vdev, "Cannot map desc"); + goto err_desc; + } size = virtio_queue_get_used_size(vdev, n) + event_size; - address_space_cache_init(&new->used, vdev->dma_as, - vq->vring.used, size, true); + len = address_space_cache_init(&new->used, vdev->dma_as, + vq->vring.used, size, true); + if (len < size) { + virtio_error(vdev, "Cannot map used"); + goto err_used; + } size = virtio_queue_get_avail_size(vdev, n) + event_size; - address_space_cache_init(&new->avail, vdev->dma_as, - vq->vring.avail, size, false); + len = address_space_cache_init(&new->avail, vdev->dma_as, + vq->vring.avail, size, false); + if (len < size) { + virtio_error(vdev, "Cannot map avail"); + goto err_avail; + } atomic_rcu_set(&vq->vring.caches, new); if (old) { call_rcu(old, virtio_free_region_cache, rcu); } + return; + +err_avail: + address_space_cache_destroy(&new->used); +err_used: + address_space_cache_destroy(&new->desc); +err_desc: + g_free(new); } /* virt queue functions */ @@ -185,10 +206,16 @@ static void vring_desc_read(VirtIODevice *vdev, VRingDesc *desc, virtio_tswap16s(vdev, &desc->next); } +static VRingMemoryRegionCaches *vring_get_region_caches(struct VirtQueue *vq) +{ + VRingMemoryRegionCaches *caches = atomic_rcu_read(&vq->vring.caches); + assert(caches != NULL); + return caches; +} /* Called within rcu_read_lock(). */ static inline uint16_t vring_avail_flags(VirtQueue *vq) { - VRingMemoryRegionCaches *caches = atomic_rcu_read(&vq->vring.caches); + VRingMemoryRegionCaches *caches = vring_get_region_caches(vq); hwaddr pa = offsetof(VRingAvail, flags); return virtio_lduw_phys_cached(vq->vdev, &caches->avail, pa); } @@ -196,7 +223,7 @@ static inline uint16_t vring_avail_flags(VirtQueue *vq) /* Called within rcu_read_lock(). */ static inline uint16_t vring_avail_idx(VirtQueue *vq) { - VRingMemoryRegionCaches *caches = atomic_rcu_read(&vq->vring.caches); + VRingMemoryRegionCaches *caches = vring_get_region_caches(vq); hwaddr pa = offsetof(VRingAvail, idx); vq->shadow_avail_idx = virtio_lduw_phys_cached(vq->vdev, &caches->avail, pa); return vq->shadow_avail_idx; @@ -205,7 +232,7 @@ static inline uint16_t vring_avail_idx(VirtQueue *vq) /* Called within rcu_read_lock(). */ static inline uint16_t vring_avail_ring(VirtQueue *vq, int i) { - VRingMemoryRegionCaches *caches = atomic_rcu_read(&vq->vring.caches); + VRingMemoryRegionCaches *caches = vring_get_region_caches(vq); hwaddr pa = offsetof(VRingAvail, ring[i]); return virtio_lduw_phys_cached(vq->vdev, &caches->avail, pa); } @@ -220,7 +247,7 @@ static inline uint16_t vring_get_used_event(VirtQueue *vq) static inline void vring_used_write(VirtQueue *vq, VRingUsedElem *uelem, int i) { - VRingMemoryRegionCaches *caches = atomic_rcu_read(&vq->vring.caches); + VRingMemoryRegionCaches *caches = vring_get_region_caches(vq); hwaddr pa = offsetof(VRingUsed, ring[i]); virtio_tswap32s(vq->vdev, &uelem->id); virtio_tswap32s(vq->vdev, &uelem->len); @@ -231,7 +258,7 @@ static inline void vring_used_write(VirtQueue *vq, VRingUsedElem *uelem, /* Called within rcu_read_lock(). */ static uint16_t vring_used_idx(VirtQueue *vq) { - VRingMemoryRegionCaches *caches = atomic_rcu_read(&vq->vring.caches); + VRingMemoryRegionCaches *caches = vring_get_region_caches(vq); hwaddr pa = offsetof(VRingUsed, idx); return virtio_lduw_phys_cached(vq->vdev, &caches->used, pa); } @@ -239,7 +266,7 @@ static uint16_t vring_used_idx(VirtQueue *vq) /* Called within rcu_read_lock(). */ static inline void vring_used_idx_set(VirtQueue *vq, uint16_t val) { - VRingMemoryRegionCaches *caches = atomic_rcu_read(&vq->vring.caches); + VRingMemoryRegionCaches *caches = vring_get_region_caches(vq); hwaddr pa = offsetof(VRingUsed, idx); virtio_stw_phys_cached(vq->vdev, &caches->used, pa, val); address_space_cache_invalidate(&caches->used, pa, sizeof(val)); @@ -249,7 +276,7 @@ static inline void vring_used_idx_set(VirtQueue *vq, uint16_t val) /* Called within rcu_read_lock(). */ static inline void vring_used_flags_set_bit(VirtQueue *vq, int mask) { - VRingMemoryRegionCaches *caches = atomic_rcu_read(&vq->vring.caches); + VRingMemoryRegionCaches *caches = vring_get_region_caches(vq); VirtIODevice *vdev = vq->vdev; hwaddr pa = offsetof(VRingUsed, flags); uint16_t flags = virtio_lduw_phys_cached(vq->vdev, &caches->used, pa); @@ -261,7 +288,7 @@ static inline void vring_used_flags_set_bit(VirtQueue *vq, int mask) /* Called within rcu_read_lock(). */ static inline void vring_used_flags_unset_bit(VirtQueue *vq, int mask) { - VRingMemoryRegionCaches *caches = atomic_rcu_read(&vq->vring.caches); + VRingMemoryRegionCaches *caches = vring_get_region_caches(vq); VirtIODevice *vdev = vq->vdev; hwaddr pa = offsetof(VRingUsed, flags); uint16_t flags = virtio_lduw_phys_cached(vq->vdev, &caches->used, pa); @@ -279,7 +306,7 @@ static inline void vring_set_avail_event(VirtQueue *vq, uint16_t val) return; } - caches = atomic_rcu_read(&vq->vring.caches); + caches = vring_get_region_caches(vq); pa = offsetof(VRingUsed, ring[vq->vring.num]); virtio_stw_phys_cached(vq->vdev, &caches->used, pa, val); address_space_cache_invalidate(&caches->used, pa, sizeof(val)); @@ -318,6 +345,10 @@ int virtio_queue_ready(VirtQueue *vq) * Called within rcu_read_lock(). */ static int virtio_queue_empty_rcu(VirtQueue *vq) { + if (unlikely(!vq->vring.avail)) { + return 1; + } + if (vq->shadow_avail_idx != vq->last_avail_idx) { return 0; } @@ -329,6 +360,10 @@ int virtio_queue_empty(VirtQueue *vq) { bool empty; + if (unlikely(!vq->vring.avail)) { + return 1; + } + if (vq->shadow_avail_idx != vq->last_avail_idx) { return 0; } @@ -431,6 +466,10 @@ void virtqueue_fill(VirtQueue *vq, const VirtQueueElement *elem, return; } + if (unlikely(!vq->vring.used)) { + return; + } + idx = (idx + vq->used_idx) % vq->vring.num; uelem.id = elem->index; @@ -448,6 +487,10 @@ void virtqueue_flush(VirtQueue *vq, unsigned int count) return; } + if (unlikely(!vq->vring.used)) { + return; + } + /* Make sure buffer is written before we update index. */ smp_wmb(); trace_virtqueue_flush(vq, count); @@ -546,12 +589,22 @@ void virtqueue_get_avail_bytes(VirtQueue *vq, unsigned int *in_bytes, int64_t len = 0; int rc; + if (unlikely(!vq->vring.desc)) { + if (in_bytes) { + *in_bytes = 0; + } + if (out_bytes) { + *out_bytes = 0; + } + return; + } + rcu_read_lock(); idx = vq->last_avail_idx; total_bufs = in_total = out_total = 0; max = vq->vring.num; - caches = atomic_rcu_read(&vq->vring.caches); + caches = vring_get_region_caches(vq); if (caches->desc.len < max * sizeof(VRingDesc)) { virtio_error(vdev, "Cannot map descriptor ring"); goto err; @@ -818,7 +871,7 @@ void *virtqueue_pop(VirtQueue *vq, size_t sz) i = head; - caches = atomic_rcu_read(&vq->vring.caches); + caches = vring_get_region_caches(vq); if (caches->desc.len < max * sizeof(VRingDesc)) { virtio_error(vdev, "Cannot map descriptor ring"); goto done; @@ -1117,6 +1170,17 @@ static enum virtio_device_endian virtio_current_cpu_endian(void) } } +static void virtio_virtqueue_reset_region_cache(struct VirtQueue *vq) +{ + VRingMemoryRegionCaches *caches; + + caches = atomic_read(&vq->vring.caches); + atomic_rcu_set(&vq->vring.caches, NULL); + if (caches) { + call_rcu(caches, virtio_free_region_cache, rcu); + } +} + void virtio_reset(void *opaque) { VirtIODevice *vdev = opaque; @@ -1157,6 +1221,7 @@ void virtio_reset(void *opaque) vdev->vq[i].notification = true; vdev->vq[i].vring.num = vdev->vq[i].vring.num_default; vdev->vq[i].inuse = 0; + virtio_virtqueue_reset_region_cache(&vdev->vq[i]); } } @@ -2451,13 +2516,10 @@ static void virtio_device_free_virtqueues(VirtIODevice *vdev) } for (i = 0; i < VIRTIO_QUEUE_MAX; i++) { - VRingMemoryRegionCaches *caches; if (vdev->vq[i].vring.num == 0) { break; } - caches = atomic_read(&vdev->vq[i].vring.caches); - atomic_set(&vdev->vq[i].vring.caches, NULL); - virtio_free_region_cache(caches); + virtio_virtqueue_reset_region_cache(&vdev->vq[i]); } g_free(vdev->vq); } diff --git a/include/block/block_int.h b/include/block/block_int.h index 6c699ac9c3..59400bd848 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -889,10 +889,6 @@ BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs, void *opaque, Error **errp); void bdrv_root_unref_child(BdrvChild *child); -int bdrv_child_check_perm(BdrvChild *c, uint64_t perm, uint64_t shared, - GSList *ignore_children, Error **errp); -void bdrv_child_set_perm(BdrvChild *c, uint64_t perm, uint64_t shared); -void bdrv_child_abort_perm_update(BdrvChild *c); int bdrv_child_try_set_perm(BdrvChild *c, uint64_t perm, uint64_t shared, Error **errp); diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h index b62f0d82e4..4d45a72ea9 100644 --- a/include/exec/cpu-common.h +++ b/include/exec/cpu-common.h @@ -69,6 +69,7 @@ RAMBlock *qemu_ram_block_from_host(void *ptr, bool round_offset, void qemu_ram_set_idstr(RAMBlock *block, const char *name, DeviceState *dev); void qemu_ram_unset_idstr(RAMBlock *block); const char *qemu_ram_get_idstr(RAMBlock *rb); +bool qemu_ram_is_shared(RAMBlock *rb); size_t qemu_ram_pagesize(RAMBlock *block); size_t qemu_ram_pagesize_largest(void); diff --git a/include/exec/memory.h b/include/exec/memory.h index 691102317c..e39256ad03 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -371,7 +371,8 @@ void memory_region_init_io(MemoryRegion *mr, * * @mr: the #MemoryRegion to be initialized. * @owner: the object that tracks the region's reference count - * @name: the name of the region. + * @name: Region name, becomes part of RAMBlock name used in migration stream + * must be unique within any device * @size: size of the region. * @errp: pointer to Error*, to store an error if it happens. */ @@ -390,7 +391,8 @@ void memory_region_init_ram(MemoryRegion *mr, * * @mr: the #MemoryRegion to be initialized. * @owner: the object that tracks the region's reference count - * @name: the name of the region. + * @name: Region name, becomes part of RAMBlock name used in migration stream + * must be unique within any device * @size: used size of the region. * @max_size: max size of the region. * @resized: callback to notify owner about used size change. @@ -412,7 +414,8 @@ void memory_region_init_resizeable_ram(MemoryRegion *mr, * * @mr: the #MemoryRegion to be initialized. * @owner: the object that tracks the region's reference count - * @name: the name of the region. + * @name: Region name, becomes part of RAMBlock name used in migration stream + * must be unique within any device * @size: size of the region. * @share: %true if memory must be mmaped with the MAP_SHARED flag * @path: the path in which to allocate the RAM. @@ -434,7 +437,8 @@ void memory_region_init_ram_from_file(MemoryRegion *mr, * * @mr: the #MemoryRegion to be initialized. * @owner: the object that tracks the region's reference count - * @name: the name of the region. + * @name: Region name, becomes part of RAMBlock name used in migration stream + * must be unique within any device * @size: size of the region. * @ptr: memory to be mapped; must contain at least @size bytes. */ @@ -496,7 +500,8 @@ void memory_region_init_alias(MemoryRegion *mr, * * @mr: the #MemoryRegion to be initialized. * @owner: the object that tracks the region's reference count - * @name: the name of the region. + * @name: Region name, becomes part of RAMBlock name used in migration stream + * must be unique within any device * @size: size of the region. * @errp: pointer to Error*, to store an error if it happens. */ @@ -513,7 +518,8 @@ void memory_region_init_rom(MemoryRegion *mr, * @mr: the #MemoryRegion to be initialized. * @owner: the object that tracks the region's reference count * @ops: callbacks for write access handling (must not be NULL). - * @name: the name of the region. + * @name: Region name, becomes part of RAMBlock name used in migration stream + * must be unique within any device * @size: size of the region. * @errp: pointer to Error*, to store an error if it happens. */ diff --git a/include/exec/ram_addr.h b/include/exec/ram_addr.h index cd432e73ae..b05dc84ab9 100644 --- a/include/exec/ram_addr.h +++ b/include/exec/ram_addr.h @@ -355,7 +355,8 @@ static inline void cpu_physical_memory_clear_dirty_range(ram_addr_t start, static inline uint64_t cpu_physical_memory_sync_dirty_bitmap(unsigned long *dest, ram_addr_t start, - ram_addr_t length) + ram_addr_t length, + int64_t *real_dirty_pages) { ram_addr_t addr; unsigned long page = BIT_WORD(start >> TARGET_PAGE_BITS); @@ -379,6 +380,7 @@ uint64_t cpu_physical_memory_sync_dirty_bitmap(unsigned long *dest, if (src[idx][offset]) { unsigned long bits = atomic_xchg(&src[idx][offset], 0); unsigned long new_dirty; + *real_dirty_pages += ctpopl(bits); new_dirty = ~dest[k]; dest[k] |= bits; new_dirty &= bits; @@ -398,6 +400,7 @@ uint64_t cpu_physical_memory_sync_dirty_bitmap(unsigned long *dest, start + addr, TARGET_PAGE_SIZE, DIRTY_MEMORY_MIGRATION)) { + *real_dirty_pages += 1; long k = (start + addr) >> TARGET_PAGE_BITS; if (!test_and_set_bit(k, dest)) { num_dirty++; diff --git a/include/hw/compat.h b/include/hw/compat.h index b7db43803c..fc8c3e0600 100644 --- a/include/hw/compat.h +++ b/include/hw/compat.h @@ -18,6 +18,30 @@ .driver = "pci-bridge",\ .property = "shpc",\ .value = "on",\ + },{\ + .driver = TYPE_PCI_DEVICE,\ + .property = "x-pcie-extcap-init",\ + .value = "off",\ + },{\ + .driver = "virtio-pci",\ + .property = "x-pcie-deverr-init",\ + .value = "off",\ + },{\ + .driver = "virtio-pci",\ + .property = "x-pcie-lnkctl-init",\ + .value = "off",\ + },{\ + .driver = "virtio-pci",\ + .property = "x-pcie-pm-init",\ + .value = "off",\ + },{\ + .driver = "cirrus-vga",\ + .property = "vgamem_mb",\ + .value = "8",\ + },{\ + .driver = "isa-cirrus-vga",\ + .property = "vgamem_mb",\ + .value = "8",\ }, #define HW_COMPAT_2_7 \ diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index ab303c7fee..f278b3ae89 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -389,6 +389,11 @@ bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *); .driver = TYPE_X86_CPU,\ .property = "vmware-cpuid-freq",\ .value = "off",\ + },\ + {\ + .driver = "Haswell-" TYPE_X86_CPU,\ + .property = "stepping",\ + .value = "1",\ }, #define PC_COMPAT_2_7 \ diff --git a/include/hw/ide/internal.h b/include/hw/ide/internal.h index 88dc11808b..482a9512be 100644 --- a/include/hw/ide/internal.h +++ b/include/hw/ide/internal.h @@ -607,6 +607,7 @@ int ide_init_drive(IDEState *s, BlockBackend *blk, IDEDriveKind kind, uint32_t cylinders, uint32_t heads, uint32_t secs, int chs_trans); void ide_init2(IDEBus *bus, qemu_irq irq); +void ide_exit(IDEState *s); void ide_init_ioport(IDEBus *bus, ISADevice *isa, int iobase, int iobase2); void ide_register_restart_cb(IDEBus *bus); diff --git a/include/hw/pci-host/spapr.h b/include/hw/pci-host/spapr.h index dfa76143f3..1c2e970da2 100644 --- a/include/hw/pci-host/spapr.h +++ b/include/hw/pci-host/spapr.h @@ -80,6 +80,8 @@ struct sPAPRPHBState { uint32_t numa_node; + bool pcie_ecs; /* Allow access to PCIe extended config space? */ + /* Fields for migration compatibility hacks */ bool pre_2_8_migration; uint32_t mig_liobn; diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index 9349acbfb2..a37a2d5cb6 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -183,6 +183,8 @@ enum { /* Link active status in endpoint capability is always set */ #define QEMU_PCIE_LNKSTA_DLLLA_BITNR 8 QEMU_PCIE_LNKSTA_DLLLA = (1 << QEMU_PCIE_LNKSTA_DLLLA_BITNR), +#define QEMU_PCIE_EXTCAP_INIT_BITNR 9 + QEMU_PCIE_EXTCAP_INIT = (1 << QEMU_PCIE_EXTCAP_INIT_BITNR), }; #define TYPE_PCI_DEVICE "pci-device" @@ -284,6 +286,7 @@ struct PCIDevice { char name[64]; PCIIORegion io_regions[PCI_NUM_REGIONS]; AddressSpace bus_master_as; + MemoryRegion bus_master_container_region; MemoryRegion bus_master_enable_region; /* do not access the following fields */ diff --git a/include/hw/pci/pcie.h b/include/hw/pci/pcie.h index 163c5195b6..3d8f24b007 100644 --- a/include/hw/pci/pcie.h +++ b/include/hw/pci/pcie.h @@ -63,6 +63,8 @@ typedef enum { struct PCIExpressDevice { /* Offset of express capability in config space */ uint8_t exp_cap; + /* Offset of Power Management capability in config space */ + uint8_t pm_cap; /* SLOT */ bool hpev_notified; /* Logical AND of conditions for hot plug event. @@ -96,6 +98,9 @@ uint8_t pcie_cap_flags_get_vector(PCIDevice *dev); void pcie_cap_deverr_init(PCIDevice *dev); void pcie_cap_deverr_reset(PCIDevice *dev); +void pcie_cap_lnkctl_init(PCIDevice *dev); +void pcie_cap_lnkctl_reset(PCIDevice *dev); + void pcie_cap_slot_init(PCIDevice *dev, uint16_t slot); void pcie_cap_slot_reset(PCIDevice *dev); void pcie_cap_slot_write_config(PCIDevice *dev, diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h index af37195fef..122ff06ff6 100644 --- a/include/qemu/osdep.h +++ b/include/qemu/osdep.h @@ -438,7 +438,8 @@ unsigned long qemu_getauxval(unsigned long type); void qemu_set_tty_echo(int fd, bool echo); -void os_mem_prealloc(int fd, char *area, size_t sz, Error **errp); +void os_mem_prealloc(int fd, char *area, size_t sz, int smp_cpus, + Error **errp); int qemu_read_password(char *buf, int buf_size); diff --git a/include/qemu/timer.h b/include/qemu/timer.h index 26e628584c..e1742f2f3d 100644 --- a/include/qemu/timer.h +++ b/include/qemu/timer.h @@ -4,7 +4,6 @@ #include "qemu-common.h" #include "qemu/notify.h" #include "qemu/host-utils.h" -#include "sysemu/cpus.h" #define NANOSECONDS_PER_SECOND 1000000000LL @@ -60,7 +59,7 @@ struct QEMUTimerListGroup { }; typedef void QEMUTimerCB(void *opaque); -typedef void QEMUTimerListNotifyCB(void *opaque); +typedef void QEMUTimerListNotifyCB(void *opaque, QEMUClockType type); struct QEMUTimer { int64_t expire_time; /* in nanoseconds */ @@ -534,6 +533,12 @@ static inline QEMUTimer *timer_new_tl(QEMUTimerList *timer_list, * Create a new timer and associate it with the default * timer list for the clock type @type. * + * The default timer list has one special feature: in icount mode, + * %QEMU_CLOCK_VIRTUAL timers are run in the vCPU thread. This is + * not true of other timer lists, which are typically associated + * with an AioContext---each of them runs its timer callbacks in its own + * AioContext thread. + * * Returns: a pointer to the timer */ static inline QEMUTimer *timer_new(QEMUClockType type, int scale, @@ -551,6 +556,12 @@ static inline QEMUTimer *timer_new(QEMUClockType type, int scale, * Create a new timer with nanosecond scale on the default timer list * associated with the clock. * + * The default timer list has one special feature: in icount mode, + * %QEMU_CLOCK_VIRTUAL timers are run in the vCPU thread. This is + * not true of other timer lists, which are typically associated + * with an AioContext---each of them runs its timer callbacks in its own + * AioContext thread. + * * Returns: a pointer to the newly created timer */ static inline QEMUTimer *timer_new_ns(QEMUClockType type, QEMUTimerCB *cb, @@ -565,6 +576,12 @@ static inline QEMUTimer *timer_new_ns(QEMUClockType type, QEMUTimerCB *cb, * @cb: the callback to call when the timer expires * @opaque: the opaque pointer to pass to the callback * + * The default timer list has one special feature: in icount mode, + * %QEMU_CLOCK_VIRTUAL timers are run in the vCPU thread. This is + * not true of other timer lists, which are typically associated + * with an AioContext---each of them runs its timer callbacks in its own + * AioContext thread. + * * Create a new timer with microsecond scale on the default timer list * associated with the clock. * @@ -582,6 +599,12 @@ static inline QEMUTimer *timer_new_us(QEMUClockType type, QEMUTimerCB *cb, * @cb: the callback to call when the timer expires * @opaque: the opaque pointer to pass to the callback * + * The default timer list has one special feature: in icount mode, + * %QEMU_CLOCK_VIRTUAL timers are run in the vCPU thread. This is + * not true of other timer lists, which are typically associated + * with an AioContext---each of them runs its timer callbacks in its own + * AioContext thread. + * * Create a new timer with millisecond scale on the default timer list * associated with the clock. * @@ -777,7 +800,7 @@ static inline int64_t qemu_soonest_timeout(int64_t timeout1, int64_t timeout2) * * Initialise the clock & timer infrastructure */ -void init_clocks(void); +void init_clocks(QEMUTimerListNotifyCB *notify_cb); int64_t cpu_get_ticks(void); /* Caller must hold BQL */ diff --git a/include/sysemu/cpus.h b/include/sysemu/cpus.h index a73b5d4bce..a8053f1715 100644 --- a/include/sysemu/cpus.h +++ b/include/sysemu/cpus.h @@ -1,6 +1,8 @@ #ifndef QEMU_CPUS_H #define QEMU_CPUS_H +#include "qemu/timer.h" + /* cpus.c */ bool qemu_in_vcpu_thread(void); void qemu_init_cpu_loop(void); @@ -20,6 +22,7 @@ void dump_drift_info(FILE *f, fprintf_function cpu_fprintf); /* Unblock cpu */ void qemu_cpu_kick_self(void); +void qemu_timer_notify_cb(void *opaque, QEMUClockType type); void cpu_synchronize_all_states(void); void cpu_synchronize_all_post_reset(void); diff --git a/include/sysemu/os-posix.h b/include/sysemu/os-posix.h index b0a6c0695b..900bdcb45a 100644 --- a/include/sysemu/os-posix.h +++ b/include/sysemu/os-posix.h @@ -34,6 +34,10 @@ #include <netdb.h> #include <sys/un.h> +#ifdef CONFIG_SYSMACROS +#include <sys/sysmacros.h> +#endif + void os_set_line_buffering(void); void os_set_proc_name(const char *s); void os_setup_signal_handling(void); diff --git a/include/ui/console.h b/include/ui/console.h index ac2895ca93..d759338816 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -189,9 +189,6 @@ typedef struct DisplayChangeListenerOps { int x, int y, int w, int h); void (*dpy_gfx_switch)(DisplayChangeListener *dcl, struct DisplaySurface *new_surface); - void (*dpy_gfx_copy)(DisplayChangeListener *dcl, - int src_x, int src_y, - int dst_x, int dst_y, int w, int h); bool (*dpy_gfx_check_format)(DisplayChangeListener *dcl, pixman_format_code_t format); @@ -277,8 +274,6 @@ int dpy_set_ui_info(QemuConsole *con, QemuUIInfo *info); void dpy_gfx_update(QemuConsole *con, int x, int y, int w, int h); void dpy_gfx_replace_surface(QemuConsole *con, DisplaySurface *surface); -void dpy_gfx_copy(QemuConsole *con, int src_x, int src_y, - int dst_x, int dst_y, int w, int h); void dpy_text_cursor(QemuConsole *con, int x, int y); void dpy_text_update(QemuConsole *con, int x, int y, int w, int h); void dpy_text_resize(QemuConsole *con, int w, int h); @@ -411,8 +406,6 @@ void qemu_console_set_window_id(QemuConsole *con, int window_id); void console_select(unsigned int index); void qemu_console_resize(QemuConsole *con, int width, int height); -void qemu_console_copy(QemuConsole *con, int src_x, int src_y, - int dst_x, int dst_y, int w, int h); DisplaySurface *qemu_console_surface(QemuConsole *con); /* console-gl.c */ @@ -29,6 +29,7 @@ #include "hw/s390x/adapter.h" #include "exec/gdbstub.h" #include "sysemu/kvm_int.h" +#include "sysemu/cpus.h" #include "qemu/bswap.h" #include "exec/memory.h" #include "exec/ram_addr.h" @@ -2494,6 +2494,7 @@ static void mtree_print_mr(fprintf_function mon_printf, void *f, MemoryRegionListHead submr_print_queue; const MemoryRegion *submr; unsigned int i; + hwaddr cur_start, cur_end; if (!mr) { return; @@ -2503,6 +2504,18 @@ static void mtree_print_mr(fprintf_function mon_printf, void *f, mon_printf(f, MTREE_INDENT); } + cur_start = base + mr->addr; + cur_end = cur_start + MR_SIZE(mr->size); + + /* + * Try to detect overflow of memory region. This should never + * happen normally. When it happens, we dump something to warn the + * user who is observing this. + */ + if (cur_start < base || cur_end < cur_start) { + mon_printf(f, "[DETECTED OVERFLOW!] "); + } + if (mr->alias) { MemoryRegionList *ml; bool found = false; @@ -2522,8 +2535,7 @@ static void mtree_print_mr(fprintf_function mon_printf, void *f, mon_printf(f, TARGET_FMT_plx "-" TARGET_FMT_plx " (prio %d, %s): alias %s @%s " TARGET_FMT_plx "-" TARGET_FMT_plx "%s\n", - base + mr->addr, - base + mr->addr + MR_SIZE(mr->size), + cur_start, cur_end, mr->priority, memory_region_type((MemoryRegion *)mr), memory_region_name(mr), @@ -2534,8 +2546,7 @@ static void mtree_print_mr(fprintf_function mon_printf, void *f, } else { mon_printf(f, TARGET_FMT_plx "-" TARGET_FMT_plx " (prio %d, %s): %s%s\n", - base + mr->addr, - base + mr->addr + MR_SIZE(mr->size), + cur_start, cur_end, mr->priority, memory_region_type((MemoryRegion *)mr), memory_region_name(mr), @@ -2562,7 +2573,7 @@ static void mtree_print_mr(fprintf_function mon_printf, void *f, } QTAILQ_FOREACH(ml, &submr_print_queue, queue) { - mtree_print_mr(mon_printf, f, ml->mr, level + 1, base + mr->addr, + mtree_print_mr(mon_printf, f, ml->mr, level + 1, cur_start, alias_print_queue); } diff --git a/migration/block.c b/migration/block.c index 1941bc2402..7734ff728a 100644 --- a/migration/block.c +++ b/migration/block.c @@ -276,6 +276,8 @@ static int mig_save_device_bulk(QEMUFile *f, BlkMigDevState *bmds) if (bmds->shared_base) { qemu_mutex_lock_iothread(); aio_context_acquire(blk_get_aio_context(bb)); + /* Skip unallocated sectors; intentionally treats failure as + * an allocated sector */ while (cur_sector < total_sectors && !bdrv_is_allocated(blk_bs(bb), cur_sector, MAX_IS_ALLOCATED_SEARCH, &nr_sectors)) { @@ -574,6 +576,9 @@ static int mig_save_device_dirty(QEMUFile *f, BlkMigDevState *bmds, } bdrv_reset_dirty_bitmap(bmds->dirty_bitmap, sector, nr_sectors); + sector += nr_sectors; + bmds->cur_dirty = sector; + break; } sector += BDRV_SECTORS_PER_DIRTY_CHUNK; diff --git a/migration/migration.c b/migration/migration.c index 3dab6845b1..54060f749a 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -110,6 +110,8 @@ MigrationState *migrate_get_current(void) if (!once) { qemu_mutex_init(¤t_migration.src_page_req_mutex); + current_migration.parameters.tls_creds = g_strdup(""); + current_migration.parameters.tls_hostname = g_strdup(""); once = true; } return ¤t_migration; @@ -458,6 +460,7 @@ void migration_channel_process_incoming(MigrationState *s, ioc, object_get_typename(OBJECT(ioc))); if (s->parameters.tls_creds && + *s->parameters.tls_creds && !object_dynamic_cast(OBJECT(ioc), TYPE_QIO_CHANNEL_TLS)) { Error *local_err = NULL; @@ -480,6 +483,7 @@ void migration_channel_connect(MigrationState *s, ioc, object_get_typename(OBJECT(ioc)), hostname); if (s->parameters.tls_creds && + *s->parameters.tls_creds && !object_dynamic_cast(OBJECT(ioc), TYPE_QIO_CHANNEL_TLS)) { Error *local_err = NULL; diff --git a/migration/postcopy-ram.c b/migration/postcopy-ram.c index effbeb64fb..dc80dbb67f 100644 --- a/migration/postcopy-ram.c +++ b/migration/postcopy-ram.c @@ -95,6 +95,19 @@ static bool ufd_version_check(int ufd) return true; } +/* Callback from postcopy_ram_supported_by_host block iterator. + */ +static int test_range_shared(const char *block_name, void *host_addr, + ram_addr_t offset, ram_addr_t length, void *opaque) +{ + if (qemu_ram_is_shared(qemu_ram_block_by_name(block_name))) { + error_report("Postcopy on shared RAM (%s) is not yet supported", + block_name); + return 1; + } + return 0; +} + /* * Note: This has the side effect of munlock'ing all of RAM, that's * normally fine since if the postcopy succeeds it gets turned back on at the @@ -127,6 +140,11 @@ bool postcopy_ram_supported_by_host(void) goto out; } + /* We don't support postcopy with shared RAM yet */ + if (qemu_ram_foreach_block(test_range_shared, NULL)) { + goto out; + } + /* * userfault and mlock don't go together; we'll put it back later if * it was enabled. diff --git a/migration/ram.c b/migration/ram.c index 719425b9b8..de1e0a3b18 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -576,18 +576,18 @@ static inline bool migration_bitmap_clear_dirty(ram_addr_t addr) return ret; } +static int64_t num_dirty_pages_period; static void migration_bitmap_sync_range(ram_addr_t start, ram_addr_t length) { unsigned long *bitmap; bitmap = atomic_rcu_read(&migration_bitmap_rcu)->bmap; - migration_dirty_pages += - cpu_physical_memory_sync_dirty_bitmap(bitmap, start, length); + migration_dirty_pages += cpu_physical_memory_sync_dirty_bitmap(bitmap, + start, length, &num_dirty_pages_period); } /* Fix me: there are too many global variables used in migration process. */ static int64_t start_time; static int64_t bytes_xfer_prev; -static int64_t num_dirty_pages_period; static uint64_t xbzrle_cache_miss_prev; static uint64_t iterations_prev; @@ -620,7 +620,6 @@ uint64_t ram_pagesize_summary(void) static void migration_bitmap_sync(void) { RAMBlock *block; - uint64_t num_dirty_pages_init = migration_dirty_pages; MigrationState *s = migrate_get_current(); int64_t end_time; int64_t bytes_xfer_now; @@ -646,9 +645,8 @@ static void migration_bitmap_sync(void) rcu_read_unlock(); qemu_mutex_unlock(&migration_bitmap_mutex); - trace_migration_bitmap_sync_end(migration_dirty_pages - - num_dirty_pages_init); - num_dirty_pages_period += migration_dirty_pages - num_dirty_pages_init; + trace_migration_bitmap_sync_end(num_dirty_pages_period); + end_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME); /* more than 1 second = 1000 millisecons */ diff --git a/migration/tls.c b/migration/tls.c index 203c11d025..45bec44ca4 100644 --- a/migration/tls.c +++ b/migration/tls.c @@ -141,7 +141,7 @@ void migration_tls_channel_connect(MigrationState *s, return; } - if (s->parameters.tls_hostname) { + if (s->parameters.tls_hostname && *s->parameters.tls_hostname) { hostname = s->parameters.tls_hostname; } if (!hostname) { diff --git a/migration/vmstate.c b/migration/vmstate.c index 78b3cd48e7..7b4a607c51 100644 --- a/migration/vmstate.c +++ b/migration/vmstate.c @@ -109,7 +109,7 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd, vmstate_handle_alloc(first_elem, field, opaque); if (field->flags & VMS_POINTER) { first_elem = *(void **)first_elem; - assert(first_elem || !n_elems); + assert(first_elem || !n_elems || !size); } for (i = 0; i < n_elems; i++) { void *curr_elem = first_elem + size * i; @@ -117,7 +117,7 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd, if (field->flags & VMS_ARRAY_OF_POINTER) { curr_elem = *(void **)curr_elem; } - if (!curr_elem) { + if (!curr_elem && size) { /* if null pointer check placeholder and do not follow */ assert(field->flags & VMS_ARRAY_OF_POINTER); ret = vmstate_info_nullptr.get(f, curr_elem, size, NULL); @@ -325,7 +325,7 @@ void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd, trace_vmstate_save_state_loop(vmsd->name, field->name, n_elems); if (field->flags & VMS_POINTER) { first_elem = *(void **)first_elem; - assert(first_elem || !n_elems); + assert(first_elem || !n_elems || !size); } for (i = 0; i < n_elems; i++) { void *curr_elem = first_elem + size * i; @@ -336,7 +336,7 @@ void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd, assert(curr_elem); curr_elem = *(void **)curr_elem; } - if (!curr_elem) { + if (!curr_elem && size) { /* if null pointer write placeholder and do not follow */ assert(field->flags & VMS_ARRAY_OF_POINTER); vmstate_info_nullptr.put(f, curr_elem, size, NULL, NULL); @@ -77,6 +77,7 @@ #include "qapi-event.h" #include "qmp-introspect.h" #include "sysemu/qtest.h" +#include "sysemu/cpus.h" #include "qemu/cutils.h" #include "qapi/qmp/dispatch.h" diff --git a/nbd/client.c b/nbd/client.c index 5c9dee37fa..3dc2564cd0 100644 --- a/nbd/client.c +++ b/nbd/client.c @@ -94,7 +94,7 @@ static ssize_t drop_sync(QIOChannel *ioc, size_t size) char small[1024]; char *buffer; - buffer = sizeof(small) < size ? small : g_malloc(MIN(65536, size)); + buffer = sizeof(small) >= size ? small : g_malloc(MIN(65536, size)); while (size > 0) { ssize_t count = read_sync(ioc, buffer, MIN(65536, size)); diff --git a/net/colo-compare.c b/net/colo-compare.c index 282727b28a..54e6d40525 100644 --- a/net/colo-compare.c +++ b/net/colo-compare.c @@ -182,10 +182,18 @@ static int packet_enqueue(CompareState *s, int mode) */ static int colo_packet_compare_common(Packet *ppkt, Packet *spkt, int offset) { - trace_colo_compare_ip_info(ppkt->size, inet_ntoa(ppkt->ip->ip_src), - inet_ntoa(ppkt->ip->ip_dst), spkt->size, - inet_ntoa(spkt->ip->ip_src), - inet_ntoa(spkt->ip->ip_dst)); + if (trace_event_get_state(TRACE_COLO_COMPARE_MISCOMPARE)) { + char pri_ip_src[20], pri_ip_dst[20], sec_ip_src[20], sec_ip_dst[20]; + + strcpy(pri_ip_src, inet_ntoa(ppkt->ip->ip_src)); + strcpy(pri_ip_dst, inet_ntoa(ppkt->ip->ip_dst)); + strcpy(sec_ip_src, inet_ntoa(spkt->ip->ip_src)); + strcpy(sec_ip_dst, inet_ntoa(spkt->ip->ip_dst)); + + trace_colo_compare_ip_info(ppkt->size, pri_ip_src, + pri_ip_dst, spkt->size, + sec_ip_src, sec_ip_dst); + } if (ppkt->size == spkt->size) { return memcmp(ppkt->data + offset, spkt->data + offset, @@ -336,10 +344,19 @@ static int colo_packet_compare_icmp(Packet *spkt, Packet *ppkt) static int colo_packet_compare_other(Packet *spkt, Packet *ppkt) { trace_colo_compare_main("compare other"); - trace_colo_compare_ip_info(ppkt->size, inet_ntoa(ppkt->ip->ip_src), - inet_ntoa(ppkt->ip->ip_dst), spkt->size, - inet_ntoa(spkt->ip->ip_src), - inet_ntoa(spkt->ip->ip_dst)); + if (trace_event_get_state(TRACE_COLO_COMPARE_MISCOMPARE)) { + char pri_ip_src[20], pri_ip_dst[20], sec_ip_src[20], sec_ip_dst[20]; + + strcpy(pri_ip_src, inet_ntoa(ppkt->ip->ip_src)); + strcpy(pri_ip_dst, inet_ntoa(ppkt->ip->ip_dst)); + strcpy(sec_ip_src, inet_ntoa(spkt->ip->ip_src)); + strcpy(sec_ip_dst, inet_ntoa(spkt->ip->ip_dst)); + + trace_colo_compare_ip_info(ppkt->size, pri_ip_src, + pri_ip_dst, spkt->size, + sec_ip_src, sec_ip_dst); + } + return colo_packet_compare_common(ppkt, spkt, 0); } diff --git a/pc-bios/openbios-ppc b/pc-bios/openbios-ppc Binary files differindex 4869c9dcf3..cfe0aee7e5 100644 --- a/pc-bios/openbios-ppc +++ b/pc-bios/openbios-ppc diff --git a/pc-bios/openbios-sparc32 b/pc-bios/openbios-sparc32 Binary files differindex aada55e094..d6244b9ebd 100644 --- a/pc-bios/openbios-sparc32 +++ b/pc-bios/openbios-sparc32 diff --git a/pc-bios/openbios-sparc64 b/pc-bios/openbios-sparc64 Binary files differindex cf466f6a4c..74f67f2724 100644 --- a/pc-bios/openbios-sparc64 +++ b/pc-bios/openbios-sparc64 diff --git a/qapi-schema.json b/qapi-schema.json index 32b4a4b782..68a43274bf 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -49,6 +49,29 @@ # ## +{ 'pragma': { 'doc-required': true } } + +# Whitelists to permit QAPI rule violations; think twice before you +# add to them! +{ 'pragma': { + # Commands allowed to return a non-dictionary: + 'returns-whitelist': [ + 'human-monitor-command', + 'qom-get', + 'query-migrate-cache-size', + 'query-tpm-models', + 'query-tpm-types', + 'ringbuf-read' ], + 'name-case-whitelist': [ + 'ACPISlotType', # DIMM, visible through query-acpi-ospm-status + 'CpuInfoMIPS', # PC, visible through query-cpu + 'CpuInfoTricore', # PC, visible through query-cpu + 'QapiErrorClass', # all members, visible through errors + 'UuidInfo', # UUID, visible through query-uuid + 'X86CPURegister32', # all members, visible indirectly through qom-get + 'q_obj_CpuInfo-base' # CPU, visible through query-cpu + ] } } + # QAPI common definitions { 'include': 'qapi/common.json' } @@ -127,10 +150,10 @@ # # @fdname: file descriptor name previously passed via 'getfd' command # -# @skipauth: #optional whether to skip authentication. Only applies +# @skipauth: whether to skip authentication. Only applies # to "vnc" and "spice" protocols # -# @tls: #optional whether to perform TLS. Only applies to the "spice" +# @tls: whether to perform TLS. Only applies to the "spice" # protocol # # Returns: nothing on success. @@ -153,7 +176,7 @@ # # Guest name information. # -# @name: #optional The name of the guest +# @name: The name of the guest # # Since: 0.14.0 ## @@ -447,7 +470,7 @@ # # @data: data to write # -# @format: #optional data encoding (default 'utf8'). +# @format: data encoding (default 'utf8'). # - base64: data must be base64 encoded text. Its binary # decoding gets written. # - utf8: data's UTF-8 encoding is written @@ -480,7 +503,7 @@ # # @size: how many bytes to read at most # -# @format: #optional data encoding (default 'utf8'). +# @format: data encoding (default 'utf8'). # - base64: the data read is returned in base64 encoding. # - utf8: the data read is interpreted as UTF-8. # Bug: can screw up when the buffer contains invalid UTF-8 @@ -644,45 +667,45 @@ # # Information about current migration process. # -# @status: #optional @MigrationStatus describing the current migration status. +# @status: @MigrationStatus describing the current migration status. # If this field is not returned, no migration process # has been initiated # -# @ram: #optional @MigrationStats containing detailed migration +# @ram: @MigrationStats containing detailed migration # status, only returned if status is 'active' or # 'completed'(since 1.2) # -# @disk: #optional @MigrationStats containing detailed disk migration +# @disk: @MigrationStats containing detailed disk migration # status, only returned if status is 'active' and it is a block # migration # -# @xbzrle-cache: #optional @XBZRLECacheStats containing detailed XBZRLE +# @xbzrle-cache: @XBZRLECacheStats containing detailed XBZRLE # migration statistics, only returned if XBZRLE feature is on and # status is 'active' or 'completed' (since 1.2) # -# @total-time: #optional total amount of milliseconds since migration started. +# @total-time: total amount of milliseconds since migration started. # If migration has ended, it returns the total migration # time. (since 1.2) # -# @downtime: #optional only present when migration finishes correctly +# @downtime: only present when migration finishes correctly # total downtime in milliseconds for the guest. # (since 1.3) # -# @expected-downtime: #optional only present while migration is active +# @expected-downtime: only present while migration is active # expected downtime in milliseconds for the guest in last walk # of the dirty bitmap. (since 1.3) # -# @setup-time: #optional amount of setup time in milliseconds _before_ the +# @setup-time: amount of setup time in milliseconds _before_ the # iterations begin but _after_ the QMP command is issued. This is designed # to provide an accounting of any activities (such as RDMA pinning) which # may be expensive, but do not actually occur during the iterative # migration rounds themselves. (since 1.6) # -# @cpu-throttle-percentage: #optional percentage of time guest cpus are being +# @cpu-throttle-percentage: percentage of time guest cpus are being # throttled during auto-converge. This is only present when auto-converge # has started throttling guest cpus. (Since 2.7) # -# @error-desc: #optional the human readable error description string, when +# @error-desc: the human readable error description string, when # @status is 'failed'. Clients should not attempt to parse the # error strings. (Since 2.7) # @@ -994,7 +1017,7 @@ ## # @migrate-set-parameters: # -# Set various migration parameters. See MigrationParameters for details. +# Set various migration parameters. # # Since: 2.4 # @@ -1015,34 +1038,38 @@ # ('query-migrate-parameters'), with the exception of tls-creds and # tls-hostname. # -# @compress-level: #optional compression level +# @compress-level: compression level # -# @compress-threads: #optional compression thread count +# @compress-threads: compression thread count # -# @decompress-threads: #optional decompression thread count +# @decompress-threads: decompression thread count # -# @cpu-throttle-initial: #optional Initial percentage of time guest cpus are +# @cpu-throttle-initial: Initial percentage of time guest cpus are # throttledwhen migration auto-converge is activated. # The default value is 20. (Since 2.7) # -# @cpu-throttle-increment: #optional throttle percentage increase each time +# @cpu-throttle-increment: throttle percentage increase each time # auto-converge detects that migration is not making # progress. The default value is 10. (Since 2.7) # -# @tls-creds: #optional ID of the 'tls-creds' object that provides credentials +# @tls-creds: ID of the 'tls-creds' object that provides credentials # for establishing a TLS connection over the migration data # channel. On the outgoing side of the migration, the credentials # must be for a 'client' endpoint, while for the incoming side the # credentials must be for a 'server' endpoint. Setting this # will enable TLS for all migrations. The default is unset, # resulting in unsecured migration at the QEMU level. (Since 2.7) +# An empty string means that QEMU will use plain text mode for +# migration, rather than TLS (Since 2.9) # -# @tls-hostname: #optional hostname of the target host for the migration. This +# @tls-hostname: hostname of the target host for the migration. This # is required when using x509 based TLS credentials and the # migration URI does not already include a hostname. For # example if using fd: or exec: based migration, the # hostname must be provided so that the server's x509 # certificate identity can be validated. (Since 2.7) +# An empty string means that QEMU will use the hostname +# associated with the migration URI, if any. (Since 2.9) # # @max-bandwidth: to set maximum speed for migration. maximum speed in # bytes per second. (Since 2.8) @@ -1102,9 +1129,9 @@ # # @protocol: must be "spice" # @hostname: migration target hostname -# @port: #optional spice tcp port for plaintext channels -# @tls-port: #optional spice tcp port for tls-secured channels -# @cert-subject: #optional server certificate subject +# @port: spice tcp port for plaintext channels +# @tls-port: spice tcp port for tls-secured channels +# @cert-subject: server certificate subject # # Since: 0.14.0 # @@ -1524,7 +1551,7 @@ # # The network connection information for server # -# @auth: #optional authentication method used for +# @auth: authentication method used for # the plain (non-websocket) VNC server # # Since: 2.1 @@ -1538,10 +1565,10 @@ # # Information about a connected VNC client. # -# @x509_dname: #optional If x509 authentication is in use, the Distinguished +# @x509_dname: If x509 authentication is in use, the Distinguished # Name of the client. # -# @sasl_username: #optional If SASL authentication is in use, the SASL username +# @sasl_username: If SASL authentication is in use, the SASL username # used for authentication. # # Since: 0.14.0 @@ -1557,19 +1584,19 @@ # # @enabled: true if the VNC server is enabled, false otherwise # -# @host: #optional The hostname the VNC server is bound to. This depends on +# @host: The hostname the VNC server is bound to. This depends on # the name resolution on the host and may be an IP address. # -# @family: #optional 'ipv6' if the host is listening for IPv6 connections +# @family: 'ipv6' if the host is listening for IPv6 connections # 'ipv4' if the host is listening for IPv4 connections # 'unix' if the host is listening on a unix domain socket # 'unknown' otherwise # -# @service: #optional The service name of the server's port. This may depends +# @service: The service name of the server's port. This may depends # on the host system's service database so symbolic names should not # be relied on. # -# @auth: #optional the current authentication type used by the server +# @auth: the current authentication type used by the server # 'none' if no authentication is being used # 'vnc' if VNC authentication is being used # 'vencrypt+plain' if VEncrypt is used with plain text authentication @@ -1624,7 +1651,7 @@ # # @auth: The current authentication type used by the servers # -# @vencrypt: #optional The vencrypt sub authentication type used by the +# @vencrypt: The vencrypt sub authentication type used by the # servers, only specified in case auth == vencrypt. # # Since: 2.9 @@ -1652,10 +1679,10 @@ # # @auth: The current authentication type used by the non-websockets servers # -# @vencrypt: #optional The vencrypt authentication type used by the servers, +# @vencrypt: The vencrypt authentication type used by the servers, # only specified in case auth == vencrypt. # -# @display: #optional The display device the vnc server is linked to. +# @display: The display device the vnc server is linked to. # # Since: 2.3 ## @@ -1732,7 +1759,7 @@ # # Information about a SPICE server # -# @auth: #optional authentication method +# @auth: authentication method # # Since: 2.1 ## @@ -1794,16 +1821,16 @@ # @migrated: true if the last guest migration completed and spice # migration had completed as well. false otherwise. (since 1.4) # -# @host: #optional The hostname the SPICE server is bound to. This depends on +# @host: The hostname the SPICE server is bound to. This depends on # the name resolution on the host and may be an IP address. # -# @port: #optional The SPICE server's port number. +# @port: The SPICE server's port number. # -# @compiled-version: #optional SPICE server version. +# @compiled-version: SPICE server version. # -# @tls-port: #optional The SPICE server's TLS port number. +# @tls-port: The SPICE server's TLS port number. # -# @auth: #optional the current authentication type used by the server +# @auth: the current authentication type used by the server # 'none' if no authentication is being used # 'spice' uses SASL or direct TLS authentication, depending on command # line options @@ -1928,9 +1955,9 @@ # # @size: memory size # -# @prefetch: #optional if @type is 'memory', true if the memory is prefetchable +# @prefetch: if @type is 'memory', true if the memory is prefetchable # -# @mem_type_64: #optional if @type is 'memory', true if the BAR is 64-bit +# @mem_type_64: if @type is 'memory', true if the BAR is 64-bit # # Since: 0.14.0 ## @@ -1986,7 +2013,7 @@ # # Information about the Class of a PCI device # -# @desc: #optional a string description of the device's class +# @desc: a string description of the device's class # # @class: the class code of the device # @@ -2024,7 +2051,7 @@ # # @id: the PCI device id # -# @irq: #optional if an IRQ is assigned to the device, the IRQ number +# @irq: if an IRQ is assigned to the device, the IRQ number # # @qdev_id: the device name of the PCI device # @@ -2314,7 +2341,7 @@ # # @filename: the file to save the memory to as binary data # -# @cpu-index: #optional the index of the virtual CPU to use for translating the +# @cpu-index: the index of the virtual CPU to use for translating the # virtual address (defaults to CPU 0) # # Returns: Nothing on success @@ -2543,7 +2570,7 @@ # # Optional arguments to modify the behavior of a Transaction. # -# @completion-mode: #optional Controls how jobs launched asynchronously by +# @completion-mode: Controls how jobs launched asynchronously by # Actions will complete or fail as a group. # See @ActionCompletionMode for details. # @@ -2587,7 +2614,7 @@ # @actions: List of @TransactionAction; # information needed for the respective operations. # -# @properties: #optional structure of additional options to control the +# @properties: structure of additional options to control the # execution of the transaction. See @TransactionProperties # for additional detail. # @@ -2636,7 +2663,7 @@ # # @command-line: the command to execute in the human monitor # -# @cpu-index: #optional The CPU to use for commands that require an implicit CPU +# @cpu-index: The CPU to use for commands that require an implicit CPU # # Returns: the output of the command as a string # @@ -2872,7 +2899,7 @@ # # @password: the new password # -# @connected: #optional how to handle existing clients when changing the +# @connected: how to handle existing clients when changing the # password. If nothing is specified, defaults to `keep' # `fail' to fail the command if clients are connected # `disconnect' to disconnect existing clients @@ -3031,7 +3058,7 @@ # # @name: the name of the property # @type: the typename of the property -# @description: #optional if specified, the description of the property. +# @description: if specified, the description of the property. # (since 2.2) # # Since: 1.2 @@ -3061,9 +3088,9 @@ # # @uri: the Uniform Resource Identifier of the destination VM # -# @blk: #optional do block migration (full disk copy) +# @blk: do block migration (full disk copy) # -# @inc: #optional incremental disk copy migration +# @inc: incremental disk copy migration # # @detach: this argument exists only for compatibility reasons and # is ignored by QEMU @@ -3172,9 +3199,9 @@ # # @driver: the name of the new device's driver # -# @bus: #optional the device's parent bus (device tree path) +# @bus: the device's parent bus (device tree path) # -# @id: #optional the device's ID, must be unique +# @id: the device's ID, must be unique # # Additional arguments depend on the type. # @@ -3287,17 +3314,17 @@ # 2. fd: the protocol starts with "fd:", and the following string # is the fd's name. # -# @detach: #optional if true, QMP will return immediately rather than +# @detach: if true, QMP will return immediately rather than # waiting for the dump to finish. The user can track progress # using "query-dump". (since 2.6). # -# @begin: #optional if specified, the starting physical address. +# @begin: if specified, the starting physical address. # -# @length: #optional if specified, the memory size, in bytes. If you don't +# @length: if specified, the memory size, in bytes. If you don't # want to dump all guest's memory, please specify the start @begin # and @length # -# @format: #optional if specified, the format of guest memory dump. But non-elf +# @format: if specified, the format of guest memory dump. But non-elf # format is conflict with paging and filter, ie. @paging, @begin and # @length is not allowed to be specified with non-elf @format at the # same time (since 2.0) @@ -3489,7 +3516,7 @@ # # @id: the name of the new object # -# @props: #optional a dictionary of properties to be passed to the backend +# @props: a dictionary of properties to be passed to the backend # # Returns: Nothing on success # Error if @qom-type is not a valid class name @@ -3542,15 +3569,15 @@ # # Create a new Network Interface Card. # -# @netdev: #optional id of -netdev to connect to +# @netdev: id of -netdev to connect to # -# @macaddr: #optional MAC address +# @macaddr: MAC address # -# @model: #optional device model (e1000, rtl8139, virtio etc.) +# @model: device model (e1000, rtl8139, virtio etc.) # -# @addr: #optional PCI device address +# @addr: PCI device address # -# @vectors: #optional number of MSI-x vectors, 0 to disable MSI-X +# @vectors: number of MSI-x vectors, 0 to disable MSI-X # # Since: 1.2 ## @@ -3579,57 +3606,57 @@ # Use the user mode network stack which requires no administrator privilege to # run. # -# @hostname: #optional client hostname reported by the builtin DHCP server +# @hostname: client hostname reported by the builtin DHCP server # -# @restrict: #optional isolate the guest from the host +# @restrict: isolate the guest from the host # -# @ipv4: #optional whether to support IPv4, default true for enabled +# @ipv4: whether to support IPv4, default true for enabled # (since 2.6) # -# @ipv6: #optional whether to support IPv6, default true for enabled +# @ipv6: whether to support IPv6, default true for enabled # (since 2.6) # -# @ip: #optional legacy parameter, use net= instead +# @ip: legacy parameter, use net= instead # -# @net: #optional IP network address that the guest will see, in the +# @net: IP network address that the guest will see, in the # form addr[/netmask] The netmask is optional, and can be # either in the form a.b.c.d or as a number of valid top-most # bits. Default is 10.0.2.0/24. # -# @host: #optional guest-visible address of the host +# @host: guest-visible address of the host # -# @tftp: #optional root directory of the built-in TFTP server +# @tftp: root directory of the built-in TFTP server # -# @bootfile: #optional BOOTP filename, for use with tftp= +# @bootfile: BOOTP filename, for use with tftp= # -# @dhcpstart: #optional the first of the 16 IPs the built-in DHCP server can +# @dhcpstart: the first of the 16 IPs the built-in DHCP server can # assign # -# @dns: #optional guest-visible address of the virtual nameserver +# @dns: guest-visible address of the virtual nameserver # -# @dnssearch: #optional list of DNS suffixes to search, passed as DHCP option +# @dnssearch: list of DNS suffixes to search, passed as DHCP option # to the guest # -# @ipv6-prefix: #optional IPv6 network prefix (default is fec0::) (since +# @ipv6-prefix: IPv6 network prefix (default is fec0::) (since # 2.6). The network prefix is given in the usual # hexadecimal IPv6 address notation. # -# @ipv6-prefixlen: #optional IPv6 network prefix length (default is 64) +# @ipv6-prefixlen: IPv6 network prefix length (default is 64) # (since 2.6) # -# @ipv6-host: #optional guest-visible IPv6 address of the host (since 2.6) +# @ipv6-host: guest-visible IPv6 address of the host (since 2.6) # -# @ipv6-dns: #optional guest-visible IPv6 address of the virtual +# @ipv6-dns: guest-visible IPv6 address of the virtual # nameserver (since 2.6) # -# @smb: #optional root directory of the built-in SMB server +# @smb: root directory of the built-in SMB server # -# @smbserver: #optional IP address of the built-in SMB server +# @smbserver: IP address of the built-in SMB server # -# @hostfwd: #optional redirect incoming TCP or UDP host connections to guest +# @hostfwd: redirect incoming TCP or UDP host connections to guest # endpoints # -# @guestfwd: #optional forward guest TCP connections +# @guestfwd: forward guest TCP connections # # Since: 1.2 ## @@ -3661,37 +3688,37 @@ # # Connect the host TAP network interface name to the VLAN. # -# @ifname: #optional interface name +# @ifname: interface name # -# @fd: #optional file descriptor of an already opened tap +# @fd: file descriptor of an already opened tap # -# @fds: #optional multiple file descriptors of already opened multiqueue capable +# @fds: multiple file descriptors of already opened multiqueue capable # tap # -# @script: #optional script to initialize the interface +# @script: script to initialize the interface # -# @downscript: #optional script to shut down the interface +# @downscript: script to shut down the interface # -# @br: #optional bridge name (since 2.8) +# @br: bridge name (since 2.8) # -# @helper: #optional command to execute to configure bridge +# @helper: command to execute to configure bridge # -# @sndbuf: #optional send buffer limit. Understands [TGMKkb] suffixes. +# @sndbuf: send buffer limit. Understands [TGMKkb] suffixes. # -# @vnet_hdr: #optional enable the IFF_VNET_HDR flag on the tap interface +# @vnet_hdr: enable the IFF_VNET_HDR flag on the tap interface # -# @vhost: #optional enable vhost-net network accelerator +# @vhost: enable vhost-net network accelerator # -# @vhostfd: #optional file descriptor of an already opened vhost net device +# @vhostfd: file descriptor of an already opened vhost net device # -# @vhostfds: #optional file descriptors of multiple already opened vhost net +# @vhostfds: file descriptors of multiple already opened vhost net # devices # -# @vhostforce: #optional vhost on for non-MSIX virtio guests +# @vhostforce: vhost on for non-MSIX virtio guests # -# @queues: #optional number of queues to be created for multiqueue capable tap +# @queues: number of queues to be created for multiqueue capable tap # -# @poll-us: #optional maximum number of microseconds that could +# @poll-us: maximum number of microseconds that could # be spent on busy polling for tap (since 2.7) # # Since: 1.2 @@ -3720,17 +3747,17 @@ # Connect the VLAN to a remote VLAN in another QEMU virtual machine using a TCP # socket connection. # -# @fd: #optional file descriptor of an already opened socket +# @fd: file descriptor of an already opened socket # -# @listen: #optional port number, and optional hostname, to listen on +# @listen: port number, and optional hostname, to listen on # -# @connect: #optional port number, and optional hostname, to connect to +# @connect: port number, and optional hostname, to connect to # -# @mcast: #optional UDP multicast address and port number +# @mcast: UDP multicast address and port number # -# @localaddr: #optional source address and port for multicast and udp packets +# @localaddr: source address and port for multicast and udp packets # -# @udp: #optional UDP unicast address and port number +# @udp: UDP unicast address and port number # # Since: 1.2 ## @@ -3752,32 +3779,32 @@ # # @dst: destination address # -# @srcport: #optional source port - mandatory for udp, optional for ip +# @srcport: source port - mandatory for udp, optional for ip # -# @dstport: #optional destination port - mandatory for udp, optional for ip +# @dstport: destination port - mandatory for udp, optional for ip # -# @ipv6: #optional - force the use of ipv6 +# @ipv6: force the use of ipv6 # -# @udp: #optional - use the udp version of l2tpv3 encapsulation +# @udp: use the udp version of l2tpv3 encapsulation # -# @cookie64: #optional - use 64 bit coookies +# @cookie64: use 64 bit coookies # -# @counter: #optional have sequence counter +# @counter: have sequence counter # -# @pincounter: #optional pin sequence counter to zero - +# @pincounter: pin sequence counter to zero - # workaround for buggy implementations or # networks with packet reorder # -# @txcookie: #optional 32 or 64 bit transmit cookie +# @txcookie: 32 or 64 bit transmit cookie # -# @rxcookie: #optional 32 or 64 bit receive cookie +# @rxcookie: 32 or 64 bit receive cookie # # @txsession: 32 bit transmit session # -# @rxsession: #optional 32 bit receive session - if not specified +# @rxsession: 32 bit receive session - if not specified # set to the same value as transmit # -# @offset: #optional additional offset - allows the insertion of +# @offset: additional offset - allows the insertion of # additional application-specific data before the packet payload # # Since: 2.1 @@ -3804,13 +3831,13 @@ # # Connect the VLAN to a vde switch running on the host. # -# @sock: #optional socket path +# @sock: socket path # -# @port: #optional port number +# @port: port number # -# @group: #optional group owner of socket +# @group: group owner of socket # -# @mode: #optional permissions for socket +# @mode: permissions for socket # # Since: 1.2 ## @@ -3826,10 +3853,10 @@ # # Dump VLAN network traffic to a file. # -# @len: #optional per-packet size limit (64k default). Understands [TGMKkb] +# @len: per-packet size limit (64k default). Understands [TGMKkb] # suffixes. # -# @file: #optional dump file path (default is qemu-vlan0.pcap) +# @file: dump file path (default is qemu-vlan0.pcap) # # Since: 1.2 ## @@ -3843,9 +3870,9 @@ # # Connect a host TAP network interface to a host bridge device. # -# @br: #optional bridge name +# @br: bridge name # -# @helper: #optional command to execute to configure bridge +# @helper: command to execute to configure bridge # # Since: 1.2 ## @@ -3879,7 +3906,7 @@ # YYY identifies a port of the switch. VALE ports having the # same XXX are therefore connected to the same switch. # -# @devname: #optional path of the netmap device (default: '/dev/netmap'). +# @devname: path of the netmap device (default: '/dev/netmap'). # # Since: 2.0 ## @@ -3895,9 +3922,9 @@ # # @chardev: name of a unix socket chardev # -# @vhostforce: #optional vhost on for non-MSIX virtio guests (default: false). +# @vhostforce: vhost on for non-MSIX virtio guests (default: false). # -# @queues: #optional number of queues to be created for multiqueue vhost-user +# @queues: number of queues to be created for multiqueue vhost-user # (default: 1) (Since 2.5) # # Since: 2.1 @@ -3954,11 +3981,11 @@ # # Captures the configuration of a network device; legacy. # -# @vlan: #optional vlan number +# @vlan: vlan number # -# @id: #optional identifier for monitor commands +# @id: identifier for monitor commands # -# @name: #optional identifier for monitor commands, ignored if @id is present +# @name: identifier for monitor commands, ignored if @id is present # # @opts: device type specific properties (legacy) # @@ -4032,17 +4059,15 @@ # # @port: port part of the address, or lowest port if @to is present # -# @numeric: #optional true if the host/port are guaranteed to be numeric, +# @numeric: true if the host/port are guaranteed to be numeric, # false if name resolution should be attempted. Defaults to false. # (Since 2.9) # # @to: highest port to try # # @ipv4: whether to accept IPv4 addresses, default try both IPv4 and IPv6 -# #optional # # @ipv6: whether to accept IPv6 addresses, default try both IPv4 and IPv6 -# #optional # # Since: 1.3 ## @@ -4190,9 +4215,9 @@ # # @name: the name of the machine # -# @alias: #optional an alias for the machine name +# @alias: an alias for the machine name # -# @is-default: #optional whether the machine is default +# @is-default: whether the machine is default # # @cpu-max: maximum number of CPUs supported by the machine type # (since 1.5.0) @@ -4224,7 +4249,7 @@ # # @name: the name of the CPU definition # -# @migration-safe: #optional whether a CPU definition can be safely used for +# @migration-safe: whether a CPU definition can be safely used for # migration in combination with a QEMU compatibility machine # when migrating between different QMU versions and between # hosts with different sets of (hardware or software) @@ -4236,7 +4261,7 @@ # QEMU version, machine type, machine options and accelerator options. # A static model is always migration-safe. (since 2.8) # -# @unavailable-features: #optional List of properties that prevent +# @unavailable-features: List of properties that prevent # the CPU model from running in the current # host. (since 2.8) # @typename: Type name that can be used as argument to @device-list-properties, @@ -4287,7 +4312,7 @@ # However, if required, architectures can expose relevant properties. # # @name: the name of the CPU definition the model is based on -# @props: #optional a dictionary of QOM properties to be applied +# @props: a dictionary of QOM properties to be applied # # Since: 2.8.0 ## @@ -4536,9 +4561,9 @@ # # Add a file descriptor, that was passed via SCM rights, to an fd set. # -# @fdset-id: #optional The ID of the fd set to add the file descriptor to. +# @fdset-id: The ID of the fd set to add the file descriptor to. # -# @opaque: #optional A free-form string that can be used to describe the fd. +# @opaque: A free-form string that can be used to describe the fd. # # Returns: @AddfdInfo on success # @@ -4568,7 +4593,7 @@ # # @fdset-id: The ID of the fd set that the file descriptor belongs to. # -# @fd: #optional The file descriptor that is to be removed. +# @fd: The file descriptor that is to be removed. # # Returns: Nothing on success # If @fdset-id or @fd is not found, FdNotFound @@ -4595,7 +4620,7 @@ # # @fd: The file descriptor value. # -# @opaque: #optional A free-form string that can be used to describe the fd. +# @opaque: A free-form string that can be used to describe the fd. # # Since: 1.2.0 ## @@ -4746,7 +4771,7 @@ # directly to the guest, while @KeyValue.qcode must be a valid # @QKeyCode value # -# @hold-time: #optional time to delay key up events, milliseconds. Defaults +# @hold-time: time to delay key up events, milliseconds. Defaults # to 100 # # Returns: Nothing on success @@ -4792,8 +4817,8 @@ # # Configuration shared across all chardev backends # -# @logfile: #optional The name of a logfile to save output -# @logappend: #optional true to append instead of truncate +# @logfile: The name of a logfile to save output +# @logappend: true to append instead of truncate # (default to false to truncate) # # Since: 2.6 @@ -4806,9 +4831,9 @@ # # Configuration info for file chardevs. # -# @in: #optional The name of the input file +# @in: The name of the input file # @out: The name of the output file -# @append: #optional Open the file in append mode (default false to +# @append: Open the file in append mode (default false to # truncate) (Since 2.6) # # Since: 1.4 @@ -4838,14 +4863,14 @@ # # @addr: socket address to listen on (server=true) # or connect to (server=false) -# @tls-creds: #optional the ID of the TLS credentials object (since 2.6) -# @server: #optional create server socket (default: true) -# @wait: #optional wait for incoming connection on server +# @tls-creds: the ID of the TLS credentials object (since 2.6) +# @server: create server socket (default: true) +# @wait: wait for incoming connection on server # sockets (default: false). -# @nodelay: #optional set TCP_NODELAY socket option (default: false) -# @telnet: #optional enable telnet protocol on server +# @nodelay: set TCP_NODELAY socket option (default: false) +# @telnet: enable telnet protocol on server # sockets (default: false) -# @reconnect: #optional For a client socket, if a socket is disconnected, +# @reconnect: For a client socket, if a socket is disconnected, # then attempt a reconnect after the given number of seconds. # Setting this to zero disables this function. (default: 0) # (Since: 2.2) @@ -4867,7 +4892,7 @@ # Configuration info for datagram socket chardevs. # # @remote: remote address -# @local: #optional local address +# @local: local address # # Since: 1.5 ## @@ -4892,7 +4917,7 @@ # # Configuration info for stdio chardevs. # -# @signal: #optional Allow signals (such as SIGINT triggered by ^C) +# @signal: Allow signals (such as SIGINT triggered by ^C) # be delivered to qemu. Default: true in -nographic mode, # false otherwise. # @@ -4949,7 +4974,7 @@ # # Configuration info for ring buffer chardevs. # -# @size: #optional ring buffer size, must be power of two, default is 65536 +# @size: ring buffer size, must be power of two, default is 65536 # # Since: 1.5 ## @@ -4990,7 +5015,7 @@ # # Return info about the chardev backend just created. # -# @pty: #optional name of the slave pseudoterminal device, present if +# @pty: name of the slave pseudoterminal device, present if # and only if a chardev of type 'pty' was created # # Since: 1.4 @@ -5112,9 +5137,9 @@ # # Information about the TPM passthrough type # -# @path: #optional string describing the path used for accessing the TPM device +# @path: string describing the path used for accessing the TPM device # -# @cancel-path: #optional string showing the TPM's sysfs cancel file +# @cancel-path: string showing the TPM's sysfs cancel file # for cancellation of TPM commands while they are executing # # Since: 1.5 @@ -5200,28 +5225,28 @@ # String fields are copied into the matching ACPI member from lowest address # upwards, and silently truncated / NUL-padded to length. # -# @sig: #optional table signature / identifier (4 bytes) +# @sig: table signature / identifier (4 bytes) # -# @rev: #optional table revision number (dependent on signature, 1 byte) +# @rev: table revision number (dependent on signature, 1 byte) # -# @oem_id: #optional OEM identifier (6 bytes) +# @oem_id: OEM identifier (6 bytes) # -# @oem_table_id: #optional OEM table identifier (8 bytes) +# @oem_table_id: OEM table identifier (8 bytes) # -# @oem_rev: #optional OEM-supplied revision number (4 bytes) +# @oem_rev: OEM-supplied revision number (4 bytes) # -# @asl_compiler_id: #optional identifier of the utility that created the table +# @asl_compiler_id: identifier of the utility that created the table # (4 bytes) # -# @asl_compiler_rev: #optional revision number of the utility that created the +# @asl_compiler_rev: revision number of the utility that created the # table (4 bytes) # -# @file: #optional colon (:) separated list of pathnames to load and +# @file: colon (:) separated list of pathnames to load and # concatenate as table data. The resultant binary blob is expected to # have an ACPI table header. At least one file is required. This field # excludes @data. # -# @data: #optional colon (:) separated list of pathnames to load and +# @data: colon (:) separated list of pathnames to load and # concatenate as table data. The resultant binary blob must not have an # ACPI table header. At least one file is required. This field excludes # @file. @@ -5268,9 +5293,9 @@ # # @type: parameter @CommandLineParameterType # -# @help: #optional human readable text string, not suitable for parsing. +# @help: human readable text string, not suitable for parsing. # -# @default: #optional default value string (since 2.1) +# @default: default value string (since 2.1) # # Since: 1.5 ## @@ -5299,7 +5324,7 @@ # # Query command line option schema. # -# @option: #optional option name +# @option: option name # # Returns: list of @CommandLineOptionInfo for all options (or for the given # @option). Returns an error if the given @option doesn't exist. @@ -5348,7 +5373,7 @@ # # @cpuid-input-eax: Input EAX value for CPUID instruction for that feature word # -# @cpuid-input-ecx: #optional Input ECX value for CPUID instruction for that +# @cpuid-input-ecx: Input ECX value for CPUID instruction for that # feature word # # @cpuid-register: Output register containing the feature bits @@ -5440,7 +5465,7 @@ # # Return rx-filter information for all NICs (or for the given NIC). # -# @name: #optional net client name +# @name: net client name # # Returns: list of @RxFilterInfo for all NICs (or for the given NIC). # Returns an error if the given @name doesn't exist, or given @@ -5574,8 +5599,8 @@ # # Send input event(s) to guest. # -# @device: #optional display device to send event(s) to. -# @head: #optional head to send event(s) to, in case the +# @device: display device to send event(s) to. +# @head: head to send event(s) to, in case the # display device supports multiple scanouts. # @events: List of InputEvent union. # @@ -5667,16 +5692,16 @@ # # Create a guest NUMA node. (for OptsVisitor) # -# @nodeid: #optional NUMA node ID (increase by 1 from 0 if omitted) +# @nodeid: NUMA node ID (increase by 1 from 0 if omitted) # -# @cpus: #optional VCPUs belonging to this node (assign VCPUS round-robin +# @cpus: VCPUs belonging to this node (assign VCPUS round-robin # if omitted) # -# @mem: #optional memory size of this node; mutually exclusive with @memdev. +# @mem: memory size of this node; mutually exclusive with @memdev. # Equally divide total memory among nodes if both @mem and @memdev are # omitted. # -# @memdev: #optional memory backend object. If specified for one node, +# @memdev: memory backend object. If specified for one node, # it must be specified for all nodes. # # Since: 2.1 @@ -5713,7 +5738,7 @@ # # Information about memory backend # -# @id: #optional backend's ID if backend has 'id' property (since 2.9) +# @id: backend's ID if backend has 'id' property (since 2.9) # # @size: memory backend size # @@ -5780,7 +5805,7 @@ # # PCDIMMDevice state information # -# @id: #optional device's ID +# @id: device's ID # # @addr: physical address, where device is mapped # @@ -5859,7 +5884,7 @@ # For description of possible values of @source and @status fields # see "_OST (OSPM Status Indication)" chapter of ACPI5.0 spec. # -# @device: #optional device ID associated with slot +# @device: device ID associated with slot # # @slot: slot ID, unique per slot of a given @slot-type # @@ -6057,7 +6082,7 @@ # # @primary: true for primary or false for secondary. # -# @failover: #optional true to do failover, false to stop. but cannot be +# @failover: true to do failover, false to stop. but cannot be # specified if 'enable' is true. default value is false. # # Returns: nothing. @@ -6080,7 +6105,7 @@ # # @error: true if an error happened, false if replication is normal. # -# @desc: #optional the human readable error description string, when +# @desc: the human readable error description string, when # @error is 'true'. # # Since: 2.9 @@ -6171,10 +6196,10 @@ # it should be passed by management with device_add command when # a CPU is being hotplugged. # -# @node-id: #optional NUMA node ID the CPU belongs to -# @socket-id: #optional socket number within node/board the CPU belongs to -# @core-id: #optional core number within socket the CPU belongs to -# @thread-id: #optional thread number within core the CPU belongs to +# @node-id: NUMA node ID the CPU belongs to +# @socket-id: socket number within node/board the CPU belongs to +# @core-id: core number within socket the CPU belongs to +# @thread-id: thread number within core the CPU belongs to # # Note: currently there are 4 properties that could be present # but management should be prepared to pass through other @@ -6198,7 +6223,7 @@ # @type: CPU object type for usage with device_add command # @props: list of properties to be used for hotplugging CPU # @vcpus-count: number of logical VCPU threads @HotpluggableCPU provides -# @qom-path: #optional link to existing CPU object if CPU is present or +# @qom-path: link to existing CPU object if CPU is present or # omitted if CPU is not present. # # Since: 2.7 diff --git a/qapi/block-core.json b/qapi/block-core.json index 9bb7f4a17b..0f132fc995 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -37,9 +37,9 @@ # # @compat: compatibility level # -# @lazy-refcounts: #optional on or off; only valid for compat >= 1.1 +# @lazy-refcounts: on or off; only valid for compat >= 1.1 # -# @corrupt: #optional true if the image has been marked corrupt; only valid for +# @corrupt: true if the image has been marked corrupt; only valid for # compat >= 1.1 (since 2.2) # # @refcount-bits: width of a refcount entry in bits (since 2.3) @@ -103,27 +103,27 @@ # # @virtual-size: maximum capacity in bytes of the image # -# @actual-size: #optional actual size on disk in bytes of the image +# @actual-size: actual size on disk in bytes of the image # -# @dirty-flag: #optional true if image is not cleanly closed +# @dirty-flag: true if image is not cleanly closed # -# @cluster-size: #optional size of a cluster in bytes +# @cluster-size: size of a cluster in bytes # -# @encrypted: #optional true if the image is encrypted +# @encrypted: true if the image is encrypted # -# @compressed: #optional true if the image is compressed (Since 1.7) +# @compressed: true if the image is compressed (Since 1.7) # -# @backing-filename: #optional name of the backing file +# @backing-filename: name of the backing file # -# @full-backing-filename: #optional full path of the backing file +# @full-backing-filename: full path of the backing file # -# @backing-filename-format: #optional the format of the backing file +# @backing-filename-format: the format of the backing file # -# @snapshots: #optional list of VM snapshots +# @snapshots: list of VM snapshots # -# @backing-image: #optional info of the backing image (since 1.6) +# @backing-image: info of the backing image (since 1.6) # -# @format-specific: #optional structure supplying additional format-specific +# @format-specific: structure supplying additional format-specific # information (since 1.7) # # Since: 1.3 @@ -149,31 +149,31 @@ # # @check-errors: number of unexpected errors occurred during check # -# @image-end-offset: #optional offset (in bytes) where the image ends, this +# @image-end-offset: offset (in bytes) where the image ends, this # field is present if the driver for the image format # supports it # -# @corruptions: #optional number of corruptions found during the check if any +# @corruptions: number of corruptions found during the check if any # -# @leaks: #optional number of leaks found during the check if any +# @leaks: number of leaks found during the check if any # -# @corruptions-fixed: #optional number of corruptions fixed during the check +# @corruptions-fixed: number of corruptions fixed during the check # if any # -# @leaks-fixed: #optional number of leaks fixed during the check if any +# @leaks-fixed: number of leaks fixed during the check if any # -# @total-clusters: #optional total number of clusters, this field is present +# @total-clusters: total number of clusters, this field is present # if the driver for the image format supports it # -# @allocated-clusters: #optional total number of allocated clusters, this +# @allocated-clusters: total number of allocated clusters, this # field is present if the driver for the image format # supports it # -# @fragmented-clusters: #optional total number of fragmented clusters, this +# @fragmented-clusters: total number of fragmented clusters, this # field is present if the driver for the image format # supports it # -# @compressed-clusters: #optional total number of compressed clusters, this +# @compressed-clusters: total number of compressed clusters, this # field is present if the driver for the image format # supports it # @@ -202,9 +202,9 @@ # # @depth: the depth of the mapping # -# @offset: #optional the offset in file that the virtual sectors are mapped to +# @offset: the offset in file that the virtual sectors are mapped to # -# @filename: #optional filename that is referred to by @offset +# @filename: filename that is referred to by @offset # # Since: 2.6 # @@ -237,7 +237,7 @@ # # @file: the filename of the backing device # -# @node-name: #optional the name of the block driver node (Since 2.0) +# @node-name: the name of the block driver node (Since 2.0) # # @ro: true if the backing device was open read-only # @@ -251,8 +251,9 @@ # 2.5: 'host_floppy' dropped # 2.6: 'luks' added # 2.8: 'replication' added, 'tftp' dropped +# 2.9: 'archipelago' dropped # -# @backing_file: #optional the name of the backing file (for copy-on-write) +# @backing_file: the name of the backing file (for copy-on-write) # # @backing_file_depth: number of files in the backing file chain (since: 1.2) # @@ -277,45 +278,45 @@ # # @image: the info of image used (since: 1.6) # -# @bps_max: #optional total throughput limit during bursts, +# @bps_max: total throughput limit during bursts, # in bytes (Since 1.7) # -# @bps_rd_max: #optional read throughput limit during bursts, +# @bps_rd_max: read throughput limit during bursts, # in bytes (Since 1.7) # -# @bps_wr_max: #optional write throughput limit during bursts, +# @bps_wr_max: write throughput limit during bursts, # in bytes (Since 1.7) # -# @iops_max: #optional total I/O operations per second during bursts, +# @iops_max: total I/O operations per second during bursts, # in bytes (Since 1.7) # -# @iops_rd_max: #optional read I/O operations per second during bursts, +# @iops_rd_max: read I/O operations per second during bursts, # in bytes (Since 1.7) # -# @iops_wr_max: #optional write I/O operations per second during bursts, +# @iops_wr_max: write I/O operations per second during bursts, # in bytes (Since 1.7) # -# @bps_max_length: #optional maximum length of the @bps_max burst +# @bps_max_length: maximum length of the @bps_max burst # period, in seconds. (Since 2.6) # -# @bps_rd_max_length: #optional maximum length of the @bps_rd_max +# @bps_rd_max_length: maximum length of the @bps_rd_max # burst period, in seconds. (Since 2.6) # -# @bps_wr_max_length: #optional maximum length of the @bps_wr_max +# @bps_wr_max_length: maximum length of the @bps_wr_max # burst period, in seconds. (Since 2.6) # -# @iops_max_length: #optional maximum length of the @iops burst +# @iops_max_length: maximum length of the @iops burst # period, in seconds. (Since 2.6) # -# @iops_rd_max_length: #optional maximum length of the @iops_rd_max +# @iops_rd_max_length: maximum length of the @iops_rd_max # burst period, in seconds. (Since 2.6) # -# @iops_wr_max_length: #optional maximum length of the @iops_wr_max +# @iops_wr_max_length: maximum length of the @iops_wr_max # burst period, in seconds. (Since 2.6) # -# @iops_size: #optional an I/O size in bytes (Since 1.7) +# @iops_size: an I/O size in bytes (Since 1.7) # -# @group: #optional throttle group name (Since 2.4) +# @group: throttle group name (Since 2.4) # # @cache: the cache mode used for the block device (since: 2.3) # @@ -410,7 +411,7 @@ # # Block dirty bitmap information. # -# @name: #optional the name of the dirty bitmap (Since 2.4) +# @name: the name of the dirty bitmap (Since 2.4) # # @count: number of dirty bytes according to the dirty bitmap # @@ -440,17 +441,17 @@ # @locked: True if the guest has locked this device from having its media # removed # -# @tray_open: #optional True if the device's tray is open +# @tray_open: True if the device's tray is open # (only present if it has a tray) # -# @dirty-bitmaps: #optional dirty bitmaps information (only present if the +# @dirty-bitmaps: dirty bitmaps information (only present if the # driver has one or more dirty bitmaps) (Since 2.0) # -# @io-status: #optional @BlockDeviceIoStatus. Only present if the device +# @io-status: @BlockDeviceIoStatus. Only present if the device # supports it and the VM is configured to stop on errors # (supported device models: virtio-blk, ide, scsi-disk) # -# @inserted: #optional @BlockDeviceInfo describing the device if media is +# @inserted: @BlockDeviceInfo describing the device if media is # present # # Since: 0.14.0 @@ -639,7 +640,7 @@ # @wr_merged: Number of write requests that have been merged into another # request (Since 2.3). # -# @idle_time_ns: #optional Time since the last I/O operation, in +# @idle_time_ns: Time since the last I/O operation, in # nanoseconds. If the field is absent it means that # there haven't been any operations yet (Since 2.5). # @@ -689,19 +690,19 @@ # # Statistics of a virtual block device or a block backing device. # -# @device: #optional If the stats are for a virtual block device, the name +# @device: If the stats are for a virtual block device, the name # corresponding to the virtual block device. # -# @node-name: #optional The node name of the device. (Since 2.3) +# @node-name: The node name of the device. (Since 2.3) # # @stats: A @BlockDeviceStats for the device. # -# @parent: #optional This describes the file block device if it has one. +# @parent: This describes the file block device if it has one. # Contains recursively the statistics of the underlying # protocol (e.g. the host file for a qcow2 image). If there is # no underlying protocol, this field is omitted # -# @backing: #optional This describes the backing block device if it has one. +# @backing: This describes the backing block device if it has one. # (Since 2.0) # # Since: 0.14.0 @@ -717,7 +718,7 @@ # # Query the @BlockStats for all virtual block devices. # -# @query-nodes: #optional If true, the command will query all the block nodes +# @query-nodes: If true, the command will query all the block nodes # that have a node name, in a list which will include "parent" # information, but not "backing". # If false or omitted, the behavior is as before - query all the @@ -956,9 +957,9 @@ # # Either @device or @node-name must be set but not both. # -# @device: #optional the name of the block backend device to set the password on +# @device: the name of the block backend device to set the password on # -# @node-name: #optional graph node name to set the password on (Since 2.0) +# @node-name: graph node name to set the password on (Since 2.0) # # @password: the password to use for the device # @@ -989,9 +990,9 @@ # # Either @device or @node-name must be set but not both. # -# @device: #optional the name of the device to get the image resized +# @device: the name of the device to get the image resized # -# @node-name: #optional graph node name to get the image resized (Since 2.0) +# @node-name: graph node name to get the image resized (Since 2.0) # # @size: new image size in bytes # @@ -1033,19 +1034,19 @@ # # Either @device or @node-name must be set but not both. # -# @device: #optional the name of the device to generate the snapshot from. +# @device: the name of the device to generate the snapshot from. # -# @node-name: #optional graph node name to generate the snapshot from (Since 2.0) +# @node-name: graph node name to generate the snapshot from (Since 2.0) # # @snapshot-file: the target of the new image. If the file exists, or # if it is a device, the snapshot will be created in the existing # file/device. Otherwise, a new file will be created. # -# @snapshot-node-name: #optional the graph node name of the new image (Since 2.0) +# @snapshot-node-name: the graph node name of the new image (Since 2.0) # -# @format: #optional the format of the snapshot image, default is 'qcow2'. +# @format: the format of the snapshot image, default is 'qcow2'. # -# @mode: #optional whether and how QEMU should create a new image, default is +# @mode: whether and how QEMU should create a new image, default is # 'absolute-paths'. ## { 'struct': 'BlockdevSnapshotSync', @@ -1071,7 +1072,7 @@ ## # @DriveBackup: # -# @job-id: #optional identifier for the newly-created block job. If +# @job-id: identifier for the newly-created block job. If # omitted, the device name will be used. (Since 2.7) # # @device: the device name or node-name of a root node which should be copied. @@ -1080,30 +1081,30 @@ # is a device, the existing file/device will be used as the new # destination. If it does not exist, a new file will be created. # -# @format: #optional the format of the new destination, default is to +# @format: the format of the new destination, default is to # probe if @mode is 'existing', else the format of the source # # @sync: what parts of the disk image should be copied to the destination # (all the disk, only the sectors allocated in the topmost image, from a # dirty bitmap, or only new I/O). # -# @mode: #optional whether and how QEMU should create a new image, default is +# @mode: whether and how QEMU should create a new image, default is # 'absolute-paths'. # -# @speed: #optional the maximum speed, in bytes per second +# @speed: the maximum speed, in bytes per second # -# @bitmap: #optional the name of dirty bitmap if sync is "incremental". +# @bitmap: the name of dirty bitmap if sync is "incremental". # Must be present if sync is "incremental", must NOT be present # otherwise. (Since 2.4) # -# @compress: #optional true to compress data, if the target format supports it. +# @compress: true to compress data, if the target format supports it. # (default: false) (since 2.8) # -# @on-source-error: #optional the action to take on an error on the source, +# @on-source-error: the action to take on an error on the source, # default 'report'. 'stop' and 'enospc' can only be used # if the block device supports io-status (see BlockInfo). # -# @on-target-error: #optional the action to take on an error on the target, +# @on-target-error: the action to take on an error on the target, # default 'report' (no limitations, since this applies to # a different block device than @device). # @@ -1123,7 +1124,7 @@ ## # @BlockdevBackup: # -# @job-id: #optional identifier for the newly-created block job. If +# @job-id: identifier for the newly-created block job. If # omitted, the device name will be used. (Since 2.7) # # @device: the device name or node-name of a root node which should be copied. @@ -1134,17 +1135,17 @@ # (all the disk, only the sectors allocated in the topmost image, or # only new I/O). # -# @speed: #optional the maximum speed, in bytes per second. The default is 0, +# @speed: the maximum speed, in bytes per second. The default is 0, # for unlimited. # -# @compress: #optional true to compress data, if the target format supports it. +# @compress: true to compress data, if the target format supports it. # (default: false) (since 2.8) # -# @on-source-error: #optional the action to take on an error on the source, +# @on-source-error: the action to take on an error on the source, # default 'report'. 'stop' and 'enospc' can only be used # if the block device supports io-status (see BlockInfo). # -# @on-target-error: #optional the action to take on an error on the target, +# @on-target-error: the action to take on an error on the target, # default 'report' (no limitations, since this applies to # a different block device than @device). # @@ -1261,19 +1262,19 @@ # Live commit of data from overlay image nodes into backing nodes - i.e., # writes data between 'top' and 'base' into 'base'. # -# @job-id: #optional identifier for the newly-created block job. If +# @job-id: identifier for the newly-created block job. If # omitted, the device name will be used. (Since 2.7) # # @device: the device name or node-name of a root node # -# @base: #optional The file name of the backing image to write data into. +# @base: The file name of the backing image to write data into. # If not specified, this is the deepest backing image. # -# @top: #optional The file name of the backing image within the image chain, +# @top: The file name of the backing image within the image chain, # which contains the topmost data to be committed down. If # not specified, this is the active layer. # -# @backing-file: #optional The backing file string to write into the overlay +# @backing-file: The backing file string to write into the overlay # image of 'top'. If 'top' is the active layer, # specifying a backing file string is an error. This # filename is not validated. @@ -1302,9 +1303,9 @@ # size of the smaller top, you can safely truncate it # yourself once the commit operation successfully completes. # -# @speed: #optional the maximum speed, in bytes per second +# @speed: the maximum speed, in bytes per second # -# @filter-node-name: #optional the node name that should be assigned to the +# @filter-node-name: the node name that should be assigned to the # filter driver that the commit job inserts into the graph # above @top. If this option is not given, a node name is # autogenerated. (Since: 2.9) @@ -1340,8 +1341,6 @@ # The operation can be stopped before it has completed using the # block-job-cancel command. # -# For the arguments, see the documentation of DriveBackup. -# # Returns: nothing on success # If @device is not a valid block device, GenericError # @@ -1368,8 +1367,6 @@ # The operation can be stopped before it has completed using the # block-job-cancel command. # -# For the arguments, see the documentation of BlockdevBackup. -# # Returns: nothing on success # If @device is not a valid block device, DeviceNotFound # @@ -1457,8 +1454,6 @@ # format of the mirror image, default is to probe if mode='existing', # else the format of the source. # -# See DriveMirror for parameter descriptions -# # Returns: nothing on success # If @device is not a valid block device, GenericError # @@ -1482,7 +1477,7 @@ # # A set of parameters describing drive mirror setup. # -# @job-id: #optional identifier for the newly-created block job. If +# @job-id: identifier for the newly-created block job. If # omitted, the device name will be used. (Since 2.7) # # @device: the device name or node-name of a root node whose writes should be @@ -1492,41 +1487,41 @@ # is a device, the existing file/device will be used as the new # destination. If it does not exist, a new file will be created. # -# @format: #optional the format of the new destination, default is to +# @format: the format of the new destination, default is to # probe if @mode is 'existing', else the format of the source # -# @node-name: #optional the new block driver state node name in the graph +# @node-name: the new block driver state node name in the graph # (Since 2.1) # -# @replaces: #optional with sync=full graph node name to be replaced by the new +# @replaces: with sync=full graph node name to be replaced by the new # image when a whole image copy is done. This can be used to repair # broken Quorum files. (Since 2.1) # -# @mode: #optional whether and how QEMU should create a new image, default is +# @mode: whether and how QEMU should create a new image, default is # 'absolute-paths'. # -# @speed: #optional the maximum speed, in bytes per second +# @speed: the maximum speed, in bytes per second # # @sync: what parts of the disk image should be copied to the destination # (all the disk, only the sectors allocated in the topmost image, or # only new I/O). # -# @granularity: #optional granularity of the dirty bitmap, default is 64K +# @granularity: granularity of the dirty bitmap, default is 64K # if the image format doesn't have clusters, 4K if the clusters # are smaller than that, else the cluster size. Must be a # power of 2 between 512 and 64M (since 1.4). # -# @buf-size: #optional maximum amount of data in flight from source to +# @buf-size: maximum amount of data in flight from source to # target (since 1.4). # -# @on-source-error: #optional the action to take on an error on the source, +# @on-source-error: the action to take on an error on the source, # default 'report'. 'stop' and 'enospc' can only be used # if the block device supports io-status (see BlockInfo). # -# @on-target-error: #optional the action to take on an error on the target, +# @on-target-error: the action to take on an error on the target, # default 'report' (no limitations, since this applies to # a different block device than @device). -# @unmap: #optional Whether to try to unmap target sectors where source has +# @unmap: Whether to try to unmap target sectors where source has # only zero. If true, and target unallocated sectors will read as zero, # target image sectors will be unmapped; otherwise, zeroes will be # written. Both will result in identical contents. @@ -1562,7 +1557,7 @@ # # @name: name of the dirty bitmap # -# @granularity: #optional the bitmap granularity, default is 64k for +# @granularity: the bitmap granularity, default is 64k for # block-dirty-bitmap-add # # Since: 2.4 @@ -1642,7 +1637,7 @@ # # Start mirroring a block device's writes to a new destination. # -# @job-id: #optional identifier for the newly-created block job. If +# @job-id: identifier for the newly-created block job. If # omitted, the device name will be used. (Since 2.7) # # @device: The device name or node-name of a root node whose writes should be @@ -1651,33 +1646,33 @@ # @target: the id or node-name of the block device to mirror to. This mustn't be # attached to guest. # -# @replaces: #optional with sync=full graph node name to be replaced by the new +# @replaces: with sync=full graph node name to be replaced by the new # image when a whole image copy is done. This can be used to repair # broken Quorum files. # -# @speed: #optional the maximum speed, in bytes per second +# @speed: the maximum speed, in bytes per second # # @sync: what parts of the disk image should be copied to the destination # (all the disk, only the sectors allocated in the topmost image, or # only new I/O). # -# @granularity: #optional granularity of the dirty bitmap, default is 64K +# @granularity: granularity of the dirty bitmap, default is 64K # if the image format doesn't have clusters, 4K if the clusters # are smaller than that, else the cluster size. Must be a # power of 2 between 512 and 64M # -# @buf-size: #optional maximum amount of data in flight from source to +# @buf-size: maximum amount of data in flight from source to # target # -# @on-source-error: #optional the action to take on an error on the source, +# @on-source-error: the action to take on an error on the source, # default 'report'. 'stop' and 'enospc' can only be used # if the block device supports io-status (see BlockInfo). # -# @on-target-error: #optional the action to take on an error on the target, +# @on-target-error: the action to take on an error on the target, # default 'report' (no limitations, since this applies to # a different block device than @device). # -# @filter-node-name: #optional the node name that should be assigned to the +# @filter-node-name: the node name that should be assigned to the # filter driver that the mirror job inserts into the graph # above @device. If this option is not given, a node name is # autogenerated. (Since: 2.9) @@ -1730,8 +1725,6 @@ # the device will be removed from its group and the rest of its # members will not be affected. The 'group' parameter is ignored. # -# See BlockIOThrottle for parameter descriptions. -# # Returns: Nothing on success # If @device is not a valid block device, DeviceNotFound # @@ -1765,9 +1758,9 @@ # # A set of parameters describing block throttling. # -# @device: #optional Block device name (deprecated, use @id instead) +# @device: Block device name (deprecated, use @id instead) # -# @id: #optional The name or QOM path of the guest device (since: 2.8) +# @id: The name or QOM path of the guest device (since: 2.8) # # @bps: total throughput limit in bytes per second # @@ -1781,57 +1774,57 @@ # # @iops_wr: write I/O operations per second # -# @bps_max: #optional total throughput limit during bursts, +# @bps_max: total throughput limit during bursts, # in bytes (Since 1.7) # -# @bps_rd_max: #optional read throughput limit during bursts, +# @bps_rd_max: read throughput limit during bursts, # in bytes (Since 1.7) # -# @bps_wr_max: #optional write throughput limit during bursts, +# @bps_wr_max: write throughput limit during bursts, # in bytes (Since 1.7) # -# @iops_max: #optional total I/O operations per second during bursts, +# @iops_max: total I/O operations per second during bursts, # in bytes (Since 1.7) # -# @iops_rd_max: #optional read I/O operations per second during bursts, +# @iops_rd_max: read I/O operations per second during bursts, # in bytes (Since 1.7) # -# @iops_wr_max: #optional write I/O operations per second during bursts, +# @iops_wr_max: write I/O operations per second during bursts, # in bytes (Since 1.7) # -# @bps_max_length: #optional maximum length of the @bps_max burst +# @bps_max_length: maximum length of the @bps_max burst # period, in seconds. It must only # be set if @bps_max is set as well. # Defaults to 1. (Since 2.6) # -# @bps_rd_max_length: #optional maximum length of the @bps_rd_max +# @bps_rd_max_length: maximum length of the @bps_rd_max # burst period, in seconds. It must only # be set if @bps_rd_max is set as well. # Defaults to 1. (Since 2.6) # -# @bps_wr_max_length: #optional maximum length of the @bps_wr_max +# @bps_wr_max_length: maximum length of the @bps_wr_max # burst period, in seconds. It must only # be set if @bps_wr_max is set as well. # Defaults to 1. (Since 2.6) # -# @iops_max_length: #optional maximum length of the @iops burst +# @iops_max_length: maximum length of the @iops burst # period, in seconds. It must only # be set if @iops_max is set as well. # Defaults to 1. (Since 2.6) # -# @iops_rd_max_length: #optional maximum length of the @iops_rd_max +# @iops_rd_max_length: maximum length of the @iops_rd_max # burst period, in seconds. It must only # be set if @iops_rd_max is set as well. # Defaults to 1. (Since 2.6) # -# @iops_wr_max_length: #optional maximum length of the @iops_wr_max +# @iops_wr_max_length: maximum length of the @iops_wr_max # burst period, in seconds. It must only # be set if @iops_wr_max is set as well. # Defaults to 1. (Since 2.6) # -# @iops_size: #optional an I/O size in bytes (Since 1.7) +# @iops_size: an I/O size in bytes (Since 1.7) # -# @group: #optional throttle group name (Since 2.4) +# @group: throttle group name (Since 2.4) # # Since: 1.1 ## @@ -1872,18 +1865,18 @@ # On successful completion the image file is updated to drop the backing file # and the BLOCK_JOB_COMPLETED event is emitted. # -# @job-id: #optional identifier for the newly-created block job. If +# @job-id: identifier for the newly-created block job. If # omitted, the device name will be used. (Since 2.7) # # @device: the device or node name of the top image # -# @base: #optional the common backing file name. +# @base: the common backing file name. # It cannot be set if @base-node is also set. # -# @base-node: #optional the node name of the backing file. +# @base-node: the node name of the backing file. # It cannot be set if @base is also set. (Since 2.8) # -# @backing-file: #optional The backing file string to write into the top +# @backing-file: The backing file string to write into the top # image. This filename is not validated. # # If a pathname string is such that it cannot be @@ -1898,9 +1891,9 @@ # protocol. # (Since 2.1) # -# @speed: #optional the maximum speed, in bytes per second +# @speed: the maximum speed, in bytes per second # -# @on-error: #optional the action to take on an error (default report). +# @on-error: the action to take on an error (default report). # 'stop' and 'enospc' can only be used if the block device # supports io-status (see BlockInfo). Since 1.3. # @@ -1967,7 +1960,7 @@ # the name of the parameter), but since QEMU 2.7 it can have # other values. # -# @force: #optional whether to allow cancellation of a paused job (default +# @force: whether to allow cancellation of a paused job (default # false). Since 1.3. # # Returns: Nothing on success @@ -2099,9 +2092,9 @@ # # Includes cache-related options for block devices # -# @direct: #optional enables use of O_DIRECT (bypass the host page cache; +# @direct: enables use of O_DIRECT (bypass the host page cache; # default: false) -# @no-flush: #optional ignore any flush requests for the device (default: +# @no-flush: ignore any flush requests for the device (default: # false) # # Since: 1.7 @@ -2129,7 +2122,7 @@ # Since: 2.0 ## { 'enum': 'BlockdevDriver', - 'data': [ 'archipelago', 'blkdebug', 'blkverify', 'bochs', 'cloop', + 'data': [ 'blkdebug', 'blkverify', 'bochs', 'cloop', 'dmg', 'file', 'ftp', 'ftps', 'gluster', 'host_cdrom', 'host_device', 'http', 'https', 'iscsi', 'luks', 'nbd', 'nfs', 'null-aio', 'null-co', 'parallels', 'qcow', 'qcow2', 'qed', @@ -2142,7 +2135,7 @@ # Driver specific block device options for the file backend. # # @filename: path to the image file -# @aio: #optional AIO backend (default: threads) (since: 2.8) +# @aio: AIO backend (default: threads) (since: 2.8) # # Since: 1.7 ## @@ -2155,8 +2148,8 @@ # # Driver specific block device options for the null backend. # -# @size: #optional size of the device in bytes. -# @latency-ns: #optional emulated latency (in nanoseconds) in processing +# @size: size of the device in bytes. +# @latency-ns: emulated latency (in nanoseconds) in processing # requests. Default to zero which completes requests immediately. # (Since 2.4) # @@ -2171,14 +2164,14 @@ # Driver specific block device options for the vvfat protocol. # # @dir: directory to be exported as FAT image -# @fat-type: #optional FAT type: 12, 16 or 32 -# @floppy: #optional whether to export a floppy image (true) or +# @fat-type: FAT type: 12, 16 or 32 +# @floppy: whether to export a floppy image (true) or # partitioned hard disk (false; default) -# @label: #optional set the volume label, limited to 11 bytes. FAT16 and +# @label: set the volume label, limited to 11 bytes. FAT16 and # FAT32 traditionally have some restrictions on labels, which are # ignored by most operating systems. Defaults to "QEMU VVFAT". # (since 2.4) -# @rw: #optional whether to allow write operations (default: false) +# @rw: whether to allow write operations (default: false) # # Since: 1.7 ## @@ -2204,7 +2197,7 @@ # # Driver specific block device options for LUKS. # -# @key-secret: #optional the ID of a QCryptoSecret object providing +# @key-secret: the ID of a QCryptoSecret object providing # the decryption key (since 2.6). Mandatory except when # doing a metadata-only probe of the image. # @@ -2221,7 +2214,7 @@ # Driver specific block device options for image format that have no option # besides their data source and an optional backing file. # -# @backing: #optional reference to or definition of the backing file block +# @backing: reference to or definition of the backing file block # device (if missing, taken from the image file content). It is # allowed to pass an empty string here in order to disable the # default backing file. @@ -2297,33 +2290,33 @@ # # Driver specific block device options for qcow2. # -# @lazy-refcounts: #optional whether to enable the lazy refcounts +# @lazy-refcounts: whether to enable the lazy refcounts # feature (default is taken from the image file) # -# @pass-discard-request: #optional whether discard requests to the qcow2 +# @pass-discard-request: whether discard requests to the qcow2 # device should be forwarded to the data source # -# @pass-discard-snapshot: #optional whether discard requests for the data source +# @pass-discard-snapshot: whether discard requests for the data source # should be issued when a snapshot operation (e.g. # deleting a snapshot) frees clusters in the qcow2 file # -# @pass-discard-other: #optional whether discard requests for the data source +# @pass-discard-other: whether discard requests for the data source # should be issued on other occasions where a cluster # gets freed # -# @overlap-check: #optional which overlap checks to perform for writes +# @overlap-check: which overlap checks to perform for writes # to the image, defaults to 'cached' (since 2.2) # -# @cache-size: #optional the maximum total size of the L2 table and +# @cache-size: the maximum total size of the L2 table and # refcount block caches in bytes (since 2.2) # -# @l2-cache-size: #optional the maximum size of the L2 table cache in +# @l2-cache-size: the maximum size of the L2 table cache in # bytes (since 2.2) # -# @refcount-cache-size: #optional the maximum size of the refcount block cache +# @refcount-cache-size: the maximum size of the refcount block cache # in bytes (since 2.2) # -# @cache-clean-interval: #optional clean unused entries in the L2 and refcount +# @cache-clean-interval: clean unused entries in the L2 and refcount # caches. The interval is in seconds. The default value # is 0 and it disables this feature (since 2.5) # @@ -2343,42 +2336,13 @@ ## -# @BlockdevOptionsArchipelago: -# -# Driver specific block device options for Archipelago. -# -# @volume: Name of the Archipelago volume image -# -# @mport: #optional The port number on which mapperd is -# listening. This is optional -# and if not specified, QEMU will make Archipelago -# use the default port (1001). -# -# @vport: #optional The port number on which vlmcd is -# listening. This is optional -# and if not specified, QEMU will make Archipelago -# use the default port (501). -# -# @segment: #optional The name of the shared memory segment -# Archipelago stack is using. This is optional -# and if not specified, QEMU will make Archipelago -# use the default value, 'archipelago'. -# Since: 2.2 -## -{ 'struct': 'BlockdevOptionsArchipelago', - 'data': { 'volume': 'str', - '*mport': 'int', - '*vport': 'int', - '*segment': 'str' } } - -## # @BlockdevOptionsSsh: # # @server: host address # # @path: path to the image on the host # -# @user: #optional user as which to connect, defaults to current +# @user: user as which to connect, defaults to current # local user name # # TODO: Expose the host_key_check option in QMP @@ -2421,20 +2385,20 @@ # # @event: trigger event # -# @state: #optional the state identifier blkdebug needs to be in to +# @state: the state identifier blkdebug needs to be in to # actually trigger the event; defaults to "any" # -# @errno: #optional error identifier (errno) to be returned; defaults to +# @errno: error identifier (errno) to be returned; defaults to # EIO # -# @sector: #optional specifies the sector index which has to be affected +# @sector: specifies the sector index which has to be affected # in order to actually trigger the event; defaults to "any # sector" # -# @once: #optional disables further events after this one has been +# @once: disables further events after this one has been # triggered; defaults to false # -# @immediately: #optional fail immediately; defaults to false +# @immediately: fail immediately; defaults to false # # Since: 2.0 ## @@ -2453,7 +2417,7 @@ # # @event: trigger event # -# @state: #optional the current state identifier blkdebug needs to be in; +# @state: the current state identifier blkdebug needs to be in; # defaults to "any" # # @new_state: the state identifier blkdebug is supposed to assume if @@ -2473,14 +2437,14 @@ # # @image: underlying raw block device (or image file) # -# @config: #optional filename of the configuration file +# @config: filename of the configuration file # -# @align: #optional required alignment for requests in bytes, +# @align: required alignment for requests in bytes, # must be power of 2, or 0 for default # -# @inject-error: #optional array of error injection descriptions +# @inject-error: array of error injection descriptions # -# @set-state: #optional array of state-change descriptions +# @set-state: array of state-change descriptions # # Since: 2.0 ## @@ -2524,17 +2488,17 @@ # # Driver specific block device options for Quorum # -# @blkverify: #optional true if the driver must print content mismatch +# @blkverify: true if the driver must print content mismatch # set to false by default # # @children: the children block devices to use # # @vote-threshold: the vote limit under which a read will fail # -# @rewrite-corrupted: #optional rewrite corrupted data when quorum is reached +# @rewrite-corrupted: rewrite corrupted data when quorum is reached # (Since 2.1) # -# @read-pattern: #optional choose read pattern and set to quorum by default +# @read-pattern: choose read pattern and set to quorum by default # (Since 2.2) # # Since: 2.0 @@ -2557,10 +2521,10 @@ # # @server: gluster servers description # -# @debug: #optional libgfapi log level (default '4' which is Error) +# @debug: libgfapi log level (default '4' which is Error) # (Since 2.8) # -# @logfile: #optional libgfapi log file (default /dev/stderr) (Since 2.8) +# @logfile: libgfapi log file (default /dev/stderr) (Since 2.8) # # Since: 2.7 ## @@ -2601,23 +2565,23 @@ # # @target: The target iqn name # -# @lun: #optional LUN to connect to. Defaults to 0. +# @lun: LUN to connect to. Defaults to 0. # -# @user: #optional User name to log in with. If omitted, no CHAP +# @user: User name to log in with. If omitted, no CHAP # authentication is performed. # -# @password-secret: #optional The ID of a QCryptoSecret object providing +# @password-secret: The ID of a QCryptoSecret object providing # the password for the login. This option is required if # @user is specified. # -# @initiator-name: #optional The iqn name we want to identify to the target +# @initiator-name: The iqn name we want to identify to the target # as. If this option is not specified, an initiator name is # generated automatically. # -# @header-digest: #optional The desired header digest. Defaults to +# @header-digest: The desired header digest. Defaults to # none-crc32c. # -# @timeout: #optional Timeout in seconds after which a request will +# @timeout: Timeout in seconds after which a request will # timeout. 0 means no timeout and is the default. # # Driver specific block device options for iscsi @@ -2664,20 +2628,20 @@ # # @image: Image name in the Ceph pool. # -# @conf: #optional path to Ceph configuration file. Values +# @conf: path to Ceph configuration file. Values # in the configuration file will be overridden by # options specified via QAPI. # -# @snapshot: #optional Ceph snapshot name. +# @snapshot: Ceph snapshot name. # -# @user: #optional Ceph id name. +# @user: Ceph id name. # -# @server: #optional Monitor host address and port. This maps +# @server: Monitor host address and port. This maps # to the "mon_host" Ceph option. # -# @auth-supported: #optional Authentication supported. +# @auth-supported: Authentication supported. # -# @password-secret: #optional The ID of a QCryptoSecret object providing +# @password-secret: The ID of a QCryptoSecret object providing # the password for the login. # # Since: 2.9 @@ -2732,7 +2696,7 @@ # # @mode: the replication mode # -# @top-id: #optional In secondary mode, node name or device ID of the root +# @top-id: In secondary mode, node name or device ID of the root # node who owns the replication node chain. Must not be given in # primary mode. # @@ -2779,24 +2743,24 @@ # # @path: path of the image on the host # -# @user: #optional UID value to use when talking to the +# @user: UID value to use when talking to the # server (defaults to 65534 on Windows and getuid() # on unix) # -# @group: #optional GID value to use when talking to the +# @group: GID value to use when talking to the # server (defaults to 65534 on Windows and getgid() # in unix) # -# @tcp-syn-count: #optional number of SYNs during the session +# @tcp-syn-count: number of SYNs during the session # establishment (defaults to libnfs default) # -# @readahead-size: #optional set the readahead size in bytes (defaults +# @readahead-size: set the readahead size in bytes (defaults # to libnfs default) # -# @page-cache-size: #optional set the pagecache size in bytes (defaults +# @page-cache-size: set the pagecache size in bytes (defaults # to libnfs default) # -# @debug: #optional set the NFS debug level (max 2) (defaults +# @debug: set the NFS debug level (max 2) (defaults # to libnfs default) # # Since: 2.8 @@ -2830,9 +2794,9 @@ # # @server: NBD server address # -# @export: #optional export name +# @export: export name # -# @tls-creds: #optional TLS credentials ID +# @tls-creds: TLS credentials ID # # Since: 2.8 ## @@ -2846,8 +2810,8 @@ # # Driver specific block device options for the raw driver. # -# @offset: #optional position where the block device starts -# @size: #optional the assumed size of the device +# @offset: position where the block device starts +# @size: the assumed size of the device # # Since: 2.8 ## @@ -2862,13 +2826,13 @@ # block devices, independent of the block driver: # # @driver: block driver name -# @node-name: #optional the node name of the new node (Since 2.0). +# @node-name: the node name of the new node (Since 2.0). # This option is required on the top level of blockdev-add. -# @discard: #optional discard-related options (default: ignore) -# @cache: #optional cache-related options -# @read-only: #optional whether the block device should be read-only +# @discard: discard-related options (default: ignore) +# @cache: cache-related options +# @read-only: whether the block device should be read-only # (default: false) -# @detect-zeroes: #optional detect and optimize zero writes (Since 2.1) +# @detect-zeroes: detect and optimize zero writes (Since 2.1) # (default: off) # # Remaining options are determined by the block driver. @@ -2884,7 +2848,6 @@ '*detect-zeroes': 'BlockdevDetectZeroesOptions' }, 'discriminator': 'driver', 'data': { - 'archipelago':'BlockdevOptionsArchipelago', 'blkdebug': 'BlockdevOptionsBlkdebug', 'blkverify': 'BlockdevOptionsBlkverify', 'bochs': 'BlockdevOptionsGenericFormat', @@ -2944,8 +2907,6 @@ # BlockBackend will be created; otherwise, @node-name is mandatory at the top # level and no BlockBackend will be created. # -# For the arguments, see the documentation of BlockdevOptions. -# # Note: This command is still a work in progress. It doesn't support all # block drivers among other things. Stay away from it unless you want # to help with its development. @@ -3050,11 +3011,11 @@ # to it # - if the guest device does not have an actual tray # -# @device: #optional Block device name (deprecated, use @id instead) +# @device: Block device name (deprecated, use @id instead) # -# @id: #optional The name or QOM path of the guest device (since: 2.8) +# @id: The name or QOM path of the guest device (since: 2.8) # -# @force: #optional if false (the default), an eject request will be sent to +# @force: if false (the default), an eject request will be sent to # the guest if it has locked the tray (and the tray will not be opened # immediately); if true, the tray will be opened regardless of whether # it is locked @@ -3090,9 +3051,9 @@ # # If the tray was already closed before, this will be a no-op. # -# @device: #optional Block device name (deprecated, use @id instead) +# @device: Block device name (deprecated, use @id instead) # -# @id: #optional The name or QOM path of the guest device (since: 2.8) +# @id: The name or QOM path of the guest device (since: 2.8) # # Since: 2.5 # @@ -3124,9 +3085,9 @@ # # If the tray is open and there is no medium inserted, this will be a no-op. # -# @device: #optional Block device name (deprecated, use @id instead) +# @device: Block device name (deprecated, use @id instead) # -# @id: #optional The name or QOM path of the guest device (since: 2.8) +# @id: The name or QOM path of the guest device (since: 2.8) # # Note: This command is still a work in progress and is considered experimental. # Stay away from it unless you want to help with its development. @@ -3170,9 +3131,9 @@ # device's tray must currently be open (unless there is no attached guest # device) and there must be no medium inserted already. # -# @device: #optional Block device name (deprecated, use @id instead) +# @device: Block device name (deprecated, use @id instead) # -# @id: #optional The name or QOM path of the guest device (since: 2.8) +# @id: The name or QOM path of the guest device (since: 2.8) # # @node-name: name of a node in the block driver state graph # @@ -3231,17 +3192,17 @@ # combines blockdev-open-tray, x-blockdev-remove-medium, # x-blockdev-insert-medium and blockdev-close-tray). # -# @device: #optional Block device name (deprecated, use @id instead) +# @device: Block device name (deprecated, use @id instead) # -# @id: #optional The name or QOM path of the guest device +# @id: The name or QOM path of the guest device # (since: 2.8) # # @filename: filename of the new image to be loaded # -# @format: #optional format to open the new image with (defaults to +# @format: format to open the new image with (defaults to # the probed format) # -# @read-only-mode: #optional change the read-only mode of the device; defaults +# @read-only-mode: change the read-only mode of the device; defaults # to 'retain' # # Since: 2.5 @@ -3314,16 +3275,16 @@ # reasons, but it can be empty ("") if the image does not # have a device name associated. # -# @node-name: #optional node name (Since: 2.4) +# @node-name: node name (Since: 2.4) # # @msg: informative message for human consumption, such as the kind of # corruption being detected. It should not be parsed by machine as it is # not guaranteed to be stable # -# @offset: #optional if the corruption resulted from an image access, this is +# @offset: if the corruption resulted from an image access, this is # the host's access offset into the image # -# @size: #optional if the corruption resulted from an image access, this is +# @size: if the corruption resulted from an image access, this is # the access size # # @fatal: if set, the image is marked corrupt and therefore unusable after this @@ -3368,7 +3329,7 @@ # # @action: action that has been taken # -# @nospace: #optional true if I/O error was caused due to a no-space +# @nospace: true if I/O error was caused due to a no-space # condition. This key is only present if query-block's # io-status is present, please see query-block documentation # for more information (since: 2.2) @@ -3414,7 +3375,7 @@ # # @speed: rate limit, bytes per second # -# @error: #optional error message. Only present on failure. This field +# @error: error message. Only present on failure. This field # contains a human-readable error message. There are no semantics # other than that streaming has failed and clients should not try to # interpret the error string @@ -3623,9 +3584,9 @@ # # @parent: the id or name of the parent node. # -# @child: #optional the name of a child under the given parent node. +# @child: the name of a child under the given parent node. # -# @node: #optional the name of the node that will be added. +# @node: the name of the node that will be added. # # Note: this command is experimental, and its API is not stable. It # does not support all kinds of operations, all kinds of children, nor diff --git a/qapi/block.json b/qapi/block.json index 22da91441b..46fca0e1f3 100644 --- a/qapi/block.json +++ b/qapi/block.json @@ -163,11 +163,11 @@ # # Ejects a device from a removable drive. # -# @device: #optional Block device name (deprecated, use @id instead) +# @device: Block device name (deprecated, use @id instead) # -# @id: #optional The name or QOM path of the guest device (since: 2.8) +# @id: The name or QOM path of the guest device (since: 2.8) # -# @force: #optional If true, eject regardless of whether the drive is locked. +# @force: If true, eject regardless of whether the drive is locked. # If not specified, the default value is false. # # Returns: Nothing on success @@ -215,7 +215,7 @@ # @device: The device name or node name of the node to be exported # # @writable: Whether clients should be able to write to the device via the -# NBD connection (default false). #optional +# NBD connection (default false). # # Returns: error if the device is already marked for export. # diff --git a/qapi/crypto.json b/qapi/crypto.json index 93a04743ea..6b6fde367a 100644 --- a/qapi/crypto.json +++ b/qapi/crypto.json @@ -152,7 +152,7 @@ # # The options that apply to QCow/QCow2 AES-CBC encryption format # -# @key-secret: #optional the ID of a QCryptoSecret object providing the +# @key-secret: the ID of a QCryptoSecret object providing the # decryption key. Mandatory except when probing image for # metadata only. # @@ -166,7 +166,7 @@ # # The options that apply to LUKS encryption format # -# @key-secret: #optional the ID of a QCryptoSecret object providing the +# @key-secret: the ID of a QCryptoSecret object providing the # decryption key. Mandatory except when probing image for # metadata only. # Since: 2.6 @@ -180,17 +180,17 @@ # # The options that apply to LUKS encryption format initialization # -# @cipher-alg: #optional the cipher algorithm for data encryption +# @cipher-alg: the cipher algorithm for data encryption # Currently defaults to 'aes'. -# @cipher-mode: #optional the cipher mode for data encryption +# @cipher-mode: the cipher mode for data encryption # Currently defaults to 'cbc' -# @ivgen-alg: #optional the initialization vector generator +# @ivgen-alg: the initialization vector generator # Currently defaults to 'essiv' -# @ivgen-hash-alg: #optional the initialization vector generator hash +# @ivgen-hash-alg: the initialization vector generator hash # Currently defaults to 'sha256' -# @hash-alg: #optional the master key hash algorithm +# @hash-alg: the master key hash algorithm # Currently defaults to 'sha256' -# @iter-time: #optional number of milliseconds to spend in +# @iter-time: number of milliseconds to spend in # PBKDF passphrase processing. Currently defaults # to 2000. (since 2.8) # Since: 2.6 @@ -257,8 +257,8 @@ # # @active: whether the key slot is currently in use # @key-offset: offset to the key material in bytes -# @iters: #optional number of PBKDF2 iterations for key material -# @stripes: #optional number of stripes for splitting key material +# @iters: number of PBKDF2 iterations for key material +# @stripes: number of stripes for splitting key material # # Since: 2.7 ## @@ -277,7 +277,7 @@ # @cipher-alg: the cipher algorithm for data encryption # @cipher-mode: the cipher mode for data encryption # @ivgen-alg: the initialization vector generator -# @ivgen-hash-alg: #optional the initialization vector generator hash +# @ivgen-hash-alg: the initialization vector generator hash # @hash-alg: the master key hash algorithm # @payload-offset: offset to the payload data in bytes # @master-key-iters: number of PBKDF2 iterations for key material diff --git a/qapi/event.json b/qapi/event.json index e02852cd8a..e80f3f4446 100644 --- a/qapi/event.json +++ b/qapi/event.json @@ -186,7 +186,7 @@ # At this point, it's safe to reuse the specified device ID. Device removal can # be initiated by the guest or by HMP/QMP commands. # -# @device: #optional device name +# @device: device name # # @path: device path # @@ -209,7 +209,7 @@ # Emitted once until the 'query-rx-filter' command is executed, the first event # will always be emitted # -# @name: #optional net client name +# @name: net client name # # @path: device path # @@ -488,7 +488,7 @@ # # @action: action that has been taken, currently always "pause" # -# @info: #optional information about a panic (since 2.9) +# @info: information about a panic (since 2.9) # # Since: 1.5 # @@ -533,7 +533,7 @@ # # @type: quorum operation type (Since 2.6) # -# @error: #optional error message. Only present on failure. This field +# @error: error message. Only present on failure. This field # contains a human-readable error message. There are no semantics other # than that the block layer reported an error and clients should not # try to interpret the error string. @@ -620,7 +620,7 @@ # # @result: DumpQueryResult type described in qapi-schema.json. # -# @error: #optional human-readable error string that provides +# @error: human-readable error string that provides # hint on why dump failed. Only presents on failure. The # user should not try to interpret the error string. # diff --git a/qapi/introspect.json b/qapi/introspect.json index f6adc439bb..1dbaef56eb 100644 --- a/qapi/introspect.json +++ b/qapi/introspect.json @@ -163,10 +163,10 @@ # # @members: the object type's (non-variant) members, in no particular order. # -# @tag: #optional the name of the member serving as type tag. +# @tag: the name of the member serving as type tag. # An element of @members with this name must exist. # -# @variants: #optional variant members, i.e. additional members that +# @variants: variant members, i.e. additional members that # depend on the type tag's value. Present exactly when # @tag is present. The variants are in no particular order, # and may even differ from the order of the values of the @@ -190,7 +190,7 @@ # # @type: the name of the member's type. # -# @default: #optional default when used as command parameter. +# @default: default when used as command parameter. # If absent, the parameter is mandatory. # If present, the value must be null. The parameter is # optional, and behavior when it's missing is not specified diff --git a/qapi/rocker.json b/qapi/rocker.json index 97e2b8376f..3587661161 100644 --- a/qapi/rocker.json +++ b/qapi/rocker.json @@ -1,3 +1,5 @@ +# -*- Mode: Python -*- + ## # = Rocker switch device ## @@ -119,26 +121,26 @@ # # @tbl-id: flow table ID # -# @in-pport: #optional physical input port +# @in-pport: physical input port # -# @tunnel-id: #optional tunnel ID +# @tunnel-id: tunnel ID # -# @vlan-id: #optional VLAN ID +# @vlan-id: VLAN ID # -# @eth-type: #optional Ethernet header type +# @eth-type: Ethernet header type # -# @eth-src: #optional Ethernet header source MAC address +# @eth-src: Ethernet header source MAC address # -# @eth-dst: #optional Ethernet header destination MAC address +# @eth-dst: Ethernet header destination MAC address # -# @ip-proto: #optional IP Header protocol field +# @ip-proto: IP Header protocol field # -# @ip-tos: #optional IP header TOS field +# @ip-tos: IP header TOS field # -# @ip-dst: #optional IP header destination address +# @ip-dst: IP header destination address # -# Note: fields are marked #optional to indicate that they may or may not -# appear in the flow key depending if they're relevant to the flow key. +# Note: optional members may or may not appear in the flow key +# depending if they're relevant to the flow key. # # Since: 2.4 ## @@ -153,22 +155,22 @@ # # Rocker switch OF-DPA flow mask # -# @in-pport: #optional physical input port +# @in-pport: physical input port # -# @tunnel-id: #optional tunnel ID +# @tunnel-id: tunnel ID # -# @vlan-id: #optional VLAN ID +# @vlan-id: VLAN ID # -# @eth-src: #optional Ethernet header source MAC address +# @eth-src: Ethernet header source MAC address # -# @eth-dst: #optional Ethernet header destination MAC address +# @eth-dst: Ethernet header destination MAC address # -# @ip-proto: #optional IP Header protocol field +# @ip-proto: IP Header protocol field # -# @ip-tos: #optional IP header TOS field +# @ip-tos: IP header TOS field # -# Note: fields are marked #optional to indicate that they may or may not -# appear in the flow mask depending if they're relevant to the flow mask. +# Note: optional members may or may not appear in the flow mask +# depending if they're relevant to the flow mask. # # Since: 2.4 ## @@ -182,20 +184,20 @@ # # Rocker switch OF-DPA flow action # -# @goto-tbl: #optional next table ID +# @goto-tbl: next table ID # -# @group-id: #optional group ID +# @group-id: group ID # -# @tunnel-lport: #optional tunnel logical port ID +# @tunnel-lport: tunnel logical port ID # -# @vlan-id: #optional VLAN ID +# @vlan-id: VLAN ID # -# @new-vlan-id: #optional new VLAN ID +# @new-vlan-id: new VLAN ID # -# @out-pport: #optional physical output port +# @out-pport: physical output port # -# Note: fields are marked #optional to indicate that they may or may not -# appear in the flow action depending if they're relevant to the flow action. +# Note: optional members may or may not appear in the flow action +# depending if they're relevant to the flow action. # # Since: 2.4 ## @@ -232,7 +234,7 @@ # # @name: switch name # -# @tbl-id: #optional flow table ID. If tbl-id is not specified, returns +# @tbl-id: flow table ID. If tbl-id is not specified, returns # flow information for all tables. # # Returns: rocker OF-DPA flow information @@ -266,30 +268,30 @@ # # @type: group type # -# @vlan-id: #optional VLAN ID +# @vlan-id: VLAN ID # -# @pport: #optional physical port number +# @pport: physical port number # -# @index: #optional group index, unique with group type +# @index: group index, unique with group type # -# @out-pport: #optional output physical port number +# @out-pport: output physical port number # -# @group-id: #optional next group ID +# @group-id: next group ID # -# @set-vlan-id: #optional VLAN ID to set +# @set-vlan-id: VLAN ID to set # -# @pop-vlan: #optional pop VLAN headr from packet +# @pop-vlan: pop VLAN headr from packet # -# @group-ids: #optional list of next group IDs +# @group-ids: list of next group IDs # -# @set-eth-src: #optional set source MAC address in Ethernet header +# @set-eth-src: set source MAC address in Ethernet header # -# @set-eth-dst: #optional set destination MAC address in Ethernet header +# @set-eth-dst: set destination MAC address in Ethernet header # -# @ttl-check: #optional perform TTL check +# @ttl-check: perform TTL check # -# Note: fields are marked #optional to indicate that they may or may not -# appear in the group depending if they're relevant to the group type. +# Note: optional members may or may not appear in the group depending +# if they're relevant to the group type. # # Since: 2.4 ## @@ -308,7 +310,7 @@ # # @name: switch name # -# @type: #optional group type. If type is not specified, returns +# @type: group type. If type is not specified, returns # group information for all group types. # # Returns: rocker OF-DPA group information diff --git a/qapi/trace.json b/qapi/trace.json index 2bfda7ac7c..de6588d9f7 100644 --- a/qapi/trace.json +++ b/qapi/trace.json @@ -48,7 +48,7 @@ # Query the state of events. # # @name: Event name pattern (case-sensitive glob). -# @vcpu: #optional The vCPU to query (any by default; since 2.7). +# @vcpu: The vCPU to query (any by default; since 2.7). # # Returns: a list of @TraceEventInfo for the matching events # @@ -81,8 +81,8 @@ # # @name: Event name pattern (case-sensitive glob). # @enable: Whether to enable tracing. -# @ignore-unavailable: #optional Do not match unavailable events with @name. -# @vcpu: #optional The vCPU to act upon (all by default; since 2.7). +# @ignore-unavailable: Do not match unavailable events with @name. +# @vcpu: The vCPU to act upon (all by default; since 2.7). # # An event's state is modified if: # - its name matches the @name pattern, and diff --git a/qemu-options.hx b/qemu-options.hx index 8dd8ee34a6..99af8edf5f 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -252,7 +252,10 @@ drive letters depend on the target architecture. The x86 PC uses: a, b (floppy 1 and 2), c (first hard disk), d (first CD-ROM), n-p (Etherboot from network adapter 1-4), hard disk boot is the default. To apply a particular boot order only on the first startup, specify it via -@option{once}. +@option{once}. Note that the @option{order} or @option{once} parameter +should not be used together with the @option{bootindex} property of +devices, since the firmware implementations normally do not support both +at the same time. Interactive boot menus/prompts can be enabled via @option{menu=on} as far as firmware/BIOS supports them. The default is non-interactive boot. diff --git a/qga/qapi-schema.json b/qga/qapi-schema.json index d421609dcb..a02dbf2d18 100644 --- a/qga/qapi-schema.json +++ b/qga/qapi-schema.json @@ -11,6 +11,23 @@ # ## +{ 'pragma': { 'doc-required': true } } + +# Whitelists to permit QAPI rule violations; think twice before you +# add to them! +{ 'pragma': { + # Commands allowed to return a non-dictionary: + 'returns-whitelist': [ + 'guest-file-open', + 'guest-fsfreeze-freeze', + 'guest-fsfreeze-freeze-list', + 'guest-fsfreeze-status', + 'guest-fsfreeze-thaw', + 'guest-get-time', + 'guest-set-vcpus', + 'guest-sync', + 'guest-sync-delimited' ] } } + ## # @guest-sync-delimited: # @@ -127,7 +144,7 @@ # If that's the case users are advised to always pass a # value. # -# @time: #optional time of nanoseconds, relative to the Epoch +# @time: time of nanoseconds, relative to the Epoch # of 1970-01-01 in UTC. # # Returns: Nothing on success. @@ -186,7 +203,7 @@ # Initiate guest-activated shutdown. Note: this is an asynchronous # shutdown request, with no guarantee of successful shutdown. # -# @mode: #optional "halt", "powerdown" (default), or "reboot" +# @mode: "halt", "powerdown" (default), or "reboot" # # This command does NOT return a response on success. Success condition # is indicated by the VM exiting with a zero exit status or, when @@ -205,7 +222,7 @@ # # @path: Full path to the file in the guest to open. # -# @mode: #optional open mode, as per fopen(), "r" is the default. +# @mode: open mode, as per fopen(), "r" is the default. # # Returns: Guest file handle on success. # @@ -253,7 +270,7 @@ # # @handle: filehandle returned by guest-file-open # -# @count: #optional maximum number of bytes to read (default is 4KB) +# @count: maximum number of bytes to read (default is 4KB) # # Returns: @GuestFileRead on success. # @@ -287,7 +304,7 @@ # # @buf-b64: base64-encoded string representing data to be written # -# @count: #optional bytes to write (actual bytes, after base64-decode), +# @count: bytes to write (actual bytes, after base64-decode), # default is all content in buf-b64 buffer after base64 decoding # # Returns: @GuestFileWrite on success. @@ -424,7 +441,7 @@ # # Sync and freeze specified guest filesystems # -# @mountpoints: #optional an array of mountpoints of filesystems to be frozen. +# @mountpoints: an array of mountpoints of filesystems to be frozen. # If omitted, every mounted filesystem is frozen. # # Returns: Number of file systems currently frozen. On error, all filesystems @@ -653,7 +670,7 @@ # # @online: Whether the VCPU is enabled. # -# @can-offline: #optional Whether offlining the VCPU is possible. This member +# @can-offline: Whether offlining the VCPU is possible. This member # is always filled in by the guest agent when the structure is # returned, and always ignored on input (hence it can be omitted # then). @@ -841,7 +858,7 @@ # # @online: Whether the MEMORY BLOCK is enabled in guest. # -# @can-offline: #optional Whether offlining the MEMORY BLOCK is possible. +# @can-offline: Whether offlining the MEMORY BLOCK is possible. # This member is always filled in by the guest agent when the # structure is returned, and always ignored on input (hence it # can be omitted then). @@ -894,7 +911,7 @@ # # @response: the result of memory block operation. # -# @error-code: #optional the error number. +# @error-code: the error number. # When memory block operation fails, we assign the value of # 'errno' to this member, it indicates what goes wrong. # When the operation succeeds, it will be omitted. @@ -962,16 +979,16 @@ # @GuestExecStatus: # # @exited: true if process has already terminated. -# @exitcode: #optional process exit code if it was normally terminated. -# @signal: #optional signal number (linux) or unhandled exception code +# @exitcode: process exit code if it was normally terminated. +# @signal: signal number (linux) or unhandled exception code # (windows) if the process was abnormally terminated. -# @out-data: #optional base64-encoded stdout of the process -# @err-data: #optional base64-encoded stderr of the process +# @out-data: base64-encoded stdout of the process +# @err-data: base64-encoded stderr of the process # Note: @out-data and @err-data are present only # if 'capture-output' was specified for 'guest-exec' -# @out-truncated: #optional true if stdout was not fully captured +# @out-truncated: true if stdout was not fully captured # due to size limitation. -# @err-truncated: #optional true if stderr was not fully captured +# @err-truncated: true if stderr was not fully captured # due to size limitation. # # Since: 2.5 @@ -1011,10 +1028,10 @@ # Execute a command in the guest # # @path: path or executable name to execute -# @arg: #optional argument list to pass to executable -# @env: #optional environment variables to pass to executable -# @input-data: #optional data to be passed to process stdin (base64 encoded) -# @capture-output: #optional bool flag to enable capture of +# @arg: argument list to pass to executable +# @env: environment variables to pass to executable +# @input-data: data to be passed to process stdin (base64 encoded) +# @capture-output: bool flag to enable capture of # stdout/stderr of running process. defaults to false. # # Returns: PID on success. diff --git a/replay/replay.c b/replay/replay.c index 1835b9902e..78e2a7e570 100644 --- a/replay/replay.c +++ b/replay/replay.c @@ -16,6 +16,7 @@ #include "replay-internal.h" #include "qemu/timer.h" #include "qemu/main-loop.h" +#include "sysemu/cpus.h" #include "sysemu/sysemu.h" #include "qemu/error-report.h" diff --git a/roms/openbios b/roms/openbios -Subproject 0cd97cc904e71fbb461112f6756934ec6af890b +Subproject f233c3f72cfa79c1123a7ccef08d2f7e228da6d @@ -380,7 +380,7 @@ define unnest-vars endef TEXI2MAN = $(call quiet-command, \ - perl -Ww -- $(SRC_PATH)/scripts/texi2pod.pl $< $@.pod && \ + perl -Ww -- $(SRC_PATH)/scripts/texi2pod.pl -I docs $< $@.pod && \ $(POD2MAN) --section=$(subst .,,$(suffix $@)) --center=" " --release=" " $@.pod > $@, \ "GEN","$@") diff --git a/scripts/coverity-model.c b/scripts/coverity-model.c index ee5bf9d078..c702804f41 100644 --- a/scripts/coverity-model.c +++ b/scripts/coverity-model.c @@ -67,18 +67,27 @@ static void __bufread(uint8_t *buf, ssize_t len) int last = buf[len-1]; } -MemTxResult address_space_rw(AddressSpace *as, hwaddr addr, MemTxAttrs attrs, - uint8_t *buf, int len, bool is_write) +MemTxResult address_space_read(AddressSpace *as, hwaddr addr, + MemTxAttrs attrs, + uint8_t *buf, int len) { MemTxResult result; - // TODO: investigate impact of treating reads as producing // tainted data, with __coverity_tainted_data_argument__(buf). - if (is_write) __bufread(buf, len); else __bufwrite(buf, len); + __bufwrite(buf, len); + return result; +} +MemTxResult address_space_write(AddressSpace *as, hwaddr addr, + MemTxAttrs attrs, + const uint8_t *buf, int len) +{ + MemTxResult result; + __bufread(buf, len); return result; } + /* Tainting */ typedef struct {} name2keysym_t; diff --git a/scripts/dump-guest-memory.py b/scripts/dump-guest-memory.py index 9956fc036c..f7c6635f15 100644 --- a/scripts/dump-guest-memory.py +++ b/scripts/dump-guest-memory.py @@ -314,8 +314,18 @@ def get_arch_phdr(endianness, elfclass): def int128_get64(val): """Returns low 64bit part of Int128 struct.""" - assert val["hi"] == 0 - return val["lo"] + try: + assert val["hi"] == 0 + return val["lo"] + except gdb.error: + u64t = gdb.lookup_type('uint64_t').array(2) + u64 = val.cast(u64t) + if sys.byteorder == 'little': + assert u64[1] == 0 + return u64[0] + else: + assert u64[0] == 0 + return u64[1] def qlist_foreach(head, field_str): diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py index 0c05449cb6..1943de4852 100644 --- a/scripts/qapi-commands.py +++ b/scripts/qapi-commands.py @@ -13,7 +13,6 @@ # See the COPYING file in the top-level directory. from qapi import * -import re def gen_command_decl(name, arg_type, boxed, ret_type): @@ -84,7 +83,8 @@ static void qmp_marshal_output_%(c_name)s(%(c_type)s ret_in, QObject **ret_out, def gen_marshal_proto(name): - return 'void qmp_marshal_%s(QDict *args, QObject **ret, Error **errp)' % c_name(name) + return ('void qmp_marshal_%s(QDict *args, QObject **ret, Error **errp)' + % c_name(name)) def gen_marshal_decl(name): @@ -198,7 +198,7 @@ def gen_register_command(name, success_response): options = 'QCO_NO_SUCCESS_RESP' ret = mcgen(''' - qmp_register_command(cmds, "%(name)s", + qmp_register_command(cmds, "%(name)s", qmp_marshal_%(c_name)s, %(opts)s); ''', name=name, c_name=c_name(name), diff --git a/scripts/qapi-event.py b/scripts/qapi-event.py index f4eb7f85b1..0485e39145 100644 --- a/scripts/qapi-event.py +++ b/scripts/qapi-event.py @@ -223,7 +223,7 @@ fdecl.write(mcgen(''' ''', prefix=prefix)) -event_enum_name = c_name(prefix + "QAPIEvent", protect=False) +event_enum_name = c_name(prefix + 'QAPIEvent', protect=False) schema = QAPISchema(input_file) gen = QAPISchemaGenEventVisitor() diff --git a/scripts/qapi-introspect.py b/scripts/qapi-introspect.py index fb72c61d02..032bcea491 100644 --- a/scripts/qapi-introspect.py +++ b/scripts/qapi-introspect.py @@ -170,10 +170,10 @@ const char %(c_name)s[] = %(c_string)s; opt_unmask = False (input_file, output_dir, do_c, do_h, prefix, opts) = \ - parse_command_line("u", ["unmask-non-abi-names"]) + parse_command_line('u', ['unmask-non-abi-names']) for o, a in opts: - if o in ("-u", "--unmask-non-abi-names"): + if o in ('-u', '--unmask-non-abi-names'): opt_unmask = True c_comment = ''' diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py index dabc42e047..b45e7b5634 100644 --- a/scripts/qapi-types.py +++ b/scripts/qapi-types.py @@ -244,10 +244,10 @@ class QAPISchemaGenTypeVisitor(QAPISchemaVisitor): do_builtins = False (input_file, output_dir, do_c, do_h, prefix, opts) = \ - parse_command_line("b", ["builtins"]) + parse_command_line('b', ['builtins']) for o, a in opts: - if o in ("-b", "--builtins"): + if o in ('-b', '--builtins'): do_builtins = True c_comment = ''' diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py index 330b9f321b..5737aefa05 100644 --- a/scripts/qapi-visit.py +++ b/scripts/qapi-visit.py @@ -13,7 +13,6 @@ # See the COPYING file in the top-level directory. from qapi import * -import re def gen_visit_decl(name, scalar=False): @@ -335,10 +334,10 @@ class QAPISchemaGenVisitVisitor(QAPISchemaVisitor): do_builtins = False (input_file, output_dir, do_c, do_h, prefix, opts) = \ - parse_command_line("b", ["builtins"]) + parse_command_line('b', ['builtins']) for o, a in opts: - if o in ("-b", "--builtins"): + if o in ('-b', '--builtins'): do_builtins = True c_comment = ''' diff --git a/scripts/qapi.py b/scripts/qapi.py index 53a44779d0..e88c047c2e 100644 --- a/scripts/qapi.py +++ b/scripts/qapi.py @@ -11,13 +11,13 @@ # This work is licensed under the terms of the GNU GPL, version 2. # See the COPYING file in the top-level directory. -import re -from ordereddict import OrderedDict import errno import getopt import os -import sys +import re import string +import sys +from ordereddict import OrderedDict builtin_types = { 'str': 'QTYPE_QSTRING', @@ -37,44 +37,18 @@ builtin_types = { 'QType': 'QTYPE_QSTRING', } +# Are documentation comments required? +doc_required = False + # Whitelist of commands allowed to return a non-dictionary -returns_whitelist = [ - # From QMP: - 'human-monitor-command', - 'qom-get', - 'query-migrate-cache-size', - 'query-tpm-models', - 'query-tpm-types', - 'ringbuf-read', - - # From QGA: - 'guest-file-open', - 'guest-fsfreeze-freeze', - 'guest-fsfreeze-freeze-list', - 'guest-fsfreeze-status', - 'guest-fsfreeze-thaw', - 'guest-get-time', - 'guest-set-vcpus', - 'guest-sync', - 'guest-sync-delimited', -] +returns_whitelist = [] # Whitelist of entities allowed to violate case conventions -case_whitelist = [ - # From QMP: - 'ACPISlotType', # DIMM, visible through query-acpi-ospm-status - 'CpuInfoMIPS', # PC, visible through query-cpu - 'CpuInfoTricore', # PC, visible through query-cpu - 'QapiErrorClass', # all members, visible through errors - 'UuidInfo', # UUID, visible through query-uuid - 'X86CPURegister32', # all members, visible indirectly through qom-get - 'q_obj_CpuInfo-base', # CPU, visible through query-cpu -] - -enum_types = [] -struct_types = [] -union_types = [] -events = [] +name_case_whitelist = [] + +enum_types = {} +struct_types = {} +union_types = {} all_names = {} # @@ -83,9 +57,9 @@ all_names = {} def error_path(parent): - res = "" + res = '' while parent: - res = ("In file included from %s:%d:\n" % (parent['file'], + res = ('In file included from %s:%d:\n' % (parent['file'], parent['line'])) + res parent = parent['parent'] return res @@ -101,10 +75,10 @@ class QAPIError(Exception): self.msg = msg def __str__(self): - loc = "%s:%d" % (self.fname, self.line) + loc = '%s:%d' % (self.fname, self.line) if self.col is not None: - loc += ":%s" % self.col - return error_path(self.info) + "%s: %s" % (loc, self.msg) + loc += ':%s' % self.col + return error_path(self.info) + '%s: %s' % (loc, self.msg) class QAPIParseError(QAPIError): @@ -132,15 +106,21 @@ class QAPIDoc(object): self.name = name # the list of lines for this section self.content = [] + self.optional = False def append(self, line): self.content.append(line) def __repr__(self): - return "\n".join(self.content).strip() + return '\n'.join(self.content).strip() class ArgSection(Section): - pass + def __init__(self, name): + QAPIDoc.Section.__init__(self, name) + self.member = None + + def connect(self, member): + self.member = member def __init__(self, parser, info): # self.parser is used to report errors with QAPIParseError. The @@ -157,8 +137,6 @@ class QAPIDoc(object): self.sections = [] # the current section self.section = self.body - # associated expression (to be set by expression parser) - self.expr = None def has_section(self, name): """Return True if we have a section with this name.""" @@ -182,8 +160,8 @@ class QAPIDoc(object): # recognized, and get silently treated as ordinary text if self.symbol: self._append_symbol_line(line) - elif not self.body.content and line.startswith("@"): - if not line.endswith(":"): + elif not self.body.content and line.startswith('@'): + if not line.endswith(':'): raise QAPIParseError(self.parser, "Line should end with :") self.symbol = line[1:-1] # FIXME invalid names other than the empty string aren't flagged @@ -192,17 +170,20 @@ class QAPIDoc(object): else: self._append_freeform(line) + def end_comment(self): + self._end_section() + def _append_symbol_line(self, line): name = line.split(' ', 1)[0] - if name.startswith("@") and name.endswith(":"): + if name.startswith('@') and name.endswith(':'): line = line[len(name)+1:] self._start_args_section(name[1:-1]) - elif name in ("Returns:", "Since:", + elif name in ('Returns:', 'Since:', # those are often singular or plural - "Note:", "Notes:", - "Example:", "Examples:", - "TODO:"): + 'Note:', 'Notes:', + 'Example:', 'Examples:', + 'TODO:'): line = line[len(name)+1:] self._start_section(name[:-1]) @@ -219,16 +200,26 @@ class QAPIDoc(object): raise QAPIParseError(self.parser, "'@%s:' can't follow '%s' section" % (name, self.sections[0].name)) + self._end_section() self.section = QAPIDoc.ArgSection(name) self.args[name] = self.section - def _start_section(self, name=""): - if name in ("Returns", "Since") and self.has_section(name): + def _start_section(self, name=''): + if name in ('Returns', 'Since') and self.has_section(name): raise QAPIParseError(self.parser, "Duplicated '%s' section" % name) + self._end_section() self.section = QAPIDoc.Section(name) self.sections.append(self.section) + def _end_section(self): + if self.section: + contents = str(self.section) + if self.section.name and (not contents or contents.isspace()): + raise QAPIParseError(self.parser, "Empty doc section '%s'" + % self.section.name) + self.section = None + def _append_freeform(self, line): in_arg = isinstance(self.section, QAPIDoc.ArgSection) if (in_arg and self.section.content @@ -236,10 +227,39 @@ class QAPIDoc(object): and line and not line[0].isspace()): self._start_section() if (in_arg or not self.section.name - or not self.section.name.startswith("Example")): + or not self.section.name.startswith('Example')): line = line.strip() + match = re.match(r'(@\S+:)', line) + if match: + raise QAPIParseError(self.parser, + "'%s' not allowed in free-form documentation" + % match.group(1)) + # TODO Drop this once the dust has settled + if (isinstance(self.section, QAPIDoc.ArgSection) + and '#optional' in line): + raise QAPISemError(self.info, "Please drop the #optional tag") self.section.append(line) + def connect_member(self, member): + if member.name not in self.args: + # Undocumented TODO outlaw + self.args[member.name] = QAPIDoc.ArgSection(member.name) + self.args[member.name].connect(member) + + def check_expr(self, expr): + if self.has_section('Returns') and 'command' not in expr: + raise QAPISemError(self.info, + "'Returns:' is only valid for commands") + + def check(self): + bogus = [name for name, section in self.args.iteritems() + if not section.member] + if bogus: + raise QAPISemError( + self.info, + "The following documented members are not in " + "the declaration: %s" % ", ".join(bogus)) + class QAPISchemaParser(object): @@ -257,55 +277,102 @@ class QAPISchemaParser(object): self.line_pos = 0 self.exprs = [] self.docs = [] + self.cur_doc = None self.accept() while self.tok is not None: info = {'file': fname, 'line': self.line, 'parent': self.incl_info} if self.tok == '#': - doc = self.get_doc(info) - self.docs.append(doc) + self.reject_expr_doc() + self.cur_doc = self.get_doc(info) + self.docs.append(self.cur_doc) continue expr = self.get_expr(False) - if isinstance(expr, dict) and "include" in expr: + if 'include' in expr: + self.reject_expr_doc() if len(expr) != 1: raise QAPISemError(info, "Invalid 'include' directive") - include = expr["include"] + include = expr['include'] if not isinstance(include, str): raise QAPISemError(info, "Value of 'include' must be a string") - incl_abs_fname = os.path.join(os.path.dirname(abs_fname), - include) - # catch inclusion cycle - inf = info - while inf: - if incl_abs_fname == os.path.abspath(inf['file']): - raise QAPISemError(info, "Inclusion loop for %s" - % include) - inf = inf['parent'] - - # skip multiple include of the same file - if incl_abs_fname in previously_included: - continue - try: - fobj = open(incl_abs_fname, 'r') - except IOError as e: - raise QAPISemError(info, '%s: %s' % (e.strerror, include)) - exprs_include = QAPISchemaParser(fobj, previously_included, - info) - self.exprs.extend(exprs_include.exprs) - self.docs.extend(exprs_include.docs) + self._include(include, info, os.path.dirname(abs_fname), + previously_included) + elif "pragma" in expr: + self.reject_expr_doc() + if len(expr) != 1: + raise QAPISemError(info, "Invalid 'pragma' directive") + pragma = expr['pragma'] + if not isinstance(pragma, dict): + raise QAPISemError( + info, "Value of 'pragma' must be a dictionary") + for name, value in pragma.iteritems(): + self._pragma(name, value, info) else: expr_elem = {'expr': expr, 'info': info} - if (self.docs - and self.docs[-1].info['file'] == fname - and not self.docs[-1].expr): - self.docs[-1].expr = expr - expr_elem['doc'] = self.docs[-1] - + if self.cur_doc: + if not self.cur_doc.symbol: + raise QAPISemError( + self.cur_doc.info, + "Expression documentation required") + expr_elem['doc'] = self.cur_doc self.exprs.append(expr_elem) + self.cur_doc = None + self.reject_expr_doc() + + def reject_expr_doc(self): + if self.cur_doc and self.cur_doc.symbol: + raise QAPISemError( + self.cur_doc.info, + "Documentation for '%s' is not followed by the definition" + % self.cur_doc.symbol) + + def _include(self, include, info, base_dir, previously_included): + incl_abs_fname = os.path.join(base_dir, include) + # catch inclusion cycle + inf = info + while inf: + if incl_abs_fname == os.path.abspath(inf['file']): + raise QAPISemError(info, "Inclusion loop for %s" % include) + inf = inf['parent'] + + # skip multiple include of the same file + if incl_abs_fname in previously_included: + return + try: + fobj = open(incl_abs_fname, 'r') + except IOError as e: + raise QAPISemError(info, '%s: %s' % (e.strerror, include)) + exprs_include = QAPISchemaParser(fobj, previously_included, info) + self.exprs.extend(exprs_include.exprs) + self.docs.extend(exprs_include.docs) + + def _pragma(self, name, value, info): + global doc_required, returns_whitelist, name_case_whitelist + if name == 'doc-required': + if not isinstance(value, bool): + raise QAPISemError(info, + "Pragma 'doc-required' must be boolean") + doc_required = value + elif name == 'returns-whitelist': + if (not isinstance(value, list) + or any([not isinstance(elt, str) for elt in value])): + raise QAPISemError(info, + "Pragma returns-whitelist must be" + " a list of strings") + returns_whitelist = value + elif name == 'name-case-whitelist': + if (not isinstance(value, list) + or any([not isinstance(elt, str) for elt in value])): + raise QAPISemError(info, + "Pragma name-case-whitelist must be" + " a list of strings") + name_case_whitelist = value + else: + raise QAPISemError(info, "Unknown pragma '%s'" % name) def accept(self, skip_comment=True): while True: @@ -322,7 +389,7 @@ class QAPISchemaParser(object): if not skip_comment: self.val = self.src[self.pos:self.cursor] return - elif self.tok in "{}:,[]": + elif self.tok in '{}:,[]': return elif self.tok == "'": string = '' @@ -348,7 +415,7 @@ class QAPISchemaParser(object): for _ in range(0, 4): ch = self.src[self.cursor] self.cursor += 1 - if ch not in "0123456789abcdefABCDEF": + if ch not in '0123456789abcdefABCDEF': raise QAPIParseError(self, '\\u escape needs 4 ' 'hex digits') @@ -363,28 +430,28 @@ class QAPISchemaParser(object): 'only supports non-zero ' 'values up to \\u007f') string += chr(value) - elif ch in "\\/'\"": + elif ch in '\\/\'"': string += ch else: raise QAPIParseError(self, "Unknown escape \\%s" % ch) esc = False - elif ch == "\\": + elif ch == '\\': esc = True elif ch == "'": self.val = string return else: string += ch - elif self.src.startswith("true", self.pos): + elif self.src.startswith('true', self.pos): self.val = True self.cursor += 3 return - elif self.src.startswith("false", self.pos): + elif self.src.startswith('false', self.pos): self.val = False self.cursor += 4 return - elif self.src.startswith("null", self.pos): + elif self.src.startswith('null', self.pos): self.val = None self.cursor += 3 return @@ -452,7 +519,8 @@ class QAPISchemaParser(object): expr = self.val self.accept() else: - raise QAPIParseError(self, 'Expected "{", "[" or string') + raise QAPIParseError(self, 'Expected "{", "[", string, ' + 'boolean or "null"') return expr def get_doc(self, info): @@ -468,6 +536,7 @@ class QAPISchemaParser(object): if self.val != '##': raise QAPIParseError(self, "Junk after '##' at end of " "documentation comment") + doc.end_comment() self.accept() return doc else: @@ -487,7 +556,7 @@ class QAPISchemaParser(object): def find_base_members(base): if isinstance(base, dict): return base - base_struct_define = find_struct(base) + base_struct_define = struct_types.get(base) if not base_struct_define: return None return base_struct_define['data'] @@ -497,12 +566,12 @@ def find_base_members(base): def find_alternate_member_qtype(qapi_type): if qapi_type in builtin_types: return builtin_types[qapi_type] - elif find_struct(qapi_type): - return "QTYPE_QDICT" - elif find_enum(qapi_type): - return "QTYPE_QSTRING" - elif find_union(qapi_type): - return "QTYPE_QDICT" + elif qapi_type in struct_types: + return 'QTYPE_QDICT' + elif qapi_type in enum_types: + return 'QTYPE_QSTRING' + elif qapi_type in union_types: + return 'QTYPE_QDICT' return None @@ -523,13 +592,13 @@ def discriminator_find_enum_define(expr): if not discriminator_type: return None - return find_enum(discriminator_type) + return enum_types.get(discriminator_type) # Names must be letters, numbers, -, and _. They must start with letter, # except for downstream extensions which must start with __RFQDN_. # Dots are only valid in the downstream extension prefix. -valid_name = re.compile('^(__[a-zA-Z0-9.-]+_)?' +valid_name = re.compile(r'^(__[a-zA-Z0-9.-]+_)?' '[a-zA-Z][a-zA-Z0-9_-]*$') @@ -570,54 +639,6 @@ def add_name(name, info, meta, implicit=False): all_names[name] = meta -def add_struct(definition, info): - global struct_types - name = definition['struct'] - add_name(name, info, 'struct') - struct_types.append(definition) - - -def find_struct(name): - global struct_types - for struct in struct_types: - if struct['struct'] == name: - return struct - return None - - -def add_union(definition, info): - global union_types - name = definition['union'] - add_name(name, info, 'union') - union_types.append(definition) - - -def find_union(name): - global union_types - for union in union_types: - if union['union'] == name: - return union - return None - - -def add_enum(name, info, enum_values=None, implicit=False): - global enum_types - add_name(name, info, 'enum', implicit) - enum_types.append({"enum_name": name, "enum_values": enum_values}) - - -def find_enum(name): - global enum_types - for enum in enum_types: - if enum['enum_name'] == name: - return enum - return None - - -def is_enum(name): - return find_enum(name) is not None - - def check_type(info, source, value, allow_array=False, allow_dict=False, allow_optional=False, allow_metas=[]): @@ -687,14 +708,12 @@ def check_command(expr, info): def check_event(expr, info): - global events name = expr['event'] boxed = expr.get('boxed', False) meta = ['struct'] if boxed: meta += ['union', 'alternate'] - events.append(name) check_type(info, "'data' for event '%s'" % name, expr.get('data'), allow_dict=not boxed, allow_optional=True, allow_metas=meta) @@ -726,7 +745,7 @@ def check_union(expr, info): raise QAPISemError(info, "Flat union '%s' must have a base" % name) base_members = find_base_members(base) - assert base_members + assert base_members is not None # The value of member 'discriminator' must name a non-optional # member of the base struct. @@ -738,7 +757,7 @@ def check_union(expr, info): "Discriminator '%s' is not a member of base " "struct '%s'" % (discriminator, base)) - enum_define = find_enum(discriminator_type) + enum_define = enum_types.get(discriminator_type) allow_metas = ['struct'] # Do not allow string discriminator if not enum_define: @@ -759,15 +778,15 @@ def check_union(expr, info): # If the discriminator names an enum type, then all members # of 'data' must also be members of the enum type. if enum_define: - if key not in enum_define['enum_values']: + if key not in enum_define['data']: raise QAPISemError(info, "Discriminator value '%s' is not found in " "enum '%s'" - % (key, enum_define["enum_name"])) + % (key, enum_define['enum'])) # If discriminator is user-defined, ensure all values are covered if enum_define: - for value in enum_define['enum_values']: + for value in enum_define['data']: if value not in members.keys(): raise QAPISemError(info, "Union '%s' data missing '%s' branch" % (name, value)) @@ -855,56 +874,69 @@ def check_keys(expr_elem, meta, required, optional=[]): def check_exprs(exprs): global all_names - # Learn the types and check for valid expression keys + # Populate name table with names of built-in types for builtin in builtin_types.keys(): all_names[builtin] = 'built-in' + + # Learn the types and check for valid expression keys for expr_elem in exprs: expr = expr_elem['expr'] info = expr_elem['info'] + doc = expr_elem.get('doc') - if 'doc' not in expr_elem: + if not doc and doc_required: raise QAPISemError(info, "Expression missing documentation comment") if 'enum' in expr: + meta = 'enum' check_keys(expr_elem, 'enum', ['data'], ['prefix']) - add_enum(expr['enum'], info, expr['data']) + enum_types[expr[meta]] = expr elif 'union' in expr: + meta = 'union' check_keys(expr_elem, 'union', ['data'], ['base', 'discriminator']) - add_union(expr, info) + union_types[expr[meta]] = expr elif 'alternate' in expr: + meta = 'alternate' check_keys(expr_elem, 'alternate', ['data']) - add_name(expr['alternate'], info, 'alternate') elif 'struct' in expr: + meta = 'struct' check_keys(expr_elem, 'struct', ['data'], ['base']) - add_struct(expr, info) + struct_types[expr[meta]] = expr elif 'command' in expr: + meta = 'command' check_keys(expr_elem, 'command', [], ['data', 'returns', 'gen', 'success-response', 'boxed']) - add_name(expr['command'], info, 'command') elif 'event' in expr: + meta = 'event' check_keys(expr_elem, 'event', [], ['data', 'boxed']) - add_name(expr['event'], info, 'event') else: raise QAPISemError(expr_elem['info'], "Expression is missing metatype") + name = expr[meta] + add_name(name, info, meta) + if doc and doc.symbol != name: + raise QAPISemError(info, "Definition of '%s' follows documentation" + " for '%s'" % (name, doc.symbol)) # Try again for hidden UnionKind enum for expr_elem in exprs: expr = expr_elem['expr'] - if 'union' in expr: - if not discriminator_find_enum_define(expr): - add_enum('%sKind' % expr['union'], expr_elem['info'], - implicit=True) + if 'union' in expr and not discriminator_find_enum_define(expr): + name = '%sKind' % expr['union'] elif 'alternate' in expr: - add_enum('%sKind' % expr['alternate'], expr_elem['info'], - implicit=True) + name = '%sKind' % expr['alternate'] + else: + continue + enum_types[name] = {'enum': name} + add_name(name, info, 'enum', implicit=True) # Validate that exprs make sense for expr_elem in exprs: expr = expr_elem['expr'] info = expr_elem['info'] + doc = expr_elem.get('doc') if 'enum' in expr: check_enum(expr, info) @@ -921,89 +953,10 @@ def check_exprs(exprs): else: assert False, 'unexpected meta type' - return exprs - - -def check_freeform_doc(doc): - if doc.symbol: - raise QAPISemError(doc.info, - "Documention for '%s' is not followed" - " by the definition" % doc.symbol) - - body = str(doc.body) - if re.search(r'@\S+:', body, re.MULTILINE): - raise QAPISemError(doc.info, - "Free-form documentation block must not contain" - " @NAME: sections") - + if doc: + doc.check_expr(expr) -def check_definition_doc(doc, expr, info): - for i in ('enum', 'union', 'alternate', 'struct', 'command', 'event'): - if i in expr: - meta = i - break - - name = expr[meta] - if doc.symbol != name: - raise QAPISemError(info, "Definition of '%s' follows documentation" - " for '%s'" % (name, doc.symbol)) - if doc.has_section('Returns') and 'command' not in expr: - raise QAPISemError(info, "'Returns:' is only valid for commands") - - if meta == 'union': - args = expr.get('base', []) - else: - args = expr.get('data', []) - if isinstance(args, str): - return - if isinstance(args, dict): - args = args.keys() - assert isinstance(args, list) - - if (meta == 'alternate' - or (meta == 'union' and not expr.get('discriminator'))): - args.append('type') - - for arg in args: - if arg[0] == '*': - opt = True - desc = doc.args.get(arg[1:]) - else: - opt = False - desc = doc.args.get(arg) - if not desc: - continue - desc_opt = "#optional" in str(desc) - if desc_opt and not opt: - raise QAPISemError(info, "Description has #optional, " - "but the declaration doesn't") - if not desc_opt and opt: - # silently fix the doc - # TODO either fix the schema and make this an error, - # or drop #optional entirely - desc.append("#optional") - - doc_args = set(doc.args.keys()) - args = set([name.strip('*') for name in args]) - if not doc_args.issubset(args): - raise QAPISemError(info, "The following documented members are not in " - "the declaration: %s" % ", ".join(doc_args - args)) - - -def check_docs(docs): - for doc in docs: - for section in doc.args.values() + doc.sections: - content = str(section) - if not content or content.isspace(): - raise QAPISemError(doc.info, - "Empty doc section '%s'" % section.name) - - if not doc.expr: - check_freeform_doc(doc) - else: - check_definition_doc(doc, doc.expr, doc.info) - - return docs + return exprs # @@ -1011,7 +964,7 @@ def check_docs(docs): # class QAPISchemaEntity(object): - def __init__(self, name, info): + def __init__(self, name, info, doc): assert isinstance(name, str) self.name = name # For explicitly defined entities, info points to the (explicit) @@ -1020,6 +973,7 @@ class QAPISchemaEntity(object): # triggered the implicit definition (there may be more than one # such place). self.info = info + self.doc = doc def c_name(self): return c_name(self.name) @@ -1098,10 +1052,15 @@ class QAPISchemaType(QAPISchemaEntity): } return json2qtype.get(self.json_type()) + def doc_type(self): + if self.is_implicit(): + return None + return self.name + class QAPISchemaBuiltinType(QAPISchemaType): def __init__(self, name, json_type, c_type): - QAPISchemaType.__init__(self, name, None) + QAPISchemaType.__init__(self, name, None, None) assert not c_type or isinstance(c_type, str) assert json_type in ('string', 'number', 'int', 'boolean', 'null', 'value') @@ -1122,13 +1081,16 @@ class QAPISchemaBuiltinType(QAPISchemaType): def json_type(self): return self._json_type_name + def doc_type(self): + return self.json_type() + def visit(self, visitor): visitor.visit_builtin_type(self.name, self.info, self.json_type()) class QAPISchemaEnumType(QAPISchemaType): - def __init__(self, name, info, values, prefix): - QAPISchemaType.__init__(self, name, info) + def __init__(self, name, info, doc, values, prefix): + QAPISchemaType.__init__(self, name, info, doc) for v in values: assert isinstance(v, QAPISchemaMember) v.set_owner(name) @@ -1140,10 +1102,12 @@ class QAPISchemaEnumType(QAPISchemaType): seen = {} for v in self.values: v.check_clash(self.info, seen) + if self.doc: + self.doc.connect_member(v) def is_implicit(self): - # See QAPISchema._make_implicit_enum_type() - return self.name.endswith('Kind') + # See QAPISchema._make_implicit_enum_type() and ._def_predefineds() + return self.name.endswith('Kind') or self.name == 'QType' def c_type(self): return c_name(self.name) @@ -1161,7 +1125,7 @@ class QAPISchemaEnumType(QAPISchemaType): class QAPISchemaArrayType(QAPISchemaType): def __init__(self, name, info, element_type): - QAPISchemaType.__init__(self, name, info) + QAPISchemaType.__init__(self, name, info, None) assert isinstance(element_type, str) self._element_type_name = element_type self.element_type = None @@ -1179,16 +1143,22 @@ class QAPISchemaArrayType(QAPISchemaType): def json_type(self): return 'array' + def doc_type(self): + elt_doc_type = self.element_type.doc_type() + if not elt_doc_type: + return None + return 'array of ' + elt_doc_type + def visit(self, visitor): visitor.visit_array_type(self.name, self.info, self.element_type) class QAPISchemaObjectType(QAPISchemaType): - def __init__(self, name, info, base, local_members, variants): + def __init__(self, name, info, doc, base, local_members, variants): # struct has local_members, optional base, and no variants # flat union has base, variants, and no local_members # simple union has local_members, variants, and no base - QAPISchemaType.__init__(self, name, info) + QAPISchemaType.__init__(self, name, info, doc) assert base is None or isinstance(base, str) for m in local_members: assert isinstance(m, QAPISchemaObjectTypeMember) @@ -1214,20 +1184,24 @@ class QAPISchemaObjectType(QAPISchemaType): self.base = schema.lookup_type(self._base_name) assert isinstance(self.base, QAPISchemaObjectType) self.base.check(schema) - self.base.check_clash(schema, self.info, seen) + self.base.check_clash(self.info, seen) for m in self.local_members: m.check(schema) m.check_clash(self.info, seen) + if self.doc: + self.doc.connect_member(m) self.members = seen.values() if self.variants: self.variants.check(schema, seen) assert self.variants.tag_member in self.members - self.variants.check_clash(schema, self.info, seen) + self.variants.check_clash(self.info, seen) + if self.doc: + self.doc.check() # Check that the members of this type do not cause duplicate JSON members, # and update seen to track the members seen so far. Report any errors # on behalf of info, which is not necessarily self.info - def check_clash(self, schema, info, seen): + def check_clash(self, info, seen): assert not self.variants # not implemented for m in self.members: m.check_clash(info, seen) @@ -1276,7 +1250,7 @@ class QAPISchemaMember(object): def check_clash(self, info, seen): cname = c_name(self.name) - if cname.lower() != cname and self.owner not in case_whitelist: + if cname.lower() != cname and self.owner not in name_case_whitelist: raise QAPISemError(info, "%s should not use uppercase" % self.describe()) if cname in seen: @@ -1356,12 +1330,12 @@ class QAPISchemaObjectTypeVariants(object): assert isinstance(v.type, QAPISchemaObjectType) v.type.check(schema) - def check_clash(self, schema, info, seen): + def check_clash(self, info, seen): for v in self.variants: # Reset seen map for each variant, since qapi names from one # branch do not affect another branch assert isinstance(v.type, QAPISchemaObjectType) - v.type.check_clash(schema, info, dict(seen)) + v.type.check_clash(info, dict(seen)) class QAPISchemaObjectTypeVariant(QAPISchemaObjectTypeMember): @@ -1372,8 +1346,8 @@ class QAPISchemaObjectTypeVariant(QAPISchemaObjectTypeMember): class QAPISchemaAlternateType(QAPISchemaType): - def __init__(self, name, info, variants): - QAPISchemaType.__init__(self, name, info) + def __init__(self, name, info, doc, variants): + QAPISchemaType.__init__(self, name, info, doc) assert isinstance(variants, QAPISchemaObjectTypeVariants) assert variants.tag_member variants.set_owner(name) @@ -1390,6 +1364,10 @@ class QAPISchemaAlternateType(QAPISchemaType): seen = {} for v in self.variants.variants: v.check_clash(self.info, seen) + if self.doc: + self.doc.connect_member(v) + if self.doc: + self.doc.check() def c_type(self): return c_name(self.name) + pointer_suffix @@ -1405,9 +1383,9 @@ class QAPISchemaAlternateType(QAPISchemaType): class QAPISchemaCommand(QAPISchemaEntity): - def __init__(self, name, info, arg_type, ret_type, gen, success_response, - boxed): - QAPISchemaEntity.__init__(self, name, info) + def __init__(self, name, info, doc, arg_type, ret_type, + gen, success_response, boxed): + QAPISchemaEntity.__init__(self, name, info, doc) assert not arg_type or isinstance(arg_type, str) assert not ret_type or isinstance(ret_type, str) self._arg_type_name = arg_type @@ -1444,8 +1422,8 @@ class QAPISchemaCommand(QAPISchemaEntity): class QAPISchemaEvent(QAPISchemaEntity): - def __init__(self, name, info, arg_type, boxed): - QAPISchemaEntity.__init__(self, name, info) + def __init__(self, name, info, doc, arg_type, boxed): + QAPISchemaEntity.__init__(self, name, info, doc) assert not arg_type or isinstance(arg_type, str) self._arg_type_name = arg_type self.arg_type = None @@ -1474,9 +1452,9 @@ class QAPISchemaEvent(QAPISchemaEntity): class QAPISchema(object): def __init__(self, fname): try: - parser = QAPISchemaParser(open(fname, "r")) + parser = QAPISchemaParser(open(fname, 'r')) self.exprs = check_exprs(parser.exprs) - self.docs = check_docs(parser.docs) + self.docs = parser.docs self._entity_dict = {} self._predefining = True self._def_predefineds() @@ -1527,14 +1505,14 @@ class QAPISchema(object): ('bool', 'boolean', 'bool'), ('any', 'value', 'QObject' + pointer_suffix)]: self._def_builtin_type(*t) - self.the_empty_object_type = QAPISchemaObjectType('q_empty', None, - None, [], None) + self.the_empty_object_type = QAPISchemaObjectType( + 'q_empty', None, None, None, [], None) self._def_entity(self.the_empty_object_type) qtype_values = self._make_enum_members(['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']) - self._def_entity(QAPISchemaEnumType('QType', None, qtype_values, - 'QTYPE')) + self._def_entity(QAPISchemaEnumType('QType', None, None, + qtype_values, 'QTYPE')) def _make_enum_members(self, values): return [QAPISchemaMember(v) for v in values] @@ -1543,7 +1521,7 @@ class QAPISchema(object): # See also QAPISchemaObjectTypeMember._pretty_owner() name = name + 'Kind' # Use namespace reserved by add_name() self._def_entity(QAPISchemaEnumType( - name, info, self._make_enum_members(values), None)) + name, info, None, self._make_enum_members(values), None)) return name def _make_array_type(self, element_type, info): @@ -1552,22 +1530,22 @@ class QAPISchema(object): self._def_entity(QAPISchemaArrayType(name, info, element_type)) return name - def _make_implicit_object_type(self, name, info, role, members): + def _make_implicit_object_type(self, name, info, doc, role, members): if not members: return None # See also QAPISchemaObjectTypeMember._pretty_owner() name = 'q_obj_%s-%s' % (name, role) if not self.lookup_entity(name, QAPISchemaObjectType): - self._def_entity(QAPISchemaObjectType(name, info, None, + self._def_entity(QAPISchemaObjectType(name, info, doc, None, members, None)) return name - def _def_enum_type(self, expr, info): + def _def_enum_type(self, expr, info, doc): name = expr['enum'] data = expr['data'] prefix = expr.get('prefix') self._def_entity(QAPISchemaEnumType( - name, info, self._make_enum_members(data), prefix)) + name, info, doc, self._make_enum_members(data), prefix)) def _make_member(self, name, typ, info): optional = False @@ -1583,11 +1561,11 @@ class QAPISchema(object): return [self._make_member(key, value, info) for (key, value) in data.iteritems()] - def _def_struct_type(self, expr, info): + def _def_struct_type(self, expr, info, doc): name = expr['struct'] base = expr.get('base') data = expr['data'] - self._def_entity(QAPISchemaObjectType(name, info, base, + self._def_entity(QAPISchemaObjectType(name, info, doc, base, self._make_members(data, info), None)) @@ -1599,10 +1577,10 @@ class QAPISchema(object): assert len(typ) == 1 typ = self._make_array_type(typ[0], info) typ = self._make_implicit_object_type( - typ, info, 'wrapper', [self._make_member('data', typ, info)]) + typ, info, None, 'wrapper', [self._make_member('data', typ, info)]) return QAPISchemaObjectTypeVariant(case, typ) - def _def_union_type(self, expr, info): + def _def_union_type(self, expr, info, doc): name = expr['union'] data = expr['data'] base = expr.get('base') @@ -1610,7 +1588,7 @@ class QAPISchema(object): tag_member = None if isinstance(base, dict): base = (self._make_implicit_object_type( - name, info, 'base', self._make_members(base, info))) + name, info, doc, 'base', self._make_members(base, info))) if tag_name: variants = [self._make_variant(key, value) for (key, value) in data.iteritems()] @@ -1623,24 +1601,24 @@ class QAPISchema(object): tag_member = QAPISchemaObjectTypeMember('type', typ, False) members = [tag_member] self._def_entity( - QAPISchemaObjectType(name, info, base, members, + QAPISchemaObjectType(name, info, doc, base, members, QAPISchemaObjectTypeVariants(tag_name, tag_member, variants))) - def _def_alternate_type(self, expr, info): + def _def_alternate_type(self, expr, info, doc): name = expr['alternate'] data = expr['data'] variants = [self._make_variant(key, value) for (key, value) in data.iteritems()] tag_member = QAPISchemaObjectTypeMember('type', 'QType', False) self._def_entity( - QAPISchemaAlternateType(name, info, + QAPISchemaAlternateType(name, info, doc, QAPISchemaObjectTypeVariants(None, tag_member, variants))) - def _def_command(self, expr, info): + def _def_command(self, expr, info, doc): name = expr['command'] data = expr.get('data') rets = expr.get('returns') @@ -1649,38 +1627,39 @@ class QAPISchema(object): boxed = expr.get('boxed', False) if isinstance(data, OrderedDict): data = self._make_implicit_object_type( - name, info, 'arg', self._make_members(data, info)) + name, info, doc, 'arg', self._make_members(data, info)) if isinstance(rets, list): assert len(rets) == 1 rets = self._make_array_type(rets[0], info) - self._def_entity(QAPISchemaCommand(name, info, data, rets, gen, - success_response, boxed)) + self._def_entity(QAPISchemaCommand(name, info, doc, data, rets, + gen, success_response, boxed)) - def _def_event(self, expr, info): + def _def_event(self, expr, info, doc): name = expr['event'] data = expr.get('data') boxed = expr.get('boxed', False) if isinstance(data, OrderedDict): data = self._make_implicit_object_type( - name, info, 'arg', self._make_members(data, info)) - self._def_entity(QAPISchemaEvent(name, info, data, boxed)) + name, info, doc, 'arg', self._make_members(data, info)) + self._def_entity(QAPISchemaEvent(name, info, doc, data, boxed)) def _def_exprs(self): for expr_elem in self.exprs: expr = expr_elem['expr'] info = expr_elem['info'] + doc = expr_elem.get('doc') if 'enum' in expr: - self._def_enum_type(expr, info) + self._def_enum_type(expr, info, doc) elif 'struct' in expr: - self._def_struct_type(expr, info) + self._def_struct_type(expr, info, doc) elif 'union' in expr: - self._def_union_type(expr, info) + self._def_union_type(expr, info, doc) elif 'alternate' in expr: - self._def_alternate_type(expr, info) + self._def_alternate_type(expr, info, doc) elif 'command' in expr: - self._def_command(expr, info) + self._def_command(expr, info, doc) elif 'event' in expr: - self._def_event(expr, info) + self._def_event(expr, info, doc) else: assert False @@ -1726,8 +1705,8 @@ def camel_to_upper(value): l = len(c_fun_str) for i in range(l): c = c_fun_str[i] - # When c is upper and no "_" appears before, do more checks - if c.isupper() and (i > 0) and c_fun_str[i - 1] != "_": + # When c is upper and no '_' appears before, do more checks + if c.isupper() and (i > 0) and c_fun_str[i - 1] != '_': if i < l - 1 and c_fun_str[i + 1].islower(): new_name += '_' elif c_fun_str[i - 1].isdigit(): @@ -1746,7 +1725,7 @@ c_name_trans = string.maketrans('.-', '__') # Map @name to a valid C identifier. # If @protect, avoid returning certain ticklish identifiers (like -# C keywords) by prepending "q_". +# C keywords) by prepending 'q_'. # # Used for converting 'name' from a 'name':'type' qapi definition # into a generated struct member, as well as converting type names @@ -1784,7 +1763,7 @@ def c_name(name, protect=True): name = name.translate(c_name_trans) if protect and (name in c89_words | c99_words | c11_words | gcc_words | cpp_words | polluted_words): - return "q_" + name + return 'q_' + name return name eatspace = '\033EATSPACE.' @@ -1792,9 +1771,9 @@ pointer_suffix = ' *' + eatspace def genindent(count): - ret = "" + ret = '' for _ in range(count): - ret += " " + ret += ' ' return ret indent_level = 0 @@ -1817,10 +1796,10 @@ def cgen(code, **kwds): if indent_level: indent = genindent(indent_level) # re.subn() lacks flags support before Python 2.7, use re.compile() - raw = re.subn(re.compile("^.", re.MULTILINE), + raw = re.subn(re.compile(r'^.', re.MULTILINE), indent + r'\g<0>', raw) raw = raw[0] - return re.sub(re.escape(eatspace) + ' *', '', raw) + return re.sub(re.escape(eatspace) + r' *', '', raw) def mcgen(code, **kwds): @@ -1934,38 +1913,38 @@ def gen_params(arg_type, boxed, extra): # -def parse_command_line(extra_options="", extra_long_options=[]): +def parse_command_line(extra_options='', extra_long_options=[]): try: opts, args = getopt.gnu_getopt(sys.argv[1:], - "chp:o:" + extra_options, - ["source", "header", "prefix=", - "output-dir="] + extra_long_options) + 'chp:o:' + extra_options, + ['source', 'header', 'prefix=', + 'output-dir='] + extra_long_options) except getopt.GetoptError as err: print >>sys.stderr, "%s: %s" % (sys.argv[0], str(err)) sys.exit(1) - output_dir = "" - prefix = "" + output_dir = '' + prefix = '' do_c = False do_h = False extra_opts = [] for oa in opts: o, a = oa - if o in ("-p", "--prefix"): - match = re.match('([A-Za-z_.-][A-Za-z0-9_.-]*)?', a) + if o in ('-p', '--prefix'): + match = re.match(r'([A-Za-z_.-][A-Za-z0-9_.-]*)?', a) if match.end() != len(a): print >>sys.stderr, \ "%s: 'funny character '%s' in argument of --prefix" \ % (sys.argv[0], a[match.end()]) sys.exit(1) prefix = a - elif o in ("-o", "--output-dir"): - output_dir = a + "/" - elif o in ("-c", "--source"): + elif o in ('-o', '--output-dir'): + output_dir = a + '/' + elif o in ('-c', '--source'): do_c = True - elif o in ("-h", "--header"): + elif o in ('-h', '--header'): do_h = True else: extra_opts.append(oa) diff --git a/scripts/qapi2texi.py b/scripts/qapi2texi.py index c1071c62c6..8eed11a60c 100755 --- a/scripts/qapi2texi.py +++ b/scripts/qapi2texi.py @@ -9,7 +9,7 @@ import sys import qapi -COMMAND_FMT = """ +MSG_FMT = """ @deftypefn {type} {{}} {name} {body} @@ -18,16 +18,7 @@ COMMAND_FMT = """ """.format -ENUM_FMT = """ -@deftp Enum {name} - -{body} - -@end deftp - -""".format - -STRUCT_FMT = """ +TYPE_FMT = """ @deftp {{{type}}} {name} {body} @@ -59,7 +50,7 @@ def subst_vars(doc): def subst_braces(doc): """Replaces {} with @{ @}""" - return doc.replace("{", "@{").replace("}", "@}") + return doc.replace('{', '@{').replace('}', '@}') def texi_example(doc): @@ -88,10 +79,10 @@ def texi_format(doc): doc = subst_vars(doc) doc = subst_emph(doc) doc = subst_strong(doc) - inlist = "" + inlist = '' lastempty = False for line in doc.split('\n'): - empty = line == "" + empty = line == '' # FIXME: Doing this in a single if / elif chain is # problematic. For instance, a line without markup terminates @@ -101,158 +92,194 @@ def texi_format(doc): # # Make sure to update section "Documentation markup" in # docs/qapi-code-gen.txt when fixing this. - if line.startswith("| "): + if line.startswith('| '): line = EXAMPLE_FMT(code=line[2:]) - elif line.startswith("= "): - line = "@section " + line[2:] - elif line.startswith("== "): - line = "@subsection " + line[3:] + elif line.startswith('= '): + line = '@section ' + line[2:] + elif line.startswith('== '): + line = '@subsection ' + line[3:] elif re.match(r'^([0-9]*\.) ', line): if not inlist: - lines.append("@enumerate") - inlist = "enumerate" - line = line[line.find(" ")+1:] - lines.append("@item") + lines.append('@enumerate') + inlist = 'enumerate' + line = line[line.find(' ')+1:] + lines.append('@item') elif re.match(r'^[*-] ', line): if not inlist: - lines.append("@itemize %s" % {'*': "@bullet", - '-': "@minus"}[line[0]]) - inlist = "itemize" - lines.append("@item") + lines.append('@itemize %s' % {'*': '@bullet', + '-': '@minus'}[line[0]]) + inlist = 'itemize' + lines.append('@item') line = line[2:] elif lastempty and inlist: - lines.append("@end %s\n" % inlist) - inlist = "" + lines.append('@end %s\n' % inlist) + inlist = '' lastempty = empty lines.append(line) if inlist: - lines.append("@end %s\n" % inlist) - return "\n".join(lines) + lines.append('@end %s\n' % inlist) + return '\n'.join(lines) def texi_body(doc): - """ - Format the body of a symbol documentation: - - main body - - table of arguments - - followed by "Returns/Notes/Since/Example" sections - """ - body = texi_format(str(doc.body)) + "\n" - if doc.args: - body += "@table @asis\n" - for arg, section in doc.args.iteritems(): - desc = str(section) - opt = '' - if "#optional" in desc: - desc = desc.replace("#optional", "") - opt = ' (optional)' - body += "@item @code{'%s'}%s\n%s\n" % (arg, opt, - texi_format(desc)) - body += "@end table\n" - + """Format the main documentation body""" + return texi_format(str(doc.body)) + '\n' + + +def texi_enum_value(value): + """Format a table of members item for an enumeration value""" + return '@item @code{%s}\n' % value.name + + +def texi_member(member, suffix=''): + """Format a table of members item for an object type member""" + typ = member.type.doc_type() + return '@item @code{%s%s%s}%s%s\n' % ( + member.name, + ': ' if typ else '', + typ if typ else '', + ' (optional)' if member.optional else '', + suffix) + + +def texi_members(doc, what, base, variants, member_func): + """Format the table of members""" + items = '' + for section in doc.args.itervalues(): + # TODO Drop fallbacks when undocumented members are outlawed + if section.content: + desc = texi_format(str(section)) + elif (variants and variants.tag_member == section.member + and not section.member.type.doc_type()): + values = section.member.type.member_names() + desc = 'One of ' + ', '.join(['@t{"%s"}' % v for v in values]) + else: + desc = 'Not documented' + items += member_func(section.member) + desc + '\n' + if base: + items += '@item The members of @code{%s}\n' % base.doc_type() + if variants: + for v in variants.variants: + when = ' when @code{%s} is @t{"%s"}' % ( + variants.tag_member.name, v.name) + if v.type.is_implicit(): + assert not v.type.base and not v.type.variants + for m in v.type.local_members: + items += member_func(m, when) + else: + items += '@item The members of @code{%s}%s\n' % ( + v.type.doc_type(), when) + if not items: + return '' + return '\n@b{%s:}\n@table @asis\n%s@end table\n' % (what, items) + + +def texi_sections(doc): + """Format additional sections following arguments""" + body = '' for section in doc.sections: name, doc = (section.name, str(section)) func = texi_format - if name.startswith("Example"): + if name.startswith('Example'): func = texi_example if name: # prefer @b over @strong, so txt doesn't translate it to *Foo:* - body += "\n\n@b{%s:}\n" % name + body += '\n\n@b{%s:}\n' % name body += func(doc) - return body -def texi_alternate(expr, doc): - """Format an alternate to texi""" - body = texi_body(doc) - return STRUCT_FMT(type="Alternate", - name=doc.symbol, - body=body) - - -def texi_union(expr, doc): - """Format a union to texi""" - discriminator = expr.get("discriminator") - if discriminator: - union = "Flat Union" - else: - union = "Simple Union" - - body = texi_body(doc) - return STRUCT_FMT(type=union, - name=doc.symbol, - body=body) - - -def texi_enum(expr, doc): - """Format an enum to texi""" - for i in expr['data']: - if i not in doc.args: - doc.args[i] = '' - body = texi_body(doc) - return ENUM_FMT(name=doc.symbol, - body=body) - - -def texi_struct(expr, doc): - """Format a struct to texi""" - body = texi_body(doc) - return STRUCT_FMT(type="Struct", - name=doc.symbol, - body=body) - - -def texi_command(expr, doc): - """Format a command to texi""" - body = texi_body(doc) - return COMMAND_FMT(type="Command", - name=doc.symbol, - body=body) - - -def texi_event(expr, doc): - """Format an event to texi""" - body = texi_body(doc) - return COMMAND_FMT(type="Event", - name=doc.symbol, - body=body) - - -def texi_expr(expr, doc): - """Format an expr to texi""" - (kind, _) = expr.items()[0] - - fmt = {"command": texi_command, - "struct": texi_struct, - "enum": texi_enum, - "union": texi_union, - "alternate": texi_alternate, - "event": texi_event}[kind] - - return fmt(expr, doc) - - -def texi(docs): - """Convert QAPI schema expressions to texi documentation""" - res = [] - for doc in docs: - expr = doc.expr - if not expr: - res.append(texi_body(doc)) - continue - try: - doc = texi_expr(expr, doc) - res.append(doc) - except: - print >>sys.stderr, "error at @%s" % doc.info - raise - - return '\n'.join(res) +def texi_entity(doc, what, base=None, variants=None, + member_func=texi_member): + return (texi_body(doc) + + texi_members(doc, what, base, variants, member_func) + + texi_sections(doc)) + + +class QAPISchemaGenDocVisitor(qapi.QAPISchemaVisitor): + def __init__(self): + self.out = None + self.cur_doc = None + + def visit_begin(self, schema): + self.out = '' + + def visit_enum_type(self, name, info, values, prefix): + doc = self.cur_doc + if self.out: + self.out += '\n' + self.out += TYPE_FMT(type='Enum', + name=doc.symbol, + body=texi_entity(doc, 'Values', + member_func=texi_enum_value)) + + def visit_object_type(self, name, info, base, members, variants): + doc = self.cur_doc + if base and base.is_implicit(): + base = None + if self.out: + self.out += '\n' + self.out += TYPE_FMT(type='Object', + name=doc.symbol, + body=texi_entity(doc, 'Members', base, variants)) + + def visit_alternate_type(self, name, info, variants): + doc = self.cur_doc + if self.out: + self.out += '\n' + self.out += TYPE_FMT(type='Alternate', + name=doc.symbol, + body=texi_entity(doc, 'Members')) + + def visit_command(self, name, info, arg_type, ret_type, + gen, success_response, boxed): + doc = self.cur_doc + if self.out: + self.out += '\n' + if boxed: + body = texi_body(doc) + body += '\n@b{Arguments:} the members of @code{%s}' % arg_type.name + body += texi_sections(doc) + else: + body = texi_entity(doc, 'Arguments') + self.out += MSG_FMT(type='Command', + name=doc.symbol, + body=body) + + def visit_event(self, name, info, arg_type, boxed): + doc = self.cur_doc + if self.out: + self.out += '\n' + self.out += MSG_FMT(type='Event', + name=doc.symbol, + body=texi_entity(doc, 'Arguments')) + + def symbol(self, doc, entity): + self.cur_doc = doc + entity.visit(self) + self.cur_doc = None + + def freeform(self, doc): + assert not doc.args + if self.out: + self.out += '\n' + self.out += texi_body(doc) + texi_sections(doc) + + +def texi_schema(schema): + """Convert QAPI schema documentation to Texinfo""" + gen = QAPISchemaGenDocVisitor() + gen.visit_begin(schema) + for doc in schema.docs: + if doc.symbol: + gen.symbol(doc, schema.lookup_entity(doc.symbol)) + else: + gen.freeform(doc) + return gen.out def main(argv): @@ -262,8 +289,11 @@ def main(argv): sys.exit(1) schema = qapi.QAPISchema(argv[1]) - print texi(schema.docs) + if not qapi.doc_required: + print >>sys.stderr, ("%s: need pragma 'doc-required' " + "to generate documentation" % argv[0]) + print texi_schema(schema) -if __name__ == "__main__": +if __name__ == '__main__': main(sys.argv) diff --git a/scripts/qmp/qmp-shell b/scripts/qmp/qmp-shell index 0373b24b20..eccb88a4e8 100755 --- a/scripts/qmp/qmp-shell +++ b/scripts/qmp/qmp-shell @@ -166,8 +166,8 @@ class QMPShell(qmp.QEMUMonitorProtocol): def __cli_expr(self, tokens, parent): for arg in tokens: - (key, _, val) = arg.partition('=') - if not val: + (key, sep, val) = arg.partition('=') + if sep != '=': raise QMPShellError("Expected a key=value pair, got '%s'" % arg) value = self.__parse_value(val) diff --git a/stubs/cpu-get-icount.c b/stubs/cpu-get-icount.c index 2e8b63b225..0b7239d721 100644 --- a/stubs/cpu-get-icount.c +++ b/stubs/cpu-get-icount.c @@ -2,6 +2,7 @@ #include "qemu-common.h" #include "qemu/timer.h" #include "sysemu/cpus.h" +#include "qemu/main-loop.h" int use_icount; @@ -9,3 +10,8 @@ int64_t cpu_get_icount(void) { abort(); } + +void qemu_timer_notify_cb(void *opaque, QEMUClockType type) +{ + qemu_notify_event(); +} diff --git a/target/alpha/translate.c b/target/alpha/translate.c index 055286a7b8..df5d695344 100644 --- a/target/alpha/translate.c +++ b/target/alpha/translate.c @@ -19,6 +19,7 @@ #include "qemu/osdep.h" #include "cpu.h" +#include "sysemu/cpus.h" #include "disas/disas.h" #include "qemu/host-utils.h" #include "exec/exec-all.h" diff --git a/target/arm/cpu.h b/target/arm/cpu.h index 25ceaabb5d..a8aabce7dd 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -536,8 +536,8 @@ typedef void ARMELChangeHook(ARMCPU *cpu, void *opaque); /* These values map onto the return values for * QEMU_PSCI_0_2_FN_AFFINITY_INFO */ typedef enum ARMPSCIState { - PSCI_OFF = 0, - PSCI_ON = 1, + PSCI_ON = 0, + PSCI_OFF = 1, PSCI_ON_PENDING = 2 } ARMPSCIState; diff --git a/target/arm/helper.c b/target/arm/helper.c index 3f4211b572..8646a7a119 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -885,7 +885,7 @@ static CPAccessResult pmreg_access(CPUARMState *env, const ARMCPRegInfo *ri, */ int el = arm_current_el(env); - if (el == 0 && !env->cp15.c9_pmuserenr) { + if (el == 0 && !(env->cp15.c9_pmuserenr & 1)) { return CP_ACCESS_TRAP; } if (el < 2 && (env->cp15.mdcr_el2 & MDCR_TPM) @@ -899,8 +899,67 @@ static CPAccessResult pmreg_access(CPUARMState *env, const ARMCPRegInfo *ri, return CP_ACCESS_OK; } +static CPAccessResult pmreg_access_xevcntr(CPUARMState *env, + const ARMCPRegInfo *ri, + bool isread) +{ + /* ER: event counter read trap control */ + if (arm_feature(env, ARM_FEATURE_V8) + && arm_current_el(env) == 0 + && (env->cp15.c9_pmuserenr & (1 << 3)) != 0 + && isread) { + return CP_ACCESS_OK; + } + + return pmreg_access(env, ri, isread); +} + +static CPAccessResult pmreg_access_swinc(CPUARMState *env, + const ARMCPRegInfo *ri, + bool isread) +{ + /* SW: software increment write trap control */ + if (arm_feature(env, ARM_FEATURE_V8) + && arm_current_el(env) == 0 + && (env->cp15.c9_pmuserenr & (1 << 1)) != 0 + && !isread) { + return CP_ACCESS_OK; + } + + return pmreg_access(env, ri, isread); +} + #ifndef CONFIG_USER_ONLY +static CPAccessResult pmreg_access_selr(CPUARMState *env, + const ARMCPRegInfo *ri, + bool isread) +{ + /* ER: event counter read trap control */ + if (arm_feature(env, ARM_FEATURE_V8) + && arm_current_el(env) == 0 + && (env->cp15.c9_pmuserenr & (1 << 3)) != 0) { + return CP_ACCESS_OK; + } + + return pmreg_access(env, ri, isread); +} + +static CPAccessResult pmreg_access_ccntr(CPUARMState *env, + const ARMCPRegInfo *ri, + bool isread) +{ + /* CR: cycle counter read trap control */ + if (arm_feature(env, ARM_FEATURE_V8) + && arm_current_el(env) == 0 + && (env->cp15.c9_pmuserenr & (1 << 2)) != 0 + && isread) { + return CP_ACCESS_OK; + } + + return pmreg_access(env, ri, isread); +} + static inline bool arm_ccnt_enabled(CPUARMState *env) { /* This does not support checking PMCCFILTR_EL0 register */ @@ -1068,7 +1127,11 @@ static uint64_t pmxevtyper_read(CPUARMState *env, const ARMCPRegInfo *ri) static void pmuserenr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) { - env->cp15.c9_pmuserenr = value & 1; + if (arm_feature(env, ARM_FEATURE_V8)) { + env->cp15.c9_pmuserenr = value & 0xf; + } else { + env->cp15.c9_pmuserenr = value & 1; + } } static void pmintenset_write(CPUARMState *env, const ARMCPRegInfo *ri, @@ -1212,25 +1275,25 @@ static const ARMCPRegInfo v7_cp_reginfo[] = { .raw_writefn = raw_write }, /* Unimplemented so WI. */ { .name = "PMSWINC", .cp = 15, .crn = 9, .crm = 12, .opc1 = 0, .opc2 = 4, - .access = PL0_W, .accessfn = pmreg_access, .type = ARM_CP_NOP }, + .access = PL0_W, .accessfn = pmreg_access_swinc, .type = ARM_CP_NOP }, #ifndef CONFIG_USER_ONLY { .name = "PMSELR", .cp = 15, .crn = 9, .crm = 12, .opc1 = 0, .opc2 = 5, .access = PL0_RW, .type = ARM_CP_ALIAS, .fieldoffset = offsetoflow32(CPUARMState, cp15.c9_pmselr), - .accessfn = pmreg_access, .writefn = pmselr_write, + .accessfn = pmreg_access_selr, .writefn = pmselr_write, .raw_writefn = raw_write}, { .name = "PMSELR_EL0", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 3, .crn = 9, .crm = 12, .opc2 = 5, - .access = PL0_RW, .accessfn = pmreg_access, + .access = PL0_RW, .accessfn = pmreg_access_selr, .fieldoffset = offsetof(CPUARMState, cp15.c9_pmselr), .writefn = pmselr_write, .raw_writefn = raw_write, }, { .name = "PMCCNTR", .cp = 15, .crn = 9, .crm = 13, .opc1 = 0, .opc2 = 0, .access = PL0_RW, .resetvalue = 0, .type = ARM_CP_IO, .readfn = pmccntr_read, .writefn = pmccntr_write32, - .accessfn = pmreg_access }, + .accessfn = pmreg_access_ccntr }, { .name = "PMCCNTR_EL0", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 3, .crn = 9, .crm = 13, .opc2 = 0, - .access = PL0_RW, .accessfn = pmreg_access, + .access = PL0_RW, .accessfn = pmreg_access_ccntr, .type = ARM_CP_IO, .readfn = pmccntr_read, .writefn = pmccntr_write, }, #endif @@ -1251,7 +1314,7 @@ static const ARMCPRegInfo v7_cp_reginfo[] = { /* Unimplemented, RAZ/WI. */ { .name = "PMXEVCNTR", .cp = 15, .crn = 9, .crm = 13, .opc1 = 0, .opc2 = 2, .access = PL0_RW, .type = ARM_CP_CONST, .resetvalue = 0, - .accessfn = pmreg_access }, + .accessfn = pmreg_access_xevcntr }, { .name = "PMUSERENR", .cp = 15, .crn = 9, .crm = 14, .opc1 = 0, .opc2 = 0, .access = PL0_R | PL1_RW, .accessfn = access_tpm, .fieldoffset = offsetof(CPUARMState, cp15.c9_pmuserenr), @@ -6857,7 +6920,7 @@ void arm_cpu_do_interrupt(CPUState *cs) new_el); if (qemu_loglevel_mask(CPU_LOG_INT) && !excp_is_internal(cs->exception_index)) { - qemu_log_mask(CPU_LOG_INT, "...with ESR %x/0x%" PRIx32 "\n", + qemu_log_mask(CPU_LOG_INT, "...with ESR 0x%x/0x%" PRIx32 "\n", env->exception.syndrome >> ARM_EL_EC_SHIFT, env->exception.syndrome); } diff --git a/target/i386/cpu.c b/target/i386/cpu.c index fba92125ab..7aa762245a 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -688,6 +688,25 @@ void host_cpuid(uint32_t function, uint32_t count, *edx = vec[3]; } +void host_vendor_fms(char *vendor, int *family, int *model, int *stepping) +{ + uint32_t eax, ebx, ecx, edx; + + host_cpuid(0x0, 0, &eax, &ebx, &ecx, &edx); + x86_cpu_vendor_words2str(vendor, ebx, edx, ecx); + + host_cpuid(0x1, 0, &eax, &ebx, &ecx, &edx); + if (family) { + *family = ((eax >> 8) & 0x0F) + ((eax >> 20) & 0xFF); + } + if (model) { + *model = ((eax >> 4) & 0x0F) | ((eax & 0xF0000) >> 12); + } + if (stepping) { + *stepping = eax & 0x0F; + } +} + /* CPU class name definitions: */ #define X86_CPU_TYPE_SUFFIX "-" TYPE_X86_CPU @@ -1177,7 +1196,7 @@ static X86CPUDefinition builtin_x86_defs[] = { .vendor = CPUID_VENDOR_INTEL, .family = 6, .model = 60, - .stepping = 1, + .stepping = 4, .features[FEAT_1_EDX] = CPUID_VME | CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | diff --git a/target/i386/cpu.h b/target/i386/cpu.h index ac2ad6d443..07401ad9fe 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -30,6 +30,9 @@ #define TARGET_LONG_BITS 32 #endif +/* The x86 has a strong memory model with some store-after-load re-ordering */ +#define TCG_GUEST_DEFAULT_MO (TCG_MO_ALL & ~TCG_MO_ST_LD) + /* Maximum instruction code size */ #define TARGET_MAX_INSN_SIZE 16 @@ -694,6 +697,7 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS]; #define EXCP_SYSCALL 0x100 /* only happens in user only emulation for syscall instruction */ +#define EXCP_VMEXIT 0x100 /* i386-specific interrupt pending bits. */ #define CPU_INTERRUPT_POLL CPU_INTERRUPT_TGT_EXT_1 @@ -1436,6 +1440,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, void cpu_clear_apic_feature(CPUX86State *env); void host_cpuid(uint32_t function, uint32_t count, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx); +void host_vendor_fms(char *vendor, int *family, int *model, int *stepping); /* helper.c */ int x86_cpu_handle_mmu_fault(CPUState *cpu, vaddr addr, @@ -1629,6 +1634,7 @@ void cpu_svm_check_intercept_param(CPUX86State *env1, uint32_t type, uint64_t param, uintptr_t retaddr); void cpu_vmexit(CPUX86State *nenv, uint32_t exit_code, uint64_t exit_info_1, uintptr_t retaddr); +void do_vmexit(CPUX86State *env, uint32_t exit_code, uint64_t exit_info_1); /* seg_helper.c */ void do_interrupt_x86_hardirq(CPUX86State *env, int intno, int is_hw); diff --git a/target/i386/kvm.c b/target/i386/kvm.c index 887a81268f..55865dbee0 100644 --- a/target/i386/kvm.c +++ b/target/i386/kvm.c @@ -266,6 +266,19 @@ static int get_para_features(KVMState *s) return features; } +static bool host_tsx_blacklisted(void) +{ + int family, model, stepping;\ + char vendor[CPUID_VENDOR_SZ + 1]; + + host_vendor_fms(vendor, &family, &model, &stepping); + + /* Check if we are running on a Haswell host known to have broken TSX */ + return !strcmp(vendor, CPUID_VENDOR_INTEL) && + (family == 6) && + ((model == 63 && stepping < 4) || + model == 60 || model == 69 || model == 70); +} /* Returns the value for a specific register on the cpuid entry */ @@ -349,6 +362,10 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function, } } else if (function == 6 && reg == R_EAX) { ret |= CPUID_6_EAX_ARAT; /* safe to allow because of emulated APIC */ + } else if (function == 7 && index == 0 && reg == R_EBX) { + if (host_tsx_blacklisted()) { + ret &= ~(CPUID_7_0_EBX_RTM | CPUID_7_0_EBX_HLE); + } } else if (function == 0x80000001 && reg == R_EDX) { /* On Intel, kvm returns cpuid according to the Intel spec, * so add missing bits according to the AMD spec: @@ -1807,6 +1824,12 @@ static int kvm_put_msrs(X86CPU *cpu, int level) return ret; } + if (ret < cpu->kvm_msr_buf->nmsrs) { + struct kvm_msr_entry *e = &cpu->kvm_msr_buf->entries[ret]; + error_report("error: failed to set MSR 0x%" PRIx32 " to 0x%" PRIx64, + (uint32_t)e->index, (uint64_t)e->data); + } + assert(ret == cpu->kvm_msr_buf->nmsrs); return 0; } @@ -2172,6 +2195,12 @@ static int kvm_get_msrs(X86CPU *cpu) return ret; } + if (ret < cpu->kvm_msr_buf->nmsrs) { + struct kvm_msr_entry *e = &cpu->kvm_msr_buf->entries[ret]; + error_report("error: failed to get MSR 0x%" PRIx32, + (uint32_t)e->index); + } + assert(ret == cpu->kvm_msr_buf->nmsrs); /* * MTRR masks: Each mask consists of 5 parts diff --git a/target/i386/seg_helper.c b/target/i386/seg_helper.c index 5c845dc25c..0374031ea2 100644 --- a/target/i386/seg_helper.c +++ b/target/i386/seg_helper.c @@ -1297,15 +1297,17 @@ void x86_cpu_do_interrupt(CPUState *cs) /* successfully delivered */ env->old_exception = -1; #else - /* simulate a real cpu exception. On i386, it can - trigger new exceptions, but we do not handle - double or triple faults yet. */ - do_interrupt_all(cpu, cs->exception_index, - env->exception_is_int, - env->error_code, - env->exception_next_eip, 0); - /* successfully delivered */ - env->old_exception = -1; + if (cs->exception_index >= EXCP_VMEXIT) { + assert(env->old_exception == -1); + do_vmexit(env, cs->exception_index - EXCP_VMEXIT, env->error_code); + } else { + do_interrupt_all(cpu, cs->exception_index, + env->exception_is_int, + env->error_code, + env->exception_next_eip, 0); + /* successfully delivered */ + env->old_exception = -1; + } #endif } diff --git a/target/i386/svm_helper.c b/target/i386/svm_helper.c index 78d8df4af6..59e8b5091c 100644 --- a/target/i386/svm_helper.c +++ b/target/i386/svm_helper.c @@ -580,12 +580,10 @@ void helper_svm_check_io(CPUX86State *env, uint32_t port, uint32_t param, } } -/* Note: currently only 32 bits of exit_code are used */ void cpu_vmexit(CPUX86State *env, uint32_t exit_code, uint64_t exit_info_1, uintptr_t retaddr) { CPUState *cs = CPU(x86_env_get_cpu(env)); - uint32_t int_ctl; if (retaddr) { cpu_restore_state(cs, retaddr); @@ -598,6 +596,19 @@ void cpu_vmexit(CPUX86State *env, uint32_t exit_code, uint64_t exit_info_1, control.exit_info_2)), env->eip); + cs->exception_index = EXCP_VMEXIT + exit_code; + env->error_code = exit_info_1; + + /* remove any pending exception */ + env->old_exception = -1; + cpu_loop_exit(cs); +} + +void do_vmexit(CPUX86State *env, uint32_t exit_code, uint64_t exit_info_1) +{ + CPUState *cs = CPU(x86_env_get_cpu(env)); + uint32_t int_ctl; + if (env->hflags & HF_INHIBIT_IRQ_MASK) { x86_stl_phys(cs, env->vm_vmcb + offsetof(struct vmcb, control.int_state), @@ -759,13 +770,6 @@ void cpu_vmexit(CPUX86State *env, uint32_t exit_code, uint64_t exit_info_1, /* If the host's rIP reloaded by #VMEXIT is outside the limit of the host's code segment or non-canonical (in the case of long mode), a #GP fault is delivered inside the host. */ - - /* remove any pending exception */ - cs->exception_index = -1; - env->error_code = 0; - env->old_exception = -1; - - cpu_loop_exit(cs); } #endif diff --git a/target/mips/op_helper.c b/target/mips/op_helper.c index b683fcb025..e5f3ea4042 100644 --- a/target/mips/op_helper.c +++ b/target/mips/op_helper.c @@ -17,6 +17,7 @@ * License along with this library; if not, see <http://www.gnu.org/licenses/>. */ #include "qemu/osdep.h" +#include "qemu/main-loop.h" #include "cpu.h" #include "qemu/host-utils.h" #include "exec/helper-proto.h" @@ -827,7 +828,11 @@ target_ulong helper_mftc0_tcschefback(CPUMIPSState *env) target_ulong helper_mfc0_count(CPUMIPSState *env) { - return (int32_t)cpu_mips_get_count(env); + int32_t count; + qemu_mutex_lock_iothread(); + count = (int32_t) cpu_mips_get_count(env); + qemu_mutex_unlock_iothread(); + return count; } target_ulong helper_mftc0_entryhi(CPUMIPSState *env) @@ -1375,7 +1380,9 @@ void helper_mtc0_hwrena(CPUMIPSState *env, target_ulong arg1) void helper_mtc0_count(CPUMIPSState *env, target_ulong arg1) { + qemu_mutex_lock_iothread(); cpu_mips_store_count(env, arg1); + qemu_mutex_unlock_iothread(); } void helper_mtc0_entryhi(CPUMIPSState *env, target_ulong arg1) @@ -1424,7 +1431,9 @@ void helper_mttc0_entryhi(CPUMIPSState *env, target_ulong arg1) void helper_mtc0_compare(CPUMIPSState *env, target_ulong arg1) { + qemu_mutex_lock_iothread(); cpu_mips_store_compare(env, arg1); + qemu_mutex_unlock_iothread(); } void helper_mtc0_status(CPUMIPSState *env, target_ulong arg1) @@ -1475,7 +1484,9 @@ void helper_mtc0_srsctl(CPUMIPSState *env, target_ulong arg1) void helper_mtc0_cause(CPUMIPSState *env, target_ulong arg1) { + qemu_mutex_lock_iothread(); cpu_mips_store_cause(env, arg1); + qemu_mutex_unlock_iothread(); } void helper_mttc0_cause(CPUMIPSState *env, target_ulong arg1) @@ -2296,12 +2307,16 @@ target_ulong helper_rdhwr_synci_step(CPUMIPSState *env) target_ulong helper_rdhwr_cc(CPUMIPSState *env) { + int32_t count; check_hwrena(env, 2, GETPC()); #ifdef CONFIG_USER_ONLY - return env->CP0_Count; + count = env->CP0_Count; #else - return (int32_t)cpu_mips_get_count(env); + qemu_mutex_lock_iothread(); + count = (int32_t)cpu_mips_get_count(env); + qemu_mutex_unlock_iothread(); #endif + return count; } target_ulong helper_rdhwr_ccres(CPUMIPSState *env) diff --git a/target/nios2/op_helper.c b/target/nios2/op_helper.c index 538853cda7..efb1c489c9 100644 --- a/target/nios2/op_helper.c +++ b/target/nios2/op_helper.c @@ -21,6 +21,7 @@ #include "cpu.h" #include "exec/helper-proto.h" #include "exec/cpu_ldst.h" +#include "qemu/main-loop.h" #if !defined(CONFIG_USER_ONLY) void helper_mmu_read_debug(CPUNios2State *env, uint32_t rn) @@ -35,7 +36,9 @@ void helper_mmu_write(CPUNios2State *env, uint32_t rn, uint32_t v) void helper_check_interrupts(CPUNios2State *env) { + qemu_mutex_lock_iothread(); nios2_check_interrupts(env); + qemu_mutex_unlock_iothread(); } #endif /* !CONFIG_USER_ONLY */ diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h index 7c4a1f50b3..5ee33b3fd3 100644 --- a/target/ppc/cpu.h +++ b/target/ppc/cpu.h @@ -1408,7 +1408,7 @@ int ppc_compat_max_threads(PowerPCCPU *cpu); #define SPR_601_UDECR (0x006) #define SPR_LR (0x008) #define SPR_CTR (0x009) -#define SPR_UAMR (0x00C) +#define SPR_UAMR (0x00D) #define SPR_DSCR (0x011) #define SPR_DSISR (0x012) #define SPR_DAR (0x013) /* DAE for PowerPC 601 */ diff --git a/target/ppc/translate.c b/target/ppc/translate.c index b6abc60a00..f40b5a1abf 100644 --- a/target/ppc/translate.c +++ b/target/ppc/translate.c @@ -818,7 +818,7 @@ static inline void gen_op_arith_compute_ov(DisasContext *ctx, TCGv arg0, if (is_isa300(ctx)) { tcg_gen_extract_tl(cpu_ov32, cpu_ov, 31, 1); } - tcg_gen_extract_tl(cpu_ov, cpu_ov, 63, 1); + tcg_gen_extract_tl(cpu_ov, cpu_ov, TARGET_LONG_BITS - 1, 1); } tcg_gen_or_tl(cpu_so, cpu_so, cpu_ov); } diff --git a/target/s390x/Makefile.objs b/target/s390x/Makefile.objs index c573633bd1..46f6a8c6b6 100644 --- a/target/s390x/Makefile.objs +++ b/target/s390x/Makefile.objs @@ -8,7 +8,7 @@ obj-$(CONFIG_KVM) += kvm.o feat-src = $(SRC_PATH)/target/$(TARGET_BASE_ARCH)/ feat-dst = $(BUILD_DIR)/$(TARGET_DIR) ifneq ($(MAKECMDGOALS),clean) -GENERATED_HEADERS += $(feat-dst)gen-features.h +GENERATED_FILES += $(feat-dst)gen-features.h endif $(feat-dst)gen-features.h: $(feat-dst)gen-features.h-timestamp diff --git a/target/s390x/misc_helper.c b/target/s390x/misc_helper.c index 3cb942e8bb..93b0e61366 100644 --- a/target/s390x/misc_helper.c +++ b/target/s390x/misc_helper.c @@ -19,6 +19,7 @@ */ #include "qemu/osdep.h" +#include "qemu/main-loop.h" #include "cpu.h" #include "exec/memory.h" #include "qemu/host-utils.h" @@ -551,61 +552,81 @@ uint32_t HELPER(sigp)(CPUS390XState *env, uint64_t order_code, uint32_t r1, void HELPER(xsch)(CPUS390XState *env, uint64_t r1) { S390CPU *cpu = s390_env_get_cpu(env); + qemu_mutex_lock_iothread(); ioinst_handle_xsch(cpu, r1); + qemu_mutex_unlock_iothread(); } void HELPER(csch)(CPUS390XState *env, uint64_t r1) { S390CPU *cpu = s390_env_get_cpu(env); + qemu_mutex_lock_iothread(); ioinst_handle_csch(cpu, r1); + qemu_mutex_unlock_iothread(); } void HELPER(hsch)(CPUS390XState *env, uint64_t r1) { S390CPU *cpu = s390_env_get_cpu(env); + qemu_mutex_lock_iothread(); ioinst_handle_hsch(cpu, r1); + qemu_mutex_unlock_iothread(); } void HELPER(msch)(CPUS390XState *env, uint64_t r1, uint64_t inst) { S390CPU *cpu = s390_env_get_cpu(env); + qemu_mutex_lock_iothread(); ioinst_handle_msch(cpu, r1, inst >> 16); + qemu_mutex_unlock_iothread(); } void HELPER(rchp)(CPUS390XState *env, uint64_t r1) { S390CPU *cpu = s390_env_get_cpu(env); + qemu_mutex_lock_iothread(); ioinst_handle_rchp(cpu, r1); + qemu_mutex_unlock_iothread(); } void HELPER(rsch)(CPUS390XState *env, uint64_t r1) { S390CPU *cpu = s390_env_get_cpu(env); + qemu_mutex_lock_iothread(); ioinst_handle_rsch(cpu, r1); + qemu_mutex_unlock_iothread(); } void HELPER(ssch)(CPUS390XState *env, uint64_t r1, uint64_t inst) { S390CPU *cpu = s390_env_get_cpu(env); + qemu_mutex_lock_iothread(); ioinst_handle_ssch(cpu, r1, inst >> 16); + qemu_mutex_unlock_iothread(); } void HELPER(stsch)(CPUS390XState *env, uint64_t r1, uint64_t inst) { S390CPU *cpu = s390_env_get_cpu(env); + qemu_mutex_lock_iothread(); ioinst_handle_stsch(cpu, r1, inst >> 16); + qemu_mutex_unlock_iothread(); } void HELPER(tsch)(CPUS390XState *env, uint64_t r1, uint64_t inst) { S390CPU *cpu = s390_env_get_cpu(env); + qemu_mutex_lock_iothread(); ioinst_handle_tsch(cpu, r1, inst >> 16); + qemu_mutex_unlock_iothread(); } void HELPER(chsc)(CPUS390XState *env, uint64_t inst) { S390CPU *cpu = s390_env_get_cpu(env); + qemu_mutex_lock_iothread(); ioinst_handle_chsc(cpu, inst >> 16); + qemu_mutex_unlock_iothread(); } #endif diff --git a/target/sparc/int64_helper.c b/target/sparc/int64_helper.c index 605747c93c..f942973c22 100644 --- a/target/sparc/int64_helper.c +++ b/target/sparc/int64_helper.c @@ -18,6 +18,7 @@ */ #include "qemu/osdep.h" +#include "qemu/main-loop.h" #include "cpu.h" #include "exec/helper-proto.h" #include "exec/log.h" @@ -208,7 +209,9 @@ static bool do_modify_softint(CPUSPARCState *env, uint32_t value) env->softint = value; #if !defined(CONFIG_USER_ONLY) if (cpu_interrupts_enabled(env)) { + qemu_mutex_lock_iothread(); cpu_check_irqs(env); + qemu_mutex_unlock_iothread(); } #endif return true; diff --git a/target/sparc/win_helper.c b/target/sparc/win_helper.c index 71b3dd37e8..154279ecda 100644 --- a/target/sparc/win_helper.c +++ b/target/sparc/win_helper.c @@ -18,6 +18,7 @@ */ #include "qemu/osdep.h" +#include "qemu/main-loop.h" #include "cpu.h" #include "exec/exec-all.h" #include "exec/helper-proto.h" @@ -82,6 +83,7 @@ void cpu_put_psr_raw(CPUSPARCState *env, target_ulong val) #endif } +/* Called with BQL held */ void cpu_put_psr(CPUSPARCState *env, target_ulong val) { cpu_put_psr_raw(env, val); @@ -153,7 +155,10 @@ void helper_wrpsr(CPUSPARCState *env, target_ulong new_psr) if ((new_psr & PSR_CWP) >= env->nwindows) { cpu_raise_exception_ra(env, TT_ILL_INSN, GETPC()); } else { + /* cpu_put_psr may trigger interrupts, hence BQL */ + qemu_mutex_lock_iothread(); cpu_put_psr(env, new_psr); + qemu_mutex_unlock_iothread(); } } @@ -368,7 +373,9 @@ void helper_wrpstate(CPUSPARCState *env, target_ulong new_state) #if !defined(CONFIG_USER_ONLY) if (cpu_interrupts_enabled(env)) { + qemu_mutex_lock_iothread(); cpu_check_irqs(env); + qemu_mutex_unlock_iothread(); } #endif } @@ -381,7 +388,9 @@ void helper_wrpil(CPUSPARCState *env, target_ulong new_pil) env->psrpil = new_pil; if (cpu_interrupts_enabled(env)) { + qemu_mutex_lock_iothread(); cpu_check_irqs(env); + qemu_mutex_unlock_iothread(); } #endif } @@ -408,7 +417,9 @@ void helper_done(CPUSPARCState *env) #if !defined(CONFIG_USER_ONLY) if (cpu_interrupts_enabled(env)) { + qemu_mutex_lock_iothread(); cpu_check_irqs(env); + qemu_mutex_unlock_iothread(); } #endif } @@ -435,7 +446,9 @@ void helper_retry(CPUSPARCState *env) #if !defined(CONFIG_USER_ONLY) if (cpu_interrupts_enabled(env)) { + qemu_mutex_lock_iothread(); cpu_check_irqs(env); + qemu_mutex_unlock_iothread(); } #endif } diff --git a/target/xtensa/helper.c b/target/xtensa/helper.c index c67d715c4b..bcd0b7738d 100644 --- a/target/xtensa/helper.c +++ b/target/xtensa/helper.c @@ -217,6 +217,7 @@ static void handle_interrupt(CPUXtensaState *env) } } +/* Called from cpu_handle_interrupt with BQL held */ void xtensa_cpu_do_interrupt(CPUState *cs) { XtensaCPU *cpu = XTENSA_CPU(cs); diff --git a/target/xtensa/op_helper.c b/target/xtensa/op_helper.c index af2723445d..519fbeddd6 100644 --- a/target/xtensa/op_helper.c +++ b/target/xtensa/op_helper.c @@ -26,6 +26,7 @@ */ #include "qemu/osdep.h" +#include "qemu/main-loop.h" #include "cpu.h" #include "exec/helper-proto.h" #include "qemu/host-utils.h" @@ -381,7 +382,11 @@ void HELPER(waiti)(CPUXtensaState *env, uint32_t pc, uint32_t intlevel) env->pc = pc; env->sregs[PS] = (env->sregs[PS] & ~PS_INTLEVEL) | (intlevel << PS_INTLEVEL_SHIFT); + + qemu_mutex_lock_iothread(); check_interrupts(env); + qemu_mutex_unlock_iothread(); + if (env->pending_irq_level) { cpu_loop_exit(CPU(xtensa_env_get_cpu(env))); return; @@ -426,7 +431,9 @@ void HELPER(update_ccompare)(CPUXtensaState *env, uint32_t i) void HELPER(check_interrupts)(CPUXtensaState *env) { + qemu_mutex_lock_iothread(); check_interrupts(env); + qemu_mutex_unlock_iothread(); } void HELPER(itlb_hit_test)(CPUXtensaState *env, uint32_t vaddr) diff --git a/tests/Makefile.include b/tests/Makefile.include index 346345e84d..402e71cf06 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -367,8 +367,12 @@ qapi-schema += base-cycle-direct.json qapi-schema += base-cycle-indirect.json qapi-schema += command-int.json qapi-schema += comments.json -qapi-schema += doc-bad-args.json +qapi-schema += doc-bad-alternate-member.json +qapi-schema += doc-bad-command-arg.json qapi-schema += doc-bad-symbol.json +qapi-schema += doc-bad-union-member.json +qapi-schema += doc-before-include.json +qapi-schema += doc-before-pragma.json qapi-schema += doc-duplicated-arg.json qapi-schema += doc-duplicated-return.json qapi-schema += doc-duplicated-since.json @@ -381,10 +385,11 @@ qapi-schema += doc-invalid-end2.json qapi-schema += doc-invalid-return.json qapi-schema += doc-invalid-section.json qapi-schema += doc-invalid-start.json +qapi-schema += doc-missing.json qapi-schema += doc-missing-colon.json qapi-schema += doc-missing-expr.json qapi-schema += doc-missing-space.json -qapi-schema += doc-optional.json +qapi-schema += doc-no-symbol.json qapi-schema += double-data.json qapi-schema += double-type.json qapi-schema += duplicate-key.json @@ -422,6 +427,7 @@ qapi-schema += funny-char.json qapi-schema += ident-with-escape.json qapi-schema += include-before-err.json qapi-schema += include-cycle.json +qapi-schema += include-extra-junk.json qapi-schema += include-format-err.json qapi-schema += include-nested-err.json qapi-schema += include-no-file.json @@ -439,6 +445,11 @@ qapi-schema += missing-comma-object.json qapi-schema += missing-type.json qapi-schema += nested-struct-data.json qapi-schema += non-objects.json +qapi-schema += pragma-doc-required-crap.json +qapi-schema += pragma-extra-junk.json +qapi-schema += pragma-name-case-whitelist-crap.json +qapi-schema += pragma-non-dict.json +qapi-schema += pragma-returns-whitelist-crap.json qapi-schema += qapi-schema-test.json qapi-schema += quoted-structural-chars.json qapi-schema += redefined-builtin.json @@ -469,6 +480,7 @@ qapi-schema += unclosed-list.json qapi-schema += unclosed-object.json qapi-schema += unclosed-string.json qapi-schema += unicode-str.json +qapi-schema += union-base-empty.json qapi-schema += union-base-no-discriminator.json qapi-schema += union-branch-case.json qapi-schema += union-clash-branches.json @@ -482,7 +494,7 @@ qapi-schema += unknown-expr-key.json check-qapi-schema-y := $(addprefix tests/qapi-schema/, $(qapi-schema)) -GENERATED_HEADERS += tests/test-qapi-types.h tests/test-qapi-visit.h \ +GENERATED_FILES += tests/test-qapi-types.h tests/test-qapi-visit.h \ tests/test-qmp-commands.h tests/test-qapi-event.h \ tests/test-qmp-introspect.h diff --git a/tests/docker/docker.py b/tests/docker/docker.py index 9fd32ab5fa..8747f6a440 100755 --- a/tests/docker/docker.py +++ b/tests/docker/docker.py @@ -28,6 +28,9 @@ from shutil import copy, rmtree from pwd import getpwuid +FILTERED_ENV_NAMES = ['ftp_proxy', 'http_proxy', 'https_proxy'] + + DEVNULL = open(os.devnull, 'wb') @@ -272,6 +275,9 @@ class BuildCommand(SubCommand): _copy_binary_with_libs(args.include_executable, docker_dir) + argv += ["--build-arg=" + k.lower() + "=" + v + for k, v in os.environ.iteritems() + if k.lower() in FILTERED_ENV_NAMES] dkr.build_image(tag, docker_dir, dockerfile, quiet=args.quiet, user=args.user, argv=argv) diff --git a/tests/docker/dockerfiles/debian-s390x-cross.docker b/tests/docker/dockerfiles/debian-s390x-cross.docker index bbb21ed088..3a687feda0 100644 --- a/tests/docker/dockerfiles/debian-s390x-cross.docker +++ b/tests/docker/dockerfiles/debian-s390x-cross.docker @@ -13,8 +13,8 @@ RUN cat /etc/apt/sources.list | sed "s/deb/deb-src/" >> /etc/apt/sources.list RUN dpkg --add-architecture s390x # Grab the updated list of packages -RUN apt update -RUN apt dist-upgrade -yy +RUN apt update && apt dist-upgrade -yy +RUN apt install -yy build-essential clang RUN apt-get build-dep -yy -a s390x qemu || apt-get -f install RUN apt install -yy gcc-multilib-s390x-linux-gnu binutils-multiarch diff --git a/tests/qapi-schema/alternate-any.err b/tests/qapi-schema/alternate-any.err index 395c8ab583..aaa0154731 100644 --- a/tests/qapi-schema/alternate-any.err +++ b/tests/qapi-schema/alternate-any.err @@ -1 +1 @@ -tests/qapi-schema/alternate-any.json:6: Alternate 'Alt' member 'one' cannot use type 'any' +tests/qapi-schema/alternate-any.json:2: Alternate 'Alt' member 'one' cannot use type 'any' diff --git a/tests/qapi-schema/alternate-any.json b/tests/qapi-schema/alternate-any.json index c958776767..e47a73a116 100644 --- a/tests/qapi-schema/alternate-any.json +++ b/tests/qapi-schema/alternate-any.json @@ -1,8 +1,4 @@ # we do not allow the 'any' type as an alternate branch - -## -# @Alt: -## { 'alternate': 'Alt', 'data': { 'one': 'any', 'two': 'int' } } diff --git a/tests/qapi-schema/alternate-array.err b/tests/qapi-schema/alternate-array.err index 09628e9755..7b930c64ab 100644 --- a/tests/qapi-schema/alternate-array.err +++ b/tests/qapi-schema/alternate-array.err @@ -1 +1 @@ -tests/qapi-schema/alternate-array.json:12: Member 'two' of alternate 'Alt' cannot be an array +tests/qapi-schema/alternate-array.json:5: Member 'two' of alternate 'Alt' cannot be an array diff --git a/tests/qapi-schema/alternate-array.json b/tests/qapi-schema/alternate-array.json index c2f98ad608..f241aac122 100644 --- a/tests/qapi-schema/alternate-array.json +++ b/tests/qapi-schema/alternate-array.json @@ -1,14 +1,7 @@ # we do not allow array branches in alternates - -## -# @One: -## # TODO: should we support this? { 'struct': 'One', 'data': { 'name': 'str' } } -## -# @Alt: -## { 'alternate': 'Alt', 'data': { 'one': 'One', 'two': [ 'int' ] } } diff --git a/tests/qapi-schema/alternate-base.err b/tests/qapi-schema/alternate-base.err index 3b679140e0..30d8a34373 100644 --- a/tests/qapi-schema/alternate-base.err +++ b/tests/qapi-schema/alternate-base.err @@ -1 +1 @@ -tests/qapi-schema/alternate-base.json:11: Unknown key 'base' in alternate 'Alt' +tests/qapi-schema/alternate-base.json:4: Unknown key 'base' in alternate 'Alt' diff --git a/tests/qapi-schema/alternate-base.json b/tests/qapi-schema/alternate-base.json index 9612b7925d..529430ecf2 100644 --- a/tests/qapi-schema/alternate-base.json +++ b/tests/qapi-schema/alternate-base.json @@ -1,13 +1,6 @@ # we reject alternate with base type - -## -# @Base: -## { 'struct': 'Base', 'data': { 'string': 'str' } } -## -# @Alt: -## { 'alternate': 'Alt', 'base': 'Base', 'data': { 'number': 'int' } } diff --git a/tests/qapi-schema/alternate-clash.err b/tests/qapi-schema/alternate-clash.err index f07c3e8ad3..604d8495eb 100644 --- a/tests/qapi-schema/alternate-clash.err +++ b/tests/qapi-schema/alternate-clash.err @@ -1 +1 @@ -tests/qapi-schema/alternate-clash.json:11: 'a_b' (branch of Alt1) collides with 'a-b' (branch of Alt1) +tests/qapi-schema/alternate-clash.json:7: 'a_b' (branch of Alt1) collides with 'a-b' (branch of Alt1) diff --git a/tests/qapi-schema/alternate-clash.json b/tests/qapi-schema/alternate-clash.json index 97ca7c80e7..6d73bc527b 100644 --- a/tests/qapi-schema/alternate-clash.json +++ b/tests/qapi-schema/alternate-clash.json @@ -4,9 +4,5 @@ # TODO: In the future, if alternates are simplified to not generate # the implicit Alt1Kind enum, we would still have a collision with the # resulting C union trying to have two members named 'a_b'. - -## -# @Alt1: -## { 'alternate': 'Alt1', 'data': { 'a-b': 'str', 'a_b': 'int' } } diff --git a/tests/qapi-schema/alternate-conflict-dict.err b/tests/qapi-schema/alternate-conflict-dict.err index 7cb023fdd8..0f411f4faf 100644 --- a/tests/qapi-schema/alternate-conflict-dict.err +++ b/tests/qapi-schema/alternate-conflict-dict.err @@ -1 +1 @@ -tests/qapi-schema/alternate-conflict-dict.json:16: Alternate 'Alt' member 'two' can't be distinguished from member 'one' +tests/qapi-schema/alternate-conflict-dict.json:6: Alternate 'Alt' member 'two' can't be distinguished from member 'one' diff --git a/tests/qapi-schema/alternate-conflict-dict.json b/tests/qapi-schema/alternate-conflict-dict.json index 9f9d97fa2e..d566cca816 100644 --- a/tests/qapi-schema/alternate-conflict-dict.json +++ b/tests/qapi-schema/alternate-conflict-dict.json @@ -1,18 +1,8 @@ # we reject alternates with multiple object branches - -## -# @One: -## { 'struct': 'One', 'data': { 'name': 'str' } } -## -# @Two: -## { 'struct': 'Two', 'data': { 'value': 'int' } } -## -# @Alt: -## { 'alternate': 'Alt', 'data': { 'one': 'One', 'two': 'Two' } } diff --git a/tests/qapi-schema/alternate-conflict-string.err b/tests/qapi-schema/alternate-conflict-string.err index 6dbbacd1d2..fc523b0879 100644 --- a/tests/qapi-schema/alternate-conflict-string.err +++ b/tests/qapi-schema/alternate-conflict-string.err @@ -1 +1 @@ -tests/qapi-schema/alternate-conflict-string.json:11: Alternate 'Alt' member 'two' can't be distinguished from member 'one' +tests/qapi-schema/alternate-conflict-string.json:4: Alternate 'Alt' member 'two' can't be distinguished from member 'one' diff --git a/tests/qapi-schema/alternate-conflict-string.json b/tests/qapi-schema/alternate-conflict-string.json index 12aafab808..72f04a820a 100644 --- a/tests/qapi-schema/alternate-conflict-string.json +++ b/tests/qapi-schema/alternate-conflict-string.json @@ -1,13 +1,6 @@ # we reject alternates with multiple string-like branches - -## -# @Enum: -## { 'enum': 'Enum', 'data': [ 'hello', 'world' ] } -## -# @Alt: -## { 'alternate': 'Alt', 'data': { 'one': 'str', 'two': 'Enum' } } diff --git a/tests/qapi-schema/alternate-empty.err b/tests/qapi-schema/alternate-empty.err index 8245ce3103..bb06c5bfec 100644 --- a/tests/qapi-schema/alternate-empty.err +++ b/tests/qapi-schema/alternate-empty.err @@ -1 +1 @@ -tests/qapi-schema/alternate-empty.json:6: Alternate 'Alt' should have at least two branches in 'data' +tests/qapi-schema/alternate-empty.json:2: Alternate 'Alt' should have at least two branches in 'data' diff --git a/tests/qapi-schema/alternate-empty.json b/tests/qapi-schema/alternate-empty.json index db54405240..fff15baf16 100644 --- a/tests/qapi-schema/alternate-empty.json +++ b/tests/qapi-schema/alternate-empty.json @@ -1,6 +1,2 @@ # alternates must list at least two types to be useful - -## -# @Alt: -## { 'alternate': 'Alt', 'data': { 'i': 'int' } } diff --git a/tests/qapi-schema/alternate-nested.err b/tests/qapi-schema/alternate-nested.err index 1804ffbf47..4d1187e60e 100644 --- a/tests/qapi-schema/alternate-nested.err +++ b/tests/qapi-schema/alternate-nested.err @@ -1 +1 @@ -tests/qapi-schema/alternate-nested.json:11: Member 'nested' of alternate 'Alt2' cannot use alternate type 'Alt1' +tests/qapi-schema/alternate-nested.json:4: Member 'nested' of alternate 'Alt2' cannot use alternate type 'Alt1' diff --git a/tests/qapi-schema/alternate-nested.json b/tests/qapi-schema/alternate-nested.json index 9f83ebe2e0..8e22186491 100644 --- a/tests/qapi-schema/alternate-nested.json +++ b/tests/qapi-schema/alternate-nested.json @@ -1,12 +1,5 @@ # we reject a nested alternate branch - -## -# @Alt1: -## { 'alternate': 'Alt1', 'data': { 'name': 'str', 'value': 'int' } } -## -# @Alt2: -## { 'alternate': 'Alt2', 'data': { 'nested': 'Alt1', 'b': 'bool' } } diff --git a/tests/qapi-schema/alternate-unknown.err b/tests/qapi-schema/alternate-unknown.err index cf5b9b6830..dea45dc730 100644 --- a/tests/qapi-schema/alternate-unknown.err +++ b/tests/qapi-schema/alternate-unknown.err @@ -1 +1 @@ -tests/qapi-schema/alternate-unknown.json:6: Member 'unknown' of alternate 'Alt' uses unknown type 'MissingType' +tests/qapi-schema/alternate-unknown.json:2: Member 'unknown' of alternate 'Alt' uses unknown type 'MissingType' diff --git a/tests/qapi-schema/alternate-unknown.json b/tests/qapi-schema/alternate-unknown.json index 941ba1fac4..08c80dced0 100644 --- a/tests/qapi-schema/alternate-unknown.json +++ b/tests/qapi-schema/alternate-unknown.json @@ -1,7 +1,3 @@ # we reject an alternate with unknown type in branch - -## -# @Alt: -## { 'alternate': 'Alt', 'data': { 'unknown': 'MissingType', 'i': 'int' } } diff --git a/tests/qapi-schema/args-alternate.err b/tests/qapi-schema/args-alternate.err index 2e6bf54245..3086eae56b 100644 --- a/tests/qapi-schema/args-alternate.err +++ b/tests/qapi-schema/args-alternate.err @@ -1 +1 @@ -tests/qapi-schema/args-alternate.json:11: 'data' for command 'oops' cannot use alternate type 'Alt' +tests/qapi-schema/args-alternate.json:3: 'data' for command 'oops' cannot use alternate type 'Alt' diff --git a/tests/qapi-schema/args-alternate.json b/tests/qapi-schema/args-alternate.json index 49d0211a03..69e94d4819 100644 --- a/tests/qapi-schema/args-alternate.json +++ b/tests/qapi-schema/args-alternate.json @@ -1,11 +1,3 @@ # we do not allow alternate arguments - -## -# @Alt: -## { 'alternate': 'Alt', 'data': { 'case1': 'int', 'case2': 'str' } } - -## -# @oops: -## { 'command': 'oops', 'data': 'Alt' } diff --git a/tests/qapi-schema/args-any.err b/tests/qapi-schema/args-any.err index 955504b10f..bf9b5e0730 100644 --- a/tests/qapi-schema/args-any.err +++ b/tests/qapi-schema/args-any.err @@ -1 +1 @@ -tests/qapi-schema/args-any.json:6: 'data' for command 'oops' cannot use built-in type 'any' +tests/qapi-schema/args-any.json:2: 'data' for command 'oops' cannot use built-in type 'any' diff --git a/tests/qapi-schema/args-any.json b/tests/qapi-schema/args-any.json index f494479cc9..58fe5e470e 100644 --- a/tests/qapi-schema/args-any.json +++ b/tests/qapi-schema/args-any.json @@ -1,6 +1,2 @@ # we do not allow an 'any' argument - -## -# @oops: -## { 'command': 'oops', 'data': 'any' } diff --git a/tests/qapi-schema/args-array-empty.err b/tests/qapi-schema/args-array-empty.err index e85f7918ab..cb7ed33b3f 100644 --- a/tests/qapi-schema/args-array-empty.err +++ b/tests/qapi-schema/args-array-empty.err @@ -1 +1 @@ -tests/qapi-schema/args-array-empty.json:6: Member 'empty' of 'data' for command 'oops': array type must contain single type name +tests/qapi-schema/args-array-empty.json:2: Member 'empty' of 'data' for command 'oops': array type must contain single type name diff --git a/tests/qapi-schema/args-array-empty.json b/tests/qapi-schema/args-array-empty.json index 78a0b88221..652dcfb24a 100644 --- a/tests/qapi-schema/args-array-empty.json +++ b/tests/qapi-schema/args-array-empty.json @@ -1,6 +1,2 @@ # we reject an array for data if it does not contain a known type - -## -# @oops: -## { 'command': 'oops', 'data': { 'empty': [ ] } } diff --git a/tests/qapi-schema/args-array-unknown.err b/tests/qapi-schema/args-array-unknown.err index 77788de099..cd7a0f98d7 100644 --- a/tests/qapi-schema/args-array-unknown.err +++ b/tests/qapi-schema/args-array-unknown.err @@ -1 +1 @@ -tests/qapi-schema/args-array-unknown.json:6: Member 'array' of 'data' for command 'oops' uses unknown type 'NoSuchType' +tests/qapi-schema/args-array-unknown.json:2: Member 'array' of 'data' for command 'oops' uses unknown type 'NoSuchType' diff --git a/tests/qapi-schema/args-array-unknown.json b/tests/qapi-schema/args-array-unknown.json index f680fc10d3..6f3e883315 100644 --- a/tests/qapi-schema/args-array-unknown.json +++ b/tests/qapi-schema/args-array-unknown.json @@ -1,6 +1,2 @@ # we reject an array for data if it does not contain a known type - -## -# @oops: -## { 'command': 'oops', 'data': { 'array': [ 'NoSuchType' ] } } diff --git a/tests/qapi-schema/args-bad-boxed.err b/tests/qapi-schema/args-bad-boxed.err index 87a906137a..ad0d417321 100644 --- a/tests/qapi-schema/args-bad-boxed.err +++ b/tests/qapi-schema/args-bad-boxed.err @@ -1 +1 @@ -tests/qapi-schema/args-bad-boxed.json:6: 'boxed' of command 'foo' should only use true value +tests/qapi-schema/args-bad-boxed.json:2: 'boxed' of command 'foo' should only use true value diff --git a/tests/qapi-schema/args-bad-boxed.json b/tests/qapi-schema/args-bad-boxed.json index 4c0b28f291..dea0cd0aa5 100644 --- a/tests/qapi-schema/args-bad-boxed.json +++ b/tests/qapi-schema/args-bad-boxed.json @@ -1,6 +1,2 @@ # 'boxed' should only appear with value true - -## -# @foo: -## { 'command': 'foo', 'boxed': false } diff --git a/tests/qapi-schema/args-boxed-anon.err b/tests/qapi-schema/args-boxed-anon.err index 3cfac0b923..f24f345218 100644 --- a/tests/qapi-schema/args-boxed-anon.err +++ b/tests/qapi-schema/args-boxed-anon.err @@ -1 +1 @@ -tests/qapi-schema/args-boxed-anon.json:6: 'data' for command 'foo' should be a type name +tests/qapi-schema/args-boxed-anon.json:2: 'data' for command 'foo' should be a type name diff --git a/tests/qapi-schema/args-boxed-anon.json b/tests/qapi-schema/args-boxed-anon.json index 2358e6abb1..95f60da2ed 100644 --- a/tests/qapi-schema/args-boxed-anon.json +++ b/tests/qapi-schema/args-boxed-anon.json @@ -1,6 +1,2 @@ # 'boxed' can only be used with named types - -## -# @foo: -## { 'command': 'foo', 'boxed': true, 'data': { 'string': 'str' } } diff --git a/tests/qapi-schema/args-boxed-empty.err b/tests/qapi-schema/args-boxed-empty.err index 963f495a9d..039603e85c 100644 --- a/tests/qapi-schema/args-boxed-empty.err +++ b/tests/qapi-schema/args-boxed-empty.err @@ -1 +1 @@ -tests/qapi-schema/args-boxed-empty.json:11: Cannot use 'boxed' with empty type +tests/qapi-schema/args-boxed-empty.json:3: Cannot use 'boxed' with empty type diff --git a/tests/qapi-schema/args-boxed-empty.json b/tests/qapi-schema/args-boxed-empty.json index 8e8cc26525..52717e065f 100644 --- a/tests/qapi-schema/args-boxed-empty.json +++ b/tests/qapi-schema/args-boxed-empty.json @@ -1,11 +1,3 @@ # 'boxed' requires a non-empty type - -## -# @Empty: -## { 'struct': 'Empty', 'data': {} } - -## -# @foo: -## { 'command': 'foo', 'boxed': true, 'data': 'Empty' } diff --git a/tests/qapi-schema/args-boxed-string.err b/tests/qapi-schema/args-boxed-string.err index 7623755208..d326b48aef 100644 --- a/tests/qapi-schema/args-boxed-string.err +++ b/tests/qapi-schema/args-boxed-string.err @@ -1 +1 @@ -tests/qapi-schema/args-boxed-string.json:6: 'data' for command 'foo' cannot use built-in type 'str' +tests/qapi-schema/args-boxed-string.json:2: 'data' for command 'foo' cannot use built-in type 'str' diff --git a/tests/qapi-schema/args-boxed-string.json b/tests/qapi-schema/args-boxed-string.json index aecdf97ce9..f91a1502e7 100644 --- a/tests/qapi-schema/args-boxed-string.json +++ b/tests/qapi-schema/args-boxed-string.json @@ -1,6 +1,2 @@ # 'boxed' requires a complex (not built-in) type - -## -# @foo: -## { 'command': 'foo', 'boxed': true, 'data': 'str' } diff --git a/tests/qapi-schema/args-int.err b/tests/qapi-schema/args-int.err index 38b3202b09..dc1d2504ff 100644 --- a/tests/qapi-schema/args-int.err +++ b/tests/qapi-schema/args-int.err @@ -1 +1 @@ -tests/qapi-schema/args-int.json:6: 'data' for command 'oops' cannot use built-in type 'int' +tests/qapi-schema/args-int.json:2: 'data' for command 'oops' cannot use built-in type 'int' diff --git a/tests/qapi-schema/args-int.json b/tests/qapi-schema/args-int.json index 7f4e1b7aa6..a334d92e8c 100644 --- a/tests/qapi-schema/args-int.json +++ b/tests/qapi-schema/args-int.json @@ -1,6 +1,2 @@ # we reject commands where data is not an array or complex type - -## -# @oops: -## { 'command': 'oops', 'data': 'int' } diff --git a/tests/qapi-schema/args-invalid.err b/tests/qapi-schema/args-invalid.err index 5d3568d7c3..fe1e94975b 100644 --- a/tests/qapi-schema/args-invalid.err +++ b/tests/qapi-schema/args-invalid.err @@ -1 +1 @@ -tests/qapi-schema/args-invalid.json:4: 'data' for command 'foo' should be a dictionary or type name +tests/qapi-schema/args-invalid.json:1: 'data' for command 'foo' should be a dictionary or type name diff --git a/tests/qapi-schema/args-invalid.json b/tests/qapi-schema/args-invalid.json index 1a7e63bb23..db0981341b 100644 --- a/tests/qapi-schema/args-invalid.json +++ b/tests/qapi-schema/args-invalid.json @@ -1,5 +1,2 @@ -## -# @foo: -## { 'command': 'foo', 'data': false } diff --git a/tests/qapi-schema/args-member-array-bad.err b/tests/qapi-schema/args-member-array-bad.err index 825ffca9bf..881b4d954f 100644 --- a/tests/qapi-schema/args-member-array-bad.err +++ b/tests/qapi-schema/args-member-array-bad.err @@ -1 +1 @@ -tests/qapi-schema/args-member-array-bad.json:6: Member 'member' of 'data' for command 'oops': array type must contain single type name +tests/qapi-schema/args-member-array-bad.json:2: Member 'member' of 'data' for command 'oops': array type must contain single type name diff --git a/tests/qapi-schema/args-member-array-bad.json b/tests/qapi-schema/args-member-array-bad.json index e934f5c457..b2ff144ec6 100644 --- a/tests/qapi-schema/args-member-array-bad.json +++ b/tests/qapi-schema/args-member-array-bad.json @@ -1,6 +1,2 @@ # we reject data if it does not contain a valid array type - -## -# @oops: -## { 'command': 'oops', 'data': { 'member': [ { 'nested': 'str' } ] } } diff --git a/tests/qapi-schema/args-member-case.err b/tests/qapi-schema/args-member-case.err index a3fb2bdd60..19c4426601 100644 --- a/tests/qapi-schema/args-member-case.err +++ b/tests/qapi-schema/args-member-case.err @@ -1 +1 @@ -tests/qapi-schema/args-member-case.json:6: 'Arg' (parameter of no-way-this-will-get-whitelisted) should not use uppercase +tests/qapi-schema/args-member-case.json:2: 'Arg' (parameter of no-way-this-will-get-whitelisted) should not use uppercase diff --git a/tests/qapi-schema/args-member-case.json b/tests/qapi-schema/args-member-case.json index 811e658d66..93439bee8b 100644 --- a/tests/qapi-schema/args-member-case.json +++ b/tests/qapi-schema/args-member-case.json @@ -1,6 +1,2 @@ # Member names should be 'lower-case' unless the struct/command is whitelisted - -## -# @no-way-this-will-get-whitelisted: -## { 'command': 'no-way-this-will-get-whitelisted', 'data': { 'Arg': 'int' } } diff --git a/tests/qapi-schema/args-member-unknown.err b/tests/qapi-schema/args-member-unknown.err index 3db452b95a..f6f82828ce 100644 --- a/tests/qapi-schema/args-member-unknown.err +++ b/tests/qapi-schema/args-member-unknown.err @@ -1 +1 @@ -tests/qapi-schema/args-member-unknown.json:6: Member 'member' of 'data' for command 'oops' uses unknown type 'NoSuchType' +tests/qapi-schema/args-member-unknown.json:2: Member 'member' of 'data' for command 'oops' uses unknown type 'NoSuchType' diff --git a/tests/qapi-schema/args-member-unknown.json b/tests/qapi-schema/args-member-unknown.json index e2fef9c46f..342a41ec90 100644 --- a/tests/qapi-schema/args-member-unknown.json +++ b/tests/qapi-schema/args-member-unknown.json @@ -1,6 +1,2 @@ # we reject data if it does not contain a known type - -## -# @oops: -## { 'command': 'oops', 'data': { 'member': 'NoSuchType' } } diff --git a/tests/qapi-schema/args-name-clash.err b/tests/qapi-schema/args-name-clash.err index 23988cb5ca..d953e8d241 100644 --- a/tests/qapi-schema/args-name-clash.err +++ b/tests/qapi-schema/args-name-clash.err @@ -1 +1 @@ -tests/qapi-schema/args-name-clash.json:8: 'a_b' (parameter of oops) collides with 'a-b' (parameter of oops) +tests/qapi-schema/args-name-clash.json:4: 'a_b' (parameter of oops) collides with 'a-b' (parameter of oops) diff --git a/tests/qapi-schema/args-name-clash.json b/tests/qapi-schema/args-name-clash.json index 991323b78d..61423cb893 100644 --- a/tests/qapi-schema/args-name-clash.json +++ b/tests/qapi-schema/args-name-clash.json @@ -1,8 +1,4 @@ # C member name collision # Reject members that clash when mapped to C names (we would have two 'a_b' # members). - -## -# @oops: -## { 'command': 'oops', 'data': { 'a-b': 'str', 'a_b': 'str' } } diff --git a/tests/qapi-schema/args-union.err b/tests/qapi-schema/args-union.err index ce0a34e16c..f8ad223dde 100644 --- a/tests/qapi-schema/args-union.err +++ b/tests/qapi-schema/args-union.err @@ -1 +1 @@ -tests/qapi-schema/args-union.json:10: 'data' for command 'oops' cannot use union type 'Uni' +tests/qapi-schema/args-union.json:3: 'data' for command 'oops' cannot use union type 'Uni' diff --git a/tests/qapi-schema/args-union.json b/tests/qapi-schema/args-union.json index 57284b43c5..2fcaeaae16 100644 --- a/tests/qapi-schema/args-union.json +++ b/tests/qapi-schema/args-union.json @@ -1,10 +1,3 @@ # use of union arguments requires 'boxed':true - -## -# @Uni: -## { 'union': 'Uni', 'data': { 'case1': 'int', 'case2': 'str' } } -## -# oops: -## { 'command': 'oops', 'data': 'Uni' } diff --git a/tests/qapi-schema/args-unknown.err b/tests/qapi-schema/args-unknown.err index ba6c6cf326..4d91ec869f 100644 --- a/tests/qapi-schema/args-unknown.err +++ b/tests/qapi-schema/args-unknown.err @@ -1 +1 @@ -tests/qapi-schema/args-unknown.json:6: 'data' for command 'oops' uses unknown type 'NoSuchType' +tests/qapi-schema/args-unknown.json:2: 'data' for command 'oops' uses unknown type 'NoSuchType' diff --git a/tests/qapi-schema/args-unknown.json b/tests/qapi-schema/args-unknown.json index 12666dc020..32aba43b3f 100644 --- a/tests/qapi-schema/args-unknown.json +++ b/tests/qapi-schema/args-unknown.json @@ -1,6 +1,2 @@ # we reject data if it does not contain a known type - -## -# @oops: -## { 'command': 'oops', 'data': 'NoSuchType' } diff --git a/tests/qapi-schema/bad-base.err b/tests/qapi-schema/bad-base.err index e668761c65..154274bdd3 100644 --- a/tests/qapi-schema/bad-base.err +++ b/tests/qapi-schema/bad-base.err @@ -1 +1 @@ -tests/qapi-schema/bad-base.json:10: 'base' for struct 'MyType' cannot use union type 'Union' +tests/qapi-schema/bad-base.json:3: 'base' for struct 'MyType' cannot use union type 'Union' diff --git a/tests/qapi-schema/bad-base.json b/tests/qapi-schema/bad-base.json index c3faa8242b..a634331cdd 100644 --- a/tests/qapi-schema/bad-base.json +++ b/tests/qapi-schema/bad-base.json @@ -1,10 +1,3 @@ # we reject a base that is not a struct - -## -# @Union: -## { 'union': 'Union', 'data': { 'a': 'int', 'b': 'str' } } -## -# @MyType: -## { 'struct': 'MyType', 'base': 'Union', 'data': { 'c': 'int' } } diff --git a/tests/qapi-schema/bad-data.err b/tests/qapi-schema/bad-data.err index c1b9e35313..8523ac4f46 100644 --- a/tests/qapi-schema/bad-data.err +++ b/tests/qapi-schema/bad-data.err @@ -1 +1 @@ -tests/qapi-schema/bad-data.json:6: 'data' for command 'oops' cannot be an array +tests/qapi-schema/bad-data.json:2: 'data' for command 'oops' cannot be an array diff --git a/tests/qapi-schema/bad-data.json b/tests/qapi-schema/bad-data.json index 51c444f4f8..832eeb76f4 100644 --- a/tests/qapi-schema/bad-data.json +++ b/tests/qapi-schema/bad-data.json @@ -1,6 +1,2 @@ # we ensure 'data' is a dictionary for all but enums - -## -# @oops: -## { 'command': 'oops', 'data': [ ] } diff --git a/tests/qapi-schema/bad-ident.err b/tests/qapi-schema/bad-ident.err index b757aa21e7..c4190602b5 100644 --- a/tests/qapi-schema/bad-ident.err +++ b/tests/qapi-schema/bad-ident.err @@ -1 +1 @@ -tests/qapi-schema/bad-ident.json:6: 'struct' does not allow optional name '*oops' +tests/qapi-schema/bad-ident.json:2: 'struct' does not allow optional name '*oops' diff --git a/tests/qapi-schema/bad-ident.json b/tests/qapi-schema/bad-ident.json index b43df7a3e0..763627ad23 100644 --- a/tests/qapi-schema/bad-ident.json +++ b/tests/qapi-schema/bad-ident.json @@ -1,6 +1,2 @@ # we reject creating a type name with bad name - -## -# @*oops: -## { 'struct': '*oops', 'data': { 'i': 'int' } } diff --git a/tests/qapi-schema/bad-type-bool.err b/tests/qapi-schema/bad-type-bool.err index 72e026b46c..62fd70baaf 100644 --- a/tests/qapi-schema/bad-type-bool.err +++ b/tests/qapi-schema/bad-type-bool.err @@ -1 +1 @@ -tests/qapi-schema/bad-type-bool.json:6: 'struct' key must have a string value +tests/qapi-schema/bad-type-bool.json:2: 'struct' key must have a string value diff --git a/tests/qapi-schema/bad-type-bool.json b/tests/qapi-schema/bad-type-bool.json index 1f9eddf938..bde17b56c4 100644 --- a/tests/qapi-schema/bad-type-bool.json +++ b/tests/qapi-schema/bad-type-bool.json @@ -1,6 +1,2 @@ # we reject an expression with a metatype that is not a string - -## -# @true: -## { 'struct': true, 'data': { } } diff --git a/tests/qapi-schema/bad-type-dict.err b/tests/qapi-schema/bad-type-dict.err index d0d1f607e5..0b2a2aeac4 100644 --- a/tests/qapi-schema/bad-type-dict.err +++ b/tests/qapi-schema/bad-type-dict.err @@ -1 +1 @@ -tests/qapi-schema/bad-type-dict.json:6: 'command' key must have a string value +tests/qapi-schema/bad-type-dict.json:2: 'command' key must have a string value diff --git a/tests/qapi-schema/bad-type-dict.json b/tests/qapi-schema/bad-type-dict.json index 5952caab28..2a91b241f8 100644 --- a/tests/qapi-schema/bad-type-dict.json +++ b/tests/qapi-schema/bad-type-dict.json @@ -1,6 +1,2 @@ # we reject an expression with a metatype that is not a string - -## -# @foo: -## { 'command': { } } diff --git a/tests/qapi-schema/base-cycle-direct.err b/tests/qapi-schema/base-cycle-direct.err index dd7f5aace6..9c68f6543d 100644 --- a/tests/qapi-schema/base-cycle-direct.err +++ b/tests/qapi-schema/base-cycle-direct.err @@ -1 +1 @@ -tests/qapi-schema/base-cycle-direct.json:6: Object Loopy contains itself +tests/qapi-schema/base-cycle-direct.json:2: Object Loopy contains itself diff --git a/tests/qapi-schema/base-cycle-direct.json b/tests/qapi-schema/base-cycle-direct.json index 9780f7e2ca..4fc66d0516 100644 --- a/tests/qapi-schema/base-cycle-direct.json +++ b/tests/qapi-schema/base-cycle-direct.json @@ -1,6 +1,2 @@ # we reject a loop in base classes - -## -# @Loopy: -## { 'struct': 'Loopy', 'base': 'Loopy', 'data': {} } diff --git a/tests/qapi-schema/base-cycle-indirect.err b/tests/qapi-schema/base-cycle-indirect.err index f4198e4a40..fc92fe47f8 100644 --- a/tests/qapi-schema/base-cycle-indirect.err +++ b/tests/qapi-schema/base-cycle-indirect.err @@ -1 +1 @@ -tests/qapi-schema/base-cycle-indirect.json:6: Object Base1 contains itself +tests/qapi-schema/base-cycle-indirect.json:2: Object Base1 contains itself diff --git a/tests/qapi-schema/base-cycle-indirect.json b/tests/qapi-schema/base-cycle-indirect.json index 99926c4609..28667721a3 100644 --- a/tests/qapi-schema/base-cycle-indirect.json +++ b/tests/qapi-schema/base-cycle-indirect.json @@ -1,10 +1,3 @@ # we reject a loop in base classes - -## -# @Base1: -## { 'struct': 'Base1', 'base': 'Base2', 'data': {} } -## -# @Base2: -## { 'struct': 'Base2', 'base': 'Base1', 'data': {} } diff --git a/tests/qapi-schema/command-int.err b/tests/qapi-schema/command-int.err index 3c834a97ab..0f9300679b 100644 --- a/tests/qapi-schema/command-int.err +++ b/tests/qapi-schema/command-int.err @@ -1 +1 @@ -tests/qapi-schema/command-int.json:6: built-in 'int' is already defined +tests/qapi-schema/command-int.json:2: built-in 'int' is already defined diff --git a/tests/qapi-schema/command-int.json b/tests/qapi-schema/command-int.json index 5b51bf148b..9a62554fc6 100644 --- a/tests/qapi-schema/command-int.json +++ b/tests/qapi-schema/command-int.json @@ -1,6 +1,2 @@ # we reject collisions between commands and types - -## -# @int: -## { 'command': 'int', 'data': { 'character': 'str' } } diff --git a/tests/qapi-schema/comments.json b/tests/qapi-schema/comments.json index d31ef0d90a..e643f3a74c 100644 --- a/tests/qapi-schema/comments.json +++ b/tests/qapi-schema/comments.json @@ -1,8 +1,4 @@ # Unindented comment - -## -# @Status: -## { 'enum': 'Status', # Comment to the right of code # Indented comment 'data': [ 'good', 'bad', 'ugly' ] } diff --git a/tests/qapi-schema/comments.out b/tests/qapi-schema/comments.out index a962fb2d2e..5d7c13cad1 100644 --- a/tests/qapi-schema/comments.out +++ b/tests/qapi-schema/comments.out @@ -2,4 +2,3 @@ enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbo prefix QTYPE enum Status ['good', 'bad', 'ugly'] object q_empty -doc symbol=Status expr=('enum', 'Status') diff --git a/tests/qapi-schema/doc-bad-alternate-member.err b/tests/qapi-schema/doc-bad-alternate-member.err new file mode 100644 index 0000000000..387f7824da --- /dev/null +++ b/tests/qapi-schema/doc-bad-alternate-member.err @@ -0,0 +1 @@ +tests/qapi-schema/doc-bad-alternate-member.json:3: The following documented members are not in the declaration: aa, bb diff --git a/tests/qapi-schema/doc-bad-args.exit b/tests/qapi-schema/doc-bad-alternate-member.exit index d00491fd7e..d00491fd7e 100644 --- a/tests/qapi-schema/doc-bad-args.exit +++ b/tests/qapi-schema/doc-bad-alternate-member.exit diff --git a/tests/qapi-schema/doc-bad-alternate-member.json b/tests/qapi-schema/doc-bad-alternate-member.json new file mode 100644 index 0000000000..738635ca8f --- /dev/null +++ b/tests/qapi-schema/doc-bad-alternate-member.json @@ -0,0 +1,9 @@ +# Arguments listed in the doc comment must exist in the actual schema + +## +# @AorB: +# @aa: a +# @bb: b +## +{ 'alternate': 'AorB', + 'data': { 'a': 'str', 'b': 'int' } } diff --git a/tests/qapi-schema/doc-bad-args.out b/tests/qapi-schema/doc-bad-alternate-member.out index e69de29bb2..e69de29bb2 100644 --- a/tests/qapi-schema/doc-bad-args.out +++ b/tests/qapi-schema/doc-bad-alternate-member.out diff --git a/tests/qapi-schema/doc-bad-args.err b/tests/qapi-schema/doc-bad-args.err deleted file mode 100644 index 5d44d9b668..0000000000 --- a/tests/qapi-schema/doc-bad-args.err +++ /dev/null @@ -1 +0,0 @@ -tests/qapi-schema/doc-bad-args.json:3: The following documented members are not in the declaration: b diff --git a/tests/qapi-schema/doc-bad-command-arg.err b/tests/qapi-schema/doc-bad-command-arg.err new file mode 100644 index 0000000000..8075b146ae --- /dev/null +++ b/tests/qapi-schema/doc-bad-command-arg.err @@ -0,0 +1 @@ +tests/qapi-schema/doc-bad-command-arg.json:3: The following documented members are not in the declaration: b diff --git a/tests/qapi-schema/doc-optional.exit b/tests/qapi-schema/doc-bad-command-arg.exit index d00491fd7e..d00491fd7e 100644 --- a/tests/qapi-schema/doc-optional.exit +++ b/tests/qapi-schema/doc-bad-command-arg.exit diff --git a/tests/qapi-schema/doc-bad-args.json b/tests/qapi-schema/doc-bad-command-arg.json index 048e0fc5ef..048e0fc5ef 100644 --- a/tests/qapi-schema/doc-bad-args.json +++ b/tests/qapi-schema/doc-bad-command-arg.json diff --git a/tests/qapi-schema/doc-optional.out b/tests/qapi-schema/doc-bad-command-arg.out index e69de29bb2..e69de29bb2 100644 --- a/tests/qapi-schema/doc-optional.out +++ b/tests/qapi-schema/doc-bad-command-arg.out diff --git a/tests/qapi-schema/doc-bad-symbol.err b/tests/qapi-schema/doc-bad-symbol.err index ac4e5667cb..8472030c79 100644 --- a/tests/qapi-schema/doc-bad-symbol.err +++ b/tests/qapi-schema/doc-bad-symbol.err @@ -1 +1 @@ -tests/qapi-schema/doc-bad-symbol.json:3: Definition of 'foo' follows documentation for 'food' +tests/qapi-schema/doc-bad-symbol.json:6: Definition of 'foo' follows documentation for 'food' diff --git a/tests/qapi-schema/doc-bad-union-member.err b/tests/qapi-schema/doc-bad-union-member.err new file mode 100644 index 0000000000..4b016df7ff --- /dev/null +++ b/tests/qapi-schema/doc-bad-union-member.err @@ -0,0 +1 @@ +tests/qapi-schema/doc-bad-union-member.json:3: The following documented members are not in the declaration: a, b diff --git a/tests/qapi-schema/doc-bad-union-member.exit b/tests/qapi-schema/doc-bad-union-member.exit new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/tests/qapi-schema/doc-bad-union-member.exit @@ -0,0 +1 @@ +1 diff --git a/tests/qapi-schema/doc-bad-union-member.json b/tests/qapi-schema/doc-bad-union-member.json new file mode 100644 index 0000000000..d611435f6a --- /dev/null +++ b/tests/qapi-schema/doc-bad-union-member.json @@ -0,0 +1,19 @@ +# Arguments listed in the doc comment must exist in the actual schema + +## +# @Frob: +# @a: a +# @b: b +## +{ 'union': 'Frob', + 'base': 'Base', + 'discriminator': 'type', + 'data': { 'nothing': 'Empty' } } + +{ 'struct': 'Base', + 'data': { 'type': 'T' } } + +{ 'struct': 'Empty', + 'data': { } } + +{ 'enum': 'T', 'data': ['nothing'] } diff --git a/tests/qapi-schema/doc-bad-union-member.out b/tests/qapi-schema/doc-bad-union-member.out new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/qapi-schema/doc-bad-union-member.out diff --git a/tests/qapi-schema/doc-before-include.err b/tests/qapi-schema/doc-before-include.err new file mode 100644 index 0000000000..a649d38a63 --- /dev/null +++ b/tests/qapi-schema/doc-before-include.err @@ -0,0 +1 @@ +tests/qapi-schema/doc-before-include.json:3: Documentation for 'foo' is not followed by the definition diff --git a/tests/qapi-schema/doc-before-include.exit b/tests/qapi-schema/doc-before-include.exit new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/tests/qapi-schema/doc-before-include.exit @@ -0,0 +1 @@ +1 diff --git a/tests/qapi-schema/doc-before-include.json b/tests/qapi-schema/doc-before-include.json new file mode 100644 index 0000000000..0caa0ae079 --- /dev/null +++ b/tests/qapi-schema/doc-before-include.json @@ -0,0 +1,7 @@ +# Doc comment separated from defining expression by non-defining expression + +## +# @foo: +## +{ 'include': 'empty.json' } +{ 'struct': 'foo', 'data': {} } diff --git a/tests/qapi-schema/doc-before-include.out b/tests/qapi-schema/doc-before-include.out new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/qapi-schema/doc-before-include.out diff --git a/tests/qapi-schema/doc-before-pragma.err b/tests/qapi-schema/doc-before-pragma.err new file mode 100644 index 0000000000..c0fb0660d1 --- /dev/null +++ b/tests/qapi-schema/doc-before-pragma.err @@ -0,0 +1 @@ +tests/qapi-schema/doc-before-pragma.json:3: Documentation for 'foo' is not followed by the definition diff --git a/tests/qapi-schema/doc-before-pragma.exit b/tests/qapi-schema/doc-before-pragma.exit new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/tests/qapi-schema/doc-before-pragma.exit @@ -0,0 +1 @@ +1 diff --git a/tests/qapi-schema/doc-before-pragma.json b/tests/qapi-schema/doc-before-pragma.json new file mode 100644 index 0000000000..a6e090e44a --- /dev/null +++ b/tests/qapi-schema/doc-before-pragma.json @@ -0,0 +1,7 @@ +# Doc comment separated from defining expression by non-defining expression + +## +# @foo: +## +{ 'pragma': {} } +{ 'struct': 'foo', 'data': {} } diff --git a/tests/qapi-schema/doc-before-pragma.out b/tests/qapi-schema/doc-before-pragma.out new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/qapi-schema/doc-before-pragma.out diff --git a/tests/qapi-schema/doc-empty-section.err b/tests/qapi-schema/doc-empty-section.err index 00ad625e17..b61e4a7886 100644 --- a/tests/qapi-schema/doc-empty-section.err +++ b/tests/qapi-schema/doc-empty-section.err @@ -1 +1 @@ -tests/qapi-schema/doc-empty-section.json:3: Empty doc section 'Note' +tests/qapi-schema/doc-empty-section.json:7:1: Empty doc section 'Note' diff --git a/tests/qapi-schema/doc-invalid-section.err b/tests/qapi-schema/doc-invalid-section.err index 85bb67b829..bda93b44fd 100644 --- a/tests/qapi-schema/doc-invalid-section.err +++ b/tests/qapi-schema/doc-invalid-section.err @@ -1 +1 @@ -tests/qapi-schema/doc-invalid-section.json:3: Free-form documentation block must not contain @NAME: sections +tests/qapi-schema/doc-invalid-section.json:5:1: '@note:' not allowed in free-form documentation diff --git a/tests/qapi-schema/doc-missing-expr.err b/tests/qapi-schema/doc-missing-expr.err index c0e687cadd..c909e26eca 100644 --- a/tests/qapi-schema/doc-missing-expr.err +++ b/tests/qapi-schema/doc-missing-expr.err @@ -1 +1 @@ -tests/qapi-schema/doc-missing-expr.json:3: Documention for 'bar' is not followed by the definition +tests/qapi-schema/doc-missing-expr.json:3: Documentation for 'bar' is not followed by the definition diff --git a/tests/qapi-schema/doc-missing.err b/tests/qapi-schema/doc-missing.err new file mode 100644 index 0000000000..7f2f326b30 --- /dev/null +++ b/tests/qapi-schema/doc-missing.err @@ -0,0 +1 @@ +tests/qapi-schema/doc-missing.json:5: Expression missing documentation comment diff --git a/tests/qapi-schema/doc-missing.exit b/tests/qapi-schema/doc-missing.exit new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/tests/qapi-schema/doc-missing.exit @@ -0,0 +1 @@ +1 diff --git a/tests/qapi-schema/doc-missing.json b/tests/qapi-schema/doc-missing.json new file mode 100644 index 0000000000..5956709742 --- /dev/null +++ b/tests/qapi-schema/doc-missing.json @@ -0,0 +1,5 @@ +# Expression documentation required + +{ 'pragma': { 'doc-required': true } } + +{ 'command': 'undocumented' } diff --git a/tests/qapi-schema/doc-missing.out b/tests/qapi-schema/doc-missing.out new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/qapi-schema/doc-missing.out diff --git a/tests/qapi-schema/doc-no-symbol.err b/tests/qapi-schema/doc-no-symbol.err new file mode 100644 index 0000000000..75f032a942 --- /dev/null +++ b/tests/qapi-schema/doc-no-symbol.err @@ -0,0 +1 @@ +tests/qapi-schema/doc-no-symbol.json:3: Expression documentation required diff --git a/tests/qapi-schema/doc-no-symbol.exit b/tests/qapi-schema/doc-no-symbol.exit new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/tests/qapi-schema/doc-no-symbol.exit @@ -0,0 +1 @@ +1 diff --git a/tests/qapi-schema/doc-no-symbol.json b/tests/qapi-schema/doc-no-symbol.json new file mode 100644 index 0000000000..98605bab96 --- /dev/null +++ b/tests/qapi-schema/doc-no-symbol.json @@ -0,0 +1,6 @@ +# Documentation for expression lacks symbol + +## +# foo: +## +{ 'command': 'foo', 'data': {'a': 'int'} } diff --git a/tests/qapi-schema/doc-no-symbol.out b/tests/qapi-schema/doc-no-symbol.out new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/qapi-schema/doc-no-symbol.out diff --git a/tests/qapi-schema/doc-optional.err b/tests/qapi-schema/doc-optional.err deleted file mode 100644 index 20d405af79..0000000000 --- a/tests/qapi-schema/doc-optional.err +++ /dev/null @@ -1 +0,0 @@ -tests/qapi-schema/doc-optional.json:3: Description has #optional, but the declaration doesn't diff --git a/tests/qapi-schema/doc-optional.json b/tests/qapi-schema/doc-optional.json deleted file mode 100644 index 06c855ec94..0000000000 --- a/tests/qapi-schema/doc-optional.json +++ /dev/null @@ -1,7 +0,0 @@ -# Description #optional should match declaration - -## -# @foo: -# @a: a #optional -## -{ 'command': 'foo', 'data': {'a': 'int'} } diff --git a/tests/qapi-schema/double-type.err b/tests/qapi-schema/double-type.err index 424df9bedd..f9613c6d6b 100644 --- a/tests/qapi-schema/double-type.err +++ b/tests/qapi-schema/double-type.err @@ -1 +1 @@ -tests/qapi-schema/double-type.json:6: Unknown key 'command' in struct 'bar' +tests/qapi-schema/double-type.json:2: Unknown key 'command' in struct 'bar' diff --git a/tests/qapi-schema/double-type.json b/tests/qapi-schema/double-type.json index ab59523ff7..911fa7af50 100644 --- a/tests/qapi-schema/double-type.json +++ b/tests/qapi-schema/double-type.json @@ -1,6 +1,2 @@ # we reject an expression with ambiguous metatype - -## -# @foo: -## { 'command': 'foo', 'struct': 'bar', 'data': { } } diff --git a/tests/qapi-schema/enum-bad-name.err b/tests/qapi-schema/enum-bad-name.err index 157d1b0d69..9c3c1002b7 100644 --- a/tests/qapi-schema/enum-bad-name.err +++ b/tests/qapi-schema/enum-bad-name.err @@ -1 +1 @@ -tests/qapi-schema/enum-bad-name.json:6: Member of enum 'MyEnum' uses invalid name 'not^possible' +tests/qapi-schema/enum-bad-name.json:2: Member of enum 'MyEnum' uses invalid name 'not^possible' diff --git a/tests/qapi-schema/enum-bad-name.json b/tests/qapi-schema/enum-bad-name.json index 978cb88994..8506562b31 100644 --- a/tests/qapi-schema/enum-bad-name.json +++ b/tests/qapi-schema/enum-bad-name.json @@ -1,6 +1,2 @@ # we ensure all enum names can map to C - -## -# @MyEnum: -## { 'enum': 'MyEnum', 'data': [ 'not^possible' ] } diff --git a/tests/qapi-schema/enum-bad-prefix.err b/tests/qapi-schema/enum-bad-prefix.err index 918915f7ab..399f5f7af5 100644 --- a/tests/qapi-schema/enum-bad-prefix.err +++ b/tests/qapi-schema/enum-bad-prefix.err @@ -1 +1 @@ -tests/qapi-schema/enum-bad-prefix.json:6: Enum 'MyEnum' requires a string for 'prefix' +tests/qapi-schema/enum-bad-prefix.json:2: Enum 'MyEnum' requires a string for 'prefix' diff --git a/tests/qapi-schema/enum-bad-prefix.json b/tests/qapi-schema/enum-bad-prefix.json index 25f17a7b08..996f628f6d 100644 --- a/tests/qapi-schema/enum-bad-prefix.json +++ b/tests/qapi-schema/enum-bad-prefix.json @@ -1,6 +1,2 @@ # The prefix must be a string type - -## -# @MyEnum: -## { 'enum': 'MyEnum', 'data': [ 'one' ], 'prefix': [ 'fish' ] } diff --git a/tests/qapi-schema/enum-clash-member.err b/tests/qapi-schema/enum-clash-member.err index 25249b63c4..5403c78507 100644 --- a/tests/qapi-schema/enum-clash-member.err +++ b/tests/qapi-schema/enum-clash-member.err @@ -1 +1 @@ -tests/qapi-schema/enum-clash-member.json:6: 'one_two' (member of MyEnum) collides with 'one-two' (member of MyEnum) +tests/qapi-schema/enum-clash-member.json:2: 'one_two' (member of MyEnum) collides with 'one-two' (member of MyEnum) diff --git a/tests/qapi-schema/enum-clash-member.json b/tests/qapi-schema/enum-clash-member.json index fd52751941..b6928b8bfd 100644 --- a/tests/qapi-schema/enum-clash-member.json +++ b/tests/qapi-schema/enum-clash-member.json @@ -1,6 +1,2 @@ # we reject enums where members will clash when mapped to C enum - -## -# @MyEnum: -## { 'enum': 'MyEnum', 'data': [ 'one-two', 'one_two' ] } diff --git a/tests/qapi-schema/enum-dict-member.err b/tests/qapi-schema/enum-dict-member.err index 9b7d2f111d..8ca146ea59 100644 --- a/tests/qapi-schema/enum-dict-member.err +++ b/tests/qapi-schema/enum-dict-member.err @@ -1 +1 @@ -tests/qapi-schema/enum-dict-member.json:6: Member of enum 'MyEnum' requires a string name +tests/qapi-schema/enum-dict-member.json:2: Member of enum 'MyEnum' requires a string name diff --git a/tests/qapi-schema/enum-dict-member.json b/tests/qapi-schema/enum-dict-member.json index 69d30f0c1e..79672e0f09 100644 --- a/tests/qapi-schema/enum-dict-member.json +++ b/tests/qapi-schema/enum-dict-member.json @@ -1,6 +1,2 @@ # we reject any enum member that is not a string - -## -# @MyEnum: -## { 'enum': 'MyEnum', 'data': [ { 'value': 'str' } ] } diff --git a/tests/qapi-schema/enum-member-case.err b/tests/qapi-schema/enum-member-case.err index df96e2205a..3c67a3a067 100644 --- a/tests/qapi-schema/enum-member-case.err +++ b/tests/qapi-schema/enum-member-case.err @@ -1 +1 @@ -tests/qapi-schema/enum-member-case.json:10: 'Value' (member of NoWayThisWillGetWhitelisted) should not use uppercase +tests/qapi-schema/enum-member-case.json:4: 'Value' (member of NoWayThisWillGetWhitelisted) should not use uppercase diff --git a/tests/qapi-schema/enum-member-case.json b/tests/qapi-schema/enum-member-case.json index d2e4aba39d..f8af3e4622 100644 --- a/tests/qapi-schema/enum-member-case.json +++ b/tests/qapi-schema/enum-member-case.json @@ -1,10 +1,4 @@ # Member names should be 'lower-case' unless the enum is whitelisted - -## -# @UuidInfo: -## +{ 'pragma': { 'name-case-whitelist': [ 'UuidInfo' ] } } { 'enum': 'UuidInfo', 'data': [ 'Value' ] } # UuidInfo is whitelisted -## -# @NoWayThisWillGetWhitelisted: -## { 'enum': 'NoWayThisWillGetWhitelisted', 'data': [ 'Value' ] } diff --git a/tests/qapi-schema/enum-missing-data.err b/tests/qapi-schema/enum-missing-data.err index de4b9e8281..ba4873ae69 100644 --- a/tests/qapi-schema/enum-missing-data.err +++ b/tests/qapi-schema/enum-missing-data.err @@ -1 +1 @@ -tests/qapi-schema/enum-missing-data.json:6: Key 'data' is missing from enum 'MyEnum' +tests/qapi-schema/enum-missing-data.json:2: Key 'data' is missing from enum 'MyEnum' diff --git a/tests/qapi-schema/enum-missing-data.json b/tests/qapi-schema/enum-missing-data.json index d7601f91fb..558fd35e93 100644 --- a/tests/qapi-schema/enum-missing-data.json +++ b/tests/qapi-schema/enum-missing-data.json @@ -1,6 +1,2 @@ # we require that all QAPI enums have a data array - -## -# @MyEnum: -## { 'enum': 'MyEnum' } diff --git a/tests/qapi-schema/enum-wrong-data.err b/tests/qapi-schema/enum-wrong-data.err index c44e9b59dc..11b43471cf 100644 --- a/tests/qapi-schema/enum-wrong-data.err +++ b/tests/qapi-schema/enum-wrong-data.err @@ -1 +1 @@ -tests/qapi-schema/enum-wrong-data.json:6: Enum 'MyEnum' requires an array for 'data' +tests/qapi-schema/enum-wrong-data.json:2: Enum 'MyEnum' requires an array for 'data' diff --git a/tests/qapi-schema/enum-wrong-data.json b/tests/qapi-schema/enum-wrong-data.json index 4b9e97878b..7b3e255c14 100644 --- a/tests/qapi-schema/enum-wrong-data.json +++ b/tests/qapi-schema/enum-wrong-data.json @@ -1,6 +1,2 @@ # we require that all qapi enums have an array for data - -## -# @MyEnum: -## { 'enum': 'MyEnum', 'data': { 'value': 'str' } } diff --git a/tests/qapi-schema/event-boxed-empty.err b/tests/qapi-schema/event-boxed-empty.err index defe656e32..68ec6f2d2b 100644 --- a/tests/qapi-schema/event-boxed-empty.err +++ b/tests/qapi-schema/event-boxed-empty.err @@ -1 +1 @@ -tests/qapi-schema/event-boxed-empty.json:6: Use of 'boxed' requires 'data' +tests/qapi-schema/event-boxed-empty.json:2: Use of 'boxed' requires 'data' diff --git a/tests/qapi-schema/event-boxed-empty.json b/tests/qapi-schema/event-boxed-empty.json index 63b870b31b..cb145f1433 100644 --- a/tests/qapi-schema/event-boxed-empty.json +++ b/tests/qapi-schema/event-boxed-empty.json @@ -1,6 +1,2 @@ # 'boxed' requires a non-empty type - -## -# @FOO: -## { 'event': 'FOO', 'boxed': true } diff --git a/tests/qapi-schema/event-case.json b/tests/qapi-schema/event-case.json index 6b05c5d247..3a92d8b610 100644 --- a/tests/qapi-schema/event-case.json +++ b/tests/qapi-schema/event-case.json @@ -1,7 +1,3 @@ # TODO: might be nice to enforce naming conventions; but until then this works # even though events should usually be ALL_CAPS - -## -# @oops: -## { 'event': 'oops' } diff --git a/tests/qapi-schema/event-case.out b/tests/qapi-schema/event-case.out index 2865714ad5..5a0f2bf805 100644 --- a/tests/qapi-schema/event-case.out +++ b/tests/qapi-schema/event-case.out @@ -3,4 +3,3 @@ enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbo event oops None boxed=False object q_empty -doc symbol=oops expr=('event', 'oops') diff --git a/tests/qapi-schema/event-nest-struct.err b/tests/qapi-schema/event-nest-struct.err index 17a6c3c7b9..5a42701b8f 100644 --- a/tests/qapi-schema/event-nest-struct.err +++ b/tests/qapi-schema/event-nest-struct.err @@ -1 +1 @@ -tests/qapi-schema/event-nest-struct.json:5: Member 'a' of 'data' for event 'EVENT_A' should be a type name +tests/qapi-schema/event-nest-struct.json:1: Member 'a' of 'data' for event 'EVENT_A' should be a type name diff --git a/tests/qapi-schema/event-nest-struct.json b/tests/qapi-schema/event-nest-struct.json index 328e0a64d3..ee6f3ecb6f 100644 --- a/tests/qapi-schema/event-nest-struct.json +++ b/tests/qapi-schema/event-nest-struct.json @@ -1,6 +1,2 @@ -## -# @EVENT_A: -# event-nest-struct -## { 'event': 'EVENT_A', 'data': { 'a' : { 'string' : 'str', 'integer': 'int' }, 'b' : 'str' } } diff --git a/tests/qapi-schema/flat-union-array-branch.err b/tests/qapi-schema/flat-union-array-branch.err index e456094993..8ea91eadb2 100644 --- a/tests/qapi-schema/flat-union-array-branch.err +++ b/tests/qapi-schema/flat-union-array-branch.err @@ -1 +1 @@ -tests/qapi-schema/flat-union-array-branch.json:20: Member 'value1' of union 'TestUnion' cannot be an array +tests/qapi-schema/flat-union-array-branch.json:8: Member 'value1' of union 'TestUnion' cannot be an array diff --git a/tests/qapi-schema/flat-union-array-branch.json b/tests/qapi-schema/flat-union-array-branch.json index 51dde10392..0b98820a8f 100644 --- a/tests/qapi-schema/flat-union-array-branch.json +++ b/tests/qapi-schema/flat-union-array-branch.json @@ -1,22 +1,10 @@ -## -# @TestEnum: -## # we require flat union branches to be a struct { 'enum': 'TestEnum', 'data': [ 'value1', 'value2' ] } -## -# @Base: -## { 'struct': 'Base', 'data': { 'enum1': 'TestEnum' } } -## -# @TestTypeB: -## { 'struct': 'TestTypeB', 'data': { 'integer': 'int' } } -## -# @TestUnion: -## { 'union': 'TestUnion', 'base': 'Base', 'discriminator': 'enum1', diff --git a/tests/qapi-schema/flat-union-bad-base.err b/tests/qapi-schema/flat-union-bad-base.err index 072ffbaadd..bee24a217a 100644 --- a/tests/qapi-schema/flat-union-bad-base.err +++ b/tests/qapi-schema/flat-union-bad-base.err @@ -1 +1 @@ -tests/qapi-schema/flat-union-bad-base.json:21: 'string' (member of TestTypeA) collides with 'string' (base of TestUnion) +tests/qapi-schema/flat-union-bad-base.json:8: 'string' (member of TestTypeA) collides with 'string' (base of TestUnion) diff --git a/tests/qapi-schema/flat-union-bad-base.json b/tests/qapi-schema/flat-union-bad-base.json index 7713e7f0ad..74dd421708 100644 --- a/tests/qapi-schema/flat-union-bad-base.json +++ b/tests/qapi-schema/flat-union-bad-base.json @@ -1,23 +1,10 @@ # we allow anonymous base, but enforce no duplicate keys - -## -# @TestEnum: -## { 'enum': 'TestEnum', 'data': [ 'value1', 'value2' ] } -## -# @TestTypeA: -## { 'struct': 'TestTypeA', 'data': { 'string': 'str' } } -## -# @TestTypeB: -## { 'struct': 'TestTypeB', 'data': { 'integer': 'int' } } -## -# @TestUnion: -## { 'union': 'TestUnion', 'base': { 'enum1': 'TestEnum', 'string': 'str' }, 'discriminator': 'enum1', diff --git a/tests/qapi-schema/flat-union-bad-discriminator.err b/tests/qapi-schema/flat-union-bad-discriminator.err index 1be4e7b23a..c38cc8e4df 100644 --- a/tests/qapi-schema/flat-union-bad-discriminator.err +++ b/tests/qapi-schema/flat-union-bad-discriminator.err @@ -1 +1 @@ -tests/qapi-schema/flat-union-bad-discriminator.json:27: Discriminator of flat union 'TestUnion' requires a string name +tests/qapi-schema/flat-union-bad-discriminator.json:11: Discriminator of flat union 'TestUnion' requires a string name diff --git a/tests/qapi-schema/flat-union-bad-discriminator.json b/tests/qapi-schema/flat-union-bad-discriminator.json index ef92f9b583..cd10b9d901 100644 --- a/tests/qapi-schema/flat-union-bad-discriminator.json +++ b/tests/qapi-schema/flat-union-bad-discriminator.json @@ -1,29 +1,13 @@ # we require the discriminator to be a string naming a base-type member # this tests the old syntax for anonymous unions before we added alternates - -## -# @TestEnum: -## { 'enum': 'TestEnum', 'data': [ 'value1', 'value2' ] } -## -# @TestBase: -## { 'struct': 'TestBase', 'data': { 'enum1': 'TestEnum', 'kind': 'str' } } -## -# @TestTypeA: -## { 'struct': 'TestTypeA', 'data': { 'string': 'str' } } -## -# @TestTypeB: -## { 'struct': 'TestTypeB', 'data': { 'integer': 'int' } } -## -# @TestUnion: -## { 'union': 'TestUnion', 'base': 'TestBase', 'discriminator': {}, diff --git a/tests/qapi-schema/flat-union-base-any.err b/tests/qapi-schema/flat-union-base-any.err index c1ea2d76b3..646f1c9cd1 100644 --- a/tests/qapi-schema/flat-union-base-any.err +++ b/tests/qapi-schema/flat-union-base-any.err @@ -1 +1 @@ -tests/qapi-schema/flat-union-base-any.json:21: 'base' for union 'TestUnion' cannot use built-in type 'any' +tests/qapi-schema/flat-union-base-any.json:8: 'base' for union 'TestUnion' cannot use built-in type 'any' diff --git a/tests/qapi-schema/flat-union-base-any.json b/tests/qapi-schema/flat-union-base-any.json index 3dfb02fa30..fe66b713ef 100644 --- a/tests/qapi-schema/flat-union-base-any.json +++ b/tests/qapi-schema/flat-union-base-any.json @@ -1,23 +1,10 @@ # we require the base to be an existing struct - -## -# @TestEnum: -## { 'enum': 'TestEnum', 'data': [ 'value1', 'value2' ] } -## -# @TestTypeA: -## { 'struct': 'TestTypeA', 'data': { 'string': 'str' } } -## -# @TestTypeB: -## { 'struct': 'TestTypeB', 'data': { 'integer': 'int' } } -## -# @TestUnion: -## { 'union': 'TestUnion', 'base': 'any', 'discriminator': 'enum1', diff --git a/tests/qapi-schema/flat-union-base-union.err b/tests/qapi-schema/flat-union-base-union.err index ccc5e85876..f138395e45 100644 --- a/tests/qapi-schema/flat-union-base-union.err +++ b/tests/qapi-schema/flat-union-base-union.err @@ -1 +1 @@ -tests/qapi-schema/flat-union-base-union.json:30: 'base' for union 'TestUnion' cannot use union type 'UnionBase' +tests/qapi-schema/flat-union-base-union.json:14: 'base' for union 'TestUnion' cannot use union type 'UnionBase' diff --git a/tests/qapi-schema/flat-union-base-union.json b/tests/qapi-schema/flat-union-base-union.json index c63c6130b8..98b4eba181 100644 --- a/tests/qapi-schema/flat-union-base-union.json +++ b/tests/qapi-schema/flat-union-base-union.json @@ -2,31 +2,15 @@ # TODO: It would be possible to allow a union as a base, as long as all # permutations of QMP names exposed by base do not clash with any QMP # member names added by local variants. - -## -# @TestEnum: -## { 'enum': 'TestEnum', 'data': [ 'value1', 'value2' ] } -## -# @TestTypeA: -## { 'struct': 'TestTypeA', 'data': { 'string': 'str' } } -## -# @TestTypeB: -## { 'struct': 'TestTypeB', 'data': { 'integer': 'int' } } -## -# @UnionBase: -## { 'union': 'UnionBase', 'data': { 'kind1': 'TestTypeA', 'kind2': 'TestTypeB' } } -## -# @TestUnion: -## { 'union': 'TestUnion', 'base': 'UnionBase', 'discriminator': 'type', diff --git a/tests/qapi-schema/flat-union-clash-member.err b/tests/qapi-schema/flat-union-clash-member.err index fe12a07e2d..2adf69755a 100644 --- a/tests/qapi-schema/flat-union-clash-member.err +++ b/tests/qapi-schema/flat-union-clash-member.err @@ -1 +1 @@ -tests/qapi-schema/flat-union-clash-member.json:27: 'name' (member of Branch1) collides with 'name' (member of Base) +tests/qapi-schema/flat-union-clash-member.json:11: 'name' (member of Branch1) collides with 'name' (member of Base) diff --git a/tests/qapi-schema/flat-union-clash-member.json b/tests/qapi-schema/flat-union-clash-member.json index 9000b94f16..9efc7719b8 100644 --- a/tests/qapi-schema/flat-union-clash-member.json +++ b/tests/qapi-schema/flat-union-clash-member.json @@ -1,29 +1,13 @@ # We check for no duplicate keys between branch members and base # base's member 'name' clashes with Branch1's - -## -# @TestEnum: -## { 'enum': 'TestEnum', 'data': [ 'value1', 'value2' ] } -## -# @Base: -## { 'struct': 'Base', 'data': { 'enum1': 'TestEnum', '*name': 'str' } } -## -# @Branch1: -## { 'struct': 'Branch1', 'data': { 'name': 'str' } } -## -# @Branch2: -## { 'struct': 'Branch2', 'data': { 'value': 'int' } } -## -# @TestUnion: -## { 'union': 'TestUnion', 'base': 'Base', 'discriminator': 'enum1', diff --git a/tests/qapi-schema/flat-union-empty.err b/tests/qapi-schema/flat-union-empty.err index ead7bd4fcb..15754f54eb 100644 --- a/tests/qapi-schema/flat-union-empty.err +++ b/tests/qapi-schema/flat-union-empty.err @@ -1 +1 @@ -tests/qapi-schema/flat-union-empty.json:14: Union 'Union' cannot have empty 'data' +tests/qapi-schema/flat-union-empty.json:4: Union 'Union' cannot have empty 'data' diff --git a/tests/qapi-schema/flat-union-empty.json b/tests/qapi-schema/flat-union-empty.json index afa8988205..77f1d9abfb 100644 --- a/tests/qapi-schema/flat-union-empty.json +++ b/tests/qapi-schema/flat-union-empty.json @@ -1,14 +1,4 @@ # flat unions cannot be empty - -## -# @Empty: -## { 'enum': 'Empty', 'data': [ ] } -## -# @Base: -## { 'struct': 'Base', 'data': { 'type': 'Empty' } } -## -# @Union: -## { 'union': 'Union', 'base': 'Base', 'discriminator': 'type', 'data': { } } diff --git a/tests/qapi-schema/flat-union-incomplete-branch.err b/tests/qapi-schema/flat-union-incomplete-branch.err index c655bbfb4a..e826bf0789 100644 --- a/tests/qapi-schema/flat-union-incomplete-branch.err +++ b/tests/qapi-schema/flat-union-incomplete-branch.err @@ -1 +1 @@ -tests/qapi-schema/flat-union-incomplete-branch.json:16: Union 'TestUnion' data missing 'value2' branch +tests/qapi-schema/flat-union-incomplete-branch.json:6: Union 'TestUnion' data missing 'value2' branch diff --git a/tests/qapi-schema/flat-union-incomplete-branch.json b/tests/qapi-schema/flat-union-incomplete-branch.json index dea03775c7..25a411bc83 100644 --- a/tests/qapi-schema/flat-union-incomplete-branch.json +++ b/tests/qapi-schema/flat-union-incomplete-branch.json @@ -1,18 +1,8 @@ # we require all branches of the union to be covered - -## -# @TestEnum: -## { 'enum': 'TestEnum', 'data': [ 'value1', 'value2' ] } -## -# @TestTypeA: -## { 'struct': 'TestTypeA', 'data': { 'string': 'str' } } -## -# @TestUnion: -## { 'union': 'TestUnion', 'base': { 'type': 'TestEnum' }, 'discriminator': 'type', diff --git a/tests/qapi-schema/flat-union-inline.err b/tests/qapi-schema/flat-union-inline.err index c2c3f7604b..2333358d28 100644 --- a/tests/qapi-schema/flat-union-inline.err +++ b/tests/qapi-schema/flat-union-inline.err @@ -1 +1 @@ -tests/qapi-schema/flat-union-inline.json:17: Member 'value1' of union 'TestUnion' should be a type name +tests/qapi-schema/flat-union-inline.json:7: Member 'value1' of union 'TestUnion' should be a type name diff --git a/tests/qapi-schema/flat-union-inline.json b/tests/qapi-schema/flat-union-inline.json index 400f0817a1..62c7cda617 100644 --- a/tests/qapi-schema/flat-union-inline.json +++ b/tests/qapi-schema/flat-union-inline.json @@ -1,19 +1,9 @@ # we require branches to be a struct name # TODO: should we allow anonymous inline branch types? - -## -# @TestEnum: -## { 'enum': 'TestEnum', 'data': [ 'value1', 'value2' ] } -## -# @Base: -## { 'struct': 'Base', 'data': { 'enum1': 'TestEnum', 'kind': 'str' } } -## -# @TestUnion: -## { 'union': 'TestUnion', 'base': 'Base', 'discriminator': 'enum1', diff --git a/tests/qapi-schema/flat-union-int-branch.err b/tests/qapi-schema/flat-union-int-branch.err index 299cbb24b2..faf01573b7 100644 --- a/tests/qapi-schema/flat-union-int-branch.err +++ b/tests/qapi-schema/flat-union-int-branch.err @@ -1 +1 @@ -tests/qapi-schema/flat-union-int-branch.json:21: Member 'value1' of union 'TestUnion' cannot use built-in type 'int' +tests/qapi-schema/flat-union-int-branch.json:8: Member 'value1' of union 'TestUnion' cannot use built-in type 'int' diff --git a/tests/qapi-schema/flat-union-int-branch.json b/tests/qapi-schema/flat-union-int-branch.json index 9603e172f8..9370c349e8 100644 --- a/tests/qapi-schema/flat-union-int-branch.json +++ b/tests/qapi-schema/flat-union-int-branch.json @@ -1,23 +1,10 @@ # we require flat union branches to be a struct - -## -# @TestEnum: -## { 'enum': 'TestEnum', 'data': [ 'value1', 'value2' ] } -## -# @Base: -## { 'struct': 'Base', 'data': { 'enum1': 'TestEnum' } } -## -# @TestTypeB: -## { 'struct': 'TestTypeB', 'data': { 'integer': 'int' } } -## -# @TestUnion: -## { 'union': 'TestUnion', 'base': 'Base', 'discriminator': 'enum1', diff --git a/tests/qapi-schema/flat-union-invalid-branch-key.err b/tests/qapi-schema/flat-union-invalid-branch-key.err index 455f2dc083..ccf72d2dfe 100644 --- a/tests/qapi-schema/flat-union-invalid-branch-key.err +++ b/tests/qapi-schema/flat-union-invalid-branch-key.err @@ -1 +1 @@ -tests/qapi-schema/flat-union-invalid-branch-key.json:28: Discriminator value 'value_wrong' is not found in enum 'TestEnum' +tests/qapi-schema/flat-union-invalid-branch-key.json:13: Discriminator value 'value_wrong' is not found in enum 'TestEnum' diff --git a/tests/qapi-schema/flat-union-invalid-branch-key.json b/tests/qapi-schema/flat-union-invalid-branch-key.json index 00f28966ff..95ff7746bf 100644 --- a/tests/qapi-schema/flat-union-invalid-branch-key.json +++ b/tests/qapi-schema/flat-union-invalid-branch-key.json @@ -1,30 +1,15 @@ -## -# @TestEnum: -## { 'enum': 'TestEnum', 'data': [ 'value1', 'value2' ] } -## -# @TestBase: -## { 'struct': 'TestBase', 'data': { 'enum1': 'TestEnum' } } -## -# @TestTypeA: -## { 'struct': 'TestTypeA', 'data': { 'string': 'str' } } -## -# @TestTypeB: -## { 'struct': 'TestTypeB', 'data': { 'integer': 'int' } } -## -# @TestUnion: -## { 'union': 'TestUnion', 'base': 'TestBase', 'discriminator': 'enum1', diff --git a/tests/qapi-schema/flat-union-invalid-discriminator.err b/tests/qapi-schema/flat-union-invalid-discriminator.err index f0e427b0a7..5f4055614e 100644 --- a/tests/qapi-schema/flat-union-invalid-discriminator.err +++ b/tests/qapi-schema/flat-union-invalid-discriminator.err @@ -1 +1 @@ -tests/qapi-schema/flat-union-invalid-discriminator.json:28: Discriminator 'enum_wrong' is not a member of base struct 'TestBase' +tests/qapi-schema/flat-union-invalid-discriminator.json:13: Discriminator 'enum_wrong' is not a member of base struct 'TestBase' diff --git a/tests/qapi-schema/flat-union-invalid-discriminator.json b/tests/qapi-schema/flat-union-invalid-discriminator.json index c8700c7d71..48b94c3a4d 100644 --- a/tests/qapi-schema/flat-union-invalid-discriminator.json +++ b/tests/qapi-schema/flat-union-invalid-discriminator.json @@ -1,30 +1,15 @@ -## -# @TestEnum: -## { 'enum': 'TestEnum', 'data': [ 'value1', 'value2' ] } -## -# @TestBase: -## { 'struct': 'TestBase', 'data': { 'enum1': 'TestEnum' } } -## -# @TestTypeA: -## { 'struct': 'TestTypeA', 'data': { 'string': 'str' } } -## -# @TestTypeB: -## { 'struct': 'TestTypeB', 'data': { 'integer': 'int' } } -## -# @TestUnion: -## { 'union': 'TestUnion', 'base': 'TestBase', 'discriminator': 'enum_wrong', diff --git a/tests/qapi-schema/flat-union-no-base.err b/tests/qapi-schema/flat-union-no-base.err index a2d0a81aa0..841c93b554 100644 --- a/tests/qapi-schema/flat-union-no-base.err +++ b/tests/qapi-schema/flat-union-no-base.err @@ -1 +1 @@ -tests/qapi-schema/flat-union-no-base.json:22: Flat union 'TestUnion' must have a base +tests/qapi-schema/flat-union-no-base.json:9: Flat union 'TestUnion' must have a base diff --git a/tests/qapi-schema/flat-union-no-base.json b/tests/qapi-schema/flat-union-no-base.json index 641f68aea4..ffc4c6f0e6 100644 --- a/tests/qapi-schema/flat-union-no-base.json +++ b/tests/qapi-schema/flat-union-no-base.json @@ -1,24 +1,11 @@ # flat unions require a base # TODO: simple unions should be able to use an enum discriminator - -## -# @TestTypeA: -## { 'struct': 'TestTypeA', 'data': { 'string': 'str' } } -## -# @TestTypeB: -## { 'struct': 'TestTypeB', 'data': { 'integer': 'int' } } -## -# @Enum: -## { 'enum': 'Enum', 'data': [ 'value1', 'value2' ] } -## -# @TestUnion: -## { 'union': 'TestUnion', 'discriminator': 'Enum', 'data': { 'value1': 'TestTypeA', diff --git a/tests/qapi-schema/flat-union-optional-discriminator.err b/tests/qapi-schema/flat-union-optional-discriminator.err index e15f8564dd..aaabedb3bd 100644 --- a/tests/qapi-schema/flat-union-optional-discriminator.err +++ b/tests/qapi-schema/flat-union-optional-discriminator.err @@ -1 +1 @@ -tests/qapi-schema/flat-union-optional-discriminator.json:19: Discriminator of flat union 'MyUnion' does not allow optional name '*switch' +tests/qapi-schema/flat-union-optional-discriminator.json:6: Discriminator of flat union 'MyUnion' does not allow optional name '*switch' diff --git a/tests/qapi-schema/flat-union-optional-discriminator.json b/tests/qapi-schema/flat-union-optional-discriminator.json index 9f19af5789..08a8f7ef8b 100644 --- a/tests/qapi-schema/flat-union-optional-discriminator.json +++ b/tests/qapi-schema/flat-union-optional-discriminator.json @@ -1,21 +1,8 @@ # we require the discriminator to be non-optional - -## -# @Enum: -## { 'enum': 'Enum', 'data': [ 'one', 'two' ] } -## -# @Base: -## { 'struct': 'Base', 'data': { '*switch': 'Enum' } } -## -# @Branch: -## { 'struct': 'Branch', 'data': { 'name': 'str' } } -## -# @MyUnion: -## { 'union': 'MyUnion', 'base': 'Base', 'discriminator': '*switch', diff --git a/tests/qapi-schema/flat-union-string-discriminator.err b/tests/qapi-schema/flat-union-string-discriminator.err index bc0c133aa9..200016bd5c 100644 --- a/tests/qapi-schema/flat-union-string-discriminator.err +++ b/tests/qapi-schema/flat-union-string-discriminator.err @@ -1 +1 @@ -tests/qapi-schema/flat-union-string-discriminator.json:28: Discriminator 'kind' must be of enumeration type +tests/qapi-schema/flat-union-string-discriminator.json:13: Discriminator 'kind' must be of enumeration type diff --git a/tests/qapi-schema/flat-union-string-discriminator.json b/tests/qapi-schema/flat-union-string-discriminator.json index 47a17d2e4a..8af60333b6 100644 --- a/tests/qapi-schema/flat-union-string-discriminator.json +++ b/tests/qapi-schema/flat-union-string-discriminator.json @@ -1,30 +1,15 @@ -## -# @TestEnum: -## { 'enum': 'TestEnum', 'data': [ 'value1', 'value2' ] } -## -# @TestBase: -## { 'struct': 'TestBase', 'data': { 'enum1': 'TestEnum', 'kind': 'str' } } -## -# @TestTypeA: -## { 'struct': 'TestTypeA', 'data': { 'string': 'str' } } -## -# @TestTypeB: -## { 'struct': 'TestTypeB', 'data': { 'integer': 'int' } } -## -# @TestUnion: -## { 'union': 'TestUnion', 'base': 'TestBase', 'discriminator': 'kind', diff --git a/tests/qapi-schema/ident-with-escape.json b/tests/qapi-schema/ident-with-escape.json index c03404bee3..56617501e7 100644 --- a/tests/qapi-schema/ident-with-escape.json +++ b/tests/qapi-schema/ident-with-escape.json @@ -1,8 +1,4 @@ # we allow escape sequences in strings, if they map back to ASCII # { 'command': 'fooA', 'data': { 'bar1': 'str' } } - -## -# @fooA: -## { 'c\u006fmmand': '\u0066\u006f\u006FA', 'd\u0061ta': { '\u0062\u0061\u00721': '\u0073\u0074\u0072' } } diff --git a/tests/qapi-schema/ident-with-escape.out b/tests/qapi-schema/ident-with-escape.out index 69fc908e68..1d2722c02e 100644 --- a/tests/qapi-schema/ident-with-escape.out +++ b/tests/qapi-schema/ident-with-escape.out @@ -5,4 +5,3 @@ command fooA q_obj_fooA-arg -> None object q_empty object q_obj_fooA-arg member bar1: str optional=False -doc symbol=fooA expr=('command', 'fooA') diff --git a/tests/qapi-schema/include-extra-junk.err b/tests/qapi-schema/include-extra-junk.err new file mode 100644 index 0000000000..e6ef2a3720 --- /dev/null +++ b/tests/qapi-schema/include-extra-junk.err @@ -0,0 +1 @@ +tests/qapi-schema/include-extra-junk.json:3: Invalid 'include' directive diff --git a/tests/qapi-schema/include-extra-junk.exit b/tests/qapi-schema/include-extra-junk.exit new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/tests/qapi-schema/include-extra-junk.exit @@ -0,0 +1 @@ +1 diff --git a/tests/qapi-schema/include-extra-junk.json b/tests/qapi-schema/include-extra-junk.json new file mode 100644 index 0000000000..25fe85078d --- /dev/null +++ b/tests/qapi-schema/include-extra-junk.json @@ -0,0 +1,3 @@ +# 'include' must be the sole member + +{ 'include': 'comments.json', 'junk': true } diff --git a/tests/qapi-schema/include-extra-junk.out b/tests/qapi-schema/include-extra-junk.out new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/qapi-schema/include-extra-junk.out diff --git a/tests/qapi-schema/include-relpath-sub.json b/tests/qapi-schema/include-relpath-sub.json index b4bd8a23d7..4bd4af4162 100644 --- a/tests/qapi-schema/include-relpath-sub.json +++ b/tests/qapi-schema/include-relpath-sub.json @@ -1,5 +1,2 @@ -## -# @Status: -## { 'enum': 'Status', 'data': [ 'good', 'bad', 'ugly' ] } diff --git a/tests/qapi-schema/include-relpath.out b/tests/qapi-schema/include-relpath.out index a962fb2d2e..5d7c13cad1 100644 --- a/tests/qapi-schema/include-relpath.out +++ b/tests/qapi-schema/include-relpath.out @@ -2,4 +2,3 @@ enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbo prefix QTYPE enum Status ['good', 'bad', 'ugly'] object q_empty -doc symbol=Status expr=('enum', 'Status') diff --git a/tests/qapi-schema/include-repetition.out b/tests/qapi-schema/include-repetition.out index a962fb2d2e..5d7c13cad1 100644 --- a/tests/qapi-schema/include-repetition.out +++ b/tests/qapi-schema/include-repetition.out @@ -2,4 +2,3 @@ enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbo prefix QTYPE enum Status ['good', 'bad', 'ugly'] object q_empty -doc symbol=Status expr=('enum', 'Status') diff --git a/tests/qapi-schema/include-simple-sub.json b/tests/qapi-schema/include-simple-sub.json index b4bd8a23d7..4bd4af4162 100644 --- a/tests/qapi-schema/include-simple-sub.json +++ b/tests/qapi-schema/include-simple-sub.json @@ -1,5 +1,2 @@ -## -# @Status: -## { 'enum': 'Status', 'data': [ 'good', 'bad', 'ugly' ] } diff --git a/tests/qapi-schema/include-simple.out b/tests/qapi-schema/include-simple.out index a962fb2d2e..5d7c13cad1 100644 --- a/tests/qapi-schema/include-simple.out +++ b/tests/qapi-schema/include-simple.out @@ -2,4 +2,3 @@ enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbo prefix QTYPE enum Status ['good', 'bad', 'ugly'] object q_empty -doc symbol=Status expr=('enum', 'Status') diff --git a/tests/qapi-schema/indented-expr.json b/tests/qapi-schema/indented-expr.json index d759be1877..7115d3131e 100644 --- a/tests/qapi-schema/indented-expr.json +++ b/tests/qapi-schema/indented-expr.json @@ -1,8 +1,2 @@ -## -# @eins: -## { 'command' : 'eins' } -## -# @zwei: -## { 'command' : 'zwei' } diff --git a/tests/qapi-schema/indented-expr.out b/tests/qapi-schema/indented-expr.out index 285d052257..e8171c935f 100644 --- a/tests/qapi-schema/indented-expr.out +++ b/tests/qapi-schema/indented-expr.out @@ -5,5 +5,3 @@ command eins None -> None object q_empty command zwei None -> None gen=True success_response=True boxed=False -doc symbol=eins expr=('command', 'eins') -doc symbol=zwei expr=('command', 'zwei') diff --git a/tests/qapi-schema/missing-type.err b/tests/qapi-schema/missing-type.err index 74c4ef7324..b3e7b14e42 100644 --- a/tests/qapi-schema/missing-type.err +++ b/tests/qapi-schema/missing-type.err @@ -1 +1 @@ -tests/qapi-schema/missing-type.json:6: Expression is missing metatype +tests/qapi-schema/missing-type.json:2: Expression is missing metatype diff --git a/tests/qapi-schema/missing-type.json b/tests/qapi-schema/missing-type.json index c2fc62d0af..ff5349d3fe 100644 --- a/tests/qapi-schema/missing-type.json +++ b/tests/qapi-schema/missing-type.json @@ -1,6 +1,2 @@ # we reject an expression with missing metatype - -## -# @foo: -## { 'data': { } } diff --git a/tests/qapi-schema/nested-struct-data.err b/tests/qapi-schema/nested-struct-data.err index 379bd1d3f4..da767bade2 100644 --- a/tests/qapi-schema/nested-struct-data.err +++ b/tests/qapi-schema/nested-struct-data.err @@ -1 +1 @@ -tests/qapi-schema/nested-struct-data.json:6: Member 'a' of 'data' for command 'foo' should be a type name +tests/qapi-schema/nested-struct-data.json:2: Member 'a' of 'data' for command 'foo' should be a type name diff --git a/tests/qapi-schema/nested-struct-data.json b/tests/qapi-schema/nested-struct-data.json index 6106e15e86..efbe773ded 100644 --- a/tests/qapi-schema/nested-struct-data.json +++ b/tests/qapi-schema/nested-struct-data.json @@ -1,7 +1,3 @@ # inline subtypes collide with our desired future use of defaults - -## -# @foo: -## { 'command': 'foo', 'data': { 'a' : { 'string' : 'str', 'integer': 'int' }, 'b' : 'str' } } diff --git a/tests/qapi-schema/pragma-doc-required-crap.err b/tests/qapi-schema/pragma-doc-required-crap.err new file mode 100644 index 0000000000..39cd56cd48 --- /dev/null +++ b/tests/qapi-schema/pragma-doc-required-crap.err @@ -0,0 +1 @@ +tests/qapi-schema/pragma-doc-required-crap.json:3: Pragma 'doc-required' must be boolean diff --git a/tests/qapi-schema/pragma-doc-required-crap.exit b/tests/qapi-schema/pragma-doc-required-crap.exit new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/tests/qapi-schema/pragma-doc-required-crap.exit @@ -0,0 +1 @@ +1 diff --git a/tests/qapi-schema/pragma-doc-required-crap.json b/tests/qapi-schema/pragma-doc-required-crap.json new file mode 100644 index 0000000000..ed763c5ffc --- /dev/null +++ b/tests/qapi-schema/pragma-doc-required-crap.json @@ -0,0 +1,3 @@ +# 'doc-required' must be bool + +{ 'pragma': { 'doc-required': {} } } diff --git a/tests/qapi-schema/pragma-doc-required-crap.out b/tests/qapi-schema/pragma-doc-required-crap.out new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/qapi-schema/pragma-doc-required-crap.out diff --git a/tests/qapi-schema/pragma-extra-junk.err b/tests/qapi-schema/pragma-extra-junk.err new file mode 100644 index 0000000000..4481688dbf --- /dev/null +++ b/tests/qapi-schema/pragma-extra-junk.err @@ -0,0 +1 @@ +tests/qapi-schema/pragma-extra-junk.json:3: Invalid 'pragma' directive diff --git a/tests/qapi-schema/pragma-extra-junk.exit b/tests/qapi-schema/pragma-extra-junk.exit new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/tests/qapi-schema/pragma-extra-junk.exit @@ -0,0 +1 @@ +1 diff --git a/tests/qapi-schema/pragma-extra-junk.json b/tests/qapi-schema/pragma-extra-junk.json new file mode 100644 index 0000000000..ba38ef2e95 --- /dev/null +++ b/tests/qapi-schema/pragma-extra-junk.json @@ -0,0 +1,3 @@ +# 'pragma' must be the sole member + +{ 'pragma': { 'doc-required': true }, 'junk': true } diff --git a/tests/qapi-schema/pragma-extra-junk.out b/tests/qapi-schema/pragma-extra-junk.out new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/qapi-schema/pragma-extra-junk.out diff --git a/tests/qapi-schema/pragma-name-case-whitelist-crap.err b/tests/qapi-schema/pragma-name-case-whitelist-crap.err new file mode 100644 index 0000000000..f83b97e075 --- /dev/null +++ b/tests/qapi-schema/pragma-name-case-whitelist-crap.err @@ -0,0 +1 @@ +tests/qapi-schema/pragma-name-case-whitelist-crap.json:3: Pragma name-case-whitelist must be a list of strings diff --git a/tests/qapi-schema/pragma-name-case-whitelist-crap.exit b/tests/qapi-schema/pragma-name-case-whitelist-crap.exit new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/tests/qapi-schema/pragma-name-case-whitelist-crap.exit @@ -0,0 +1 @@ +1 diff --git a/tests/qapi-schema/pragma-name-case-whitelist-crap.json b/tests/qapi-schema/pragma-name-case-whitelist-crap.json new file mode 100644 index 0000000000..58382bf4e4 --- /dev/null +++ b/tests/qapi-schema/pragma-name-case-whitelist-crap.json @@ -0,0 +1,3 @@ +# 'name-case-whitelist' must be list of strings + +{ 'pragma': { 'name-case-whitelist': null } } diff --git a/tests/qapi-schema/pragma-name-case-whitelist-crap.out b/tests/qapi-schema/pragma-name-case-whitelist-crap.out new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/qapi-schema/pragma-name-case-whitelist-crap.out diff --git a/tests/qapi-schema/pragma-non-dict.err b/tests/qapi-schema/pragma-non-dict.err new file mode 100644 index 0000000000..75bc335aea --- /dev/null +++ b/tests/qapi-schema/pragma-non-dict.err @@ -0,0 +1 @@ +tests/qapi-schema/pragma-non-dict.json:3: Value of 'pragma' must be a dictionary diff --git a/tests/qapi-schema/pragma-non-dict.exit b/tests/qapi-schema/pragma-non-dict.exit new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/tests/qapi-schema/pragma-non-dict.exit @@ -0,0 +1 @@ +1 diff --git a/tests/qapi-schema/pragma-non-dict.json b/tests/qapi-schema/pragma-non-dict.json new file mode 100644 index 0000000000..60fcc79bdb --- /dev/null +++ b/tests/qapi-schema/pragma-non-dict.json @@ -0,0 +1,3 @@ +# Value of 'pragma' must be a dictionary + +{ 'pragma': [] } diff --git a/tests/qapi-schema/pragma-non-dict.out b/tests/qapi-schema/pragma-non-dict.out new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/qapi-schema/pragma-non-dict.out diff --git a/tests/qapi-schema/pragma-returns-whitelist-crap.err b/tests/qapi-schema/pragma-returns-whitelist-crap.err new file mode 100644 index 0000000000..5d77021674 --- /dev/null +++ b/tests/qapi-schema/pragma-returns-whitelist-crap.err @@ -0,0 +1 @@ +tests/qapi-schema/pragma-returns-whitelist-crap.json:3: Pragma returns-whitelist must be a list of strings diff --git a/tests/qapi-schema/pragma-returns-whitelist-crap.exit b/tests/qapi-schema/pragma-returns-whitelist-crap.exit new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/tests/qapi-schema/pragma-returns-whitelist-crap.exit @@ -0,0 +1 @@ +1 diff --git a/tests/qapi-schema/pragma-returns-whitelist-crap.json b/tests/qapi-schema/pragma-returns-whitelist-crap.json new file mode 100644 index 0000000000..f6b81b093f --- /dev/null +++ b/tests/qapi-schema/pragma-returns-whitelist-crap.json @@ -0,0 +1,3 @@ +# 'returns-whitelist' must be list of strings + +{ 'pragma': { 'returns-whitelist': [ 'good', [ 'bad' ] ] } } diff --git a/tests/qapi-schema/pragma-returns-whitelist-crap.out b/tests/qapi-schema/pragma-returns-whitelist-crap.out new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/qapi-schema/pragma-returns-whitelist-crap.out diff --git a/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qapi-schema-test.json index f4d8cc4230..842ea3c5e3 100644 --- a/tests/qapi-schema/qapi-schema-test.json +++ b/tests/qapi-schema/qapi-schema-test.json @@ -3,153 +3,74 @@ # This file is a stress test of supported qapi constructs that must # parse and compile correctly. -## -# = Section -# == subsection -# -# Some text foo with *strong* and _emphasis_ -# 1. with a list -# 2. like that @foo -# -# And some code: -# | $ echo foo -# | -> do this -# | <- get that -# -# Note: is not a meta -## +# Whitelists to permit QAPI rule violations +{ 'pragma': { + # Commands allowed to return a non-dictionary: + 'returns-whitelist': [ + 'guest-get-time', + 'guest-sync' ] } } -## -# @TestStruct: -# -# body with @var -# -# @integer: foo -# blah -# -# bao -# -# @boolean: bar -# @string: baz -# -# Example: -# -# -> { "execute": ... } -# <- { "return": ... } -# -# Since: 2.3 -# Note: a note -# -## { 'struct': 'TestStruct', 'data': { 'integer': 'int', 'boolean': 'bool', 'string': 'str' } } -## -# @NestedEnumsOne: # for testing enums -## { 'struct': 'NestedEnumsOne', 'data': { 'enum1': 'EnumOne', # Intentional forward reference '*enum2': 'EnumOne', 'enum3': 'EnumOne', '*enum4': 'EnumOne' } } -## -# @MyEnum: # An empty enum, although unusual, is currently acceptable -## { 'enum': 'MyEnum', 'data': [ ] } -## -# @Empty1: # Likewise for an empty struct, including an empty base -## { 'struct': 'Empty1', 'data': { } } -## -# @Empty2: -## { 'struct': 'Empty2', 'base': 'Empty1', 'data': { } } -## -# @user_def_cmd0: -## { 'command': 'user_def_cmd0', 'data': 'Empty2', 'returns': 'Empty2' } -## -# @QEnumTwo: # for testing override of default naming heuristic -## { 'enum': 'QEnumTwo', 'prefix': 'QENUM_TWO', 'data': [ 'value1', 'value2' ] } -## -# @UserDefOne: # for testing nested structs -## { 'struct': 'UserDefOne', 'base': 'UserDefZero', # intentional forward reference 'data': { 'string': 'str', '*enum1': 'EnumOne' } } # intentional forward reference -## -# @EnumOne: -## { 'enum': 'EnumOne', 'data': [ 'value1', 'value2', 'value3' ] } -## -# @UserDefZero: -## { 'struct': 'UserDefZero', 'data': { 'integer': 'int' } } -## -# @UserDefTwoDictDict: -## { 'struct': 'UserDefTwoDictDict', 'data': { 'userdef': 'UserDefOne', 'string': 'str' } } -## -# @UserDefTwoDict: -## { 'struct': 'UserDefTwoDict', 'data': { 'string1': 'str', 'dict2': 'UserDefTwoDictDict', '*dict3': 'UserDefTwoDictDict' } } -## -# @UserDefTwo: -## { 'struct': 'UserDefTwo', 'data': { 'string0': 'str', 'dict1': 'UserDefTwoDict' } } -## -# @ForceArrays: # dummy struct to force generation of array types not otherwise mentioned -## { 'struct': 'ForceArrays', 'data': { 'unused1':['UserDefOne'], 'unused2':['UserDefTwo'], 'unused3':['TestStruct'] } } -## -# @UserDefA: # for testing unions # Among other things, test that a name collision between branches does # not cause any problems (since only one branch can be in use at a time), # by intentionally using two branches that both have a C member 'a_b' -## { 'struct': 'UserDefA', 'data': { 'boolean': 'bool', '*a_b': 'int' } } -## -# @UserDefB: -## { 'struct': 'UserDefB', 'data': { 'intb': 'int', '*a-b': 'bool' } } -## -# @UserDefFlatUnion: -## { 'union': 'UserDefFlatUnion', 'base': 'UserDefUnionBase', # intentional forward reference 'discriminator': 'enum1', @@ -157,71 +78,35 @@ 'value2' : 'UserDefB', 'value3' : 'UserDefB' } } -## -# @UserDefUnionBase: -## { 'struct': 'UserDefUnionBase', 'base': 'UserDefZero', 'data': { 'string': 'str', 'enum1': 'EnumOne' } } -## -# @UserDefFlatUnion2: # this variant of UserDefFlatUnion defaults to a union that uses members with # allocated types to test corner cases in the cleanup/dealloc visitor -## { 'union': 'UserDefFlatUnion2', 'base': { '*integer': 'int', 'string': 'str', 'enum1': 'QEnumTwo' }, 'discriminator': 'enum1', 'data': { 'value1' : 'UserDefC', # intentional forward reference 'value2' : 'UserDefB' } } -## -# @WrapAlternate: -## { 'struct': 'WrapAlternate', 'data': { 'alt': 'UserDefAlternate' } } -## -# @UserDefAlternate: -## { 'alternate': 'UserDefAlternate', 'data': { 'udfu': 'UserDefFlatUnion', 's': 'str', 'i': 'int' } } -## -# @UserDefC: -## { 'struct': 'UserDefC', 'data': { 'string1': 'str', 'string2': 'str' } } # for testing use of 'number' within alternates -## -# @AltStrBool: -## { 'alternate': 'AltStrBool', 'data': { 's': 'str', 'b': 'bool' } } -## -# @AltStrNum: -## { 'alternate': 'AltStrNum', 'data': { 's': 'str', 'n': 'number' } } -## -# @AltNumStr: -## { 'alternate': 'AltNumStr', 'data': { 'n': 'number', 's': 'str' } } -## -# @AltStrInt: -## { 'alternate': 'AltStrInt', 'data': { 's': 'str', 'i': 'int' } } -## -# @AltIntNum: -## { 'alternate': 'AltIntNum', 'data': { 'i': 'int', 'n': 'number' } } -## -# @AltNumInt: -## { 'alternate': 'AltNumInt', 'data': { 'n': 'number', 'i': 'int' } } -## -# @UserDefNativeListUnion: # for testing native lists -## { 'union': 'UserDefNativeListUnion', 'data': { 'integer': ['int'], 's8': ['int8'], @@ -239,61 +124,19 @@ 'any': ['any'] } } # testing commands -## -# @user_def_cmd: -## { 'command': 'user_def_cmd', 'data': {} } -## -# @user_def_cmd1: -## { 'command': 'user_def_cmd1', 'data': {'ud1a': 'UserDefOne'} } -## -# @user_def_cmd2: -## { 'command': 'user_def_cmd2', 'data': {'ud1a': 'UserDefOne', '*ud1b': 'UserDefOne'}, 'returns': 'UserDefTwo' } -## -# Another comment -## - -## -# @guest-get-time: -# -# @guest-get-time body -# -# @a: an integer -# @b: #optional integer -# -# Returns: returns something -# -# Example: -# -# -> { "execute": "guest-get-time", ... } -# <- { "return": "42" } -# -## - # Returning a non-dictionary requires a name from the whitelist { 'command': 'guest-get-time', 'data': {'a': 'int', '*b': 'int' }, 'returns': 'int' } -## -# @guest-sync: -## { 'command': 'guest-sync', 'data': { 'arg': 'any' }, 'returns': 'any' } -## -# @boxed-struct: -## { 'command': 'boxed-struct', 'boxed': true, 'data': 'UserDefZero' } -## -# @boxed-union: -## { 'command': 'boxed-union', 'data': 'UserDefNativeListUnion', 'boxed': true } -## -# @UserDefOptions: -# # For testing integer range flattening in opts-visitor. The following schema # corresponds to the option format: # @@ -301,7 +144,6 @@ # # For simplicity, this example doesn't use [type=]discriminator nor optargs # specific to discriminator values. -## { 'struct': 'UserDefOptions', 'data': { '*i64' : [ 'int' ], @@ -311,83 +153,35 @@ '*u64x': 'uint64' } } # testing event -## -# @EventStructOne: -## { 'struct': 'EventStructOne', 'data': { 'struct1': 'UserDefOne', 'string': 'str', '*enum2': 'EnumOne' } } -## -# @EVENT_A: -## { 'event': 'EVENT_A' } -## -# @EVENT_B: -## { 'event': 'EVENT_B', 'data': { } } -## -# @EVENT_C: -## { 'event': 'EVENT_C', 'data': { '*a': 'int', '*b': 'UserDefOne', 'c': 'str' } } -## -# @EVENT_D: -## { 'event': 'EVENT_D', 'data': { 'a' : 'EventStructOne', 'b' : 'str', '*c': 'str', '*enum3': 'EnumOne' } } -## -# @EVENT_E: -## { 'event': 'EVENT_E', 'boxed': true, 'data': 'UserDefZero' } -## -# @EVENT_F: -## { 'event': 'EVENT_F', 'boxed': true, 'data': 'UserDefAlternate' } # test that we correctly compile downstream extensions, as well as munge # ticklish names -## -# @__org.qemu_x-Enum: -## { 'enum': '__org.qemu_x-Enum', 'data': [ '__org.qemu_x-value' ] } -## -# @__org.qemu_x-Base: -## { 'struct': '__org.qemu_x-Base', 'data': { '__org.qemu_x-member1': '__org.qemu_x-Enum' } } -## -# @__org.qemu_x-Struct: -## { 'struct': '__org.qemu_x-Struct', 'base': '__org.qemu_x-Base', 'data': { '__org.qemu_x-member2': 'str', '*wchar-t': 'int' } } -## -# @__org.qemu_x-Union1: -## { 'union': '__org.qemu_x-Union1', 'data': { '__org.qemu_x-branch': 'str' } } -## -# @__org.qemu_x-Struct2: -## { 'struct': '__org.qemu_x-Struct2', 'data': { 'array': ['__org.qemu_x-Union1'] } } -## -# @__org.qemu_x-Union2: -## { 'union': '__org.qemu_x-Union2', 'base': '__org.qemu_x-Base', 'discriminator': '__org.qemu_x-member1', 'data': { '__org.qemu_x-value': '__org.qemu_x-Struct2' } } -## -# @__org.qemu_x-Alt: -## { 'alternate': '__org.qemu_x-Alt', 'data': { '__org.qemu_x-branch': 'str', 'b': '__org.qemu_x-Base' } } -## -# @__ORG.QEMU_X-EVENT: -## { 'event': '__ORG.QEMU_X-EVENT', 'data': '__org.qemu_x-Struct' } -## -# @__org.qemu_x-command: -## { 'command': '__org.qemu_x-command', 'data': { 'a': ['__org.qemu_x-Enum'], 'b': ['__org.qemu_x-Struct'], 'c': '__org.qemu_x-Union2', 'd': '__org.qemu_x-Alt' }, diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qapi-schema-test.out index bc8d496ff4..9d99c4eebb 100644 --- a/tests/qapi-schema/qapi-schema-test.out +++ b/tests/qapi-schema/qapi-schema-test.out @@ -232,133 +232,3 @@ command user_def_cmd1 q_obj_user_def_cmd1-arg -> None gen=True success_response=True boxed=False command user_def_cmd2 q_obj_user_def_cmd2-arg -> UserDefTwo gen=True success_response=True boxed=False -doc freeform - body= -= Section -== subsection - -Some text foo with *strong* and _emphasis_ -1. with a list -2. like that @foo - -And some code: -| $ echo foo -| -> do this -| <- get that - -Note: is not a meta -doc symbol=TestStruct expr=('struct', 'TestStruct') - arg=integer -foo -blah - -bao - arg=boolean -bar - arg=string -baz - section=Example --> { "execute": ... } -<- { "return": ... } - section=Since -2.3 - section=Note -a note - body= -body with @var -doc symbol=NestedEnumsOne expr=('struct', 'NestedEnumsOne') - body= -for testing enums -doc symbol=MyEnum expr=('enum', 'MyEnum') - body= -An empty enum, although unusual, is currently acceptable -doc symbol=Empty1 expr=('struct', 'Empty1') - body= -Likewise for an empty struct, including an empty base -doc symbol=Empty2 expr=('struct', 'Empty2') -doc symbol=user_def_cmd0 expr=('command', 'user_def_cmd0') -doc symbol=QEnumTwo expr=('enum', 'QEnumTwo') - body= -for testing override of default naming heuristic -doc symbol=UserDefOne expr=('struct', 'UserDefOne') - body= -for testing nested structs -doc symbol=EnumOne expr=('enum', 'EnumOne') -doc symbol=UserDefZero expr=('struct', 'UserDefZero') -doc symbol=UserDefTwoDictDict expr=('struct', 'UserDefTwoDictDict') -doc symbol=UserDefTwoDict expr=('struct', 'UserDefTwoDict') -doc symbol=UserDefTwo expr=('struct', 'UserDefTwo') -doc symbol=ForceArrays expr=('struct', 'ForceArrays') - body= -dummy struct to force generation of array types not otherwise mentioned -doc symbol=UserDefA expr=('struct', 'UserDefA') - body= -for testing unions -Among other things, test that a name collision between branches does -not cause any problems (since only one branch can be in use at a time), -by intentionally using two branches that both have a C member 'a_b' -doc symbol=UserDefB expr=('struct', 'UserDefB') -doc symbol=UserDefFlatUnion expr=('union', 'UserDefFlatUnion') -doc symbol=UserDefUnionBase expr=('struct', 'UserDefUnionBase') -doc symbol=UserDefFlatUnion2 expr=('union', 'UserDefFlatUnion2') - body= -this variant of UserDefFlatUnion defaults to a union that uses members with -allocated types to test corner cases in the cleanup/dealloc visitor -doc symbol=WrapAlternate expr=('struct', 'WrapAlternate') -doc symbol=UserDefAlternate expr=('alternate', 'UserDefAlternate') -doc symbol=UserDefC expr=('struct', 'UserDefC') -doc symbol=AltStrBool expr=('alternate', 'AltStrBool') -doc symbol=AltStrNum expr=('alternate', 'AltStrNum') -doc symbol=AltNumStr expr=('alternate', 'AltNumStr') -doc symbol=AltStrInt expr=('alternate', 'AltStrInt') -doc symbol=AltIntNum expr=('alternate', 'AltIntNum') -doc symbol=AltNumInt expr=('alternate', 'AltNumInt') -doc symbol=UserDefNativeListUnion expr=('union', 'UserDefNativeListUnion') - body= -for testing native lists -doc symbol=user_def_cmd expr=('command', 'user_def_cmd') -doc symbol=user_def_cmd1 expr=('command', 'user_def_cmd1') -doc symbol=user_def_cmd2 expr=('command', 'user_def_cmd2') -doc freeform - body= -Another comment -doc symbol=guest-get-time expr=('command', 'guest-get-time') - arg=a -an integer - arg=b -#optional integer - section=Returns -returns something - section=Example --> { "execute": "guest-get-time", ... } -<- { "return": "42" } - body= -@guest-get-time body -doc symbol=guest-sync expr=('command', 'guest-sync') -doc symbol=boxed-struct expr=('command', 'boxed-struct') -doc symbol=boxed-union expr=('command', 'boxed-union') -doc symbol=UserDefOptions expr=('struct', 'UserDefOptions') - body= -For testing integer range flattening in opts-visitor. The following schema -corresponds to the option format: - --userdef i64=3-6,i64=-5--1,u64=2,u16=1,u16=7-12 - -For simplicity, this example doesn't use [type=]discriminator nor optargs -specific to discriminator values. -doc symbol=EventStructOne expr=('struct', 'EventStructOne') -doc symbol=EVENT_A expr=('event', 'EVENT_A') -doc symbol=EVENT_B expr=('event', 'EVENT_B') -doc symbol=EVENT_C expr=('event', 'EVENT_C') -doc symbol=EVENT_D expr=('event', 'EVENT_D') -doc symbol=EVENT_E expr=('event', 'EVENT_E') -doc symbol=EVENT_F expr=('event', 'EVENT_F') -doc symbol=__org.qemu_x-Enum expr=('enum', '__org.qemu_x-Enum') -doc symbol=__org.qemu_x-Base expr=('struct', '__org.qemu_x-Base') -doc symbol=__org.qemu_x-Struct expr=('struct', '__org.qemu_x-Struct') -doc symbol=__org.qemu_x-Union1 expr=('union', '__org.qemu_x-Union1') -doc symbol=__org.qemu_x-Struct2 expr=('struct', '__org.qemu_x-Struct2') -doc symbol=__org.qemu_x-Union2 expr=('union', '__org.qemu_x-Union2') -doc symbol=__org.qemu_x-Alt expr=('alternate', '__org.qemu_x-Alt') -doc symbol=__ORG.QEMU_X-EVENT expr=('event', '__ORG.QEMU_X-EVENT') -doc symbol=__org.qemu_x-command expr=('command', '__org.qemu_x-command') diff --git a/tests/qapi-schema/redefined-builtin.err b/tests/qapi-schema/redefined-builtin.err index ee0a2adf0b..b2757225c4 100644 --- a/tests/qapi-schema/redefined-builtin.err +++ b/tests/qapi-schema/redefined-builtin.err @@ -1 +1 @@ -tests/qapi-schema/redefined-builtin.json:6: built-in 'size' is already defined +tests/qapi-schema/redefined-builtin.json:2: built-in 'size' is already defined diff --git a/tests/qapi-schema/redefined-builtin.json b/tests/qapi-schema/redefined-builtin.json index 6d3a940d5e..45b8a550ad 100644 --- a/tests/qapi-schema/redefined-builtin.json +++ b/tests/qapi-schema/redefined-builtin.json @@ -1,6 +1,2 @@ # we reject types that duplicate builtin names - -## -# @size: -## { 'struct': 'size', 'data': { 'myint': 'size' } } diff --git a/tests/qapi-schema/redefined-command.err b/tests/qapi-schema/redefined-command.err index 1e297c43ba..82ae256e63 100644 --- a/tests/qapi-schema/redefined-command.err +++ b/tests/qapi-schema/redefined-command.err @@ -1 +1 @@ -tests/qapi-schema/redefined-command.json:10: command 'foo' is already defined +tests/qapi-schema/redefined-command.json:3: command 'foo' is already defined diff --git a/tests/qapi-schema/redefined-command.json b/tests/qapi-schema/redefined-command.json index 3a8cb9024c..247e401948 100644 --- a/tests/qapi-schema/redefined-command.json +++ b/tests/qapi-schema/redefined-command.json @@ -1,10 +1,3 @@ # we reject commands defined more than once - -## -# @foo: -## { 'command': 'foo', 'data': { 'one': 'str' } } -## -# @foo: -## { 'command': 'foo', 'data': { '*two': 'str' } } diff --git a/tests/qapi-schema/redefined-event.err b/tests/qapi-schema/redefined-event.err index 912c785119..35429cb481 100644 --- a/tests/qapi-schema/redefined-event.err +++ b/tests/qapi-schema/redefined-event.err @@ -1 +1 @@ -tests/qapi-schema/redefined-event.json:10: event 'EVENT_A' is already defined +tests/qapi-schema/redefined-event.json:3: event 'EVENT_A' is already defined diff --git a/tests/qapi-schema/redefined-event.json b/tests/qapi-schema/redefined-event.json index ec7aeea0f0..7717e91c18 100644 --- a/tests/qapi-schema/redefined-event.json +++ b/tests/qapi-schema/redefined-event.json @@ -1,10 +1,3 @@ # we reject duplicate events - -## -# @EVENT_A: -## { 'event': 'EVENT_A', 'data': { 'myint': 'int' } } -## -# @EVENT_A: -## { 'event': 'EVENT_A', 'data': { 'myint': 'int' } } diff --git a/tests/qapi-schema/redefined-type.err b/tests/qapi-schema/redefined-type.err index 28d87c098c..06ea78c478 100644 --- a/tests/qapi-schema/redefined-type.err +++ b/tests/qapi-schema/redefined-type.err @@ -1 +1 @@ -tests/qapi-schema/redefined-type.json:10: struct 'foo' is already defined +tests/qapi-schema/redefined-type.json:3: struct 'foo' is already defined diff --git a/tests/qapi-schema/redefined-type.json b/tests/qapi-schema/redefined-type.json index 7a8f3e1ec8..a09e768bae 100644 --- a/tests/qapi-schema/redefined-type.json +++ b/tests/qapi-schema/redefined-type.json @@ -1,10 +1,3 @@ # we reject types defined more than once - -## -# @foo: -## { 'struct': 'foo', 'data': { 'one': 'str' } } -## -# @foo: -## { 'enum': 'foo', 'data': [ 'two' ] } diff --git a/tests/qapi-schema/reserved-command-q.err b/tests/qapi-schema/reserved-command-q.err index 5e17f3169b..f939e044eb 100644 --- a/tests/qapi-schema/reserved-command-q.err +++ b/tests/qapi-schema/reserved-command-q.err @@ -1 +1 @@ -tests/qapi-schema/reserved-command-q.json:12: 'command' uses invalid name 'q-unix' +tests/qapi-schema/reserved-command-q.json:5: 'command' uses invalid name 'q-unix' diff --git a/tests/qapi-schema/reserved-command-q.json b/tests/qapi-schema/reserved-command-q.json index bba0860c99..99f8aae314 100644 --- a/tests/qapi-schema/reserved-command-q.json +++ b/tests/qapi-schema/reserved-command-q.json @@ -1,12 +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. - -## -# @unix: -## { 'command': 'unix' } -## -# @q-unix: -## { 'command': 'q-unix' } diff --git a/tests/qapi-schema/reserved-enum-q.err b/tests/qapi-schema/reserved-enum-q.err index acb2df811d..e1c3480ee2 100644 --- a/tests/qapi-schema/reserved-enum-q.err +++ b/tests/qapi-schema/reserved-enum-q.err @@ -1 +1 @@ -tests/qapi-schema/reserved-enum-q.json:8: Member of enum 'Foo' uses invalid name 'q-Unix' +tests/qapi-schema/reserved-enum-q.json:4: Member of enum 'Foo' uses invalid name 'q-Unix' diff --git a/tests/qapi-schema/reserved-enum-q.json b/tests/qapi-schema/reserved-enum-q.json index 6c7e7177c3..3593a765ea 100644 --- a/tests/qapi-schema/reserved-enum-q.json +++ b/tests/qapi-schema/reserved-enum-q.json @@ -1,8 +1,4 @@ # C entity name collision # We reject names like 'q-unix', because they can collide with the mangled # name for 'unix' in generated C. - -## -# @Foo: -## { 'enum': 'Foo', 'data': [ 'unix', 'q-Unix' ] } diff --git a/tests/qapi-schema/reserved-member-has.err b/tests/qapi-schema/reserved-member-has.err index 9ace796055..e755771446 100644 --- a/tests/qapi-schema/reserved-member-has.err +++ b/tests/qapi-schema/reserved-member-has.err @@ -1 +1 @@ -tests/qapi-schema/reserved-member-has.json:9: Member of 'data' for command 'oops' uses reserved name 'has-a' +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.json b/tests/qapi-schema/reserved-member-has.json index f0d8905ca2..45b9109bdc 100644 --- a/tests/qapi-schema/reserved-member-has.json +++ b/tests/qapi-schema/reserved-member-has.json @@ -2,8 +2,4 @@ # 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. - -## -# @oops: -## { 'command': 'oops', 'data': { '*a': 'str', 'has-a': 'str' } } diff --git a/tests/qapi-schema/reserved-member-q.err b/tests/qapi-schema/reserved-member-q.err index 1709a88462..f3d5dd7818 100644 --- a/tests/qapi-schema/reserved-member-q.err +++ b/tests/qapi-schema/reserved-member-q.err @@ -1 +1 @@ -tests/qapi-schema/reserved-member-q.json:8: Member of 'data' for struct 'Foo' uses invalid name 'q-unix' +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.json b/tests/qapi-schema/reserved-member-q.json index f51e312917..62fed8fddf 100644 --- a/tests/qapi-schema/reserved-member-q.json +++ b/tests/qapi-schema/reserved-member-q.json @@ -1,8 +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. - -## -# @Foo: -## { 'struct': 'Foo', 'data': { 'unix':'int', 'q-unix':'bool' } } diff --git a/tests/qapi-schema/reserved-member-u.err b/tests/qapi-schema/reserved-member-u.err index 6ec69a712a..87d42296cc 100644 --- a/tests/qapi-schema/reserved-member-u.err +++ b/tests/qapi-schema/reserved-member-u.err @@ -1 +1 @@ -tests/qapi-schema/reserved-member-u.json:11: Member of 'data' for struct 'Oops' uses reserved name 'u' +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.json b/tests/qapi-schema/reserved-member-u.json index 3a578e5b56..1eaf0f301c 100644 --- a/tests/qapi-schema/reserved-member-u.json +++ b/tests/qapi-schema/reserved-member-u.json @@ -4,8 +4,4 @@ # 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 - -## -# @Oops: -## { 'struct': 'Oops', 'data': { 'u': 'str' } } diff --git a/tests/qapi-schema/reserved-member-underscore.err b/tests/qapi-schema/reserved-member-underscore.err index c9aefee3a8..65ff0da8ce 100644 --- a/tests/qapi-schema/reserved-member-underscore.err +++ b/tests/qapi-schema/reserved-member-underscore.err @@ -1 +1 @@ -tests/qapi-schema/reserved-member-underscore.json:8: Member of 'data' for struct 'Oops' uses invalid name '_oops' +tests/qapi-schema/reserved-member-underscore.json:4: Member of 'data' for struct 'Oops' uses invalid name '_oops' diff --git a/tests/qapi-schema/reserved-member-underscore.json b/tests/qapi-schema/reserved-member-underscore.json index cc34b54b02..4a3a017638 100644 --- a/tests/qapi-schema/reserved-member-underscore.json +++ b/tests/qapi-schema/reserved-member-underscore.json @@ -1,8 +1,4 @@ # C member name collision # We reject use of a single leading underscore in all names (names must # begin with a letter or a downstream extension double-underscore prefix). - -## -# @Oops: -## { 'struct': 'Oops', 'data': { '_oops': 'str' } } diff --git a/tests/qapi-schema/reserved-type-kind.err b/tests/qapi-schema/reserved-type-kind.err index 8698073062..0a38efaad8 100644 --- a/tests/qapi-schema/reserved-type-kind.err +++ b/tests/qapi-schema/reserved-type-kind.err @@ -1 +1 @@ -tests/qapi-schema/reserved-type-kind.json:6: enum 'UnionKind' should not end in 'Kind' +tests/qapi-schema/reserved-type-kind.json:2: enum 'UnionKind' should not end in 'Kind' diff --git a/tests/qapi-schema/reserved-type-kind.json b/tests/qapi-schema/reserved-type-kind.json index a094941561..9ecaba12bc 100644 --- a/tests/qapi-schema/reserved-type-kind.json +++ b/tests/qapi-schema/reserved-type-kind.json @@ -1,6 +1,2 @@ # we reject types that would conflict with implicit union enum - -## -# @UnionKind: -## { 'enum': 'UnionKind', 'data': [ 'oops' ] } diff --git a/tests/qapi-schema/reserved-type-list.err b/tests/qapi-schema/reserved-type-list.err index ec0531c4b9..4510fa6d90 100644 --- a/tests/qapi-schema/reserved-type-list.err +++ b/tests/qapi-schema/reserved-type-list.err @@ -1 +1 @@ -tests/qapi-schema/reserved-type-list.json:9: struct 'FooList' should not end in 'List' +tests/qapi-schema/reserved-type-list.json:5: struct 'FooList' should not end in 'List' diff --git a/tests/qapi-schema/reserved-type-list.json b/tests/qapi-schema/reserved-type-list.json index 6effb78e7f..98d53bf808 100644 --- a/tests/qapi-schema/reserved-type-list.json +++ b/tests/qapi-schema/reserved-type-list.json @@ -2,8 +2,4 @@ # 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 - -## -# @FooList: -## { 'struct': 'FooList', 'data': { 's': 'str' } } diff --git a/tests/qapi-schema/returns-alternate.err b/tests/qapi-schema/returns-alternate.err index 2b81623ca3..dfbb419cac 100644 --- a/tests/qapi-schema/returns-alternate.err +++ b/tests/qapi-schema/returns-alternate.err @@ -1 +1 @@ -tests/qapi-schema/returns-alternate.json:10: 'returns' for command 'oops' cannot use alternate type 'Alt' +tests/qapi-schema/returns-alternate.json:3: 'returns' for command 'oops' cannot use alternate type 'Alt' diff --git a/tests/qapi-schema/returns-alternate.json b/tests/qapi-schema/returns-alternate.json index 005bf2d148..972390c06b 100644 --- a/tests/qapi-schema/returns-alternate.json +++ b/tests/qapi-schema/returns-alternate.json @@ -1,10 +1,3 @@ # we reject returns if it is an alternate type - -## -# @Alt: -## { 'alternate': 'Alt', 'data': { 'a': 'int', 'b': 'str' } } -## -# @oops: -## { 'command': 'oops', 'returns': 'Alt' } diff --git a/tests/qapi-schema/returns-array-bad.err b/tests/qapi-schema/returns-array-bad.err index b53bdb0ade..138095ccde 100644 --- a/tests/qapi-schema/returns-array-bad.err +++ b/tests/qapi-schema/returns-array-bad.err @@ -1 +1 @@ -tests/qapi-schema/returns-array-bad.json:6: 'returns' for command 'oops': array type must contain single type name +tests/qapi-schema/returns-array-bad.json:2: 'returns' for command 'oops': array type must contain single type name diff --git a/tests/qapi-schema/returns-array-bad.json b/tests/qapi-schema/returns-array-bad.json index 30528fed29..09b0b1f182 100644 --- a/tests/qapi-schema/returns-array-bad.json +++ b/tests/qapi-schema/returns-array-bad.json @@ -1,6 +1,2 @@ # we reject an array return that is not a single type - -## -# @oops: -## { 'command': 'oops', 'returns': [ 'str', 'str' ] } diff --git a/tests/qapi-schema/returns-dict.err b/tests/qapi-schema/returns-dict.err index 1570a35d49..eb2d0c4661 100644 --- a/tests/qapi-schema/returns-dict.err +++ b/tests/qapi-schema/returns-dict.err @@ -1 +1 @@ -tests/qapi-schema/returns-dict.json:6: 'returns' for command 'oops' should be a type name +tests/qapi-schema/returns-dict.json:2: 'returns' for command 'oops' should be a type name diff --git a/tests/qapi-schema/returns-dict.json b/tests/qapi-schema/returns-dict.json index 6a3ed0f34d..1cfef3ede7 100644 --- a/tests/qapi-schema/returns-dict.json +++ b/tests/qapi-schema/returns-dict.json @@ -1,6 +1,2 @@ # we reject inline struct return type - -## -# @oops: -## { 'command': 'oops', 'returns': { 'a': 'str' } } diff --git a/tests/qapi-schema/returns-unknown.err b/tests/qapi-schema/returns-unknown.err index d76bcfe455..1f43e3ac9f 100644 --- a/tests/qapi-schema/returns-unknown.err +++ b/tests/qapi-schema/returns-unknown.err @@ -1 +1 @@ -tests/qapi-schema/returns-unknown.json:6: 'returns' for command 'oops' uses unknown type 'NoSuchType' +tests/qapi-schema/returns-unknown.json:2: 'returns' for command 'oops' uses unknown type 'NoSuchType' diff --git a/tests/qapi-schema/returns-unknown.json b/tests/qapi-schema/returns-unknown.json index 3837f0e607..25bd498bff 100644 --- a/tests/qapi-schema/returns-unknown.json +++ b/tests/qapi-schema/returns-unknown.json @@ -1,6 +1,2 @@ # we reject returns if it does not contain a known type - -## -# @oops: -## { 'command': 'oops', 'returns': 'NoSuchType' } diff --git a/tests/qapi-schema/returns-whitelist.err b/tests/qapi-schema/returns-whitelist.err index e77ea2da3f..b2ba7a9deb 100644 --- a/tests/qapi-schema/returns-whitelist.err +++ b/tests/qapi-schema/returns-whitelist.err @@ -1 +1 @@ -tests/qapi-schema/returns-whitelist.json:26: 'returns' for command 'no-way-this-will-get-whitelisted' cannot use built-in type 'int' +tests/qapi-schema/returns-whitelist.json:14: 'returns' for command 'no-way-this-will-get-whitelisted' cannot use built-in type 'int' diff --git a/tests/qapi-schema/returns-whitelist.json b/tests/qapi-schema/returns-whitelist.json index 0bc952db87..da209329b1 100644 --- a/tests/qapi-schema/returns-whitelist.json +++ b/tests/qapi-schema/returns-whitelist.json @@ -1,27 +1,15 @@ # we enforce that 'returns' be a dict or array of dict unless whitelisted -## -# @human-monitor-command: -## +{ 'pragma': { 'returns-whitelist': [ + 'human-monitor-command', 'query-tpm-models', 'guest-get-time' ] } } + { 'command': 'human-monitor-command', 'data': {'command-line': 'str', '*cpu-index': 'int'}, 'returns': 'str' } -## -# @TpmModel: -## { 'enum': 'TpmModel', 'data': [ 'tpm-tis' ] } -## -# @query-tpm-models: -## { 'command': 'query-tpm-models', 'returns': ['TpmModel'] } -## -# @guest-get-time: -## { 'command': 'guest-get-time', 'returns': 'int' } -## -# @no-way-this-will-get-whitelisted: -## { 'command': 'no-way-this-will-get-whitelisted', 'returns': [ 'int' ] } diff --git a/tests/qapi-schema/struct-base-clash-deep.err b/tests/qapi-schema/struct-base-clash-deep.err index 1b7c0e9d12..e2d7943f21 100644 --- a/tests/qapi-schema/struct-base-clash-deep.err +++ b/tests/qapi-schema/struct-base-clash-deep.err @@ -1 +1 @@ -tests/qapi-schema/struct-base-clash-deep.json:20: 'name' (member of Sub) collides with 'name' (member of Base) +tests/qapi-schema/struct-base-clash-deep.json:10: 'name' (member of Sub) collides with 'name' (member of Base) diff --git a/tests/qapi-schema/struct-base-clash-deep.json b/tests/qapi-schema/struct-base-clash-deep.json index 646d680ad6..fa873ab5d4 100644 --- a/tests/qapi-schema/struct-base-clash-deep.json +++ b/tests/qapi-schema/struct-base-clash-deep.json @@ -2,21 +2,11 @@ # Here, 'name' would have to appear twice on the wire, locally and # indirectly for the grandparent base; the collision doesn't care that # one instance is optional. - -## -# @Base: -## { 'struct': 'Base', 'data': { 'name': 'str' } } -## -# @Mid: -## { 'struct': 'Mid', 'base': 'Base', 'data': { 'value': 'int' } } -## -# @Sub: -## { 'struct': 'Sub', 'base': 'Mid', 'data': { '*name': 'str' } } diff --git a/tests/qapi-schema/struct-base-clash.err b/tests/qapi-schema/struct-base-clash.err index 5fe6393efa..c52f33d27b 100644 --- a/tests/qapi-schema/struct-base-clash.err +++ b/tests/qapi-schema/struct-base-clash.err @@ -1 +1 @@ -tests/qapi-schema/struct-base-clash.json:12: 'name' (member of Sub) collides with 'name' (member of Base) +tests/qapi-schema/struct-base-clash.json:5: 'name' (member of Sub) collides with 'name' (member of Base) diff --git a/tests/qapi-schema/struct-base-clash.json b/tests/qapi-schema/struct-base-clash.json index a8539958b5..11aec80fe5 100644 --- a/tests/qapi-schema/struct-base-clash.json +++ b/tests/qapi-schema/struct-base-clash.json @@ -1,14 +1,7 @@ # Reject attempts to duplicate QMP members # Here, 'name' would have to appear twice on the wire, locally and for base. - -## -# @Base: -## { 'struct': 'Base', 'data': { 'name': 'str' } } -## -# @Sub: -## { 'struct': 'Sub', 'base': 'Base', 'data': { 'name': 'str' } } diff --git a/tests/qapi-schema/struct-data-invalid.err b/tests/qapi-schema/struct-data-invalid.err index 27163355bd..6644f4c2ad 100644 --- a/tests/qapi-schema/struct-data-invalid.err +++ b/tests/qapi-schema/struct-data-invalid.err @@ -1 +1 @@ -tests/qapi-schema/struct-data-invalid.json:4: 'data' for struct 'foo' should be a dictionary or type name +tests/qapi-schema/struct-data-invalid.json:1: 'data' for struct 'foo' should be a dictionary or type name diff --git a/tests/qapi-schema/struct-data-invalid.json b/tests/qapi-schema/struct-data-invalid.json index aa817bda34..9adbc3bb6b 100644 --- a/tests/qapi-schema/struct-data-invalid.json +++ b/tests/qapi-schema/struct-data-invalid.json @@ -1,5 +1,2 @@ -## -# @foo: -## { 'struct': 'foo', 'data': false } diff --git a/tests/qapi-schema/struct-member-invalid.err b/tests/qapi-schema/struct-member-invalid.err index f2b105ba88..69a326d450 100644 --- a/tests/qapi-schema/struct-member-invalid.err +++ b/tests/qapi-schema/struct-member-invalid.err @@ -1 +1 @@ -tests/qapi-schema/struct-member-invalid.json:4: Member 'a' of 'data' for struct 'foo' should be a type name +tests/qapi-schema/struct-member-invalid.json:1: Member 'a' of 'data' for struct 'foo' should be a type name diff --git a/tests/qapi-schema/struct-member-invalid.json b/tests/qapi-schema/struct-member-invalid.json index 10c74262d3..8f172f7a87 100644 --- a/tests/qapi-schema/struct-member-invalid.json +++ b/tests/qapi-schema/struct-member-invalid.json @@ -1,5 +1,2 @@ -## -# @foo: -## { 'struct': 'foo', 'data': { 'a': false } } diff --git a/tests/qapi-schema/test-qapi.py b/tests/qapi-schema/test-qapi.py index b4cde4ff4f..ef74e2c4c8 100644 --- a/tests/qapi-schema/test-qapi.py +++ b/tests/qapi-schema/test-qapi.py @@ -55,17 +55,3 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor): schema = QAPISchema(sys.argv[1]) schema.visit(QAPISchemaTestVisitor()) - -for doc in schema.docs: - if doc.symbol: - print 'doc symbol=%s expr=%s' % \ - (doc.symbol, doc.expr.items()[0]) - else: - print 'doc freeform' - for arg, section in doc.args.iteritems(): - print ' arg=%s\n%s' % (arg, section) - for section in doc.sections: - print ' section=%s\n%s' % (section.name, section) - body = str(doc.body) - if body: - print ' body=\n%s' % body diff --git a/tests/qapi-schema/trailing-comma-list.err b/tests/qapi-schema/trailing-comma-list.err index 24c24b0108..212e14ae28 100644 --- a/tests/qapi-schema/trailing-comma-list.err +++ b/tests/qapi-schema/trailing-comma-list.err @@ -1 +1 @@ -tests/qapi-schema/trailing-comma-list.json:2:36: Expected "{", "[" or string +tests/qapi-schema/trailing-comma-list.json:2:36: Expected "{", "[", string, boolean or "null" diff --git a/tests/qapi-schema/type-bypass-bad-gen.err b/tests/qapi-schema/type-bypass-bad-gen.err index bd5431f60b..a83c3c655d 100644 --- a/tests/qapi-schema/type-bypass-bad-gen.err +++ b/tests/qapi-schema/type-bypass-bad-gen.err @@ -1 +1 @@ -tests/qapi-schema/type-bypass-bad-gen.json:6: 'gen' of command 'foo' should only use false value +tests/qapi-schema/type-bypass-bad-gen.json:2: 'gen' of command 'foo' should only use false value diff --git a/tests/qapi-schema/type-bypass-bad-gen.json b/tests/qapi-schema/type-bypass-bad-gen.json index 7162c1a0ca..e8dec34249 100644 --- a/tests/qapi-schema/type-bypass-bad-gen.json +++ b/tests/qapi-schema/type-bypass-bad-gen.json @@ -1,6 +1,2 @@ # 'gen' should only appear with value false - -## -# @foo: -## { 'command': 'foo', 'gen': 'whatever' } diff --git a/tests/qapi-schema/unicode-str.err b/tests/qapi-schema/unicode-str.err index 92ee277370..f621cd6448 100644 --- a/tests/qapi-schema/unicode-str.err +++ b/tests/qapi-schema/unicode-str.err @@ -1 +1 @@ -tests/qapi-schema/unicode-str.json:6: 'command' uses invalid name 'é' +tests/qapi-schema/unicode-str.json:2: 'command' uses invalid name 'é' diff --git a/tests/qapi-schema/unicode-str.json b/tests/qapi-schema/unicode-str.json index 75a08b3d93..5253a1b9f3 100644 --- a/tests/qapi-schema/unicode-str.json +++ b/tests/qapi-schema/unicode-str.json @@ -1,6 +1,2 @@ # we don't support full Unicode strings, yet - -## -# @e: -## { 'command': 'é' } diff --git a/tests/qapi-schema/union-base-empty.err b/tests/qapi-schema/union-base-empty.err new file mode 100644 index 0000000000..7695806d81 --- /dev/null +++ b/tests/qapi-schema/union-base-empty.err @@ -0,0 +1 @@ +tests/qapi-schema/union-base-empty.json:5: Discriminator 'type' is not a member of base struct 'Empty' diff --git a/tests/qapi-schema/union-base-empty.exit b/tests/qapi-schema/union-base-empty.exit new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/tests/qapi-schema/union-base-empty.exit @@ -0,0 +1 @@ +1 diff --git a/tests/qapi-schema/union-base-empty.json b/tests/qapi-schema/union-base-empty.json new file mode 100644 index 0000000000..d1843d33b4 --- /dev/null +++ b/tests/qapi-schema/union-base-empty.json @@ -0,0 +1,9 @@ +# Flat union with empty base and therefore without discriminator + +{ 'struct': 'Empty', 'data': { } } + +{ 'union': 'TestUnion', + 'base': 'Empty', + 'discriminator': 'type', + 'data': { 'value1': 'int', + 'value2': 'str' } } diff --git a/tests/qapi-schema/union-base-empty.out b/tests/qapi-schema/union-base-empty.out new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/qapi-schema/union-base-empty.out diff --git a/tests/qapi-schema/union-base-no-discriminator.err b/tests/qapi-schema/union-base-no-discriminator.err index ca6ee92357..8b7a24260f 100644 --- a/tests/qapi-schema/union-base-no-discriminator.err +++ b/tests/qapi-schema/union-base-no-discriminator.err @@ -1 +1 @@ -tests/qapi-schema/union-base-no-discriminator.json:23: Simple union 'TestUnion' must not have a base +tests/qapi-schema/union-base-no-discriminator.json:11: Simple union 'TestUnion' must not have a base diff --git a/tests/qapi-schema/union-base-no-discriminator.json b/tests/qapi-schema/union-base-no-discriminator.json index cc6bac1424..1409cf5c9e 100644 --- a/tests/qapi-schema/union-base-no-discriminator.json +++ b/tests/qapi-schema/union-base-no-discriminator.json @@ -1,25 +1,13 @@ -## -# @TestTypeA: -## # we reject simple unions with a base (or flat unions without discriminator) { 'struct': 'TestTypeA', 'data': { 'string': 'str' } } -## -# @TestTypeB: -## { 'struct': 'TestTypeB', 'data': { 'integer': 'int' } } -## -# @Base: -## { 'struct': 'Base', 'data': { 'string': 'str' } } -## -# @TestUnion: -## { 'union': 'TestUnion', 'base': 'Base', 'data': { 'value1': 'TestTypeA', diff --git a/tests/qapi-schema/union-branch-case.err b/tests/qapi-schema/union-branch-case.err index 9095bae565..11521901d8 100644 --- a/tests/qapi-schema/union-branch-case.err +++ b/tests/qapi-schema/union-branch-case.err @@ -1 +1 @@ -tests/qapi-schema/union-branch-case.json:6: 'Branch' (branch of NoWayThisWillGetWhitelisted) should not use uppercase +tests/qapi-schema/union-branch-case.json:2: 'Branch' (branch of NoWayThisWillGetWhitelisted) should not use uppercase diff --git a/tests/qapi-schema/union-branch-case.json b/tests/qapi-schema/union-branch-case.json index 6de131548c..e6565dc3b3 100644 --- a/tests/qapi-schema/union-branch-case.json +++ b/tests/qapi-schema/union-branch-case.json @@ -1,6 +1,2 @@ # Branch names should be 'lower-case' unless the union is whitelisted - -## -# @NoWayThisWillGetWhitelisted: -## { 'union': 'NoWayThisWillGetWhitelisted', 'data': { 'Branch': 'int' } } diff --git a/tests/qapi-schema/union-clash-branches.err b/tests/qapi-schema/union-clash-branches.err index 640caeab8c..e5b21135bb 100644 --- a/tests/qapi-schema/union-clash-branches.err +++ b/tests/qapi-schema/union-clash-branches.err @@ -1 +1 @@ -tests/qapi-schema/union-clash-branches.json:8: 'a_b' (branch of TestUnion) collides with 'a-b' (branch of TestUnion) +tests/qapi-schema/union-clash-branches.json:4: 'a_b' (branch of TestUnion) collides with 'a-b' (branch of TestUnion) diff --git a/tests/qapi-schema/union-clash-branches.json b/tests/qapi-schema/union-clash-branches.json index 6615665dfe..3bece8c948 100644 --- a/tests/qapi-schema/union-clash-branches.json +++ b/tests/qapi-schema/union-clash-branches.json @@ -1,9 +1,5 @@ # Union branch name collision # Reject a union that would result in a collision in generated C names (this # would try to generate two members 'a_b'). - -## -# @TestUnion: -## { 'union': 'TestUnion', 'data': { 'a-b': 'int', 'a_b': 'str' } } diff --git a/tests/qapi-schema/union-empty.err b/tests/qapi-schema/union-empty.err index 749bc76fc5..12c20221bd 100644 --- a/tests/qapi-schema/union-empty.err +++ b/tests/qapi-schema/union-empty.err @@ -1 +1 @@ -tests/qapi-schema/union-empty.json:6: Union 'Union' cannot have empty 'data' +tests/qapi-schema/union-empty.json:2: Union 'Union' cannot have empty 'data' diff --git a/tests/qapi-schema/union-empty.json b/tests/qapi-schema/union-empty.json index c9b0a1ef33..1f0b13ca21 100644 --- a/tests/qapi-schema/union-empty.json +++ b/tests/qapi-schema/union-empty.json @@ -1,6 +1,2 @@ # unions cannot be empty - -## -# @Union: -## { 'union': 'Union', 'data': { } } diff --git a/tests/qapi-schema/union-invalid-base.err b/tests/qapi-schema/union-invalid-base.err index 41e238f453..03d7b97a93 100644 --- a/tests/qapi-schema/union-invalid-base.err +++ b/tests/qapi-schema/union-invalid-base.err @@ -1 +1 @@ -tests/qapi-schema/union-invalid-base.json:18: 'base' for union 'TestUnion' cannot use built-in type 'int' +tests/qapi-schema/union-invalid-base.json:8: 'base' for union 'TestUnion' cannot use built-in type 'int' diff --git a/tests/qapi-schema/union-invalid-base.json b/tests/qapi-schema/union-invalid-base.json index fd837cb80b..92be39df69 100644 --- a/tests/qapi-schema/union-invalid-base.json +++ b/tests/qapi-schema/union-invalid-base.json @@ -1,20 +1,10 @@ # a union base type must be a struct - -## -# @TestTypeA: -## { 'struct': 'TestTypeA', 'data': { 'string': 'str' } } -## -# @TestTypeB: -## { 'struct': 'TestTypeB', 'data': { 'integer': 'int' } } -## -# @TestUnion: -## { 'union': 'TestUnion', 'base': 'int', 'discriminator': 'int', diff --git a/tests/qapi-schema/union-optional-branch.err b/tests/qapi-schema/union-optional-branch.err index 60523c07e4..3ada1334dc 100644 --- a/tests/qapi-schema/union-optional-branch.err +++ b/tests/qapi-schema/union-optional-branch.err @@ -1 +1 @@ -tests/qapi-schema/union-optional-branch.json:6: Member of union 'Union' does not allow optional name '*a' +tests/qapi-schema/union-optional-branch.json:2: Member of union 'Union' does not allow optional name '*a' diff --git a/tests/qapi-schema/union-optional-branch.json b/tests/qapi-schema/union-optional-branch.json index 7d2ee4c730..591615fc68 100644 --- a/tests/qapi-schema/union-optional-branch.json +++ b/tests/qapi-schema/union-optional-branch.json @@ -1,6 +1,2 @@ # union branches cannot be optional - -## -# @Union: -## { 'union': 'Union', 'data': { '*a': 'int', 'b': 'str' } } diff --git a/tests/qapi-schema/union-unknown.err b/tests/qapi-schema/union-unknown.err index 5568302205..54fe456f9c 100644 --- a/tests/qapi-schema/union-unknown.err +++ b/tests/qapi-schema/union-unknown.err @@ -1 +1 @@ -tests/qapi-schema/union-unknown.json:6: Member 'unknown' of union 'Union' uses unknown type 'MissingType' +tests/qapi-schema/union-unknown.json:2: Member 'unknown' of union 'Union' uses unknown type 'MissingType' diff --git a/tests/qapi-schema/union-unknown.json b/tests/qapi-schema/union-unknown.json index 5042b23197..aa7e8143d8 100644 --- a/tests/qapi-schema/union-unknown.json +++ b/tests/qapi-schema/union-unknown.json @@ -1,7 +1,3 @@ # we reject a union with unknown type in branch - -## -# @Union: -## { 'union': 'Union', 'data': { 'unknown': 'MissingType' } } diff --git a/tests/qapi-schema/unknown-escape.err b/tests/qapi-schema/unknown-escape.err index 1a4ead632b..000e30ddf3 100644 --- a/tests/qapi-schema/unknown-escape.err +++ b/tests/qapi-schema/unknown-escape.err @@ -1 +1 @@ -tests/qapi-schema/unknown-escape.json:7:21: Unknown escape \x +tests/qapi-schema/unknown-escape.json:3:21: Unknown escape \x diff --git a/tests/qapi-schema/unknown-escape.json b/tests/qapi-schema/unknown-escape.json index e3ae6793f2..8e6891e52a 100644 --- a/tests/qapi-schema/unknown-escape.json +++ b/tests/qapi-schema/unknown-escape.json @@ -1,7 +1,3 @@ # we only recognize JSON escape sequences, plus our \' extension (no \x) - -## -# @foo: -## # { 'command': 'foo', 'data': {} } { 'command': 'foo', 'dat\x61':{} } diff --git a/tests/qapi-schema/unknown-expr-key.err b/tests/qapi-schema/unknown-expr-key.err index b19a668bd6..12f5ed5b43 100644 --- a/tests/qapi-schema/unknown-expr-key.err +++ b/tests/qapi-schema/unknown-expr-key.err @@ -1 +1 @@ -tests/qapi-schema/unknown-expr-key.json:6: Unknown key 'bogus' in struct 'bar' +tests/qapi-schema/unknown-expr-key.json:2: Unknown key 'bogus' in struct 'bar' diff --git a/tests/qapi-schema/unknown-expr-key.json b/tests/qapi-schema/unknown-expr-key.json index 1b764c7b9d..3b2be00cc4 100644 --- a/tests/qapi-schema/unknown-expr-key.json +++ b/tests/qapi-schema/unknown-expr-key.json @@ -1,6 +1,2 @@ # we reject an expression with unknown top-level keys - -## -# @bar: -## { 'struct': 'bar', 'data': { 'string': 'str'}, 'bogus': { } } diff --git a/tests/qemu-iotests/025 b/tests/qemu-iotests/025 index c41370f3b2..f5e672e6b3 100755 --- a/tests/qemu-iotests/025 +++ b/tests/qemu-iotests/025 @@ -39,7 +39,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 . ./common.pattern _supported_fmt raw qcow2 qed -_supported_proto file sheepdog rbd nfs archipelago +_supported_proto file sheepdog rbd nfs _supported_os Linux echo "=== Creating image" diff --git a/tests/qemu-iotests/common b/tests/qemu-iotests/common index b6274bee0a..4d5650d7c8 100644 --- a/tests/qemu-iotests/common +++ b/tests/qemu-iotests/common @@ -156,7 +156,6 @@ check options -nbd test nbd -ssh test ssh -nfs test nfs - -archipelago test archipelago -luks test luks -xdiff graphical mode diff -nocache use O_DIRECT on backing file @@ -271,11 +270,6 @@ testlist options xpand=false ;; - -archipelago) - IMGPROTO=archipelago - xpand=false - ;; - -nocache) CACHEMODE="none" CACHEMODE_IS_DEFAULT=false diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter index 4befd865f4..104001358b 100644 --- a/tests/qemu-iotests/common.filter +++ b/tests/qemu-iotests/common.filter @@ -112,7 +112,6 @@ _filter_img_create() -e "s# block_size=[0-9]\\+##g" \ -e "s# block_state_zero=\\(on\\|off\\)##g" \ -e "s# log_size=[0-9]\\+##g" \ - -e "s/archipelago:a/TEST_DIR\//g" \ -e "s# refcount_bits=[0-9]\\+##g" \ -e "s# key-secret=[a-zA-Z0-9]\\+##g" } @@ -136,8 +135,7 @@ _filter_img_info() -e "/lazy_refcounts: \\(on\\|off\\)/d" \ -e "/block_size: [0-9]\\+/d" \ -e "/block_state_zero: \\(on\\|off\\)/d" \ - -e "/log_size: [0-9]\\+/d" \ - -e "s/archipelago:a/TEST_DIR\//g" + -e "/log_size: [0-9]\\+/d" } # filter out offsets and file names from qemu-img map diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc index 08065dceae..7d4781d4ad 100644 --- a/tests/qemu-iotests/common.rc +++ b/tests/qemu-iotests/common.rc @@ -70,8 +70,6 @@ if [ "$IMGOPTSSYNTAX" = "true" ]; then elif [ "$IMGPROTO" = "nfs" ]; then TEST_DIR="$DRIVER,file.driver=nfs,file.filename=nfs://127.0.0.1/$TEST_DIR" TEST_IMG=$TEST_DIR/t.$IMGFMT - elif [ "$IMGPROTO" = "archipelago" ]; then - TEST_IMG="$DRIVER,file.driver=archipelago,file.volume=:at.$IMGFMT" else TEST_IMG="$DRIVER,file.driver=$IMGPROTO,file.filename=$TEST_DIR/t.$IMGFMT" fi @@ -87,8 +85,6 @@ else elif [ "$IMGPROTO" = "nfs" ]; then TEST_DIR="nfs://127.0.0.1/$TEST_DIR" TEST_IMG=$TEST_DIR/t.$IMGFMT - elif [ "$IMGPROTO" = "archipelago" ]; then - TEST_IMG="archipelago:at.$IMGFMT" else TEST_IMG=$IMGPROTO:$TEST_DIR/t.$IMGFMT fi @@ -215,10 +211,6 @@ _cleanup_test_img() rbd --no-progress rm "$TEST_DIR/t.$IMGFMT" > /dev/null ;; - archipelago) - vlmc remove "at.$IMGFMT" > /dev/null - ;; - sheepdog) collie vdi delete "$TEST_DIR/t.$IMGFMT" ;; diff --git a/tests/test-aio-multithread.c b/tests/test-aio-multithread.c index 8b0b40ec78..549d784915 100644 --- a/tests/test-aio-multithread.c +++ b/tests/test-aio-multithread.c @@ -438,7 +438,7 @@ static void test_multi_mutex_10(void) int main(int argc, char **argv) { - init_clocks(); + init_clocks(NULL); g_test_init(&argc, &argv, NULL); g_test_add_func("/aio/multi/lifecycle", test_lifecycle); diff --git a/tests/test-aio.c b/tests/test-aio.c index 2754f154ce..54e20d6ab1 100644 --- a/tests/test-aio.c +++ b/tests/test-aio.c @@ -835,7 +835,7 @@ int main(int argc, char **argv) Error *local_error = NULL; GSource *src; - init_clocks(); + init_clocks(NULL); ctx = aio_context_new(&local_error); if (!ctx) { diff --git a/tests/test-qemu-opts.c b/tests/test-qemu-opts.c index f6310b34f1..0ad74b464f 100644 --- a/tests/test-qemu-opts.c +++ b/tests/test-qemu-opts.c @@ -93,8 +93,7 @@ static void test_find_unknown_opts(void) /* should not return anything, we don't have an "unknown" option */ list = qemu_find_opts_err("unknown", &err); g_assert(list == NULL); - g_assert(err); - error_free(err); + error_free_or_abort(&err); } static void test_qemu_find_opts(void) diff --git a/tests/test-qobject-output-visitor.c b/tests/test-qobject-output-visitor.c index 500b452d98..c213fceeb3 100644 --- a/tests/test-qobject-output-visitor.c +++ b/tests/test-qobject-output-visitor.c @@ -145,8 +145,7 @@ static void test_visitor_out_enum_errors(TestOutputVisitorData *data, for (i = 0; i < ARRAY_SIZE(bad_values) ; i++) { err = NULL; visit_type_EnumOne(data->ov, "unused", &bad_values[i], &err); - g_assert(err); - error_free(err); + error_free_or_abort(&err); visitor_reset(data); } } @@ -244,8 +243,7 @@ static void test_visitor_out_struct_errors(TestOutputVisitorData *data, u.has_enum1 = true; u.enum1 = bad_values[i]; visit_type_UserDefOne(data->ov, "unused", &pu, &err); - g_assert(err); - error_free(err); + error_free_or_abort(&err); visitor_reset(data); } } diff --git a/trace/Makefile.objs b/trace/Makefile.objs index 7de840ad7e..1b8eb4a616 100644 --- a/trace/Makefile.objs +++ b/trace/Makefile.objs @@ -1,13 +1,5 @@ # -*- mode: makefile -*- -###################################################################### -# tracetool source files -# Every rule that invokes tracetool must depend on this so code is regenerated -# if tracetool itself changes. - -tracetool-y = $(SRC_PATH)/scripts/tracetool.py -tracetool-y += $(shell find $(SRC_PATH)/scripts/tracetool -name "*.py") - $(BUILD_DIR)/trace-events-all: $(trace-events-files) $(call quiet-command,cat $^ > $@) diff --git a/translate-all.c b/translate-all.c index d42d003e67..b3ee876526 100644 --- a/translate-all.c +++ b/translate-all.c @@ -57,6 +57,7 @@ #include "qemu/timer.h" #include "qemu/main-loop.h" #include "exec/log.h" +#include "sysemu/cpus.h" /* #define DEBUG_TB_INVALIDATE */ /* #define DEBUG_TB_FLUSH */ @@ -333,6 +334,19 @@ bool cpu_restore_state(CPUState *cpu, uintptr_t retaddr) TranslationBlock *tb; bool r = false; + /* A retaddr of zero is invalid so we really shouldn't have ended + * up here. The target code has likely forgotten to check retaddr + * != 0 before attempting to restore state. We return early to + * avoid blowing up on a recursive tb_lock(). The target must have + * previously survived a failed cpu_restore_state because + * tb_find_pc(0) would have failed anyway. It still should be + * fixed though. + */ + + if (!retaddr) { + return r; + } + tb_lock(); tb = tb_find_pc(retaddr); if (tb) { diff --git a/ui/cocoa.m b/ui/cocoa.m index 26d4a1c07f..c81f7b6183 100644 --- a/ui/cocoa.m +++ b/ui/cocoa.m @@ -879,7 +879,7 @@ QemuCocoaView *cocoaView; // set the supported image file types that can be opened supportedImageFileTypes = [NSArray arrayWithObjects: @"img", @"iso", @"dmg", @"qcow", @"qcow2", @"cloop", @"vmdk", @"cdr", - nil]; + @"toast", nil]; [self make_about_window]; } return self; diff --git a/ui/console.c b/ui/console.c index d1ff7504ec..4c70d8bfda 100644 --- a/ui/console.c +++ b/ui/console.c @@ -1586,27 +1586,6 @@ static void dpy_refresh(DisplayState *s) } } -void dpy_gfx_copy(QemuConsole *con, int src_x, int src_y, - int dst_x, int dst_y, int w, int h) -{ - DisplayState *s = con->ds; - DisplayChangeListener *dcl; - - if (!qemu_console_is_visible(con)) { - return; - } - QLIST_FOREACH(dcl, &s->listeners, next) { - if (con != (dcl->con ? dcl->con : active_console)) { - continue; - } - if (dcl->ops->dpy_gfx_copy) { - dcl->ops->dpy_gfx_copy(dcl, src_x, src_y, dst_x, dst_y, w, h); - } else { /* TODO */ - dcl->ops->dpy_gfx_update(dcl, dst_x, dst_y, w, h); - } - } -} - void dpy_text_cursor(QemuConsole *con, int x, int y) { DisplayState *s = con->ds; @@ -2138,13 +2117,6 @@ void qemu_console_resize(QemuConsole *s, int width, int height) dpy_gfx_replace_surface(s, surface); } -void qemu_console_copy(QemuConsole *con, int src_x, int src_y, - int dst_x, int dst_y, int w, int h) -{ - assert(con->console_type == GRAPHIC_CONSOLE); - dpy_gfx_copy(con, src_x, src_y, dst_x, dst_y, w, h); -} - DisplaySurface *qemu_console_surface(QemuConsole *console) { return console->surface; @@ -894,105 +894,6 @@ int vnc_send_framebuffer_update(VncState *vs, int x, int y, int w, int h) return n; } -static void vnc_copy(VncState *vs, int src_x, int src_y, int dst_x, int dst_y, int w, int h) -{ - /* send bitblit op to the vnc client */ - vnc_lock_output(vs); - vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE); - vnc_write_u8(vs, 0); - vnc_write_u16(vs, 1); /* number of rects */ - vnc_framebuffer_update(vs, dst_x, dst_y, w, h, VNC_ENCODING_COPYRECT); - vnc_write_u16(vs, src_x); - vnc_write_u16(vs, src_y); - vnc_unlock_output(vs); - vnc_flush(vs); -} - -static void vnc_dpy_copy(DisplayChangeListener *dcl, - int src_x, int src_y, - int dst_x, int dst_y, int w, int h) -{ - VncDisplay *vd = container_of(dcl, VncDisplay, dcl); - VncState *vs, *vn; - uint8_t *src_row; - uint8_t *dst_row; - int i, x, y, pitch, inc, w_lim, s; - int cmp_bytes; - - if (!vd->server) { - /* no client connected */ - return; - } - - vnc_refresh_server_surface(vd); - QTAILQ_FOREACH_SAFE(vs, &vd->clients, next, vn) { - if (vnc_has_feature(vs, VNC_FEATURE_COPYRECT)) { - vs->force_update = 1; - vnc_update_client(vs, 1, true); - /* vs might be free()ed here */ - } - } - - if (!vd->server) { - /* no client connected */ - return; - } - /* do bitblit op on the local surface too */ - pitch = vnc_server_fb_stride(vd); - src_row = vnc_server_fb_ptr(vd, src_x, src_y); - dst_row = vnc_server_fb_ptr(vd, dst_x, dst_y); - y = dst_y; - inc = 1; - if (dst_y > src_y) { - /* copy backwards */ - src_row += pitch * (h-1); - dst_row += pitch * (h-1); - pitch = -pitch; - y = dst_y + h - 1; - inc = -1; - } - w_lim = w - (VNC_DIRTY_PIXELS_PER_BIT - (dst_x % VNC_DIRTY_PIXELS_PER_BIT)); - if (w_lim < 0) { - w_lim = w; - } else { - w_lim = w - (w_lim % VNC_DIRTY_PIXELS_PER_BIT); - } - for (i = 0; i < h; i++) { - for (x = 0; x <= w_lim; - x += s, src_row += cmp_bytes, dst_row += cmp_bytes) { - if (x == w_lim) { - if ((s = w - w_lim) == 0) - break; - } else if (!x) { - s = (VNC_DIRTY_PIXELS_PER_BIT - - (dst_x % VNC_DIRTY_PIXELS_PER_BIT)); - s = MIN(s, w_lim); - } else { - s = VNC_DIRTY_PIXELS_PER_BIT; - } - cmp_bytes = s * VNC_SERVER_FB_BYTES; - if (memcmp(src_row, dst_row, cmp_bytes) == 0) - continue; - memmove(dst_row, src_row, cmp_bytes); - QTAILQ_FOREACH(vs, &vd->clients, next) { - if (!vnc_has_feature(vs, VNC_FEATURE_COPYRECT)) { - set_bit(((x + dst_x) / VNC_DIRTY_PIXELS_PER_BIT), - vs->dirty[y]); - } - } - } - src_row += pitch - w * VNC_SERVER_FB_BYTES; - dst_row += pitch - w * VNC_SERVER_FB_BYTES; - y += inc; - } - - QTAILQ_FOREACH(vs, &vd->clients, next) { - if (vnc_has_feature(vs, VNC_FEATURE_COPYRECT)) { - vnc_copy(vs, src_x, src_y, dst_x, dst_y, w, h); - } - } -} - static void vnc_mouse_set(DisplayChangeListener *dcl, int x, int y, int visible) { @@ -3120,7 +3021,6 @@ static gboolean vnc_listen_io(QIOChannel *ioc, static const DisplayChangeListenerOps dcl_ops = { .dpy_name = "vnc", .dpy_refresh = vnc_refresh, - .dpy_gfx_copy = vnc_dpy_copy, .dpy_gfx_update = vnc_dpy_update, .dpy_gfx_switch = vnc_dpy_switch, .dpy_gfx_check_format = qemu_pixman_check_format, diff --git a/util/async.c b/util/async.c index 7d469eb857..663e297e1f 100644 --- a/util/async.c +++ b/util/async.c @@ -351,7 +351,7 @@ void aio_notify_accept(AioContext *ctx) } } -static void aio_timerlist_notify(void *opaque) +static void aio_timerlist_notify(void *opaque, QEMUClockType type) { aio_notify(opaque); } diff --git a/util/main-loop.c b/util/main-loop.c index ca7bb072f9..4534c89308 100644 --- a/util/main-loop.c +++ b/util/main-loop.c @@ -28,6 +28,7 @@ #include "qemu/timer.h" #include "qemu/sockets.h" // struct in_addr needed for libslirp.h #include "sysemu/qtest.h" +#include "sysemu/cpus.h" #include "slirp/libslirp.h" #include "qemu/main-loop.h" #include "block/aio.h" @@ -143,7 +144,7 @@ int qemu_init_main_loop(Error **errp) GSource *src; Error *local_error = NULL; - init_clocks(); + init_clocks(qemu_timer_notify_cb); ret = qemu_signal_init(); if (ret) { diff --git a/util/oslib-posix.c b/util/oslib-posix.c index cd686aae3d..3fe6089c3e 100644 --- a/util/oslib-posix.c +++ b/util/oslib-posix.c @@ -55,6 +55,21 @@ #include "qemu/error-report.h" #endif +#define MAX_MEM_PREALLOC_THREAD_COUNT (MIN(sysconf(_SC_NPROCESSORS_ONLN), 16)) + +struct MemsetThread { + char *addr; + uint64_t numpages; + uint64_t hpagesize; + QemuThread pgthread; + sigjmp_buf env; +}; +typedef struct MemsetThread MemsetThread; + +static MemsetThread *memset_thread; +static int memset_num_threads; +static bool memset_thread_failed; + int qemu_get_thread_id(void) { #if defined(__linux__) @@ -316,18 +331,95 @@ char *qemu_get_exec_dir(void) return g_strdup(exec_dir); } -static sigjmp_buf sigjump; - static void sigbus_handler(int signal) { - siglongjmp(sigjump, 1); + int i; + if (memset_thread) { + for (i = 0; i < memset_num_threads; i++) { + if (qemu_thread_is_self(&memset_thread[i].pgthread)) { + siglongjmp(memset_thread[i].env, 1); + } + } + } +} + +static void *do_touch_pages(void *arg) +{ + MemsetThread *memset_args = (MemsetThread *)arg; + char *addr = memset_args->addr; + uint64_t numpages = memset_args->numpages; + uint64_t hpagesize = memset_args->hpagesize; + sigset_t set, oldset; + int i = 0; + + /* unblock SIGBUS */ + sigemptyset(&set); + sigaddset(&set, SIGBUS); + pthread_sigmask(SIG_UNBLOCK, &set, &oldset); + + if (sigsetjmp(memset_args->env, 1)) { + memset_thread_failed = true; + } else { + for (i = 0; i < numpages; i++) { + /* + * Read & write back the same value, so we don't + * corrupt existing user/app data that might be + * stored. + * + * 'volatile' to stop compiler optimizing this away + * to a no-op + * + * TODO: get a better solution from kernel so we + * don't need to write at all so we don't cause + * wear on the storage backing the region... + */ + *(volatile char *)addr = *addr; + addr += hpagesize; + } + } + pthread_sigmask(SIG_SETMASK, &oldset, NULL); + return NULL; +} + +static bool touch_all_pages(char *area, size_t hpagesize, size_t numpages, + int smp_cpus) +{ + uint64_t numpages_per_thread, size_per_thread; + char *addr = area; + int i = 0; + + memset_thread_failed = false; + memset_num_threads = MIN(smp_cpus, MAX_MEM_PREALLOC_THREAD_COUNT); + memset_thread = g_new0(MemsetThread, memset_num_threads); + numpages_per_thread = (numpages / memset_num_threads); + size_per_thread = (hpagesize * numpages_per_thread); + for (i = 0; i < memset_num_threads; i++) { + memset_thread[i].addr = addr; + memset_thread[i].numpages = (i == (memset_num_threads - 1)) ? + numpages : numpages_per_thread; + memset_thread[i].hpagesize = hpagesize; + qemu_thread_create(&memset_thread[i].pgthread, "touch_pages", + do_touch_pages, &memset_thread[i], + QEMU_THREAD_JOINABLE); + addr += size_per_thread; + numpages -= numpages_per_thread; + } + for (i = 0; i < memset_num_threads; i++) { + qemu_thread_join(&memset_thread[i].pgthread); + } + g_free(memset_thread); + memset_thread = NULL; + + return memset_thread_failed; } -void os_mem_prealloc(int fd, char *area, size_t memory, Error **errp) +void os_mem_prealloc(int fd, char *area, size_t memory, int smp_cpus, + Error **errp) { int ret; struct sigaction act, oldact; - sigset_t set, oldset; + size_t hpagesize = qemu_fd_getpagesize(fd); + size_t numpages = DIV_ROUND_UP(memory, hpagesize); memset(&act, 0, sizeof(act)); act.sa_handler = &sigbus_handler; @@ -340,23 +432,10 @@ void os_mem_prealloc(int fd, char *area, size_t memory, Error **errp) return; } - /* unblock SIGBUS */ - sigemptyset(&set); - sigaddset(&set, SIGBUS); - pthread_sigmask(SIG_UNBLOCK, &set, &oldset); - - if (sigsetjmp(sigjump, 1)) { + /* touch pages simultaneously */ + if (touch_all_pages(area, hpagesize, numpages, smp_cpus)) { error_setg(errp, "os_mem_prealloc: Insufficient free host memory " "pages available to allocate guest RAM\n"); - } else { - int i; - size_t hpagesize = qemu_fd_getpagesize(fd); - size_t numpages = DIV_ROUND_UP(memory, hpagesize); - - /* MAP_POPULATE silently ignores failures */ - for (i = 0; i < numpages; i++) { - memset(area + (hpagesize * i), 0, 1); - } } ret = sigaction(SIGBUS, &oldact, NULL); @@ -365,7 +444,6 @@ void os_mem_prealloc(int fd, char *area, size_t memory, Error **errp) perror("os_mem_prealloc: failed to reinstall signal handler"); exit(1); } - pthread_sigmask(SIG_SETMASK, &oldset, NULL); } @@ -631,8 +709,6 @@ void sigaction_invoke(struct sigaction *action, si.si_pid = info->ssi_pid; si.si_status = info->ssi_status; si.si_uid = info->ssi_uid; - } else if (info->ssi_signo == SIGIO) { - si.si_band = info->ssi_band; } action->sa_sigaction(info->ssi_signo, &si, NULL); } diff --git a/util/oslib-win32.c b/util/oslib-win32.c index 0b1890fd33..80e4668935 100644 --- a/util/oslib-win32.c +++ b/util/oslib-win32.c @@ -541,7 +541,8 @@ int getpagesize(void) return system_info.dwPageSize; } -void os_mem_prealloc(int fd, char *area, size_t memory, Error **errp) +void os_mem_prealloc(int fd, char *area, size_t memory, int smp_cpus, + Error **errp) { int i; size_t pagesize = getpagesize(); diff --git a/util/path.c b/util/path.c index 5479f76c6d..7f9fc272fb 100644 --- a/util/path.c +++ b/util/path.c @@ -6,7 +6,6 @@ #include "qemu/osdep.h" #include <sys/param.h> #include <dirent.h> -#include "qemu-common.h" #include "qemu/cutils.h" #include "qemu/path.h" diff --git a/util/qemu-timer.c b/util/qemu-timer.c index 6cf70b96f6..82d56507a2 100644 --- a/util/qemu-timer.c +++ b/util/qemu-timer.c @@ -27,6 +27,7 @@ #include "qemu/timer.h" #include "sysemu/replay.h" #include "sysemu/sysemu.h" +#include "sysemu/cpus.h" #ifdef CONFIG_POSIX #include <pthread.h> @@ -121,7 +122,7 @@ void timerlist_free(QEMUTimerList *timer_list) g_free(timer_list); } -static void qemu_clock_init(QEMUClockType type) +static void qemu_clock_init(QEMUClockType type, QEMUTimerListNotifyCB *notify_cb) { QEMUClock *clock = qemu_clock_ptr(type); @@ -133,7 +134,7 @@ static void qemu_clock_init(QEMUClockType type) clock->last = INT64_MIN; QLIST_INIT(&clock->timerlists); notifier_list_init(&clock->reset_notifiers); - main_loop_tlg.tl[type] = timerlist_new(type, NULL, NULL); + main_loop_tlg.tl[type] = timerlist_new(type, notify_cb, NULL); } bool qemu_clock_use_for_deadline(QEMUClockType type) @@ -199,7 +200,7 @@ bool timerlist_expired(QEMUTimerList *timer_list) expire_time = timer_list->active_timers->expire_time; qemu_mutex_unlock(&timer_list->active_timers_lock); - return expire_time < qemu_clock_get_ns(timer_list->clock->type); + return expire_time <= qemu_clock_get_ns(timer_list->clock->type); } bool qemu_clock_expired(QEMUClockType type) @@ -277,7 +278,7 @@ QEMUTimerList *qemu_clock_get_main_loop_timerlist(QEMUClockType type) void timerlist_notify(QEMUTimerList *timer_list) { if (timer_list->notify_cb) { - timer_list->notify_cb(timer_list->notify_opaque); + timer_list->notify_cb(timer_list->notify_opaque, timer_list->clock->type); } else { qemu_notify_event(); } @@ -634,11 +635,11 @@ void qemu_clock_unregister_reset_notifier(QEMUClockType type, notifier_remove(notifier); } -void init_clocks(void) +void init_clocks(QEMUTimerListNotifyCB *notify_cb) { QEMUClockType type; for (type = 0; type < QEMU_CLOCK_MAX; type++) { - qemu_clock_init(type); + qemu_clock_init(type, notify_cb); } #ifdef CONFIG_PRCTL_PR_SET_TIMERSLACK @@ -657,7 +658,9 @@ bool qemu_clock_run_all_timers(void) QEMUClockType type; for (type = 0; type < QEMU_CLOCK_MAX; type++) { - progress |= qemu_clock_run_timers(type); + if (qemu_clock_use_for_deadline(type)) { + progress |= qemu_clock_run_timers(type); + } } return progress; diff --git a/util/thread-pool.c b/util/thread-pool.c index ce6cd30193..610646d131 100644 --- a/util/thread-pool.c +++ b/util/thread-pool.c @@ -188,6 +188,13 @@ restart: aio_context_release(pool->ctx); elem->common.cb(elem->common.opaque, elem->ret); aio_context_acquire(pool->ctx); + + /* We can safely cancel the completion_bh here regardless of someone + * else having scheduled it meanwhile because we reenter the + * completion function anyway (goto restart). + */ + qemu_bh_cancel(pool->completion_bh); + qemu_aio_unref(elem); goto restart; } else { @@ -1888,17 +1888,14 @@ static bool main_loop_should_exit(void) static void main_loop(void) { - bool nonblocking; - int last_io = 0; #ifdef CONFIG_PROFILER int64_t ti; #endif do { - nonblocking = tcg_enabled() && last_io > 0; #ifdef CONFIG_PROFILER ti = profile_getclock(); #endif - last_io = main_loop_wait(nonblocking); + main_loop_wait(false); #ifdef CONFIG_PROFILER dev_time += profile_getclock() - ti; #endif @@ -4055,8 +4052,6 @@ int main(int argc, char **argv, char **envp) replay_configure(icount_opts); - qemu_tcg_configure(accel_opts, &error_fatal); - machine_class = select_machine(); set_memory_options(&ram_slots, &maxram_size, machine_class); @@ -4423,14 +4418,13 @@ int main(int argc, char **argv, char **envp) if (!tcg_enabled()) { error_report("-icount is not allowed with hardware virtualization"); exit(1); - } else if (qemu_tcg_mttcg_enabled()) { - error_report("-icount does not currently work with MTTCG"); - exit(1); } configure_icount(icount_opts, &error_abort); qemu_opts_del(icount_opts); } + qemu_tcg_configure(accel_opts, &error_fatal); + if (default_net) { QemuOptsList *net = qemu_find_opts("net"); qemu_opts_set(net, NULL, "type", "nic", &error_abort); |