aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore72
-rw-r--r--.mailmap2
-rw-r--r--MAINTAINERS53
-rw-r--r--Makefile194
-rw-r--r--Makefile.objs75
-rw-r--r--Makefile.target3
-rw-r--r--VERSION2
-rw-r--r--accel/accel.c9
-rw-r--r--audio/alsaaudio.c2
-rw-r--r--backends/hostmem-file.c14
-rw-r--r--backends/hostmem.c17
-rw-r--r--block/crypto.c1
-rw-r--r--block/qcow.c2
-rw-r--r--block/qcow2.c4
-rw-r--r--chardev/char.c11
-rwxr-xr-xconfigure47
-rw-r--r--crypto/block-luks.c57
-rw-r--r--crypto/block-qcow.c26
-rw-r--r--crypto/block.c225
-rw-r--r--crypto/blockpriv.h42
-rw-r--r--docs/cpu-hotplug.rst142
-rw-r--r--docs/devel/qapi-code-gen.txt21
-rw-r--r--docs/interop/qmp-spec.txt7
-rw-r--r--fsdev/qemu-fsdev.c3
-rw-r--r--hmp-commands.hx6
-rw-r--r--hmp.c2
-rw-r--r--hw/9pfs/9p-handle.c710
-rw-r--r--hw/9pfs/9p.c4
-rw-r--r--hw/9pfs/Makefile.objs1
-rw-r--r--hw/9pfs/xen-9p-backend.c6
-rw-r--r--hw/arm/boot.c35
-rw-r--r--hw/arm/musicpal.c11
-rw-r--r--hw/arm/virt.c94
-rw-r--r--hw/arm/xlnx-versal-virt.c7
-rw-r--r--hw/block/onenand.c16
-rw-r--r--hw/block/virtio-blk.c10
-rw-r--r--hw/char/grlib_apbuart.c12
-rw-r--r--hw/core/empty_slot.c9
-rw-r--r--hw/core/machine.c11
-rw-r--r--hw/core/qdev-properties-system.c4
-rw-r--r--hw/core/qdev-properties.c30
-rw-r--r--hw/core/sysbus.c15
-rw-r--r--hw/display/g364fb.c9
-rw-r--r--hw/dma/puv3_dma.c10
-rw-r--r--hw/gpio/puv3_gpio.c29
-rw-r--r--hw/i2c/bitbang_i2c.h2
-rw-r--r--hw/i386/pc.c18
-rw-r--r--hw/i386/pc_piix.c20
-rw-r--r--hw/i386/pc_q35.c19
-rw-r--r--hw/input/milkymist-softusb.c16
-rw-r--r--hw/input/pl050.c11
-rw-r--r--hw/intc/arm_gicv3_cpuif.c21
-rw-r--r--hw/intc/puv3_intc.c11
-rw-r--r--hw/mem/memory-device.c9
-rw-r--r--hw/misc/ivshmem.c2
-rw-r--r--hw/misc/milkymist-hpdmc.c9
-rw-r--r--hw/misc/milkymist-pfpu.c12
-rw-r--r--hw/misc/puv3_pm.c10
-rw-r--r--hw/misc/tmp105.c2
-rw-r--r--hw/misc/tmp421.c2
-rw-r--r--hw/nvram/ds1225y.c12
-rw-r--r--hw/pci-bridge/dec.c12
-rw-r--r--hw/ppc/spapr.c102
-rw-r--r--hw/s390x/s390-pci-bus.c2
-rw-r--r--hw/s390x/s390-pci-bus.h1
-rw-r--r--hw/s390x/s390-virtio-ccw.c17
-rw-r--r--hw/s390x/tod-kvm.c102
-rw-r--r--hw/s390x/virtio-ccw.c42
-rw-r--r--hw/timer/etraxfs_timer.c14
-rw-r--r--hw/timer/grlib_gptimer.c11
-rw-r--r--hw/timer/puv3_ost.c13
-rw-r--r--hw/timer/sun4v-rtc.c2
-rw-r--r--hw/tpm/tpm_tis.c12
-rw-r--r--hw/usb/tusb6010.c8
-rw-r--r--hw/vfio/ap.c8
-rw-r--r--hw/virtio/virtio-rng.c2
-rw-r--r--hw/virtio/virtio.c8
-rw-r--r--hw/xen/xen_backend.c7
-rw-r--r--include/chardev/char.h3
-rw-r--r--include/crypto/block.h2
-rw-r--r--include/hw/acpi/acpi_dev_interface.h6
-rw-r--r--include/hw/arm/linux-boot-if.h5
-rw-r--r--include/hw/arm/xlnx-versal.h8
-rw-r--r--include/hw/compat.h3
-rw-r--r--include/hw/fw-path-provider.h4
-rw-r--r--include/hw/hotplug.h6
-rw-r--r--include/hw/i2c/i2c.h2
-rw-r--r--include/hw/i2c/ppc4xx_i2c.h3
-rw-r--r--include/hw/i386/pc.h9
-rw-r--r--include/hw/intc/intc.h4
-rw-r--r--include/hw/ipmi/ipmi.h4
-rw-r--r--include/hw/isa/isa.h4
-rw-r--r--include/hw/mem/memory-device.h4
-rw-r--r--include/hw/nmi.h4
-rw-r--r--include/hw/qdev-core.h2
-rw-r--r--include/hw/qdev-properties.h30
-rw-r--r--include/hw/s390x/tod.h8
-rw-r--r--include/hw/stream.h4
-rw-r--r--include/hw/sysbus.h3
-rw-r--r--include/hw/timer/m48t59.h4
-rw-r--r--include/monitor/monitor.h3
-rw-r--r--include/qapi/string-input-visitor.h4
-rw-r--r--include/qemu/compiler.h8
-rw-r--r--include/qemu/cutils.h8
-rw-r--r--include/qemu/host-utils.h4
-rw-r--r--include/qemu/range.h6
-rw-r--r--include/qemu/typedefs.h3
-rw-r--r--include/qom/object.h8
-rw-r--r--include/qom/object_interfaces.h10
-rw-r--r--include/sysemu/numa.h2
-rw-r--r--include/sysemu/tpm.h4
-rw-r--r--migration/colo.c16
-rw-r--r--monitor.c146
-rw-r--r--net/colo-compare.c6
-rw-r--r--qapi/block-core.json26
-rw-r--r--qapi/char.json150
-rw-r--r--qapi/crypto.json6
-rw-r--r--qapi/migration.json15
-rw-r--r--qapi/misc.json55
-rw-r--r--qapi/net.json3
-rw-r--r--qapi/qobject-input-visitor.c9
-rw-r--r--qapi/string-input-visitor.c413
-rw-r--r--qapi/tpm.json5
-rw-r--r--qapi/ui.json3
-rw-r--r--qemu-deprecated.texi13
-rw-r--r--qemu-options.hx8
-rw-r--r--qobject/json-parser.c5
-rw-r--r--qom/object.c14
-rw-r--r--qom/object_interfaces.c14
-rwxr-xr-xscripts/checkpatch.pl1
-rw-r--r--scripts/cocci-macro-file.h1
-rw-r--r--scripts/qapi/common.py207
-rwxr-xr-xscripts/qapi/doc.py31
-rw-r--r--scripts/qapi/events.py13
-rw-r--r--scripts/qapi/introspect.py17
-rw-r--r--scripts/qapi/types.py10
-rw-r--r--scripts/qapi/visit.py8
-rw-r--r--scripts/tracetool/backend/log.py2
-rw-r--r--target/arm/cpu.c4
-rw-r--r--target/arm/cpu.h141
-rw-r--r--target/arm/cpu64.c11
-rw-r--r--target/arm/helper.c222
-rw-r--r--target/arm/idau.h4
-rw-r--r--target/arm/internals.h3
-rw-r--r--target/arm/kvm64.c4
-rw-r--r--target/arm/op_helper.c14
-rw-r--r--target/arm/translate-a64.c12
-rw-r--r--target/i386/cpu.c8
-rw-r--r--target/i386/cpu.h2
-rw-r--r--target/i386/hax-all.c17
-rw-r--r--target/i386/kvm.c10
-rw-r--r--tcg/tcg.h4
-rw-r--r--tests/Makefile.include11
-rw-r--r--tests/check-qom-interface.c4
-rw-r--r--tests/libqtest.c9
-rw-r--r--tests/libqtest.h4
-rw-r--r--tests/qapi-schema/alternate-base.err1
-rw-r--r--tests/qapi-schema/alternate-invalid-dict.err1
-rw-r--r--tests/qapi-schema/alternate-invalid-dict.exit (renamed from tests/qapi-schema/enum-dict-member.exit)0
-rw-r--r--tests/qapi-schema/alternate-invalid-dict.json4
-rw-r--r--tests/qapi-schema/alternate-invalid-dict.out (renamed from tests/qapi-schema/enum-dict-member.out)0
-rw-r--r--tests/qapi-schema/comments.out14
-rw-r--r--tests/qapi-schema/doc-bad-section.out13
-rw-r--r--tests/qapi-schema/doc-good.json11
-rw-r--r--tests/qapi-schema/doc-good.out22
-rw-r--r--tests/qapi-schema/doc-good.texi7
-rw-r--r--tests/qapi-schema/double-type.err1
-rw-r--r--tests/qapi-schema/empty.out9
-rw-r--r--tests/qapi-schema/enum-bad-member.err1
-rw-r--r--tests/qapi-schema/enum-bad-member.exit1
-rw-r--r--tests/qapi-schema/enum-bad-member.json2
-rw-r--r--tests/qapi-schema/enum-bad-member.out0
-rw-r--r--tests/qapi-schema/enum-dict-member-unknown.err2
-rw-r--r--tests/qapi-schema/enum-dict-member-unknown.exit1
-rw-r--r--tests/qapi-schema/enum-dict-member-unknown.json2
-rw-r--r--tests/qapi-schema/enum-dict-member-unknown.out0
-rw-r--r--tests/qapi-schema/enum-dict-member.err1
-rw-r--r--tests/qapi-schema/enum-dict-member.json2
-rw-r--r--tests/qapi-schema/enum-if-invalid.err1
-rw-r--r--tests/qapi-schema/enum-if-invalid.exit1
-rw-r--r--tests/qapi-schema/enum-if-invalid.json3
-rw-r--r--tests/qapi-schema/enum-if-invalid.out0
-rw-r--r--tests/qapi-schema/event-case.out9
-rw-r--r--tests/qapi-schema/event-member-invalid-dict.err1
-rw-r--r--tests/qapi-schema/event-member-invalid-dict.exit1
-rw-r--r--tests/qapi-schema/event-member-invalid-dict.json2
-rw-r--r--tests/qapi-schema/event-member-invalid-dict.out0
-rw-r--r--tests/qapi-schema/event-nest-struct.json2
-rw-r--r--tests/qapi-schema/flat-union-inline-invalid-dict.err1
-rw-r--r--tests/qapi-schema/flat-union-inline-invalid-dict.exit1
-rw-r--r--tests/qapi-schema/flat-union-inline-invalid-dict.json11
-rw-r--r--tests/qapi-schema/flat-union-inline-invalid-dict.out0
-rw-r--r--tests/qapi-schema/flat-union-inline.json2
-rw-r--r--tests/qapi-schema/flat-union-invalid-if-discriminator.err1
-rw-r--r--tests/qapi-schema/flat-union-invalid-if-discriminator.exit1
-rw-r--r--tests/qapi-schema/flat-union-invalid-if-discriminator.json17
-rw-r--r--tests/qapi-schema/flat-union-invalid-if-discriminator.out0
-rw-r--r--tests/qapi-schema/ident-with-escape.out9
-rw-r--r--tests/qapi-schema/include-relpath.out14
-rw-r--r--tests/qapi-schema/include-repetition.out14
-rw-r--r--tests/qapi-schema/include-simple.out14
-rw-r--r--tests/qapi-schema/indented-expr.out9
-rw-r--r--tests/qapi-schema/nested-struct-data-invalid-dict.err1
-rw-r--r--tests/qapi-schema/nested-struct-data-invalid-dict.exit1
-rw-r--r--tests/qapi-schema/nested-struct-data-invalid-dict.json3
-rw-r--r--tests/qapi-schema/nested-struct-data-invalid-dict.out0
-rw-r--r--tests/qapi-schema/nested-struct-data.json2
-rw-r--r--tests/qapi-schema/qapi-schema-test.json39
-rw-r--r--tests/qapi-schema/qapi-schema-test.out74
-rw-r--r--tests/qapi-schema/struct-member-invalid-dict.err1
-rw-r--r--tests/qapi-schema/struct-member-invalid-dict.exit1
-rw-r--r--tests/qapi-schema/struct-member-invalid-dict.json3
-rw-r--r--tests/qapi-schema/struct-member-invalid-dict.out0
-rw-r--r--tests/qapi-schema/test-qapi.py9
-rw-r--r--tests/qapi-schema/union-branch-invalid-dict.err1
-rw-r--r--tests/qapi-schema/union-branch-invalid-dict.exit1
-rw-r--r--tests/qapi-schema/union-branch-invalid-dict.json4
-rw-r--r--tests/qapi-schema/union-branch-invalid-dict.out0
-rw-r--r--tests/qapi-schema/unknown-expr-key.err3
-rw-r--r--tests/qapi-schema/unknown-expr-key.json2
-rwxr-xr-xtests/qemu-iotests/2291
-rw-r--r--tests/qmp-test.c6
-rw-r--r--tests/tcg/i386/test-i386.c2
-rw-r--r--tests/test-crypto-block.c3
-rw-r--r--tests/test-cutils.c24
-rw-r--r--tests/test-qdev-global-props.c30
-rw-r--r--tests/test-qmp-cmds.c16
-rw-r--r--tests/test-string-input-visitor.c223
-rw-r--r--trace/simple.c4
-rw-r--r--util/cutils.c91
-rw-r--r--util/vfio-helpers.c2
-rw-r--r--vl.c5
232 files changed, 2666 insertions, 2559 deletions
diff --git a/.gitignore b/.gitignore
index 64efdfd929..0430257313 100644
--- a/.gitignore
+++ b/.gitignore
@@ -30,78 +30,14 @@
/qapi-gen-timestamp
/qapi/qapi-builtin-types.[ch]
/qapi/qapi-builtin-visit.[ch]
-/qapi/qapi-commands-block-core.[ch]
-/qapi/qapi-commands-block.[ch]
-/qapi/qapi-commands-char.[ch]
-/qapi/qapi-commands-common.[ch]
-/qapi/qapi-commands-crypto.[ch]
-/qapi/qapi-commands-introspect.[ch]
-/qapi/qapi-commands-job.[ch]
-/qapi/qapi-commands-migration.[ch]
-/qapi/qapi-commands-misc.[ch]
-/qapi/qapi-commands-net.[ch]
-/qapi/qapi-commands-rocker.[ch]
-/qapi/qapi-commands-run-state.[ch]
-/qapi/qapi-commands-sockets.[ch]
-/qapi/qapi-commands-tpm.[ch]
-/qapi/qapi-commands-trace.[ch]
-/qapi/qapi-commands-transaction.[ch]
-/qapi/qapi-commands-ui.[ch]
+/qapi/qapi-commands-*.[ch]
/qapi/qapi-commands.[ch]
-/qapi/qapi-events-block-core.[ch]
-/qapi/qapi-events-block.[ch]
-/qapi/qapi-events-char.[ch]
-/qapi/qapi-events-common.[ch]
-/qapi/qapi-events-crypto.[ch]
-/qapi/qapi-events-introspect.[ch]
-/qapi/qapi-events-job.[ch]
-/qapi/qapi-events-migration.[ch]
-/qapi/qapi-events-misc.[ch]
-/qapi/qapi-events-net.[ch]
-/qapi/qapi-events-rocker.[ch]
-/qapi/qapi-events-run-state.[ch]
-/qapi/qapi-events-sockets.[ch]
-/qapi/qapi-events-tpm.[ch]
-/qapi/qapi-events-trace.[ch]
-/qapi/qapi-events-transaction.[ch]
-/qapi/qapi-events-ui.[ch]
+/qapi/qapi-events-*.[ch]
/qapi/qapi-events.[ch]
/qapi/qapi-introspect.[ch]
-/qapi/qapi-types-block-core.[ch]
-/qapi/qapi-types-block.[ch]
-/qapi/qapi-types-char.[ch]
-/qapi/qapi-types-common.[ch]
-/qapi/qapi-types-crypto.[ch]
-/qapi/qapi-types-introspect.[ch]
-/qapi/qapi-types-job.[ch]
-/qapi/qapi-types-migration.[ch]
-/qapi/qapi-types-misc.[ch]
-/qapi/qapi-types-net.[ch]
-/qapi/qapi-types-rocker.[ch]
-/qapi/qapi-types-run-state.[ch]
-/qapi/qapi-types-sockets.[ch]
-/qapi/qapi-types-tpm.[ch]
-/qapi/qapi-types-trace.[ch]
-/qapi/qapi-types-transaction.[ch]
-/qapi/qapi-types-ui.[ch]
+/qapi/qapi-types-*.[ch]
/qapi/qapi-types.[ch]
-/qapi/qapi-visit-block-core.[ch]
-/qapi/qapi-visit-block.[ch]
-/qapi/qapi-visit-char.[ch]
-/qapi/qapi-visit-common.[ch]
-/qapi/qapi-visit-crypto.[ch]
-/qapi/qapi-visit-introspect.[ch]
-/qapi/qapi-visit-job.[ch]
-/qapi/qapi-visit-migration.[ch]
-/qapi/qapi-visit-misc.[ch]
-/qapi/qapi-visit-net.[ch]
-/qapi/qapi-visit-rocker.[ch]
-/qapi/qapi-visit-run-state.[ch]
-/qapi/qapi-visit-sockets.[ch]
-/qapi/qapi-visit-tpm.[ch]
-/qapi/qapi-visit-trace.[ch]
-/qapi/qapi-visit-transaction.[ch]
-/qapi/qapi-visit-ui.[ch]
+/qapi/qapi-visit-*.[ch]
/qapi/qapi-visit.[ch]
/qapi/qapi-doc.texi
/qemu-doc.html
diff --git a/.mailmap b/.mailmap
index ed8faa5719..b8e08297c9 100644
--- a/.mailmap
+++ b/.mailmap
@@ -34,6 +34,6 @@ Justin Terry (VM) <juterry@microsoft.com> Justin Terry (VM) via Qemu-devel <qemu
# Also list preferred name forms where people have changed their
-# git author config, or having utf8/latin1 encoding issues.
+# git author config, or had utf8/latin1 encoding issues.
Daniel P. Berrangé <berrange@redhat.com>
Reimar Döffinger <Reimar.Doeffinger@gmx.de>
diff --git a/MAINTAINERS b/MAINTAINERS
index 63effdc473..83c127f0d6 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -233,7 +233,9 @@ M: Marek Vasut <marex@denx.de>
S: Maintained
F: target/nios2/
F: hw/nios2/
+F: hw/intc/nios2_iic.c
F: disas/nios2.c
+F: default-configs/nios2-softmmu.mak
OpenRISC
M: Stafford Horne <shorne@gmail.com>
@@ -289,6 +291,7 @@ S: Maintained
F: target/sparc/
F: hw/sparc/
F: hw/sparc64/
+F: include/hw/sparc/sparc64.h
F: disas/sparc.c
UniCore32
@@ -365,8 +368,9 @@ S: Maintained
F: target/ppc/kvm.c
S390
-M: Christian Borntraeger <borntraeger@de.ibm.com>
+M: Halil Pasic <pasic@linux.ibm.com>
M: Cornelia Huck <cohuck@redhat.com>
+M: Christian Borntraeger <borntraeger@de.ibm.com>
S: Maintained
F: target/s390x/kvm.c
F: target/s390x/kvm_s390x.h
@@ -538,6 +542,7 @@ L: qemu-arm@nongnu.org
S: Odd Fixes
F: include/hw/arm/digic.h
F: hw/*/digic*
+F: include/hw/*/digic*
Gumstix
M: Peter Maydell <peter.maydell@linaro.org>
@@ -608,6 +613,8 @@ F: hw/misc/mps2-*.c
F: include/hw/misc/mps2-*.h
F: hw/arm/iotkit.c
F: include/hw/arm/iotkit.h
+F: hw/misc/iotkit-secctl.c
+F: include/hw/misc/iotkit-secctl.h
F: hw/misc/iotkit-sysctl.c
F: include/hw/misc/iotkit-sysctl.h
F: hw/misc/iotkit-sysinfo.c
@@ -738,6 +745,9 @@ L: qemu-arm@nongnu.org
S: Maintained
F: hw/*/xlnx*.c
F: include/hw/*/xlnx*.h
+F: include/hw/ssi/xilinx_spips.h
+F: hw/display/dpcd.c
+F: include/hw/display/dpcd.h
ARM ACPI Subsystem
M: Shannon Zhao <shannon.zhaosl@gmail.com>
@@ -846,6 +856,7 @@ petalogix_s3adsp1800
M: Edgar E. Iglesias <edgar.iglesias@gmail.com>
S: Maintained
F: hw/microblaze/petalogix_s3adsp1800_mmu.c
+F: include/hw/char/xilinx_uartlite.h
petalogix_ml605
M: Edgar E. Iglesias <edgar.iglesias@gmail.com>
@@ -859,6 +870,8 @@ M: Hervé Poussineau <hpoussin@reactos.org>
R: Stefan Markovic <smarkovic@wavecomp.com>
S: Maintained
F: hw/mips/mips_jazz.c
+F: hw/display/jazz_led.c
+F: hw/dma/rc4030.c
Malta
M: Aurelien Jarno <aurelien@aurel32.net>
@@ -885,7 +898,7 @@ R: Stefan Markovic <smarkovic@wavecomp.com>
S: Odd Fixes
F: hw/mips/mips_fulong2e.c
F: hw/isa/vt82c686.c
-
+F: hw/pci-host/bonito.c
F: include/hw/isa/vt82c686.h
Boston
@@ -895,6 +908,7 @@ S: Maintained
F: hw/core/loader-fit.c
F: hw/mips/boston.c
F: hw/pci-host/xilinx-pcie.c
+F: include/hw/pci-host/xilinx-pcie.h
OpenRISC Machines
-----------------
@@ -947,6 +961,7 @@ F: hw/nvram/mac_nvram.c
F: include/hw/misc/macio/
F: include/hw/misc/mos6522.h
F: include/hw/ppc/mac_dbdma.h
+F: include/hw/pci-host/uninorth.h
Old World
M: David Gibson <david@gibson.dropbear.id.au>
@@ -956,6 +971,7 @@ F: hw/ppc/mac_oldworld.c
F: hw/pci-host/grackle.c
F: hw/misc/macio/
F: hw/intc/heathrow_pic.c
+F: include/hw/intc/heathrow_pic.h
PReP
M: Hervé Poussineau <hpoussin@reactos.org>
@@ -1032,12 +1048,15 @@ F: hw/misc/eccmemctl.c
F: hw/misc/slavio_misc.c
F: include/hw/sparc/sparc32_dma.h
F: pc-bios/openbios-sparc32
+F: include/hw/sparc/sun4m_iommu.h
Sun4u
M: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
S: Maintained
F: hw/sparc64/sun4u.c
F: pc-bios/openbios-sparc64
+F: hw/pci-host/sabre.c
+F: include/hw/pci-host/sabre.h
Sun4v
M: Artyom Tarasenko <atar4qemu@gmail.com>
@@ -1057,6 +1076,7 @@ S390 Machines
-------------
S390 Virtio-ccw
M: Cornelia Huck <cohuck@redhat.com>
+M: Halil Pasic <pasic@linux.ibm.com>
M: Christian Borntraeger <borntraeger@de.ibm.com>
S: Supported
F: hw/char/sclp*.[hc]
@@ -1136,11 +1156,13 @@ F: hw/timer/hpet*
F: hw/timer/i8254*
F: hw/timer/mc146818rtc*
F: hw/watchdog/wdt_ib700.c
+F: hw/watchdog/wdt_i6300esb.c
F: include/hw/display/vga.h
F: include/hw/char/parallel.h
F: include/hw/dma/i8257.h
F: include/hw/i2c/pm_smbus.h
F: include/hw/input/i8042.h
+F: include/hw/isa/i8259_internal.h
F: include/hw/isa/superio.h
F: include/hw/timer/hpet.h
F: include/hw/timer/i8254*
@@ -1246,8 +1268,7 @@ F: hw/i386/acpi-build.[hc]
F: hw/arm/virt-acpi-build.c
F: tests/bios-tables-test.c
F: tests/acpi-utils.[hc]
-F: tests/acpi-test-data/*
-F: tests/acpi-test-data/*/*
+F: tests/data/acpi/
ppc4xx
M: David Gibson <david@gibson.dropbear.id.au>
@@ -1282,7 +1303,7 @@ T: git https://github.com/jasowang/qemu.git net
SCSI
M: Paolo Bonzini <pbonzini@redhat.com>
-R: Fam Zheng <famz@redhat.com>
+R: Fam Zheng <fam@euphon.net>
S: Supported
F: include/hw/scsi/*
F: hw/scsi/*
@@ -1366,6 +1387,7 @@ M: Michael S. Tsirkin <mst@redhat.com>
S: Supported
F: hw/*/*vhost*
F: docs/interop/vhost-user.txt
+F: contrib/vhost-user-*/
virtio
M: Michael S. Tsirkin <mst@redhat.com>
@@ -1478,6 +1500,7 @@ S: Maintained
F: hw/acpi/nvdimm.c
F: hw/mem/nvdimm.c
F: include/hw/mem/nvdimm.h
+F: docs/nvdimm.txt
e1000x
M: Dmitry Fleytman <dmitry.fleytman@gmail.com>
@@ -1608,7 +1631,7 @@ T: git https://repo.or.cz/qemu/kevin.git block
Block I/O path
M: Stefan Hajnoczi <stefanha@redhat.com>
-M: Fam Zheng <famz@redhat.com>
+M: Fam Zheng <fam@euphon.net>
L: qemu-block@nongnu.org
S: Supported
F: util/async.c
@@ -1622,7 +1645,7 @@ T: git https://github.com/stefanha/qemu.git block
Block SCSI subsystem
M: Paolo Bonzini <pbonzini@redhat.com>
-R: Fam Zheng <famz@redhat.com>
+R: Fam Zheng <fam@euphon.net>
L: qemu-block@nongnu.org
S: Supported
F: include/scsi/*
@@ -1654,7 +1677,7 @@ F: qapi/transaction.json
T: git https://repo.or.cz/qemu/armbru.git block-next
Dirty Bitmaps
-M: Fam Zheng <famz@redhat.com>
+M: Fam Zheng <fam@euphon.net>
M: John Snow <jsnow@redhat.com>
L: qemu-block@nongnu.org
S: Supported
@@ -1752,6 +1775,7 @@ F: ui/spice-*.c
F: audio/spiceaudio.c
F: hw/display/qxl*
F: qapi/ui.json
+F: docs/spice-port-fqdn.txt
Graphics
M: Gerd Hoffmann <kraxel@redhat.com>
@@ -1896,6 +1920,7 @@ S: Supported
F: qmp.c
F: monitor.c
F: docs/devel/*qmp-*
+F: docs/interop/*qmp-*
F: scripts/qmp/
F: tests/qmp-test.c
F: tests/qmp-cmd-test.c
@@ -2028,7 +2053,7 @@ F: tests/test-throttle.c
L: qemu-block@nongnu.org
UUID
-M: Fam Zheng <famz@redhat.com>
+M: Fam Zheng <fam@euphon.net>
S: Supported
F: util/uuid.c
F: include/qemu/uuid.h
@@ -2159,7 +2184,7 @@ F: disas/tci.c
Block drivers
-------------
VMDK
-M: Fam Zheng <famz@redhat.com>
+M: Fam Zheng <fam@euphon.net>
L: qemu-block@nongnu.org
S: Supported
F: block/vmdk.c
@@ -2245,13 +2270,13 @@ F: block/gluster.c
T: git https://github.com/codyprime/qemu-kvm-jtc.git block
Null Block Driver
-M: Fam Zheng <famz@redhat.com>
+M: Fam Zheng <fam@euphon.net>
L: qemu-block@nongnu.org
S: Supported
F: block/null.c
NVMe Block Driver
-M: Fam Zheng <famz@redhat.com>
+M: Fam Zheng <fam@euphon.net>
L: qemu-block@nongnu.org
S: Supported
F: block/nvme*
@@ -2382,8 +2407,8 @@ Build and test automation
-------------------------
Build and test automation
M: Alex Bennée <alex.bennee@linaro.org>
-M: Fam Zheng <famz@redhat.com>
-R: Philippe Mathieu-Daudé <f4bug@amsat.org>
+M: Fam Zheng <fam@euphon.net>
+R: Philippe Mathieu-Daudé <philmd@redhat.com>
L: qemu-devel@nongnu.org
S: Maintained
F: .travis.yml
diff --git a/Makefile b/Makefile
index f2947186a4..c8b9efdad4 100644
--- a/Makefile
+++ b/Makefile
@@ -88,82 +88,26 @@ endif
include $(SRC_PATH)/rules.mak
GENERATED_FILES = qemu-version.h config-host.h qemu-options.def
-GENERATED_FILES += qapi/qapi-builtin-types.h qapi/qapi-builtin-types.c
-GENERATED_FILES += qapi/qapi-types.h qapi/qapi-types.c
-GENERATED_FILES += qapi/qapi-types-block-core.h qapi/qapi-types-block-core.c
-GENERATED_FILES += qapi/qapi-types-block.h qapi/qapi-types-block.c
-GENERATED_FILES += qapi/qapi-types-char.h qapi/qapi-types-char.c
-GENERATED_FILES += qapi/qapi-types-common.h qapi/qapi-types-common.c
-GENERATED_FILES += qapi/qapi-types-crypto.h qapi/qapi-types-crypto.c
-GENERATED_FILES += qapi/qapi-types-introspect.h qapi/qapi-types-introspect.c
-GENERATED_FILES += qapi/qapi-types-job.h qapi/qapi-types-job.c
-GENERATED_FILES += qapi/qapi-types-migration.h qapi/qapi-types-migration.c
-GENERATED_FILES += qapi/qapi-types-misc.h qapi/qapi-types-misc.c
-GENERATED_FILES += qapi/qapi-types-net.h qapi/qapi-types-net.c
-GENERATED_FILES += qapi/qapi-types-rocker.h qapi/qapi-types-rocker.c
-GENERATED_FILES += qapi/qapi-types-run-state.h qapi/qapi-types-run-state.c
-GENERATED_FILES += qapi/qapi-types-sockets.h qapi/qapi-types-sockets.c
-GENERATED_FILES += qapi/qapi-types-tpm.h qapi/qapi-types-tpm.c
-GENERATED_FILES += qapi/qapi-types-trace.h qapi/qapi-types-trace.c
-GENERATED_FILES += qapi/qapi-types-transaction.h qapi/qapi-types-transaction.c
-GENERATED_FILES += qapi/qapi-types-ui.h qapi/qapi-types-ui.c
-GENERATED_FILES += qapi/qapi-builtin-visit.h qapi/qapi-builtin-visit.c
-GENERATED_FILES += qapi/qapi-visit.h qapi/qapi-visit.c
-GENERATED_FILES += qapi/qapi-visit-block-core.h qapi/qapi-visit-block-core.c
-GENERATED_FILES += qapi/qapi-visit-block.h qapi/qapi-visit-block.c
-GENERATED_FILES += qapi/qapi-visit-char.h qapi/qapi-visit-char.c
-GENERATED_FILES += qapi/qapi-visit-common.h qapi/qapi-visit-common.c
-GENERATED_FILES += qapi/qapi-visit-crypto.h qapi/qapi-visit-crypto.c
-GENERATED_FILES += qapi/qapi-visit-introspect.h qapi/qapi-visit-introspect.c
-GENERATED_FILES += qapi/qapi-visit-job.h qapi/qapi-visit-job.c
-GENERATED_FILES += qapi/qapi-visit-migration.h qapi/qapi-visit-migration.c
-GENERATED_FILES += qapi/qapi-visit-misc.h qapi/qapi-visit-misc.c
-GENERATED_FILES += qapi/qapi-visit-net.h qapi/qapi-visit-net.c
-GENERATED_FILES += qapi/qapi-visit-rocker.h qapi/qapi-visit-rocker.c
-GENERATED_FILES += qapi/qapi-visit-run-state.h qapi/qapi-visit-run-state.c
-GENERATED_FILES += qapi/qapi-visit-sockets.h qapi/qapi-visit-sockets.c
-GENERATED_FILES += qapi/qapi-visit-tpm.h qapi/qapi-visit-tpm.c
-GENERATED_FILES += qapi/qapi-visit-trace.h qapi/qapi-visit-trace.c
-GENERATED_FILES += qapi/qapi-visit-transaction.h qapi/qapi-visit-transaction.c
-GENERATED_FILES += qapi/qapi-visit-ui.h qapi/qapi-visit-ui.c
-GENERATED_FILES += qapi/qapi-commands.h qapi/qapi-commands.c
-GENERATED_FILES += qapi/qapi-commands-block-core.h qapi/qapi-commands-block-core.c
-GENERATED_FILES += qapi/qapi-commands-block.h qapi/qapi-commands-block.c
-GENERATED_FILES += qapi/qapi-commands-char.h qapi/qapi-commands-char.c
-GENERATED_FILES += qapi/qapi-commands-common.h qapi/qapi-commands-common.c
-GENERATED_FILES += qapi/qapi-commands-crypto.h qapi/qapi-commands-crypto.c
-GENERATED_FILES += qapi/qapi-commands-introspect.h qapi/qapi-commands-introspect.c
-GENERATED_FILES += qapi/qapi-commands-job.h qapi/qapi-commands-job.c
-GENERATED_FILES += qapi/qapi-commands-migration.h qapi/qapi-commands-migration.c
-GENERATED_FILES += qapi/qapi-commands-misc.h qapi/qapi-commands-misc.c
-GENERATED_FILES += qapi/qapi-commands-net.h qapi/qapi-commands-net.c
-GENERATED_FILES += qapi/qapi-commands-rocker.h qapi/qapi-commands-rocker.c
-GENERATED_FILES += qapi/qapi-commands-run-state.h qapi/qapi-commands-run-state.c
-GENERATED_FILES += qapi/qapi-commands-sockets.h qapi/qapi-commands-sockets.c
-GENERATED_FILES += qapi/qapi-commands-tpm.h qapi/qapi-commands-tpm.c
-GENERATED_FILES += qapi/qapi-commands-trace.h qapi/qapi-commands-trace.c
-GENERATED_FILES += qapi/qapi-commands-transaction.h qapi/qapi-commands-transaction.c
-GENERATED_FILES += qapi/qapi-commands-ui.h qapi/qapi-commands-ui.c
-GENERATED_FILES += qapi/qapi-events.h qapi/qapi-events.c
-GENERATED_FILES += qapi/qapi-events-block-core.h qapi/qapi-events-block-core.c
-GENERATED_FILES += qapi/qapi-events-block.h qapi/qapi-events-block.c
-GENERATED_FILES += qapi/qapi-events-char.h qapi/qapi-events-char.c
-GENERATED_FILES += qapi/qapi-events-common.h qapi/qapi-events-common.c
-GENERATED_FILES += qapi/qapi-events-crypto.h qapi/qapi-events-crypto.c
-GENERATED_FILES += qapi/qapi-events-introspect.h qapi/qapi-events-introspect.c
-GENERATED_FILES += qapi/qapi-events-job.h qapi/qapi-events-job.c
-GENERATED_FILES += qapi/qapi-events-migration.h qapi/qapi-events-migration.c
-GENERATED_FILES += qapi/qapi-events-misc.h qapi/qapi-events-misc.c
-GENERATED_FILES += qapi/qapi-events-net.h qapi/qapi-events-net.c
-GENERATED_FILES += qapi/qapi-events-rocker.h qapi/qapi-events-rocker.c
-GENERATED_FILES += qapi/qapi-events-run-state.h qapi/qapi-events-run-state.c
-GENERATED_FILES += qapi/qapi-events-sockets.h qapi/qapi-events-sockets.c
-GENERATED_FILES += qapi/qapi-events-tpm.h qapi/qapi-events-tpm.c
-GENERATED_FILES += qapi/qapi-events-trace.h qapi/qapi-events-trace.c
-GENERATED_FILES += qapi/qapi-events-transaction.h qapi/qapi-events-transaction.c
-GENERATED_FILES += qapi/qapi-events-ui.h qapi/qapi-events-ui.c
-GENERATED_FILES += qapi/qapi-introspect.c qapi/qapi-introspect.h
-GENERATED_FILES += qapi/qapi-doc.texi
+
+#see Makefile.objs for the definition of QAPI_MODULES
+GENERATED_QAPI_FILES = qapi/qapi-builtin-types.h qapi/qapi-builtin-types.c
+GENERATED_QAPI_FILES += qapi/qapi-types.h qapi/qapi-types.c
+GENERATED_QAPI_FILES += $(QAPI_MODULES:%=qapi/qapi-types-%.h)
+GENERATED_QAPI_FILES += $(QAPI_MODULES:%=qapi/qapi-types-%.c)
+GENERATED_QAPI_FILES += qapi/qapi-builtin-visit.h qapi/qapi-builtin-visit.c
+GENERATED_QAPI_FILES += qapi/qapi-visit.h qapi/qapi-visit.c
+GENERATED_QAPI_FILES += $(QAPI_MODULES:%=qapi/qapi-visit-%.h)
+GENERATED_QAPI_FILES += $(QAPI_MODULES:%=qapi/qapi-visit-%.c)
+GENERATED_QAPI_FILES += qapi/qapi-commands.h qapi/qapi-commands.c
+GENERATED_QAPI_FILES += $(QAPI_MODULES:%=qapi/qapi-commands-%.h)
+GENERATED_QAPI_FILES += $(QAPI_MODULES:%=qapi/qapi-commands-%.c)
+GENERATED_QAPI_FILES += qapi/qapi-events.h qapi/qapi-events.c
+GENERATED_QAPI_FILES += $(QAPI_MODULES:%=qapi/qapi-events-%.h)
+GENERATED_QAPI_FILES += $(QAPI_MODULES:%=qapi/qapi-events-%.c)
+GENERATED_QAPI_FILES += qapi/qapi-introspect.c qapi/qapi-introspect.h
+GENERATED_QAPI_FILES += qapi/qapi-doc.texi
+
+GENERATED_FILES += $(GENERATED_QAPI_FILES)
GENERATED_FILES += trace/generated-tcg-tracers.h
@@ -583,100 +527,10 @@ qga/qapi-generated/qapi-gen-timestamp: $(SRC_PATH)/qga/qapi-schema.json $(qapi-p
"GEN","$(@:%-timestamp=%)")
@>$@
-qapi-modules = $(SRC_PATH)/qapi/qapi-schema.json $(SRC_PATH)/qapi/common.json \
- $(SRC_PATH)/qapi/block.json $(SRC_PATH)/qapi/block-core.json \
- $(SRC_PATH)/qapi/char.json \
- $(SRC_PATH)/qapi/crypto.json \
- $(SRC_PATH)/qapi/introspect.json \
- $(SRC_PATH)/qapi/job.json \
- $(SRC_PATH)/qapi/migration.json \
- $(SRC_PATH)/qapi/misc.json \
- $(SRC_PATH)/qapi/net.json \
- $(SRC_PATH)/qapi/rocker.json \
- $(SRC_PATH)/qapi/run-state.json \
- $(SRC_PATH)/qapi/sockets.json \
- $(SRC_PATH)/qapi/tpm.json \
- $(SRC_PATH)/qapi/trace.json \
- $(SRC_PATH)/qapi/transaction.json \
- $(SRC_PATH)/qapi/ui.json
-
-qapi/qapi-builtin-types.c qapi/qapi-builtin-types.h \
-qapi/qapi-types.c qapi/qapi-types.h \
-qapi/qapi-types-block-core.c qapi/qapi-types-block-core.h \
-qapi/qapi-types-block.c qapi/qapi-types-block.h \
-qapi/qapi-types-char.c qapi/qapi-types-char.h \
-qapi/qapi-types-common.c qapi/qapi-types-common.h \
-qapi/qapi-types-crypto.c qapi/qapi-types-crypto.h \
-qapi/qapi-types-introspect.c qapi/qapi-types-introspect.h \
-qapi/qapi-types-job.c qapi/qapi-types-job.h \
-qapi/qapi-types-migration.c qapi/qapi-types-migration.h \
-qapi/qapi-types-misc.c qapi/qapi-types-misc.h \
-qapi/qapi-types-net.c qapi/qapi-types-net.h \
-qapi/qapi-types-rocker.c qapi/qapi-types-rocker.h \
-qapi/qapi-types-run-state.c qapi/qapi-types-run-state.h \
-qapi/qapi-types-sockets.c qapi/qapi-types-sockets.h \
-qapi/qapi-types-tpm.c qapi/qapi-types-tpm.h \
-qapi/qapi-types-trace.c qapi/qapi-types-trace.h \
-qapi/qapi-types-transaction.c qapi/qapi-types-transaction.h \
-qapi/qapi-types-ui.c qapi/qapi-types-ui.h \
-qapi/qapi-builtin-visit.c qapi/qapi-builtin-visit.h \
-qapi/qapi-visit.c qapi/qapi-visit.h \
-qapi/qapi-visit-block-core.c qapi/qapi-visit-block-core.h \
-qapi/qapi-visit-block.c qapi/qapi-visit-block.h \
-qapi/qapi-visit-char.c qapi/qapi-visit-char.h \
-qapi/qapi-visit-common.c qapi/qapi-visit-common.h \
-qapi/qapi-visit-crypto.c qapi/qapi-visit-crypto.h \
-qapi/qapi-visit-introspect.c qapi/qapi-visit-introspect.h \
-qapi/qapi-visit-job.c qapi/qapi-visit-job.h \
-qapi/qapi-visit-migration.c qapi/qapi-visit-migration.h \
-qapi/qapi-visit-misc.c qapi/qapi-visit-misc.h \
-qapi/qapi-visit-net.c qapi/qapi-visit-net.h \
-qapi/qapi-visit-rocker.c qapi/qapi-visit-rocker.h \
-qapi/qapi-visit-run-state.c qapi/qapi-visit-run-state.h \
-qapi/qapi-visit-sockets.c qapi/qapi-visit-sockets.h \
-qapi/qapi-visit-tpm.c qapi/qapi-visit-tpm.h \
-qapi/qapi-visit-trace.c qapi/qapi-visit-trace.h \
-qapi/qapi-visit-transaction.c qapi/qapi-visit-transaction.h \
-qapi/qapi-visit-ui.c qapi/qapi-visit-ui.h \
-qapi/qapi-commands.h qapi/qapi-commands.c \
-qapi/qapi-commands-block-core.c qapi/qapi-commands-block-core.h \
-qapi/qapi-commands-block.c qapi/qapi-commands-block.h \
-qapi/qapi-commands-char.c qapi/qapi-commands-char.h \
-qapi/qapi-commands-common.c qapi/qapi-commands-common.h \
-qapi/qapi-commands-crypto.c qapi/qapi-commands-crypto.h \
-qapi/qapi-commands-introspect.c qapi/qapi-commands-introspect.h \
-qapi/qapi-commands-job.c qapi/qapi-commands-job.h \
-qapi/qapi-commands-migration.c qapi/qapi-commands-migration.h \
-qapi/qapi-commands-misc.c qapi/qapi-commands-misc.h \
-qapi/qapi-commands-net.c qapi/qapi-commands-net.h \
-qapi/qapi-commands-rocker.c qapi/qapi-commands-rocker.h \
-qapi/qapi-commands-run-state.c qapi/qapi-commands-run-state.h \
-qapi/qapi-commands-sockets.c qapi/qapi-commands-sockets.h \
-qapi/qapi-commands-tpm.c qapi/qapi-commands-tpm.h \
-qapi/qapi-commands-trace.c qapi/qapi-commands-trace.h \
-qapi/qapi-commands-transaction.c qapi/qapi-commands-transaction.h \
-qapi/qapi-commands-ui.c qapi/qapi-commands-ui.h \
-qapi/qapi-events.c qapi/qapi-events.h \
-qapi/qapi-events-block-core.c qapi/qapi-events-block-core.h \
-qapi/qapi-events-block.c qapi/qapi-events-block.h \
-qapi/qapi-events-char.c qapi/qapi-events-char.h \
-qapi/qapi-events-common.c qapi/qapi-events-common.h \
-qapi/qapi-events-crypto.c qapi/qapi-events-crypto.h \
-qapi/qapi-events-introspect.c qapi/qapi-events-introspect.h \
-qapi/qapi-events-job.c qapi/qapi-events-job.h \
-qapi/qapi-events-migration.c qapi/qapi-events-migration.h \
-qapi/qapi-events-misc.c qapi/qapi-events-misc.h \
-qapi/qapi-events-net.c qapi/qapi-events-net.h \
-qapi/qapi-events-rocker.c qapi/qapi-events-rocker.h \
-qapi/qapi-events-run-state.c qapi/qapi-events-run-state.h \
-qapi/qapi-events-sockets.c qapi/qapi-events-sockets.h \
-qapi/qapi-events-tpm.c qapi/qapi-events-tpm.h \
-qapi/qapi-events-trace.c qapi/qapi-events-trace.h \
-qapi/qapi-events-transaction.c qapi/qapi-events-transaction.h \
-qapi/qapi-events-ui.c qapi/qapi-events-ui.h \
-qapi/qapi-introspect.h qapi/qapi-introspect.c \
-qapi/qapi-doc.texi: \
-qapi-gen-timestamp ;
+qapi-modules = $(SRC_PATH)/qapi/qapi-schema.json \
+ $(QAPI_MODULES:%=$(SRC_PATH)/qapi/%.json)
+
+$(GENERATED_QAPI_FILES): qapi-gen-timestamp ;
qapi-gen-timestamp: $(qapi-modules) $(qapi-py)
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-gen.py \
-o "qapi" -b $<, \
diff --git a/Makefile.objs b/Makefile.objs
index 1e1ff387d7..56af0347d3 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -1,63 +1,18 @@
+QAPI_MODULES = block-core block char common crypto introspect job migration
+QAPI_MODULES += misc net rocker run-state sockets tpm trace transaction ui
+
#######################################################################
# Common libraries for tools and emulators
stub-obj-y = stubs/ crypto/
util-obj-y = util/ qobject/ qapi/
util-obj-y += qapi/qapi-builtin-types.o
util-obj-y += qapi/qapi-types.o
-util-obj-y += qapi/qapi-types-block-core.o
-util-obj-y += qapi/qapi-types-block.o
-util-obj-y += qapi/qapi-types-char.o
-util-obj-y += qapi/qapi-types-common.o
-util-obj-y += qapi/qapi-types-crypto.o
-util-obj-y += qapi/qapi-types-introspect.o
-util-obj-y += qapi/qapi-types-job.o
-util-obj-y += qapi/qapi-types-migration.o
-util-obj-y += qapi/qapi-types-misc.o
-util-obj-y += qapi/qapi-types-net.o
-util-obj-y += qapi/qapi-types-rocker.o
-util-obj-y += qapi/qapi-types-run-state.o
-util-obj-y += qapi/qapi-types-sockets.o
-util-obj-y += qapi/qapi-types-tpm.o
-util-obj-y += qapi/qapi-types-trace.o
-util-obj-y += qapi/qapi-types-transaction.o
-util-obj-y += qapi/qapi-types-ui.o
+util-obj-y += $(QAPI_MODULES:%=qapi/qapi-types-%.o)
util-obj-y += qapi/qapi-builtin-visit.o
util-obj-y += qapi/qapi-visit.o
-util-obj-y += qapi/qapi-visit-block-core.o
-util-obj-y += qapi/qapi-visit-block.o
-util-obj-y += qapi/qapi-visit-char.o
-util-obj-y += qapi/qapi-visit-common.o
-util-obj-y += qapi/qapi-visit-crypto.o
-util-obj-y += qapi/qapi-visit-introspect.o
-util-obj-y += qapi/qapi-visit-job.o
-util-obj-y += qapi/qapi-visit-migration.o
-util-obj-y += qapi/qapi-visit-misc.o
-util-obj-y += qapi/qapi-visit-net.o
-util-obj-y += qapi/qapi-visit-rocker.o
-util-obj-y += qapi/qapi-visit-run-state.o
-util-obj-y += qapi/qapi-visit-sockets.o
-util-obj-y += qapi/qapi-visit-tpm.o
-util-obj-y += qapi/qapi-visit-trace.o
-util-obj-y += qapi/qapi-visit-transaction.o
-util-obj-y += qapi/qapi-visit-ui.o
+util-obj-y += $(QAPI_MODULES:%=qapi/qapi-visit-%.o)
util-obj-y += qapi/qapi-events.o
-util-obj-y += qapi/qapi-events-block-core.o
-util-obj-y += qapi/qapi-events-block.o
-util-obj-y += qapi/qapi-events-char.o
-util-obj-y += qapi/qapi-events-common.o
-util-obj-y += qapi/qapi-events-crypto.o
-util-obj-y += qapi/qapi-events-introspect.o
-util-obj-y += qapi/qapi-events-job.o
-util-obj-y += qapi/qapi-events-migration.o
-util-obj-y += qapi/qapi-events-misc.o
-util-obj-y += qapi/qapi-events-net.o
-util-obj-y += qapi/qapi-events-rocker.o
-util-obj-y += qapi/qapi-events-run-state.o
-util-obj-y += qapi/qapi-events-sockets.o
-util-obj-y += qapi/qapi-events-tpm.o
-util-obj-y += qapi/qapi-events-trace.o
-util-obj-y += qapi/qapi-events-transaction.o
-util-obj-y += qapi/qapi-events-ui.o
+util-obj-y += $(QAPI_MODULES:%=qapi/qapi-events-%.o)
util-obj-y += qapi/qapi-introspect.o
chardev-obj-y = chardev/
@@ -138,23 +93,7 @@ common-obj-$(CONFIG_FDT) += device_tree.o
# qapi
common-obj-y += qapi/qapi-commands.o
-common-obj-y += qapi/qapi-commands-block-core.o
-common-obj-y += qapi/qapi-commands-block.o
-common-obj-y += qapi/qapi-commands-char.o
-common-obj-y += qapi/qapi-commands-common.o
-common-obj-y += qapi/qapi-commands-crypto.o
-common-obj-y += qapi/qapi-commands-introspect.o
-common-obj-y += qapi/qapi-commands-job.o
-common-obj-y += qapi/qapi-commands-migration.o
-common-obj-y += qapi/qapi-commands-misc.o
-common-obj-y += qapi/qapi-commands-net.o
-common-obj-y += qapi/qapi-commands-rocker.o
-common-obj-y += qapi/qapi-commands-run-state.o
-common-obj-y += qapi/qapi-commands-sockets.o
-common-obj-y += qapi/qapi-commands-tpm.o
-common-obj-y += qapi/qapi-commands-trace.o
-common-obj-y += qapi/qapi-commands-transaction.o
-common-obj-y += qapi/qapi-commands-ui.o
+common-obj-y += $(QAPI_MODULES:%=qapi/qapi-commands-%.o)
common-obj-y += qapi/qapi-introspect.o
common-obj-y += qmp.o hmp.o
endif
diff --git a/Makefile.target b/Makefile.target
index 4d56298bbf..44ec4b630c 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -158,9 +158,6 @@ GENERATED_FILES += hmp-commands.h hmp-commands-info.h
endif # CONFIG_SOFTMMU
-# Workaround for http://gcc.gnu.org/PR55489, see configure.
-%/translate.o: QEMU_CFLAGS += $(TRANSLATE_OPT_CFLAGS)
-
dummy := $(call unnest-vars,,obj-y)
all-obj-y := $(obj-y)
diff --git a/VERSION b/VERSION
index 2e90136f42..0bc4611411 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-3.0.95
+3.1.50
diff --git a/accel/accel.c b/accel/accel.c
index 966b2d8f53..3da26eb90f 100644
--- a/accel/accel.c
+++ b/accel/accel.c
@@ -34,6 +34,7 @@
#include "qom/object.h"
#include "qemu/error-report.h"
#include "qemu/option.h"
+#include "qapi/error.h"
static const TypeInfo accel_type = {
.name = TYPE_ACCEL,
@@ -121,7 +122,13 @@ void configure_accelerator(MachineState *ms)
void accel_register_compat_props(AccelState *accel)
{
AccelClass *class = ACCEL_GET_CLASS(accel);
- register_compat_props_array(class->global_props);
+ GlobalProperty *prop = class->global_props;
+
+ for (; prop && prop->driver; prop++) {
+ /* Any compat_props must never cause error */
+ prop->errp = &error_abort;
+ qdev_prop_register_global(prop);
+ }
}
void accel_setup_post(MachineState *ms)
diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c
index 362a2276fd..635be73bf4 100644
--- a/audio/alsaaudio.c
+++ b/audio/alsaaudio.c
@@ -28,9 +28,7 @@
#include "audio.h"
#include "trace.h"
-#if QEMU_GNUC_PREREQ(4, 3)
#pragma GCC diagnostic ignored "-Waddress"
-#endif
#define AUDIO_CAP "alsa"
#include "audio_int.h"
diff --git a/backends/hostmem-file.c b/backends/hostmem-file.c
index 6630021226..78f058dee2 100644
--- a/backends/hostmem-file.c
+++ b/backends/hostmem-file.c
@@ -145,26 +145,20 @@ static void file_memory_backend_set_pmem(Object *o, bool value, Error **errp)
HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(o);
if (host_memory_backend_mr_inited(backend)) {
- char *path = object_get_canonical_path_component(o);
- error_setg(errp, "cannot change property 'pmem' of %s '%s'",
- object_get_typename(o),
- path);
- g_free(path);
+ error_setg(errp, "cannot change property 'pmem' of %s.",
+ object_get_typename(o));
return;
}
#ifndef CONFIG_LIBPMEM
if (value) {
Error *local_err = NULL;
- char *path = object_get_canonical_path_component(o);
error_setg(&local_err,
"Lack of libpmem support while setting the 'pmem=on'"
- " of %s '%s'. We can't ensure data persistence.",
- object_get_typename(o),
- path);
- g_free(path);
+ " of %s. We can't ensure data persistence.",
+ object_get_typename(o));
error_propagate(errp, local_err);
return;
}
diff --git a/backends/hostmem.c b/backends/hostmem.c
index 1a89342039..af800284e0 100644
--- a/backends/hostmem.c
+++ b/backends/hostmem.c
@@ -103,14 +103,23 @@ host_memory_backend_set_host_nodes(Object *obj, Visitor *v, const char *name,
{
#ifdef CONFIG_NUMA
HostMemoryBackend *backend = MEMORY_BACKEND(obj);
- uint16List *l = NULL;
+ uint16List *l, *host_nodes = NULL;
- visit_type_uint16List(v, name, &l, errp);
+ visit_type_uint16List(v, name, &host_nodes, errp);
- while (l) {
+ for (l = host_nodes; l; l = l->next) {
+ if (l->value >= MAX_NODES) {
+ error_setg(errp, "Invalid host-nodes value: %d", l->value);
+ goto out;
+ }
+ }
+
+ for (l = host_nodes; l; l = l->next) {
bitmap_set(backend->host_nodes, l->value, 1);
- l = l->next;
}
+
+out:
+ qapi_free_uint16List(host_nodes);
#else
error_setg(errp, "NUMA node binding are not supported by this QEMU");
#endif
diff --git a/block/crypto.c b/block/crypto.c
index 33ee01bebd..f0a5f6b987 100644
--- a/block/crypto.c
+++ b/block/crypto.c
@@ -229,6 +229,7 @@ static int block_crypto_open_generic(QCryptoBlockFormat format,
block_crypto_read_func,
bs,
cflags,
+ 1,
errp);
if (!crypto->block) {
diff --git a/block/qcow.c b/block/qcow.c
index 4518cb4c35..0a235bf393 100644
--- a/block/qcow.c
+++ b/block/qcow.c
@@ -213,7 +213,7 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
cflags |= QCRYPTO_BLOCK_OPEN_NO_IO;
}
s->crypto = qcrypto_block_open(crypto_opts, "encrypt.",
- NULL, NULL, cflags, errp);
+ NULL, NULL, cflags, 1, errp);
if (!s->crypto) {
ret = -EINVAL;
goto fail;
diff --git a/block/qcow2.c b/block/qcow2.c
index 991d6ac91b..bc8868c36a 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -294,7 +294,7 @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
}
s->crypto = qcrypto_block_open(s->crypto_opts, "encrypt.",
qcow2_crypto_hdr_read_func,
- bs, cflags, errp);
+ bs, cflags, 1, errp);
if (!s->crypto) {
return -EINVAL;
}
@@ -1445,7 +1445,7 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
cflags |= QCRYPTO_BLOCK_OPEN_NO_IO;
}
s->crypto = qcrypto_block_open(s->crypto_opts, "encrypt.",
- NULL, NULL, cflags, errp);
+ NULL, NULL, cflags, 1, errp);
if (!s->crypto) {
ret = -EINVAL;
goto fail;
diff --git a/chardev/char.c b/chardev/char.c
index 152dde5327..ccba36bafb 100644
--- a/chardev/char.c
+++ b/chardev/char.c
@@ -193,6 +193,8 @@ void qemu_chr_be_update_read_handlers(Chardev *s,
{
ChardevClass *cc = CHARDEV_GET_CLASS(s);
+ assert(qemu_chr_has_feature(s, QEMU_CHAR_FEATURE_GCONTEXT)
+ || !context);
s->gcontext = context;
if (cc->chr_update_read_handler) {
cc->chr_update_read_handler(s);
@@ -240,6 +242,15 @@ static void char_init(Object *obj)
chr->logfd = -1;
qemu_mutex_init(&chr->chr_write_lock);
+
+ /*
+ * Assume if chr_update_read_handler is implemented it will
+ * take the updated gcontext into account.
+ */
+ if (CHARDEV_GET_CLASS(chr)->chr_update_read_handler) {
+ qemu_chr_set_feature(chr, QEMU_CHAR_FEATURE_GCONTEXT);
+ }
+
}
static int null_chr_write(Chardev *chr, const uint8_t *buf, int len)
diff --git a/configure b/configure
index 0a3c6a72c3..0886f45bf4 100755
--- a/configure
+++ b/configure
@@ -1840,6 +1840,31 @@ if test "$bogus_os" = "yes"; then
error_exit "Unrecognized host OS (uname -s reports '$(uname -s)')"
fi
+# Check whether the compiler matches our minimum requirements:
+cat > $TMPC << EOF
+#if defined(__clang_major__) && defined(__clang_minor__)
+# ifdef __apple_build_version__
+# if __clang_major__ < 5 || (__clang_major__ == 5 && __clang_minor__ < 1)
+# error You need at least XCode Clang v5.1 to compile QEMU
+# endif
+# else
+# if __clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ < 4)
+# error You need at least Clang v3.4 to compile QEMU
+# endif
+# endif
+#elif defined(__GNUC__) && defined(__GNUC_MINOR__)
+# if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 8)
+# error You need at least GCC v4.8 to compile QEMU
+# endif
+#else
+# error You either need GCC or Clang to compiler QEMU
+#endif
+int main (void) { return 0; }
+EOF
+if ! compile_prog "" "" ; then
+ error_exit "You need at least GCC v4.8 or Clang v3.4 (or XCode Clang v5.1)"
+fi
+
gcc_flags="-Wold-style-declaration -Wold-style-definition -Wtype-limits"
gcc_flags="-Wformat-security -Wformat-y2k -Winit-self -Wignored-qualifiers $gcc_flags"
gcc_flags="-Wno-missing-include-dirs -Wempty-body -Wnested-externs $gcc_flags"
@@ -1911,21 +1936,7 @@ else
QEMU_CFLAGS="$QEMU_CFLAGS -Wno-missing-braces"
fi
-# Workaround for http://gcc.gnu.org/PR55489. Happens with -fPIE/-fPIC and
-# large functions that use global variables. The bug is in all releases of
-# GCC, but it became particularly acute in 4.6.x and 4.7.x. It is fixed in
-# 4.7.3 and 4.8.0. We should be able to delete this at the end of 2013.
-cat > $TMPC << EOF
-#if __GNUC__ == 4 && (__GNUC_MINOR__ == 6 || (__GNUC_MINOR__ == 7 && __GNUC_PATCHLEVEL__ <= 2))
-int main(void) { return 0; }
-#else
-#error No bug in this compiler.
-#endif
-EOF
-if compile_prog "-Werror -fno-gcse" "" ; then
- TRANSLATE_OPT_CFLAGS=-fno-gcse
-fi
-
+# Static linking is not possible with modules or PIE
if test "$static" = "yes" ; then
if test "$modules" = "yes" ; then
error_exit "static and modules are mutually incompatible"
@@ -5123,11 +5134,6 @@ fi
int128=no
cat > $TMPC << EOF
-#if defined(__clang_major__) && defined(__clang_minor__)
-# if ((__clang_major__ < 3) || (__clang_major__ == 3) && (__clang_minor__ < 2))
-# error __int128_t does not work in CLANG before 3.2
-# endif
-#endif
__int128_t a;
__uint128_t b;
int main (void) {
@@ -6963,7 +6969,6 @@ echo "LIBS_QGA+=$libs_qga" >> $config_host_mak
echo "TASN1_LIBS=$tasn1_libs" >> $config_host_mak
echo "TASN1_CFLAGS=$tasn1_cflags" >> $config_host_mak
echo "POD2MAN=$POD2MAN" >> $config_host_mak
-echo "TRANSLATE_OPT_CFLAGS=$TRANSLATE_OPT_CFLAGS" >> $config_host_mak
if test "$gcov" = "yes" ; then
echo "CONFIG_GCOV=y" >> $config_host_mak
echo "GCOV=$gcov_tool" >> $config_host_mak
diff --git a/crypto/block-luks.c b/crypto/block-luks.c
index 5738124773..6bac79c3ab 100644
--- a/crypto/block-luks.c
+++ b/crypto/block-luks.c
@@ -504,14 +504,14 @@ qcrypto_block_luks_load_key(QCryptoBlock *block,
* to reset the encryption cipher every time the master
* key crosses a sector boundary.
*/
- if (qcrypto_block_decrypt_helper(cipher,
- niv,
- ivgen,
- QCRYPTO_BLOCK_LUKS_SECTOR_SIZE,
- 0,
- splitkey,
- splitkeylen,
- errp) < 0) {
+ if (qcrypto_block_cipher_decrypt_helper(cipher,
+ niv,
+ ivgen,
+ QCRYPTO_BLOCK_LUKS_SECTOR_SIZE,
+ 0,
+ splitkey,
+ splitkeylen,
+ errp) < 0) {
goto cleanup;
}
@@ -636,6 +636,7 @@ qcrypto_block_luks_open(QCryptoBlock *block,
QCryptoBlockReadFunc readfunc,
void *opaque,
unsigned int flags,
+ size_t n_threads,
Error **errp)
{
QCryptoBlockLUKS *luks;
@@ -836,11 +837,10 @@ qcrypto_block_luks_open(QCryptoBlock *block,
goto fail;
}
- block->cipher = qcrypto_cipher_new(cipheralg,
- ciphermode,
- masterkey, masterkeylen,
- errp);
- if (!block->cipher) {
+ ret = qcrypto_block_init_cipher(block, cipheralg, ciphermode,
+ masterkey, masterkeylen, n_threads,
+ errp);
+ if (ret < 0) {
ret = -ENOTSUP;
goto fail;
}
@@ -863,7 +863,7 @@ qcrypto_block_luks_open(QCryptoBlock *block,
fail:
g_free(masterkey);
- qcrypto_cipher_free(block->cipher);
+ qcrypto_block_free_cipher(block);
qcrypto_ivgen_free(block->ivgen);
g_free(luks);
g_free(password);
@@ -1030,11 +1030,9 @@ qcrypto_block_luks_create(QCryptoBlock *block,
/* Setup the block device payload encryption objects */
- block->cipher = qcrypto_cipher_new(luks_opts.cipher_alg,
- luks_opts.cipher_mode,
- masterkey, luks->header.key_bytes,
- errp);
- if (!block->cipher) {
+ if (qcrypto_block_init_cipher(block, luks_opts.cipher_alg,
+ luks_opts.cipher_mode, masterkey,
+ luks->header.key_bytes, 1, errp) < 0) {
goto error;
}
@@ -1219,12 +1217,12 @@ qcrypto_block_luks_create(QCryptoBlock *block,
/* Now we encrypt the split master key with the key generated
* from the user's password, before storing it */
- if (qcrypto_block_encrypt_helper(cipher, block->niv, ivgen,
- QCRYPTO_BLOCK_LUKS_SECTOR_SIZE,
- 0,
- splitkey,
- splitkeylen,
- errp) < 0) {
+ if (qcrypto_block_cipher_encrypt_helper(cipher, block->niv, ivgen,
+ QCRYPTO_BLOCK_LUKS_SECTOR_SIZE,
+ 0,
+ splitkey,
+ splitkeylen,
+ errp) < 0) {
goto error;
}
@@ -1341,6 +1339,9 @@ qcrypto_block_luks_create(QCryptoBlock *block,
qcrypto_ivgen_free(ivgen);
qcrypto_cipher_free(cipher);
+ qcrypto_block_free_cipher(block);
+ qcrypto_ivgen_free(block->ivgen);
+
g_free(luks);
return -1;
}
@@ -1406,8 +1407,7 @@ qcrypto_block_luks_decrypt(QCryptoBlock *block,
{
assert(QEMU_IS_ALIGNED(offset, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE));
assert(QEMU_IS_ALIGNED(len, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE));
- return qcrypto_block_decrypt_helper(block->cipher,
- block->niv, block->ivgen,
+ return qcrypto_block_decrypt_helper(block,
QCRYPTO_BLOCK_LUKS_SECTOR_SIZE,
offset, buf, len, errp);
}
@@ -1422,8 +1422,7 @@ qcrypto_block_luks_encrypt(QCryptoBlock *block,
{
assert(QEMU_IS_ALIGNED(offset, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE));
assert(QEMU_IS_ALIGNED(len, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE));
- return qcrypto_block_encrypt_helper(block->cipher,
- block->niv, block->ivgen,
+ return qcrypto_block_encrypt_helper(block,
QCRYPTO_BLOCK_LUKS_SECTOR_SIZE,
offset, buf, len, errp);
}
diff --git a/crypto/block-qcow.c b/crypto/block-qcow.c
index 7606231e79..cefb3b2a7b 100644
--- a/crypto/block-qcow.c
+++ b/crypto/block-qcow.c
@@ -44,6 +44,7 @@ qcrypto_block_qcow_has_format(const uint8_t *buf G_GNUC_UNUSED,
static int
qcrypto_block_qcow_init(QCryptoBlock *block,
const char *keysecret,
+ size_t n_threads,
Error **errp)
{
char *password;
@@ -71,11 +72,11 @@ qcrypto_block_qcow_init(QCryptoBlock *block,
goto fail;
}
- block->cipher = qcrypto_cipher_new(QCRYPTO_CIPHER_ALG_AES_128,
- QCRYPTO_CIPHER_MODE_CBC,
- keybuf, G_N_ELEMENTS(keybuf),
- errp);
- if (!block->cipher) {
+ ret = qcrypto_block_init_cipher(block, QCRYPTO_CIPHER_ALG_AES_128,
+ QCRYPTO_CIPHER_MODE_CBC,
+ keybuf, G_N_ELEMENTS(keybuf),
+ n_threads, errp);
+ if (ret < 0) {
ret = -ENOTSUP;
goto fail;
}
@@ -86,7 +87,7 @@ qcrypto_block_qcow_init(QCryptoBlock *block,
return 0;
fail:
- qcrypto_cipher_free(block->cipher);
+ qcrypto_block_free_cipher(block);
qcrypto_ivgen_free(block->ivgen);
return ret;
}
@@ -99,6 +100,7 @@ qcrypto_block_qcow_open(QCryptoBlock *block,
QCryptoBlockReadFunc readfunc G_GNUC_UNUSED,
void *opaque G_GNUC_UNUSED,
unsigned int flags,
+ size_t n_threads,
Error **errp)
{
if (flags & QCRYPTO_BLOCK_OPEN_NO_IO) {
@@ -112,8 +114,8 @@ qcrypto_block_qcow_open(QCryptoBlock *block,
optprefix ? optprefix : "");
return -1;
}
- return qcrypto_block_qcow_init(block,
- options->u.qcow.key_secret, errp);
+ return qcrypto_block_qcow_init(block, options->u.qcow.key_secret,
+ n_threads, errp);
}
}
@@ -133,7 +135,7 @@ qcrypto_block_qcow_create(QCryptoBlock *block,
return -1;
}
/* QCow2 has no special header, since everything is hardwired */
- return qcrypto_block_qcow_init(block, options->u.qcow.key_secret, errp);
+ return qcrypto_block_qcow_init(block, options->u.qcow.key_secret, 1, errp);
}
@@ -152,8 +154,7 @@ qcrypto_block_qcow_decrypt(QCryptoBlock *block,
{
assert(QEMU_IS_ALIGNED(offset, QCRYPTO_BLOCK_QCOW_SECTOR_SIZE));
assert(QEMU_IS_ALIGNED(len, QCRYPTO_BLOCK_QCOW_SECTOR_SIZE));
- return qcrypto_block_decrypt_helper(block->cipher,
- block->niv, block->ivgen,
+ return qcrypto_block_decrypt_helper(block,
QCRYPTO_BLOCK_QCOW_SECTOR_SIZE,
offset, buf, len, errp);
}
@@ -168,8 +169,7 @@ qcrypto_block_qcow_encrypt(QCryptoBlock *block,
{
assert(QEMU_IS_ALIGNED(offset, QCRYPTO_BLOCK_QCOW_SECTOR_SIZE));
assert(QEMU_IS_ALIGNED(len, QCRYPTO_BLOCK_QCOW_SECTOR_SIZE));
- return qcrypto_block_encrypt_helper(block->cipher,
- block->niv, block->ivgen,
+ return qcrypto_block_encrypt_helper(block,
QCRYPTO_BLOCK_QCOW_SECTOR_SIZE,
offset, buf, len, errp);
}
diff --git a/crypto/block.c b/crypto/block.c
index e59d1140fe..d70d401f87 100644
--- a/crypto/block.c
+++ b/crypto/block.c
@@ -52,6 +52,7 @@ QCryptoBlock *qcrypto_block_open(QCryptoBlockOpenOptions *options,
QCryptoBlockReadFunc readfunc,
void *opaque,
unsigned int flags,
+ size_t n_threads,
Error **errp)
{
QCryptoBlock *block = g_new0(QCryptoBlock, 1);
@@ -69,11 +70,14 @@ QCryptoBlock *qcrypto_block_open(QCryptoBlockOpenOptions *options,
block->driver = qcrypto_block_drivers[options->format];
if (block->driver->open(block, options, optprefix,
- readfunc, opaque, flags, errp) < 0) {
+ readfunc, opaque, flags, n_threads, errp) < 0)
+ {
g_free(block);
return NULL;
}
+ qemu_mutex_init(&block->mutex);
+
return block;
}
@@ -105,6 +109,8 @@ QCryptoBlock *qcrypto_block_create(QCryptoBlockCreateOptions *options,
return NULL;
}
+ qemu_mutex_init(&block->mutex);
+
return block;
}
@@ -148,12 +154,97 @@ int qcrypto_block_encrypt(QCryptoBlock *block,
QCryptoCipher *qcrypto_block_get_cipher(QCryptoBlock *block)
{
- return block->cipher;
+ /* Ciphers should be accessed through pop/push method to be thread-safe.
+ * Better, they should not be accessed externally at all (note, that
+ * pop/push are static functions)
+ * This function is used only in test with one thread (it's safe to skip
+ * pop/push interface), so it's enough to assert it here:
+ */
+ assert(block->n_ciphers <= 1);
+ return block->ciphers ? block->ciphers[0] : NULL;
+}
+
+
+static QCryptoCipher *qcrypto_block_pop_cipher(QCryptoBlock *block)
+{
+ QCryptoCipher *cipher;
+
+ qemu_mutex_lock(&block->mutex);
+
+ assert(block->n_free_ciphers > 0);
+ block->n_free_ciphers--;
+ cipher = block->ciphers[block->n_free_ciphers];
+
+ qemu_mutex_unlock(&block->mutex);
+
+ return cipher;
+}
+
+
+static void qcrypto_block_push_cipher(QCryptoBlock *block,
+ QCryptoCipher *cipher)
+{
+ qemu_mutex_lock(&block->mutex);
+
+ assert(block->n_free_ciphers < block->n_ciphers);
+ block->ciphers[block->n_free_ciphers] = cipher;
+ block->n_free_ciphers++;
+
+ qemu_mutex_unlock(&block->mutex);
}
+int qcrypto_block_init_cipher(QCryptoBlock *block,
+ QCryptoCipherAlgorithm alg,
+ QCryptoCipherMode mode,
+ const uint8_t *key, size_t nkey,
+ size_t n_threads, Error **errp)
+{
+ size_t i;
+
+ assert(!block->ciphers && !block->n_ciphers && !block->n_free_ciphers);
+
+ block->ciphers = g_new0(QCryptoCipher *, n_threads);
+
+ for (i = 0; i < n_threads; i++) {
+ block->ciphers[i] = qcrypto_cipher_new(alg, mode, key, nkey, errp);
+ if (!block->ciphers[i]) {
+ qcrypto_block_free_cipher(block);
+ return -1;
+ }
+ block->n_ciphers++;
+ block->n_free_ciphers++;
+ }
+
+ return 0;
+}
+
+
+void qcrypto_block_free_cipher(QCryptoBlock *block)
+{
+ size_t i;
+
+ if (!block->ciphers) {
+ return;
+ }
+
+ assert(block->n_ciphers == block->n_free_ciphers);
+
+ for (i = 0; i < block->n_ciphers; i++) {
+ qcrypto_cipher_free(block->ciphers[i]);
+ }
+
+ g_free(block->ciphers);
+ block->ciphers = NULL;
+ block->n_ciphers = block->n_free_ciphers = 0;
+}
+
QCryptoIVGen *qcrypto_block_get_ivgen(QCryptoBlock *block)
{
+ /* ivgen should be accessed under mutex. However, this function is used only
+ * in test with one thread, so it's enough to assert it here:
+ */
+ assert(block->n_ciphers <= 1);
return block->ivgen;
}
@@ -184,20 +275,29 @@ void qcrypto_block_free(QCryptoBlock *block)
block->driver->cleanup(block);
- qcrypto_cipher_free(block->cipher);
+ qcrypto_block_free_cipher(block);
qcrypto_ivgen_free(block->ivgen);
+ qemu_mutex_destroy(&block->mutex);
g_free(block);
}
-int qcrypto_block_decrypt_helper(QCryptoCipher *cipher,
- size_t niv,
- QCryptoIVGen *ivgen,
- int sectorsize,
- uint64_t offset,
- uint8_t *buf,
- size_t len,
- Error **errp)
+typedef int (*QCryptoCipherEncDecFunc)(QCryptoCipher *cipher,
+ const void *in,
+ void *out,
+ size_t len,
+ Error **errp);
+
+static int do_qcrypto_block_cipher_encdec(QCryptoCipher *cipher,
+ size_t niv,
+ QCryptoIVGen *ivgen,
+ QemuMutex *ivgen_mutex,
+ int sectorsize,
+ uint64_t offset,
+ uint8_t *buf,
+ size_t len,
+ QCryptoCipherEncDecFunc func,
+ Error **errp)
{
uint8_t *iv;
int ret = -1;
@@ -211,10 +311,15 @@ int qcrypto_block_decrypt_helper(QCryptoCipher *cipher,
while (len > 0) {
size_t nbytes;
if (niv) {
- if (qcrypto_ivgen_calculate(ivgen,
- startsector,
- iv, niv,
- errp) < 0) {
+ if (ivgen_mutex) {
+ qemu_mutex_lock(ivgen_mutex);
+ }
+ ret = qcrypto_ivgen_calculate(ivgen, startsector, iv, niv, errp);
+ if (ivgen_mutex) {
+ qemu_mutex_unlock(ivgen_mutex);
+ }
+
+ if (ret < 0) {
goto cleanup;
}
@@ -226,8 +331,7 @@ int qcrypto_block_decrypt_helper(QCryptoCipher *cipher,
}
nbytes = len > sectorsize ? sectorsize : len;
- if (qcrypto_cipher_decrypt(cipher, buf, buf,
- nbytes, errp) < 0) {
+ if (func(cipher, buf, buf, nbytes, errp) < 0) {
goto cleanup;
}
@@ -243,54 +347,69 @@ int qcrypto_block_decrypt_helper(QCryptoCipher *cipher,
}
-int qcrypto_block_encrypt_helper(QCryptoCipher *cipher,
- size_t niv,
- QCryptoIVGen *ivgen,
+int qcrypto_block_cipher_decrypt_helper(QCryptoCipher *cipher,
+ size_t niv,
+ QCryptoIVGen *ivgen,
+ int sectorsize,
+ uint64_t offset,
+ uint8_t *buf,
+ size_t len,
+ Error **errp)
+{
+ return do_qcrypto_block_cipher_encdec(cipher, niv, ivgen, NULL, sectorsize,
+ offset, buf, len,
+ qcrypto_cipher_decrypt, errp);
+}
+
+
+int qcrypto_block_cipher_encrypt_helper(QCryptoCipher *cipher,
+ size_t niv,
+ QCryptoIVGen *ivgen,
+ int sectorsize,
+ uint64_t offset,
+ uint8_t *buf,
+ size_t len,
+ Error **errp)
+{
+ return do_qcrypto_block_cipher_encdec(cipher, niv, ivgen, NULL, sectorsize,
+ offset, buf, len,
+ qcrypto_cipher_encrypt, errp);
+}
+
+int qcrypto_block_decrypt_helper(QCryptoBlock *block,
int sectorsize,
uint64_t offset,
uint8_t *buf,
size_t len,
Error **errp)
{
- uint8_t *iv;
- int ret = -1;
- uint64_t startsector = offset / sectorsize;
+ int ret;
+ QCryptoCipher *cipher = qcrypto_block_pop_cipher(block);
- assert(QEMU_IS_ALIGNED(offset, sectorsize));
- assert(QEMU_IS_ALIGNED(len, sectorsize));
+ ret = do_qcrypto_block_cipher_encdec(cipher, block->niv, block->ivgen,
+ &block->mutex, sectorsize, offset, buf,
+ len, qcrypto_cipher_decrypt, errp);
- iv = niv ? g_new0(uint8_t, niv) : NULL;
+ qcrypto_block_push_cipher(block, cipher);
- while (len > 0) {
- size_t nbytes;
- if (niv) {
- if (qcrypto_ivgen_calculate(ivgen,
- startsector,
- iv, niv,
- errp) < 0) {
- goto cleanup;
- }
+ return ret;
+}
- if (qcrypto_cipher_setiv(cipher,
- iv, niv,
- errp) < 0) {
- goto cleanup;
- }
- }
+int qcrypto_block_encrypt_helper(QCryptoBlock *block,
+ int sectorsize,
+ uint64_t offset,
+ uint8_t *buf,
+ size_t len,
+ Error **errp)
+{
+ int ret;
+ QCryptoCipher *cipher = qcrypto_block_pop_cipher(block);
- nbytes = len > sectorsize ? sectorsize : len;
- if (qcrypto_cipher_encrypt(cipher, buf, buf,
- nbytes, errp) < 0) {
- goto cleanup;
- }
+ ret = do_qcrypto_block_cipher_encdec(cipher, block->niv, block->ivgen,
+ &block->mutex, sectorsize, offset, buf,
+ len, qcrypto_cipher_encrypt, errp);
- startsector++;
- buf += nbytes;
- len -= nbytes;
- }
+ qcrypto_block_push_cipher(block, cipher);
- ret = 0;
- cleanup:
- g_free(iv);
return ret;
}
diff --git a/crypto/blockpriv.h b/crypto/blockpriv.h
index 41840abcec..5438e822fd 100644
--- a/crypto/blockpriv.h
+++ b/crypto/blockpriv.h
@@ -22,6 +22,7 @@
#define QCRYPTO_BLOCKPRIV_H
#include "crypto/block.h"
+#include "qemu/thread.h"
typedef struct QCryptoBlockDriver QCryptoBlockDriver;
@@ -31,8 +32,12 @@ struct QCryptoBlock {
const QCryptoBlockDriver *driver;
void *opaque;
- QCryptoCipher *cipher;
+ QCryptoCipher **ciphers;
+ size_t n_ciphers;
+ size_t n_free_ciphers;
QCryptoIVGen *ivgen;
+ QemuMutex mutex;
+
QCryptoHashAlgorithm kdfhash;
size_t niv;
uint64_t payload_offset; /* In bytes */
@@ -46,6 +51,7 @@ struct QCryptoBlockDriver {
QCryptoBlockReadFunc readfunc,
void *opaque,
unsigned int flags,
+ size_t n_threads,
Error **errp);
int (*create)(QCryptoBlock *block,
@@ -78,22 +84,44 @@ struct QCryptoBlockDriver {
};
-int qcrypto_block_decrypt_helper(QCryptoCipher *cipher,
- size_t niv,
- QCryptoIVGen *ivgen,
+int qcrypto_block_cipher_decrypt_helper(QCryptoCipher *cipher,
+ size_t niv,
+ QCryptoIVGen *ivgen,
+ int sectorsize,
+ uint64_t offset,
+ uint8_t *buf,
+ size_t len,
+ Error **errp);
+
+int qcrypto_block_cipher_encrypt_helper(QCryptoCipher *cipher,
+ size_t niv,
+ QCryptoIVGen *ivgen,
+ int sectorsize,
+ uint64_t offset,
+ uint8_t *buf,
+ size_t len,
+ Error **errp);
+
+int qcrypto_block_decrypt_helper(QCryptoBlock *block,
int sectorsize,
uint64_t offset,
uint8_t *buf,
size_t len,
Error **errp);
-int qcrypto_block_encrypt_helper(QCryptoCipher *cipher,
- size_t niv,
- QCryptoIVGen *ivgen,
+int qcrypto_block_encrypt_helper(QCryptoBlock *block,
int sectorsize,
uint64_t offset,
uint8_t *buf,
size_t len,
Error **errp);
+int qcrypto_block_init_cipher(QCryptoBlock *block,
+ QCryptoCipherAlgorithm alg,
+ QCryptoCipherMode mode,
+ const uint8_t *key, size_t nkey,
+ size_t n_threads, Error **errp);
+
+void qcrypto_block_free_cipher(QCryptoBlock *block);
+
#endif /* QCRYPTO_BLOCKPRIV_H */
diff --git a/docs/cpu-hotplug.rst b/docs/cpu-hotplug.rst
new file mode 100644
index 0000000000..1c268e00b4
--- /dev/null
+++ b/docs/cpu-hotplug.rst
@@ -0,0 +1,142 @@
+===================
+Virtual CPU hotplug
+===================
+
+A complete example of vCPU hotplug (and hot-unplug) using QMP
+``device_add`` and ``device_del``.
+
+vCPU hotplug
+------------
+
+(1) Launch QEMU as follows (note that the "maxcpus" is mandatory to
+ allow vCPU hotplug)::
+
+ $ qemu-system-x86_64 -display none -no-user-config -m 2048 \
+ -nodefaults -monitor stdio -machine pc,accel=kvm,usb=off \
+ -smp 1,maxcpus=2 -cpu IvyBridge-IBRS \
+ -qmp unix:/tmp/qmp-sock,server,nowait
+
+(2) Run 'qmp-shell' (located in the source tree, under: "scripts/qmp/)
+ to connect to the just-launched QEMU::
+
+ $> ./qmp-shell -p -v /tmp/qmp-sock
+ [...]
+ (QEMU)
+
+(3) Find out which CPU types could be plugged, and into which sockets::
+
+ (QEMU) query-hotpluggable-cpus
+ {
+ "execute": "query-hotpluggable-cpus",
+ "arguments": {}
+ }
+ {
+ "return": [
+ {
+ "type": "IvyBridge-IBRS-x86_64-cpu",
+ "vcpus-count": 1,
+ "props": {
+ "socket-id": 1,
+ "core-id": 0,
+ "thread-id": 0
+ }
+ },
+ {
+ "qom-path": "/machine/unattached/device[0]",
+ "type": "IvyBridge-IBRS-x86_64-cpu",
+ "vcpus-count": 1,
+ "props": {
+ "socket-id": 0,
+ "core-id": 0,
+ "thread-id": 0
+ }
+ }
+ ]
+ }
+ (QEMU)
+
+(4) The ``query-hotpluggable-cpus`` command returns an object for CPUs
+ that are present (containing a "qom-path" member) or which may be
+ hot-plugged (no "qom-path" member). From its output in step (3), we
+ can see that ``IvyBridge-IBRS-x86_64-cpu`` is present in socket 0,
+ while hot-plugging a CPU into socket 1 requires passing the listed
+ properties to QMP ``device_add``:
+
+ (QEMU) device_add id=cpu-2 driver=IvyBridge-IBRS-x86_64-cpu socket-id=1 core-id=0 thread-id=0
+ {
+ "execute": "device_add",
+ "arguments": {
+ "socket-id": 1,
+ "driver": "IvyBridge-IBRS-x86_64-cpu",
+ "id": "cpu-2",
+ "core-id": 0,
+ "thread-id": 0
+ }
+ }
+ {
+ "return": {}
+ }
+ (QEMU)
+
+(5) Optionally, run QMP `query-cpus-fast` for some details about the
+ vCPUs::
+
+ (QEMU) query-cpus-fast
+ {
+ "execute": "query-cpus-fast",
+ "arguments": {}
+ }
+ {
+ "return": [
+ {
+ "qom-path": "/machine/unattached/device[0]",
+ "target": "x86_64",
+ "thread-id": 11534,
+ "cpu-index": 0,
+ "props": {
+ "socket-id": 0,
+ "core-id": 0,
+ "thread-id": 0
+ },
+ "arch": "x86"
+ },
+ {
+ "qom-path": "/machine/peripheral/cpu-2",
+ "target": "x86_64",
+ "thread-id": 12106,
+ "cpu-index": 1,
+ "props": {
+ "socket-id": 1,
+ "core-id": 0,
+ "thread-id": 0
+ },
+ "arch": "x86"
+ }
+ ]
+ }
+ (QEMU)
+
+vCPU hot-unplug
+---------------
+
+From the 'qmp-shell', invoke the QMP ``device_del`` command::
+
+ (QEMU) device_del id=cpu-2
+ {
+ "execute": "device_del",
+ "arguments": {
+ "id": "cpu-2"
+ }
+ }
+ {
+ "return": {}
+ }
+ (QEMU)
+
+.. note::
+ vCPU hot-unplug requires guest cooperation; so the ``device_del``
+ command above does not guarantee vCPU removal -- it's a "request to
+ unplug". At this point, the guest will get a System Control
+ Interupt (SCI) and calls the ACPI handler for the affected vCPU
+ device. Then the guest kernel will bring the vCPU offline and tell
+ QEMU to unplug it.
diff --git a/docs/devel/qapi-code-gen.txt b/docs/devel/qapi-code-gen.txt
index 53eaf01f34..43bd853e69 100644
--- a/docs/devel/qapi-code-gen.txt
+++ b/docs/devel/qapi-code-gen.txt
@@ -26,7 +26,7 @@ how the schemas, scripts, and resulting code are used.
== QMP/Guest agent schema ==
A QAPI schema file is designed to be loosely based on JSON
-(http://www.ietf.org/rfc/rfc7159.txt) with changes for quoting style
+(http://www.ietf.org/rfc/rfc8259.txt) with changes for quoting style
and the use of comments; a QAPI schema file is then parsed by a python
code generation program. A valid QAPI schema consists of a series of
top-level expressions, with no commas between them. Where
@@ -752,6 +752,25 @@ gets its generated code guarded like this:
#endif /* defined(HAVE_BAR) */
#endif /* defined(CONFIG_FOO) */
+Where a member can be defined with a single string value for its type,
+it is also possible to supply a dictionary instead with both 'type'
+and 'if' keys.
+
+Example: a conditional 'bar' member
+
+{ 'struct': 'IfStruct', 'data':
+ { 'foo': 'int',
+ 'bar': { 'type': 'int', 'if': 'defined(IFCOND)'} } }
+
+An enum value can be replaced by a dictionary with a 'name' and a 'if'
+key.
+
+Example: a conditional 'bar' enum member.
+
+{ 'enum': 'IfEnum', 'data':
+ [ 'foo',
+ { 'name' : 'bar', 'if': 'defined(IFCOND)' } ] }
+
Please note that you are responsible to ensure that the C code will
compile with an arbitrary combination of conditions, since the
generators are unable to check it at this point.
diff --git a/docs/interop/qmp-spec.txt b/docs/interop/qmp-spec.txt
index 8f7da0245d..adcf86754d 100644
--- a/docs/interop/qmp-spec.txt
+++ b/docs/interop/qmp-spec.txt
@@ -32,7 +32,7 @@ following format:
Where DATA-STRUCTURE-NAME is any valid JSON data structure, as defined
by the JSON standard:
-http://www.ietf.org/rfc/rfc7159.txt
+http://www.ietf.org/rfc/rfc8259.txt
The server expects its input to be encoded in UTF-8, and sends its
output encoded in ASCII.
@@ -130,8 +130,9 @@ to pass "id" with out-of-band commands. Passing it with all commands
is recommended for clients that accept capability "oob".
If the client sends in-band commands faster than the server can
-execute them, the server will eventually drop commands to limit the
-queue length. The sever sends event COMMAND_DROPPED then.
+execute them, the server will stop reading the requests from the QMP
+channel until the request queue length is reduced to an acceptable
+range.
Only a few commands support out-of-band execution. The ones that do
have "allow-oob": true in output of query-qmp-schema.
diff --git a/fsdev/qemu-fsdev.c b/fsdev/qemu-fsdev.c
index 7a3b87cc9e..4536fd977d 100644
--- a/fsdev/qemu-fsdev.c
+++ b/fsdev/qemu-fsdev.c
@@ -23,9 +23,6 @@ static QTAILQ_HEAD(FsDriverEntry_head, FsDriverListEntry) fsdriver_entries =
static FsDriverTable FsDrivers[] = {
{ .name = "local", .ops = &local_ops},
-#ifdef CONFIG_OPEN_BY_HANDLE
- { .name = "handle", .ops = &handle_ops},
-#endif
{ .name = "synth", .ops = &synth_ops},
{ .name = "proxy", .ops = &proxy_ops},
};
diff --git a/hmp-commands.hx b/hmp-commands.hx
index db0c681f74..ba71558c25 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1849,14 +1849,16 @@ ETEXI
.name = "cpu-add",
.args_type = "id:i",
.params = "id",
- .help = "add cpu",
+ .help = "add cpu (deprecated, use device_add instead)",
.cmd = hmp_cpu_add,
},
STEXI
@item cpu-add @var{id}
@findex cpu-add
-Add CPU with id @var{id}
+Add CPU with id @var{id}. This command is deprecated, please
++use @code{device_add} instead. For details, refer to
+'docs/cpu-hotplug.rst'.
ETEXI
{
diff --git a/hmp.c b/hmp.c
index 7828f93a39..43ae9ec61a 100644
--- a/hmp.c
+++ b/hmp.c
@@ -2372,6 +2372,8 @@ void hmp_cpu_add(Monitor *mon, const QDict *qdict)
int cpuid;
Error *err = NULL;
+ error_report("cpu_add is deprecated, please use device_add instead");
+
cpuid = qdict_get_int(qdict, "id");
qmp_cpu_add(cpuid, &err);
hmp_handle_error(mon, &err);
diff --git a/hw/9pfs/9p-handle.c b/hw/9pfs/9p-handle.c
deleted file mode 100644
index 3465b1ef30..0000000000
--- a/hw/9pfs/9p-handle.c
+++ /dev/null
@@ -1,710 +0,0 @@
-/*
- * 9p handle callback
- *
- * Copyright IBM, Corp. 2011
- *
- * Authors:
- * Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2. See
- * the COPYING file in the top-level directory.
- *
- */
-
-#include "qemu/osdep.h"
-#include "9p.h"
-#include "9p-xattr.h"
-#include <arpa/inet.h>
-#include <pwd.h>
-#include <grp.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include "qapi/error.h"
-#include "qemu/xattr.h"
-#include "qemu/cutils.h"
-#include "qemu/error-report.h"
-#include "qemu/option.h"
-#include <linux/fs.h>
-#ifdef CONFIG_LINUX_MAGIC_H
-#include <linux/magic.h>
-#endif
-#include <sys/ioctl.h>
-
-#ifndef XFS_SUPER_MAGIC
-#define XFS_SUPER_MAGIC 0x58465342
-#endif
-#ifndef EXT2_SUPER_MAGIC
-#define EXT2_SUPER_MAGIC 0xEF53
-#endif
-#ifndef REISERFS_SUPER_MAGIC
-#define REISERFS_SUPER_MAGIC 0x52654973
-#endif
-#ifndef BTRFS_SUPER_MAGIC
-#define BTRFS_SUPER_MAGIC 0x9123683E
-#endif
-
-typedef struct HandleData {
- int mountfd;
- int handle_bytes;
-} HandleData;
-
-static inline int name_to_handle(int dirfd, const char *name,
- struct file_handle *fh, int *mnt_id, int flags)
-{
- return name_to_handle_at(dirfd, name, fh, mnt_id, flags);
-}
-
-static inline int open_by_handle(int mountfd, const char *fh, int flags)
-{
- return open_by_handle_at(mountfd, (struct file_handle *)fh, flags);
-}
-
-static int handle_update_file_cred(int dirfd, const char *name, FsCred *credp)
-{
- int fd, ret;
- fd = openat(dirfd, name, O_NONBLOCK | O_NOFOLLOW);
- if (fd < 0) {
- return fd;
- }
- ret = fchownat(fd, "", credp->fc_uid, credp->fc_gid, AT_EMPTY_PATH);
- if (ret < 0) {
- goto err_out;
- }
- ret = fchmod(fd, credp->fc_mode & 07777);
-err_out:
- close(fd);
- return ret;
-}
-
-
-static int handle_lstat(FsContext *fs_ctx, V9fsPath *fs_path,
- struct stat *stbuf)
-{
- int fd, ret;
- HandleData *data = (HandleData *) fs_ctx->private;
-
- fd = open_by_handle(data->mountfd, fs_path->data, O_PATH);
- if (fd < 0) {
- return fd;
- }
- ret = fstatat(fd, "", stbuf, AT_EMPTY_PATH);
- close(fd);
- return ret;
-}
-
-static ssize_t handle_readlink(FsContext *fs_ctx, V9fsPath *fs_path,
- char *buf, size_t bufsz)
-{
- int fd, ret;
- HandleData *data = (HandleData *) fs_ctx->private;
-
- fd = open_by_handle(data->mountfd, fs_path->data, O_PATH);
- if (fd < 0) {
- return fd;
- }
- ret = readlinkat(fd, "", buf, bufsz);
- close(fd);
- return ret;
-}
-
-static int handle_close(FsContext *ctx, V9fsFidOpenState *fs)
-{
- return close(fs->fd);
-}
-
-static int handle_closedir(FsContext *ctx, V9fsFidOpenState *fs)
-{
- return closedir(fs->dir.stream);
-}
-
-static int handle_open(FsContext *ctx, V9fsPath *fs_path,
- int flags, V9fsFidOpenState *fs)
-{
- HandleData *data = (HandleData *) ctx->private;
-
- fs->fd = open_by_handle(data->mountfd, fs_path->data, flags);
- return fs->fd;
-}
-
-static int handle_opendir(FsContext *ctx,
- V9fsPath *fs_path, V9fsFidOpenState *fs)
-{
- int ret;
- ret = handle_open(ctx, fs_path, O_DIRECTORY, fs);
- if (ret < 0) {
- return -1;
- }
- fs->dir.stream = fdopendir(ret);
- if (!fs->dir.stream) {
- return -1;
- }
- return 0;
-}
-
-static void handle_rewinddir(FsContext *ctx, V9fsFidOpenState *fs)
-{
- rewinddir(fs->dir.stream);
-}
-
-static off_t handle_telldir(FsContext *ctx, V9fsFidOpenState *fs)
-{
- return telldir(fs->dir.stream);
-}
-
-static struct dirent *handle_readdir(FsContext *ctx, V9fsFidOpenState *fs)
-{
- return readdir(fs->dir.stream);
-}
-
-static void handle_seekdir(FsContext *ctx, V9fsFidOpenState *fs, off_t off)
-{
- seekdir(fs->dir.stream, off);
-}
-
-static ssize_t handle_preadv(FsContext *ctx, V9fsFidOpenState *fs,
- const struct iovec *iov,
- int iovcnt, off_t offset)
-{
-#ifdef CONFIG_PREADV
- return preadv(fs->fd, iov, iovcnt, offset);
-#else
- int err = lseek(fs->fd, offset, SEEK_SET);
- if (err == -1) {
- return err;
- } else {
- return readv(fs->fd, iov, iovcnt);
- }
-#endif
-}
-
-static ssize_t handle_pwritev(FsContext *ctx, V9fsFidOpenState *fs,
- const struct iovec *iov,
- int iovcnt, off_t offset)
-{
- ssize_t ret;
-#ifdef CONFIG_PREADV
- ret = pwritev(fs->fd, iov, iovcnt, offset);
-#else
- int err = lseek(fs->fd, offset, SEEK_SET);
- if (err == -1) {
- return err;
- } else {
- ret = writev(fs->fd, iov, iovcnt);
- }
-#endif
-#ifdef CONFIG_SYNC_FILE_RANGE
- if (ret > 0 && ctx->export_flags & V9FS_IMMEDIATE_WRITEOUT) {
- /*
- * Initiate a writeback. This is not a data integrity sync.
- * We want to ensure that we don't leave dirty pages in the cache
- * after write when writeout=immediate is sepcified.
- */
- sync_file_range(fs->fd, offset, ret,
- SYNC_FILE_RANGE_WAIT_BEFORE | SYNC_FILE_RANGE_WRITE);
- }
-#endif
- return ret;
-}
-
-static int handle_chmod(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
-{
- int fd, ret;
- HandleData *data = (HandleData *) fs_ctx->private;
-
- fd = open_by_handle(data->mountfd, fs_path->data, O_NONBLOCK);
- if (fd < 0) {
- return fd;
- }
- ret = fchmod(fd, credp->fc_mode);
- close(fd);
- return ret;
-}
-
-static int handle_mknod(FsContext *fs_ctx, V9fsPath *dir_path,
- const char *name, FsCred *credp)
-{
- int dirfd, ret;
- HandleData *data = (HandleData *) fs_ctx->private;
-
- dirfd = open_by_handle(data->mountfd, dir_path->data, O_PATH);
- if (dirfd < 0) {
- return dirfd;
- }
- ret = mknodat(dirfd, name, credp->fc_mode, credp->fc_rdev);
- if (!ret) {
- ret = handle_update_file_cred(dirfd, name, credp);
- }
- close(dirfd);
- return ret;
-}
-
-static int handle_mkdir(FsContext *fs_ctx, V9fsPath *dir_path,
- const char *name, FsCred *credp)
-{
- int dirfd, ret;
- HandleData *data = (HandleData *) fs_ctx->private;
-
- dirfd = open_by_handle(data->mountfd, dir_path->data, O_PATH);
- if (dirfd < 0) {
- return dirfd;
- }
- ret = mkdirat(dirfd, name, credp->fc_mode);
- if (!ret) {
- ret = handle_update_file_cred(dirfd, name, credp);
- }
- close(dirfd);
- return ret;
-}
-
-static int handle_fstat(FsContext *fs_ctx, int fid_type,
- V9fsFidOpenState *fs, struct stat *stbuf)
-{
- int fd;
-
- if (fid_type == P9_FID_DIR) {
- fd = dirfd(fs->dir.stream);
- } else {
- fd = fs->fd;
- }
- return fstat(fd, stbuf);
-}
-
-static int handle_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name,
- int flags, FsCred *credp, V9fsFidOpenState *fs)
-{
- int ret;
- int dirfd, fd;
- HandleData *data = (HandleData *) fs_ctx->private;
-
- dirfd = open_by_handle(data->mountfd, dir_path->data, O_PATH);
- if (dirfd < 0) {
- return dirfd;
- }
- fd = openat(dirfd, name, flags | O_NOFOLLOW, credp->fc_mode);
- if (fd >= 0) {
- ret = handle_update_file_cred(dirfd, name, credp);
- if (ret < 0) {
- close(fd);
- fd = ret;
- } else {
- fs->fd = fd;
- }
- }
- close(dirfd);
- return fd;
-}
-
-
-static int handle_symlink(FsContext *fs_ctx, const char *oldpath,
- V9fsPath *dir_path, const char *name, FsCred *credp)
-{
- int fd, dirfd, ret;
- HandleData *data = (HandleData *) fs_ctx->private;
-
- dirfd = open_by_handle(data->mountfd, dir_path->data, O_PATH);
- if (dirfd < 0) {
- return dirfd;
- }
- ret = symlinkat(oldpath, dirfd, name);
- if (!ret) {
- fd = openat(dirfd, name, O_PATH | O_NOFOLLOW);
- if (fd < 0) {
- ret = fd;
- goto err_out;
- }
- ret = fchownat(fd, "", credp->fc_uid, credp->fc_gid, AT_EMPTY_PATH);
- close(fd);
- }
-err_out:
- close(dirfd);
- return ret;
-}
-
-static int handle_link(FsContext *ctx, V9fsPath *oldpath,
- V9fsPath *dirpath, const char *name)
-{
- int oldfd, newdirfd, ret;
- HandleData *data = (HandleData *) ctx->private;
-
- oldfd = open_by_handle(data->mountfd, oldpath->data, O_PATH);
- if (oldfd < 0) {
- return oldfd;
- }
- newdirfd = open_by_handle(data->mountfd, dirpath->data, O_PATH);
- if (newdirfd < 0) {
- close(oldfd);
- return newdirfd;
- }
- ret = linkat(oldfd, "", newdirfd, name, AT_EMPTY_PATH);
- close(newdirfd);
- close(oldfd);
- return ret;
-}
-
-static int handle_truncate(FsContext *ctx, V9fsPath *fs_path, off_t size)
-{
- int fd, ret;
- HandleData *data = (HandleData *) ctx->private;
-
- fd = open_by_handle(data->mountfd, fs_path->data, O_NONBLOCK | O_WRONLY);
- if (fd < 0) {
- return fd;
- }
- ret = ftruncate(fd, size);
- close(fd);
- return ret;
-}
-
-static int handle_rename(FsContext *ctx, const char *oldpath,
- const char *newpath)
-{
- errno = EOPNOTSUPP;
- return -1;
-}
-
-static int handle_chown(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
-{
- int fd, ret;
- HandleData *data = (HandleData *) fs_ctx->private;
-
- fd = open_by_handle(data->mountfd, fs_path->data, O_PATH);
- if (fd < 0) {
- return fd;
- }
- ret = fchownat(fd, "", credp->fc_uid, credp->fc_gid, AT_EMPTY_PATH);
- close(fd);
- return ret;
-}
-
-static int handle_utimensat(FsContext *ctx, V9fsPath *fs_path,
- const struct timespec *buf)
-{
- int ret;
- int fd;
- HandleData *data = (HandleData *) ctx->private;
-
- fd = open_by_handle(data->mountfd, fs_path->data, O_NONBLOCK);
- if (fd < 0) {
- return fd;
- }
- ret = futimens(fd, buf);
- close(fd);
- return ret;
-}
-
-static int handle_remove(FsContext *ctx, const char *path)
-{
- errno = EOPNOTSUPP;
- return -1;
-}
-
-static int handle_fsync(FsContext *ctx, int fid_type,
- V9fsFidOpenState *fs, int datasync)
-{
- int fd;
-
- if (fid_type == P9_FID_DIR) {
- fd = dirfd(fs->dir.stream);
- } else {
- fd = fs->fd;
- }
-
- if (datasync) {
- return qemu_fdatasync(fd);
- } else {
- return fsync(fd);
- }
-}
-
-static int handle_statfs(FsContext *ctx, V9fsPath *fs_path,
- struct statfs *stbuf)
-{
- int fd, ret;
- HandleData *data = (HandleData *) ctx->private;
-
- fd = open_by_handle(data->mountfd, fs_path->data, O_NONBLOCK);
- if (fd < 0) {
- return fd;
- }
- ret = fstatfs(fd, stbuf);
- close(fd);
- return ret;
-}
-
-static ssize_t handle_lgetxattr(FsContext *ctx, V9fsPath *fs_path,
- const char *name, void *value, size_t size)
-{
- int fd, ret;
- HandleData *data = (HandleData *) ctx->private;
-
- fd = open_by_handle(data->mountfd, fs_path->data, O_NONBLOCK);
- if (fd < 0) {
- return fd;
- }
- ret = fgetxattr(fd, name, value, size);
- close(fd);
- return ret;
-}
-
-static ssize_t handle_llistxattr(FsContext *ctx, V9fsPath *fs_path,
- void *value, size_t size)
-{
- int fd, ret;
- HandleData *data = (HandleData *) ctx->private;
-
- fd = open_by_handle(data->mountfd, fs_path->data, O_NONBLOCK);
- if (fd < 0) {
- return fd;
- }
- ret = flistxattr(fd, value, size);
- close(fd);
- return ret;
-}
-
-static int handle_lsetxattr(FsContext *ctx, V9fsPath *fs_path, const char *name,
- void *value, size_t size, int flags)
-{
- int fd, ret;
- HandleData *data = (HandleData *) ctx->private;
-
- fd = open_by_handle(data->mountfd, fs_path->data, O_NONBLOCK);
- if (fd < 0) {
- return fd;
- }
- ret = fsetxattr(fd, name, value, size, flags);
- close(fd);
- return ret;
-}
-
-static int handle_lremovexattr(FsContext *ctx, V9fsPath *fs_path,
- const char *name)
-{
- int fd, ret;
- HandleData *data = (HandleData *) ctx->private;
-
- fd = open_by_handle(data->mountfd, fs_path->data, O_NONBLOCK);
- if (fd < 0) {
- return fd;
- }
- ret = fremovexattr(fd, name);
- close(fd);
- return ret;
-}
-
-static int handle_name_to_path(FsContext *ctx, V9fsPath *dir_path,
- const char *name, V9fsPath *target)
-{
- char *buffer;
- struct file_handle *fh;
- int dirfd, ret, mnt_id;
- HandleData *data = (HandleData *) ctx->private;
-
- /* "." and ".." are not allowed */
- if (!strcmp(name, ".") || !strcmp(name, "..")) {
- errno = EINVAL;
- return -1;
-
- }
- if (dir_path) {
- dirfd = open_by_handle(data->mountfd, dir_path->data, O_PATH);
- } else {
- /* relative to export root */
- buffer = rpath(ctx, ".");
- dirfd = open(buffer, O_DIRECTORY);
- g_free(buffer);
- }
- if (dirfd < 0) {
- return dirfd;
- }
- fh = g_malloc(sizeof(struct file_handle) + data->handle_bytes);
- fh->handle_bytes = data->handle_bytes;
- /* add a "./" at the beginning of the path */
- buffer = g_strdup_printf("./%s", name);
- /* flag = 0 imply don't follow symlink */
- ret = name_to_handle(dirfd, buffer, fh, &mnt_id, 0);
- if (!ret) {
- target->data = (char *)fh;
- target->size = sizeof(struct file_handle) + data->handle_bytes;
- } else {
- g_free(fh);
- }
- close(dirfd);
- g_free(buffer);
- return ret;
-}
-
-static int handle_renameat(FsContext *ctx, V9fsPath *olddir,
- const char *old_name, V9fsPath *newdir,
- const char *new_name)
-{
- int olddirfd, newdirfd, ret;
- HandleData *data = (HandleData *) ctx->private;
-
- olddirfd = open_by_handle(data->mountfd, olddir->data, O_PATH);
- if (olddirfd < 0) {
- return olddirfd;
- }
- newdirfd = open_by_handle(data->mountfd, newdir->data, O_PATH);
- if (newdirfd < 0) {
- close(olddirfd);
- return newdirfd;
- }
- ret = renameat(olddirfd, old_name, newdirfd, new_name);
- close(newdirfd);
- close(olddirfd);
- return ret;
-}
-
-static int handle_unlinkat(FsContext *ctx, V9fsPath *dir,
- const char *name, int flags)
-{
- int dirfd, ret;
- HandleData *data = (HandleData *) ctx->private;
-
- dirfd = open_by_handle(data->mountfd, dir->data, O_PATH);
- if (dirfd < 0) {
- return dirfd;
- }
-
- ret = unlinkat(dirfd, name, flags);
-
- close(dirfd);
- return ret;
-}
-
-static int handle_ioc_getversion(FsContext *ctx, V9fsPath *path,
- mode_t st_mode, uint64_t *st_gen)
-{
-#ifdef FS_IOC_GETVERSION
- int err;
- V9fsFidOpenState fid_open;
-
- /*
- * Do not try to open special files like device nodes, fifos etc
- * We can get fd for regular files and directories only
- */
- if (!S_ISREG(st_mode) && !S_ISDIR(st_mode)) {
- errno = ENOTTY;
- return -1;
- }
- err = handle_open(ctx, path, O_RDONLY, &fid_open);
- if (err < 0) {
- return err;
- }
- err = ioctl(fid_open.fd, FS_IOC_GETVERSION, st_gen);
- handle_close(ctx, &fid_open);
- return err;
-#else
- errno = ENOTTY;
- return -1;
-#endif
-}
-
-static int handle_init(FsContext *ctx, Error **errp)
-{
- int ret, mnt_id;
- struct statfs stbuf;
- struct file_handle fh;
- HandleData *data = g_malloc(sizeof(HandleData));
-
- data->mountfd = open(ctx->fs_root, O_DIRECTORY);
- if (data->mountfd < 0) {
- ret = data->mountfd;
- goto err_out;
- }
- ret = statfs(ctx->fs_root, &stbuf);
- if (!ret) {
- switch (stbuf.f_type) {
- case EXT2_SUPER_MAGIC:
- case BTRFS_SUPER_MAGIC:
- case REISERFS_SUPER_MAGIC:
- case XFS_SUPER_MAGIC:
- ctx->exops.get_st_gen = handle_ioc_getversion;
- break;
- }
- }
- memset(&fh, 0, sizeof(struct file_handle));
- ret = name_to_handle(data->mountfd, ".", &fh, &mnt_id, 0);
- if (ret && errno == EOVERFLOW) {
- data->handle_bytes = fh.handle_bytes;
- ctx->private = data;
- ret = 0;
- goto out;
- }
- /* we got 0 byte handle ? */
- ret = -1;
- close(data->mountfd);
-err_out:
- g_free(data);
-out:
- return ret;
-}
-
-static void handle_cleanup(FsContext *ctx)
-{
- HandleData *data = ctx->private;
-
- close(data->mountfd);
- g_free(data);
-}
-
-static int handle_parse_opts(QemuOpts *opts, FsDriverEntry *fse, Error **errp)
-{
- const char *sec_model = qemu_opt_get(opts, "security_model");
- const char *path = qemu_opt_get(opts, "path");
-
- warn_report("handle backend is deprecated");
-
- if (sec_model) {
- error_setg(errp,
- "Invalid argument security_model specified with handle fsdriver");
- return -1;
- }
-
- if (!path) {
- error_setg(errp, "fsdev: No path specified");
- return -1;
- }
- fse->path = g_strdup(path);
- return 0;
-
-}
-
-FileOperations handle_ops = {
- .parse_opts = handle_parse_opts,
- .init = handle_init,
- .cleanup = handle_cleanup,
- .lstat = handle_lstat,
- .readlink = handle_readlink,
- .close = handle_close,
- .closedir = handle_closedir,
- .open = handle_open,
- .opendir = handle_opendir,
- .rewinddir = handle_rewinddir,
- .telldir = handle_telldir,
- .readdir = handle_readdir,
- .seekdir = handle_seekdir,
- .preadv = handle_preadv,
- .pwritev = handle_pwritev,
- .chmod = handle_chmod,
- .mknod = handle_mknod,
- .mkdir = handle_mkdir,
- .fstat = handle_fstat,
- .open2 = handle_open2,
- .symlink = handle_symlink,
- .link = handle_link,
- .truncate = handle_truncate,
- .rename = handle_rename,
- .chown = handle_chown,
- .utimensat = handle_utimensat,
- .remove = handle_remove,
- .fsync = handle_fsync,
- .statfs = handle_statfs,
- .lgetxattr = handle_lgetxattr,
- .llistxattr = handle_llistxattr,
- .lsetxattr = handle_lsetxattr,
- .lremovexattr = handle_lremovexattr,
- .name_to_path = handle_name_to_path,
- .renameat = handle_renameat,
- .unlinkat = handle_unlinkat,
-};
diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c
index bdf7919abf..55821343e5 100644
--- a/hw/9pfs/9p.c
+++ b/hw/9pfs/9p.c
@@ -1331,8 +1331,8 @@ static void coroutine_fn v9fs_walk(void *opaque)
trace_v9fs_walk(pdu->tag, pdu->id, fid, newfid, nwnames);
if (nwnames && nwnames <= P9_MAXWELEM) {
- wnames = g_malloc0(sizeof(wnames[0]) * nwnames);
- qids = g_malloc0(sizeof(qids[0]) * nwnames);
+ wnames = g_new0(V9fsString, nwnames);
+ qids = g_new0(V9fsQID, nwnames);
for (i = 0; i < nwnames; i++) {
err = pdu_unmarshal(pdu, offset, "s", &wnames[i]);
if (err < 0) {
diff --git a/hw/9pfs/Makefile.objs b/hw/9pfs/Makefile.objs
index e3fa673665..8ac04962bd 100644
--- a/hw/9pfs/Makefile.objs
+++ b/hw/9pfs/Makefile.objs
@@ -4,7 +4,6 @@ common-obj-y += 9p-local.o 9p-xattr.o
common-obj-y += 9p-xattr-user.o 9p-posix-acl.o
common-obj-y += coth.o cofs.o codir.o cofile.o
common-obj-y += coxattr.o 9p-synth.o
-common-obj-$(CONFIG_OPEN_BY_HANDLE) += 9p-handle.o
common-obj-y += 9p-proxy.o
endif
diff --git a/hw/9pfs/xen-9p-backend.c b/hw/9pfs/xen-9p-backend.c
index 3f54a21c76..9015fe7773 100644
--- a/hw/9pfs/xen-9p-backend.c
+++ b/hw/9pfs/xen-9p-backend.c
@@ -178,7 +178,7 @@ static void xen_9pfs_init_out_iov_from_pdu(V9fsPDU *pdu,
g_free(ring->sg);
- ring->sg = g_malloc0(sizeof(*ring->sg) * 2);
+ ring->sg = g_new0(struct iovec, 2);
xen_9pfs_out_sg(ring, ring->sg, &num, pdu->idx);
*piov = ring->sg;
*pniov = num;
@@ -196,7 +196,7 @@ static void xen_9pfs_init_in_iov_from_pdu(V9fsPDU *pdu,
g_free(ring->sg);
- ring->sg = g_malloc0(sizeof(*ring->sg) * 2);
+ ring->sg = g_new0(struct iovec, 2);
xen_9pfs_in_sg(ring, ring->sg, &num, pdu->idx, size);
buf_size = iov_size(ring->sg, num);
@@ -368,7 +368,7 @@ static int xen_9pfs_connect(struct XenDevice *xendev)
return -1;
}
- xen_9pdev->rings = g_malloc0(xen_9pdev->num_rings * sizeof(Xen9pfsRing));
+ xen_9pdev->rings = g_new0(Xen9pfsRing, xen_9pdev->num_rings);
for (i = 0; i < xen_9pdev->num_rings; i++) {
char *str;
int ring_order;
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
index 586baa9b64..94fce12802 100644
--- a/hw/arm/boot.c
+++ b/hw/arm/boot.c
@@ -63,8 +63,10 @@ typedef enum {
FIXUP_TERMINATOR, /* end of insns */
FIXUP_BOARDID, /* overwrite with board ID number */
FIXUP_BOARD_SETUP, /* overwrite with board specific setup code address */
- FIXUP_ARGPTR, /* overwrite with pointer to kernel args */
- FIXUP_ENTRYPOINT, /* overwrite with kernel entry point */
+ FIXUP_ARGPTR_LO, /* overwrite with pointer to kernel args */
+ FIXUP_ARGPTR_HI, /* overwrite with pointer to kernel args (high half) */
+ FIXUP_ENTRYPOINT_LO, /* overwrite with kernel entry point */
+ FIXUP_ENTRYPOINT_HI, /* overwrite with kernel entry point (high half) */
FIXUP_GIC_CPU_IF, /* overwrite with GIC CPU interface address */
FIXUP_BOOTREG, /* overwrite with boot register address */
FIXUP_DSB, /* overwrite with correct DSB insn for cpu */
@@ -83,10 +85,10 @@ static const ARMInsnFixup bootloader_aarch64[] = {
{ 0xaa1f03e3 }, /* mov x3, xzr */
{ 0x58000084 }, /* ldr x4, entry ; Load the lower 32-bits of kernel entry */
{ 0xd61f0080 }, /* br x4 ; Jump to the kernel entry point */
- { 0, FIXUP_ARGPTR }, /* arg: .word @DTB Lower 32-bits */
- { 0 }, /* .word @DTB Higher 32-bits */
- { 0, FIXUP_ENTRYPOINT }, /* entry: .word @Kernel Entry Lower 32-bits */
- { 0 }, /* .word @Kernel Entry Higher 32-bits */
+ { 0, FIXUP_ARGPTR_LO }, /* arg: .word @DTB Lower 32-bits */
+ { 0, FIXUP_ARGPTR_HI}, /* .word @DTB Higher 32-bits */
+ { 0, FIXUP_ENTRYPOINT_LO }, /* entry: .word @Kernel Entry Lower 32-bits */
+ { 0, FIXUP_ENTRYPOINT_HI }, /* .word @Kernel Entry Higher 32-bits */
{ 0, FIXUP_TERMINATOR }
};
@@ -106,8 +108,8 @@ static const ARMInsnFixup bootloader[] = {
{ 0xe59f2004 }, /* ldr r2, [pc, #4] */
{ 0xe59ff004 }, /* ldr pc, [pc, #4] */
{ 0, FIXUP_BOARDID },
- { 0, FIXUP_ARGPTR },
- { 0, FIXUP_ENTRYPOINT },
+ { 0, FIXUP_ARGPTR_LO },
+ { 0, FIXUP_ENTRYPOINT_LO },
{ 0, FIXUP_TERMINATOR }
};
@@ -174,8 +176,10 @@ static void write_bootloader(const char *name, hwaddr addr,
break;
case FIXUP_BOARDID:
case FIXUP_BOARD_SETUP:
- case FIXUP_ARGPTR:
- case FIXUP_ENTRYPOINT:
+ case FIXUP_ARGPTR_LO:
+ case FIXUP_ARGPTR_HI:
+ case FIXUP_ENTRYPOINT_LO:
+ case FIXUP_ENTRYPOINT_HI:
case FIXUP_GIC_CPU_IF:
case FIXUP_BOOTREG:
case FIXUP_DSB:
@@ -1152,9 +1156,13 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
/* Place the DTB after the initrd in memory with alignment. */
info->dtb_start = QEMU_ALIGN_UP(info->initrd_start + initrd_size,
align);
- fixupcontext[FIXUP_ARGPTR] = info->dtb_start;
+ fixupcontext[FIXUP_ARGPTR_LO] = info->dtb_start;
+ fixupcontext[FIXUP_ARGPTR_HI] = info->dtb_start >> 32;
} else {
- fixupcontext[FIXUP_ARGPTR] = info->loader_start + KERNEL_ARGS_ADDR;
+ fixupcontext[FIXUP_ARGPTR_LO] =
+ info->loader_start + KERNEL_ARGS_ADDR;
+ fixupcontext[FIXUP_ARGPTR_HI] =
+ (info->loader_start + KERNEL_ARGS_ADDR) >> 32;
if (info->ram_size >= (1ULL << 32)) {
error_report("RAM size must be less than 4GB to boot"
" Linux kernel using ATAGS (try passing a device tree"
@@ -1162,7 +1170,8 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
exit(1);
}
}
- fixupcontext[FIXUP_ENTRYPOINT] = entry;
+ fixupcontext[FIXUP_ENTRYPOINT_LO] = entry;
+ fixupcontext[FIXUP_ENTRYPOINT_HI] = entry >> 32;
write_bootloader("bootloader", info->loader_start,
primary_loader, fixupcontext, as);
diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c
index 9648b3af44..d22532a11c 100644
--- a/hw/arm/musicpal.c
+++ b/hw/arm/musicpal.c
@@ -1147,14 +1147,13 @@ static const MemoryRegionOps mv88w8618_wlan_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
-static int mv88w8618_wlan_init(SysBusDevice *dev)
+static void mv88w8618_wlan_realize(DeviceState *dev, Error **errp)
{
MemoryRegion *iomem = g_new(MemoryRegion, 1);
memory_region_init_io(iomem, OBJECT(dev), &mv88w8618_wlan_ops, NULL,
"musicpal-wlan", MP_WLAN_SIZE);
- sysbus_init_mmio(dev, iomem);
- return 0;
+ sysbus_init_mmio(SYS_BUS_DEVICE(dev), iomem);
}
/* GPIO register offsets */
@@ -1696,7 +1695,7 @@ static void musicpal_init(MachineState *machine)
dev = qdev_create(NULL, TYPE_MV88W8618_AUDIO);
s = SYS_BUS_DEVICE(dev);
object_property_set_link(OBJECT(dev), OBJECT(wm8750_dev),
- TYPE_WM8750, NULL);
+ "wm8750", NULL);
qdev_init_nofail(dev);
sysbus_mmio_map(s, 0, MP_AUDIO_BASE);
sysbus_connect_irq(s, 0, pic[MP_AUDIO_IRQ]);
@@ -1720,9 +1719,9 @@ DEFINE_MACHINE("musicpal", musicpal_machine_init)
static void mv88w8618_wlan_class_init(ObjectClass *klass, void *data)
{
- SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+ DeviceClass *dc = DEVICE_CLASS(klass);
- sdc->init = mv88w8618_wlan_init;
+ dc->realize = mv88w8618_wlan_realize;
}
static const TypeInfo mv88w8618_wlan_info = {
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index f69e7eb399..17f1b49d11 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -74,7 +74,6 @@
static const TypeInfo machvirt_##major##_##minor##_info = { \
.name = MACHINE_TYPE_NAME("virt-" # major "." # minor), \
.parent = TYPE_VIRT_MACHINE, \
- .instance_init = virt_##major##_##minor##_instance_init, \
.class_init = virt_##major##_##minor##_class_init, \
}; \
static void machvirt_machine_##major##_##minor##_init(void) \
@@ -1778,26 +1777,7 @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
hc->plug = virt_machine_device_plug_cb;
}
-static const TypeInfo virt_machine_info = {
- .name = TYPE_VIRT_MACHINE,
- .parent = TYPE_MACHINE,
- .abstract = true,
- .instance_size = sizeof(VirtMachineState),
- .class_size = sizeof(VirtMachineClass),
- .class_init = virt_machine_class_init,
- .interfaces = (InterfaceInfo[]) {
- { TYPE_HOTPLUG_HANDLER },
- { }
- },
-};
-
-static void machvirt_machine_init(void)
-{
- type_register_static(&virt_machine_info);
-}
-type_init(machvirt_machine_init);
-
-static void virt_3_1_instance_init(Object *obj)
+static void virt_instance_init(Object *obj)
{
VirtMachineState *vms = VIRT_MACHINE(obj);
VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
@@ -1867,18 +1847,43 @@ static void virt_3_1_instance_init(Object *obj)
vms->irqmap = a15irqmap;
}
-static void virt_machine_3_1_options(MachineClass *mc)
+static const TypeInfo virt_machine_info = {
+ .name = TYPE_VIRT_MACHINE,
+ .parent = TYPE_MACHINE,
+ .abstract = true,
+ .instance_size = sizeof(VirtMachineState),
+ .class_size = sizeof(VirtMachineClass),
+ .class_init = virt_machine_class_init,
+ .instance_init = virt_instance_init,
+ .interfaces = (InterfaceInfo[]) {
+ { TYPE_HOTPLUG_HANDLER },
+ { }
+ },
+};
+
+static void machvirt_machine_init(void)
{
+ type_register_static(&virt_machine_info);
}
-DEFINE_VIRT_MACHINE_AS_LATEST(3, 1)
+type_init(machvirt_machine_init);
-#define VIRT_COMPAT_3_0 \
- HW_COMPAT_3_0
+static void virt_machine_4_0_options(MachineClass *mc)
+{
+}
+DEFINE_VIRT_MACHINE_AS_LATEST(4, 0)
-static void virt_3_0_instance_init(Object *obj)
+#define VIRT_COMPAT_3_1 \
+ HW_COMPAT_3_1
+
+static void virt_machine_3_1_options(MachineClass *mc)
{
- virt_3_1_instance_init(obj);
+ virt_machine_4_0_options(mc);
+ SET_MACHINE_COMPAT(mc, VIRT_COMPAT_3_1);
}
+DEFINE_VIRT_MACHINE(3, 1)
+
+#define VIRT_COMPAT_3_0 \
+ HW_COMPAT_3_0
static void virt_machine_3_0_options(MachineClass *mc)
{
@@ -1890,11 +1895,6 @@ DEFINE_VIRT_MACHINE(3, 0)
#define VIRT_COMPAT_2_12 \
HW_COMPAT_2_12
-static void virt_2_12_instance_init(Object *obj)
-{
- virt_3_0_instance_init(obj);
-}
-
static void virt_machine_2_12_options(MachineClass *mc)
{
VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc));
@@ -1909,11 +1909,6 @@ DEFINE_VIRT_MACHINE(2, 12)
#define VIRT_COMPAT_2_11 \
HW_COMPAT_2_11
-static void virt_2_11_instance_init(Object *obj)
-{
- virt_2_12_instance_init(obj);
-}
-
static void virt_machine_2_11_options(MachineClass *mc)
{
VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc));
@@ -1927,11 +1922,6 @@ DEFINE_VIRT_MACHINE(2, 11)
#define VIRT_COMPAT_2_10 \
HW_COMPAT_2_10
-static void virt_2_10_instance_init(Object *obj)
-{
- virt_2_11_instance_init(obj);
-}
-
static void virt_machine_2_10_options(MachineClass *mc)
{
virt_machine_2_11_options(mc);
@@ -1944,11 +1934,6 @@ DEFINE_VIRT_MACHINE(2, 10)
#define VIRT_COMPAT_2_9 \
HW_COMPAT_2_9
-static void virt_2_9_instance_init(Object *obj)
-{
- virt_2_10_instance_init(obj);
-}
-
static void virt_machine_2_9_options(MachineClass *mc)
{
virt_machine_2_10_options(mc);
@@ -1959,11 +1944,6 @@ DEFINE_VIRT_MACHINE(2, 9)
#define VIRT_COMPAT_2_8 \
HW_COMPAT_2_8
-static void virt_2_8_instance_init(Object *obj)
-{
- virt_2_9_instance_init(obj);
-}
-
static void virt_machine_2_8_options(MachineClass *mc)
{
VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc));
@@ -1980,11 +1960,6 @@ DEFINE_VIRT_MACHINE(2, 8)
#define VIRT_COMPAT_2_7 \
HW_COMPAT_2_7
-static void virt_2_7_instance_init(Object *obj)
-{
- virt_2_8_instance_init(obj);
-}
-
static void virt_machine_2_7_options(MachineClass *mc)
{
VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc));
@@ -2001,11 +1976,6 @@ DEFINE_VIRT_MACHINE(2, 7)
#define VIRT_COMPAT_2_6 \
HW_COMPAT_2_6
-static void virt_2_6_instance_init(Object *obj)
-{
- virt_2_7_instance_init(obj);
-}
-
static void virt_machine_2_6_options(MachineClass *mc)
{
VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc));
diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
index 1e31a3f442..c6feeac532 100644
--- a/hw/arm/xlnx-versal-virt.c
+++ b/hw/arm/xlnx-versal-virt.c
@@ -342,7 +342,7 @@ static void *versal_virt_get_dtb(const struct arm_boot_info *binfo,
return board->fdt;
}
-#define NUM_VIRTIO_TRANSPORT 32
+#define NUM_VIRTIO_TRANSPORT 8
static void create_virtio_regions(VersalVirt *s)
{
int virtio_mmio_size = 0x200;
@@ -351,7 +351,7 @@ static void create_virtio_regions(VersalVirt *s)
for (i = 0; i < NUM_VIRTIO_TRANSPORT; i++) {
char *name = g_strdup_printf("virtio%d", i);;
hwaddr base = MM_TOP_RSVD + i * virtio_mmio_size;
- int irq = VERSAL_RSVD_HIGH_IRQ_FIRST + i;
+ int irq = VERSAL_RSVD_IRQ_FIRST + i;
MemoryRegion *mr;
DeviceState *dev;
qemu_irq pic_irq;
@@ -364,12 +364,11 @@ static void create_virtio_regions(VersalVirt *s)
sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic_irq);
mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
memory_region_add_subregion(&s->soc.mr_ps, base, mr);
- sysbus_create_simple("virtio-mmio", base, pic_irq);
}
for (i = 0; i < NUM_VIRTIO_TRANSPORT; i++) {
hwaddr base = MM_TOP_RSVD + i * virtio_mmio_size;
- int irq = VERSAL_RSVD_HIGH_IRQ_FIRST + i;
+ int irq = VERSAL_RSVD_IRQ_FIRST + i;
char *name = g_strdup_printf("/virtio_mmio@%" PRIx64, base);
qemu_fdt_add_subnode(s->fdt, name);
diff --git a/hw/block/onenand.c b/hw/block/onenand.c
index 2b48609776..f11118a687 100644
--- a/hw/block/onenand.c
+++ b/hw/block/onenand.c
@@ -772,9 +772,9 @@ static const MemoryRegionOps onenand_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
-static int onenand_initfn(SysBusDevice *sbd)
+static void onenand_realize(DeviceState *dev, Error **errp)
{
- DeviceState *dev = DEVICE(sbd);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
OneNANDState *s = ONE_NAND(dev);
uint32_t size = 1 << (24 + ((s->id.dev >> 4) & 7));
void *ram;
@@ -794,14 +794,14 @@ static int onenand_initfn(SysBusDevice *sbd)
0xff, size + (size >> 5));
} else {
if (blk_is_read_only(s->blk)) {
- error_report("Can't use a read-only drive");
- return -1;
+ error_setg(errp, "Can't use a read-only drive");
+ return;
}
blk_set_perm(s->blk, BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE,
BLK_PERM_ALL, &local_err);
if (local_err) {
- error_report_err(local_err);
- return -1;
+ error_propagate(errp, local_err);
+ return;
}
s->blk_cur = s->blk;
}
@@ -826,7 +826,6 @@ static int onenand_initfn(SysBusDevice *sbd)
| ((s->id.dev & 0xff) << 8)
| (s->id.ver & 0xff),
&vmstate_onenand, s);
- return 0;
}
static Property onenand_properties[] = {
@@ -841,9 +840,8 @@ static Property onenand_properties[] = {
static void onenand_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
- SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
- k->init = onenand_initfn;
+ dc->realize = onenand_realize;
dc->reset = onenand_system_reset;
dc->props = onenand_properties;
}
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
index 83cf5c01f9..f208c6ddb9 100644
--- a/hw/block/virtio-blk.c
+++ b/hw/block/virtio-blk.c
@@ -96,7 +96,7 @@ static void virtio_blk_rw_complete(void *opaque, int ret)
trace_virtio_blk_rw_complete(vdev, req, ret);
if (req->qiov.nalloc != -1) {
- /* If nalloc is != 1 req->qiov is a local copy of the original
+ /* If nalloc is != -1 req->qiov is a local copy of the original
* external iovec. It was allocated in submit_requests to be
* able to merge requests. */
qemu_iovec_destroy(&req->qiov);
@@ -482,7 +482,7 @@ static int virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb)
{
uint32_t type;
struct iovec *in_iov = req->elem.in_sg;
- struct iovec *iov = req->elem.out_sg;
+ struct iovec *out_iov = req->elem.out_sg;
unsigned in_num = req->elem.in_num;
unsigned out_num = req->elem.out_num;
VirtIOBlock *s = req->dev;
@@ -493,13 +493,13 @@ static int virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb)
return -1;
}
- if (unlikely(iov_to_buf(iov, out_num, 0, &req->out,
+ if (unlikely(iov_to_buf(out_iov, out_num, 0, &req->out,
sizeof(req->out)) != sizeof(req->out))) {
virtio_error(vdev, "virtio-blk request outhdr too short");
return -1;
}
- iov_discard_front(&iov, &out_num, sizeof(req->out));
+ iov_discard_front(&out_iov, &out_num, sizeof(req->out));
if (in_iov[in_num - 1].iov_len < sizeof(struct virtio_blk_inhdr)) {
virtio_error(vdev, "virtio-blk request inhdr too short");
@@ -526,7 +526,7 @@ static int virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb)
&req->out.sector);
if (is_write) {
- qemu_iovec_init_external(&req->qiov, iov, out_num);
+ qemu_iovec_init_external(&req->qiov, out_iov, out_num);
trace_virtio_blk_handle_write(vdev, req, req->sector_num,
req->qiov.size / BDRV_SECTOR_SIZE);
} else {
diff --git a/hw/char/grlib_apbuart.c b/hw/char/grlib_apbuart.c
index bac11bec58..e1d258b611 100644
--- a/hw/char/grlib_apbuart.c
+++ b/hw/char/grlib_apbuart.c
@@ -239,9 +239,10 @@ static const MemoryRegionOps grlib_apbuart_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
-static int grlib_apbuart_init(SysBusDevice *dev)
+static void grlib_apbuart_realize(DeviceState *dev, Error **errp)
{
UART *uart = GRLIB_APB_UART(dev);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
qemu_chr_fe_set_handlers(&uart->chr,
grlib_apbuart_can_receive,
@@ -249,14 +250,12 @@ static int grlib_apbuart_init(SysBusDevice *dev)
grlib_apbuart_event,
NULL, uart, NULL, true);
- sysbus_init_irq(dev, &uart->irq);
+ sysbus_init_irq(sbd, &uart->irq);
memory_region_init_io(&uart->iomem, OBJECT(uart), &grlib_apbuart_ops, uart,
"uart", UART_REG_SIZE);
- sysbus_init_mmio(dev, &uart->iomem);
-
- return 0;
+ sysbus_init_mmio(sbd, &uart->iomem);
}
static void grlib_apbuart_reset(DeviceState *d)
@@ -280,9 +279,8 @@ static Property grlib_apbuart_properties[] = {
static void grlib_apbuart_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
- SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
- k->init = grlib_apbuart_init;
+ dc->realize = grlib_apbuart_realize;
dc->reset = grlib_apbuart_reset;
dc->props = grlib_apbuart_properties;
}
diff --git a/hw/core/empty_slot.c b/hw/core/empty_slot.c
index c1b9c2b104..239f78e2a7 100644
--- a/hw/core/empty_slot.c
+++ b/hw/core/empty_slot.c
@@ -71,21 +71,20 @@ void empty_slot_init(hwaddr addr, uint64_t slot_size)
}
}
-static int empty_slot_init1(SysBusDevice *dev)
+static void empty_slot_realize(DeviceState *dev, Error **errp)
{
EmptySlot *s = EMPTY_SLOT(dev);
memory_region_init_io(&s->iomem, OBJECT(s), &empty_slot_ops, s,
"empty-slot", s->size);
- sysbus_init_mmio(dev, &s->iomem);
- return 0;
+ sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
}
static void empty_slot_class_init(ObjectClass *klass, void *data)
{
- SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+ DeviceClass *dc = DEVICE_CLASS(klass);
- k->init = empty_slot_init1;
+ dc->realize = empty_slot_realize;
}
static const TypeInfo empty_slot_info = {
diff --git a/hw/core/machine.c b/hw/core/machine.c
index da50ad6de7..c51423b647 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -834,16 +834,6 @@ void machine_run_board_init(MachineState *machine)
machine_class->init(machine);
}
-static void machine_class_finalize(ObjectClass *klass, void *data)
-{
- MachineClass *mc = MACHINE_CLASS(klass);
-
- if (mc->compat_props) {
- g_array_free(mc->compat_props, true);
- }
- g_free(mc->name);
-}
-
void machine_register_compat_props(MachineState *machine)
{
MachineClass *mc = MACHINE_GET_CLASS(machine);
@@ -869,7 +859,6 @@ static const TypeInfo machine_info = {
.class_size = sizeof(MachineClass),
.class_init = machine_class_init,
.class_base_init = machine_class_base_init,
- .class_finalize = machine_class_finalize,
.instance_size = sizeof(MachineState),
.instance_init = machine_initfn,
.instance_finalize = machine_finalize,
diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c
index 8b22fb51c9..b45a7ef54b 100644
--- a/hw/core/qdev-properties-system.c
+++ b/hw/core/qdev-properties-system.c
@@ -288,10 +288,6 @@ static void set_netdev(Object *obj, Visitor *v, const char *name,
}
for (i = 0; i < queues; i++) {
- if (peers[i] == NULL) {
- err = -ENOENT;
- goto out;
- }
if (peers[i]->peer) {
err = -EEXIST;
diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c
index 35072dec1e..bd84c4ea4c 100644
--- a/hw/core/qdev-properties.c
+++ b/hw/core/qdev-properties.c
@@ -1180,36 +1180,6 @@ void qdev_prop_register_global(GlobalProperty *prop)
global_props = g_list_append(global_props, prop);
}
-void register_compat_prop(const char *driver,
- const char *property,
- const char *value)
-{
- GlobalProperty *p = g_new0(GlobalProperty, 1);
-
- /* Any compat_props must never cause error */
- p->errp = &error_abort;
- p->driver = driver;
- p->property = property;
- p->value = value;
- qdev_prop_register_global(p);
-}
-
-void register_compat_props_array(GlobalProperty *prop)
-{
- for (; prop && prop->driver; prop++) {
- register_compat_prop(prop->driver, prop->property, prop->value);
- }
-}
-
-void qdev_prop_register_global_list(GlobalProperty *props)
-{
- int i;
-
- for (i = 0; props[i].driver != NULL; i++) {
- qdev_prop_register_global(props+i);
- }
-}
-
int qdev_prop_check_globals(void)
{
GList *l;
diff --git a/hw/core/sysbus.c b/hw/core/sysbus.c
index 7ac36ad3e7..9f9edbcab9 100644
--- a/hw/core/sysbus.c
+++ b/hw/core/sysbus.c
@@ -201,18 +201,13 @@ void sysbus_init_ioports(SysBusDevice *dev, uint32_t ioport, uint32_t size)
}
}
-/* TODO remove once all sysbus devices have been converted to realize */
+/* The purpose of preserving this empty realize function
+ * is to prevent the parent_realize field of some subclasses
+ * from being set to NULL to break the normal init/realize
+ * of some devices.
+ */
static void sysbus_realize(DeviceState *dev, Error **errp)
{
- SysBusDevice *sd = SYS_BUS_DEVICE(dev);
- SysBusDeviceClass *sbc = SYS_BUS_DEVICE_GET_CLASS(sd);
-
- if (!sbc->init) {
- return;
- }
- if (sbc->init(sd) < 0) {
- error_setg(errp, "Device initialization failed");
- }
}
DeviceState *sysbus_create_varargs(const char *name,
diff --git a/hw/display/g364fb.c b/hw/display/g364fb.c
index 8ad7e5d824..3407adf98d 100644
--- a/hw/display/g364fb.c
+++ b/hw/display/g364fb.c
@@ -489,18 +489,16 @@ typedef struct {
G364State g364;
} G364SysBusState;
-static int g364fb_sysbus_init(SysBusDevice *sbd)
+static void g364fb_sysbus_realize(DeviceState *dev, Error **errp)
{
- DeviceState *dev = DEVICE(sbd);
G364SysBusState *sbs = G364(dev);
G364State *s = &sbs->g364;
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
g364fb_init(dev, s);
sysbus_init_irq(sbd, &s->irq);
sysbus_init_mmio(sbd, &s->mem_ctrl);
sysbus_init_mmio(sbd, &s->mem_vram);
-
- return 0;
}
static void g364fb_sysbus_reset(DeviceState *d)
@@ -518,9 +516,8 @@ static Property g364fb_sysbus_properties[] = {
static void g364fb_sysbus_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
- SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
- k->init = g364fb_sysbus_init;
+ dc->realize = g364fb_sysbus_realize;
set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
dc->desc = "G364 framebuffer";
dc->reset = g364fb_sysbus_reset;
diff --git a/hw/dma/puv3_dma.c b/hw/dma/puv3_dma.c
index b97a6c1767..c89eade029 100644
--- a/hw/dma/puv3_dma.c
+++ b/hw/dma/puv3_dma.c
@@ -76,7 +76,7 @@ static const MemoryRegionOps puv3_dma_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
-static int puv3_dma_init(SysBusDevice *dev)
+static void puv3_dma_realize(DeviceState *dev, Error **errp)
{
PUV3DMAState *s = PUV3_DMA(dev);
int i;
@@ -87,16 +87,14 @@ static int puv3_dma_init(SysBusDevice *dev)
memory_region_init_io(&s->iomem, OBJECT(s), &puv3_dma_ops, s, "puv3_dma",
PUV3_REGS_OFFSET);
- sysbus_init_mmio(dev, &s->iomem);
-
- return 0;
+ sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
}
static void puv3_dma_class_init(ObjectClass *klass, void *data)
{
- SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+ DeviceClass *dc = DEVICE_CLASS(klass);
- sdc->init = puv3_dma_init;
+ dc->realize = puv3_dma_realize;
}
static const TypeInfo puv3_dma_info = {
diff --git a/hw/gpio/puv3_gpio.c b/hw/gpio/puv3_gpio.c
index 445afccf9f..33241b8564 100644
--- a/hw/gpio/puv3_gpio.c
+++ b/hw/gpio/puv3_gpio.c
@@ -99,36 +99,35 @@ static const MemoryRegionOps puv3_gpio_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
-static int puv3_gpio_init(SysBusDevice *dev)
+static void puv3_gpio_realize(DeviceState *dev, Error **errp)
{
PUV3GPIOState *s = PUV3_GPIO(dev);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
s->reg_GPLR = 0;
s->reg_GPDR = 0;
/* FIXME: these irqs not handled yet */
- sysbus_init_irq(dev, &s->irq[PUV3_IRQS_GPIOLOW0]);
- sysbus_init_irq(dev, &s->irq[PUV3_IRQS_GPIOLOW1]);
- sysbus_init_irq(dev, &s->irq[PUV3_IRQS_GPIOLOW2]);
- sysbus_init_irq(dev, &s->irq[PUV3_IRQS_GPIOLOW3]);
- sysbus_init_irq(dev, &s->irq[PUV3_IRQS_GPIOLOW4]);
- sysbus_init_irq(dev, &s->irq[PUV3_IRQS_GPIOLOW5]);
- sysbus_init_irq(dev, &s->irq[PUV3_IRQS_GPIOLOW6]);
- sysbus_init_irq(dev, &s->irq[PUV3_IRQS_GPIOLOW7]);
- sysbus_init_irq(dev, &s->irq[PUV3_IRQS_GPIOHIGH]);
+ sysbus_init_irq(sbd, &s->irq[PUV3_IRQS_GPIOLOW0]);
+ sysbus_init_irq(sbd, &s->irq[PUV3_IRQS_GPIOLOW1]);
+ sysbus_init_irq(sbd, &s->irq[PUV3_IRQS_GPIOLOW2]);
+ sysbus_init_irq(sbd, &s->irq[PUV3_IRQS_GPIOLOW3]);
+ sysbus_init_irq(sbd, &s->irq[PUV3_IRQS_GPIOLOW4]);
+ sysbus_init_irq(sbd, &s->irq[PUV3_IRQS_GPIOLOW5]);
+ sysbus_init_irq(sbd, &s->irq[PUV3_IRQS_GPIOLOW6]);
+ sysbus_init_irq(sbd, &s->irq[PUV3_IRQS_GPIOLOW7]);
+ sysbus_init_irq(sbd, &s->irq[PUV3_IRQS_GPIOHIGH]);
memory_region_init_io(&s->iomem, OBJECT(s), &puv3_gpio_ops, s, "puv3_gpio",
PUV3_REGS_OFFSET);
- sysbus_init_mmio(dev, &s->iomem);
-
- return 0;
+ sysbus_init_mmio(sbd, &s->iomem);
}
static void puv3_gpio_class_init(ObjectClass *klass, void *data)
{
- SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+ DeviceClass *dc = DEVICE_CLASS(klass);
- sdc->init = puv3_gpio_init;
+ dc->realize = puv3_gpio_realize;
}
static const TypeInfo puv3_gpio_info = {
diff --git a/hw/i2c/bitbang_i2c.h b/hw/i2c/bitbang_i2c.h
index 3a7126d5de..9443021710 100644
--- a/hw/i2c/bitbang_i2c.h
+++ b/hw/i2c/bitbang_i2c.h
@@ -3,8 +3,6 @@
#include "hw/i2c/i2c.h"
-typedef struct bitbang_i2c_interface bitbang_i2c_interface;
-
#define BITBANG_I2C_SDA 0
#define BITBANG_I2C_SCL 1
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index f095725dba..4cd2fbca4d 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -2222,42 +2222,42 @@ static bool pc_machine_get_smbus(Object *obj, Error **errp)
{
PCMachineState *pcms = PC_MACHINE(obj);
- return pcms->smbus;
+ return pcms->smbus_enabled;
}
static void pc_machine_set_smbus(Object *obj, bool value, Error **errp)
{
PCMachineState *pcms = PC_MACHINE(obj);
- pcms->smbus = value;
+ pcms->smbus_enabled = value;
}
static bool pc_machine_get_sata(Object *obj, Error **errp)
{
PCMachineState *pcms = PC_MACHINE(obj);
- return pcms->sata;
+ return pcms->sata_enabled;
}
static void pc_machine_set_sata(Object *obj, bool value, Error **errp)
{
PCMachineState *pcms = PC_MACHINE(obj);
- pcms->sata = value;
+ pcms->sata_enabled = value;
}
static bool pc_machine_get_pit(Object *obj, Error **errp)
{
PCMachineState *pcms = PC_MACHINE(obj);
- return pcms->pit;
+ return pcms->pit_enabled;
}
static void pc_machine_set_pit(Object *obj, bool value, Error **errp)
{
PCMachineState *pcms = PC_MACHINE(obj);
- pcms->pit = value;
+ pcms->pit_enabled = value;
}
static void pc_machine_initfn(Object *obj)
@@ -2271,9 +2271,9 @@ static void pc_machine_initfn(Object *obj)
pcms->acpi_nvdimm_state.is_enabled = false;
/* acpi build is enabled by default if machine supports it */
pcms->acpi_build_enabled = PC_MACHINE_GET_CLASS(pcms)->has_acpi_build;
- pcms->smbus = true;
- pcms->sata = true;
- pcms->pit = true;
+ pcms->smbus_enabled = true;
+ pcms->sata_enabled = true;
+ pcms->pit_enabled = true;
}
static void pc_machine_reset(void)
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index 7092d6d13f..6981cfa740 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -239,7 +239,8 @@ static void pc_init1(MachineState *machine,
/* init basic PC hardware */
pc_basic_device_init(isa_bus, pcms->gsi, &rtc_state, true,
- (pcms->vmport != ON_OFF_AUTO_ON), pcms->pit, 0x4);
+ (pcms->vmport != ON_OFF_AUTO_ON), pcms->pit_enabled,
+ 0x4);
pc_nic_init(pcmc, isa_bus, pci_bus);
@@ -320,7 +321,6 @@ static void pc_compat_2_3(MachineState *machine)
static void pc_compat_2_2(MachineState *machine)
{
pc_compat_2_3(machine);
- machine->suppress_vmdesc = true;
}
static void pc_compat_2_1(MachineState *machine)
@@ -428,21 +428,30 @@ static void pc_i440fx_machine_options(MachineClass *m)
machine_class_allow_dynamic_sysbus_dev(m, TYPE_RAMFB_DEVICE);
}
-static void pc_i440fx_3_1_machine_options(MachineClass *m)
+static void pc_i440fx_4_0_machine_options(MachineClass *m)
{
pc_i440fx_machine_options(m);
m->alias = "pc";
m->is_default = 1;
}
+DEFINE_I440FX_MACHINE(v4_0, "pc-i440fx-4.0", NULL,
+ pc_i440fx_4_0_machine_options);
+
+static void pc_i440fx_3_1_machine_options(MachineClass *m)
+{
+ pc_i440fx_4_0_machine_options(m);
+ m->is_default = 0;
+ m->alias = NULL;
+ SET_MACHINE_COMPAT(m, PC_COMPAT_3_1);
+}
+
DEFINE_I440FX_MACHINE(v3_1, "pc-i440fx-3.1", NULL,
pc_i440fx_3_1_machine_options);
static void pc_i440fx_3_0_machine_options(MachineClass *m)
{
pc_i440fx_3_1_machine_options(m);
- m->is_default = 0;
- m->alias = NULL;
SET_MACHINE_COMPAT(m, PC_COMPAT_3_0);
}
@@ -562,6 +571,7 @@ static void pc_i440fx_2_2_machine_options(MachineClass *m)
PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
pc_i440fx_2_3_machine_options(m);
m->hw_version = "2.2.0";
+ m->default_machine_opts = "firmware=bios-256k.bin,suppress-vmdesc=on";
SET_MACHINE_COMPAT(m, PC_COMPAT_2_2);
pcmc->rsdp_in_ram = false;
}
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index 4702bb13c4..58459bdab5 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -236,13 +236,13 @@ static void pc_q35_init(MachineState *machine)
/* init basic PC hardware */
pc_basic_device_init(isa_bus, pcms->gsi, &rtc_state, !mc->no_floppy,
- (pcms->vmport != ON_OFF_AUTO_ON), pcms->pit,
+ (pcms->vmport != ON_OFF_AUTO_ON), pcms->pit_enabled,
0xff0104);
/* connect pm stuff to lpc */
ich9_lpc_pm_init(lpc, pc_machine_is_smm_enabled(pcms));
- if (pcms->sata) {
+ if (pcms->sata_enabled) {
/* ahci and SATA device, for q35 1 ahci controller is built-in */
ahci = pci_create_simple_multifunction(host_bus,
PCI_DEVFN(ICH9_SATA1_DEV,
@@ -262,7 +262,7 @@ static void pc_q35_init(MachineState *machine)
ehci_create_ich9_with_companions(host_bus, 0x1d);
}
- if (pcms->smbus) {
+ if (pcms->smbus_enabled) {
/* TODO: Populate SPD eeprom data. */
smbus_eeprom_init(ich9_smb_init(host_bus,
PCI_DEVFN(ICH9_SMB_DEV, ICH9_SMB_FUNC),
@@ -311,19 +311,28 @@ static void pc_q35_machine_options(MachineClass *m)
m->max_cpus = 288;
}
-static void pc_q35_3_1_machine_options(MachineClass *m)
+static void pc_q35_4_0_machine_options(MachineClass *m)
{
pc_q35_machine_options(m);
m->alias = "q35";
}
+DEFINE_Q35_MACHINE(v4_0, "pc-q35-4.0", NULL,
+ pc_q35_4_0_machine_options);
+
+static void pc_q35_3_1_machine_options(MachineClass *m)
+{
+ pc_q35_4_0_machine_options(m);
+ m->alias = NULL;
+ SET_MACHINE_COMPAT(m, PC_COMPAT_3_1);
+}
+
DEFINE_Q35_MACHINE(v3_1, "pc-q35-3.1", NULL,
pc_q35_3_1_machine_options);
static void pc_q35_3_0_machine_options(MachineClass *m)
{
pc_q35_3_1_machine_options(m);
- m->alias = NULL;
SET_MACHINE_COMPAT(m, PC_COMPAT_3_0);
}
diff --git a/hw/input/milkymist-softusb.c b/hw/input/milkymist-softusb.c
index ef8f47cd83..8766a17d9e 100644
--- a/hw/input/milkymist-softusb.c
+++ b/hw/input/milkymist-softusb.c
@@ -245,32 +245,31 @@ static void milkymist_softusb_reset(DeviceState *d)
s->regs[R_CTRL] = CTRL_RESET;
}
-static int milkymist_softusb_init(SysBusDevice *dev)
+static void milkymist_softusb_realize(DeviceState *dev, Error **errp)
{
MilkymistSoftUsbState *s = MILKYMIST_SOFTUSB(dev);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
- sysbus_init_irq(dev, &s->irq);
+ sysbus_init_irq(sbd, &s->irq);
memory_region_init_io(&s->regs_region, OBJECT(s), &softusb_mmio_ops, s,
"milkymist-softusb", R_MAX * 4);
- sysbus_init_mmio(dev, &s->regs_region);
+ sysbus_init_mmio(sbd, &s->regs_region);
/* register pmem and dmem */
memory_region_init_ram_nomigrate(&s->pmem, OBJECT(s), "milkymist-softusb.pmem",
s->pmem_size, &error_fatal);
vmstate_register_ram_global(&s->pmem);
s->pmem_ptr = memory_region_get_ram_ptr(&s->pmem);
- sysbus_init_mmio(dev, &s->pmem);
+ sysbus_init_mmio(sbd, &s->pmem);
memory_region_init_ram_nomigrate(&s->dmem, OBJECT(s), "milkymist-softusb.dmem",
s->dmem_size, &error_fatal);
vmstate_register_ram_global(&s->dmem);
s->dmem_ptr = memory_region_get_ram_ptr(&s->dmem);
- sysbus_init_mmio(dev, &s->dmem);
+ sysbus_init_mmio(sbd, &s->dmem);
hid_init(&s->hid_kbd, HID_KEYBOARD, softusb_kbd_hid_datain);
hid_init(&s->hid_mouse, HID_MOUSE, softusb_mouse_hid_datain);
-
- return 0;
}
static const VMStateDescription vmstate_milkymist_softusb = {
@@ -296,9 +295,8 @@ static Property milkymist_softusb_properties[] = {
static void milkymist_softusb_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
- SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
- k->init = milkymist_softusb_init;
+ dc->realize = milkymist_softusb_realize;
dc->reset = milkymist_softusb_reset;
dc->vmsd = &vmstate_milkymist_softusb;
dc->props = milkymist_softusb_properties;
diff --git a/hw/input/pl050.c b/hw/input/pl050.c
index be9cd57b17..15bffbfcad 100644
--- a/hw/input/pl050.c
+++ b/hw/input/pl050.c
@@ -139,19 +139,19 @@ static const MemoryRegionOps pl050_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
-static int pl050_initfn(SysBusDevice *dev)
+static void pl050_realize(DeviceState *dev, Error **errp)
{
PL050State *s = PL050(dev);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
memory_region_init_io(&s->iomem, OBJECT(s), &pl050_ops, s, "pl050", 0x1000);
- sysbus_init_mmio(dev, &s->iomem);
- sysbus_init_irq(dev, &s->irq);
+ sysbus_init_mmio(sbd, &s->iomem);
+ sysbus_init_irq(sbd, &s->irq);
if (s->is_mouse) {
s->dev = ps2_mouse_init(pl050_update, s);
} else {
s->dev = ps2_kbd_init(pl050_update, s);
}
- return 0;
}
static void pl050_keyboard_init(Object *obj)
@@ -183,9 +183,8 @@ static const TypeInfo pl050_mouse_info = {
static void pl050_class_init(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
- SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(oc);
- sdc->init = pl050_initfn;
+ dc->realize = pl050_realize;
dc->vmsd = &vmstate_pl050;
}
diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
index 068a8e8e9b..cbad6037f1 100644
--- a/hw/intc/arm_gicv3_cpuif.c
+++ b/hw/intc/arm_gicv3_cpuif.c
@@ -85,8 +85,8 @@ static bool icv_access(CPUARMState *env, int hcr_flags)
* * access if NS EL1 and either IMO or FMO == 1:
* CTLR, DIR, PMR, RPR
*/
- bool flagmatch = ((hcr_flags & HCR_IMO) && arm_hcr_el2_imo(env)) ||
- ((hcr_flags & HCR_FMO) && arm_hcr_el2_fmo(env));
+ uint64_t hcr_el2 = arm_hcr_el2_eff(env);
+ bool flagmatch = hcr_el2 & hcr_flags & (HCR_IMO | HCR_FMO);
return flagmatch && arm_current_el(env) == 1
&& !arm_is_secure_below_el3(env);
@@ -1552,8 +1552,9 @@ static void icc_dir_write(CPUARMState *env, const ARMCPRegInfo *ri,
/* No need to include !IsSecure in route_*_to_el2 as it's only
* tested in cases where we know !IsSecure is true.
*/
- route_fiq_to_el2 = arm_hcr_el2_fmo(env);
- route_irq_to_el2 = arm_hcr_el2_imo(env);
+ uint64_t hcr_el2 = arm_hcr_el2_eff(env);
+ route_fiq_to_el2 = hcr_el2 & HCR_FMO;
+ route_irq_to_el2 = hcr_el2 & HCR_IMO;
switch (arm_current_el(env)) {
case 3:
@@ -1895,8 +1896,8 @@ static CPAccessResult gicv3_irqfiq_access(CPUARMState *env,
if ((env->cp15.scr_el3 & (SCR_FIQ | SCR_IRQ)) == (SCR_FIQ | SCR_IRQ)) {
switch (el) {
case 1:
- if (arm_is_secure_below_el3(env) ||
- (arm_hcr_el2_imo(env) == 0 && arm_hcr_el2_fmo(env) == 0)) {
+ /* Note that arm_hcr_el2_eff takes secure state into account. */
+ if ((arm_hcr_el2_eff(env) & (HCR_IMO | HCR_FMO)) == 0) {
r = CP_ACCESS_TRAP_EL3;
}
break;
@@ -1936,8 +1937,8 @@ static CPAccessResult gicv3_dir_access(CPUARMState *env,
static CPAccessResult gicv3_sgi_access(CPUARMState *env,
const ARMCPRegInfo *ri, bool isread)
{
- if ((arm_hcr_el2_imo(env) || arm_hcr_el2_fmo(env)) &&
- arm_current_el(env) == 1 && !arm_is_secure_below_el3(env)) {
+ if (arm_current_el(env) == 1 &&
+ (arm_hcr_el2_eff(env) & (HCR_IMO | HCR_FMO)) != 0) {
/* Takes priority over a possible EL3 trap */
return CP_ACCESS_TRAP_EL2;
}
@@ -1961,7 +1962,7 @@ static CPAccessResult gicv3_fiq_access(CPUARMState *env,
if (env->cp15.scr_el3 & SCR_FIQ) {
switch (el) {
case 1:
- if (arm_is_secure_below_el3(env) || !arm_hcr_el2_fmo(env)) {
+ if ((arm_hcr_el2_eff(env) & HCR_FMO) == 0) {
r = CP_ACCESS_TRAP_EL3;
}
break;
@@ -2000,7 +2001,7 @@ static CPAccessResult gicv3_irq_access(CPUARMState *env,
if (env->cp15.scr_el3 & SCR_IRQ) {
switch (el) {
case 1:
- if (arm_is_secure_below_el3(env) || !arm_hcr_el2_imo(env)) {
+ if ((arm_hcr_el2_eff(env) & HCR_IMO) == 0) {
r = CP_ACCESS_TRAP_EL3;
}
break;
diff --git a/hw/intc/puv3_intc.c b/hw/intc/puv3_intc.c
index ef8488aacc..69ddc8c19a 100644
--- a/hw/intc/puv3_intc.c
+++ b/hw/intc/puv3_intc.c
@@ -101,10 +101,10 @@ static const MemoryRegionOps puv3_intc_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
-static int puv3_intc_init(SysBusDevice *sbd)
+static void puv3_intc_realize(DeviceState *dev, Error **errp)
{
- DeviceState *dev = DEVICE(sbd);
PUV3INTCState *s = PUV3_INTC(dev);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
qdev_init_gpio_in(dev, puv3_intc_handler, PUV3_IRQS_NR);
sysbus_init_irq(sbd, &s->parent_irq);
@@ -115,15 +115,12 @@ static int puv3_intc_init(SysBusDevice *sbd)
memory_region_init_io(&s->iomem, OBJECT(s), &puv3_intc_ops, s, "puv3_intc",
PUV3_REGS_OFFSET);
sysbus_init_mmio(sbd, &s->iomem);
-
- return 0;
}
static void puv3_intc_class_init(ObjectClass *klass, void *data)
{
- SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
-
- sdc->init = puv3_intc_init;
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ dc->realize = puv3_intc_realize;
}
static const TypeInfo puv3_intc_info = {
diff --git a/hw/mem/memory-device.c b/hw/mem/memory-device.c
index 7de1ccd497..8be63c8032 100644
--- a/hw/mem/memory-device.c
+++ b/hw/mem/memory-device.c
@@ -85,7 +85,8 @@ static void memory_device_check_addable(MachineState *ms, uint64_t size,
/* will we exceed the total amount of memory specified */
memory_device_used_region_size(OBJECT(ms), &used_region_size);
- if (used_region_size + size > ms->maxram_size - ms->ram_size) {
+ if (used_region_size + size < used_region_size ||
+ used_region_size + size > ms->maxram_size - ms->ram_size) {
error_setg(errp, "not enough space, currently 0x%" PRIx64
" in use of total space for memory devices 0x" RAM_ADDR_FMT,
used_region_size, ms->maxram_size - ms->ram_size);
@@ -120,7 +121,7 @@ static uint64_t memory_device_get_free_addr(MachineState *ms,
g_assert(address_space_end >= address_space_start);
/* address_space_start indicates the maximum alignment we expect */
- if (QEMU_ALIGN_UP(address_space_start, align) != address_space_start) {
+ if (!QEMU_IS_ALIGNED(address_space_start, align)) {
error_setg(errp, "the alignment (0x%" PRIx64 ") is not supported",
align);
return 0;
@@ -131,13 +132,13 @@ static uint64_t memory_device_get_free_addr(MachineState *ms,
return 0;
}
- if (hint && QEMU_ALIGN_UP(*hint, align) != *hint) {
+ if (hint && !QEMU_IS_ALIGNED(*hint, align)) {
error_setg(errp, "address must be aligned to 0x%" PRIx64 " bytes",
align);
return 0;
}
- if (QEMU_ALIGN_UP(size, align) != size) {
+ if (!QEMU_IS_ALIGNED(size, align)) {
error_setg(errp, "backend memory size must be multiple of 0x%"
PRIx64, align);
return 0;
diff --git a/hw/misc/ivshmem.c b/hw/misc/ivshmem.c
index ecfd10a29a..8213659602 100644
--- a/hw/misc/ivshmem.c
+++ b/hw/misc/ivshmem.c
@@ -1280,7 +1280,7 @@ static void desugar_shm(IVShmemState *s)
object_property_add_child(OBJECT(s), "internal-shm-backend", obj,
&error_abort);
object_unref(obj);
- user_creatable_complete(obj, &error_abort);
+ user_creatable_complete(USER_CREATABLE(obj), &error_abort);
s->hostmem = MEMORY_BACKEND(obj);
}
diff --git a/hw/misc/milkymist-hpdmc.c b/hw/misc/milkymist-hpdmc.c
index e6140eec6b..44dc0698ec 100644
--- a/hw/misc/milkymist-hpdmc.c
+++ b/hw/misc/milkymist-hpdmc.c
@@ -129,15 +129,13 @@ static void milkymist_hpdmc_reset(DeviceState *d)
| IODELAY_PLL2_LOCKED;
}
-static int milkymist_hpdmc_init(SysBusDevice *dev)
+static void milkymist_hpdmc_realize(DeviceState *dev, Error **errp)
{
MilkymistHpdmcState *s = MILKYMIST_HPDMC(dev);
memory_region_init_io(&s->regs_region, OBJECT(dev), &hpdmc_mmio_ops, s,
"milkymist-hpdmc", R_MAX * 4);
- sysbus_init_mmio(dev, &s->regs_region);
-
- return 0;
+ sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->regs_region);
}
static const VMStateDescription vmstate_milkymist_hpdmc = {
@@ -153,9 +151,8 @@ static const VMStateDescription vmstate_milkymist_hpdmc = {
static void milkymist_hpdmc_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
- SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
- k->init = milkymist_hpdmc_init;
+ dc->realize = milkymist_hpdmc_realize;
dc->reset = milkymist_hpdmc_reset;
dc->vmsd = &vmstate_milkymist_hpdmc;
}
diff --git a/hw/misc/milkymist-pfpu.c b/hw/misc/milkymist-pfpu.c
index 86f5e383b0..4a03c7ee63 100644
--- a/hw/misc/milkymist-pfpu.c
+++ b/hw/misc/milkymist-pfpu.c
@@ -497,17 +497,16 @@ static void milkymist_pfpu_reset(DeviceState *d)
}
}
-static int milkymist_pfpu_init(SysBusDevice *dev)
+static void milkymist_pfpu_realize(DeviceState *dev, Error **errp)
{
MilkymistPFPUState *s = MILKYMIST_PFPU(dev);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
- sysbus_init_irq(dev, &s->irq);
+ sysbus_init_irq(sbd, &s->irq);
memory_region_init_io(&s->regs_region, OBJECT(dev), &pfpu_mmio_ops, s,
"milkymist-pfpu", MICROCODE_END * 4);
- sysbus_init_mmio(dev, &s->regs_region);
-
- return 0;
+ sysbus_init_mmio(sbd, &s->regs_region);
}
static const VMStateDescription vmstate_milkymist_pfpu = {
@@ -527,9 +526,8 @@ static const VMStateDescription vmstate_milkymist_pfpu = {
static void milkymist_pfpu_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
- SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
- k->init = milkymist_pfpu_init;
+ dc->realize = milkymist_pfpu_realize;
dc->reset = milkymist_pfpu_reset;
dc->vmsd = &vmstate_milkymist_pfpu;
}
diff --git a/hw/misc/puv3_pm.c b/hw/misc/puv3_pm.c
index 577cebaac7..afe191fbe1 100644
--- a/hw/misc/puv3_pm.c
+++ b/hw/misc/puv3_pm.c
@@ -119,7 +119,7 @@ static const MemoryRegionOps puv3_pm_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
-static int puv3_pm_init(SysBusDevice *dev)
+static void puv3_pm_realize(DeviceState *dev, Error **errp)
{
PUV3PMState *s = PUV3_PM(dev);
@@ -127,16 +127,14 @@ static int puv3_pm_init(SysBusDevice *dev)
memory_region_init_io(&s->iomem, OBJECT(s), &puv3_pm_ops, s, "puv3_pm",
PUV3_REGS_OFFSET);
- sysbus_init_mmio(dev, &s->iomem);
-
- return 0;
+ sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
}
static void puv3_pm_class_init(ObjectClass *klass, void *data)
{
- SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+ DeviceClass *dc = DEVICE_CLASS(klass);
- sdc->init = puv3_pm_init;
+ dc->realize = puv3_pm_realize;
}
static const TypeInfo puv3_pm_info = {
diff --git a/hw/misc/tmp105.c b/hw/misc/tmp105.c
index 0918f3a6ea..f6d7163273 100644
--- a/hw/misc/tmp105.c
+++ b/hw/misc/tmp105.c
@@ -79,7 +79,7 @@ static void tmp105_set_temperature(Object *obj, Visitor *v, const char *name,
return;
}
if (temp >= 128000 || temp < -128000) {
- error_setg(errp, "value %" PRId64 ".%03" PRIu64 " °C is out of range",
+ error_setg(errp, "value %" PRId64 ".%03" PRIu64 " C is out of range",
temp / 1000, temp % 1000);
return;
}
diff --git a/hw/misc/tmp421.c b/hw/misc/tmp421.c
index c234044305..eeb11000f0 100644
--- a/hw/misc/tmp421.c
+++ b/hw/misc/tmp421.c
@@ -153,7 +153,7 @@ static void tmp421_set_temperature(Object *obj, Visitor *v, const char *name,
}
if (temp >= maxs[ext_range] || temp < mins[ext_range]) {
- error_setg(errp, "value %" PRId64 ".%03" PRIu64 " °C is out of range",
+ error_setg(errp, "value %" PRId64 ".%03" PRIu64 " C is out of range",
temp / 1000, temp % 1000);
return;
}
diff --git a/hw/nvram/ds1225y.c b/hw/nvram/ds1225y.c
index ad7345f288..b6ef463db0 100644
--- a/hw/nvram/ds1225y.c
+++ b/hw/nvram/ds1225y.c
@@ -25,6 +25,7 @@
#include "qemu/osdep.h"
#include "hw/sysbus.h"
#include "trace.h"
+#include "qemu/error-report.h"
typedef struct {
MemoryRegion iomem;
@@ -113,7 +114,7 @@ typedef struct {
NvRamState nvram;
} SysBusNvRamState;
-static int nvram_sysbus_initfn(SysBusDevice *dev)
+static void nvram_sysbus_realize(DeviceState *dev, Error **errp)
{
SysBusNvRamState *sys = DS1225Y(dev);
NvRamState *s = &sys->nvram;
@@ -123,20 +124,18 @@ static int nvram_sysbus_initfn(SysBusDevice *dev)
memory_region_init_io(&s->iomem, OBJECT(s), &nvram_ops, s,
"nvram", s->chip_size);
- sysbus_init_mmio(dev, &s->iomem);
+ sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
/* Read current file */
file = s->filename ? fopen(s->filename, "rb") : NULL;
if (file) {
/* Read nvram contents */
if (fread(s->contents, s->chip_size, 1, file) != 1) {
- printf("nvram_sysbus_initfn: short read\n");
+ error_report("nvram_sysbus_realize: short read");
}
fclose(file);
}
nvram_post_load(s, 0);
-
- return 0;
}
static Property nvram_sysbus_properties[] = {
@@ -148,9 +147,8 @@ static Property nvram_sysbus_properties[] = {
static void nvram_sysbus_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
- SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
- k->init = nvram_sysbus_initfn;
+ dc->realize = nvram_sysbus_realize;
dc->vmsd = &vmstate_nvram;
dc->props = nvram_sysbus_properties;
}
diff --git a/hw/pci-bridge/dec.c b/hw/pci-bridge/dec.c
index 84492d5e5f..8484bfd434 100644
--- a/hw/pci-bridge/dec.c
+++ b/hw/pci-bridge/dec.c
@@ -98,9 +98,10 @@ PCIBus *pci_dec_21154_init(PCIBus *parent_bus, int devfn)
return pci_bridge_get_sec_bus(br);
}
-static int pci_dec_21154_device_init(SysBusDevice *dev)
+static void pci_dec_21154_device_realize(DeviceState *dev, Error **errp)
{
PCIHostState *phb;
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
phb = PCI_HOST_BRIDGE(dev);
@@ -108,9 +109,8 @@ static int pci_dec_21154_device_init(SysBusDevice *dev)
dev, "pci-conf-idx", 0x1000);
memory_region_init_io(&phb->data_mem, OBJECT(dev), &pci_host_data_le_ops,
dev, "pci-data-idx", 0x1000);
- sysbus_init_mmio(dev, &phb->conf_mem);
- sysbus_init_mmio(dev, &phb->data_mem);
- return 0;
+ sysbus_init_mmio(sbd, &phb->conf_mem);
+ sysbus_init_mmio(sbd, &phb->data_mem);
}
static void dec_21154_pci_host_realize(PCIDevice *d, Error **errp)
@@ -150,9 +150,9 @@ static const TypeInfo dec_21154_pci_host_info = {
static void pci_dec_21154_device_class_init(ObjectClass *klass, void *data)
{
- SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+ DeviceClass *dc = DEVICE_CLASS(klass);
- sdc->init = pci_dec_21154_device_init;
+ dc->realize = pci_dec_21154_device_realize;
}
static const TypeInfo pci_dec_21154_device_info = {
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 7afd1a175b..55be0f56cb 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -3939,16 +3939,10 @@ static const TypeInfo spapr_machine_info = {
mc->is_default = 1; \
} \
} \
- static void spapr_machine_##suffix##_instance_init(Object *obj) \
- { \
- MachineState *machine = MACHINE(obj); \
- spapr_machine_##suffix##_instance_options(machine); \
- } \
static const TypeInfo spapr_machine_##suffix##_info = { \
.name = MACHINE_TYPE_NAME("pseries-" verstr), \
.parent = TYPE_SPAPR_MACHINE, \
.class_init = spapr_machine_##suffix##_class_init, \
- .instance_init = spapr_machine_##suffix##_instance_init, \
}; \
static void spapr_machine_register_##suffix(void) \
{ \
@@ -3956,19 +3950,29 @@ static const TypeInfo spapr_machine_info = {
} \
type_init(spapr_machine_register_##suffix)
- /*
- * pseries-3.1
+/*
+ * pseries-4.0
*/
-static void spapr_machine_3_1_instance_options(MachineState *machine)
+static void spapr_machine_4_0_class_options(MachineClass *mc)
{
+ /* Defaults for the latest behaviour inherited from the base class */
}
+DEFINE_SPAPR_MACHINE(4_0, "4.0", true);
+
+/*
+ * pseries-3.1
+ */
+#define SPAPR_COMPAT_3_1 \
+ HW_COMPAT_3_1
+
static void spapr_machine_3_1_class_options(MachineClass *mc)
{
- /* Defaults for the latest behaviour inherited from the base class */
+ spapr_machine_4_0_class_options(mc);
+ SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_3_1);
}
-DEFINE_SPAPR_MACHINE(3_1, "3.1", true);
+DEFINE_SPAPR_MACHINE(3_1, "3.1", false);
/*
* pseries-3.0
@@ -3976,11 +3980,6 @@ DEFINE_SPAPR_MACHINE(3_1, "3.1", true);
#define SPAPR_COMPAT_3_0 \
HW_COMPAT_3_0
-static void spapr_machine_3_0_instance_options(MachineState *machine)
-{
- spapr_machine_3_1_instance_options(machine);
-}
-
static void spapr_machine_3_0_class_options(MachineClass *mc)
{
sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
@@ -4010,11 +4009,6 @@ DEFINE_SPAPR_MACHINE(3_0, "3.0", false);
.value = "on", \
},
-static void spapr_machine_2_12_instance_options(MachineState *machine)
-{
- spapr_machine_3_0_instance_options(machine);
-}
-
static void spapr_machine_2_12_class_options(MachineClass *mc)
{
sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
@@ -4032,11 +4026,6 @@ static void spapr_machine_2_12_class_options(MachineClass *mc)
DEFINE_SPAPR_MACHINE(2_12, "2.12", false);
-static void spapr_machine_2_12_sxxm_instance_options(MachineState *machine)
-{
- spapr_machine_2_12_instance_options(machine);
-}
-
static void spapr_machine_2_12_sxxm_class_options(MachineClass *mc)
{
sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
@@ -4055,11 +4044,6 @@ DEFINE_SPAPR_MACHINE(2_12_sxxm, "2.12-sxxm", false);
#define SPAPR_COMPAT_2_11 \
HW_COMPAT_2_11
-static void spapr_machine_2_11_instance_options(MachineState *machine)
-{
- spapr_machine_2_12_instance_options(machine);
-}
-
static void spapr_machine_2_11_class_options(MachineClass *mc)
{
sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
@@ -4077,11 +4061,6 @@ DEFINE_SPAPR_MACHINE(2_11, "2.11", false);
#define SPAPR_COMPAT_2_10 \
HW_COMPAT_2_10
-static void spapr_machine_2_10_instance_options(MachineState *machine)
-{
- spapr_machine_2_11_instance_options(machine);
-}
-
static void spapr_machine_2_10_class_options(MachineClass *mc)
{
spapr_machine_2_11_class_options(mc);
@@ -4101,11 +4080,6 @@ DEFINE_SPAPR_MACHINE(2_10, "2.10", false);
.value = "on", \
}, \
-static void spapr_machine_2_9_instance_options(MachineState *machine)
-{
- spapr_machine_2_10_instance_options(machine);
-}
-
static void spapr_machine_2_9_class_options(MachineClass *mc)
{
sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
@@ -4130,11 +4104,6 @@ DEFINE_SPAPR_MACHINE(2_9, "2.9", false);
.value = "off", \
},
-static void spapr_machine_2_8_instance_options(MachineState *machine)
-{
- spapr_machine_2_9_instance_options(machine);
-}
-
static void spapr_machine_2_8_class_options(MachineClass *mc)
{
spapr_machine_2_9_class_options(mc);
@@ -4219,20 +4188,13 @@ static void phb_placement_2_7(sPAPRMachineState *spapr, uint32_t index,
*/
}
-static void spapr_machine_2_7_instance_options(MachineState *machine)
-{
- sPAPRMachineState *spapr = SPAPR_MACHINE(machine);
-
- spapr_machine_2_8_instance_options(machine);
- spapr->use_hotplug_event_source = false;
-}
-
static void spapr_machine_2_7_class_options(MachineClass *mc)
{
sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
spapr_machine_2_8_class_options(mc);
mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power7_v2.3");
+ mc->default_machine_opts = "modern-hotplug-events=off";
SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_7);
smc->phb_placement = phb_placement_2_7;
}
@@ -4250,11 +4212,6 @@ DEFINE_SPAPR_MACHINE(2_7, "2.7", false);
.value = stringify(off),\
},
-static void spapr_machine_2_6_instance_options(MachineState *machine)
-{
- spapr_machine_2_7_instance_options(machine);
-}
-
static void spapr_machine_2_6_class_options(MachineClass *mc)
{
spapr_machine_2_7_class_options(mc);
@@ -4275,11 +4232,6 @@ DEFINE_SPAPR_MACHINE(2_6, "2.6", false);
.value = "off", \
},
-static void spapr_machine_2_5_instance_options(MachineState *machine)
-{
- spapr_machine_2_6_instance_options(machine);
-}
-
static void spapr_machine_2_5_class_options(MachineClass *mc)
{
sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
@@ -4297,11 +4249,6 @@ DEFINE_SPAPR_MACHINE(2_5, "2.5", false);
#define SPAPR_COMPAT_2_4 \
HW_COMPAT_2_4
-static void spapr_machine_2_4_instance_options(MachineState *machine)
-{
- spapr_machine_2_5_instance_options(machine);
-}
-
static void spapr_machine_2_4_class_options(MachineClass *mc)
{
sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
@@ -4324,11 +4271,6 @@ DEFINE_SPAPR_MACHINE(2_4, "2.4", false);
.value = "off",\
},
-static void spapr_machine_2_3_instance_options(MachineState *machine)
-{
- spapr_machine_2_4_instance_options(machine);
-}
-
static void spapr_machine_2_3_class_options(MachineClass *mc)
{
spapr_machine_2_4_class_options(mc);
@@ -4348,16 +4290,11 @@ DEFINE_SPAPR_MACHINE(2_3, "2.3", false);
.value = "0x20000000",\
},
-static void spapr_machine_2_2_instance_options(MachineState *machine)
-{
- spapr_machine_2_3_instance_options(machine);
- machine->suppress_vmdesc = true;
-}
-
static void spapr_machine_2_2_class_options(MachineClass *mc)
{
spapr_machine_2_3_class_options(mc);
SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_2);
+ mc->default_machine_opts = "modern-hotplug-events=off,suppress-vmdesc=on";
}
DEFINE_SPAPR_MACHINE(2_2, "2.2", false);
@@ -4367,11 +4304,6 @@ DEFINE_SPAPR_MACHINE(2_2, "2.2", false);
#define SPAPR_COMPAT_2_1 \
HW_COMPAT_2_1
-static void spapr_machine_2_1_instance_options(MachineState *machine)
-{
- spapr_machine_2_2_instance_options(machine);
-}
-
static void spapr_machine_2_1_class_options(MachineClass *mc)
{
spapr_machine_2_2_class_options(mc);
diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c
index 060ff062bc..99d0368868 100644
--- a/hw/s390x/s390-pci-bus.c
+++ b/hw/s390x/s390-pci-bus.c
@@ -745,7 +745,6 @@ static int s390_pci_msix_init(S390PCIBusDevice *pbdev)
pos = pci_find_capability(pbdev->pdev, PCI_CAP_ID_MSIX);
if (!pos) {
- pbdev->msix.available = false;
return -1;
}
@@ -761,7 +760,6 @@ static int s390_pci_msix_init(S390PCIBusDevice *pbdev)
pbdev->msix.pba_bar = pba & PCI_MSIX_FLAGS_BIRMASK;
pbdev->msix.pba_offset = pba & ~PCI_MSIX_FLAGS_BIRMASK;
pbdev->msix.entries = (ctrl & PCI_MSIX_FLAGS_QSIZE) + 1;
- pbdev->msix.available = true;
name = g_strdup_printf("msix-s390-%04x", pbdev->uid);
memory_region_init_io(&pbdev->msix_notify_mr, OBJECT(pbdev),
diff --git a/hw/s390x/s390-pci-bus.h b/hw/s390x/s390-pci-bus.h
index 1f7f9b5814..f47a0f2da5 100644
--- a/hw/s390x/s390-pci-bus.h
+++ b/hw/s390x/s390-pci-bus.h
@@ -252,7 +252,6 @@ typedef struct ChscSeiNt2Res {
} QEMU_PACKED ChscSeiNt2Res;
typedef struct S390MsixInfo {
- bool available;
uint8_t table_bar;
uint8_t pba_bar;
uint16_t entries;
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index a0615a8b35..fd9d0b0542 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -651,6 +651,9 @@ bool css_migration_enabled(void)
} \
type_init(ccw_machine_register_##suffix)
+#define CCW_COMPAT_3_1 \
+ HW_COMPAT_3_1
+
#define CCW_COMPAT_3_0 \
HW_COMPAT_3_0
@@ -742,14 +745,26 @@ bool css_migration_enabled(void)
.value = "0",\
},
+static void ccw_machine_4_0_instance_options(MachineState *machine)
+{
+}
+
+static void ccw_machine_4_0_class_options(MachineClass *mc)
+{
+}
+DEFINE_CCW_MACHINE(4_0, "4.0", true);
+
static void ccw_machine_3_1_instance_options(MachineState *machine)
{
+ ccw_machine_4_0_instance_options(machine);
}
static void ccw_machine_3_1_class_options(MachineClass *mc)
{
+ ccw_machine_4_0_class_options(mc);
+ SET_MACHINE_COMPAT(mc, CCW_COMPAT_3_1);
}
-DEFINE_CCW_MACHINE(3_1, "3.1", true);
+DEFINE_CCW_MACHINE(3_1, "3.1", false);
static void ccw_machine_3_0_instance_options(MachineState *machine)
{
diff --git a/hw/s390x/tod-kvm.c b/hw/s390x/tod-kvm.c
index df564ab89c..2456bf7b24 100644
--- a/hw/s390x/tod-kvm.c
+++ b/hw/s390x/tod-kvm.c
@@ -10,10 +10,11 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
+#include "sysemu/sysemu.h"
#include "hw/s390x/tod.h"
#include "kvm_s390x.h"
-static void kvm_s390_tod_get(const S390TODState *td, S390TOD *tod, Error **errp)
+static void kvm_s390_get_tod_raw(S390TOD *tod, Error **errp)
{
int r;
@@ -27,7 +28,17 @@ static void kvm_s390_tod_get(const S390TODState *td, S390TOD *tod, Error **errp)
}
}
-static void kvm_s390_tod_set(S390TODState *td, const S390TOD *tod, Error **errp)
+static void kvm_s390_tod_get(const S390TODState *td, S390TOD *tod, Error **errp)
+{
+ if (td->stopped) {
+ *tod = td->base;
+ return;
+ }
+
+ kvm_s390_get_tod_raw(tod, errp);
+}
+
+static void kvm_s390_set_tod_raw(const S390TOD *tod, Error **errp)
{
int r;
@@ -41,18 +52,105 @@ static void kvm_s390_tod_set(S390TODState *td, const S390TOD *tod, Error **errp)
}
}
+static void kvm_s390_tod_set(S390TODState *td, const S390TOD *tod, Error **errp)
+{
+ Error *local_err = NULL;
+
+ /*
+ * Somebody (e.g. migration) set the TOD. We'll store it into KVM to
+ * properly detect errors now but take a look at the runstate to decide
+ * whether really to keep the tod running. E.g. during migration, this
+ * is the point where we want to stop the initially running TOD to fire
+ * it back up when actually starting the migrated guest.
+ */
+ kvm_s390_set_tod_raw(tod, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
+ }
+
+ if (runstate_is_running()) {
+ td->stopped = false;
+ } else {
+ td->stopped = true;
+ td->base = *tod;
+ }
+}
+
+static void kvm_s390_tod_vm_state_change(void *opaque, int running,
+ RunState state)
+{
+ S390TODState *td = opaque;
+ Error *local_err = NULL;
+
+ if (running && td->stopped) {
+ /* Set the old TOD when running the VM - start the TOD clock. */
+ kvm_s390_set_tod_raw(&td->base, &local_err);
+ if (local_err) {
+ warn_report_err(local_err);
+ }
+ /* Treat errors like the TOD was running all the time. */
+ td->stopped = false;
+ } else if (!running && !td->stopped) {
+ /* Store the TOD when stopping the VM - stop the TOD clock. */
+ kvm_s390_get_tod_raw(&td->base, &local_err);
+ if (local_err) {
+ /* Keep the TOD running in case we could not back it up. */
+ warn_report_err(local_err);
+ } else {
+ td->stopped = true;
+ }
+ }
+}
+
+static void kvm_s390_tod_realize(DeviceState *dev, Error **errp)
+{
+ S390TODState *td = S390_TOD(dev);
+ S390TODClass *tdc = S390_TOD_GET_CLASS(td);
+ Error *local_err = NULL;
+
+ tdc->parent_realize(dev, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
+ }
+
+ /*
+ * We need to know when the VM gets started/stopped to start/stop the TOD.
+ * As we can never have more than one TOD instance (and that will never be
+ * removed), registering here and never unregistering is good enough.
+ */
+ qemu_add_vm_change_state_handler(kvm_s390_tod_vm_state_change, td);
+}
+
static void kvm_s390_tod_class_init(ObjectClass *oc, void *data)
{
S390TODClass *tdc = S390_TOD_CLASS(oc);
+ device_class_set_parent_realize(DEVICE_CLASS(oc), kvm_s390_tod_realize,
+ &tdc->parent_realize);
tdc->get = kvm_s390_tod_get;
tdc->set = kvm_s390_tod_set;
}
+static void kvm_s390_tod_init(Object *obj)
+{
+ S390TODState *td = S390_TOD(obj);
+
+ /*
+ * The TOD is initially running (value stored in KVM). Avoid needless
+ * loading/storing of the TOD when starting a simple VM, so let it
+ * run although the (never started) VM is stopped. For migration, we
+ * will properly set the TOD later.
+ */
+ td->stopped = false;
+}
+
static TypeInfo kvm_s390_tod_info = {
.name = TYPE_KVM_S390_TOD,
.parent = TYPE_S390_TOD,
.instance_size = sizeof(S390TODState),
+ .instance_init = kvm_s390_tod_init,
.class_init = kvm_s390_tod_class_init,
.class_size = sizeof(S390TODClass),
};
diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index 212b3d3dea..c2b78c8e9b 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -287,18 +287,18 @@ static int virtio_ccw_handle_set_vq(SubchDev *sch, CCW1 ccw, bool check_len,
}
if (is_legacy) {
ccw_dstream_read(&sch->cds, linfo);
- be64_to_cpus(&linfo.queue);
- be32_to_cpus(&linfo.align);
- be16_to_cpus(&linfo.index);
- be16_to_cpus(&linfo.num);
+ linfo.queue = be64_to_cpu(linfo.queue);
+ linfo.align = be32_to_cpu(linfo.align);
+ linfo.index = be16_to_cpu(linfo.index);
+ linfo.num = be16_to_cpu(linfo.num);
ret = virtio_ccw_set_vqs(sch, NULL, &linfo);
} else {
ccw_dstream_read(&sch->cds, info);
- be64_to_cpus(&info.desc);
- be16_to_cpus(&info.index);
- be16_to_cpus(&info.num);
- be64_to_cpus(&info.avail);
- be64_to_cpus(&info.used);
+ info.desc = be64_to_cpu(info.desc);
+ info.index = be16_to_cpu(info.index);
+ info.num = be16_to_cpu(info.num);
+ info.avail = be64_to_cpu(info.avail);
+ info.used = be64_to_cpu(info.used);
ret = virtio_ccw_set_vqs(sch, &info, NULL);
}
sch->curr_status.scsw.count = 0;
@@ -382,7 +382,7 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
features.features = 0;
}
ccw_dstream_rewind(&sch->cds);
- cpu_to_le32s(&features.features);
+ features.features = cpu_to_le32(features.features);
ccw_dstream_write(&sch->cds, features.features);
sch->curr_status.scsw.count = ccw.count - sizeof(features);
ret = 0;
@@ -403,7 +403,7 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
ret = -EFAULT;
} else {
ccw_dstream_read(&sch->cds, features);
- le32_to_cpus(&features.features);
+ features.features = le32_to_cpu(features.features);
if (features.index == 0) {
virtio_set_features(vdev,
(vdev->guest_features & 0xffffffff00000000ULL) |
@@ -546,7 +546,7 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
ret = -EFAULT;
} else {
ccw_dstream_read(&sch->cds, indicators);
- be64_to_cpus(&indicators);
+ indicators = be64_to_cpu(indicators);
dev->indicators = get_indicator(indicators, sizeof(uint64_t));
sch->curr_status.scsw.count = ccw.count - sizeof(indicators);
ret = 0;
@@ -567,7 +567,7 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
ret = -EFAULT;
} else {
ccw_dstream_read(&sch->cds, indicators);
- be64_to_cpus(&indicators);
+ indicators = be64_to_cpu(indicators);
dev->indicators2 = get_indicator(indicators, sizeof(uint64_t));
sch->curr_status.scsw.count = ccw.count - sizeof(indicators);
ret = 0;
@@ -588,14 +588,14 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
ret = -EFAULT;
} else {
ccw_dstream_read(&sch->cds, vq_config.index);
- be16_to_cpus(&vq_config.index);
+ vq_config.index = be16_to_cpu(vq_config.index);
if (vq_config.index >= VIRTIO_QUEUE_MAX) {
ret = -EINVAL;
break;
}
vq_config.num_max = virtio_queue_get_num(vdev,
vq_config.index);
- cpu_to_be16s(&vq_config.num_max);
+ vq_config.num_max = cpu_to_be16(vq_config.num_max);
ccw_dstream_write(&sch->cds, vq_config.num_max);
sch->curr_status.scsw.count = ccw.count - sizeof(vq_config);
ret = 0;
@@ -621,9 +621,11 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
if (ccw_dstream_read(&sch->cds, thinint)) {
ret = -EFAULT;
} else {
- be64_to_cpus(&thinint.ind_bit);
- be64_to_cpus(&thinint.summary_indicator);
- be64_to_cpus(&thinint.device_indicator);
+ thinint.ind_bit = be64_to_cpu(thinint.ind_bit);
+ thinint.summary_indicator =
+ be64_to_cpu(thinint.summary_indicator);
+ thinint.device_indicator =
+ be64_to_cpu(thinint.device_indicator);
dev->summary_indicator =
get_indicator(thinint.summary_indicator, sizeof(uint8_t));
@@ -654,8 +656,8 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
break;
}
ccw_dstream_read_buf(&sch->cds, &revinfo, 4);
- be16_to_cpus(&revinfo.revision);
- be16_to_cpus(&revinfo.length);
+ revinfo.revision = be16_to_cpu(revinfo.revision);
+ revinfo.length = be16_to_cpu(revinfo.length);
if (ccw.count < len + revinfo.length ||
(check_len && ccw.count > len + revinfo.length)) {
ret = -EINVAL;
diff --git a/hw/timer/etraxfs_timer.c b/hw/timer/etraxfs_timer.c
index d13bc30b2d..2280914b1d 100644
--- a/hw/timer/etraxfs_timer.c
+++ b/hw/timer/etraxfs_timer.c
@@ -315,9 +315,10 @@ static void etraxfs_timer_reset(void *opaque)
qemu_irq_lower(t->irq);
}
-static int etraxfs_timer_init(SysBusDevice *dev)
+static void etraxfs_timer_realize(DeviceState *dev, Error **errp)
{
ETRAXTimerState *t = ETRAX_TIMER(dev);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
t->bh_t0 = qemu_bh_new(timer0_hit, t);
t->bh_t1 = qemu_bh_new(timer1_hit, t);
@@ -326,21 +327,20 @@ static int etraxfs_timer_init(SysBusDevice *dev)
t->ptimer_t1 = ptimer_init(t->bh_t1, PTIMER_POLICY_DEFAULT);
t->ptimer_wd = ptimer_init(t->bh_wd, PTIMER_POLICY_DEFAULT);
- sysbus_init_irq(dev, &t->irq);
- sysbus_init_irq(dev, &t->nmi);
+ sysbus_init_irq(sbd, &t->irq);
+ sysbus_init_irq(sbd, &t->nmi);
memory_region_init_io(&t->mmio, OBJECT(t), &timer_ops, t,
"etraxfs-timer", 0x5c);
- sysbus_init_mmio(dev, &t->mmio);
+ sysbus_init_mmio(sbd, &t->mmio);
qemu_register_reset(etraxfs_timer_reset, t);
- return 0;
}
static void etraxfs_timer_class_init(ObjectClass *klass, void *data)
{
- SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+ DeviceClass *dc = DEVICE_CLASS(klass);
- sdc->init = etraxfs_timer_init;
+ dc->realize = etraxfs_timer_realize;
}
static const TypeInfo etraxfs_timer_info = {
diff --git a/hw/timer/grlib_gptimer.c b/hw/timer/grlib_gptimer.c
index 4ed96e970a..183eddc073 100644
--- a/hw/timer/grlib_gptimer.c
+++ b/hw/timer/grlib_gptimer.c
@@ -347,10 +347,11 @@ static void grlib_gptimer_reset(DeviceState *d)
}
}
-static int grlib_gptimer_init(SysBusDevice *dev)
+static void grlib_gptimer_realize(DeviceState *dev, Error **errp)
{
GPTimerUnit *unit = GRLIB_GPTIMER(dev);
unsigned int i;
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
assert(unit->nr_timers > 0);
assert(unit->nr_timers <= GPTIMER_MAX_TIMERS);
@@ -366,7 +367,7 @@ static int grlib_gptimer_init(SysBusDevice *dev)
timer->id = i;
/* One IRQ line for each timer */
- sysbus_init_irq(dev, &timer->irq);
+ sysbus_init_irq(sbd, &timer->irq);
ptimer_set_freq(timer->ptimer, unit->freq_hz);
}
@@ -375,8 +376,7 @@ static int grlib_gptimer_init(SysBusDevice *dev)
unit, "gptimer",
UNIT_REG_SIZE + GPTIMER_REG_SIZE * unit->nr_timers);
- sysbus_init_mmio(dev, &unit->iomem);
- return 0;
+ sysbus_init_mmio(sbd, &unit->iomem);
}
static Property grlib_gptimer_properties[] = {
@@ -389,9 +389,8 @@ static Property grlib_gptimer_properties[] = {
static void grlib_gptimer_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
- SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
- k->init = grlib_gptimer_init;
+ dc->realize = grlib_gptimer_realize;
dc->reset = grlib_gptimer_reset;
dc->props = grlib_gptimer_properties;
}
diff --git a/hw/timer/puv3_ost.c b/hw/timer/puv3_ost.c
index 0b3d717e60..3be58c7fdd 100644
--- a/hw/timer/puv3_ost.c
+++ b/hw/timer/puv3_ost.c
@@ -113,16 +113,17 @@ static void puv3_ost_tick(void *opaque)
}
}
-static int puv3_ost_init(SysBusDevice *dev)
+static void puv3_ost_realize(DeviceState *dev, Error **errp)
{
PUV3OSTState *s = PUV3_OST(dev);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
s->reg_OIER = 0;
s->reg_OSSR = 0;
s->reg_OSMR0 = 0;
s->reg_OSCR = 0;
- sysbus_init_irq(dev, &s->irq);
+ sysbus_init_irq(sbd, &s->irq);
s->bh = qemu_bh_new(puv3_ost_tick, s);
s->ptimer = ptimer_init(s->bh, PTIMER_POLICY_DEFAULT);
@@ -130,16 +131,14 @@ static int puv3_ost_init(SysBusDevice *dev)
memory_region_init_io(&s->iomem, OBJECT(s), &puv3_ost_ops, s, "puv3_ost",
PUV3_REGS_OFFSET);
- sysbus_init_mmio(dev, &s->iomem);
-
- return 0;
+ sysbus_init_mmio(sbd, &s->iomem);
}
static void puv3_ost_class_init(ObjectClass *klass, void *data)
{
- SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+ DeviceClass *dc = DEVICE_CLASS(klass);
- sdc->init = puv3_ost_init;
+ dc->realize = puv3_ost_realize;
}
static const TypeInfo puv3_ost_info = {
diff --git a/hw/timer/sun4v-rtc.c b/hw/timer/sun4v-rtc.c
index 4e7f6a1eff..b93cbd6a81 100644
--- a/hw/timer/sun4v-rtc.c
+++ b/hw/timer/sun4v-rtc.c
@@ -41,7 +41,7 @@ static uint64_t sun4v_rtc_read(void *opaque, hwaddr addr,
static void sun4v_rtc_write(void *opaque, hwaddr addr,
uint64_t val, unsigned size)
{
- trace_sun4v_rtc_read(addr, val);
+ trace_sun4v_rtc_write(addr, val);
}
static const MemoryRegionOps sun4v_rtc_ops = {
diff --git a/hw/tpm/tpm_tis.c b/hw/tpm/tpm_tis.c
index d9322692ee..2563d7501f 100644
--- a/hw/tpm/tpm_tis.c
+++ b/hw/tpm/tpm_tis.c
@@ -233,7 +233,7 @@ static void tpm_tis_new_active_locality(TPMState *s, uint8_t new_active_locty)
}
/* abort -- this function switches the locality */
-static void tpm_tis_abort(TPMState *s, uint8_t locty)
+static void tpm_tis_abort(TPMState *s)
{
s->rw_offset = 0;
@@ -263,7 +263,9 @@ static void tpm_tis_prep_abort(TPMState *s, uint8_t locty, uint8_t newlocty)
{
uint8_t busy_locty;
- s->aborting_locty = locty;
+ assert(TPM_TIS_IS_VALID_LOCTY(newlocty));
+
+ s->aborting_locty = locty; /* may also be TPM_TIS_NO_LOCALITY */
s->next_locty = newlocty; /* locality after successful abort */
/*
@@ -281,7 +283,7 @@ static void tpm_tis_prep_abort(TPMState *s, uint8_t locty, uint8_t newlocty)
}
}
- tpm_tis_abort(s, locty);
+ tpm_tis_abort(s);
}
/*
@@ -293,6 +295,8 @@ static void tpm_tis_request_completed(TPMIf *ti, int ret)
uint8_t locty = s->cmd.locty;
uint8_t l;
+ assert(TPM_TIS_IS_VALID_LOCTY(locty));
+
if (s->cmd.selftest_done) {
for (l = 0; l < TPM_TIS_NUM_LOCALITIES; l++) {
s->loc[l].sts |= TPM_TIS_STS_SELFTEST_DONE;
@@ -311,7 +315,7 @@ static void tpm_tis_request_completed(TPMIf *ti, int ret)
}
if (TPM_TIS_IS_VALID_LOCTY(s->next_locty)) {
- tpm_tis_abort(s, locty);
+ tpm_tis_abort(s);
}
tpm_tis_raise_irq(s, locty,
diff --git a/hw/usb/tusb6010.c b/hw/usb/tusb6010.c
index a2128024c1..501706e2b2 100644
--- a/hw/usb/tusb6010.c
+++ b/hw/usb/tusb6010.c
@@ -808,10 +808,10 @@ static void tusb6010_reset(DeviceState *dev)
musb_reset(s->musb);
}
-static int tusb6010_init(SysBusDevice *sbd)
+static void tusb6010_realize(DeviceState *dev, Error **errp)
{
- DeviceState *dev = DEVICE(sbd);
TUSBState *s = TUSB(dev);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
s->otg_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, tusb_otg_tick, s);
s->pwr_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, tusb_power_tick, s);
@@ -822,15 +822,13 @@ static int tusb6010_init(SysBusDevice *sbd)
sysbus_init_irq(sbd, &s->irq);
qdev_init_gpio_in(dev, tusb6010_irq, musb_irq_max + 1);
s->musb = musb_init(dev, 1);
- return 0;
}
static void tusb6010_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
- SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
- k->init = tusb6010_init;
+ dc->realize = tusb6010_realize;
dc->reset = tusb6010_reset;
}
diff --git a/hw/vfio/ap.c b/hw/vfio/ap.c
index 65de952f44..0a25f5e096 100644
--- a/hw/vfio/ap.c
+++ b/hw/vfio/ap.c
@@ -104,6 +104,14 @@ static void vfio_ap_realize(DeviceState *dev, Error **errp)
vapdev->vdev.name = g_strdup_printf("%s", mdevid);
vapdev->vdev.dev = dev;
+ /*
+ * vfio-ap devices operate in a way compatible with
+ * memory ballooning, as no pages are pinned in the host.
+ * This needs to be set before vfio_get_device() for vfio common to
+ * handle the balloon inhibitor.
+ */
+ vapdev->vdev.balloon_allowed = true;
+
ret = vfio_get_device(vfio_group, mdevid, &vapdev->vdev, &local_err);
if (ret) {
goto out_get_dev_err;
diff --git a/hw/virtio/virtio-rng.c b/hw/virtio/virtio-rng.c
index 855f1b41d1..30493a2586 100644
--- a/hw/virtio/virtio-rng.c
+++ b/hw/virtio/virtio-rng.c
@@ -191,7 +191,7 @@ static void virtio_rng_device_realize(DeviceState *dev, Error **errp)
if (vrng->conf.rng == NULL) {
vrng->conf.default_backend = RNG_RANDOM(object_new(TYPE_RNG_RANDOM));
- user_creatable_complete(OBJECT(vrng->conf.default_backend),
+ user_creatable_complete(USER_CREATABLE(vrng->conf.default_backend),
&local_err);
if (local_err) {
error_propagate(errp, local_err);
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index 5828ed14df..22bd1ac34e 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -796,13 +796,13 @@ static void virtqueue_undo_map_desc(unsigned int out_num, unsigned int in_num,
}
static void virtqueue_map_iovec(VirtIODevice *vdev, struct iovec *sg,
- hwaddr *addr, unsigned int *num_sg,
+ hwaddr *addr, unsigned int num_sg,
int is_write)
{
unsigned int i;
hwaddr len;
- for (i = 0; i < *num_sg; i++) {
+ for (i = 0; i < num_sg; i++) {
len = sg[i].iov_len;
sg[i].iov_base = dma_memory_map(vdev->dma_as,
addr[i], &len, is_write ?
@@ -821,8 +821,8 @@ static void virtqueue_map_iovec(VirtIODevice *vdev, struct iovec *sg,
void virtqueue_map(VirtIODevice *vdev, VirtQueueElement *elem)
{
- virtqueue_map_iovec(vdev, elem->in_sg, elem->in_addr, &elem->in_num, 1);
- virtqueue_map_iovec(vdev, elem->out_sg, elem->out_addr, &elem->out_num, 0);
+ virtqueue_map_iovec(vdev, elem->in_sg, elem->in_addr, elem->in_num, 1);
+ virtqueue_map_iovec(vdev, elem->out_sg, elem->out_addr, elem->out_num, 0);
}
static void *virtqueue_alloc_element(size_t sz, unsigned out_num, unsigned in_num)
diff --git a/hw/xen/xen_backend.c b/hw/xen/xen_backend.c
index 9a8e8771ec..0bc6b1de60 100644
--- a/hw/xen/xen_backend.c
+++ b/hw/xen/xen_backend.c
@@ -809,11 +809,6 @@ static const TypeInfo xensysbus_info = {
}
};
-static int xen_sysdev_init(SysBusDevice *dev)
-{
- return 0;
-}
-
static Property xen_sysdev_properties[] = {
{/* end of property list */},
};
@@ -821,9 +816,7 @@ static Property xen_sysdev_properties[] = {
static void xen_sysdev_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
- SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
- k->init = xen_sysdev_init;
dc->props = xen_sysdev_properties;
dc->bus_type = TYPE_XENSYSBUS;
}
diff --git a/include/chardev/char.h b/include/chardev/char.h
index 7becd8c80c..014566c3de 100644
--- a/include/chardev/char.h
+++ b/include/chardev/char.h
@@ -47,6 +47,9 @@ typedef enum {
QEMU_CHAR_FEATURE_FD_PASS,
/* Whether replay or record mode is enabled */
QEMU_CHAR_FEATURE_REPLAY,
+ /* Whether the gcontext can be changed after calling
+ * qemu_chr_be_update_read_handlers() */
+ QEMU_CHAR_FEATURE_GCONTEXT,
QEMU_CHAR_FEATURE_LAST,
} ChardevFeature;
diff --git a/include/crypto/block.h b/include/crypto/block.h
index cd18f46d56..e729d5bd66 100644
--- a/include/crypto/block.h
+++ b/include/crypto/block.h
@@ -75,6 +75,7 @@ typedef enum {
* @readfunc: callback for reading data from the volume
* @opaque: data to pass to @readfunc
* @flags: bitmask of QCryptoBlockOpenFlags values
+ * @n_threads: allow concurrent I/O from up to @n_threads threads
* @errp: pointer to a NULL-initialized error object
*
* Create a new block encryption object for an existing
@@ -107,6 +108,7 @@ QCryptoBlock *qcrypto_block_open(QCryptoBlockOpenOptions *options,
QCryptoBlockReadFunc readfunc,
void *opaque,
unsigned int flags,
+ size_t n_threads,
Error **errp);
/**
diff --git a/include/hw/acpi/acpi_dev_interface.h b/include/hw/acpi/acpi_dev_interface.h
index dabf4c4fc9..43ff119179 100644
--- a/include/hw/acpi/acpi_dev_interface.h
+++ b/include/hw/acpi/acpi_dev_interface.h
@@ -25,11 +25,7 @@ typedef enum {
INTERFACE_CHECK(AcpiDeviceIf, (obj), \
TYPE_ACPI_DEVICE_IF)
-
-typedef struct AcpiDeviceIf {
- /* <private> */
- Object Parent;
-} AcpiDeviceIf;
+typedef struct AcpiDeviceIf AcpiDeviceIf;
void acpi_send_event(DeviceState *dev, AcpiEventStatusBits event);
diff --git a/include/hw/arm/linux-boot-if.h b/include/hw/arm/linux-boot-if.h
index aba4479a14..7bbdfd1cc6 100644
--- a/include/hw/arm/linux-boot-if.h
+++ b/include/hw/arm/linux-boot-if.h
@@ -16,10 +16,7 @@
#define ARM_LINUX_BOOT_IF(obj) \
INTERFACE_CHECK(ARMLinuxBootIf, (obj), TYPE_ARM_LINUX_BOOT_IF)
-typedef struct ARMLinuxBootIf {
- /*< private >*/
- Object parent_obj;
-} ARMLinuxBootIf;
+typedef struct ARMLinuxBootIf ARMLinuxBootIf;
typedef struct ARMLinuxBootIfClass {
/*< private >*/
diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
index 9da621e4b6..ec7c859d08 100644
--- a/include/hw/arm/xlnx-versal.h
+++ b/include/hw/arm/xlnx-versal.h
@@ -22,7 +22,7 @@
#define XLNX_VERSAL_NR_ACPUS 2
#define XLNX_VERSAL_NR_UARTS 2
#define XLNX_VERSAL_NR_GEMS 2
-#define XLNX_VERSAL_NR_IRQS 256
+#define XLNX_VERSAL_NR_IRQS 192
typedef struct Versal {
/*< private >*/
@@ -75,9 +75,9 @@ typedef struct Versal {
#define VERSAL_GEM1_IRQ_0 58
#define VERSAL_GEM1_WAKE_IRQ_0 59
-/* Architecturally eserved IRQs suitable for virtualization. */
-#define VERSAL_RSVD_HIGH_IRQ_FIRST 160
-#define VERSAL_RSVD_HIGH_IRQ_LAST 255
+/* Architecturally reserved IRQs suitable for virtualization. */
+#define VERSAL_RSVD_IRQ_FIRST 111
+#define VERSAL_RSVD_IRQ_LAST 118
#define MM_TOP_RSVD 0xa0000000U
#define MM_TOP_RSVD_SIZE 0x4000000
diff --git a/include/hw/compat.h b/include/hw/compat.h
index 6f4d5fc647..70958328fe 100644
--- a/include/hw/compat.h
+++ b/include/hw/compat.h
@@ -1,6 +1,9 @@
#ifndef HW_COMPAT_H
#define HW_COMPAT_H
+#define HW_COMPAT_3_1 \
+ /* empty */
+
#define HW_COMPAT_3_0 \
/* empty */
diff --git a/include/hw/fw-path-provider.h b/include/hw/fw-path-provider.h
index 050cb05d92..5df893a3d8 100644
--- a/include/hw/fw-path-provider.h
+++ b/include/hw/fw-path-provider.h
@@ -30,9 +30,7 @@
#define FW_PATH_PROVIDER(obj) \
INTERFACE_CHECK(FWPathProvider, (obj), TYPE_FW_PATH_PROVIDER)
-typedef struct FWPathProvider {
- Object parent_obj;
-} FWPathProvider;
+typedef struct FWPathProvider FWPathProvider;
typedef struct FWPathProviderClass {
InterfaceClass parent_class;
diff --git a/include/hw/hotplug.h b/include/hw/hotplug.h
index 1a0516a479..6321e292fd 100644
--- a/include/hw/hotplug.h
+++ b/include/hw/hotplug.h
@@ -23,11 +23,7 @@
#define HOTPLUG_HANDLER(obj) \
INTERFACE_CHECK(HotplugHandler, (obj), TYPE_HOTPLUG_HANDLER)
-
-typedef struct HotplugHandler {
- /* <private> */
- Object Parent;
-} HotplugHandler;
+typedef struct HotplugHandler HotplugHandler;
/**
* hotplug_fn:
diff --git a/include/hw/i2c/i2c.h b/include/hw/i2c/i2c.h
index 5dc166158b..cf4c45a98f 100644
--- a/include/hw/i2c/i2c.h
+++ b/include/hw/i2c/i2c.h
@@ -82,6 +82,8 @@ int i2c_recv(I2CBus *bus);
DeviceState *i2c_create_slave(I2CBus *bus, const char *name, uint8_t addr);
+typedef struct bitbang_i2c_interface bitbang_i2c_interface;
+
/* lm832x.c */
void lm832x_key_event(DeviceState *dev, int key, int state);
diff --git a/include/hw/i2c/ppc4xx_i2c.h b/include/hw/i2c/ppc4xx_i2c.h
index 0891a9c948..b3450bacf7 100644
--- a/include/hw/i2c/ppc4xx_i2c.h
+++ b/include/hw/i2c/ppc4xx_i2c.h
@@ -31,9 +31,6 @@
#include "hw/sysbus.h"
#include "hw/i2c/i2c.h"
-/* from hw/i2c/bitbang_i2c.h */
-typedef struct bitbang_i2c_interface bitbang_i2c_interface;
-
#define TYPE_PPC4xx_I2C "ppc4xx-i2c"
#define PPC4xx_I2C(obj) OBJECT_CHECK(PPC4xxI2CState, (obj), TYPE_PPC4xx_I2C)
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index 136fe497b6..9d29c4b1df 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -49,9 +49,9 @@ struct PCMachineState {
AcpiNVDIMMState acpi_nvdimm_state;
bool acpi_build_enabled;
- bool smbus;
- bool sata;
- bool pit;
+ bool smbus_enabled;
+ bool sata_enabled;
+ bool pit_enabled;
/* RAM information (sizes, addresses, configuration): */
ram_addr_t below_4g_mem_size, above_4g_mem_size;
@@ -294,6 +294,9 @@ int e820_add_entry(uint64_t, uint64_t, uint32_t);
int e820_get_num_entries(void);
bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *);
+#define PC_COMPAT_3_1 \
+ HW_COMPAT_3_1 \
+
#define PC_COMPAT_3_0 \
HW_COMPAT_3_0 \
{\
diff --git a/include/hw/intc/intc.h b/include/hw/intc/intc.h
index 27d9828943..fb3e8e621f 100644
--- a/include/hw/intc/intc.h
+++ b/include/hw/intc/intc.h
@@ -15,9 +15,7 @@
INTERFACE_CHECK(InterruptStatsProvider, (obj), \
TYPE_INTERRUPT_STATS_PROVIDER)
-typedef struct InterruptStatsProvider {
- Object parent;
-} InterruptStatsProvider;
+typedef struct InterruptStatsProvider InterruptStatsProvider;
typedef struct InterruptStatsProviderClass {
InterfaceClass parent;
diff --git a/include/hw/ipmi/ipmi.h b/include/hw/ipmi/ipmi.h
index 0affe5a4d8..99661d2bf0 100644
--- a/include/hw/ipmi/ipmi.h
+++ b/include/hw/ipmi/ipmi.h
@@ -114,9 +114,7 @@ uint32_t ipmi_next_uuid(void);
#define IPMI_INTERFACE_GET_CLASS(class) \
OBJECT_GET_CLASS(IPMIInterfaceClass, (class), TYPE_IPMI_INTERFACE)
-typedef struct IPMIInterface {
- Object parent;
-} IPMIInterface;
+typedef struct IPMIInterface IPMIInterface;
typedef struct IPMIInterfaceClass {
InterfaceClass parent;
diff --git a/include/hw/isa/isa.h b/include/hw/isa/isa.h
index b9dbab24b4..e62ac91c19 100644
--- a/include/hw/isa/isa.h
+++ b/include/hw/isa/isa.h
@@ -43,10 +43,6 @@ static inline uint16_t applesmc_port(void)
#define ISADMA(obj) \
INTERFACE_CHECK(IsaDma, (obj), TYPE_ISADMA)
-struct IsaDma {
- Object parent;
-};
-
typedef enum {
ISADMA_TRANSFER_VERIFY,
ISADMA_TRANSFER_READ,
diff --git a/include/hw/mem/memory-device.h b/include/hw/mem/memory-device.h
index e904e194d5..0293a96abb 100644
--- a/include/hw/mem/memory-device.h
+++ b/include/hw/mem/memory-device.h
@@ -25,9 +25,7 @@
#define MEMORY_DEVICE(obj) \
INTERFACE_CHECK(MemoryDeviceState, (obj), TYPE_MEMORY_DEVICE)
-typedef struct MemoryDeviceState {
- Object parent_obj;
-} MemoryDeviceState;
+typedef struct MemoryDeviceState MemoryDeviceState;
/**
* MemoryDeviceClass:
diff --git a/include/hw/nmi.h b/include/hw/nmi.h
index d092c684a1..ad857f3832 100644
--- a/include/hw/nmi.h
+++ b/include/hw/nmi.h
@@ -34,9 +34,7 @@
#define NMI(obj) \
INTERFACE_CHECK(NMI, (obj), TYPE_NMI)
-typedef struct NMIState {
- Object parent_obj;
-} NMIState;
+typedef struct NMIState NMIState;
typedef struct NMIClass {
InterfaceClass parent_class;
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
index a24d0dd566..92851e55df 100644
--- a/include/hw/qdev-core.h
+++ b/include/hw/qdev-core.h
@@ -197,7 +197,7 @@ typedef struct BusChild {
/**
* BusState:
- * @hotplug_device: link to a hotplug device associated with bus.
+ * @hotplug_handler: link to a hotplug handler associated with bus.
*/
struct BusState {
Object obj;
diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h
index 4f60cc88f3..3ab9cd2eb6 100644
--- a/include/hw/qdev-properties.h
+++ b/include/hw/qdev-properties.h
@@ -249,42 +249,12 @@ void qdev_prop_set_enum(DeviceState *dev, const char *name, int value);
void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value);
void qdev_prop_register_global(GlobalProperty *prop);
-void qdev_prop_register_global_list(GlobalProperty *props);
int qdev_prop_check_globals(void);
void qdev_prop_set_globals(DeviceState *dev);
void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev,
Property *prop, const char *value);
/**
- * register_compat_prop:
- *
- * Register internal (not user-provided) global property, changing the
- * default value of a given property in a device type. This can be used
- * for enabling machine-type compatibility or for enabling
- * accelerator-specific defaults in devices.
- *
- * The property values set using this function must be always valid and
- * never report setter errors, as the property will have
- * GlobalProperty::errp set to &error_abort.
- *
- * User-provided global properties should override internal global
- * properties, so callers of this function should ensure that it is
- * called before user-provided global properties are registered.
- *
- * @driver: Device type to be affected
- * @property: Property whose default value is going to be changed
- * @value: New default value for the property
- */
-void register_compat_prop(const char *driver, const char *property,
- const char *value);
-/*
- * register_compat_props_array(): using register_compat_prop(), which
- * only registers internal global properties (which has lower priority
- * than user-provided global properties)
- */
-void register_compat_props_array(GlobalProperty *prop);
-
-/**
* qdev_property_add_static:
* @dev: Device to add the property to.
* @prop: The qdev property definition.
diff --git a/include/hw/s390x/tod.h b/include/hw/s390x/tod.h
index 413c0d7c02..cbd7552e7a 100644
--- a/include/hw/s390x/tod.h
+++ b/include/hw/s390x/tod.h
@@ -31,13 +31,19 @@ typedef struct S390TODState {
/* private */
DeviceState parent_obj;
- /* unused by KVM implementation */
+ /*
+ * Used by TCG to remember the time base. Used by KVM to backup the TOD
+ * while the TOD is stopped.
+ */
S390TOD base;
+ /* Used by KVM to remember if the TOD is stopped and base is valid. */
+ bool stopped;
} S390TODState;
typedef struct S390TODClass {
/* private */
DeviceClass parent_class;
+ void (*parent_realize)(DeviceState *dev, Error **errp);
/* public */
void (*get)(const S390TODState *td, S390TOD *tod, Error **errp);
diff --git a/include/hw/stream.h b/include/hw/stream.h
index c370ba0c66..15774f07ab 100644
--- a/include/hw/stream.h
+++ b/include/hw/stream.h
@@ -14,9 +14,7 @@
#define STREAM_SLAVE(obj) \
INTERFACE_CHECK(StreamSlave, (obj), TYPE_STREAM_SLAVE)
-typedef struct StreamSlave {
- Object Parent;
-} StreamSlave;
+typedef struct StreamSlave StreamSlave;
typedef void (*StreamCanPushNotifyFn)(void *opaque);
diff --git a/include/hw/sysbus.h b/include/hw/sysbus.h
index 0b59a3b8d6..1aedcf05c9 100644
--- a/include/hw/sysbus.h
+++ b/include/hw/sysbus.h
@@ -38,9 +38,6 @@ typedef struct SysBusDevice SysBusDevice;
typedef struct SysBusDeviceClass {
/*< private >*/
DeviceClass parent_class;
- /*< public >*/
-
- int (*init)(SysBusDevice *dev);
/*
* Let the sysbus device format its own non-PIO, non-MMIO unit address.
diff --git a/include/hw/timer/m48t59.h b/include/hw/timer/m48t59.h
index db5e43a8da..6f8db04fce 100644
--- a/include/hw/timer/m48t59.h
+++ b/include/hw/timer/m48t59.h
@@ -13,9 +13,7 @@
#define NVRAM(obj) \
INTERFACE_CHECK(Nvram, (obj), TYPE_NVRAM)
-typedef struct Nvram {
- Object parent;
-} Nvram;
+typedef struct Nvram Nvram;
typedef struct NvramClass {
InterfaceClass parent;
diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h
index 6fd2c53b09..c1b40a9cac 100644
--- a/include/monitor/monitor.h
+++ b/include/monitor/monitor.h
@@ -13,7 +13,8 @@ extern __thread Monitor *cur_mon;
#define MONITOR_USE_READLINE 0x02
#define MONITOR_USE_CONTROL 0x04
#define MONITOR_USE_PRETTY 0x08
-#define MONITOR_USE_OOB 0x10
+
+#define QMP_REQ_QUEUE_LEN_MAX 8
bool monitor_cur_is_qmp(void);
diff --git a/include/qapi/string-input-visitor.h b/include/qapi/string-input-visitor.h
index 33551340e3..921f3875b9 100644
--- a/include/qapi/string-input-visitor.h
+++ b/include/qapi/string-input-visitor.h
@@ -19,8 +19,8 @@ typedef struct StringInputVisitor StringInputVisitor;
/*
* The string input visitor does not implement support for visiting
- * QAPI structs, alternates, null, or arbitrary QTypes. It also
- * requires a non-null list argument to visit_start_list().
+ * QAPI structs, alternates, null, or arbitrary QTypes. Only flat lists
+ * of integers (except type "size") are supported.
*/
Visitor *string_input_visitor_new(const char *str);
diff --git a/include/qemu/compiler.h b/include/qemu/compiler.h
index 6b92710487..261842beae 100644
--- a/include/qemu/compiler.h
+++ b/include/qemu/compiler.h
@@ -28,12 +28,6 @@
#define QEMU_SENTINEL __attribute__((sentinel))
-#if QEMU_GNUC_PREREQ(4, 3)
-#define QEMU_ARTIFICIAL __attribute__((always_inline, artificial))
-#else
-#define QEMU_ARTIFICIAL
-#endif
-
#if defined(_WIN32)
# define QEMU_PACKED __attribute__((gcc_struct, packed))
#else
@@ -127,7 +121,7 @@
#define __has_builtin(x) 0 /* compatibility with non-clang compilers */
#endif
-#if __has_builtin(__builtin_assume_aligned) || QEMU_GNUC_PREREQ(4, 7)
+#if __has_builtin(__builtin_assume_aligned) || !defined(__clang__)
#define HAS_ASSUME_ALIGNED
#endif
diff --git a/include/qemu/cutils.h b/include/qemu/cutils.h
index 7071bfe2d4..d2dad3057c 100644
--- a/include/qemu/cutils.h
+++ b/include/qemu/cutils.h
@@ -146,14 +146,16 @@ int qemu_strtoi64(const char *nptr, const char **endptr, int base,
int64_t *result);
int qemu_strtou64(const char *nptr, const char **endptr, int base,
uint64_t *result);
+int qemu_strtod(const char *nptr, const char **endptr, double *result);
+int qemu_strtod_finite(const char *nptr, const char **endptr, double *result);
int parse_uint(const char *s, unsigned long long *value, char **endptr,
int base);
int parse_uint_full(const char *s, unsigned long long *value, int base);
-int qemu_strtosz(const char *nptr, char **end, uint64_t *result);
-int qemu_strtosz_MiB(const char *nptr, char **end, uint64_t *result);
-int qemu_strtosz_metric(const char *nptr, char **end, uint64_t *result);
+int qemu_strtosz(const char *nptr, const char **end, uint64_t *result);
+int qemu_strtosz_MiB(const char *nptr, const char **end, uint64_t *result);
+int qemu_strtosz_metric(const char *nptr, const char **end, uint64_t *result);
/* used to print char* safely */
#define STR_OR_NULL(str) ((str) ? (str) : "null")
diff --git a/include/qemu/host-utils.h b/include/qemu/host-utils.h
index 38da849be9..4cd170e6cd 100644
--- a/include/qemu/host-utils.h
+++ b/include/qemu/host-utils.h
@@ -207,7 +207,7 @@ static inline int cto64(uint64_t val)
*/
static inline int clrsb32(uint32_t val)
{
-#if QEMU_GNUC_PREREQ(4, 7)
+#if __has_builtin(__builtin_clrsb) || !defined(__clang__)
return __builtin_clrsb(val);
#else
return clz32(val ^ ((int32_t)val >> 1)) - 1;
@@ -223,7 +223,7 @@ static inline int clrsb32(uint32_t val)
*/
static inline int clrsb64(uint64_t val)
{
-#if QEMU_GNUC_PREREQ(4, 7)
+#if __has_builtin(__builtin_clrsbll) || !defined(__clang__)
return __builtin_clrsbll(val);
#else
return clz64(val ^ ((int64_t)val >> 1)) - 1;
diff --git a/include/qemu/range.h b/include/qemu/range.h
index f28f0c1825..7e75f4e655 100644
--- a/include/qemu/range.h
+++ b/include/qemu/range.h
@@ -39,7 +39,7 @@ struct Range {
uint64_t upb; /* inclusive upper bound */
};
-static inline void range_invariant(Range *range)
+static inline void range_invariant(const Range *range)
{
assert(range->lob <= range->upb || range->lob == range->upb + 1);
}
@@ -48,14 +48,14 @@ static inline void range_invariant(Range *range)
#define range_empty ((Range){ .lob = 1, .upb = 0 })
/* Is @range empty? */
-static inline bool range_is_empty(Range *range)
+static inline bool range_is_empty(const Range *range)
{
range_invariant(range);
return range->lob > range->upb;
}
/* Does @range contain @val? */
-static inline bool range_contains(Range *range, uint64_t val)
+static inline bool range_contains(const Range *range, uint64_t val)
{
return val >= range->lob && val <= range->upb;
}
diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h
index 3ec0e13a96..d59df20c4d 100644
--- a/include/qemu/typedefs.h
+++ b/include/qemu/typedefs.h
@@ -61,7 +61,9 @@ typedef struct MSIMessage MSIMessage;
typedef struct NetClientState NetClientState;
typedef struct NetFilterState NetFilterState;
typedef struct NICInfo NICInfo;
+typedef struct NodeInfo NodeInfo;
typedef struct NumaNodeMem NumaNodeMem;
+typedef struct ObjectClass ObjectClass;
typedef struct PCIBridge PCIBridge;
typedef struct PCIBus PCIBus;
typedef struct PCIDevice PCIDevice;
@@ -112,7 +114,6 @@ typedef struct SSIBus SSIBus;
typedef struct uWireSlave uWireSlave;
typedef struct VirtIODevice VirtIODevice;
typedef struct Visitor Visitor;
-typedef struct node_info NodeInfo;
typedef void SaveStateHandler(QEMUFile *f, void *opaque);
typedef int LoadStateHandler(QEMUFile *f, void *opaque, int version_id);
diff --git a/include/qom/object.h b/include/qom/object.h
index f0b0bf39cc..bcae3f4951 100644
--- a/include/qom/object.h
+++ b/include/qom/object.h
@@ -20,7 +20,6 @@
struct TypeImpl;
typedef struct TypeImpl *Type;
-typedef struct ObjectClass ObjectClass;
typedef struct Object Object;
typedef struct TypeInfo TypeInfo;
@@ -455,10 +454,8 @@ struct Object
* parent class initialization has occurred, but before the class itself
* is initialized. This is the function to use to undo the effects of
* memcpy from the parent class to the descendants.
- * @class_finalize: This function is called during class destruction and is
- * meant to release and dynamic parameters allocated by @class_init.
- * @class_data: Data to pass to the @class_init, @class_base_init and
- * @class_finalize functions. This can be useful when building dynamic
+ * @class_data: Data to pass to the @class_init,
+ * @class_base_init. This can be useful when building dynamic
* classes.
* @interfaces: The list of interfaces associated with this type. This
* should point to a static array that's terminated with a zero filled
@@ -479,7 +476,6 @@ struct TypeInfo
void (*class_init)(ObjectClass *klass, void *data);
void (*class_base_init)(ObjectClass *klass, void *data);
- void (*class_finalize)(ObjectClass *klass, void *data);
void *class_data;
InterfaceInfo *interfaces;
diff --git a/include/qom/object_interfaces.h b/include/qom/object_interfaces.h
index 4d513fb329..682ba1d9b0 100644
--- a/include/qom/object_interfaces.h
+++ b/include/qom/object_interfaces.h
@@ -16,11 +16,7 @@
INTERFACE_CHECK(UserCreatable, (obj), \
TYPE_USER_CREATABLE)
-
-typedef struct UserCreatable {
- /* <private> */
- Object Parent;
-} UserCreatable;
+typedef struct UserCreatable UserCreatable;
/**
* UserCreatableClass:
@@ -55,14 +51,14 @@ typedef struct UserCreatableClass {
/**
* user_creatable_complete:
- * @obj: the object whose complete() method is called if defined
+ * @uc: the user-creatable object whose complete() method is called if defined
* @errp: if an error occurs, a pointer to an area to store the error
*
* Wrapper to call complete() method if one of types it's inherited
* from implements USER_CREATABLE interface, otherwise the call does
* nothing.
*/
-void user_creatable_complete(Object *obj, Error **errp);
+void user_creatable_complete(UserCreatable *uc, Error **errp);
/**
* user_creatable_can_be_deleted:
diff --git a/include/sysemu/numa.h b/include/sysemu/numa.h
index 21713b7e2f..b6ac7de43e 100644
--- a/include/sysemu/numa.h
+++ b/include/sysemu/numa.h
@@ -9,7 +9,7 @@
extern int nb_numa_nodes; /* Number of NUMA nodes */
extern bool have_numa_distance;
-struct node_info {
+struct NodeInfo {
uint64_t node_mem;
struct HostMemoryBackend *node_memdev;
bool present;
diff --git a/include/sysemu/tpm.h b/include/sysemu/tpm.h
index 17a97ed77a..5b541a71c8 100644
--- a/include/sysemu/tpm.h
+++ b/include/sysemu/tpm.h
@@ -33,9 +33,7 @@ typedef enum TPMVersion {
#define TPM_IF(obj) \
INTERFACE_CHECK(TPMIf, (obj), TYPE_TPM_IF)
-typedef struct TPMIf {
- Object parent_obj;
-} TPMIf;
+typedef struct TPMIf TPMIf;
typedef struct TPMIfClass {
InterfaceClass parent_class;
diff --git a/migration/colo.c b/migration/colo.c
index fcff04c78c..398b239d1c 100644
--- a/migration/colo.c
+++ b/migration/colo.c
@@ -24,7 +24,9 @@
#include "trace.h"
#include "qemu/error-report.h"
#include "migration/failover.h"
+#ifdef CONFIG_REPLICATION
#include "replication.h"
+#endif
#include "net/colo-compare.h"
#include "net/colo.h"
#include "block/block.h"
@@ -201,11 +203,11 @@ void colo_do_failover(MigrationState *s)
}
}
+#ifdef CONFIG_REPLICATION
void qmp_xen_set_replication(bool enable, bool primary,
bool has_failover, bool failover,
Error **errp)
{
-#ifdef CONFIG_REPLICATION
ReplicationMode mode = primary ?
REPLICATION_MODE_PRIMARY :
REPLICATION_MODE_SECONDARY;
@@ -224,14 +226,10 @@ void qmp_xen_set_replication(bool enable, bool primary,
}
replication_stop_all(failover, failover ? NULL : errp);
}
-#else
- abort();
-#endif
}
ReplicationStatus *qmp_query_xen_replication_status(Error **errp)
{
-#ifdef CONFIG_REPLICATION
Error *err = NULL;
ReplicationStatus *s = g_new0(ReplicationStatus, 1);
@@ -246,19 +244,13 @@ ReplicationStatus *qmp_query_xen_replication_status(Error **errp)
error_free(err);
return s;
-#else
- abort();
-#endif
}
void qmp_xen_colo_do_checkpoint(Error **errp)
{
-#ifdef CONFIG_REPLICATION
replication_do_checkpoint_all(errp);
-#else
- abort();
-#endif
}
+#endif
COLOStatus *qmp_query_colo_status(Error **errp)
{
diff --git a/monitor.c b/monitor.c
index d39390c2f2..7848a3cb0d 100644
--- a/monitor.c
+++ b/monitor.c
@@ -263,10 +263,11 @@ typedef struct QMPRequest QMPRequest;
/* QMP checker flags */
#define QMP_ACCEPT_UNKNOWNS 1
-/* Protects mon_list, monitor_qapi_event_state. */
+/* Protects mon_list, monitor_qapi_event_state, monitor_destroyed. */
static QemuMutex monitor_lock;
static GHashTable *monitor_qapi_event_state;
static QTAILQ_HEAD(mon_list, Monitor) mon_list;
+static bool monitor_destroyed;
/* Protects mon_fdsets */
static QemuMutex mon_fdsets_lock;
@@ -1146,11 +1147,6 @@ static void qmp_query_qmp_schema(QDict *qdict, QObject **ret_data,
*/
static void qmp_unregister_commands_hack(void)
{
-#ifndef CONFIG_REPLICATION
- qmp_unregister_command(&qmp_commands, "xen-set-replication");
- qmp_unregister_command(&qmp_commands, "query-xen-replication-status");
- qmp_unregister_command(&qmp_commands, "xen-colo-do-checkpoint");
-#endif
#ifndef TARGET_I386
qmp_unregister_command(&qmp_commands, "rtc-reset-reinjection");
qmp_unregister_command(&qmp_commands, "query-sev");
@@ -3231,7 +3227,7 @@ static QDict *monitor_parse_arguments(Monitor *mon,
{
int ret;
uint64_t val;
- char *end;
+ const char *end;
while (qemu_isspace(*p)) {
p++;
@@ -4109,8 +4105,12 @@ static void monitor_qmp_dispatch(Monitor *mon, QObject *req, QObject *id)
* processing commands only on a very busy monitor. To achieve that,
* when we process one request on a specific monitor, we put that
* monitor to the end of mon_list queue.
+ *
+ * Note: if the function returned with non-NULL, then the caller will
+ * be with mon->qmp.qmp_queue_lock held, and the caller is responsible
+ * to release it.
*/
-static QMPRequest *monitor_qmp_requests_pop_any(void)
+static QMPRequest *monitor_qmp_requests_pop_any_with_lock(void)
{
QMPRequest *req_obj = NULL;
Monitor *mon;
@@ -4120,10 +4120,11 @@ static QMPRequest *monitor_qmp_requests_pop_any(void)
QTAILQ_FOREACH(mon, &mon_list, entry) {
qemu_mutex_lock(&mon->qmp.qmp_queue_lock);
req_obj = g_queue_pop_head(mon->qmp.qmp_requests);
- qemu_mutex_unlock(&mon->qmp.qmp_queue_lock);
if (req_obj) {
+ /* With the lock of corresponding queue held */
break;
}
+ qemu_mutex_unlock(&mon->qmp.qmp_queue_lock);
}
if (req_obj) {
@@ -4142,30 +4143,34 @@ static QMPRequest *monitor_qmp_requests_pop_any(void)
static void monitor_qmp_bh_dispatcher(void *data)
{
- QMPRequest *req_obj = monitor_qmp_requests_pop_any();
+ QMPRequest *req_obj = monitor_qmp_requests_pop_any_with_lock();
QDict *rsp;
bool need_resume;
+ Monitor *mon;
if (!req_obj) {
return;
}
+ mon = req_obj->mon;
/* qmp_oob_enabled() might change after "qmp_capabilities" */
- need_resume = !qmp_oob_enabled(req_obj->mon);
+ need_resume = !qmp_oob_enabled(mon) ||
+ mon->qmp.qmp_requests->length == QMP_REQ_QUEUE_LEN_MAX - 1;
+ qemu_mutex_unlock(&mon->qmp.qmp_queue_lock);
if (req_obj->req) {
trace_monitor_qmp_cmd_in_band(qobject_get_try_str(req_obj->id) ?: "");
- monitor_qmp_dispatch(req_obj->mon, req_obj->req, req_obj->id);
+ monitor_qmp_dispatch(mon, req_obj->req, req_obj->id);
} else {
assert(req_obj->err);
rsp = qmp_error_response(req_obj->err);
req_obj->err = NULL;
- monitor_qmp_respond(req_obj->mon, rsp, NULL);
+ monitor_qmp_respond(mon, rsp, NULL);
qobject_unref(rsp);
}
if (need_resume) {
/* Pairs with the monitor_suspend() in handle_qmp_command() */
- monitor_resume(req_obj->mon);
+ monitor_resume(mon);
}
qmp_request_free(req_obj);
@@ -4173,8 +4178,6 @@ static void monitor_qmp_bh_dispatcher(void *data)
qemu_bh_schedule(qmp_dispatcher_bh);
}
-#define QMP_REQ_QUEUE_LEN_MAX (8)
-
static void handle_qmp_command(void *opaque, QObject *req, Error *err)
{
Monitor *mon = opaque;
@@ -4216,28 +4219,14 @@ static void handle_qmp_command(void *opaque, QObject *req, Error *err)
qemu_mutex_lock(&mon->qmp.qmp_queue_lock);
/*
- * If OOB is not enabled on the current monitor, we'll emulate the
- * old behavior that we won't process the current monitor any more
- * until it has responded. This helps make sure that as long as
- * OOB is not enabled, the server will never drop any command.
+ * Suspend the monitor when we can't queue more requests after
+ * this one. Dequeuing in monitor_qmp_bh_dispatcher() will resume
+ * it. Note that when OOB is disabled, we queue at most one
+ * command, for backward compatibility.
*/
- if (!qmp_oob_enabled(mon)) {
+ if (!qmp_oob_enabled(mon) ||
+ mon->qmp.qmp_requests->length == QMP_REQ_QUEUE_LEN_MAX - 1) {
monitor_suspend(mon);
- } else {
- /* Drop the request if queue is full. */
- if (mon->qmp.qmp_requests->length >= QMP_REQ_QUEUE_LEN_MAX) {
- qemu_mutex_unlock(&mon->qmp.qmp_queue_lock);
- /*
- * FIXME @id's scope is just @mon, and broadcasting it is
- * wrong. If another monitor's client has a command with
- * the same ID in flight, the event will incorrectly claim
- * that command was dropped.
- */
- qapi_event_send_command_dropped(id,
- COMMAND_DROP_REASON_QUEUE_FULL);
- qmp_request_free(req_obj);
- return;
- }
}
/*
@@ -4245,6 +4234,7 @@ static void handle_qmp_command(void *opaque, QObject *req, Error *err)
* handled in time order. Ownership for req_obj, req, id,
* etc. will be delivered to the handler side.
*/
+ assert(mon->qmp.qmp_requests->length < QMP_REQ_QUEUE_LEN_MAX);
g_queue_push_tail(mon->qmp.qmp_requests, req_obj);
qemu_mutex_unlock(&mon->qmp.qmp_queue_lock);
@@ -4297,7 +4287,7 @@ int monitor_suspend(Monitor *mon)
atomic_inc(&mon->suspend_cnt);
- if (monitor_is_qmp(mon) && mon->use_io_thread) {
+ if (mon->use_io_thread) {
/*
* Kick I/O thread to make sure this takes effect. It'll be
* evaluated again in prepare() of the watch object.
@@ -4309,6 +4299,13 @@ int monitor_suspend(Monitor *mon)
return 0;
}
+static void monitor_accept_input(void *opaque)
+{
+ Monitor *mon = opaque;
+
+ qemu_chr_fe_accept_input(&mon->chr);
+}
+
void monitor_resume(Monitor *mon)
{
if (monitor_is_hmp_non_interactive(mon)) {
@@ -4316,20 +4313,22 @@ void monitor_resume(Monitor *mon)
}
if (atomic_dec_fetch(&mon->suspend_cnt) == 0) {
- if (monitor_is_qmp(mon)) {
- /*
- * For QMP monitors that are running in the I/O thread,
- * let's kick the thread in case it's sleeping.
- */
- if (mon->use_io_thread) {
- aio_notify(iothread_get_aio_context(mon_iothread));
- }
+ AioContext *ctx;
+
+ if (mon->use_io_thread) {
+ ctx = iothread_get_aio_context(mon_iothread);
} else {
+ ctx = qemu_get_aio_context();
+ }
+
+ if (!monitor_is_qmp(mon)) {
assert(mon->rs);
readline_show_prompt(mon->rs);
}
- qemu_chr_fe_accept_input(&mon->chr);
+
+ aio_bh_schedule_oneshot(ctx, monitor_accept_input, mon);
}
+
trace_monitor_suspend(mon, -1);
}
@@ -4453,16 +4452,6 @@ static void sortcmdlist(void)
qsort((void *)info_cmds, array_num, elem_size, compare_mon_cmd);
}
-static GMainContext *monitor_get_io_context(void)
-{
- return iothread_get_g_main_context(mon_iothread);
-}
-
-static AioContext *monitor_get_aio_context(void)
-{
- return iothread_get_aio_context(mon_iothread);
-}
-
static void monitor_iothread_init(void)
{
mon_iothread = iothread_create("mon_iothread", &error_abort);
@@ -4539,8 +4528,21 @@ void error_vprintf_unless_qmp(const char *fmt, va_list ap)
static void monitor_list_append(Monitor *mon)
{
qemu_mutex_lock(&monitor_lock);
- QTAILQ_INSERT_HEAD(&mon_list, mon, entry);
+ /*
+ * This prevents inserting new monitors during monitor_cleanup().
+ * A cleaner solution would involve the main thread telling other
+ * threads to terminate, waiting for their termination.
+ */
+ if (!monitor_destroyed) {
+ QTAILQ_INSERT_HEAD(&mon_list, mon, entry);
+ mon = NULL;
+ }
qemu_mutex_unlock(&monitor_lock);
+
+ if (mon) {
+ monitor_data_destroy(mon);
+ g_free(mon);
+ }
}
static void monitor_qmp_setup_handlers_bh(void *opaque)
@@ -4549,7 +4551,7 @@ static void monitor_qmp_setup_handlers_bh(void *opaque)
GMainContext *context;
assert(mon->use_io_thread);
- context = monitor_get_io_context();
+ context = iothread_get_g_main_context(mon_iothread);
assert(context);
qemu_chr_fe_set_handlers(&mon->chr, monitor_can_read, monitor_qmp_read,
monitor_qmp_event, NULL, mon, context, true);
@@ -4560,21 +4562,12 @@ void monitor_init(Chardev *chr, int flags)
{
Monitor *mon = g_malloc(sizeof(*mon));
bool use_readline = flags & MONITOR_USE_READLINE;
- bool use_oob = flags & MONITOR_USE_OOB;
- if (use_oob) {
- if (CHARDEV_IS_MUX(chr)) {
- error_report("Monitor out-of-band is not supported with "
- "MUX typed chardev backend");
- exit(1);
- }
- if (use_readline) {
- error_report("Monitor out-of-band is only supported by QMP");
- exit(1);
- }
- }
-
- monitor_data_init(mon, false, use_oob);
+ /* Note: we run QMP monitor in I/O thread when @chr supports that */
+ monitor_data_init(mon, false,
+ (flags & MONITOR_USE_CONTROL)
+ && qemu_chr_has_feature(chr,
+ QEMU_CHAR_FEATURE_GCONTEXT));
qemu_chr_fe_init(&mon->chr, chr, &error_abort);
mon->flags = flags;
@@ -4601,7 +4594,7 @@ void monitor_init(Chardev *chr, int flags)
* since chardev might be running in the monitor I/O
* thread. Schedule a bottom half.
*/
- aio_bh_schedule_oneshot(monitor_get_aio_context(),
+ aio_bh_schedule_oneshot(iothread_get_aio_context(mon_iothread),
monitor_qmp_setup_handlers_bh, mon);
/* The bottom half will add @mon to @mon_list */
return;
@@ -4634,10 +4627,14 @@ void monitor_cleanup(void)
/* Flush output buffers and destroy monitors */
qemu_mutex_lock(&monitor_lock);
+ monitor_destroyed = true;
QTAILQ_FOREACH_SAFE(mon, &mon_list, entry, next) {
QTAILQ_REMOVE(&mon_list, mon, entry);
+ /* Permit QAPI event emission from character frontend release */
+ qemu_mutex_unlock(&monitor_lock);
monitor_flush(mon);
monitor_data_destroy(mon);
+ qemu_mutex_lock(&monitor_lock);
g_free(mon);
}
qemu_mutex_unlock(&monitor_lock);
@@ -4665,9 +4662,6 @@ QemuOptsList qemu_mon_opts = {
},{
.name = "pretty",
.type = QEMU_OPT_BOOL,
- },{
- .name = "x-oob",
- .type = QEMU_OPT_BOOL,
},
{ /* end of list */ }
},
diff --git a/net/colo-compare.c b/net/colo-compare.c
index a39191d522..9156ab3349 100644
--- a/net/colo-compare.c
+++ b/net/colo-compare.c
@@ -957,6 +957,12 @@ static int find_and_check_chardev(Chardev **chr,
return 1;
}
+ if (!qemu_chr_has_feature(*chr, QEMU_CHAR_FEATURE_GCONTEXT)) {
+ error_setg(errp, "chardev \"%s\" cannot switch context",
+ chr_name);
+ return 1;
+ }
+
return 0;
}
diff --git a/qapi/block-core.json b/qapi/block-core.json
index d4fe710836..762000f31f 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -1143,8 +1143,10 @@
# This command is now obsolete and will always return an error since 2.10
#
##
-{ 'command': 'block_passwd', 'data': {'*device': 'str',
- '*node-name': 'str', 'password': 'str'} }
+{ 'command': 'block_passwd',
+ 'data': { '*device': 'str',
+ '*node-name': 'str',
+ 'password': 'str' } }
##
# @block_resize:
@@ -1171,9 +1173,10 @@
# <- { "return": {} }
#
##
-{ 'command': 'block_resize', 'data': { '*device': 'str',
- '*node-name': 'str',
- 'size': 'int' }}
+{ 'command': 'block_resize',
+ 'data': { '*device': 'str',
+ '*node-name': 'str',
+ 'size': 'int' } }
##
# @NewImageMode:
@@ -2620,7 +2623,9 @@
'copy-on-read', 'dmg', 'file', 'ftp', 'ftps', 'gluster',
'host_cdrom', 'host_device', 'http', 'https', 'iscsi', 'luks',
'nbd', 'nfs', 'null-aio', 'null-co', 'nvme', 'parallels', 'qcow',
- 'qcow2', 'qed', 'quorum', 'raw', 'rbd', 'replication', 'sheepdog',
+ 'qcow2', 'qed', 'quorum', 'raw', 'rbd',
+ { 'name': 'replication', 'if': 'defined(CONFIG_REPLICATION)' },
+ 'sheepdog',
'ssh', 'throttle', 'vdi', 'vhdx', 'vmdk', 'vpc', 'vvfat', 'vxhs' ] }
##
@@ -3377,7 +3382,8 @@
#
# Since: 2.9
##
-{ 'enum' : 'ReplicationMode', 'data' : [ 'primary', 'secondary' ] }
+{ 'enum' : 'ReplicationMode', 'data' : [ 'primary', 'secondary' ],
+ 'if': 'defined(CONFIG_REPLICATION)' }
##
# @BlockdevOptionsReplication:
@@ -3395,7 +3401,8 @@
{ 'struct': 'BlockdevOptionsReplication',
'base': 'BlockdevOptionsGenericFormat',
'data': { 'mode': 'ReplicationMode',
- '*top-id': 'str' } }
+ '*top-id': 'str' },
+ 'if': 'defined(CONFIG_REPLICATION)' }
##
# @NFSTransport:
@@ -3711,7 +3718,8 @@
'quorum': 'BlockdevOptionsQuorum',
'raw': 'BlockdevOptionsRaw',
'rbd': 'BlockdevOptionsRbd',
- 'replication':'BlockdevOptionsReplication',
+ 'replication': { 'type': 'BlockdevOptionsReplication',
+ 'if': 'defined(CONFIG_REPLICATION)' },
'sheepdog': 'BlockdevOptionsSheepdog',
'ssh': 'BlockdevOptionsSsh',
'throttle': 'BlockdevOptionsThrottle',
diff --git a/qapi/char.json b/qapi/char.json
index 79bac598a0..77ed847972 100644
--- a/qapi/char.json
+++ b/qapi/char.json
@@ -25,9 +25,10 @@
#
# Since: 0.14.0
##
-{ 'struct': 'ChardevInfo', 'data': {'label': 'str',
- 'filename': 'str',
- 'frontend-open': 'bool'} }
+{ 'struct': 'ChardevInfo',
+ 'data': { 'label': 'str',
+ 'filename': 'str',
+ 'frontend-open': 'bool' } }
##
# @query-chardev:
@@ -152,7 +153,8 @@
#
##
{ 'command': 'ringbuf-write',
- 'data': {'device': 'str', 'data': 'str',
+ 'data': { 'device': 'str',
+ 'data': 'str',
'*format': 'DataFormat'} }
##
@@ -202,8 +204,9 @@
#
# Since: 2.6
##
-{ 'struct': 'ChardevCommon', 'data': { '*logfile': 'str',
- '*logappend': 'bool' } }
+{ 'struct': 'ChardevCommon',
+ 'data': { '*logfile': 'str',
+ '*logappend': 'bool' } }
##
# @ChardevFile:
@@ -217,9 +220,10 @@
#
# Since: 1.4
##
-{ 'struct': 'ChardevFile', 'data': { '*in' : 'str',
- 'out' : 'str',
- '*append': 'bool' },
+{ 'struct': 'ChardevFile',
+ 'data': { '*in': 'str',
+ 'out': 'str',
+ '*append': 'bool' },
'base': 'ChardevCommon' }
##
@@ -232,7 +236,8 @@
#
# Since: 1.4
##
-{ 'struct': 'ChardevHostdev', 'data': { 'device' : 'str' },
+{ 'struct': 'ChardevHostdev',
+ 'data': { 'device': 'str' },
'base': 'ChardevCommon' }
##
@@ -260,15 +265,16 @@
#
# Since: 1.4
##
-{ 'struct': 'ChardevSocket', 'data': { 'addr' : 'SocketAddressLegacy',
- '*tls-creds' : 'str',
- '*server' : 'bool',
- '*wait' : 'bool',
- '*nodelay' : 'bool',
- '*telnet' : 'bool',
- '*tn3270' : 'bool',
- '*websocket' : 'bool',
- '*reconnect' : 'int' },
+{ 'struct': 'ChardevSocket',
+ 'data': { 'addr': 'SocketAddressLegacy',
+ '*tls-creds': 'str',
+ '*server': 'bool',
+ '*wait': 'bool',
+ '*nodelay': 'bool',
+ '*telnet': 'bool',
+ '*tn3270': 'bool',
+ '*websocket': 'bool',
+ '*reconnect': 'int' },
'base': 'ChardevCommon' }
##
@@ -281,8 +287,9 @@
#
# Since: 1.5
##
-{ 'struct': 'ChardevUdp', 'data': { 'remote' : 'SocketAddressLegacy',
- '*local' : 'SocketAddressLegacy' },
+{ 'struct': 'ChardevUdp',
+ 'data': { 'remote': 'SocketAddressLegacy',
+ '*local': 'SocketAddressLegacy' },
'base': 'ChardevCommon' }
##
@@ -294,7 +301,8 @@
#
# Since: 1.5
##
-{ 'struct': 'ChardevMux', 'data': { 'chardev' : 'str' },
+{ 'struct': 'ChardevMux',
+ 'data': { 'chardev': 'str' },
'base': 'ChardevCommon' }
##
@@ -308,7 +316,8 @@
#
# Since: 1.5
##
-{ 'struct': 'ChardevStdio', 'data': { '*signal' : 'bool' },
+{ 'struct': 'ChardevStdio',
+ 'data': { '*signal': 'bool' },
'base': 'ChardevCommon' }
@@ -321,9 +330,10 @@
#
# Since: 1.5
##
-{ 'struct': 'ChardevSpiceChannel', 'data': { 'type' : 'str' },
- 'base': 'ChardevCommon' }
-# TODO: 'if': 'defined(CONFIG_SPICE)'
+{ 'struct': 'ChardevSpiceChannel',
+ 'data': { 'type': 'str' },
+ 'base': 'ChardevCommon',
+ 'if': 'defined(CONFIG_SPICE)' }
##
# @ChardevSpicePort:
@@ -334,9 +344,10 @@
#
# Since: 1.5
##
-{ 'struct': 'ChardevSpicePort', 'data': { 'fqdn' : 'str' },
- 'base': 'ChardevCommon' }
-# TODO: 'if': 'defined(CONFIG_SPICE)'
+{ 'struct': 'ChardevSpicePort',
+ 'data': { 'fqdn': 'str' },
+ 'base': 'ChardevCommon',
+ 'if': 'defined(CONFIG_SPICE)' }
##
# @ChardevVC:
@@ -350,10 +361,11 @@
#
# Since: 1.5
##
-{ 'struct': 'ChardevVC', 'data': { '*width' : 'int',
- '*height' : 'int',
- '*cols' : 'int',
- '*rows' : 'int' },
+{ 'struct': 'ChardevVC',
+ 'data': { '*width': 'int',
+ '*height': 'int',
+ '*cols': 'int',
+ '*rows': 'int' },
'base': 'ChardevCommon' }
##
@@ -365,7 +377,8 @@
#
# Since: 1.5
##
-{ 'struct': 'ChardevRingbuf', 'data': { '*size' : 'int' },
+{ 'struct': 'ChardevRingbuf',
+ 'data': { '*size': 'int' },
'base': 'ChardevCommon' }
##
@@ -375,29 +388,30 @@
#
# Since: 1.4 (testdev since 2.2, wctablet since 2.9)
##
-{ 'union': 'ChardevBackend', 'data': { 'file' : 'ChardevFile',
- 'serial' : 'ChardevHostdev',
- 'parallel': 'ChardevHostdev',
- 'pipe' : 'ChardevHostdev',
- 'socket' : 'ChardevSocket',
- 'udp' : 'ChardevUdp',
- 'pty' : 'ChardevCommon',
- 'null' : 'ChardevCommon',
- 'mux' : 'ChardevMux',
- 'msmouse': 'ChardevCommon',
- 'wctablet' : 'ChardevCommon',
- 'braille': 'ChardevCommon',
- 'testdev': 'ChardevCommon',
- 'stdio' : 'ChardevStdio',
- 'console': 'ChardevCommon',
- 'spicevmc': 'ChardevSpiceChannel',
-# TODO: { 'type': 'ChardevSpiceChannel', 'if': 'defined(CONFIG_SPICE)' },
- 'spiceport': 'ChardevSpicePort',
-# TODO: { 'type': 'ChardevSpicePort', 'if': 'defined(CONFIG_SPICE)' },
- 'vc' : 'ChardevVC',
- 'ringbuf': 'ChardevRingbuf',
- # next one is just for compatibility
- 'memory' : 'ChardevRingbuf' } }
+{ 'union': 'ChardevBackend',
+ 'data': { 'file': 'ChardevFile',
+ 'serial': 'ChardevHostdev',
+ 'parallel': 'ChardevHostdev',
+ 'pipe': 'ChardevHostdev',
+ 'socket': 'ChardevSocket',
+ 'udp': 'ChardevUdp',
+ 'pty': 'ChardevCommon',
+ 'null': 'ChardevCommon',
+ 'mux': 'ChardevMux',
+ 'msmouse': 'ChardevCommon',
+ 'wctablet': 'ChardevCommon',
+ 'braille': 'ChardevCommon',
+ 'testdev': 'ChardevCommon',
+ 'stdio': 'ChardevStdio',
+ 'console': 'ChardevCommon',
+ 'spicevmc': { 'type': 'ChardevSpiceChannel',
+ 'if': 'defined(CONFIG_SPICE)' },
+ 'spiceport': { 'type': 'ChardevSpicePort',
+ 'if': 'defined(CONFIG_SPICE)' },
+ 'vc': 'ChardevVC',
+ 'ringbuf': 'ChardevRingbuf',
+ # next one is just for compatibility
+ 'memory': 'ChardevRingbuf' } }
##
# @ChardevReturn:
@@ -409,7 +423,8 @@
#
# Since: 1.4
##
-{ 'struct' : 'ChardevReturn', 'data': { '*pty' : 'str' } }
+{ 'struct' : 'ChardevReturn',
+ 'data': { '*pty': 'str' } }
##
# @chardev-add:
@@ -442,8 +457,9 @@
# <- { "return": { "pty" : "/dev/pty/42" } }
#
##
-{ 'command': 'chardev-add', 'data': {'id' : 'str',
- 'backend' : 'ChardevBackend' },
+{ 'command': 'chardev-add',
+ 'data': { 'id': 'str',
+ 'backend': 'ChardevBackend' },
'returns': 'ChardevReturn' }
##
@@ -482,8 +498,9 @@
# <- {"return": {}}
#
##
-{ 'command': 'chardev-change', 'data': {'id' : 'str',
- 'backend' : 'ChardevBackend' },
+{ 'command': 'chardev-change',
+ 'data': { 'id': 'str',
+ 'backend': 'ChardevBackend' },
'returns': 'ChardevReturn' }
##
@@ -503,7 +520,8 @@
# <- { "return": {} }
#
##
-{ 'command': 'chardev-remove', 'data': {'id': 'str'} }
+{ 'command': 'chardev-remove',
+ 'data': { 'id': 'str' } }
##
# @chardev-send-break:
@@ -522,7 +540,8 @@
# <- { "return": {} }
#
##
-{ 'command': 'chardev-send-break', 'data': {'id': 'str'} }
+{ 'command': 'chardev-send-break',
+ 'data': { 'id': 'str' } }
##
# @VSERPORT_CHANGE:
@@ -543,4 +562,5 @@
#
##
{ 'event': 'VSERPORT_CHANGE',
- 'data': { 'id': 'str', 'open': 'bool' } }
+ 'data': { 'id': 'str',
+ 'open': 'bool' } }
diff --git a/qapi/crypto.json b/qapi/crypto.json
index a51b434412..b2a4cff683 100644
--- a/qapi/crypto.json
+++ b/qapi/crypto.json
@@ -181,11 +181,11 @@
# The options that apply to LUKS encryption format initialization
#
# @cipher-alg: the cipher algorithm for data encryption
-# Currently defaults to 'aes'.
+# Currently defaults to 'aes-256'.
# @cipher-mode: the cipher mode for data encryption
-# Currently defaults to 'cbc'
+# Currently defaults to 'xts'
# @ivgen-alg: the initialization vector generator
-# Currently defaults to 'essiv'
+# Currently defaults to 'plain64'
# @ivgen-hash-alg: the initialization vector generator hash
# Currently defaults to 'sha256'
# @hash-alg: the master key hash algorithm
diff --git a/qapi/migration.json b/qapi/migration.json
index 38d4c41d88..31b589ec26 100644
--- a/qapi/migration.json
+++ b/qapi/migration.json
@@ -1257,7 +1257,8 @@
# Since: 2.9
##
{ 'command': 'xen-set-replication',
- 'data': { 'enable': 'bool', 'primary': 'bool', '*failover' : 'bool' } }
+ 'data': { 'enable': 'bool', 'primary': 'bool', '*failover' : 'bool' },
+ 'if': 'defined(CONFIG_REPLICATION)' }
##
# @ReplicationStatus:
@@ -1272,7 +1273,8 @@
# Since: 2.9
##
{ 'struct': 'ReplicationStatus',
- 'data': { 'error': 'bool', '*desc': 'str' } }
+ 'data': { 'error': 'bool', '*desc': 'str' },
+ 'if': 'defined(CONFIG_REPLICATION)' }
##
# @query-xen-replication-status:
@@ -1289,7 +1291,8 @@
# Since: 2.9
##
{ 'command': 'query-xen-replication-status',
- 'returns': 'ReplicationStatus' }
+ 'returns': 'ReplicationStatus',
+ 'if': 'defined(CONFIG_REPLICATION)' }
##
# @xen-colo-do-checkpoint:
@@ -1305,7 +1308,8 @@
#
# Since: 2.9
##
-{ 'command': 'xen-colo-do-checkpoint' }
+{ 'command': 'xen-colo-do-checkpoint',
+ 'if': 'defined(CONFIG_REPLICATION)' }
##
# @COLOStatus:
@@ -1356,7 +1360,8 @@
#
# Since: 3.0
##
-{ 'command': 'migrate-recover', 'data': { 'uri': 'str' },
+{ 'command': 'migrate-recover',
+ 'data': { 'uri': 'str' },
'allow-oob': true }
##
diff --git a/qapi/misc.json b/qapi/misc.json
index 6c1c5c0a37..8325e0dc9c 100644
--- a/qapi/misc.json
+++ b/qapi/misc.json
@@ -1109,7 +1109,7 @@
##
# @cpu-add:
#
-# Adds CPU with specified ID
+# Adds CPU with specified ID.
#
# @id: ID of CPU to be created, valid values [0..max_cpus)
#
@@ -1117,6 +1117,10 @@
#
# Since: 1.5
#
+# Note: This command is deprecated. The `device_add` command should be
+# used instead. See the `query-hotpluggable-cpus` command for
+# details.
+#
# Example:
#
# -> { "execute": "cpu-add", "arguments": { "id": 2 } }
@@ -2381,7 +2385,9 @@
# <- { "return": { "fdset-id": 1, "fd": 3 } }
#
##
-{ 'command': 'add-fd', 'data': {'*fdset-id': 'int', '*opaque': 'str'},
+{ 'command': 'add-fd',
+ 'data': { '*fdset-id': 'int',
+ '*opaque': 'str' },
'returns': 'AddfdInfo' }
##
@@ -2653,7 +2659,8 @@
# }
#
##
-{'command': 'query-command-line-options', 'data': { '*option': 'str' },
+{'command': 'query-command-line-options',
+ 'data': { '*option': 'str' },
'returns': ['CommandLineOptionInfo'],
'allow-preconfig': true }
@@ -3219,6 +3226,8 @@
##
# @query-hotpluggable-cpus:
#
+# TODO: Better documentation; currently there is none.
+#
# Returns: a list of HotpluggableCPU objects.
#
# Since: 2.7
@@ -3439,46 +3448,6 @@
{ 'command': 'query-sev-capabilities', 'returns': 'SevCapability' }
##
-# @CommandDropReason:
-#
-# Reasons that caused one command to be dropped.
-#
-# @queue-full: the command queue is full. This can only occur when
-# the client sends a new non-oob command before the
-# response to the previous non-oob command has been
-# received.
-#
-# Since: 2.12
-##
-{ 'enum': 'CommandDropReason',
- 'data': [ 'queue-full' ] }
-
-##
-# @COMMAND_DROPPED:
-#
-# Emitted when a command is dropped due to some reason. Commands can
-# only be dropped when the oob capability is enabled.
-#
-# @id: The dropped command's "id" field.
-# FIXME Broken by design. Events are broadcast to all monitors. If
-# another monitor's client has a command with the same ID in flight,
-# the event will incorrectly claim that command was dropped.
-#
-# @reason: The reason why the command is dropped.
-#
-# Since: 2.12
-#
-# Example:
-#
-# { "event": "COMMAND_DROPPED",
-# "data": {"result": {"id": "libvirt-102",
-# "reason": "queue-full" } } }
-#
-##
-{ 'event': 'COMMAND_DROPPED' ,
- 'data': { 'id': 'any', 'reason': 'CommandDropReason' } }
-
-##
# @set-numa-node:
#
# Runtime equivalent of '-numa' CLI option, available at
diff --git a/qapi/net.json b/qapi/net.json
index 8f99fd911d..a1a0f39f74 100644
--- a/qapi/net.json
+++ b/qapi/net.json
@@ -657,7 +657,8 @@
# }
#
##
-{ 'command': 'query-rx-filter', 'data': { '*name': 'str' },
+{ 'command': 'query-rx-filter',
+ 'data': { '*name': 'str' },
'returns': ['RxFilterInfo'] }
##
diff --git a/qapi/qobject-input-visitor.c b/qapi/qobject-input-visitor.c
index 3e88b27f9e..07465f9947 100644
--- a/qapi/qobject-input-visitor.c
+++ b/qapi/qobject-input-visitor.c
@@ -562,19 +562,20 @@ static void qobject_input_type_number_keyval(Visitor *v, const char *name,
{
QObjectInputVisitor *qiv = to_qiv(v);
const char *str = qobject_input_get_keyval(qiv, name, errp);
- char *endp;
+ double val;
if (!str) {
return;
}
- errno = 0;
- *obj = strtod(str, &endp);
- if (errno || endp == str || *endp || !isfinite(*obj)) {
+ if (qemu_strtod_finite(str, NULL, &val)) {
/* TODO report -ERANGE more nicely */
error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
full_name(qiv, name), "number");
+ return;
}
+
+ *obj = val;
}
static void qobject_input_type_any(Visitor *v, const char *name, QObject **obj,
diff --git a/qapi/string-input-visitor.c b/qapi/string-input-visitor.c
index b3fdd0827d..bd92080667 100644
--- a/qapi/string-input-visitor.c
+++ b/qapi/string-input-visitor.c
@@ -4,10 +4,10 @@
* Copyright Red Hat, Inc. 2012-2016
*
* Author: Paolo Bonzini <pbonzini@redhat.com>
+ * David Hildenbrand <david@redhat.com>
*
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
* See the COPYING.LIB file in the top-level directory.
- *
*/
#include "qemu/osdep.h"
@@ -18,20 +18,42 @@
#include "qapi/qmp/qerror.h"
#include "qapi/qmp/qnull.h"
#include "qemu/option.h"
-#include "qemu/queue.h"
-#include "qemu/range.h"
-
+#include "qemu/cutils.h"
+
+typedef enum ListMode {
+ /* no list parsing active / no list expected */
+ LM_NONE,
+ /* we have an unparsed string remaining */
+ LM_UNPARSED,
+ /* we have an unfinished int64 range */
+ LM_INT64_RANGE,
+ /* we have an unfinished uint64 range */
+ LM_UINT64_RANGE,
+ /* we have parsed the string completely and no range is remaining */
+ LM_END,
+} ListMode;
+
+/* protect against DOS attacks, limit the amount of elements per range */
+#define RANGE_MAX_ELEMENTS 65536
+
+typedef union RangeElement {
+ int64_t i64;
+ uint64_t u64;
+} RangeElement;
struct StringInputVisitor
{
Visitor visitor;
- GList *ranges;
- GList *cur_range;
- int64_t cur;
+ /* List parsing state */
+ ListMode lm;
+ RangeElement rangeNext;
+ RangeElement rangeEnd;
+ const char *unparsed_string;
+ void *list;
+ /* The original string to parse */
const char *string;
- void *list; /* Only needed for sanity checking the caller */
};
static StringInputVisitor *to_siv(Visitor *v)
@@ -39,136 +61,42 @@ static StringInputVisitor *to_siv(Visitor *v)
return container_of(v, StringInputVisitor, visitor);
}
-static void free_range(void *range, void *dummy)
-{
- g_free(range);
-}
-
-static int parse_str(StringInputVisitor *siv, const char *name, Error **errp)
-{
- char *str = (char *) siv->string;
- long long start, end;
- Range *cur;
- char *endptr;
-
- if (siv->ranges) {
- return 0;
- }
-
- if (!*str) {
- return 0;
- }
-
- do {
- errno = 0;
- start = strtoll(str, &endptr, 0);
- if (errno == 0 && endptr > str) {
- if (*endptr == '\0') {
- cur = g_malloc0(sizeof(*cur));
- range_set_bounds(cur, start, start);
- siv->ranges = range_list_insert(siv->ranges, cur);
- cur = NULL;
- str = NULL;
- } else if (*endptr == '-') {
- str = endptr + 1;
- errno = 0;
- end = strtoll(str, &endptr, 0);
- if (errno == 0 && endptr > str && start <= end &&
- (start > INT64_MAX - 65536 ||
- end < start + 65536)) {
- if (*endptr == '\0') {
- cur = g_malloc0(sizeof(*cur));
- range_set_bounds(cur, start, end);
- siv->ranges = range_list_insert(siv->ranges, cur);
- cur = NULL;
- str = NULL;
- } else if (*endptr == ',') {
- str = endptr + 1;
- cur = g_malloc0(sizeof(*cur));
- range_set_bounds(cur, start, end);
- siv->ranges = range_list_insert(siv->ranges, cur);
- cur = NULL;
- } else {
- goto error;
- }
- } else {
- goto error;
- }
- } else if (*endptr == ',') {
- str = endptr + 1;
- cur = g_malloc0(sizeof(*cur));
- range_set_bounds(cur, start, start);
- siv->ranges = range_list_insert(siv->ranges, cur);
- cur = NULL;
- } else {
- goto error;
- }
- } else {
- goto error;
- }
- } while (str);
-
- return 0;
-error:
- g_list_foreach(siv->ranges, free_range, NULL);
- g_list_free(siv->ranges);
- siv->ranges = NULL;
- error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name ? name : "null",
- "an int64 value or range");
- return -1;
-}
-
-static void
-start_list(Visitor *v, const char *name, GenericList **list, size_t size,
- Error **errp)
+static void start_list(Visitor *v, const char *name, GenericList **list,
+ size_t size, Error **errp)
{
StringInputVisitor *siv = to_siv(v);
- /* We don't support visits without a list */
- assert(list);
+ assert(siv->lm == LM_NONE);
siv->list = list;
+ siv->unparsed_string = siv->string;
- if (parse_str(siv, name, errp) < 0) {
- *list = NULL;
- return;
- }
-
- siv->cur_range = g_list_first(siv->ranges);
- if (siv->cur_range) {
- Range *r = siv->cur_range->data;
- if (r) {
- siv->cur = range_lob(r);
+ if (!siv->string[0]) {
+ if (list) {
+ *list = NULL;
}
- *list = g_malloc0(size);
+ siv->lm = LM_END;
} else {
- *list = NULL;
+ if (list) {
+ *list = g_malloc0(size);
+ }
+ siv->lm = LM_UNPARSED;
}
}
static GenericList *next_list(Visitor *v, GenericList *tail, size_t size)
{
StringInputVisitor *siv = to_siv(v);
- Range *r;
- if (!siv->ranges || !siv->cur_range) {
+ switch (siv->lm) {
+ case LM_END:
return NULL;
- }
-
- r = siv->cur_range->data;
- if (!r) {
- return NULL;
- }
-
- if (!range_contains(r, siv->cur)) {
- siv->cur_range = g_list_next(siv->cur_range);
- if (!siv->cur_range) {
- return NULL;
- }
- r = siv->cur_range->data;
- if (!r) {
- return NULL;
- }
- siv->cur = range_lob(r);
+ case LM_INT64_RANGE:
+ case LM_UINT64_RANGE:
+ case LM_UNPARSED:
+ /* we have an unparsed string or something left in a range */
+ break;
+ default:
+ abort();
}
tail->next = g_malloc0(size);
@@ -178,88 +106,208 @@ static GenericList *next_list(Visitor *v, GenericList *tail, size_t size)
static void check_list(Visitor *v, Error **errp)
{
const StringInputVisitor *siv = to_siv(v);
- Range *r;
- GList *cur_range;
- if (!siv->ranges || !siv->cur_range) {
+ switch (siv->lm) {
+ case LM_INT64_RANGE:
+ case LM_UINT64_RANGE:
+ case LM_UNPARSED:
+ error_setg(errp, "Fewer list elements expected");
return;
- }
-
- r = siv->cur_range->data;
- if (!r) {
+ case LM_END:
return;
+ default:
+ abort();
}
-
- if (!range_contains(r, siv->cur)) {
- cur_range = g_list_next(siv->cur_range);
- if (!cur_range) {
- return;
- }
- r = cur_range->data;
- if (!r) {
- return;
- }
- }
-
- error_setg(errp, "Range contains too many values");
}
static void end_list(Visitor *v, void **obj)
{
StringInputVisitor *siv = to_siv(v);
+ assert(siv->lm != LM_NONE);
assert(siv->list == obj);
+ siv->list = NULL;
+ siv->unparsed_string = NULL;
+ siv->lm = LM_NONE;
+}
+
+static int try_parse_int64_list_entry(StringInputVisitor *siv, int64_t *obj)
+{
+ const char *endptr;
+ int64_t start, end;
+
+ /* parse a simple int64 or range */
+ if (qemu_strtoi64(siv->unparsed_string, &endptr, 0, &start)) {
+ return -EINVAL;
+ }
+ end = start;
+
+ switch (endptr[0]) {
+ case '\0':
+ siv->unparsed_string = endptr;
+ break;
+ case ',':
+ siv->unparsed_string = endptr + 1;
+ break;
+ case '-':
+ /* parse the end of the range */
+ if (qemu_strtoi64(endptr + 1, &endptr, 0, &end)) {
+ return -EINVAL;
+ }
+ if (start > end || end - start >= RANGE_MAX_ELEMENTS) {
+ return -EINVAL;
+ }
+ switch (endptr[0]) {
+ case '\0':
+ siv->unparsed_string = endptr;
+ break;
+ case ',':
+ siv->unparsed_string = endptr + 1;
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* we have a proper range (with maybe only one element) */
+ siv->lm = LM_INT64_RANGE;
+ siv->rangeNext.i64 = start;
+ siv->rangeEnd.i64 = end;
+ return 0;
}
static void parse_type_int64(Visitor *v, const char *name, int64_t *obj,
Error **errp)
{
StringInputVisitor *siv = to_siv(v);
-
- if (parse_str(siv, name, errp) < 0) {
+ int64_t val;
+
+ switch (siv->lm) {
+ case LM_NONE:
+ /* just parse a simple int64, bail out if not completely consumed */
+ if (qemu_strtoi64(siv->string, NULL, 0, &val)) {
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
+ name ? name : "null", "int64");
+ return;
+ }
+ *obj = val;
return;
+ case LM_UNPARSED:
+ if (try_parse_int64_list_entry(siv, obj)) {
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name ? name : "null",
+ "list of int64 values or ranges");
+ return;
+ }
+ assert(siv->lm == LM_INT64_RANGE);
+ /* fall through */
+ case LM_INT64_RANGE:
+ /* return the next element in the range */
+ assert(siv->rangeNext.i64 <= siv->rangeEnd.i64);
+ *obj = siv->rangeNext.i64++;
+
+ if (siv->rangeNext.i64 > siv->rangeEnd.i64 || *obj == INT64_MAX) {
+ /* end of range, check if there is more to parse */
+ siv->lm = siv->unparsed_string[0] ? LM_UNPARSED : LM_END;
+ }
+ return;
+ case LM_END:
+ error_setg(errp, "Fewer list elements expected");
+ return;
+ default:
+ abort();
}
+}
- if (!siv->ranges) {
- goto error;
- }
-
- if (!siv->cur_range) {
- Range *r;
+static int try_parse_uint64_list_entry(StringInputVisitor *siv, uint64_t *obj)
+{
+ const char *endptr;
+ uint64_t start, end;
- siv->cur_range = g_list_first(siv->ranges);
- if (!siv->cur_range) {
- goto error;
+ /* parse a simple uint64 or range */
+ if (qemu_strtou64(siv->unparsed_string, &endptr, 0, &start)) {
+ return -EINVAL;
+ }
+ end = start;
+
+ switch (endptr[0]) {
+ case '\0':
+ siv->unparsed_string = endptr;
+ break;
+ case ',':
+ siv->unparsed_string = endptr + 1;
+ break;
+ case '-':
+ /* parse the end of the range */
+ if (qemu_strtou64(endptr + 1, &endptr, 0, &end)) {
+ return -EINVAL;
}
-
- r = siv->cur_range->data;
- if (!r) {
- goto error;
+ if (start > end || end - start >= RANGE_MAX_ELEMENTS) {
+ return -EINVAL;
}
-
- siv->cur = range_lob(r);
+ switch (endptr[0]) {
+ case '\0':
+ siv->unparsed_string = endptr;
+ break;
+ case ',':
+ siv->unparsed_string = endptr + 1;
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+ default:
+ return -EINVAL;
}
- *obj = siv->cur;
- siv->cur++;
- return;
-
-error:
- error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name ? name : "null",
- "an int64 value or range");
+ /* we have a proper range (with maybe only one element) */
+ siv->lm = LM_UINT64_RANGE;
+ siv->rangeNext.u64 = start;
+ siv->rangeEnd.u64 = end;
+ return 0;
}
static void parse_type_uint64(Visitor *v, const char *name, uint64_t *obj,
Error **errp)
{
- /* FIXME: parse_type_int64 mishandles values over INT64_MAX */
- int64_t i;
- Error *err = NULL;
- parse_type_int64(v, name, &i, &err);
- if (err) {
- error_propagate(errp, err);
- } else {
- *obj = i;
+ StringInputVisitor *siv = to_siv(v);
+ uint64_t val;
+
+ switch (siv->lm) {
+ case LM_NONE:
+ /* just parse a simple uint64, bail out if not completely consumed */
+ if (qemu_strtou64(siv->string, NULL, 0, &val)) {
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name ? name : "null",
+ "uint64");
+ return;
+ }
+ *obj = val;
+ return;
+ case LM_UNPARSED:
+ if (try_parse_uint64_list_entry(siv, obj)) {
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name ? name : "null",
+ "list of uint64 values or ranges");
+ return;
+ }
+ assert(siv->lm == LM_UINT64_RANGE);
+ /* fall through */
+ case LM_UINT64_RANGE:
+ /* return the next element in the range */
+ assert(siv->rangeNext.u64 <= siv->rangeEnd.u64);
+ *obj = siv->rangeNext.u64++;
+
+ if (siv->rangeNext.u64 > siv->rangeEnd.u64 || *obj == UINT64_MAX) {
+ /* end of range, check if there is more to parse */
+ siv->lm = siv->unparsed_string[0] ? LM_UNPARSED : LM_END;
+ }
+ return;
+ case LM_END:
+ error_setg(errp, "Fewer list elements expected");
+ return;
+ default:
+ abort();
}
}
@@ -270,6 +318,7 @@ static void parse_type_size(Visitor *v, const char *name, uint64_t *obj,
Error *err = NULL;
uint64_t val;
+ assert(siv->lm == LM_NONE);
parse_option_size(name, siv->string, &val, &err);
if (err) {
error_propagate(errp, err);
@@ -284,6 +333,7 @@ static void parse_type_bool(Visitor *v, const char *name, bool *obj,
{
StringInputVisitor *siv = to_siv(v);
+ assert(siv->lm == LM_NONE);
if (!strcasecmp(siv->string, "on") ||
!strcasecmp(siv->string, "yes") ||
!strcasecmp(siv->string, "true")) {
@@ -306,6 +356,7 @@ static void parse_type_str(Visitor *v, const char *name, char **obj,
{
StringInputVisitor *siv = to_siv(v);
+ assert(siv->lm == LM_NONE);
*obj = g_strdup(siv->string);
}
@@ -313,12 +364,10 @@ static void parse_type_number(Visitor *v, const char *name, double *obj,
Error **errp)
{
StringInputVisitor *siv = to_siv(v);
- char *endp = (char *) siv->string;
double val;
- errno = 0;
- val = strtod(siv->string, &endp);
- if (errno || endp == siv->string || *endp) {
+ assert(siv->lm == LM_NONE);
+ if (qemu_strtod_finite(siv->string, NULL, &val)) {
error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
"number");
return;
@@ -332,9 +381,10 @@ static void parse_type_null(Visitor *v, const char *name, QNull **obj,
{
StringInputVisitor *siv = to_siv(v);
+ assert(siv->lm == LM_NONE);
*obj = NULL;
- if (!siv->string || siv->string[0]) {
+ if (siv->string[0]) {
error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
"null");
return;
@@ -347,8 +397,6 @@ static void string_input_free(Visitor *v)
{
StringInputVisitor *siv = to_siv(v);
- g_list_foreach(siv->ranges, free_range, NULL);
- g_list_free(siv->ranges);
g_free(siv);
}
@@ -374,5 +422,6 @@ Visitor *string_input_visitor_new(const char *str)
v->visitor.free = string_input_free;
v->string = str;
+ v->lm = LM_NONE;
return &v->visitor;
}
diff --git a/qapi/tpm.json b/qapi/tpm.json
index d50deef5e9..b30323bb6b 100644
--- a/qapi/tpm.json
+++ b/qapi/tpm.json
@@ -76,8 +76,9 @@
#
# Since: 1.5
##
-{ 'struct': 'TPMPassthroughOptions', 'data': { '*path' : 'str',
- '*cancel-path' : 'str'} }
+{ 'struct': 'TPMPassthroughOptions',
+ 'data': { '*path': 'str',
+ '*cancel-path': 'str' } }
##
# @TPMEmulatorOptions:
diff --git a/qapi/ui.json b/qapi/ui.json
index fd39acb5c3..5ad13248d5 100644
--- a/qapi/ui.json
+++ b/qapi/ui.json
@@ -598,7 +598,8 @@
# Notes: An empty password in this command will set the password to the empty
# string. Existing clients are unaffected by executing this command.
##
-{ 'command': 'change-vnc-password', 'data': {'password': 'str'},
+{ 'command': 'change-vnc-password',
+ 'data': { 'password': 'str' },
'if': 'defined(CONFIG_VNC)' }
##
diff --git a/qemu-deprecated.texi b/qemu-deprecated.texi
index cb4291f1e5..e362d37225 100644
--- a/qemu-deprecated.texi
+++ b/qemu-deprecated.texi
@@ -46,14 +46,6 @@ would automatically enable USB support on the machine type.
If using the new syntax, USB support must be explicitly
enabled via the ``-machine usb=on'' argument.
-@subsection -fsdev handle (since 2.12.0)
-
-The ``handle'' fsdev backend does not support symlinks and causes the 9p
-filesystem in the guest to fail a fair amount of tests from the PJD POSIX
-filesystem test suite. Also it requires the CAP_DAC_READ_SEARCH capability,
-which is not the recommended way to run QEMU. This backend should not be
-used and it will be removed with no replacement.
-
@subsection -no-frame (since 2.12.0)
The @code{--no-frame} argument works with SDL 1.2 only. The other user
@@ -121,6 +113,11 @@ replaced by the ``target'' output member.
The @option{[hub_id name]} parameter tuple of the 'hostfwd_add' and
'hostfwd_remove' HMP commands has been replaced by @option{netdev_id}.
+@subsection cpu-add (since 3.1)
+
+Use ``device_add'' for hotplugging vCPUs instead of ``cpu-add''. See
+documentation of ``query-hotpluggable-cpus'' for additional details.
+
@section System emulator devices
@subsection ivshmem (since 2.6.0)
diff --git a/qemu-options.hx b/qemu-options.hx
index 269eda7a5d..df42116ecc 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -1019,7 +1019,7 @@ Define a new file system device. Valid options are:
@table @option
@item @var{fsdriver}
This option specifies the fs driver backend to use.
-Currently "local", "handle" and "proxy" file system drivers are supported.
+Currently "local" and "proxy" file system drivers are supported.
@item id=@var{id}
Specifies identifier for this device
@item path=@var{path}
@@ -1037,7 +1037,7 @@ hidden .virtfs_metadata directory. Directories exported by this security model c
interact with other unix tools. "none" security model is same as
passthrough except the sever won't report failures if it fails to
set file attributes like ownership. Security model is mandatory
-only for local fsdriver. Other fsdrivers (like handle, proxy) don't take
+only for local fsdriver. Other fsdrivers (like proxy) don't take
security model as a parameter.
@item writeout=@var{writeout}
This is an optional argument. The only supported value is "immediate".
@@ -1088,7 +1088,7 @@ The general form of a Virtual File system pass-through options are:
@table @option
@item @var{fsdriver}
This option specifies the fs driver backend to use.
-Currently "local", "handle" and "proxy" file system drivers are supported.
+Currently "local" and "proxy" file system drivers are supported.
@item id=@var{id}
Specifies identifier for this device
@item path=@var{path}
@@ -1106,7 +1106,7 @@ hidden .virtfs_metadata directory. Directories exported by this security model c
interact with other unix tools. "none" security model is same as
passthrough except the sever won't report failures if it fails to
set file attributes like ownership. Security model is mandatory only
-for local fsdriver. Other fsdrivers (like handle, proxy) don't take security
+for local fsdriver. Other fsdrivers (like proxy) don't take security
model as a parameter.
@item writeout=@var{writeout}
This is an optional argument. The only supported value is "immediate".
diff --git a/qobject/json-parser.c b/qobject/json-parser.c
index 5a840dfd86..7a7ae9e8d1 100644
--- a/qobject/json-parser.c
+++ b/qobject/json-parser.c
@@ -288,6 +288,11 @@ static int parse_pair(JSONParserContext *ctxt, QDict *dict)
goto out;
}
+ if (qdict_haskey(dict, qstring_get_str(key))) {
+ parse_error(ctxt, token, "duplicate key");
+ goto out;
+ }
+
qdict_put_obj(dict, qstring_get_str(key), value);
qobject_unref(key);
diff --git a/qom/object.c b/qom/object.c
index 547dcf97c3..17921c0a71 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -49,7 +49,6 @@ struct TypeImpl
void (*class_init)(ObjectClass *klass, void *data);
void (*class_base_init)(ObjectClass *klass, void *data);
- void (*class_finalize)(ObjectClass *klass, void *data);
void *class_data;
@@ -114,7 +113,6 @@ static TypeImpl *type_new(const TypeInfo *info)
ti->class_init = info->class_init;
ti->class_base_init = info->class_base_init;
- ti->class_finalize = info->class_finalize;
ti->class_data = info->class_data;
ti->instance_init = info->instance_init;
@@ -417,6 +415,7 @@ void object_initialize_childv(Object *parentobj, const char *propname,
{
Error *local_err = NULL;
Object *obj;
+ UserCreatable *uc;
object_initialize(childobj, size, type);
obj = OBJECT(childobj);
@@ -431,8 +430,9 @@ void object_initialize_childv(Object *parentobj, const char *propname,
goto out;
}
- if (object_dynamic_cast(obj, TYPE_USER_CREATABLE)) {
- user_creatable_complete(obj, &local_err);
+ uc = (UserCreatable *)object_dynamic_cast(obj, TYPE_USER_CREATABLE);
+ if (uc) {
+ user_creatable_complete(uc, &local_err);
if (local_err) {
object_unparent(obj);
goto out;
@@ -590,6 +590,7 @@ Object *object_new_with_propv(const char *typename,
Object *obj;
ObjectClass *klass;
Error *local_err = NULL;
+ UserCreatable *uc;
klass = object_class_by_name(typename);
if (!klass) {
@@ -612,8 +613,9 @@ Object *object_new_with_propv(const char *typename,
goto error;
}
- if (object_dynamic_cast(obj, TYPE_USER_CREATABLE)) {
- user_creatable_complete(obj, &local_err);
+ uc = (UserCreatable *)object_dynamic_cast(obj, TYPE_USER_CREATABLE);
+ if (uc) {
+ user_creatable_complete(uc, &local_err);
if (local_err) {
object_unparent(obj);
goto error;
diff --git a/qom/object_interfaces.c b/qom/object_interfaces.c
index 97b79b48bb..db85d1eb75 100644
--- a/qom/object_interfaces.c
+++ b/qom/object_interfaces.c
@@ -8,18 +8,10 @@
#include "qapi/opts-visitor.h"
#include "qemu/config-file.h"
-void user_creatable_complete(Object *obj, Error **errp)
+void user_creatable_complete(UserCreatable *uc, Error **errp)
{
+ UserCreatableClass *ucc = USER_CREATABLE_GET_CLASS(uc);
- UserCreatableClass *ucc;
- UserCreatable *uc =
- (UserCreatable *)object_dynamic_cast(obj, TYPE_USER_CREATABLE);
-
- if (!uc) {
- return;
- }
-
- ucc = USER_CREATABLE_GET_CLASS(uc);
if (ucc->complete) {
ucc->complete(uc, errp);
}
@@ -89,7 +81,7 @@ Object *user_creatable_add_type(const char *type, const char *id,
goto out;
}
- user_creatable_complete(obj, &local_err);
+ user_creatable_complete(USER_CREATABLE(obj), &local_err);
if (local_err) {
object_property_del(object_get_objects_root(),
id, &error_abort);
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 60f6f89a27..a892a6cc7c 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -202,7 +202,6 @@ our $Attribute = qr{
QEMU_NORETURN|
QEMU_WARN_UNUSED_RESULT|
QEMU_SENTINEL|
- QEMU_ARTIFICIAL|
QEMU_PACKED|
GCC_FMT_ATTR
}x;
diff --git a/scripts/cocci-macro-file.h b/scripts/cocci-macro-file.h
index 9f2e72e7e1..7e200a1023 100644
--- a/scripts/cocci-macro-file.h
+++ b/scripts/cocci-macro-file.h
@@ -23,7 +23,6 @@
#define QEMU_NORETURN __attribute__ ((__noreturn__))
#define QEMU_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
#define QEMU_SENTINEL __attribute__((sentinel))
-#define QEMU_ARTIFICIAL __attribute__((always_inline, artificial))
#define QEMU_PACKED __attribute__((gcc_struct, packed))
#define cat(x,y) x ## y
diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index 7b62a4c7b0..8c2d97369e 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -588,11 +588,11 @@ def discriminator_find_enum_define(expr):
if not base_members:
return None
- discriminator_type = base_members.get(discriminator)
- if not discriminator_type:
+ discriminator_value = base_members.get(discriminator)
+ if not discriminator_value:
return None
- return enum_types.get(discriminator_type)
+ return enum_types.get(discriminator_value['type'])
# Names must be letters, numbers, -, and _. They must start with letter,
@@ -704,8 +704,10 @@ def check_type(info, source, value, allow_array=False,
% (source, key))
# Todo: allow dictionaries to represent default values of
# an optional argument.
- check_type(info, "Member '%s' of %s" % (key, source), arg,
- allow_array=True,
+ check_known_keys(info, "member '%s' of %s" % (key, source),
+ arg, ['type'], ['if'])
+ check_type(info, "Member '%s' of %s" % (key, source),
+ arg['type'], allow_array=True,
allow_metas=['built-in', 'union', 'alternate', 'struct',
'enum'])
@@ -740,6 +742,10 @@ def check_event(expr, info):
allow_metas=meta)
+def enum_get_names(expr):
+ return [e['name'] for e in expr['data']]
+
+
def check_union(expr, info):
name = expr['union']
base = expr.get('base')
@@ -772,13 +778,17 @@ def check_union(expr, info):
# member of the base struct.
check_name(info, "Discriminator of flat union '%s'" % name,
discriminator)
- discriminator_type = base_members.get(discriminator)
- if not discriminator_type:
+ discriminator_value = base_members.get(discriminator)
+ if not discriminator_value:
raise QAPISemError(info,
"Discriminator '%s' is not a member of base "
"struct '%s'"
% (discriminator, base))
- enum_define = enum_types.get(discriminator_type)
+ if discriminator_value.get('if'):
+ raise QAPISemError(info, 'The discriminator %s.%s for union %s '
+ 'must not be conditional' %
+ (base, discriminator, name))
+ enum_define = enum_types.get(discriminator_value['type'])
allow_metas = ['struct']
# Do not allow string discriminator
if not enum_define:
@@ -792,14 +802,17 @@ def check_union(expr, info):
for (key, value) in members.items():
check_name(info, "Member of union '%s'" % name, key)
+ check_known_keys(info, "member '%s' of union '%s'" % (key, name),
+ value, ['type'], ['if'])
# Each value must name a known type
check_type(info, "Member '%s' of union '%s'" % (key, name),
- value, allow_array=not base, allow_metas=allow_metas)
+ value['type'],
+ allow_array=not base, allow_metas=allow_metas)
# 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['data']:
+ if key not in enum_get_names(enum_define):
raise QAPISemError(info,
"Discriminator value '%s' is not found in "
"enum '%s'"
@@ -818,20 +831,23 @@ def check_alternate(expr, info):
"in 'data'" % name)
for (key, value) in members.items():
check_name(info, "Member of alternate '%s'" % name, key)
+ check_known_keys(info,
+ "member '%s' of alternate '%s'" % (key, name),
+ value, ['type'], ['if'])
+ typ = value['type']
# Ensure alternates have no type conflicts.
- check_type(info, "Member '%s' of alternate '%s'" % (key, name),
- value,
+ check_type(info, "Member '%s' of alternate '%s'" % (key, name), typ,
allow_metas=['built-in', 'union', 'struct', 'enum'])
- qtype = find_alternate_member_qtype(value)
+ qtype = find_alternate_member_qtype(typ)
if not qtype:
raise QAPISemError(info, "Alternate '%s' member '%s' cannot use "
- "type '%s'" % (name, key, value))
+ "type '%s'" % (name, key, typ))
conflicting = set([qtype])
if qtype == 'QTYPE_QSTRING':
- enum_expr = enum_types.get(value)
+ enum_expr = enum_types.get(typ)
if enum_expr:
- for v in enum_expr['data']:
+ for v in enum_get_names(enum_expr):
if v in ['on', 'off']:
conflicting.add('QTYPE_QBOOL')
if re.match(r'[-+0-9.]', v): # lazy, could be tightened
@@ -849,7 +865,7 @@ def check_alternate(expr, info):
def check_enum(expr, info):
name = expr['enum']
- members = expr.get('data')
+ members = expr['data']
prefix = expr.get('prefix')
if not isinstance(members, list):
@@ -858,8 +874,12 @@ def check_enum(expr, info):
if prefix is not None and not isinstance(prefix, str):
raise QAPISemError(info,
"Enum '%s' requires a string for 'prefix'" % name)
+
for member in members:
- check_name(info, "Member of enum '%s'" % name, member,
+ source = "dictionary member of enum '%s'" % name
+ check_known_keys(info, source, member, ['name'], ['if'])
+ check_if(member, info)
+ check_name(info, "Member of enum '%s'" % name, member['name'],
enum_member=True)
@@ -873,6 +893,24 @@ def check_struct(expr, info):
allow_metas=['struct'])
+def check_known_keys(info, source, keys, required, optional):
+
+ def pprint(elems):
+ return ', '.join("'" + e + "'" for e in sorted(elems))
+
+ missing = set(required) - set(keys)
+ if missing:
+ raise QAPISemError(info, "Key%s %s %s missing from %s"
+ % ('s' if len(missing) > 1 else '', pprint(missing),
+ 'are' if len(missing) > 1 else 'is', source))
+ allowed = set(required + optional)
+ unknown = set(keys) - allowed
+ if unknown:
+ raise QAPISemError(info, "Unknown key%s %s in %s\nValid keys are %s."
+ % ('s' if len(unknown) > 1 else '', pprint(unknown),
+ source, pprint(allowed)))
+
+
def check_keys(expr_elem, meta, required, optional=[]):
expr = expr_elem['expr']
info = expr_elem['info']
@@ -880,10 +918,9 @@ def check_keys(expr_elem, meta, required, optional=[]):
if not isinstance(name, str):
raise QAPISemError(info, "'%s' key must have a string value" % meta)
required = required + [meta]
+ source = "%s '%s'" % (meta, name)
+ check_known_keys(info, source, expr.keys(), required, optional)
for (key, value) in expr.items():
- if key not in required and key not in optional:
- raise QAPISemError(info, "Unknown key '%s' in %s '%s'"
- % (key, meta, name))
if key in ['gen', 'success-response'] and value is not False:
raise QAPISemError(info,
"'%s' of %s '%s' should only use false value"
@@ -895,10 +932,20 @@ def check_keys(expr_elem, meta, required, optional=[]):
% (key, meta, name))
if key == 'if':
check_if(expr, info)
- for key in required:
- if key not in expr:
- raise QAPISemError(info, "Key '%s' is missing from %s '%s'"
- % (key, meta, name))
+
+
+def normalize_enum(expr):
+ if isinstance(expr['data'], list):
+ expr['data'] = [m if isinstance(m, dict) else {'name': m}
+ for m in expr['data']]
+
+
+def normalize_members(members):
+ if isinstance(members, OrderedDict):
+ for key, arg in members.items():
+ if isinstance(arg, dict):
+ continue
+ members[key] = {'type': arg}
def check_exprs(exprs):
@@ -924,27 +971,34 @@ def check_exprs(exprs):
if 'enum' in expr:
meta = 'enum'
check_keys(expr_elem, 'enum', ['data'], ['if', 'prefix'])
+ normalize_enum(expr)
enum_types[expr[meta]] = expr
elif 'union' in expr:
meta = 'union'
check_keys(expr_elem, 'union', ['data'],
['base', 'discriminator', 'if'])
+ normalize_members(expr.get('base'))
+ normalize_members(expr['data'])
union_types[expr[meta]] = expr
elif 'alternate' in expr:
meta = 'alternate'
check_keys(expr_elem, 'alternate', ['data'], ['if'])
+ normalize_members(expr['data'])
elif 'struct' in expr:
meta = 'struct'
check_keys(expr_elem, 'struct', ['data'], ['base', 'if'])
+ normalize_members(expr['data'])
struct_types[expr[meta]] = expr
elif 'command' in expr:
meta = 'command'
check_keys(expr_elem, 'command', [],
['data', 'returns', 'gen', 'success-response',
'boxed', 'allow-oob', 'allow-preconfig', 'if'])
+ normalize_members(expr.get('data'))
elif 'event' in expr:
meta = 'event'
check_keys(expr_elem, 'event', [], ['data', 'boxed', 'if'])
+ normalize_members(expr.get('data'))
else:
raise QAPISemError(expr_elem['info'],
"Expression is missing metatype")
@@ -1063,7 +1117,7 @@ class QAPISchemaVisitor(object):
def visit_builtin_type(self, name, info, json_type):
pass
- def visit_enum_type(self, name, info, ifcond, values, prefix):
+ def visit_enum_type(self, name, info, ifcond, members, prefix):
pass
def visit_array_type(self, name, info, ifcond, element_type):
@@ -1161,22 +1215,22 @@ class QAPISchemaBuiltinType(QAPISchemaType):
class QAPISchemaEnumType(QAPISchemaType):
- def __init__(self, name, info, doc, ifcond, values, prefix):
+ def __init__(self, name, info, doc, ifcond, members, prefix):
QAPISchemaType.__init__(self, name, info, doc, ifcond)
- for v in values:
- assert isinstance(v, QAPISchemaMember)
- v.set_owner(name)
+ for m in members:
+ assert isinstance(m, QAPISchemaMember)
+ m.set_owner(name)
assert prefix is None or isinstance(prefix, str)
- self.values = values
+ self.members = members
self.prefix = prefix
def check(self, schema):
QAPISchemaType.check(self, schema)
seen = {}
- for v in self.values:
- v.check_clash(self.info, seen)
+ for m in self.members:
+ m.check_clash(self.info, seen)
if self.doc:
- self.doc.connect_member(v)
+ self.doc.connect_member(m)
def is_implicit(self):
# See QAPISchema._make_implicit_enum_type() and ._def_predefineds()
@@ -1186,14 +1240,14 @@ class QAPISchemaEnumType(QAPISchemaType):
return c_name(self.name)
def member_names(self):
- return [v.name for v in self.values]
+ return [m.name for m in self.members]
def json_type(self):
return 'string'
def visit(self, visitor):
visitor.visit_enum_type(self.name, self.info, self.ifcond,
- self.member_names(), self.prefix)
+ self.members, self.prefix)
class QAPISchemaArrayType(QAPISchemaType):
@@ -1318,9 +1372,10 @@ class QAPISchemaObjectType(QAPISchemaType):
class QAPISchemaMember(object):
role = 'member'
- def __init__(self, name):
+ def __init__(self, name, ifcond=None):
assert isinstance(name, str)
self.name = name
+ self.ifcond = listify_cond(ifcond)
self.owner = None
def set_owner(self, name):
@@ -1361,8 +1416,8 @@ class QAPISchemaMember(object):
class QAPISchemaObjectTypeMember(QAPISchemaMember):
- def __init__(self, name, typ, optional):
- QAPISchemaMember.__init__(self, name)
+ def __init__(self, name, typ, optional, ifcond=None):
+ QAPISchemaMember.__init__(self, name, ifcond)
assert isinstance(typ, str)
assert isinstance(optional, bool)
self._type_name = typ
@@ -1403,9 +1458,9 @@ class QAPISchemaObjectTypeVariants(object):
if self._tag_name: # flat union
# branches that are not explicitly covered get an empty type
cases = set([v.name for v in self.variants])
- for val in self.tag_member.type.values:
- if val.name not in cases:
- v = QAPISchemaObjectTypeVariant(val.name, 'q_empty')
+ for m in self.tag_member.type.members:
+ if m.name not in cases:
+ v = QAPISchemaObjectTypeVariant(m.name, 'q_empty')
v.set_owner(self.tag_member.owner)
self.variants.append(v)
for v in self.variants:
@@ -1428,8 +1483,8 @@ class QAPISchemaObjectTypeVariants(object):
class QAPISchemaObjectTypeVariant(QAPISchemaObjectTypeMember):
role = 'branch'
- def __init__(self, name, typ):
- QAPISchemaObjectTypeMember.__init__(self, name, typ, False)
+ def __init__(self, name, typ, ifcond=None):
+ QAPISchemaObjectTypeMember.__init__(self, name, typ, False, ifcond)
class QAPISchemaAlternateType(QAPISchemaType):
@@ -1620,14 +1675,16 @@ class QAPISchema(object):
self.the_empty_object_type = QAPISchemaObjectType(
'q_empty', None, None, None, None, [], None)
self._def_entity(self.the_empty_object_type)
- qtype_values = self._make_enum_members(['none', 'qnull', 'qnum',
- 'qstring', 'qdict', 'qlist',
- 'qbool'])
+
+ qtypes = ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist',
+ 'qbool']
+ qtype_values = self._make_enum_members([{'name': n} for n in qtypes])
+
self._def_entity(QAPISchemaEnumType('QType', None, None, None,
qtype_values, 'QTYPE'))
def _make_enum_members(self, values):
- return [QAPISchemaMember(v) for v in values]
+ return [QAPISchemaMember(v['name'], v.get('if')) for v in values]
def _make_implicit_enum_type(self, name, info, ifcond, values):
# See also QAPISchemaObjectTypeMember._pretty_owner()
@@ -1674,7 +1731,7 @@ class QAPISchema(object):
name, info, doc, ifcond,
self._make_enum_members(data), prefix))
- def _make_member(self, name, typ, info):
+ def _make_member(self, name, typ, ifcond, info):
optional = False
if name.startswith('*'):
name = name[1:]
@@ -1682,10 +1739,10 @@ class QAPISchema(object):
if isinstance(typ, list):
assert len(typ) == 1
typ = self._make_array_type(typ[0], info)
- return QAPISchemaObjectTypeMember(name, typ, optional)
+ return QAPISchemaObjectTypeMember(name, typ, optional, ifcond)
def _make_members(self, data, info):
- return [self._make_member(key, value, info)
+ return [self._make_member(key, value['type'], value.get('if'), info)
for (key, value) in data.items()]
def _def_struct_type(self, expr, info, doc):
@@ -1697,17 +1754,17 @@ class QAPISchema(object):
self._make_members(data, info),
None))
- def _make_variant(self, case, typ):
- return QAPISchemaObjectTypeVariant(case, typ)
+ def _make_variant(self, case, typ, ifcond):
+ return QAPISchemaObjectTypeVariant(case, typ, ifcond)
- def _make_simple_variant(self, case, typ, info):
+ def _make_simple_variant(self, case, typ, ifcond, info):
if isinstance(typ, list):
assert len(typ) == 1
typ = self._make_array_type(typ[0], info)
typ = self._make_implicit_object_type(
typ, info, None, self.lookup_type(typ),
- 'wrapper', [self._make_member('data', typ, info)])
- return QAPISchemaObjectTypeVariant(case, typ)
+ 'wrapper', [self._make_member('data', typ, None, info)])
+ return QAPISchemaObjectTypeVariant(case, typ, ifcond)
def _def_union_type(self, expr, info, doc):
name = expr['union']
@@ -1721,14 +1778,15 @@ class QAPISchema(object):
name, info, doc, ifcond,
'base', self._make_members(base, info))
if tag_name:
- variants = [self._make_variant(key, value)
+ variants = [self._make_variant(key, value['type'], value.get('if'))
for (key, value) in data.items()]
members = []
else:
- variants = [self._make_simple_variant(key, value, info)
+ variants = [self._make_simple_variant(key, value['type'],
+ value.get('if'), info)
for (key, value) in data.items()]
- typ = self._make_implicit_enum_type(name, info, ifcond,
- [v.name for v in variants])
+ enum = [{'name': v.name, 'if': v.ifcond} for v in variants]
+ typ = self._make_implicit_enum_type(name, info, ifcond, enum)
tag_member = QAPISchemaObjectTypeMember('type', typ, False)
members = [tag_member]
self._def_entity(
@@ -1741,7 +1799,7 @@ class QAPISchema(object):
name = expr['alternate']
data = expr['data']
ifcond = expr.get('if')
- variants = [self._make_variant(key, value)
+ variants = [self._make_variant(key, value['type'], value.get('if'))
for (key, value) in data.items()]
tag_member = QAPISchemaObjectTypeMember('type', 'QType', False)
self._def_entity(
@@ -2012,19 +2070,21 @@ def _wrap_ifcond(ifcond, before, after):
return out
-def gen_enum_lookup(name, values, prefix=None):
+def gen_enum_lookup(name, members, prefix=None):
ret = mcgen('''
const QEnumLookup %(c_name)s_lookup = {
.array = (const char *const[]) {
''',
c_name=c_name(name))
- for value in values:
- index = c_enum_const(name, value, prefix)
+ for m in members:
+ ret += gen_if(m.ifcond)
+ index = c_enum_const(name, m.name, prefix)
ret += mcgen('''
- [%(index)s] = "%(value)s",
+ [%(index)s] = "%(name)s",
''',
- index=index, value=value)
+ index=index, name=m.name)
+ ret += gen_endif(m.ifcond)
ret += mcgen('''
},
@@ -2035,9 +2095,9 @@ const QEnumLookup %(c_name)s_lookup = {
return ret
-def gen_enum(name, values, prefix=None):
+def gen_enum(name, members, prefix=None):
# append automatically generated _MAX value
- enum_values = values + ['_MAX']
+ enum_members = members + [QAPISchemaMember('_MAX')]
ret = mcgen('''
@@ -2045,14 +2105,13 @@ typedef enum %(c_name)s {
''',
c_name=c_name(name))
- i = 0
- for value in enum_values:
+ for m in enum_members:
+ ret += gen_if(m.ifcond)
ret += mcgen('''
- %(c_enum)s = %(i)d,
+ %(c_enum)s,
''',
- c_enum=c_enum_const(name, value, prefix),
- i=i)
- i += 1
+ c_enum=c_enum_const(name, m.name, prefix))
+ ret += gen_endif(m.ifcond)
ret += mcgen('''
} %(c_name)s;
diff --git a/scripts/qapi/doc.py b/scripts/qapi/doc.py
index 987fd3c943..c03b690161 100755
--- a/scripts/qapi/doc.py
+++ b/scripts/qapi/doc.py
@@ -126,19 +126,27 @@ def texi_body(doc):
return texi_format(doc.body.text)
-def texi_enum_value(value):
+def texi_if(ifcond, prefix='\n', suffix='\n'):
+ """Format the #if condition"""
+ if not ifcond:
+ return ''
+ return '%s@b{If:} @code{%s}%s' % (prefix, ', '.join(ifcond), suffix)
+
+
+def texi_enum_value(value, desc, suffix):
"""Format a table of members item for an enumeration value"""
- return '@item @code{%s}\n' % value.name
+ return '@item @code{%s}\n%s%s' % (
+ value.name, desc, texi_if(value.ifcond, prefix='@*'))
-def texi_member(member, suffix=''):
+def texi_member(member, desc, suffix):
"""Format a table of members item for an object type member"""
typ = member.type.doc_type()
membertype = ': ' + typ if typ else ''
- return '@item @code{%s%s}%s%s\n' % (
+ return '@item @code{%s%s}%s%s\n%s%s' % (
member.name, membertype,
' (optional)' if member.optional else '',
- suffix)
+ suffix, desc, texi_if(member.ifcond, prefix='@*'))
def texi_members(doc, what, base, variants, member_func):
@@ -155,17 +163,17 @@ def texi_members(doc, what, base, variants, member_func):
desc = 'One of ' + members_text + '\n'
else:
desc = 'Not documented\n'
- items += member_func(section.member) + desc
+ items += member_func(section.member, desc, suffix='')
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)
+ when = ' when @code{%s} is @t{"%s"}%s' % (
+ variants.tag_member.name, v.name, texi_if(v.ifcond, " (", ")"))
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)
+ items += member_func(m, desc='', suffix=when)
else:
items += '@item The members of @code{%s}%s\n' % (
v.type.doc_type(), when)
@@ -185,8 +193,7 @@ def texi_sections(doc, ifcond):
body += texi_example(section.text)
else:
body += texi_format(section.text)
- if ifcond:
- body += '\n\n@b{If:} @code{%s}' % ", ".join(ifcond)
+ body += texi_if(ifcond, suffix='')
return body
@@ -206,7 +213,7 @@ class QAPISchemaGenDocVisitor(qapi.common.QAPISchemaVisitor):
def write(self, output_dir):
self._gen.write(output_dir, self._prefix + 'qapi-doc.texi')
- def visit_enum_type(self, name, info, ifcond, values, prefix):
+ def visit_enum_type(self, name, info, ifcond, members, prefix):
doc = self.cur_doc
self._gen.add(TYPE_FMT(type='Enum',
name=doc.symbol,
diff --git a/scripts/qapi/events.py b/scripts/qapi/events.py
index 2ed7902424..37ee5de682 100644
--- a/scripts/qapi/events.py
+++ b/scripts/qapi/events.py
@@ -143,8 +143,8 @@ class QAPISchemaGenEventVisitor(QAPISchemaModularCVisitor):
QAPISchemaModularCVisitor.__init__(
self, prefix, 'qapi-events',
' * Schema-defined QAPI/QMP events', __doc__)
- self._enum_name = c_name(prefix + 'QAPIEvent', protect=False)
- self._event_names = []
+ self._event_enum_name = c_name(prefix + 'QAPIEvent', protect=False)
+ self._event_enum_members = []
def _begin_module(self, name):
types = self._module_basename('qapi-types', name)
@@ -170,15 +170,16 @@ class QAPISchemaGenEventVisitor(QAPISchemaModularCVisitor):
def visit_end(self):
(genc, genh) = self._module[self._main_module]
- genh.add(gen_enum(self._enum_name, self._event_names))
- genc.add(gen_enum_lookup(self._enum_name, self._event_names))
+ genh.add(gen_enum(self._event_enum_name, self._event_enum_members))
+ genc.add(gen_enum_lookup(self._event_enum_name,
+ self._event_enum_members))
def visit_event(self, name, info, ifcond, arg_type, boxed):
with ifcontext(ifcond, self._genh, self._genc):
self._genh.add(gen_event_send_decl(name, arg_type, boxed))
self._genc.add(gen_event_send(name, arg_type, boxed,
- self._enum_name))
- self._event_names.append(name)
+ self._event_enum_name))
+ self._event_enum_members.append(QAPISchemaMember(name, ifcond))
def gen_events(schema, output_dir, prefix):
diff --git a/scripts/qapi/introspect.py b/scripts/qapi/introspect.py
index 67d6106f77..f7f2ca07e4 100644
--- a/scripts/qapi/introspect.py
+++ b/scripts/qapi/introspect.py
@@ -162,6 +162,8 @@ const QLitObject %(c_name)s = %(c_string)s;
ret = {'name': member.name, 'type': self._use_type(member.type)}
if member.optional:
ret['default'] = None
+ if member.ifcond:
+ ret = (ret, {'if': member.ifcond})
return ret
def _gen_variants(self, tag_name, variants):
@@ -169,13 +171,17 @@ const QLitObject %(c_name)s = %(c_string)s;
'variants': [self._gen_variant(v) for v in variants]}
def _gen_variant(self, variant):
- return {'case': variant.name, 'type': self._use_type(variant.type)}
+ return ({'case': variant.name, 'type': self._use_type(variant.type)},
+ {'if': variant.ifcond})
def visit_builtin_type(self, name, info, json_type):
self._gen_qlit(name, 'builtin', {'json-type': json_type}, [])
- def visit_enum_type(self, name, info, ifcond, values, prefix):
- self._gen_qlit(name, 'enum', {'values': values}, ifcond)
+ def visit_enum_type(self, name, info, ifcond, members, prefix):
+ self._gen_qlit(name, 'enum',
+ {'values':
+ [(m.name, {'if': m.ifcond}) for m in members]},
+ ifcond)
def visit_array_type(self, name, info, ifcond, element_type):
element = self._use_type(element_type)
@@ -191,8 +197,9 @@ const QLitObject %(c_name)s = %(c_string)s;
def visit_alternate_type(self, name, info, ifcond, variants):
self._gen_qlit(name, 'alternate',
- {'members': [{'type': self._use_type(m.type)}
- for m in variants.variants]}, ifcond)
+ {'members': [
+ ({'type': self._use_type(m.type)}, {'if': m.ifcond})
+ for m in variants.variants]}, ifcond)
def visit_command(self, name, info, ifcond, arg_type, ret_type, gen,
success_response, boxed, allow_oob, allow_preconfig):
diff --git a/scripts/qapi/types.py b/scripts/qapi/types.py
index fd7808103c..62d4cf9f95 100644
--- a/scripts/qapi/types.py
+++ b/scripts/qapi/types.py
@@ -43,6 +43,7 @@ struct %(c_name)s {
def gen_struct_members(members):
ret = ''
for memb in members:
+ ret += gen_if(memb.ifcond)
if memb.optional:
ret += mcgen('''
bool has_%(c_name)s;
@@ -52,6 +53,7 @@ def gen_struct_members(members):
%(c_type)s %(c_name)s;
''',
c_type=memb.type.c_type(), c_name=c_name(memb.name))
+ ret += gen_endif(memb.ifcond)
return ret
@@ -131,11 +133,13 @@ def gen_variants(variants):
for var in variants.variants:
if var.type.name == 'q_empty':
continue
+ ret += gen_if(var.ifcond)
ret += mcgen('''
%(c_type)s %(c_name)s;
''',
c_type=var.type.c_unboxed_type(),
c_name=c_name(var.name))
+ ret += gen_endif(var.ifcond)
ret += mcgen('''
} u;
@@ -212,10 +216,10 @@ class QAPISchemaGenTypeVisitor(QAPISchemaModularCVisitor):
self._genh.add(gen_type_cleanup_decl(name))
self._genc.add(gen_type_cleanup(name))
- def visit_enum_type(self, name, info, ifcond, values, prefix):
+ def visit_enum_type(self, name, info, ifcond, members, prefix):
with ifcontext(ifcond, self._genh, self._genc):
- self._genh.preamble_add(gen_enum(name, values, prefix))
- self._genc.add(gen_enum_lookup(name, values, prefix))
+ self._genh.preamble_add(gen_enum(name, members, prefix))
+ self._genc.add(gen_enum_lookup(name, members, prefix))
def visit_array_type(self, name, info, ifcond, element_type):
with ifcontext(ifcond, self._genh, self._genc):
diff --git a/scripts/qapi/visit.py b/scripts/qapi/visit.py
index 460cf12989..82eab72b21 100644
--- a/scripts/qapi/visit.py
+++ b/scripts/qapi/visit.py
@@ -54,6 +54,7 @@ void visit_type_%(c_name)s_members(Visitor *v, %(c_name)s *obj, Error **errp)
c_type=base.c_name())
for memb in members:
+ ret += gen_if(memb.ifcond)
if memb.optional:
ret += mcgen('''
if (visit_optional(v, "%(name)s", &obj->has_%(c_name)s)) {
@@ -73,6 +74,7 @@ void visit_type_%(c_name)s_members(Visitor *v, %(c_name)s *obj, Error **errp)
ret += mcgen('''
}
''')
+ ret += gen_endif(memb.ifcond)
if variants:
ret += mcgen('''
@@ -84,6 +86,7 @@ void visit_type_%(c_name)s_members(Visitor *v, %(c_name)s *obj, Error **errp)
case_str = c_enum_const(variants.tag_member.type.name,
var.name,
variants.tag_member.type.prefix)
+ ret += gen_if(var.ifcond)
if var.type.name == 'q_empty':
# valid variant and nothing to do
ret += mcgen('''
@@ -100,6 +103,7 @@ void visit_type_%(c_name)s_members(Visitor *v, %(c_name)s *obj, Error **errp)
case=case_str,
c_type=var.type.c_name(), c_name=c_name(var.name))
+ ret += gen_endif(var.ifcond)
ret += mcgen('''
default:
abort();
@@ -190,6 +194,7 @@ void visit_type_%(c_name)s(Visitor *v, const char *name, %(c_name)s **obj, Error
c_name=c_name(name))
for var in variants.variants:
+ ret += gen_if(var.ifcond)
ret += mcgen('''
case %(case)s:
''',
@@ -217,6 +222,7 @@ void visit_type_%(c_name)s(Visitor *v, const char *name, %(c_name)s **obj, Error
ret += mcgen('''
break;
''')
+ ret += gen_endif(var.ifcond)
ret += mcgen('''
case QTYPE_NONE:
@@ -310,7 +316,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaModularCVisitor):
''',
types=types))
- def visit_enum_type(self, name, info, ifcond, values, prefix):
+ def visit_enum_type(self, name, info, ifcond, members, prefix):
with ifcontext(ifcond, self._genh, self._genc):
self._genh.add(gen_visit_decl(name, scalar=True))
self._genc.add(gen_visit_enum(name))
diff --git a/scripts/tracetool/backend/log.py b/scripts/tracetool/backend/log.py
index 6751f41bc5..33c95af8e9 100644
--- a/scripts/tracetool/backend/log.py
+++ b/scripts/tracetool/backend/log.py
@@ -39,7 +39,7 @@ def generate_h(event, group):
' struct timeval _now;',
' gettimeofday(&_now, NULL);',
' qemu_log("%%d@%%zu.%%06zu:%(name)s " %(fmt)s "\\n",',
- ' getpid(),',
+ ' qemu_get_thread_id(),',
' (size_t)_now.tv_sec, (size_t)_now.tv_usec',
' %(argnames)s);',
' }',
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 60411f6bfe..0b185f8d30 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -1932,6 +1932,10 @@ static void arm_max_initfn(Object *obj)
t = cpu->isar.id_isar6;
t = FIELD_DP32(t, ID_ISAR6, DP, 1);
cpu->isar.id_isar6 = t;
+
+ t = cpu->id_mmfr4;
+ t = FIELD_DP32(t, ID_MMFR4, HPDS, 1); /* AA32HPD */
+ cpu->id_mmfr4 = t;
}
#endif
}
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 2a73fed9a0..c943f35dd9 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -818,6 +818,8 @@ struct ARMCPU {
uint64_t id_aa64isar1;
uint64_t id_aa64pfr0;
uint64_t id_aa64pfr1;
+ uint64_t id_aa64mmfr0;
+ uint64_t id_aa64mmfr1;
} isar;
uint32_t midr;
uint32_t revidr;
@@ -839,8 +841,6 @@ struct ARMCPU {
uint64_t id_aa64dfr1;
uint64_t id_aa64afr0;
uint64_t id_aa64afr1;
- uint64_t id_aa64mmfr0;
- uint64_t id_aa64mmfr1;
uint32_t dbgdidr;
uint32_t clidr;
uint64_t mp_affinity; /* MP ID without feature bits */
@@ -1249,7 +1249,7 @@ static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
#define HCR_TIDCP (1ULL << 20)
#define HCR_TACR (1ULL << 21)
#define HCR_TSW (1ULL << 22)
-#define HCR_TPC (1ULL << 23)
+#define HCR_TPCP (1ULL << 23)
#define HCR_TPU (1ULL << 24)
#define HCR_TTLB (1ULL << 25)
#define HCR_TVM (1ULL << 26)
@@ -1261,6 +1261,26 @@ static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
#define HCR_CD (1ULL << 32)
#define HCR_ID (1ULL << 33)
#define HCR_E2H (1ULL << 34)
+#define HCR_TLOR (1ULL << 35)
+#define HCR_TERR (1ULL << 36)
+#define HCR_TEA (1ULL << 37)
+#define HCR_MIOCNCE (1ULL << 38)
+#define HCR_APK (1ULL << 40)
+#define HCR_API (1ULL << 41)
+#define HCR_NV (1ULL << 42)
+#define HCR_NV1 (1ULL << 43)
+#define HCR_AT (1ULL << 44)
+#define HCR_NV2 (1ULL << 45)
+#define HCR_FWB (1ULL << 46)
+#define HCR_FIEN (1ULL << 47)
+#define HCR_TID4 (1ULL << 49)
+#define HCR_TICAB (1ULL << 50)
+#define HCR_TOCU (1ULL << 52)
+#define HCR_TTLBIS (1ULL << 54)
+#define HCR_TTLBOS (1ULL << 55)
+#define HCR_ATA (1ULL << 56)
+#define HCR_DCT (1ULL << 57)
+
/*
* When we actually implement ARMv8.1-VHE we should add HCR_E2H to
* HCR_MASK and then clear it again if the feature bit is not set in
@@ -1282,8 +1302,16 @@ static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
#define SCR_ST (1U << 11)
#define SCR_TWI (1U << 12)
#define SCR_TWE (1U << 13)
-#define SCR_AARCH32_MASK (0x3fff & ~(SCR_RW | SCR_ST))
-#define SCR_AARCH64_MASK (0x3fff & ~SCR_NET)
+#define SCR_TLOR (1U << 14)
+#define SCR_TERR (1U << 15)
+#define SCR_APK (1U << 16)
+#define SCR_API (1U << 17)
+#define SCR_EEL2 (1U << 18)
+#define SCR_EASE (1U << 19)
+#define SCR_NMEA (1U << 20)
+#define SCR_FIEN (1U << 21)
+#define SCR_ENSCXT (1U << 25)
+#define SCR_ATA (1U << 26)
/* Return the current FPSCR value. */
uint32_t vfp_get_fpscr(CPUARMState *env);
@@ -1520,6 +1548,15 @@ FIELD(ID_ISAR6, FHM, 8, 4)
FIELD(ID_ISAR6, SB, 12, 4)
FIELD(ID_ISAR6, SPECRES, 16, 4)
+FIELD(ID_MMFR4, SPECSEI, 0, 4)
+FIELD(ID_MMFR4, AC2, 4, 4)
+FIELD(ID_MMFR4, XNX, 8, 4)
+FIELD(ID_MMFR4, CNP, 12, 4)
+FIELD(ID_MMFR4, HPDS, 16, 4)
+FIELD(ID_MMFR4, LSM, 20, 4)
+FIELD(ID_MMFR4, CCIDX, 24, 4)
+FIELD(ID_MMFR4, EVT, 28, 4)
+
FIELD(ID_AA64ISAR0, AES, 4, 4)
FIELD(ID_AA64ISAR0, SHA1, 8, 4)
FIELD(ID_AA64ISAR0, SHA2, 12, 4)
@@ -1557,6 +1594,28 @@ FIELD(ID_AA64PFR0, GIC, 24, 4)
FIELD(ID_AA64PFR0, RAS, 28, 4)
FIELD(ID_AA64PFR0, SVE, 32, 4)
+FIELD(ID_AA64MMFR0, PARANGE, 0, 4)
+FIELD(ID_AA64MMFR0, ASIDBITS, 4, 4)
+FIELD(ID_AA64MMFR0, BIGEND, 8, 4)
+FIELD(ID_AA64MMFR0, SNSMEM, 12, 4)
+FIELD(ID_AA64MMFR0, BIGENDEL0, 16, 4)
+FIELD(ID_AA64MMFR0, TGRAN16, 20, 4)
+FIELD(ID_AA64MMFR0, TGRAN64, 24, 4)
+FIELD(ID_AA64MMFR0, TGRAN4, 28, 4)
+FIELD(ID_AA64MMFR0, TGRAN16_2, 32, 4)
+FIELD(ID_AA64MMFR0, TGRAN64_2, 36, 4)
+FIELD(ID_AA64MMFR0, TGRAN4_2, 40, 4)
+FIELD(ID_AA64MMFR0, EXS, 44, 4)
+
+FIELD(ID_AA64MMFR1, HAFDBS, 0, 4)
+FIELD(ID_AA64MMFR1, VMIDBITS, 4, 4)
+FIELD(ID_AA64MMFR1, VH, 8, 4)
+FIELD(ID_AA64MMFR1, HPDS, 12, 4)
+FIELD(ID_AA64MMFR1, LO, 16, 4)
+FIELD(ID_AA64MMFR1, PAN, 20, 4)
+FIELD(ID_AA64MMFR1, SPECSEI, 24, 4)
+FIELD(ID_AA64MMFR1, XNX, 28, 4)
+
QEMU_BUILD_BUG_ON(ARRAY_SIZE(((ARMCPU *)0)->ccsidr) <= R_V7M_CSSELR_INDEX_MASK);
/* If adding a feature bit which corresponds to a Linux ELF
@@ -1670,6 +1729,14 @@ static inline bool arm_is_secure(CPUARMState *env)
}
#endif
+/**
+ * arm_hcr_el2_eff(): Return the effective value of HCR_EL2.
+ * E.g. when in secure state, fields in HCR_EL2 are suppressed,
+ * "for all purposes other than a direct read or write access of HCR_EL2."
+ * Not included here is HCR_RW.
+ */
+uint64_t arm_hcr_el2_eff(CPUARMState *env);
+
/* Return true if the specified exception level is running in AArch64 state. */
static inline bool arm_el_is_aa64(CPUARMState *env, int el)
{
@@ -2355,54 +2422,6 @@ bool write_cpustate_to_list(ARMCPU *cpu);
# define TARGET_VIRT_ADDR_SPACE_BITS 32
#endif
-/**
- * arm_hcr_el2_imo(): Return the effective value of HCR_EL2.IMO.
- * Depending on the values of HCR_EL2.E2H and TGE, this may be
- * "behaves as 1 for all purposes other than direct read/write" or
- * "behaves as 0 for all purposes other than direct read/write"
- */
-static inline bool arm_hcr_el2_imo(CPUARMState *env)
-{
- switch (env->cp15.hcr_el2 & (HCR_TGE | HCR_E2H)) {
- case HCR_TGE:
- return true;
- case HCR_TGE | HCR_E2H:
- return false;
- default:
- return env->cp15.hcr_el2 & HCR_IMO;
- }
-}
-
-/**
- * arm_hcr_el2_fmo(): Return the effective value of HCR_EL2.FMO.
- */
-static inline bool arm_hcr_el2_fmo(CPUARMState *env)
-{
- switch (env->cp15.hcr_el2 & (HCR_TGE | HCR_E2H)) {
- case HCR_TGE:
- return true;
- case HCR_TGE | HCR_E2H:
- return false;
- default:
- return env->cp15.hcr_el2 & HCR_FMO;
- }
-}
-
-/**
- * arm_hcr_el2_amo(): Return the effective value of HCR_EL2.AMO.
- */
-static inline bool arm_hcr_el2_amo(CPUARMState *env)
-{
- switch (env->cp15.hcr_el2 & (HCR_TGE | HCR_E2H)) {
- case HCR_TGE:
- return true;
- case HCR_TGE | HCR_E2H:
- return false;
- default:
- return env->cp15.hcr_el2 & HCR_AMO;
- }
-}
-
static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx,
unsigned int target_el)
{
@@ -2411,6 +2430,7 @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx,
bool secure = arm_is_secure(env);
bool pstate_unmasked;
int8_t unmasked = 0;
+ uint64_t hcr_el2;
/* Don't take exceptions if they target a lower EL.
* This check should catch any exceptions that would not be taken but left
@@ -2420,6 +2440,8 @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx,
return false;
}
+ hcr_el2 = arm_hcr_el2_eff(env);
+
switch (excp_idx) {
case EXCP_FIQ:
pstate_unmasked = !(env->daif & PSTATE_F);
@@ -2430,13 +2452,13 @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx,
break;
case EXCP_VFIQ:
- if (secure || !arm_hcr_el2_fmo(env) || (env->cp15.hcr_el2 & HCR_TGE)) {
+ if (secure || !(hcr_el2 & HCR_FMO) || (hcr_el2 & HCR_TGE)) {
/* VFIQs are only taken when hypervized and non-secure. */
return false;
}
return !(env->daif & PSTATE_F);
case EXCP_VIRQ:
- if (secure || !arm_hcr_el2_imo(env) || (env->cp15.hcr_el2 & HCR_TGE)) {
+ if (secure || !(hcr_el2 & HCR_IMO) || (hcr_el2 & HCR_TGE)) {
/* VIRQs are only taken when hypervized and non-secure. */
return false;
}
@@ -2475,7 +2497,7 @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx,
* to the CPSR.F setting otherwise we further assess the state
* below.
*/
- hcr = arm_hcr_el2_fmo(env);
+ hcr = hcr_el2 & HCR_FMO;
scr = (env->cp15.scr_el3 & SCR_FIQ);
/* When EL3 is 32-bit, the SCR.FW bit controls whether the
@@ -2492,7 +2514,7 @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx,
* when setting the target EL, so it does not have a further
* affect here.
*/
- hcr = arm_hcr_el2_imo(env);
+ hcr = hcr_el2 & HCR_IMO;
scr = false;
break;
default:
@@ -3318,6 +3340,11 @@ static inline bool isar_feature_aa64_sve(const ARMISARegisters *id)
return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, SVE) != 0;
}
+static inline bool isar_feature_aa64_lor(const ARMISARegisters *id)
+{
+ return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, LO) != 0;
+}
+
/*
* Forward to the above feature tests given an ARMCPU pointer.
*/
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index 873f059bf2..1d57be0c91 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -141,7 +141,7 @@ static void aarch64_a57_initfn(Object *obj)
cpu->pmceid0 = 0x00000000;
cpu->pmceid1 = 0x00000000;
cpu->isar.id_aa64isar0 = 0x00011120;
- cpu->id_aa64mmfr0 = 0x00001124;
+ cpu->isar.id_aa64mmfr0 = 0x00001124;
cpu->dbgdidr = 0x3516d000;
cpu->clidr = 0x0a200023;
cpu->ccsidr[0] = 0x701fe00a; /* 32KB L1 dcache */
@@ -195,7 +195,7 @@ static void aarch64_a53_initfn(Object *obj)
cpu->isar.id_aa64pfr0 = 0x00002222;
cpu->id_aa64dfr0 = 0x10305106;
cpu->isar.id_aa64isar0 = 0x00011120;
- cpu->id_aa64mmfr0 = 0x00001122; /* 40 bit physical addr */
+ cpu->isar.id_aa64mmfr0 = 0x00001122; /* 40 bit physical addr */
cpu->dbgdidr = 0x3516d000;
cpu->clidr = 0x0a200023;
cpu->ccsidr[0] = 0x700fe01a; /* 32KB L1 dcache */
@@ -249,7 +249,7 @@ static void aarch64_a72_initfn(Object *obj)
cpu->pmceid0 = 0x00000000;
cpu->pmceid1 = 0x00000000;
cpu->isar.id_aa64isar0 = 0x00011120;
- cpu->id_aa64mmfr0 = 0x00001124;
+ cpu->isar.id_aa64mmfr0 = 0x00001124;
cpu->dbgdidr = 0x3516d000;
cpu->clidr = 0x0a200023;
cpu->ccsidr[0] = 0x701fe00a; /* 32KB L1 dcache */
@@ -324,6 +324,11 @@ static void aarch64_max_initfn(Object *obj)
t = FIELD_DP64(t, ID_AA64PFR0, ADVSIMD, 1);
cpu->isar.id_aa64pfr0 = t;
+ t = cpu->isar.id_aa64mmfr1;
+ t = FIELD_DP64(t, ID_AA64MMFR1, HPDS, 1); /* HPD */
+ t = FIELD_DP64(t, ID_AA64MMFR1, LO, 1);
+ cpu->isar.id_aa64mmfr1 = t;
+
/* Replicate the same data to the 32-bit id registers. */
u = cpu->isar.id_isar5;
u = FIELD_DP32(u, ID_ISAR5, AES, 2); /* AES + PMULL */
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 0da1424f72..644599b29d 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -448,7 +448,7 @@ static CPAccessResult access_tdosa(CPUARMState *env, const ARMCPRegInfo *ri,
int el = arm_current_el(env);
bool mdcr_el2_tdosa = (env->cp15.mdcr_el2 & MDCR_TDOSA) ||
(env->cp15.mdcr_el2 & MDCR_TDE) ||
- (env->cp15.hcr_el2 & HCR_TGE);
+ (arm_hcr_el2_eff(env) & HCR_TGE);
if (el < 2 && mdcr_el2_tdosa && !arm_is_secure_below_el3(env)) {
return CP_ACCESS_TRAP_EL2;
@@ -468,7 +468,7 @@ static CPAccessResult access_tdra(CPUARMState *env, const ARMCPRegInfo *ri,
int el = arm_current_el(env);
bool mdcr_el2_tdra = (env->cp15.mdcr_el2 & MDCR_TDRA) ||
(env->cp15.mdcr_el2 & MDCR_TDE) ||
- (env->cp15.hcr_el2 & HCR_TGE);
+ (arm_hcr_el2_eff(env) & HCR_TGE);
if (el < 2 && mdcr_el2_tdra && !arm_is_secure_below_el3(env)) {
return CP_ACCESS_TRAP_EL2;
@@ -488,7 +488,7 @@ static CPAccessResult access_tda(CPUARMState *env, const ARMCPRegInfo *ri,
int el = arm_current_el(env);
bool mdcr_el2_tda = (env->cp15.mdcr_el2 & MDCR_TDA) ||
(env->cp15.mdcr_el2 & MDCR_TDE) ||
- (env->cp15.hcr_el2 & HCR_TGE);
+ (arm_hcr_el2_eff(env) & HCR_TGE);
if (el < 2 && mdcr_el2_tda && !arm_is_secure_below_el3(env)) {
return CP_ACCESS_TRAP_EL2;
@@ -1279,11 +1279,16 @@ static void vbar_write(CPUARMState *env, const ARMCPRegInfo *ri,
static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
{
- /* We only mask off bits that are RES0 both for AArch64 and AArch32.
- * For bits that vary between AArch32/64, code needs to check the
- * current execution mode before directly using the feature bit.
- */
- uint32_t valid_mask = SCR_AARCH64_MASK | SCR_AARCH32_MASK;
+ /* Begin with base v8.0 state. */
+ uint32_t valid_mask = 0x3fff;
+ ARMCPU *cpu = arm_env_get_cpu(env);
+
+ if (arm_el_is_aa64(env, 3)) {
+ value |= SCR_FW | SCR_AW; /* these two bits are RES1. */
+ valid_mask &= ~SCR_NET;
+ } else {
+ valid_mask &= ~(SCR_RW | SCR_ST);
+ }
if (!arm_feature(env, ARM_FEATURE_EL2)) {
valid_mask &= ~SCR_HCE;
@@ -1299,6 +1304,9 @@ static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
valid_mask &= ~SCR_SMD;
}
}
+ if (cpu_isar_feature(aa64_lor, cpu)) {
+ valid_mask |= SCR_TLOR;
+ }
/* Clear all-context RES0 bits. */
value &= valid_mask;
@@ -1327,9 +1335,10 @@ static void csselr_write(CPUARMState *env, const ARMCPRegInfo *ri,
static uint64_t isr_read(CPUARMState *env, const ARMCPRegInfo *ri)
{
CPUState *cs = ENV_GET_CPU(env);
+ uint64_t hcr_el2 = arm_hcr_el2_eff(env);
uint64_t ret = 0;
- if (arm_hcr_el2_imo(env)) {
+ if (hcr_el2 & HCR_IMO) {
if (cs->interrupt_request & CPU_INTERRUPT_VIRQ) {
ret |= CPSR_I;
}
@@ -1339,7 +1348,7 @@ static uint64_t isr_read(CPUARMState *env, const ARMCPRegInfo *ri)
}
}
- if (arm_hcr_el2_fmo(env)) {
+ if (hcr_el2 & HCR_FMO) {
if (cs->interrupt_request & CPU_INTERRUPT_VFIQ) {
ret |= CPSR_F;
}
@@ -2724,6 +2733,7 @@ static void vmsa_ttbcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
uint64_t value)
{
ARMCPU *cpu = arm_env_get_cpu(env);
+ TCR *tcr = raw_ptr(env, ri);
if (arm_feature(env, ARM_FEATURE_LPAE)) {
/* With LPAE the TTBCR could result in a change of ASID
@@ -2731,6 +2741,8 @@ static void vmsa_ttbcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
*/
tlb_flush(CPU(cpu));
}
+ /* Preserve the high half of TCR_EL1, set via TTBCR2. */
+ value = deposit64(tcr->raw_tcr, 0, 32, value);
vmsa_ttbcr_raw_write(env, ri, value);
}
@@ -2833,6 +2845,16 @@ static const ARMCPRegInfo vmsa_cp_reginfo[] = {
REGINFO_SENTINEL
};
+/* Note that unlike TTBCR, writing to TTBCR2 does not require flushing
+ * qemu tlbs nor adjusting cached masks.
+ */
+static const ARMCPRegInfo ttbcr2_reginfo = {
+ .name = "TTBCR2", .cp = 15, .opc1 = 0, .crn = 2, .crm = 0, .opc2 = 3,
+ .access = PL1_RW, .type = ARM_CP_ALIAS,
+ .bank_fieldoffsets = { offsetofhigh32(CPUARMState, cp15.tcr_el[3]),
+ offsetofhigh32(CPUARMState, cp15.tcr_el[1]) },
+};
+
static void omap_ticonfig_write(CPUARMState *env, const ARMCPRegInfo *ri,
uint64_t value)
{
@@ -3945,6 +3967,9 @@ static void hcr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
*/
valid_mask &= ~HCR_TSC;
}
+ if (cpu_isar_feature(aa64_lor, cpu)) {
+ valid_mask |= HCR_TLOR;
+ }
/* Clear RES0 bits. */
value &= valid_mask;
@@ -3991,6 +4016,51 @@ static void hcr_writelow(CPUARMState *env, const ARMCPRegInfo *ri,
hcr_write(env, NULL, value);
}
+/*
+ * Return the effective value of HCR_EL2.
+ * Bits that are not included here:
+ * RW (read from SCR_EL3.RW as needed)
+ */
+uint64_t arm_hcr_el2_eff(CPUARMState *env)
+{
+ uint64_t ret = env->cp15.hcr_el2;
+
+ if (arm_is_secure_below_el3(env)) {
+ /*
+ * "This register has no effect if EL2 is not enabled in the
+ * current Security state". This is ARMv8.4-SecEL2 speak for
+ * !(SCR_EL3.NS==1 || SCR_EL3.EEL2==1).
+ *
+ * Prior to that, the language was "In an implementation that
+ * includes EL3, when the value of SCR_EL3.NS is 0 the PE behaves
+ * as if this field is 0 for all purposes other than a direct
+ * read or write access of HCR_EL2". With lots of enumeration
+ * on a per-field basis. In current QEMU, this is condition
+ * is arm_is_secure_below_el3.
+ *
+ * Since the v8.4 language applies to the entire register, and
+ * appears to be backward compatible, use that.
+ */
+ ret = 0;
+ } else if (ret & HCR_TGE) {
+ /* These bits are up-to-date as of ARMv8.4. */
+ if (ret & HCR_E2H) {
+ ret &= ~(HCR_VM | HCR_FMO | HCR_IMO | HCR_AMO |
+ HCR_BSU_MASK | HCR_DC | HCR_TWI | HCR_TWE |
+ HCR_TID0 | HCR_TID2 | HCR_TPCP | HCR_TPU |
+ HCR_TDZ | HCR_CD | HCR_ID | HCR_MIOCNCE);
+ } else {
+ ret |= HCR_FMO | HCR_IMO | HCR_AMO;
+ }
+ ret &= ~(HCR_SWIO | HCR_PTW | HCR_VF | HCR_VI | HCR_VSE |
+ HCR_FB | HCR_TID1 | HCR_TID3 | HCR_TSC | HCR_TACR |
+ HCR_TSW | HCR_TTLB | HCR_TVM | HCR_HCD | HCR_TRVM |
+ HCR_TLOR);
+ }
+
+ return ret;
+}
+
static const ARMCPRegInfo el2_cp_reginfo[] = {
{ .name = "HCR_EL2", .state = ARM_CP_STATE_AA64,
.type = ARM_CP_IO,
@@ -4503,8 +4573,7 @@ int sve_exception_el(CPUARMState *env, int el)
if (disabled) {
/* route_to_el2 */
return (arm_feature(env, ARM_FEATURE_EL2)
- && !arm_is_secure(env)
- && (env->cp15.hcr_el2 & HCR_TGE) ? 2 : 1);
+ && (arm_hcr_el2_eff(env) & HCR_TGE) ? 2 : 1);
}
/* Check CPACR.FPEN. */
@@ -4956,6 +5025,42 @@ static uint64_t id_aa64pfr0_read(CPUARMState *env, const ARMCPRegInfo *ri)
return pfr0;
}
+/* Shared logic between LORID and the rest of the LOR* registers.
+ * Secure state has already been delt with.
+ */
+static CPAccessResult access_lor_ns(CPUARMState *env)
+{
+ int el = arm_current_el(env);
+
+ if (el < 2 && (arm_hcr_el2_eff(env) & HCR_TLOR)) {
+ return CP_ACCESS_TRAP_EL2;
+ }
+ if (el < 3 && (env->cp15.scr_el3 & SCR_TLOR)) {
+ return CP_ACCESS_TRAP_EL3;
+ }
+ return CP_ACCESS_OK;
+}
+
+static CPAccessResult access_lorid(CPUARMState *env, const ARMCPRegInfo *ri,
+ bool isread)
+{
+ if (arm_is_secure_below_el3(env)) {
+ /* Access ok in secure mode. */
+ return CP_ACCESS_OK;
+ }
+ return access_lor_ns(env);
+}
+
+static CPAccessResult access_lor_other(CPUARMState *env,
+ const ARMCPRegInfo *ri, bool isread)
+{
+ if (arm_is_secure_below_el3(env)) {
+ /* Access denied in secure mode. */
+ return CP_ACCESS_TRAP;
+ }
+ return access_lor_ns(env);
+}
+
void register_cp_regs_for_features(ARMCPU *cpu)
{
/* Register all the coprocessor registers based on feature bits */
@@ -5207,11 +5312,11 @@ void register_cp_regs_for_features(ARMCPU *cpu)
{ .name = "ID_AA64MMFR0_EL1", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 0,
.access = PL1_R, .type = ARM_CP_CONST,
- .resetvalue = cpu->id_aa64mmfr0 },
+ .resetvalue = cpu->isar.id_aa64mmfr0 },
{ .name = "ID_AA64MMFR1_EL1", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 1,
.access = PL1_R, .type = ARM_CP_CONST,
- .resetvalue = cpu->id_aa64mmfr1 },
+ .resetvalue = cpu->isar.id_aa64mmfr1 },
{ .name = "ID_AA64MMFR2_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 2,
.access = PL1_R, .type = ARM_CP_CONST,
@@ -5433,6 +5538,10 @@ void register_cp_regs_for_features(ARMCPU *cpu)
} else {
define_arm_cp_regs(cpu, vmsa_pmsa_cp_reginfo);
define_arm_cp_regs(cpu, vmsa_cp_reginfo);
+ /* TTCBR2 is introduced with ARMv8.2-A32HPD. */
+ if (FIELD_EX32(cpu->id_mmfr4, ID_MMFR4, HPDS) != 0) {
+ define_one_arm_cp_reg(cpu, &ttbcr2_reginfo);
+ }
}
if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
define_arm_cp_regs(cpu, t2ee_cp_reginfo);
@@ -5693,6 +5802,38 @@ void register_cp_regs_for_features(ARMCPU *cpu)
define_one_arm_cp_reg(cpu, &sctlr);
}
+ if (cpu_isar_feature(aa64_lor, cpu)) {
+ /*
+ * A trivial implementation of ARMv8.1-LOR leaves all of these
+ * registers fixed at 0, which indicates that there are zero
+ * supported Limited Ordering regions.
+ */
+ static const ARMCPRegInfo lor_reginfo[] = {
+ { .name = "LORSA_EL1", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 4, .opc2 = 0,
+ .access = PL1_RW, .accessfn = access_lor_other,
+ .type = ARM_CP_CONST, .resetvalue = 0 },
+ { .name = "LOREA_EL1", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 4, .opc2 = 1,
+ .access = PL1_RW, .accessfn = access_lor_other,
+ .type = ARM_CP_CONST, .resetvalue = 0 },
+ { .name = "LORN_EL1", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 4, .opc2 = 2,
+ .access = PL1_RW, .accessfn = access_lor_other,
+ .type = ARM_CP_CONST, .resetvalue = 0 },
+ { .name = "LORC_EL1", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 4, .opc2 = 3,
+ .access = PL1_RW, .accessfn = access_lor_other,
+ .type = ARM_CP_CONST, .resetvalue = 0 },
+ { .name = "LORID_EL1", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 4, .opc2 = 7,
+ .access = PL1_R, .accessfn = access_lorid,
+ .type = ARM_CP_CONST, .resetvalue = 0 },
+ REGINFO_SENTINEL
+ };
+ define_arm_cp_regs(cpu, lor_reginfo);
+ }
+
if (cpu_isar_feature(aa64_sve, cpu)) {
define_one_arm_cp_reg(cpu, &zcr_el1_reginfo);
if (arm_feature(env, ARM_FEATURE_EL2)) {
@@ -6149,9 +6290,8 @@ static int bad_mode_switch(CPUARMState *env, int mode, CPSRWriteType write_type)
* and CPS are treated as illegal mode changes.
*/
if (write_type == CPSRWriteByInstr &&
- (env->cp15.hcr_el2 & HCR_TGE) &&
(env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_MON &&
- !arm_is_secure_below_el3(env)) {
+ (arm_hcr_el2_eff(env) & HCR_TGE)) {
return 1;
}
return 0;
@@ -6505,12 +6645,13 @@ uint32_t arm_phys_excp_target_el(CPUState *cs, uint32_t excp_idx,
uint32_t cur_el, bool secure)
{
CPUARMState *env = cs->env_ptr;
- int rw;
- int scr;
- int hcr;
+ bool rw;
+ bool scr;
+ bool hcr;
int target_el;
/* Is the highest EL AArch64? */
- int is64 = arm_feature(env, ARM_FEATURE_AARCH64);
+ bool is64 = arm_feature(env, ARM_FEATURE_AARCH64);
+ uint64_t hcr_el2;
if (arm_feature(env, ARM_FEATURE_EL3)) {
rw = ((env->cp15.scr_el3 & SCR_RW) == SCR_RW);
@@ -6522,24 +6663,22 @@ uint32_t arm_phys_excp_target_el(CPUState *cs, uint32_t excp_idx,
rw = is64;
}
+ hcr_el2 = arm_hcr_el2_eff(env);
switch (excp_idx) {
case EXCP_IRQ:
scr = ((env->cp15.scr_el3 & SCR_IRQ) == SCR_IRQ);
- hcr = arm_hcr_el2_imo(env);
+ hcr = hcr_el2 & HCR_IMO;
break;
case EXCP_FIQ:
scr = ((env->cp15.scr_el3 & SCR_FIQ) == SCR_FIQ);
- hcr = arm_hcr_el2_fmo(env);
+ hcr = hcr_el2 & HCR_FMO;
break;
default:
scr = ((env->cp15.scr_el3 & SCR_EA) == SCR_EA);
- hcr = arm_hcr_el2_amo(env);
+ hcr = hcr_el2 & HCR_AMO;
break;
};
- /* If HCR.TGE is set then HCR is treated as being 1 */
- hcr |= ((env->cp15.hcr_el2 & HCR_TGE) == HCR_TGE);
-
/* Perform a table-lookup for the target EL given the current state */
target_el = target_el_table[is64][scr][rw][hcr][secure][cur_el];
@@ -9635,6 +9774,7 @@ static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
bool ttbr1_valid = true;
uint64_t descaddrmask;
bool aarch64 = arm_el_is_aa64(env, el);
+ bool hpd = false;
/* TODO:
* This code does not handle the different format TCR for VTCR_EL2.
@@ -9749,6 +9889,15 @@ static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
if (tg == 2) { /* 16KB pages */
stride = 11;
}
+ if (aarch64 && el > 1) {
+ hpd = extract64(tcr->raw_tcr, 24, 1);
+ } else {
+ hpd = extract64(tcr->raw_tcr, 41, 1);
+ }
+ if (!aarch64) {
+ /* For aarch32, hpd0 is not enabled without t2e as well. */
+ hpd &= extract64(tcr->raw_tcr, 6, 1);
+ }
} else {
/* We should only be here if TTBR1 is valid */
assert(ttbr1_valid);
@@ -9764,6 +9913,11 @@ static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
if (tg == 1) { /* 16KB pages */
stride = 11;
}
+ hpd = extract64(tcr->raw_tcr, 42, 1);
+ if (!aarch64) {
+ /* For aarch32, hpd1 is not enabled without t2e as well. */
+ hpd &= extract64(tcr->raw_tcr, 6, 1);
+ }
}
/* Here we should have set up all the parameters for the translation:
@@ -9857,7 +10011,7 @@ static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
descaddr = descriptor & descaddrmask;
if ((descriptor & 2) && (level < 3)) {
- /* Table entry. The top five bits are attributes which may
+ /* Table entry. The top five bits are attributes which may
* propagate down through lower levels of the table (and
* which are all arranged so that 0 means "no effect", so
* we can gather them up by ORing in the bits at each level).
@@ -9882,15 +10036,17 @@ static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
break;
}
/* Merge in attributes from table descriptors */
- attrs |= extract32(tableattrs, 0, 2) << 11; /* XN, PXN */
- attrs |= extract32(tableattrs, 3, 1) << 5; /* APTable[1] => AP[2] */
+ attrs |= nstable << 3; /* NS */
+ if (hpd) {
+ /* HPD disables all the table attributes except NSTable. */
+ break;
+ }
+ attrs |= extract32(tableattrs, 0, 2) << 11; /* XN, PXN */
/* The sense of AP[1] vs APTable[0] is reversed, as APTable[0] == 1
* means "force PL1 access only", which means forcing AP[1] to 0.
*/
- if (extract32(tableattrs, 2, 1)) {
- attrs &= ~(1 << 4);
- }
- attrs |= nstable << 3; /* NS */
+ attrs &= ~(extract32(tableattrs, 2, 1) << 4); /* !APT[0] => AP[1] */
+ attrs |= extract32(tableattrs, 3, 1) << 5; /* APT[1] => AP[2] */
break;
}
/* Here descaddr is the final physical address, and attributes
diff --git a/target/arm/idau.h b/target/arm/idau.h
index cac27b95fa..7c0e4e3776 100644
--- a/target/arm/idau.h
+++ b/target/arm/idau.h
@@ -38,9 +38,7 @@
#define IDAU_INTERFACE_GET_CLASS(obj) \
OBJECT_GET_CLASS(IDAUInterfaceClass, (obj), TYPE_IDAU_INTERFACE)
-typedef struct IDAUInterface {
- Object parent;
-} IDAUInterface;
+typedef struct IDAUInterface IDAUInterface;
#define IREGION_NOTVALID -1
diff --git a/target/arm/internals.h b/target/arm/internals.h
index d208b70a64..78e026d6e9 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -229,7 +229,8 @@ static inline unsigned int arm_pamax(ARMCPU *cpu)
[4] = 44,
[5] = 48,
};
- unsigned int parange = extract32(cpu->id_aa64mmfr0, 0, 4);
+ unsigned int parange =
+ FIELD_EX64(cpu->isar.id_aa64mmfr0, ID_AA64MMFR0, PARANGE);
/* id_aa64mmfr0 is a read-only register so values outside of the
* supported mappings can be considered an implementation error. */
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
index 0a502091e7..089af9c5f0 100644
--- a/target/arm/kvm64.c
+++ b/target/arm/kvm64.c
@@ -538,6 +538,10 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
ARM64_SYS_REG(3, 0, 0, 6, 0));
err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64isar1,
ARM64_SYS_REG(3, 0, 0, 6, 1));
+ err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64mmfr0,
+ ARM64_SYS_REG(3, 0, 0, 7, 0));
+ err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64mmfr1,
+ ARM64_SYS_REG(3, 0, 0, 7, 1));
/*
* Note that if AArch32 support is not present in the host,
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
index 0d6e89e474..ef72361a36 100644
--- a/target/arm/op_helper.c
+++ b/target/arm/op_helper.c
@@ -33,8 +33,7 @@ void raise_exception(CPUARMState *env, uint32_t excp,
{
CPUState *cs = CPU(arm_env_get_cpu(env));
- if ((env->cp15.hcr_el2 & HCR_TGE) &&
- target_el == 1 && !arm_is_secure(env)) {
+ if (target_el == 1 && (arm_hcr_el2_eff(env) & HCR_TGE)) {
/*
* Redirect NS EL1 exceptions to NS EL2. These are reported with
* their original syndrome register value, with the exception of
@@ -428,9 +427,9 @@ static inline int check_wfx_trap(CPUARMState *env, bool is_wfe)
* No need for ARM_FEATURE check as if HCR_EL2 doesn't exist the
* bits will be zero indicating no trap.
*/
- if (cur_el < 2 && !arm_is_secure(env)) {
- mask = (is_wfe) ? HCR_TWE : HCR_TWI;
- if (env->cp15.hcr_el2 & mask) {
+ if (cur_el < 2) {
+ mask = is_wfe ? HCR_TWE : HCR_TWI;
+ if (arm_hcr_el2_eff(env) & mask) {
return 2;
}
}
@@ -995,7 +994,7 @@ void HELPER(pre_smc)(CPUARMState *env, uint32_t syndrome)
exception_target_el(env));
}
- if (!secure && cur_el == 1 && (env->cp15.hcr_el2 & HCR_TSC)) {
+ if (cur_el == 1 && (arm_hcr_el2_eff(env) & HCR_TSC)) {
/* In NS EL1, HCR controlled routing to EL2 has priority over SMD.
* We also want an EL2 guest to be able to forbid its EL1 from
* making PSCI calls into QEMU's "firmware" via HCR.TSC.
@@ -1098,8 +1097,7 @@ void HELPER(exception_return)(CPUARMState *env)
goto illegal_return;
}
- if (new_el == 1 && (env->cp15.hcr_el2 & HCR_TGE)
- && !arm_is_secure_below_el3(env)) {
+ if (new_el == 1 && (arm_hcr_el2_eff(env) & HCR_TGE)) {
goto illegal_return;
}
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index fd36425f1a..e1da1e4d6f 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -2290,6 +2290,12 @@ static void disas_ldst_excl(DisasContext *s, uint32_t insn)
}
return;
+ case 0x8: /* STLLR */
+ if (!dc_isar_feature(aa64_lor, s)) {
+ break;
+ }
+ /* StoreLORelease is the same as Store-Release for QEMU. */
+ /* fall through */
case 0x9: /* STLR */
/* Generate ISS for non-exclusive accesses including LASR. */
if (rn == 31) {
@@ -2301,6 +2307,12 @@ static void disas_ldst_excl(DisasContext *s, uint32_t insn)
disas_ldst_compute_iss_sf(size, false, 0), is_lasr);
return;
+ case 0xc: /* LDLAR */
+ if (!dc_isar_feature(aa64_lor, s)) {
+ break;
+ }
+ /* LoadLOAcquire is the same as Load-Acquire for QEMU. */
+ /* fall through */
case 0xd: /* LDAR */
/* Generate ISS for non-exclusive accesses including LASR. */
if (rn == 31) {
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index f81d35e1f9..677a3bd5fb 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -1023,8 +1023,8 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
"avx512bitalg", NULL, "avx512-vpopcntdq", NULL,
"la57", NULL, NULL, NULL,
NULL, NULL, "rdpid", NULL,
- NULL, "cldemote", NULL, NULL,
- NULL, NULL, NULL, NULL,
+ NULL, "cldemote", NULL, "movdiri",
+ "movdir64b", NULL, NULL, NULL,
},
.cpuid = {
.eax = 7,
@@ -1042,7 +1042,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
NULL, NULL, NULL, NULL,
NULL, NULL, "pconfig", NULL,
NULL, NULL, NULL, NULL,
- NULL, NULL, "spec-ctrl", NULL,
+ NULL, NULL, "spec-ctrl", "stibp",
NULL, "arch-capabilities", NULL, "ssbd",
},
.cpuid = {
@@ -4065,7 +4065,7 @@ arch_query_cpu_model_expansion(CpuModelExpansionType type,
x86_cpu_to_dict_full(xc, props);
break;
default:
- error_setg(&err, "Unsupportted expansion type");
+ error_setg(&err, "Unsupported expansion type");
goto out;
}
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 9c52d0cbeb..ef41a033c5 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -687,6 +687,8 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS];
#define CPUID_7_0_ECX_LA57 (1U << 16)
#define CPUID_7_0_ECX_RDPID (1U << 22)
#define CPUID_7_0_ECX_CLDEMOTE (1U << 25) /* CLDEMOTE Instruction */
+#define CPUID_7_0_ECX_MOVDIRI (1U << 27) /* MOVDIRI Instruction */
+#define CPUID_7_0_ECX_MOVDIR64B (1U << 28) /* MOVDIR64B Instruction */
#define CPUID_7_0_EDX_AVX512_4VNNIW (1U << 2) /* AVX512 Neural Network Instructions */
#define CPUID_7_0_EDX_AVX512_4FMAPS (1U << 3) /* AVX512 Multiply Accumulation Single Precision */
diff --git a/target/i386/hax-all.c b/target/i386/hax-all.c
index d2e512856b..b978a9b821 100644
--- a/target/i386/hax-all.c
+++ b/target/i386/hax-all.c
@@ -154,13 +154,7 @@ int hax_vcpu_create(int id)
return 0;
}
- vcpu = g_malloc(sizeof(struct hax_vcpu_state));
- if (!vcpu) {
- fprintf(stderr, "Failed to alloc vcpu state\n");
- return -ENOMEM;
- }
-
- memset(vcpu, 0, sizeof(struct hax_vcpu_state));
+ vcpu = g_new0(struct hax_vcpu_state, 1);
ret = hax_host_create_vcpu(hax_global.vm->fd, id);
if (ret) {
@@ -211,7 +205,7 @@ int hax_vcpu_destroy(CPUState *cpu)
}
/*
- * 1. The hax_tunnel is also destroied when vcpu destroy
+ * 1. The hax_tunnel is also destroyed when vcpu is destroyed
* 2. close fd will cause hax module vcpu be cleaned
*/
hax_close_fd(vcpu->fd);
@@ -250,11 +244,8 @@ struct hax_vm *hax_vm_create(struct hax_state *hax)
return hax->vm;
}
- vm = g_malloc(sizeof(struct hax_vm));
- if (!vm) {
- return NULL;
- }
- memset(vm, 0, sizeof(struct hax_vm));
+ vm = g_new0(struct hax_vm, 1);
+
ret = hax_host_create_vm(hax, &vm_id);
if (ret) {
fprintf(stderr, "Failed to create vm %x\n", ret);
diff --git a/target/i386/kvm.c b/target/i386/kvm.c
index b2401d13ea..739cf8c8ea 100644
--- a/target/i386/kvm.c
+++ b/target/i386/kvm.c
@@ -864,7 +864,15 @@ int kvm_arch_init_vcpu(CPUState *cs)
struct {
struct kvm_cpuid2 cpuid;
struct kvm_cpuid_entry2 entries[KVM_MAX_CPUID_ENTRIES];
- } QEMU_PACKED cpuid_data;
+ } cpuid_data;
+ /*
+ * The kernel defines these structs with padding fields so there
+ * should be no extra padding in our cpuid_data struct.
+ */
+ QEMU_BUILD_BUG_ON(sizeof(cpuid_data) !=
+ sizeof(struct kvm_cpuid2) +
+ sizeof(struct kvm_cpuid_entry2) * KVM_MAX_CPUID_ENTRIES);
+
X86CPU *cpu = X86_CPU(cs);
CPUX86State *env = &cpu->env;
uint32_t limit, i, j, cpuid_i;
diff --git a/tcg/tcg.h b/tcg/tcg.h
index f4efbaa680..f9a56a9520 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -230,11 +230,9 @@ typedef uint64_t tcg_insn_unit;
#if defined CONFIG_DEBUG_TCG || defined QEMU_STATIC_ANALYSIS
# define tcg_debug_assert(X) do { assert(X); } while (0)
-#elif QEMU_GNUC_PREREQ(4, 5)
+#else
# define tcg_debug_assert(X) \
do { if (!(X)) { __builtin_unreachable(); } } while (0)
-#else
-# define tcg_debug_assert(X) do { (void)(X); } while (0)
#endif
typedef struct TCGRelocation {
diff --git a/tests/Makefile.include b/tests/Makefile.include
index fb0b449c02..3f5a1d0c30 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -318,6 +318,7 @@ qapi-schema += alternate-conflict-string.json
qapi-schema += alternate-conflict-bool-string.json
qapi-schema += alternate-conflict-num-string.json
qapi-schema += alternate-empty.json
+qapi-schema += alternate-invalid-dict.json
qapi-schema += alternate-nested.json
qapi-schema += alternate-unknown.json
qapi-schema += args-alternate.json
@@ -379,10 +380,12 @@ qapi-schema += double-data.json
qapi-schema += double-type.json
qapi-schema += duplicate-key.json
qapi-schema += empty.json
+qapi-schema += enum-bad-member.json
qapi-schema += enum-bad-name.json
qapi-schema += enum-bad-prefix.json
qapi-schema += enum-clash-member.json
-qapi-schema += enum-dict-member.json
+qapi-schema += enum-dict-member-unknown.json
+qapi-schema += enum-if-invalid.json
qapi-schema += enum-int-member.json
qapi-schema += enum-member-case.json
qapi-schema += enum-missing-data.json
@@ -392,6 +395,7 @@ qapi-schema += escape-too-big.json
qapi-schema += escape-too-short.json
qapi-schema += event-boxed-empty.json
qapi-schema += event-case.json
+qapi-schema += event-member-invalid-dict.json
qapi-schema += event-nest-struct.json
qapi-schema += flat-union-array-branch.json
qapi-schema += flat-union-bad-base.json
@@ -401,9 +405,11 @@ qapi-schema += flat-union-base-union.json
qapi-schema += flat-union-clash-member.json
qapi-schema += flat-union-empty.json
qapi-schema += flat-union-inline.json
+qapi-schema += flat-union-inline-invalid-dict.json
qapi-schema += flat-union-int-branch.json
qapi-schema += flat-union-invalid-branch-key.json
qapi-schema += flat-union-invalid-discriminator.json
+qapi-schema += flat-union-invalid-if-discriminator.json
qapi-schema += flat-union-no-base.json
qapi-schema += flat-union-optional-discriminator.json
qapi-schema += flat-union-string-discriminator.json
@@ -428,6 +434,7 @@ qapi-schema += missing-comma-list.json
qapi-schema += missing-comma-object.json
qapi-schema += missing-type.json
qapi-schema += nested-struct-data.json
+qapi-schema += nested-struct-data-invalid-dict.json
qapi-schema += non-objects.json
qapi-schema += oob-test.json
qapi-schema += allow-preconfig-test.json
@@ -458,6 +465,7 @@ qapi-schema += returns-whitelist.json
qapi-schema += struct-base-clash-deep.json
qapi-schema += struct-base-clash.json
qapi-schema += struct-data-invalid.json
+qapi-schema += struct-member-invalid-dict.json
qapi-schema += struct-member-invalid.json
qapi-schema += trailing-comma-list.json
qapi-schema += trailing-comma-object.json
@@ -469,6 +477,7 @@ 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-branch-invalid-dict.json
qapi-schema += union-clash-branches.json
qapi-schema += union-empty.json
qapi-schema += union-invalid-base.json
diff --git a/tests/check-qom-interface.c b/tests/check-qom-interface.c
index f87c9aaa8a..2177f0dce5 100644
--- a/tests/check-qom-interface.c
+++ b/tests/check-qom-interface.c
@@ -23,9 +23,7 @@
#define TEST_IF(obj) \
INTERFACE_CHECK(TestIf, (obj), TYPE_TEST_IF)
-typedef struct TestIf {
- Object parent_obj;
-} TestIf;
+typedef struct TestIf TestIf;
typedef struct TestIfClass {
InterfaceClass parent_class;
diff --git a/tests/libqtest.c b/tests/libqtest.c
index 75e07e16e7..43be078518 100644
--- a/tests/libqtest.c
+++ b/tests/libqtest.c
@@ -187,8 +187,7 @@ static const char *qtest_qemu_binary(void)
return qemu_bin;
}
-QTestState *qtest_init_without_qmp_handshake(bool use_oob,
- const char *extra_args)
+QTestState *qtest_init_without_qmp_handshake(const char *extra_args)
{
QTestState *s;
int sock, qmpsock, i;
@@ -219,12 +218,12 @@ QTestState *qtest_init_without_qmp_handshake(bool use_oob,
"-qtest unix:%s,nowait "
"-qtest-log %s "
"-chardev socket,path=%s,nowait,id=char0 "
- "-mon chardev=char0,mode=control%s "
+ "-mon chardev=char0,mode=control "
"-machine accel=qtest "
"-display none "
"%s", qemu_binary, socket_path,
getenv("QTEST_LOG") ? "/dev/fd/2" : "/dev/null",
- qmp_socket_path, use_oob ? ",x-oob=on" : "",
+ qmp_socket_path,
extra_args ?: "");
g_test_message("starting QEMU: %s", command);
@@ -266,7 +265,7 @@ QTestState *qtest_init_without_qmp_handshake(bool use_oob,
QTestState *qtest_init(const char *extra_args)
{
- QTestState *s = qtest_init_without_qmp_handshake(false, extra_args);
+ QTestState *s = qtest_init_without_qmp_handshake(extra_args);
QDict *greeting;
/* Read the QMP greeting and then do the handshake */
diff --git a/tests/libqtest.h b/tests/libqtest.h
index ed88ff99d5..96a6c01352 100644
--- a/tests/libqtest.h
+++ b/tests/libqtest.h
@@ -55,14 +55,12 @@ QTestState *qtest_init(const char *extra_args);
/**
* qtest_init_without_qmp_handshake:
- * @use_oob: true to have the server advertise OOB support
* @extra_args: other arguments to pass to QEMU. CAUTION: these
* arguments are subject to word splitting and shell evaluation.
*
* Returns: #QTestState instance.
*/
-QTestState *qtest_init_without_qmp_handshake(bool use_oob,
- const char *extra_args);
+QTestState *qtest_init_without_qmp_handshake(const char *extra_args);
/**
* qtest_quit:
diff --git a/tests/qapi-schema/alternate-base.err b/tests/qapi-schema/alternate-base.err
index 30d8a34373..ebe05bc898 100644
--- a/tests/qapi-schema/alternate-base.err
+++ b/tests/qapi-schema/alternate-base.err
@@ -1 +1,2 @@
tests/qapi-schema/alternate-base.json:4: Unknown key 'base' in alternate 'Alt'
+Valid keys are 'alternate', 'data', 'if'.
diff --git a/tests/qapi-schema/alternate-invalid-dict.err b/tests/qapi-schema/alternate-invalid-dict.err
new file mode 100644
index 0000000000..631d46628e
--- /dev/null
+++ b/tests/qapi-schema/alternate-invalid-dict.err
@@ -0,0 +1 @@
+tests/qapi-schema/alternate-invalid-dict.json:2: Key 'type' is missing from member 'two' of alternate 'Alt'
diff --git a/tests/qapi-schema/enum-dict-member.exit b/tests/qapi-schema/alternate-invalid-dict.exit
index d00491fd7e..d00491fd7e 100644
--- a/tests/qapi-schema/enum-dict-member.exit
+++ b/tests/qapi-schema/alternate-invalid-dict.exit
diff --git a/tests/qapi-schema/alternate-invalid-dict.json b/tests/qapi-schema/alternate-invalid-dict.json
new file mode 100644
index 0000000000..8e0b2ac287
--- /dev/null
+++ b/tests/qapi-schema/alternate-invalid-dict.json
@@ -0,0 +1,4 @@
+# exploded member form must have a 'type'
+{ 'alternate': 'Alt',
+ 'data': { 'one': 'str',
+ 'two': { 'if': 'foo' } } }
diff --git a/tests/qapi-schema/enum-dict-member.out b/tests/qapi-schema/alternate-invalid-dict.out
index e69de29bb2..e69de29bb2 100644
--- a/tests/qapi-schema/enum-dict-member.out
+++ b/tests/qapi-schema/alternate-invalid-dict.out
diff --git a/tests/qapi-schema/comments.out b/tests/qapi-schema/comments.out
index 8d2f1ce8a2..d1abc4b5a1 100644
--- a/tests/qapi-schema/comments.out
+++ b/tests/qapi-schema/comments.out
@@ -1,5 +1,15 @@
object q_empty
-enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
+enum QType
prefix QTYPE
+ member none
+ member qnull
+ member qnum
+ member qstring
+ member qdict
+ member qlist
+ member qbool
module comments.json
-enum Status ['good', 'bad', 'ugly']
+enum Status
+ member good
+ member bad
+ member ugly
diff --git a/tests/qapi-schema/doc-bad-section.out b/tests/qapi-schema/doc-bad-section.out
index cd28721568..db8014eed0 100644
--- a/tests/qapi-schema/doc-bad-section.out
+++ b/tests/qapi-schema/doc-bad-section.out
@@ -1,8 +1,17 @@
object q_empty
-enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
+enum QType
prefix QTYPE
+ member none
+ member qnull
+ member qnum
+ member qstring
+ member qdict
+ member qlist
+ member qbool
module doc-bad-section.json
-enum Enum ['one', 'two']
+enum Enum
+ member one
+ member two
doc symbol=Enum
body=
== Produces *invalid* texinfo
diff --git a/tests/qapi-schema/doc-good.json b/tests/qapi-schema/doc-good.json
index 984cd8ed06..f7fb48af38 100644
--- a/tests/qapi-schema/doc-good.json
+++ b/tests/qapi-schema/doc-good.json
@@ -55,7 +55,9 @@
#
# @two is undocumented
##
-{ 'enum': 'Enum', 'data': [ 'one', 'two' ], 'if': 'defined(IFCOND)' }
+{ 'enum': 'Enum', 'data':
+ [ { 'name': 'one', 'if': 'defined(IFONE)' }, 'two' ],
+ 'if': 'defined(IFCOND)' }
##
# @Base:
@@ -70,7 +72,8 @@
#
# Another paragraph (but no @var: line)
##
-{ 'struct': 'Variant1', 'data': { 'var1': 'str' } }
+{ 'struct': 'Variant1',
+ 'data': { 'var1': { 'type': 'str', 'if': 'defined(IFSTR)' } } }
##
# @Variant2:
@@ -83,13 +86,13 @@
{ 'union': 'Object',
'base': 'Base',
'discriminator': 'base1',
- 'data': { 'one': 'Variant1', 'two': 'Variant2' } }
+ 'data': { 'one': 'Variant1', 'two': { 'type': 'Variant2', 'if': 'IFTWO' } } }
##
# @SugaredUnion:
##
{ 'union': 'SugaredUnion',
- 'data': { 'one': 'Variant1', 'two': 'Variant2' } }
+ 'data': { 'one': 'Variant1', 'two': { 'type': 'Variant2', 'if': 'IFTWO' } } }
##
# == Another subsection
diff --git a/tests/qapi-schema/doc-good.out b/tests/qapi-schema/doc-good.out
index 35f3f1164c..21bf345ff0 100644
--- a/tests/qapi-schema/doc-good.out
+++ b/tests/qapi-schema/doc-good.out
@@ -1,29 +1,45 @@
object q_empty
-enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
+enum QType
prefix QTYPE
+ member none
+ member qnull
+ member qnum
+ member qstring
+ member qdict
+ member qlist
+ member qbool
module doc-good.json
-enum Enum ['one', 'two']
+enum Enum
+ member one
+ if ['defined(IFONE)']
+ member two
if ['defined(IFCOND)']
object Base
member base1: Enum optional=False
object Variant1
member var1: str optional=False
+ if ['defined(IFSTR)']
object Variant2
object Object
base Base
tag base1
case one: Variant1
case two: Variant2
+ if ['IFTWO']
object q_obj_Variant1-wrapper
member data: Variant1 optional=False
object q_obj_Variant2-wrapper
member data: Variant2 optional=False
-enum SugaredUnionKind ['one', 'two']
+enum SugaredUnionKind
+ member one
+ member two
+ if ['IFTWO']
object SugaredUnion
member type: SugaredUnionKind optional=False
tag type
case one: q_obj_Variant1-wrapper
case two: q_obj_Variant2-wrapper
+ if ['IFTWO']
object q_obj_cmd-arg
member arg1: int optional=False
member arg2: str optional=True
diff --git a/tests/qapi-schema/doc-good.texi b/tests/qapi-schema/doc-good.texi
index e42eace474..2526abc6d9 100644
--- a/tests/qapi-schema/doc-good.texi
+++ b/tests/qapi-schema/doc-good.texi
@@ -84,12 +84,12 @@ Examples:
@table @asis
@item @code{one}
The @emph{one} @{and only@}
+@*@b{If:} @code{defined(IFONE)}
@item @code{two}
Not documented
@end table
@code{two} is undocumented
-
@b{If:} @code{defined(IFCOND)}
@end deftp
@@ -119,6 +119,7 @@ Another paragraph (but no @code{var}: line)
@table @asis
@item @code{var1: string}
Not documented
+@*@b{If:} @code{defined(IFSTR)}
@end table
@end deftp
@@ -141,7 +142,7 @@ Not documented
@table @asis
@item The members of @code{Base}
@item The members of @code{Variant1} when @code{base1} is @t{"one"}
-@item The members of @code{Variant2} when @code{base1} is @t{"two"}
+@item The members of @code{Variant2} when @code{base1} is @t{"two"} (@b{If:} @code{IFTWO})
@end table
@end deftp
@@ -157,7 +158,7 @@ Not documented
@item @code{type}
One of @t{"one"}, @t{"two"}
@item @code{data: Variant1} when @code{type} is @t{"one"}
-@item @code{data: Variant2} when @code{type} is @t{"two"}
+@item @code{data: Variant2} when @code{type} is @t{"two"} (@b{If:} @code{IFTWO})
@end table
@end deftp
diff --git a/tests/qapi-schema/double-type.err b/tests/qapi-schema/double-type.err
index f9613c6d6b..799193dba1 100644
--- a/tests/qapi-schema/double-type.err
+++ b/tests/qapi-schema/double-type.err
@@ -1 +1,2 @@
tests/qapi-schema/double-type.json:2: Unknown key 'command' in struct 'bar'
+Valid keys are 'base', 'data', 'if', 'struct'.
diff --git a/tests/qapi-schema/empty.out b/tests/qapi-schema/empty.out
index 0ec234eec4..5483cb7bc6 100644
--- a/tests/qapi-schema/empty.out
+++ b/tests/qapi-schema/empty.out
@@ -1,3 +1,10 @@
object q_empty
-enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
+enum QType
prefix QTYPE
+ member none
+ member qnull
+ member qnum
+ member qstring
+ member qdict
+ member qlist
+ member qbool
diff --git a/tests/qapi-schema/enum-bad-member.err b/tests/qapi-schema/enum-bad-member.err
new file mode 100644
index 0000000000..211db9e6fc
--- /dev/null
+++ b/tests/qapi-schema/enum-bad-member.err
@@ -0,0 +1 @@
+tests/qapi-schema/enum-bad-member.json:2: Member of enum 'MyEnum' requires a string name
diff --git a/tests/qapi-schema/enum-bad-member.exit b/tests/qapi-schema/enum-bad-member.exit
new file mode 100644
index 0000000000..d00491fd7e
--- /dev/null
+++ b/tests/qapi-schema/enum-bad-member.exit
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/enum-bad-member.json b/tests/qapi-schema/enum-bad-member.json
new file mode 100644
index 0000000000..98da6828b4
--- /dev/null
+++ b/tests/qapi-schema/enum-bad-member.json
@@ -0,0 +1,2 @@
+# we reject any enum member that is not a string
+{ 'enum': 'MyEnum', 'data': [ [ ] ] }
diff --git a/tests/qapi-schema/enum-bad-member.out b/tests/qapi-schema/enum-bad-member.out
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/qapi-schema/enum-bad-member.out
diff --git a/tests/qapi-schema/enum-dict-member-unknown.err b/tests/qapi-schema/enum-dict-member-unknown.err
new file mode 100644
index 0000000000..2aae618be0
--- /dev/null
+++ b/tests/qapi-schema/enum-dict-member-unknown.err
@@ -0,0 +1,2 @@
+tests/qapi-schema/enum-dict-member-unknown.json:2: Unknown key 'bad-key' in dictionary member of enum 'MyEnum'
+Valid keys are 'if', 'name'.
diff --git a/tests/qapi-schema/enum-dict-member-unknown.exit b/tests/qapi-schema/enum-dict-member-unknown.exit
new file mode 100644
index 0000000000..d00491fd7e
--- /dev/null
+++ b/tests/qapi-schema/enum-dict-member-unknown.exit
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/enum-dict-member-unknown.json b/tests/qapi-schema/enum-dict-member-unknown.json
new file mode 100644
index 0000000000..6664c59201
--- /dev/null
+++ b/tests/qapi-schema/enum-dict-member-unknown.json
@@ -0,0 +1,2 @@
+# we reject any enum member that is not a string or a dict with 'name'
+{ 'enum': 'MyEnum', 'data': [ { 'name': 'foo', 'bad-key': 'str' } ] }
diff --git a/tests/qapi-schema/enum-dict-member-unknown.out b/tests/qapi-schema/enum-dict-member-unknown.out
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/qapi-schema/enum-dict-member-unknown.out
diff --git a/tests/qapi-schema/enum-dict-member.err b/tests/qapi-schema/enum-dict-member.err
deleted file mode 100644
index 8ca146ea59..0000000000
--- a/tests/qapi-schema/enum-dict-member.err
+++ /dev/null
@@ -1 +0,0 @@
-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
deleted file mode 100644
index 79672e0f09..0000000000
--- a/tests/qapi-schema/enum-dict-member.json
+++ /dev/null
@@ -1,2 +0,0 @@
-# we reject any enum member that is not a string
-{ 'enum': 'MyEnum', 'data': [ { 'value': 'str' } ] }
diff --git a/tests/qapi-schema/enum-if-invalid.err b/tests/qapi-schema/enum-if-invalid.err
new file mode 100644
index 0000000000..54c3cf887b
--- /dev/null
+++ b/tests/qapi-schema/enum-if-invalid.err
@@ -0,0 +1 @@
+tests/qapi-schema/enum-if-invalid.json:2: 'if' condition must be a string or a list of strings
diff --git a/tests/qapi-schema/enum-if-invalid.exit b/tests/qapi-schema/enum-if-invalid.exit
new file mode 100644
index 0000000000..d00491fd7e
--- /dev/null
+++ b/tests/qapi-schema/enum-if-invalid.exit
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/enum-if-invalid.json b/tests/qapi-schema/enum-if-invalid.json
new file mode 100644
index 0000000000..60bd0ef1d7
--- /dev/null
+++ b/tests/qapi-schema/enum-if-invalid.json
@@ -0,0 +1,3 @@
+# check invalid 'if' type
+{ 'enum': 'TestIfEnum', 'data':
+ [ 'foo', { 'name' : 'bar', 'if': { 'val': 'foo' } } ] }
diff --git a/tests/qapi-schema/enum-if-invalid.out b/tests/qapi-schema/enum-if-invalid.out
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/qapi-schema/enum-if-invalid.out
diff --git a/tests/qapi-schema/event-case.out b/tests/qapi-schema/event-case.out
index 88c0964917..f69d4ffe4e 100644
--- a/tests/qapi-schema/event-case.out
+++ b/tests/qapi-schema/event-case.out
@@ -1,6 +1,13 @@
object q_empty
-enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
+enum QType
prefix QTYPE
+ member none
+ member qnull
+ member qnum
+ member qstring
+ member qdict
+ member qlist
+ member qbool
module event-case.json
event oops None
boxed=False
diff --git a/tests/qapi-schema/event-member-invalid-dict.err b/tests/qapi-schema/event-member-invalid-dict.err
new file mode 100644
index 0000000000..1a57fa29b0
--- /dev/null
+++ b/tests/qapi-schema/event-member-invalid-dict.err
@@ -0,0 +1 @@
+tests/qapi-schema/event-member-invalid-dict.json:1: Key 'type' is missing from member 'a' of 'data' for event 'EVENT_A'
diff --git a/tests/qapi-schema/event-member-invalid-dict.exit b/tests/qapi-schema/event-member-invalid-dict.exit
new file mode 100644
index 0000000000..d00491fd7e
--- /dev/null
+++ b/tests/qapi-schema/event-member-invalid-dict.exit
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/event-member-invalid-dict.json b/tests/qapi-schema/event-member-invalid-dict.json
new file mode 100644
index 0000000000..ee6f3ecb6f
--- /dev/null
+++ b/tests/qapi-schema/event-member-invalid-dict.json
@@ -0,0 +1,2 @@
+{ 'event': 'EVENT_A',
+ 'data': { 'a' : { 'string' : 'str', 'integer': 'int' }, 'b' : 'str' } }
diff --git a/tests/qapi-schema/event-member-invalid-dict.out b/tests/qapi-schema/event-member-invalid-dict.out
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/qapi-schema/event-member-invalid-dict.out
diff --git a/tests/qapi-schema/event-nest-struct.json b/tests/qapi-schema/event-nest-struct.json
index ee6f3ecb6f..355ddaeff1 100644
--- a/tests/qapi-schema/event-nest-struct.json
+++ b/tests/qapi-schema/event-nest-struct.json
@@ -1,2 +1,2 @@
{ 'event': 'EVENT_A',
- 'data': { 'a' : { 'string' : 'str', 'integer': 'int' }, 'b' : 'str' } }
+ 'data': { 'a' : { 'type' : { 'integer': 'int' } }, 'b' : 'str' } }
diff --git a/tests/qapi-schema/flat-union-inline-invalid-dict.err b/tests/qapi-schema/flat-union-inline-invalid-dict.err
new file mode 100644
index 0000000000..9c4c45b7f0
--- /dev/null
+++ b/tests/qapi-schema/flat-union-inline-invalid-dict.err
@@ -0,0 +1 @@
+tests/qapi-schema/flat-union-inline-invalid-dict.json:7: Key 'type' is missing from member 'value1' of union 'TestUnion'
diff --git a/tests/qapi-schema/flat-union-inline-invalid-dict.exit b/tests/qapi-schema/flat-union-inline-invalid-dict.exit
new file mode 100644
index 0000000000..d00491fd7e
--- /dev/null
+++ b/tests/qapi-schema/flat-union-inline-invalid-dict.exit
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/flat-union-inline-invalid-dict.json b/tests/qapi-schema/flat-union-inline-invalid-dict.json
new file mode 100644
index 0000000000..62c7cda617
--- /dev/null
+++ b/tests/qapi-schema/flat-union-inline-invalid-dict.json
@@ -0,0 +1,11 @@
+# we require branches to be a struct name
+# TODO: should we allow anonymous inline branch types?
+{ 'enum': 'TestEnum',
+ 'data': [ 'value1', 'value2' ] }
+{ 'struct': 'Base',
+ 'data': { 'enum1': 'TestEnum', 'kind': 'str' } }
+{ 'union': 'TestUnion',
+ 'base': 'Base',
+ 'discriminator': 'enum1',
+ 'data': { 'value1': { 'string': 'str' },
+ 'value2': { 'integer': 'int' } } }
diff --git a/tests/qapi-schema/flat-union-inline-invalid-dict.out b/tests/qapi-schema/flat-union-inline-invalid-dict.out
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/qapi-schema/flat-union-inline-invalid-dict.out
diff --git a/tests/qapi-schema/flat-union-inline.json b/tests/qapi-schema/flat-union-inline.json
index 62c7cda617..a9b3ce3f0d 100644
--- a/tests/qapi-schema/flat-union-inline.json
+++ b/tests/qapi-schema/flat-union-inline.json
@@ -7,5 +7,5 @@
{ 'union': 'TestUnion',
'base': 'Base',
'discriminator': 'enum1',
- 'data': { 'value1': { 'string': 'str' },
+ 'data': { 'value1': { 'type': {} },
'value2': { 'integer': 'int' } } }
diff --git a/tests/qapi-schema/flat-union-invalid-if-discriminator.err b/tests/qapi-schema/flat-union-invalid-if-discriminator.err
new file mode 100644
index 0000000000..0c94c9860d
--- /dev/null
+++ b/tests/qapi-schema/flat-union-invalid-if-discriminator.err
@@ -0,0 +1 @@
+tests/qapi-schema/flat-union-invalid-if-discriminator.json:13: The discriminator TestBase.enum1 for union TestUnion must not be conditional
diff --git a/tests/qapi-schema/flat-union-invalid-if-discriminator.exit b/tests/qapi-schema/flat-union-invalid-if-discriminator.exit
new file mode 100644
index 0000000000..d00491fd7e
--- /dev/null
+++ b/tests/qapi-schema/flat-union-invalid-if-discriminator.exit
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/flat-union-invalid-if-discriminator.json b/tests/qapi-schema/flat-union-invalid-if-discriminator.json
new file mode 100644
index 0000000000..618ec36396
--- /dev/null
+++ b/tests/qapi-schema/flat-union-invalid-if-discriminator.json
@@ -0,0 +1,17 @@
+{ 'enum': 'TestEnum',
+ 'data': [ 'value1', 'value2' ] }
+
+{ 'struct': 'TestBase',
+ 'data': { 'enum1': { 'type': 'TestEnum', 'if': 'FOO' } } }
+
+{ 'struct': 'TestTypeA',
+ 'data': { 'string': 'str' } }
+
+{ 'struct': 'TestTypeB',
+ 'data': { 'integer': 'int' } }
+
+{ 'union': 'TestUnion',
+ 'base': 'TestBase',
+ 'discriminator': 'enum1',
+ 'data': { 'value1': 'TestTypeA',
+ 'value2': 'TestTypeB' } }
diff --git a/tests/qapi-schema/flat-union-invalid-if-discriminator.out b/tests/qapi-schema/flat-union-invalid-if-discriminator.out
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/qapi-schema/flat-union-invalid-if-discriminator.out
diff --git a/tests/qapi-schema/ident-with-escape.out b/tests/qapi-schema/ident-with-escape.out
index 24c976f473..7f891f7e90 100644
--- a/tests/qapi-schema/ident-with-escape.out
+++ b/tests/qapi-schema/ident-with-escape.out
@@ -1,6 +1,13 @@
object q_empty
-enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
+enum QType
prefix QTYPE
+ member none
+ member qnull
+ member qnum
+ member qstring
+ member qdict
+ member qlist
+ member qbool
module ident-with-escape.json
object q_obj_fooA-arg
member bar1: str optional=False
diff --git a/tests/qapi-schema/include-relpath.out b/tests/qapi-schema/include-relpath.out
index ebbabd7a18..783ccfc855 100644
--- a/tests/qapi-schema/include-relpath.out
+++ b/tests/qapi-schema/include-relpath.out
@@ -1,9 +1,19 @@
object q_empty
-enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
+enum QType
prefix QTYPE
+ member none
+ member qnull
+ member qnum
+ member qstring
+ member qdict
+ member qlist
+ member qbool
module include-relpath.json
include include/relpath.json
module include/relpath.json
include include-relpath-sub.json
module include-relpath-sub.json
-enum Status ['good', 'bad', 'ugly']
+enum Status
+ member good
+ member bad
+ member ugly
diff --git a/tests/qapi-schema/include-repetition.out b/tests/qapi-schema/include-repetition.out
index 7235e055bc..d45977ee56 100644
--- a/tests/qapi-schema/include-repetition.out
+++ b/tests/qapi-schema/include-repetition.out
@@ -1,10 +1,20 @@
object q_empty
-enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
+enum QType
prefix QTYPE
+ member none
+ member qnull
+ member qnum
+ member qstring
+ member qdict
+ member qlist
+ member qbool
module include-repetition.json
include comments.json
module comments.json
-enum Status ['good', 'bad', 'ugly']
+enum Status
+ member good
+ member bad
+ member ugly
module include-repetition.json
include include-repetition-sub.json
module include-repetition-sub.json
diff --git a/tests/qapi-schema/include-simple.out b/tests/qapi-schema/include-simple.out
index 006f723eeb..1afe20802a 100644
--- a/tests/qapi-schema/include-simple.out
+++ b/tests/qapi-schema/include-simple.out
@@ -1,7 +1,17 @@
object q_empty
-enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
+enum QType
prefix QTYPE
+ member none
+ member qnull
+ member qnum
+ member qstring
+ member qdict
+ member qlist
+ member qbool
module include-simple.json
include include-simple-sub.json
module include-simple-sub.json
-enum Status ['good', 'bad', 'ugly']
+enum Status
+ member good
+ member bad
+ member ugly
diff --git a/tests/qapi-schema/indented-expr.out b/tests/qapi-schema/indented-expr.out
index bd8a48630e..c0cf3243f3 100644
--- a/tests/qapi-schema/indented-expr.out
+++ b/tests/qapi-schema/indented-expr.out
@@ -1,6 +1,13 @@
object q_empty
-enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
+enum QType
prefix QTYPE
+ member none
+ member qnull
+ member qnum
+ member qstring
+ member qdict
+ member qlist
+ member qbool
module indented-expr.json
command eins None -> None
gen=True success_response=True boxed=False oob=False preconfig=False
diff --git a/tests/qapi-schema/nested-struct-data-invalid-dict.err b/tests/qapi-schema/nested-struct-data-invalid-dict.err
new file mode 100644
index 0000000000..5bd364e8d9
--- /dev/null
+++ b/tests/qapi-schema/nested-struct-data-invalid-dict.err
@@ -0,0 +1 @@
+tests/qapi-schema/nested-struct-data-invalid-dict.json:2: Key 'type' is missing from member 'a' of 'data' for command 'foo'
diff --git a/tests/qapi-schema/nested-struct-data-invalid-dict.exit b/tests/qapi-schema/nested-struct-data-invalid-dict.exit
new file mode 100644
index 0000000000..d00491fd7e
--- /dev/null
+++ b/tests/qapi-schema/nested-struct-data-invalid-dict.exit
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/nested-struct-data-invalid-dict.json b/tests/qapi-schema/nested-struct-data-invalid-dict.json
new file mode 100644
index 0000000000..efbe773ded
--- /dev/null
+++ b/tests/qapi-schema/nested-struct-data-invalid-dict.json
@@ -0,0 +1,3 @@
+# inline subtypes collide with our desired future use of defaults
+{ 'command': 'foo',
+ 'data': { 'a' : { 'string' : 'str', 'integer': 'int' }, 'b' : 'str' } }
diff --git a/tests/qapi-schema/nested-struct-data-invalid-dict.out b/tests/qapi-schema/nested-struct-data-invalid-dict.out
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/qapi-schema/nested-struct-data-invalid-dict.out
diff --git a/tests/qapi-schema/nested-struct-data.json b/tests/qapi-schema/nested-struct-data.json
index efbe773ded..5b8a40cca3 100644
--- a/tests/qapi-schema/nested-struct-data.json
+++ b/tests/qapi-schema/nested-struct-data.json
@@ -1,3 +1,3 @@
# inline subtypes collide with our desired future use of defaults
{ 'command': 'foo',
- 'data': { 'a' : { 'string' : 'str', 'integer': 'int' }, 'b' : 'str' } }
+ 'data': { 'a' : { 'type': {} }, 'b' : 'str' } }
diff --git a/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qapi-schema-test.json
index fb03163430..cb0857df52 100644
--- a/tests/qapi-schema/qapi-schema-test.json
+++ b/tests/qapi-schema/qapi-schema-test.json
@@ -11,7 +11,7 @@
'guest-sync' ] } }
{ 'struct': 'TestStruct',
- 'data': { 'integer': 'int', 'boolean': 'bool', 'string': 'str' } }
+ 'data': { 'integer': {'type': 'int'}, 'boolean': 'bool', 'string': 'str' } }
# for testing enums
{ 'struct': 'NestedEnumsOne',
@@ -77,7 +77,7 @@
{ 'union': 'UserDefFlatUnion',
'base': 'UserDefUnionBase', # intentional forward reference
'discriminator': 'enum1',
- 'data': { 'value1' : 'UserDefA',
+ 'data': { 'value1' : {'type': 'UserDefA'},
'value2' : 'UserDefB',
'value3' : 'UserDefB'
# 'value4' defaults to empty
@@ -98,7 +98,7 @@
{ 'struct': 'WrapAlternate',
'data': { 'alt': 'UserDefAlternate' } }
{ 'alternate': 'UserDefAlternate',
- 'data': { 'udfu': 'UserDefFlatUnion', 'e': 'EnumOne', 'i': 'int',
+ 'data': { 'udfu': {'type': 'UserDefFlatUnion'}, 'e': 'EnumOne', 'i': 'int',
'n': 'null' } }
{ 'struct': 'UserDefC',
@@ -134,7 +134,7 @@
{ 'command': 'user_def_cmd', 'data': {} }
{ 'command': 'user_def_cmd1', 'data': {'ud1a': 'UserDefOne'} }
{ 'command': 'user_def_cmd2',
- 'data': {'ud1a': 'UserDefOne', '*ud1b': 'UserDefOne'},
+ 'data': {'ud1a': {'type': 'UserDefOne'}, '*ud1b': 'UserDefOne'},
'returns': 'UserDefTwo' }
{ 'command': 'cmd-success-response', 'data': {}, 'success-response': false }
@@ -166,7 +166,7 @@
# testing event
{ 'struct': 'EventStructOne',
- 'data': { 'struct1': 'UserDefOne', 'string': 'str', '*enum2': 'EnumOne' } }
+ 'data': { 'struct1': {'type': 'UserDefOne'}, 'string': 'str', '*enum2': 'EnumOne' } }
{ 'event': 'EVENT_A' }
{ 'event': 'EVENT_B',
@@ -201,23 +201,40 @@
# test 'if' condition handling
-{ 'struct': 'TestIfStruct', 'data': { 'foo': 'int' },
+{ 'struct': 'TestIfStruct', 'data':
+ { 'foo': 'int',
+ 'bar': { 'type': 'int', 'if': 'defined(TEST_IF_STRUCT_BAR)'} },
'if': 'defined(TEST_IF_STRUCT)' }
-{ 'enum': 'TestIfEnum', 'data': [ 'foo', 'bar' ],
+{ 'enum': 'TestIfEnum', 'data':
+ [ 'foo', { 'name' : 'bar', 'if': 'defined(TEST_IF_ENUM_BAR)' } ],
'if': 'defined(TEST_IF_ENUM)' }
-{ 'union': 'TestIfUnion', 'data': { 'foo': 'TestStruct' },
+{ 'union': 'TestIfUnion', 'data':
+ { 'foo': 'TestStruct',
+ 'union_bar': { 'type': 'str', 'if': 'defined(TEST_IF_UNION_BAR)'} },
'if': 'defined(TEST_IF_UNION) && defined(TEST_IF_STRUCT)' }
-{ 'alternate': 'TestIfAlternate', 'data': { 'foo': 'int', 'bar': 'TestStruct' },
+{ 'command': 'TestIfUnionCmd', 'data': { 'union_cmd_arg': 'TestIfUnion' },
+ 'if': 'defined(TEST_IF_UNION)' }
+
+{ 'alternate': 'TestIfAlternate', 'data':
+ { 'foo': 'int',
+ 'bar': { 'type': 'TestStruct', 'if': 'defined(TEST_IF_ALT_BAR)'} },
'if': 'defined(TEST_IF_ALT) && defined(TEST_IF_STRUCT)' }
-{ 'command': 'TestIfCmd', 'data': { 'foo': 'TestIfStruct' },
+{ 'command': 'TestIfAlternateCmd', 'data': { 'alt_cmd_arg': 'TestIfAlternate' },
+ 'if': 'defined(TEST_IF_ALT)' }
+
+{ 'command': 'TestIfCmd', 'data':
+ { 'foo': 'TestIfStruct',
+ 'bar': { 'type': 'TestIfEnum', 'if': 'defined(TEST_IF_CMD_BAR)' } },
'returns': 'UserDefThree',
'if': ['defined(TEST_IF_CMD)', 'defined(TEST_IF_STRUCT)'] }
{ 'command': 'TestCmdReturnDefThree', 'returns': 'UserDefThree' }
-{ 'event': 'TestIfEvent', 'data': { 'foo': 'TestIfStruct' },
+{ 'event': 'TestIfEvent', 'data':
+ { 'foo': 'TestIfStruct',
+ 'bar': { 'type': 'TestIfEnum', 'if': 'defined(TEST_IF_EVT_BAR)' } },
'if': 'defined(TEST_IF_EVT) && defined(TEST_IF_STRUCT)' }
diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qapi-schema-test.out
index 218ac7d556..9464101d26 100644
--- a/tests/qapi-schema/qapi-schema-test.out
+++ b/tests/qapi-schema/qapi-schema-test.out
@@ -1,6 +1,13 @@
object q_empty
-enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
+enum QType
prefix QTYPE
+ member none
+ member qnull
+ member qnum
+ member qstring
+ member qdict
+ member qlist
+ member qbool
module qapi-schema-test.json
object TestStruct
member integer: int optional=False
@@ -11,19 +18,25 @@ object NestedEnumsOne
member enum2: EnumOne optional=True
member enum3: EnumOne optional=False
member enum4: EnumOne optional=True
-enum MyEnum []
+enum MyEnum
object Empty1
object Empty2
base Empty1
command user_def_cmd0 Empty2 -> Empty2
gen=True success_response=True boxed=False oob=False preconfig=False
-enum QEnumTwo ['value1', 'value2']
+enum QEnumTwo
prefix QENUM_TWO
+ member value1
+ member value2
object UserDefOne
base UserDefZero
member string: str optional=False
member enum1: EnumOne optional=True
-enum EnumOne ['value1', 'value2', 'value3', 'value4']
+enum EnumOne
+ member value1
+ member value2
+ member value3
+ member value4
object UserDefZero
member integer: int optional=False
object UserDefTwoDictDict
@@ -127,7 +140,21 @@ object q_obj_sizeList-wrapper
member data: sizeList optional=False
object q_obj_anyList-wrapper
member data: anyList optional=False
-enum UserDefNativeListUnionKind ['integer', 's8', 's16', 's32', 's64', 'u8', 'u16', 'u32', 'u64', 'number', 'boolean', 'string', 'sizes', 'any']
+enum UserDefNativeListUnionKind
+ member integer
+ member s8
+ member s16
+ member s32
+ member s64
+ member u8
+ member u16
+ member u32
+ member u64
+ member number
+ member boolean
+ member string
+ member sizes
+ member any
object UserDefNativeListUnion
member type: UserDefNativeListUnionKind optional=False
tag type
@@ -204,7 +231,8 @@ event EVENT_E UserDefZero
boxed=True
event EVENT_F UserDefAlternate
boxed=True
-enum __org.qemu_x-Enum ['__org.qemu_x-value']
+enum __org.qemu_x-Enum
+ member __org.qemu_x-value
object __org.qemu_x-Base
member __org.qemu_x-member1: __org.qemu_x-Enum optional=False
object __org.qemu_x-Struct
@@ -213,7 +241,8 @@ object __org.qemu_x-Struct
member wchar-t: int optional=True
object q_obj_str-wrapper
member data: str optional=False
-enum __org.qemu_x-Union1Kind ['__org.qemu_x-branch']
+enum __org.qemu_x-Union1Kind
+ member __org.qemu_x-branch
object __org.qemu_x-Union1
member type: __org.qemu_x-Union1Kind optional=False
tag type
@@ -239,25 +268,50 @@ command __org.qemu_x-command q_obj___org.qemu_x-command-arg -> __org.qemu_x-Unio
gen=True success_response=True boxed=False oob=False preconfig=False
object TestIfStruct
member foo: int optional=False
+ member bar: int optional=False
+ if ['defined(TEST_IF_STRUCT_BAR)']
if ['defined(TEST_IF_STRUCT)']
-enum TestIfEnum ['foo', 'bar']
+enum TestIfEnum
+ member foo
+ member bar
+ if ['defined(TEST_IF_ENUM_BAR)']
if ['defined(TEST_IF_ENUM)']
object q_obj_TestStruct-wrapper
member data: TestStruct optional=False
-enum TestIfUnionKind ['foo']
+enum TestIfUnionKind
+ member foo
+ member union_bar
+ if ['defined(TEST_IF_UNION_BAR)']
if ['defined(TEST_IF_UNION) && defined(TEST_IF_STRUCT)']
object TestIfUnion
member type: TestIfUnionKind optional=False
tag type
case foo: q_obj_TestStruct-wrapper
+ case union_bar: q_obj_str-wrapper
+ if ['defined(TEST_IF_UNION_BAR)']
if ['defined(TEST_IF_UNION) && defined(TEST_IF_STRUCT)']
+object q_obj_TestIfUnionCmd-arg
+ member union_cmd_arg: TestIfUnion optional=False
+ if ['defined(TEST_IF_UNION)']
+command TestIfUnionCmd q_obj_TestIfUnionCmd-arg -> None
+ gen=True success_response=True boxed=False oob=False preconfig=False
+ if ['defined(TEST_IF_UNION)']
alternate TestIfAlternate
tag type
case foo: int
case bar: TestStruct
+ if ['defined(TEST_IF_ALT_BAR)']
if ['defined(TEST_IF_ALT) && defined(TEST_IF_STRUCT)']
+object q_obj_TestIfAlternateCmd-arg
+ member alt_cmd_arg: TestIfAlternate optional=False
+ if ['defined(TEST_IF_ALT)']
+command TestIfAlternateCmd q_obj_TestIfAlternateCmd-arg -> None
+ gen=True success_response=True boxed=False oob=False preconfig=False
+ if ['defined(TEST_IF_ALT)']
object q_obj_TestIfCmd-arg
member foo: TestIfStruct optional=False
+ member bar: TestIfEnum optional=False
+ if ['defined(TEST_IF_CMD_BAR)']
if ['defined(TEST_IF_CMD)', 'defined(TEST_IF_STRUCT)']
command TestIfCmd q_obj_TestIfCmd-arg -> UserDefThree
gen=True success_response=True boxed=False oob=False preconfig=False
@@ -266,6 +320,8 @@ command TestCmdReturnDefThree None -> UserDefThree
gen=True success_response=True boxed=False oob=False preconfig=False
object q_obj_TestIfEvent-arg
member foo: TestIfStruct optional=False
+ member bar: TestIfEnum optional=False
+ if ['defined(TEST_IF_EVT_BAR)']
if ['defined(TEST_IF_EVT) && defined(TEST_IF_STRUCT)']
event TestIfEvent q_obj_TestIfEvent-arg
boxed=False
diff --git a/tests/qapi-schema/struct-member-invalid-dict.err b/tests/qapi-schema/struct-member-invalid-dict.err
new file mode 100644
index 0000000000..6a765bc668
--- /dev/null
+++ b/tests/qapi-schema/struct-member-invalid-dict.err
@@ -0,0 +1 @@
+tests/qapi-schema/struct-member-invalid-dict.json:2: Key 'type' is missing from member '*a' of 'data' for struct 'foo'
diff --git a/tests/qapi-schema/struct-member-invalid-dict.exit b/tests/qapi-schema/struct-member-invalid-dict.exit
new file mode 100644
index 0000000000..d00491fd7e
--- /dev/null
+++ b/tests/qapi-schema/struct-member-invalid-dict.exit
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/struct-member-invalid-dict.json b/tests/qapi-schema/struct-member-invalid-dict.json
new file mode 100644
index 0000000000..9fe0d455a9
--- /dev/null
+++ b/tests/qapi-schema/struct-member-invalid-dict.json
@@ -0,0 +1,3 @@
+# Long form of member must have a value member 'type'
+{ 'struct': 'foo',
+ 'data': { '*a': { 'case': 'foo' } } }
diff --git a/tests/qapi-schema/struct-member-invalid-dict.out b/tests/qapi-schema/struct-member-invalid-dict.out
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/qapi-schema/struct-member-invalid-dict.out
diff --git a/tests/qapi-schema/test-qapi.py b/tests/qapi-schema/test-qapi.py
index cea21c773a..d592854601 100644
--- a/tests/qapi-schema/test-qapi.py
+++ b/tests/qapi-schema/test-qapi.py
@@ -23,10 +23,13 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor):
def visit_include(self, name, info):
print('include %s' % name)
- def visit_enum_type(self, name, info, ifcond, values, prefix):
- print('enum %s %s' % (name, values))
+ def visit_enum_type(self, name, info, ifcond, members, prefix):
+ print('enum %s' % name)
if prefix:
print(' prefix %s' % prefix)
+ for m in members:
+ print(' member %s' % m.name)
+ self._print_if(m.ifcond, indent=8)
self._print_if(ifcond)
def visit_object_type(self, name, info, ifcond, base, members, variants):
@@ -36,6 +39,7 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor):
for m in members:
print(' member %s: %s optional=%s'
% (m.name, m.type.name, m.optional))
+ self._print_if(m.ifcond, 8)
self._print_variants(variants)
self._print_if(ifcond)
@@ -64,6 +68,7 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor):
print(' tag %s' % variants.tag_member.name)
for v in variants.variants:
print(' case %s: %s' % (v.name, v.type.name))
+ QAPISchemaTestVisitor._print_if(v.ifcond, indent=8)
@staticmethod
def _print_if(ifcond, indent=4):
diff --git a/tests/qapi-schema/union-branch-invalid-dict.err b/tests/qapi-schema/union-branch-invalid-dict.err
new file mode 100644
index 0000000000..89f9b36791
--- /dev/null
+++ b/tests/qapi-schema/union-branch-invalid-dict.err
@@ -0,0 +1 @@
+tests/qapi-schema/union-branch-invalid-dict.json:2: Key 'type' is missing from member 'integer' of union 'UnionInvalidBranch'
diff --git a/tests/qapi-schema/union-branch-invalid-dict.exit b/tests/qapi-schema/union-branch-invalid-dict.exit
new file mode 100644
index 0000000000..d00491fd7e
--- /dev/null
+++ b/tests/qapi-schema/union-branch-invalid-dict.exit
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/union-branch-invalid-dict.json b/tests/qapi-schema/union-branch-invalid-dict.json
new file mode 100644
index 0000000000..9778598dbd
--- /dev/null
+++ b/tests/qapi-schema/union-branch-invalid-dict.json
@@ -0,0 +1,4 @@
+# Long form of member must have a value member 'type'
+{ 'union': 'UnionInvalidBranch',
+ 'data': { 'integer': { 'if': 'foo'},
+ 's8': 'int8' } }
diff --git a/tests/qapi-schema/union-branch-invalid-dict.out b/tests/qapi-schema/union-branch-invalid-dict.out
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/qapi-schema/union-branch-invalid-dict.out
diff --git a/tests/qapi-schema/unknown-expr-key.err b/tests/qapi-schema/unknown-expr-key.err
index 12f5ed5b43..6ff8bb99c5 100644
--- a/tests/qapi-schema/unknown-expr-key.err
+++ b/tests/qapi-schema/unknown-expr-key.err
@@ -1 +1,2 @@
-tests/qapi-schema/unknown-expr-key.json:2: Unknown key 'bogus' in struct 'bar'
+tests/qapi-schema/unknown-expr-key.json:2: Unknown keys 'bogus', 'phony' in struct 'bar'
+Valid keys are 'base', 'data', 'if', 'struct'.
diff --git a/tests/qapi-schema/unknown-expr-key.json b/tests/qapi-schema/unknown-expr-key.json
index 3b2be00cc4..13292d75ed 100644
--- a/tests/qapi-schema/unknown-expr-key.json
+++ b/tests/qapi-schema/unknown-expr-key.json
@@ -1,2 +1,2 @@
# we reject an expression with unknown top-level keys
-{ 'struct': 'bar', 'data': { 'string': 'str'}, 'bogus': { } }
+{ 'struct': 'bar', 'data': { 'string': 'str'}, 'bogus': { }, 'phony': { } }
diff --git a/tests/qemu-iotests/229 b/tests/qemu-iotests/229
index 86602437ff..893d098ad2 100755
--- a/tests/qemu-iotests/229
+++ b/tests/qemu-iotests/229
@@ -69,7 +69,6 @@ echo
_send_qemu_cmd $QEMU_HANDLE \
"{'execute': 'drive-mirror',
'arguments': {'device': 'testdisk',
- 'mode': 'absolute-paths',
'format': '$IMGFMT',
'target': '$DEST_IMG',
'sync': 'full',
diff --git a/tests/qmp-test.c b/tests/qmp-test.c
index 7517be4654..48a4fa791a 100644
--- a/tests/qmp-test.c
+++ b/tests/qmp-test.c
@@ -108,7 +108,7 @@ static void test_qmp_protocol(void)
QList *capabilities;
QTestState *qts;
- qts = qtest_init_without_qmp_handshake(false, common_args);
+ qts = qtest_init_without_qmp_handshake(common_args);
/* Test greeting */
resp = qtest_qmp_receive(qts);
@@ -116,7 +116,7 @@ static void test_qmp_protocol(void)
g_assert(q);
test_version(qdict_get(q, "version"));
capabilities = qdict_get_qlist(q, "capabilities");
- g_assert(capabilities && qlist_empty(capabilities));
+ g_assert(capabilities);
qobject_unref(resp);
/* Test valid command before handshake */
@@ -219,7 +219,7 @@ static void test_qmp_oob(void)
QList *capabilities;
QString *qstr;
- qts = qtest_init_without_qmp_handshake(true, common_args);
+ qts = qtest_init_without_qmp_handshake(common_args);
/* Check the greeting message. */
resp = qtest_qmp_receive(qts);
diff --git a/tests/tcg/i386/test-i386.c b/tests/tcg/i386/test-i386.c
index a29b41e764..18d5609665 100644
--- a/tests/tcg/i386/test-i386.c
+++ b/tests/tcg/i386/test-i386.c
@@ -1137,7 +1137,7 @@ void test_xchg(void)
TEST_XCHG(xchgb, "b", "+q");
#if defined(__x86_64__)
- TEST_XCHG(xchgq, "", "=m");
+ TEST_XCHG(xchgq, "", "+m");
#endif
TEST_XCHG(xchgl, "k", "+m");
TEST_XCHG(xchgw, "w", "+m");
diff --git a/tests/test-crypto-block.c b/tests/test-crypto-block.c
index fae4ffc453..d309d044ef 100644
--- a/tests/test-crypto-block.c
+++ b/tests/test-crypto-block.c
@@ -305,6 +305,7 @@ static void test_block(gconstpointer opaque)
test_block_read_func,
&header,
0,
+ 1,
NULL);
g_assert(blk == NULL);
@@ -313,6 +314,7 @@ static void test_block(gconstpointer opaque)
test_block_read_func,
&header,
QCRYPTO_BLOCK_OPEN_NO_IO,
+ 1,
&error_abort);
g_assert(qcrypto_block_get_cipher(blk) == NULL);
@@ -327,6 +329,7 @@ static void test_block(gconstpointer opaque)
test_block_read_func,
&header,
0,
+ 1,
&error_abort);
g_assert(blk);
diff --git a/tests/test-cutils.c b/tests/test-cutils.c
index d85c3e0f6d..1aa8351520 100644
--- a/tests/test-cutils.c
+++ b/tests/test-cutils.c
@@ -1950,7 +1950,7 @@ static void test_qemu_strtou64_full_max(void)
static void test_qemu_strtosz_simple(void)
{
const char *str;
- char *endptr = NULL;
+ const char *endptr;
int err;
uint64_t res = 0xbaadf00d;
@@ -2017,7 +2017,7 @@ static void test_qemu_strtosz_units(void)
const char *p = "1P";
const char *e = "1E";
int err;
- char *endptr = NULL;
+ const char *endptr;
uint64_t res = 0xbaadf00d;
/* default is M */
@@ -2066,7 +2066,7 @@ static void test_qemu_strtosz_float(void)
{
const char *str = "12.345M";
int err;
- char *endptr = NULL;
+ const char *endptr;
uint64_t res = 0xbaadf00d;
err = qemu_strtosz(str, &endptr, &res);
@@ -2078,7 +2078,7 @@ static void test_qemu_strtosz_float(void)
static void test_qemu_strtosz_invalid(void)
{
const char *str;
- char *endptr = NULL;
+ const char *endptr;
int err;
uint64_t res = 0xbaadf00d;
@@ -2096,12 +2096,22 @@ static void test_qemu_strtosz_invalid(void)
err = qemu_strtosz(str, &endptr, &res);
g_assert_cmpint(err, ==, -EINVAL);
g_assert(endptr == str);
+
+ str = "inf";
+ err = qemu_strtosz(str, &endptr, &res);
+ g_assert_cmpint(err, ==, -EINVAL);
+ g_assert(endptr == str);
+
+ str = "NaN";
+ err = qemu_strtosz(str, &endptr, &res);
+ g_assert_cmpint(err, ==, -EINVAL);
+ g_assert(endptr == str);
}
static void test_qemu_strtosz_trailing(void)
{
const char *str;
- char *endptr = NULL;
+ const char *endptr;
int err;
uint64_t res = 0xbaadf00d;
@@ -2126,7 +2136,7 @@ static void test_qemu_strtosz_trailing(void)
static void test_qemu_strtosz_erange(void)
{
const char *str;
- char *endptr = NULL;
+ const char *endptr;
int err;
uint64_t res = 0xbaadf00d;
@@ -2160,7 +2170,7 @@ static void test_qemu_strtosz_metric(void)
{
const char *str = "12345k";
int err;
- char *endptr = NULL;
+ const char *endptr;
uint64_t res = 0xbaadf00d;
err = qemu_strtosz_metric(str, &endptr, &res);
diff --git a/tests/test-qdev-global-props.c b/tests/test-qdev-global-props.c
index d81b0862d5..b1eb505442 100644
--- a/tests/test-qdev-global-props.c
+++ b/tests/test-qdev-global-props.c
@@ -89,6 +89,16 @@ static void test_static_prop(void)
g_test_trap_assert_stdout("");
}
+static void register_global_properties(GlobalProperty *props)
+{
+ int i;
+
+ for (i = 0; props[i].driver != NULL; i++) {
+ qdev_prop_register_global(props + i);
+ }
+}
+
+
/* Test setting of static property using global properties */
static void test_static_globalprop_subprocess(void)
{
@@ -98,7 +108,7 @@ static void test_static_globalprop_subprocess(void)
{}
};
- qdev_prop_register_global_list(props);
+ register_global_properties(props);
mt = STATIC_TYPE(object_new(TYPE_STATIC_PROPS));
qdev_init_nofail(DEVICE(mt));
@@ -214,17 +224,17 @@ static void test_dynamic_globalprop_subprocess(void)
{ TYPE_NONDEVICE, "prop6", "106", true },
{}
};
- int all_used;
+ int global_error;
- qdev_prop_register_global_list(props);
+ register_global_properties(props);
mt = DYNAMIC_TYPE(object_new(TYPE_DYNAMIC_PROPS));
qdev_init_nofail(DEVICE(mt));
g_assert_cmpuint(mt->prop1, ==, 101);
g_assert_cmpuint(mt->prop2, ==, 102);
- all_used = qdev_prop_check_globals();
- g_assert_cmpuint(all_used, ==, 1);
+ global_error = qdev_prop_check_globals();
+ g_assert_cmpuint(global_error, ==, 1);
g_assert(props[0].used);
g_assert(props[1].used);
g_assert(!props[2].used);
@@ -259,17 +269,17 @@ static void test_dynamic_globalprop_nouser_subprocess(void)
{ TYPE_NONDEVICE, "prop6", "106" },
{}
};
- int all_used;
+ int global_error;
- qdev_prop_register_global_list(props);
+ register_global_properties(props);
mt = DYNAMIC_TYPE(object_new(TYPE_DYNAMIC_PROPS));
qdev_init_nofail(DEVICE(mt));
g_assert_cmpuint(mt->prop1, ==, 101);
g_assert_cmpuint(mt->prop2, ==, 102);
- all_used = qdev_prop_check_globals();
- g_assert_cmpuint(all_used, ==, 0);
+ global_error = qdev_prop_check_globals();
+ g_assert_cmpuint(global_error, ==, 0);
g_assert(props[0].used);
g_assert(props[1].used);
g_assert(!props[2].used);
@@ -299,7 +309,7 @@ static void test_subclass_global_props(void)
{}
};
- qdev_prop_register_global_list(props);
+ register_global_properties(props);
mt = STATIC_TYPE(object_new(TYPE_SUBCLASS));
qdev_init_nofail(DEVICE(mt));
diff --git a/tests/test-qmp-cmds.c b/tests/test-qmp-cmds.c
index 4ab2b6e5ce..481cb069ca 100644
--- a/tests/test-qmp-cmds.c
+++ b/tests/test-qmp-cmds.c
@@ -126,6 +126,21 @@ static void test_dispatch_cmd(void)
qobject_unref(req);
}
+static void test_dispatch_cmd_oob(void)
+{
+ QDict *req = qdict_new();
+ QDict *resp;
+
+ qdict_put_str(req, "exec-oob", "test-flags-command");
+
+ resp = qmp_dispatch(&qmp_commands, QOBJECT(req), true);
+ assert(resp != NULL);
+ assert(!qdict_haskey(resp, "error"));
+
+ qobject_unref(resp);
+ qobject_unref(req);
+}
+
/* test commands that return an error due to invalid parameters */
static void test_dispatch_cmd_failure(void)
{
@@ -302,6 +317,7 @@ int main(int argc, char **argv)
g_test_init(&argc, &argv, NULL);
g_test_add_func("/qmp/dispatch_cmd", test_dispatch_cmd);
+ g_test_add_func("/qmp/dispatch_cmd_oob", test_dispatch_cmd_oob);
g_test_add_func("/qmp/dispatch_cmd_failure", test_dispatch_cmd_failure);
g_test_add_func("/qmp/dispatch_cmd_io", test_dispatch_cmd_io);
g_test_add_func("/qmp/dispatch_cmd_success_response",
diff --git a/tests/test-string-input-visitor.c b/tests/test-string-input-visitor.c
index 88e0e1aa9a..34b54dfc89 100644
--- a/tests/test-string-input-visitor.c
+++ b/tests/test-string-input-visitor.c
@@ -92,16 +92,6 @@ static void check_ulist(Visitor *v, uint64_t *expected, size_t n)
uint64List *tail;
int i;
- /* BUG: unsigned numbers above INT64_MAX don't work */
- for (i = 0; i < n; i++) {
- if (expected[i] > INT64_MAX) {
- Error *err = NULL;
- visit_type_uint64List(v, NULL, &res, &err);
- error_free_or_abort(&err);
- return;
- }
- }
-
visit_type_uint64List(v, NULL, &res, &error_abort);
tail = res;
for (i = 0; i < n; i++) {
@@ -117,14 +107,14 @@ static void check_ulist(Visitor *v, uint64_t *expected, size_t n)
static void test_visitor_in_intList(TestInputVisitorData *data,
const void *unused)
{
- /* Note: the visitor *sorts* ranges *unsigned* */
- int64_t expect1[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 20 };
+ int64_t expect1[] = { 1, 2, 0, 2, 3, 4, 20, 5, 6, 7,
+ 8, 9, 1, 2, 3, 4, 5, 6, 7, 8 };
int64_t expect2[] = { 32767, -32768, -32767 };
- int64_t expect3[] = { INT64_MAX, INT64_MIN };
- uint64_t expect4[] = { UINT64_MAX };
+ int64_t expect3[] = { INT64_MIN, INT64_MAX };
+ int64_t expect4[] = { 1 };
+ int64_t expect5[] = { INT64_MAX - 2, INT64_MAX - 1, INT64_MAX };
Error *err = NULL;
int64List *res = NULL;
- int64List *tail;
Visitor *v;
int64_t val;
@@ -140,8 +130,45 @@ static void test_visitor_in_intList(TestInputVisitorData *data,
"-9223372036854775808,9223372036854775807");
check_ilist(v, expect3, ARRAY_SIZE(expect3));
- v = visitor_input_test_init(data, "18446744073709551615");
- check_ulist(v, expect4, ARRAY_SIZE(expect4));
+ v = visitor_input_test_init(data, "1-1");
+ check_ilist(v, expect4, ARRAY_SIZE(expect4));
+
+ v = visitor_input_test_init(data,
+ "9223372036854775805-9223372036854775807");
+ check_ilist(v, expect5, ARRAY_SIZE(expect5));
+
+ /* Value too large */
+
+ v = visitor_input_test_init(data, "9223372036854775808");
+ visit_type_int64List(v, NULL, &res, &err);
+ error_free_or_abort(&err);
+ g_assert(!res);
+
+ /* Value too small */
+
+ v = visitor_input_test_init(data, "-9223372036854775809");
+ visit_type_int64List(v, NULL, &res, &err);
+ error_free_or_abort(&err);
+ g_assert(!res);
+
+ /* Range not ascending */
+
+ v = visitor_input_test_init(data, "3-1");
+ visit_type_int64List(v, NULL, &res, &err);
+ error_free_or_abort(&err);
+ g_assert(!res);
+
+ v = visitor_input_test_init(data, "9223372036854775807-0");
+ visit_type_int64List(v, NULL, &res, &err);
+ error_free_or_abort(&err);
+ g_assert(!res);
+
+ /* Range too big (65536 is the limit against DOS attacks) */
+
+ v = visitor_input_test_init(data, "0-65536");
+ visit_type_int64List(v, NULL, &res, &err);
+ error_free_or_abort(&err);
+ g_assert(!res);
/* Empty list */
@@ -161,39 +188,140 @@ static void test_visitor_in_intList(TestInputVisitorData *data,
v = visitor_input_test_init(data, "0,2-3");
- /* Would be simpler if the visitor genuinely supported virtual walks */
- visit_start_list(v, NULL, (GenericList **)&res, sizeof(*res),
- &error_abort);
- tail = res;
- visit_type_int64(v, NULL, &tail->value, &error_abort);
- g_assert_cmpint(tail->value, ==, 0);
- tail = (int64List *)visit_next_list(v, (GenericList *)tail, sizeof(*res));
- g_assert(tail);
- visit_type_int64(v, NULL, &tail->value, &error_abort);
- g_assert_cmpint(tail->value, ==, 2);
- tail = (int64List *)visit_next_list(v, (GenericList *)tail, sizeof(*res));
- g_assert(tail);
+ visit_start_list(v, NULL, NULL, 0, &error_abort);
+ visit_type_int64(v, NULL, &val, &error_abort);
+ g_assert_cmpint(val, ==, 0);
+ visit_type_int64(v, NULL, &val, &error_abort);
+ g_assert_cmpint(val, ==, 2);
visit_check_list(v, &err);
error_free_or_abort(&err);
- visit_end_list(v, (void **)&res);
-
- qapi_free_int64List(res);
+ visit_end_list(v, NULL);
/* Visit beyond end of list */
+
v = visitor_input_test_init(data, "0");
- visit_start_list(v, NULL, (GenericList **)&res, sizeof(*res),
- &error_abort);
- tail = res;
- visit_type_int64(v, NULL, &tail->value, &err);
- g_assert_cmpint(tail->value, ==, 0);
+ visit_start_list(v, NULL, NULL, 0, &error_abort);
visit_type_int64(v, NULL, &val, &err);
- g_assert_cmpint(val, ==, 1); /* BUG */
+ g_assert_cmpint(val, ==, 0);
+ visit_type_int64(v, NULL, &val, &err);
+ error_free_or_abort(&err);
+
visit_check_list(v, &error_abort);
- visit_end_list(v, (void **)&res);
+ visit_end_list(v, NULL);
+}
- qapi_free_int64List(res);
+static void test_visitor_in_uintList(TestInputVisitorData *data,
+ const void *unused)
+{
+ uint64_t expect1[] = { 1, 2, 0, 2, 3, 4, 20, 5, 6, 7,
+ 8, 9, 1, 2, 3, 4, 5, 6, 7, 8 };
+ uint64_t expect2[] = { 32767, -32768, -32767 };
+ uint64_t expect3[] = { INT64_MIN, INT64_MAX };
+ uint64_t expect4[] = { 1 };
+ uint64_t expect5[] = { UINT64_MAX };
+ uint64_t expect6[] = { UINT64_MAX - 2, UINT64_MAX - 1, UINT64_MAX };
+ Error *err = NULL;
+ uint64List *res = NULL;
+ Visitor *v;
+ uint64_t val;
+
+ /* Valid lists */
+
+ v = visitor_input_test_init(data, "1,2,0,2-4,20,5-9,1-8");
+ check_ulist(v, expect1, ARRAY_SIZE(expect1));
+
+ v = visitor_input_test_init(data, "32767,-32768--32767");
+ check_ulist(v, expect2, ARRAY_SIZE(expect2));
+
+ v = visitor_input_test_init(data,
+ "-9223372036854775808,9223372036854775807");
+ check_ulist(v, expect3, ARRAY_SIZE(expect3));
+
+ v = visitor_input_test_init(data, "1-1");
+ check_ulist(v, expect4, ARRAY_SIZE(expect4));
+
+ v = visitor_input_test_init(data, "18446744073709551615");
+ check_ulist(v, expect5, ARRAY_SIZE(expect5));
+
+ v = visitor_input_test_init(data,
+ "18446744073709551613-18446744073709551615");
+ check_ulist(v, expect6, ARRAY_SIZE(expect6));
+
+ /* Value too large */
+
+ v = visitor_input_test_init(data, "18446744073709551616");
+ visit_type_uint64List(v, NULL, &res, &err);
+ error_free_or_abort(&err);
+ g_assert(!res);
+
+ /* Value too small */
+
+ v = visitor_input_test_init(data, "-18446744073709551616");
+ visit_type_uint64List(v, NULL, &res, &err);
+ error_free_or_abort(&err);
+ g_assert(!res);
+
+ /* Range not ascending */
+
+ v = visitor_input_test_init(data, "3-1");
+ visit_type_uint64List(v, NULL, &res, &err);
+ error_free_or_abort(&err);
+ g_assert(!res);
+
+ v = visitor_input_test_init(data, "18446744073709551615-0");
+ visit_type_uint64List(v, NULL, &res, &err);
+ error_free_or_abort(&err);
+ g_assert(!res);
+
+ /* Range too big (65536 is the limit against DOS attacks) */
+
+ v = visitor_input_test_init(data, "0-65536");
+ visit_type_uint64List(v, NULL, &res, &err);
+ error_free_or_abort(&err);
+ g_assert(!res);
+
+ /* Empty list */
+
+ v = visitor_input_test_init(data, "");
+ visit_type_uint64List(v, NULL, &res, &error_abort);
+ g_assert(!res);
+
+ /* Not a list */
+
+ v = visitor_input_test_init(data, "not an uint list");
+
+ visit_type_uint64List(v, NULL, &res, &err);
+ error_free_or_abort(&err);
+ g_assert(!res);
+
+ /* Unvisited list tail */
+
+ v = visitor_input_test_init(data, "0,2-3");
+
+ visit_start_list(v, NULL, NULL, 0, &error_abort);
+ visit_type_uint64(v, NULL, &val, &error_abort);
+ g_assert_cmpuint(val, ==, 0);
+ visit_type_uint64(v, NULL, &val, &error_abort);
+ g_assert_cmpuint(val, ==, 2);
+
+ visit_check_list(v, &err);
+ error_free_or_abort(&err);
+ visit_end_list(v, NULL);
+
+ /* Visit beyond end of list */
+
+ v = visitor_input_test_init(data, "0");
+
+ visit_start_list(v, NULL, NULL, 0, &error_abort);
+ visit_type_uint64(v, NULL, &val, &err);
+ g_assert_cmpuint(val, ==, 0);
+ visit_type_uint64(v, NULL, &val, &err);
+ error_free_or_abort(&err);
+
+ visit_check_list(v, &error_abort);
+ visit_end_list(v, NULL);
}
static void test_visitor_in_bool(TestInputVisitorData *data,
@@ -252,6 +380,19 @@ static void test_visitor_in_number(TestInputVisitorData *data,
visit_type_number(v, NULL, &res, &err);
g_assert(!err);
g_assert_cmpfloat(res, ==, value);
+
+ /* NaN and infinity has to be rejected */
+
+ v = visitor_input_test_init(data, "NaN");
+
+ visit_type_number(v, NULL, &res, &err);
+ error_free_or_abort(&err);
+
+ v = visitor_input_test_init(data, "inf");
+
+ visit_type_number(v, NULL, &res, &err);
+ error_free_or_abort(&err);
+
}
static void test_visitor_in_string(TestInputVisitorData *data,
@@ -356,6 +497,8 @@ int main(int argc, char **argv)
&in_visitor_data, test_visitor_in_int);
input_visitor_test_add("/string-visitor/input/intList",
&in_visitor_data, test_visitor_in_intList);
+ input_visitor_test_add("/string-visitor/input/uintList",
+ &in_visitor_data, test_visitor_in_uintList);
input_visitor_test_add("/string-visitor/input/bool",
&in_visitor_data, test_visitor_in_bool);
input_visitor_test_add("/string-visitor/input/number",
diff --git a/trace/simple.c b/trace/simple.c
index 701dec639c..ac904eca91 100644
--- a/trace/simple.c
+++ b/trace/simple.c
@@ -169,9 +169,9 @@ static gpointer writeout_thread(gpointer opaque)
wait_for_trace_records_available();
if (g_atomic_int_get(&dropped_events)) {
- dropped.rec.event = DROPPED_EVENT_ID,
+ dropped.rec.event = DROPPED_EVENT_ID;
dropped.rec.timestamp_ns = get_clock();
- dropped.rec.length = sizeof(TraceRecord) + sizeof(uint64_t),
+ dropped.rec.length = sizeof(TraceRecord) + sizeof(uint64_t);
dropped.rec.pid = trace_pid;
do {
dropped_count = g_atomic_int_get(&dropped_events);
diff --git a/util/cutils.c b/util/cutils.c
index 698bd315bd..e098debdc0 100644
--- a/util/cutils.c
+++ b/util/cutils.c
@@ -203,23 +203,21 @@ static int64_t suffix_mul(char suffix, int64_t unit)
/*
* Convert string to bytes, allowing either B/b for bytes, K/k for KB,
* M/m for MB, G/g for GB or T/t for TB. End pointer will be returned
- * in *end, if not NULL. Return -ERANGE on overflow, Return -EINVAL on
+ * in *end, if not NULL. Return -ERANGE on overflow, and -EINVAL on
* other error.
*/
-static int do_strtosz(const char *nptr, char **end,
+static int do_strtosz(const char *nptr, const char **end,
const char default_suffix, int64_t unit,
uint64_t *result)
{
int retval;
- char *endptr;
+ const char *endptr;
unsigned char c;
int mul_required = 0;
double val, mul, integral, fraction;
- errno = 0;
- val = strtod(nptr, &endptr);
- if (isnan(val) || endptr == nptr || errno != 0) {
- retval = -EINVAL;
+ retval = qemu_strtod_finite(nptr, &endptr, &val);
+ if (retval) {
goto out;
}
fraction = modf(val, &integral);
@@ -259,17 +257,17 @@ out:
return retval;
}
-int qemu_strtosz(const char *nptr, char **end, uint64_t *result)
+int qemu_strtosz(const char *nptr, const char **end, uint64_t *result)
{
return do_strtosz(nptr, end, 'B', 1024, result);
}
-int qemu_strtosz_MiB(const char *nptr, char **end, uint64_t *result)
+int qemu_strtosz_MiB(const char *nptr, const char **end, uint64_t *result)
{
return do_strtosz(nptr, end, 'M', 1024, result);
}
-int qemu_strtosz_metric(const char *nptr, char **end, uint64_t *result)
+int qemu_strtosz_metric(const char *nptr, const char **end, uint64_t *result)
{
return do_strtosz(nptr, end, 'B', 1000, result);
}
@@ -280,6 +278,7 @@ int qemu_strtosz_metric(const char *nptr, char **end, uint64_t *result)
static int check_strtox_error(const char *nptr, char *ep,
const char **endptr, int libc_errno)
{
+ assert(ep >= nptr);
if (endptr) {
*endptr = ep;
}
@@ -327,6 +326,7 @@ int qemu_strtoi(const char *nptr, const char **endptr, int base,
char *ep;
long long lresult;
+ assert((unsigned) base <= 36 && base != 1);
if (!nptr) {
if (endptr) {
*endptr = nptr;
@@ -379,6 +379,7 @@ int qemu_strtoui(const char *nptr, const char **endptr, int base,
char *ep;
long long lresult;
+ assert((unsigned) base <= 36 && base != 1);
if (!nptr) {
if (endptr) {
*endptr = nptr;
@@ -435,6 +436,7 @@ int qemu_strtol(const char *nptr, const char **endptr, int base,
{
char *ep;
+ assert((unsigned) base <= 36 && base != 1);
if (!nptr) {
if (endptr) {
*endptr = nptr;
@@ -477,6 +479,7 @@ int qemu_strtoul(const char *nptr, const char **endptr, int base,
{
char *ep;
+ assert((unsigned) base <= 36 && base != 1);
if (!nptr) {
if (endptr) {
*endptr = nptr;
@@ -504,6 +507,7 @@ int qemu_strtoi64(const char *nptr, const char **endptr, int base,
{
char *ep;
+ assert((unsigned) base <= 36 && base != 1);
if (!nptr) {
if (endptr) {
*endptr = nptr;
@@ -527,6 +531,7 @@ int qemu_strtou64(const char *nptr, const char **endptr, int base,
{
char *ep;
+ assert((unsigned) base <= 36 && base != 1);
if (!nptr) {
if (endptr) {
*endptr = nptr;
@@ -545,6 +550,71 @@ int qemu_strtou64(const char *nptr, const char **endptr, int base,
}
/**
+ * Convert string @nptr to a double.
+ *
+ * This is a wrapper around strtod() that is harder to misuse.
+ * Semantics of @nptr and @endptr match strtod() with differences
+ * noted below.
+ *
+ * @nptr may be null, and no conversion is performed then.
+ *
+ * If no conversion is performed, store @nptr in *@endptr and return
+ * -EINVAL.
+ *
+ * If @endptr is null, and the string isn't fully converted, return
+ * -EINVAL. This is the case when the pointer that would be stored in
+ * a non-null @endptr points to a character other than '\0'.
+ *
+ * If the conversion overflows, store +/-HUGE_VAL in @result, depending
+ * on the sign, and return -ERANGE.
+ *
+ * If the conversion underflows, store +/-0.0 in @result, depending on the
+ * sign, and return -ERANGE.
+ *
+ * Else store the converted value in @result, and return zero.
+ */
+int qemu_strtod(const char *nptr, const char **endptr, double *result)
+{
+ char *ep;
+
+ if (!nptr) {
+ if (endptr) {
+ *endptr = nptr;
+ }
+ return -EINVAL;
+ }
+
+ errno = 0;
+ *result = strtod(nptr, &ep);
+ return check_strtox_error(nptr, ep, endptr, errno);
+}
+
+/**
+ * Convert string @nptr to a finite double.
+ *
+ * Works like qemu_strtod(), except that "NaN" and "inf" are rejected
+ * with -EINVAL and no conversion is performed.
+ */
+int qemu_strtod_finite(const char *nptr, const char **endptr, double *result)
+{
+ double tmp;
+ int ret;
+
+ ret = qemu_strtod(nptr, endptr, &tmp);
+ if (!ret && !isfinite(tmp)) {
+ if (endptr) {
+ *endptr = nptr;
+ }
+ ret = -EINVAL;
+ }
+
+ if (ret != -EINVAL) {
+ *result = tmp;
+ }
+ return ret;
+}
+
+/**
* Searches for the first occurrence of 'c' in 's', and returns a pointer
* to the trailing null byte if none was found.
*/
@@ -594,6 +664,7 @@ int parse_uint(const char *s, unsigned long long *value, char **endptr,
char *endp = (char *)s;
unsigned long long val = 0;
+ assert((unsigned) base <= 36 && base != 1);
if (!s) {
r = -EINVAL;
goto out;
diff --git a/util/vfio-helpers.c b/util/vfio-helpers.c
index cccc9cd42e..342d4a2285 100644
--- a/util/vfio-helpers.c
+++ b/util/vfio-helpers.c
@@ -348,7 +348,7 @@ static int qemu_vfio_init_pci(QEMUVFIOState *s, const char *device,
goto fail;
}
- for (i = 0; i < 6; i++) {
+ for (i = 0; i < ARRAY_SIZE(s->bar_region_info); i++) {
ret = qemu_vfio_pci_init_bar(s, i, errp);
if (ret) {
goto fail;
diff --git a/vl.c b/vl.c
index a5ae5f23d2..2a8b2ee16d 100644
--- a/vl.c
+++ b/vl.c
@@ -2322,11 +2322,6 @@ static int mon_init_func(void *opaque, QemuOpts *opts, Error **errp)
if (qemu_opt_get_bool(opts, "pretty", 0))
flags |= MONITOR_USE_PRETTY;
- /* OOB is off by default */
- if (qemu_opt_get_bool(opts, "x-oob", 0)) {
- flags |= MONITOR_USE_OOB;
- }
-
chardev = qemu_opt_get(opts, "chardev");
if (!chardev) {
error_report("chardev is required");