aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore10
-rw-r--r--MAINTAINERS8
-rw-r--r--Makefile69
-rw-r--r--Makefile.target6
-rw-r--r--VERSION2
-rw-r--r--backends/hostmem.c4
-rw-r--r--block.c44
-rw-r--r--block/Makefile.objs2
-rw-r--r--block/archipelago.c1079
-rw-r--r--block/backup.c26
-rw-r--r--block/commit.c28
-rw-r--r--block/curl.c2
-rw-r--r--block/file-posix.c50
-rw-r--r--block/io.c2
-rw-r--r--block/mirror.c15
-rw-r--r--block/replication.c14
-rw-r--r--block/vvfat.c22
-rw-r--r--blockdev.c4
-rwxr-xr-xconfigure73
-rw-r--r--cpu-exec.c1
-rw-r--r--cpus.c42
-rw-r--r--docs/bootindex.txt9
-rw-r--r--docs/qapi-code-gen.txt80
-rw-r--r--docs/qemu-qmp-ref.texi2
-rw-r--r--docs/writing-qmp-commands.txt4
m---------dtc0
-rw-r--r--exec.c9
-rw-r--r--hmp.c4
-rw-r--r--hw/acpi/vmgenid.c1
-rw-r--r--hw/char/virtio-serial-bus.c1
-rw-r--r--hw/core/machine.c39
-rw-r--r--hw/core/ptimer.c1
-rw-r--r--hw/display/cirrus_vga.c106
-rw-r--r--hw/display/cirrus_vga_rop.h191
-rw-r--r--hw/display/cirrus_vga_rop2.h125
-rw-r--r--hw/i386/kvm/clock.c6
-rw-r--r--hw/ide/ahci.c12
-rw-r--r--hw/ide/core.c8
-rw-r--r--hw/ide/qdev.c12
-rw-r--r--hw/intc/arm_gic.c13
-rw-r--r--hw/misc/imx6_src.c8
-rw-r--r--hw/net/e1000e.c2
-rw-r--r--hw/net/mcf_fec.c115
-rw-r--r--hw/pci/pci.c11
-rw-r--r--hw/pci/pcie.c20
-rw-r--r--hw/ppc/pnv.c1
-rw-r--r--hw/ppc/spapr.c9
-rw-r--r--hw/ppc/spapr_pci.c4
-rw-r--r--hw/scsi/mptsas.c6
-rw-r--r--hw/sparc/sun4m.c3
-rw-r--r--hw/sparc64/sparc64.c3
-rw-r--r--hw/virtio/virtio-pci.c37
-rw-r--r--hw/virtio/virtio-pci.h12
-rw-r--r--hw/virtio/virtio.c104
-rw-r--r--include/block/block_int.h4
-rw-r--r--include/exec/cpu-common.h1
-rw-r--r--include/exec/memory.h18
-rw-r--r--include/exec/ram_addr.h5
-rw-r--r--include/hw/compat.h24
-rw-r--r--include/hw/i386/pc.h5
-rw-r--r--include/hw/ide/internal.h1
-rw-r--r--include/hw/pci-host/spapr.h2
-rw-r--r--include/hw/pci/pci.h3
-rw-r--r--include/hw/pci/pcie.h5
-rw-r--r--include/qemu/osdep.h3
-rw-r--r--include/qemu/timer.h29
-rw-r--r--include/sysemu/cpus.h3
-rw-r--r--include/sysemu/os-posix.h4
-rw-r--r--include/ui/console.h7
-rw-r--r--kvm-all.c1
-rw-r--r--memory.c21
-rw-r--r--migration/block.c5
-rw-r--r--migration/migration.c4
-rw-r--r--migration/postcopy-ram.c18
-rw-r--r--migration/ram.c12
-rw-r--r--migration/tls.c2
-rw-r--r--migration/vmstate.c8
-rw-r--r--monitor.c1
-rw-r--r--nbd/client.c2
-rw-r--r--net/colo-compare.c33
-rw-r--r--pc-bios/openbios-ppcbin750840 -> 750840 bytes
-rw-r--r--pc-bios/openbios-sparc32bin382048 -> 382048 bytes
-rw-r--r--pc-bios/openbios-sparc64bin1593408 -> 1593408 bytes
-rw-r--r--qapi-schema.json407
-rw-r--r--qapi/block-core.json455
-rw-r--r--qapi/block.json8
-rw-r--r--qapi/crypto.json22
-rw-r--r--qapi/event.json10
-rw-r--r--qapi/introspect.json6
-rw-r--r--qapi/rocker.json88
-rw-r--r--qapi/trace.json6
-rw-r--r--qemu-options.hx5
-rw-r--r--qga/qapi-schema.json55
-rw-r--r--replay/replay.c1
m---------roms/openbios0
-rw-r--r--rules.mak2
-rw-r--r--scripts/coverity-model.c17
-rw-r--r--scripts/dump-guest-memory.py14
-rw-r--r--scripts/qapi-commands.py6
-rw-r--r--scripts/qapi-event.py2
-rw-r--r--scripts/qapi-introspect.py4
-rw-r--r--scripts/qapi-types.py4
-rw-r--r--scripts/qapi-visit.py5
-rw-r--r--scripts/qapi.py639
-rwxr-xr-xscripts/qapi2texi.py312
-rwxr-xr-xscripts/qmp/qmp-shell4
-rw-r--r--stubs/cpu-get-icount.c6
-rw-r--r--target/alpha/translate.c1
-rw-r--r--target/arm/cpu.h4
-rw-r--r--target/arm/helper.c81
-rw-r--r--target/i386/cpu.c21
-rw-r--r--target/i386/cpu.h6
-rw-r--r--target/i386/kvm.c29
-rw-r--r--target/i386/seg_helper.c20
-rw-r--r--target/i386/svm_helper.c22
-rw-r--r--target/mips/op_helper.c21
-rw-r--r--target/nios2/op_helper.c3
-rw-r--r--target/ppc/cpu.h2
-rw-r--r--target/ppc/translate.c2
-rw-r--r--target/s390x/Makefile.objs2
-rw-r--r--target/s390x/misc_helper.c21
-rw-r--r--target/sparc/int64_helper.c3
-rw-r--r--target/sparc/win_helper.c13
-rw-r--r--target/xtensa/helper.c1
-rw-r--r--target/xtensa/op_helper.c7
-rw-r--r--tests/Makefile.include18
-rwxr-xr-xtests/docker/docker.py6
-rw-r--r--tests/docker/dockerfiles/debian-s390x-cross.docker4
-rw-r--r--tests/qapi-schema/alternate-any.err2
-rw-r--r--tests/qapi-schema/alternate-any.json4
-rw-r--r--tests/qapi-schema/alternate-array.err2
-rw-r--r--tests/qapi-schema/alternate-array.json7
-rw-r--r--tests/qapi-schema/alternate-base.err2
-rw-r--r--tests/qapi-schema/alternate-base.json7
-rw-r--r--tests/qapi-schema/alternate-clash.err2
-rw-r--r--tests/qapi-schema/alternate-clash.json4
-rw-r--r--tests/qapi-schema/alternate-conflict-dict.err2
-rw-r--r--tests/qapi-schema/alternate-conflict-dict.json10
-rw-r--r--tests/qapi-schema/alternate-conflict-string.err2
-rw-r--r--tests/qapi-schema/alternate-conflict-string.json7
-rw-r--r--tests/qapi-schema/alternate-empty.err2
-rw-r--r--tests/qapi-schema/alternate-empty.json4
-rw-r--r--tests/qapi-schema/alternate-nested.err2
-rw-r--r--tests/qapi-schema/alternate-nested.json7
-rw-r--r--tests/qapi-schema/alternate-unknown.err2
-rw-r--r--tests/qapi-schema/alternate-unknown.json4
-rw-r--r--tests/qapi-schema/args-alternate.err2
-rw-r--r--tests/qapi-schema/args-alternate.json8
-rw-r--r--tests/qapi-schema/args-any.err2
-rw-r--r--tests/qapi-schema/args-any.json4
-rw-r--r--tests/qapi-schema/args-array-empty.err2
-rw-r--r--tests/qapi-schema/args-array-empty.json4
-rw-r--r--tests/qapi-schema/args-array-unknown.err2
-rw-r--r--tests/qapi-schema/args-array-unknown.json4
-rw-r--r--tests/qapi-schema/args-bad-boxed.err2
-rw-r--r--tests/qapi-schema/args-bad-boxed.json4
-rw-r--r--tests/qapi-schema/args-boxed-anon.err2
-rw-r--r--tests/qapi-schema/args-boxed-anon.json4
-rw-r--r--tests/qapi-schema/args-boxed-empty.err2
-rw-r--r--tests/qapi-schema/args-boxed-empty.json8
-rw-r--r--tests/qapi-schema/args-boxed-string.err2
-rw-r--r--tests/qapi-schema/args-boxed-string.json4
-rw-r--r--tests/qapi-schema/args-int.err2
-rw-r--r--tests/qapi-schema/args-int.json4
-rw-r--r--tests/qapi-schema/args-invalid.err2
-rw-r--r--tests/qapi-schema/args-invalid.json3
-rw-r--r--tests/qapi-schema/args-member-array-bad.err2
-rw-r--r--tests/qapi-schema/args-member-array-bad.json4
-rw-r--r--tests/qapi-schema/args-member-case.err2
-rw-r--r--tests/qapi-schema/args-member-case.json4
-rw-r--r--tests/qapi-schema/args-member-unknown.err2
-rw-r--r--tests/qapi-schema/args-member-unknown.json4
-rw-r--r--tests/qapi-schema/args-name-clash.err2
-rw-r--r--tests/qapi-schema/args-name-clash.json4
-rw-r--r--tests/qapi-schema/args-union.err2
-rw-r--r--tests/qapi-schema/args-union.json7
-rw-r--r--tests/qapi-schema/args-unknown.err2
-rw-r--r--tests/qapi-schema/args-unknown.json4
-rw-r--r--tests/qapi-schema/bad-base.err2
-rw-r--r--tests/qapi-schema/bad-base.json7
-rw-r--r--tests/qapi-schema/bad-data.err2
-rw-r--r--tests/qapi-schema/bad-data.json4
-rw-r--r--tests/qapi-schema/bad-ident.err2
-rw-r--r--tests/qapi-schema/bad-ident.json4
-rw-r--r--tests/qapi-schema/bad-type-bool.err2
-rw-r--r--tests/qapi-schema/bad-type-bool.json4
-rw-r--r--tests/qapi-schema/bad-type-dict.err2
-rw-r--r--tests/qapi-schema/bad-type-dict.json4
-rw-r--r--tests/qapi-schema/base-cycle-direct.err2
-rw-r--r--tests/qapi-schema/base-cycle-direct.json4
-rw-r--r--tests/qapi-schema/base-cycle-indirect.err2
-rw-r--r--tests/qapi-schema/base-cycle-indirect.json7
-rw-r--r--tests/qapi-schema/command-int.err2
-rw-r--r--tests/qapi-schema/command-int.json4
-rw-r--r--tests/qapi-schema/comments.json4
-rw-r--r--tests/qapi-schema/comments.out1
-rw-r--r--tests/qapi-schema/doc-bad-alternate-member.err1
-rw-r--r--tests/qapi-schema/doc-bad-alternate-member.exit (renamed from tests/qapi-schema/doc-bad-args.exit)0
-rw-r--r--tests/qapi-schema/doc-bad-alternate-member.json9
-rw-r--r--tests/qapi-schema/doc-bad-alternate-member.out (renamed from tests/qapi-schema/doc-bad-args.out)0
-rw-r--r--tests/qapi-schema/doc-bad-args.err1
-rw-r--r--tests/qapi-schema/doc-bad-command-arg.err1
-rw-r--r--tests/qapi-schema/doc-bad-command-arg.exit (renamed from tests/qapi-schema/doc-optional.exit)0
-rw-r--r--tests/qapi-schema/doc-bad-command-arg.json (renamed from tests/qapi-schema/doc-bad-args.json)0
-rw-r--r--tests/qapi-schema/doc-bad-command-arg.out (renamed from tests/qapi-schema/doc-optional.out)0
-rw-r--r--tests/qapi-schema/doc-bad-symbol.err2
-rw-r--r--tests/qapi-schema/doc-bad-union-member.err1
-rw-r--r--tests/qapi-schema/doc-bad-union-member.exit1
-rw-r--r--tests/qapi-schema/doc-bad-union-member.json19
-rw-r--r--tests/qapi-schema/doc-bad-union-member.out0
-rw-r--r--tests/qapi-schema/doc-before-include.err1
-rw-r--r--tests/qapi-schema/doc-before-include.exit1
-rw-r--r--tests/qapi-schema/doc-before-include.json7
-rw-r--r--tests/qapi-schema/doc-before-include.out0
-rw-r--r--tests/qapi-schema/doc-before-pragma.err1
-rw-r--r--tests/qapi-schema/doc-before-pragma.exit1
-rw-r--r--tests/qapi-schema/doc-before-pragma.json7
-rw-r--r--tests/qapi-schema/doc-before-pragma.out0
-rw-r--r--tests/qapi-schema/doc-empty-section.err2
-rw-r--r--tests/qapi-schema/doc-invalid-section.err2
-rw-r--r--tests/qapi-schema/doc-missing-expr.err2
-rw-r--r--tests/qapi-schema/doc-missing.err1
-rw-r--r--tests/qapi-schema/doc-missing.exit1
-rw-r--r--tests/qapi-schema/doc-missing.json5
-rw-r--r--tests/qapi-schema/doc-missing.out0
-rw-r--r--tests/qapi-schema/doc-no-symbol.err1
-rw-r--r--tests/qapi-schema/doc-no-symbol.exit1
-rw-r--r--tests/qapi-schema/doc-no-symbol.json6
-rw-r--r--tests/qapi-schema/doc-no-symbol.out0
-rw-r--r--tests/qapi-schema/doc-optional.err1
-rw-r--r--tests/qapi-schema/doc-optional.json7
-rw-r--r--tests/qapi-schema/double-type.err2
-rw-r--r--tests/qapi-schema/double-type.json4
-rw-r--r--tests/qapi-schema/enum-bad-name.err2
-rw-r--r--tests/qapi-schema/enum-bad-name.json4
-rw-r--r--tests/qapi-schema/enum-bad-prefix.err2
-rw-r--r--tests/qapi-schema/enum-bad-prefix.json4
-rw-r--r--tests/qapi-schema/enum-clash-member.err2
-rw-r--r--tests/qapi-schema/enum-clash-member.json4
-rw-r--r--tests/qapi-schema/enum-dict-member.err2
-rw-r--r--tests/qapi-schema/enum-dict-member.json4
-rw-r--r--tests/qapi-schema/enum-member-case.err2
-rw-r--r--tests/qapi-schema/enum-member-case.json8
-rw-r--r--tests/qapi-schema/enum-missing-data.err2
-rw-r--r--tests/qapi-schema/enum-missing-data.json4
-rw-r--r--tests/qapi-schema/enum-wrong-data.err2
-rw-r--r--tests/qapi-schema/enum-wrong-data.json4
-rw-r--r--tests/qapi-schema/event-boxed-empty.err2
-rw-r--r--tests/qapi-schema/event-boxed-empty.json4
-rw-r--r--tests/qapi-schema/event-case.json4
-rw-r--r--tests/qapi-schema/event-case.out1
-rw-r--r--tests/qapi-schema/event-nest-struct.err2
-rw-r--r--tests/qapi-schema/event-nest-struct.json4
-rw-r--r--tests/qapi-schema/flat-union-array-branch.err2
-rw-r--r--tests/qapi-schema/flat-union-array-branch.json12
-rw-r--r--tests/qapi-schema/flat-union-bad-base.err2
-rw-r--r--tests/qapi-schema/flat-union-bad-base.json13
-rw-r--r--tests/qapi-schema/flat-union-bad-discriminator.err2
-rw-r--r--tests/qapi-schema/flat-union-bad-discriminator.json16
-rw-r--r--tests/qapi-schema/flat-union-base-any.err2
-rw-r--r--tests/qapi-schema/flat-union-base-any.json13
-rw-r--r--tests/qapi-schema/flat-union-base-union.err2
-rw-r--r--tests/qapi-schema/flat-union-base-union.json16
-rw-r--r--tests/qapi-schema/flat-union-clash-member.err2
-rw-r--r--tests/qapi-schema/flat-union-clash-member.json16
-rw-r--r--tests/qapi-schema/flat-union-empty.err2
-rw-r--r--tests/qapi-schema/flat-union-empty.json10
-rw-r--r--tests/qapi-schema/flat-union-incomplete-branch.err2
-rw-r--r--tests/qapi-schema/flat-union-incomplete-branch.json10
-rw-r--r--tests/qapi-schema/flat-union-inline.err2
-rw-r--r--tests/qapi-schema/flat-union-inline.json10
-rw-r--r--tests/qapi-schema/flat-union-int-branch.err2
-rw-r--r--tests/qapi-schema/flat-union-int-branch.json13
-rw-r--r--tests/qapi-schema/flat-union-invalid-branch-key.err2
-rw-r--r--tests/qapi-schema/flat-union-invalid-branch-key.json15
-rw-r--r--tests/qapi-schema/flat-union-invalid-discriminator.err2
-rw-r--r--tests/qapi-schema/flat-union-invalid-discriminator.json15
-rw-r--r--tests/qapi-schema/flat-union-no-base.err2
-rw-r--r--tests/qapi-schema/flat-union-no-base.json13
-rw-r--r--tests/qapi-schema/flat-union-optional-discriminator.err2
-rw-r--r--tests/qapi-schema/flat-union-optional-discriminator.json13
-rw-r--r--tests/qapi-schema/flat-union-string-discriminator.err2
-rw-r--r--tests/qapi-schema/flat-union-string-discriminator.json15
-rw-r--r--tests/qapi-schema/ident-with-escape.json4
-rw-r--r--tests/qapi-schema/ident-with-escape.out1
-rw-r--r--tests/qapi-schema/include-extra-junk.err1
-rw-r--r--tests/qapi-schema/include-extra-junk.exit1
-rw-r--r--tests/qapi-schema/include-extra-junk.json3
-rw-r--r--tests/qapi-schema/include-extra-junk.out0
-rw-r--r--tests/qapi-schema/include-relpath-sub.json3
-rw-r--r--tests/qapi-schema/include-relpath.out1
-rw-r--r--tests/qapi-schema/include-repetition.out1
-rw-r--r--tests/qapi-schema/include-simple-sub.json3
-rw-r--r--tests/qapi-schema/include-simple.out1
-rw-r--r--tests/qapi-schema/indented-expr.json6
-rw-r--r--tests/qapi-schema/indented-expr.out2
-rw-r--r--tests/qapi-schema/missing-type.err2
-rw-r--r--tests/qapi-schema/missing-type.json4
-rw-r--r--tests/qapi-schema/nested-struct-data.err2
-rw-r--r--tests/qapi-schema/nested-struct-data.json4
-rw-r--r--tests/qapi-schema/pragma-doc-required-crap.err1
-rw-r--r--tests/qapi-schema/pragma-doc-required-crap.exit1
-rw-r--r--tests/qapi-schema/pragma-doc-required-crap.json3
-rw-r--r--tests/qapi-schema/pragma-doc-required-crap.out0
-rw-r--r--tests/qapi-schema/pragma-extra-junk.err1
-rw-r--r--tests/qapi-schema/pragma-extra-junk.exit1
-rw-r--r--tests/qapi-schema/pragma-extra-junk.json3
-rw-r--r--tests/qapi-schema/pragma-extra-junk.out0
-rw-r--r--tests/qapi-schema/pragma-name-case-whitelist-crap.err1
-rw-r--r--tests/qapi-schema/pragma-name-case-whitelist-crap.exit1
-rw-r--r--tests/qapi-schema/pragma-name-case-whitelist-crap.json3
-rw-r--r--tests/qapi-schema/pragma-name-case-whitelist-crap.out0
-rw-r--r--tests/qapi-schema/pragma-non-dict.err1
-rw-r--r--tests/qapi-schema/pragma-non-dict.exit1
-rw-r--r--tests/qapi-schema/pragma-non-dict.json3
-rw-r--r--tests/qapi-schema/pragma-non-dict.out0
-rw-r--r--tests/qapi-schema/pragma-returns-whitelist-crap.err1
-rw-r--r--tests/qapi-schema/pragma-returns-whitelist-crap.exit1
-rw-r--r--tests/qapi-schema/pragma-returns-whitelist-crap.json3
-rw-r--r--tests/qapi-schema/pragma-returns-whitelist-crap.out0
-rw-r--r--tests/qapi-schema/qapi-schema-test.json218
-rw-r--r--tests/qapi-schema/qapi-schema-test.out130
-rw-r--r--tests/qapi-schema/redefined-builtin.err2
-rw-r--r--tests/qapi-schema/redefined-builtin.json4
-rw-r--r--tests/qapi-schema/redefined-command.err2
-rw-r--r--tests/qapi-schema/redefined-command.json7
-rw-r--r--tests/qapi-schema/redefined-event.err2
-rw-r--r--tests/qapi-schema/redefined-event.json7
-rw-r--r--tests/qapi-schema/redefined-type.err2
-rw-r--r--tests/qapi-schema/redefined-type.json7
-rw-r--r--tests/qapi-schema/reserved-command-q.err2
-rw-r--r--tests/qapi-schema/reserved-command-q.json7
-rw-r--r--tests/qapi-schema/reserved-enum-q.err2
-rw-r--r--tests/qapi-schema/reserved-enum-q.json4
-rw-r--r--tests/qapi-schema/reserved-member-has.err2
-rw-r--r--tests/qapi-schema/reserved-member-has.json4
-rw-r--r--tests/qapi-schema/reserved-member-q.err2
-rw-r--r--tests/qapi-schema/reserved-member-q.json4
-rw-r--r--tests/qapi-schema/reserved-member-u.err2
-rw-r--r--tests/qapi-schema/reserved-member-u.json4
-rw-r--r--tests/qapi-schema/reserved-member-underscore.err2
-rw-r--r--tests/qapi-schema/reserved-member-underscore.json4
-rw-r--r--tests/qapi-schema/reserved-type-kind.err2
-rw-r--r--tests/qapi-schema/reserved-type-kind.json4
-rw-r--r--tests/qapi-schema/reserved-type-list.err2
-rw-r--r--tests/qapi-schema/reserved-type-list.json4
-rw-r--r--tests/qapi-schema/returns-alternate.err2
-rw-r--r--tests/qapi-schema/returns-alternate.json7
-rw-r--r--tests/qapi-schema/returns-array-bad.err2
-rw-r--r--tests/qapi-schema/returns-array-bad.json4
-rw-r--r--tests/qapi-schema/returns-dict.err2
-rw-r--r--tests/qapi-schema/returns-dict.json4
-rw-r--r--tests/qapi-schema/returns-unknown.err2
-rw-r--r--tests/qapi-schema/returns-unknown.json4
-rw-r--r--tests/qapi-schema/returns-whitelist.err2
-rw-r--r--tests/qapi-schema/returns-whitelist.json18
-rw-r--r--tests/qapi-schema/struct-base-clash-deep.err2
-rw-r--r--tests/qapi-schema/struct-base-clash-deep.json10
-rw-r--r--tests/qapi-schema/struct-base-clash.err2
-rw-r--r--tests/qapi-schema/struct-base-clash.json7
-rw-r--r--tests/qapi-schema/struct-data-invalid.err2
-rw-r--r--tests/qapi-schema/struct-data-invalid.json3
-rw-r--r--tests/qapi-schema/struct-member-invalid.err2
-rw-r--r--tests/qapi-schema/struct-member-invalid.json3
-rw-r--r--tests/qapi-schema/test-qapi.py14
-rw-r--r--tests/qapi-schema/trailing-comma-list.err2
-rw-r--r--tests/qapi-schema/type-bypass-bad-gen.err2
-rw-r--r--tests/qapi-schema/type-bypass-bad-gen.json4
-rw-r--r--tests/qapi-schema/unicode-str.err2
-rw-r--r--tests/qapi-schema/unicode-str.json4
-rw-r--r--tests/qapi-schema/union-base-empty.err1
-rw-r--r--tests/qapi-schema/union-base-empty.exit1
-rw-r--r--tests/qapi-schema/union-base-empty.json9
-rw-r--r--tests/qapi-schema/union-base-empty.out0
-rw-r--r--tests/qapi-schema/union-base-no-discriminator.err2
-rw-r--r--tests/qapi-schema/union-base-no-discriminator.json12
-rw-r--r--tests/qapi-schema/union-branch-case.err2
-rw-r--r--tests/qapi-schema/union-branch-case.json4
-rw-r--r--tests/qapi-schema/union-clash-branches.err2
-rw-r--r--tests/qapi-schema/union-clash-branches.json4
-rw-r--r--tests/qapi-schema/union-empty.err2
-rw-r--r--tests/qapi-schema/union-empty.json4
-rw-r--r--tests/qapi-schema/union-invalid-base.err2
-rw-r--r--tests/qapi-schema/union-invalid-base.json10
-rw-r--r--tests/qapi-schema/union-optional-branch.err2
-rw-r--r--tests/qapi-schema/union-optional-branch.json4
-rw-r--r--tests/qapi-schema/union-unknown.err2
-rw-r--r--tests/qapi-schema/union-unknown.json4
-rw-r--r--tests/qapi-schema/unknown-escape.err2
-rw-r--r--tests/qapi-schema/unknown-escape.json4
-rw-r--r--tests/qapi-schema/unknown-expr-key.err2
-rw-r--r--tests/qapi-schema/unknown-expr-key.json4
-rwxr-xr-xtests/qemu-iotests/0252
-rw-r--r--tests/qemu-iotests/common6
-rw-r--r--tests/qemu-iotests/common.filter4
-rw-r--r--tests/qemu-iotests/common.rc8
-rw-r--r--tests/test-aio-multithread.c2
-rw-r--r--tests/test-aio.c2
-rw-r--r--tests/test-qemu-opts.c3
-rw-r--r--tests/test-qobject-output-visitor.c6
-rw-r--r--trace/Makefile.objs8
-rw-r--r--translate-all.c14
-rw-r--r--ui/cocoa.m2
-rw-r--r--ui/console.c28
-rw-r--r--ui/vnc.c100
-rw-r--r--util/async.c2
-rw-r--r--util/main-loop.c3
-rw-r--r--util/oslib-posix.c122
-rw-r--r--util/oslib-win32.c3
-rw-r--r--util/path.c1
-rw-r--r--util/qemu-timer.c17
-rw-r--r--util/thread-pool.c7
-rw-r--r--vl.c12
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
diff --git a/Makefile b/Makefile
index 1c4c04f6f2..73e0c121c8 100644
--- a/Makefile
+++ b/Makefile
@@ -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)
diff --git a/VERSION b/VERSION
index e65e2ce44f..172912c107 100644
--- a/VERSION
+++ b/VERSION
@@ -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;
}
diff --git a/block.c b/block.c
index b404ef251a..6e906ec53c 100644
--- a/block.c
+++ b/block.c
@@ -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)
diff --git a/configure b/configure
index 6c21975f02..99d8bece70 100755
--- a/configure
+++ b/configure
@@ -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. */
diff --git a/cpus.c b/cpus.c
index c857ad2957..b84a392dda 100644
--- a/cpus.c
+++ b/cpus.c
@@ -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
diff --git a/exec.c b/exec.c
index aabb035e92..e57a8a2178 100644
--- a/exec.c
+++ b/exec.c
@@ -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;
diff --git a/hmp.c b/hmp.c
index 261843f7a2..edb8970461 100644
--- a/hmp.c
+++ b/hmp.c
@@ -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 */
diff --git a/kvm-all.c b/kvm-all.c
index 9040bd50a4..90b8573656 100644
--- a/kvm-all.c
+++ b/kvm-all.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"
diff --git a/memory.c b/memory.c
index 284894b135..64b0a605ef 100644
--- a/memory.c
+++ b/memory.c
@@ -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(&current_migration.src_page_req_mutex);
+ current_migration.parameters.tls_creds = g_strdup("");
+ current_migration.parameters.tls_hostname = g_strdup("");
once = true;
}
return &current_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);
diff --git a/monitor.c b/monitor.c
index f11893e1c3..be282ecb80 100644
--- a/monitor.c
+++ b/monitor.c
@@ -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
index 4869c9dcf3..cfe0aee7e5 100644
--- a/pc-bios/openbios-ppc
+++ b/pc-bios/openbios-ppc
Binary files differ
diff --git a/pc-bios/openbios-sparc32 b/pc-bios/openbios-sparc32
index aada55e094..d6244b9ebd 100644
--- a/pc-bios/openbios-sparc32
+++ b/pc-bios/openbios-sparc32
Binary files differ
diff --git a/pc-bios/openbios-sparc64 b/pc-bios/openbios-sparc64
index cf466f6a4c..74f67f2724 100644
--- a/pc-bios/openbios-sparc64
+++ b/pc-bios/openbios-sparc64
Binary files differ
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
diff --git a/rules.mak b/rules.mak
index 83d6dd1dae..1c0eabb367 100644
--- a/rules.mak
+++ b/rules.mak
@@ -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;
diff --git a/ui/vnc.c b/ui/vnc.c
index 51f4b30959..8bfb1e0685 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -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 {
diff --git a/vl.c b/vl.c
index 7f1644a2be..0b4ed5241c 100644
--- a/vl.c
+++ b/vl.c
@@ -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);