summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Baumann <mail@daniel-baumann.ch>2025-06-06 10:05:27 +0000
committerDaniel Baumann <mail@daniel-baumann.ch>2025-06-06 10:05:27 +0000
commit43904a02caeb311a505bbb5ffa431ea9859db5f4 (patch)
treecd841d75f639d9092243b0d02a3bb93cbdea5804
parentAdding upstream version 1:7.2+dfsg. (diff)
downloadqemu-debian.tar.xz
qemu-debian.zip
Adding debian version 1:7.2+dfsg-7+deb12u13.debian/1%7.2+dfsg-7+deb12u13debian
Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
-rw-r--r--debian/README-components-versions74
-rw-r--r--debian/TODO16
-rwxr-xr-xdebian/binfmt-install160
-rw-r--r--debian/changelog5965
-rw-r--r--debian/control514
-rw-r--r--debian/control-in565
-rw-r--r--debian/copyright532
-rwxr-xr-xdebian/extract-config-opts11
-rw-r--r--debian/gbp.conf4
-rwxr-xr-xdebian/get-orig-source.sh141
-rwxr-xr-xdebian/kvm-spice10
-rw-r--r--debian/kvm-spice.117
-rw-r--r--debian/kvm.120
-rw-r--r--debian/microvm-devices.mak26
-rw-r--r--debian/not-installed17
-rw-r--r--debian/optionrom.mak31
-rw-r--r--debian/patches/ignore-roms-dependency-in-qtest.patch20
-rw-r--r--debian/patches/linux-user-binfmt-P.diff90
-rw-r--r--debian/patches/mark-internal-codegen-functions-hidden.patch50
-rw-r--r--debian/patches/microvm-default-machine-type.patch31
-rw-r--r--debian/patches/note-missing-module-pkg-name.diff38
-rw-r--r--debian/patches/openbios-address-of-packet-member.patch11
-rw-r--r--debian/patches/openbios-array-bounds-gcc12.patch25
-rw-r--r--debian/patches/openbios-array-bounds.diff11
-rw-r--r--debian/patches/openbios-spelling-endianess.patch24
-rw-r--r--debian/patches/openbios-use-source_date_epoch-in-makefile.patch34
-rw-r--r--debian/patches/seabios-hppa-use-consistent-date-and-remove-hostname.patch32
-rw-r--r--debian/patches/series34
-rw-r--r--debian/patches/skip-meson-pc-bios.diff14
-rw-r--r--debian/patches/slof-ensure-ld-is-called-with-C-locale.patch20
-rw-r--r--debian/patches/slof-remove-user-and-host-from-release-version.patch21
-rw-r--r--debian/patches/slof-spelling-seperator.patch7
-rw-r--r--debian/patches/spelling.diff73
-rw-r--r--debian/patches/v7.2.1.diff1945
-rw-r--r--debian/patches/v7.2.10.diff1444
-rw-r--r--debian/patches/v7.2.11.diff2353
-rw-r--r--debian/patches/v7.2.12.diff1516
-rw-r--r--debian/patches/v7.2.13.diff3859
-rw-r--r--debian/patches/v7.2.14.diff3173
-rw-r--r--debian/patches/v7.2.15.diff1245
-rw-r--r--debian/patches/v7.2.16.diff1368
-rw-r--r--debian/patches/v7.2.17.diff1397
-rw-r--r--debian/patches/v7.2.2.diff514
-rw-r--r--debian/patches/v7.2.3.diff2258
-rw-r--r--debian/patches/v7.2.4.diff1420
-rw-r--r--debian/patches/v7.2.5.diff1575
-rw-r--r--debian/patches/v7.2.6.diff3085
-rw-r--r--debian/patches/v7.2.7.diff2307
-rw-r--r--debian/patches/v7.2.8.diff1524
-rw-r--r--debian/patches/v7.2.9.diff3566
-rw-r--r--debian/qemu-block-extra.install1
-rwxr-xr-xdebian/qemu-debootstrap15
-rw-r--r--debian/qemu-debootstrap.119
-rw-r--r--debian/qemu-guest-agent.dirs1
-rw-r--r--debian/qemu-guest-agent.init131
-rw-r--r--debian/qemu-guest-agent.install5
-rw-r--r--debian/qemu-guest-agent.postinst59
-rw-r--r--debian/qemu-guest-agent.postrm56
-rw-r--r--debian/qemu-guest-agent.preinst62
-rw-r--r--debian/qemu-guest-agent.service11
-rw-r--r--debian/qemu-guest-agent.udev2
-rwxr-xr-xdebian/qemu-ifdown6
-rwxr-xr-xdebian/qemu-ifup.kfreebsd3
-rwxr-xr-xdebian/qemu-ifup.linux41
-rw-r--r--debian/qemu-io.143
-rw-r--r--debian/qemu-system-common.NEWS46
-rw-r--r--debian/qemu-system-common.doc-base12
-rw-r--r--debian/qemu-system-common.install18
-rw-r--r--debian/qemu-system-common.lintian-overrides5
-rw-r--r--debian/qemu-system-data.docs5
-rw-r--r--debian/qemu-system-data.lintian-overrides5
-rw-r--r--debian/qemu-system-gui.install3
-rwxr-xr-xdebian/qemu-system-i386.xen-wrapper29
-rw-r--r--debian/qemu-system-misc.install2
-rw-r--r--debian/qemu-system-misc.lintian-overrides2
-rw-r--r--debian/qemu-system-ppc.README.Debian13
-rw-r--r--debian/qemu-system-ppc.links2
-rw-r--r--debian/qemu-system-ppc.lintian-overrides1
-rw-r--r--debian/qemu-system-x86.NEWS50
-rwxr-xr-xdebian/qemu-system-x86_64-spice5
-rw-r--r--debian/qemu-system.NEWS47
-rw-r--r--debian/qemu-user-static.137
-rw-r--r--debian/qemu-user-static.docs1
-rw-r--r--debian/qemu-user-static.install3
-rw-r--r--debian/qemu-user-static.lintian-overrides4
-rw-r--r--debian/qemu-user.docs1
-rw-r--r--debian/qemu-user.install1
-rw-r--r--debian/qemu-user.lintian-overrides3
-rw-r--r--debian/qemu-utils.NEWS15
-rw-r--r--debian/qemu-utils.install5
-rw-r--r--debian/qemu-utils.manpages1
-rw-r--r--debian/qemu.desktop8
-rwxr-xr-xdebian/rules653
-rw-r--r--debian/run-qemu.mount14
-rw-r--r--debian/s390fw.mak49
-rw-r--r--debian/source/format1
-rw-r--r--debian/source/lintian-overrides6
-rw-r--r--debian/source/options2
-rw-r--r--debian/source_qemu.py25
-rw-r--r--debian/tests/control11
-rwxr-xr-xdebian/tests/test-qemu-img.sh35
-rwxr-xr-xdebian/tests/test-qemu-system.sh10
-rwxr-xr-xdebian/tests/test-qemu-user.sh34
-rw-r--r--debian/upstream/signing-key.asc44
-rw-r--r--debian/watch9
105 files changed, 44859 insertions, 0 deletions
diff --git a/debian/README-components-versions b/debian/README-components-versions
new file mode 100644
index 00000000..de78efe6
--- /dev/null
+++ b/debian/README-components-versions
@@ -0,0 +1,74 @@
+Evolution of qemu-related packages in debian
+
+kvm: was a binary package providing /usr/bin/kvm before squeeze.
+
+ In squeeze it has been renamed to qemu-kvm,
+ so kvm becomes a transitional package.
+
+ Probably can be get rid of now.
+
+ No need to conflict with this package, but we can force-remove it
+ by conflicting with it.
+
+ Some packages may still Require/Depend/Suggest: kvm.
+
+
+qemu-kvm: was a binary package providing /usr/bin/kvm in wheezy (v. 1.1)
+
+ This binary become a (deprecated) shell wrapper and was a part of
+ qemu-system-x86 package between versions 1.3.0+dfsg-5 (when qemu-system
+ were split) up to 1.7.0+dfsg-1, with qemu-kvm package being transitional.
+
+ At version 1.7.0+dfsg-2, qemu-kvm packcage is not transitional anymore,
+ and the wrapper is provided by qemu-kvm, not qemu-system-x86.
+
+ Some packages may Require/Depend/Suggest: qemu-kvm.
+
+qemu: initially it was a mix of all of qemu (unrelated, not conflicting
+with qemu-kvm or kvm)
+
+ at 0.11.0-1 it were split to qemu-user, qemu-user-static and qemu-system.
+
+ Also qemu-keymaps is made a separate package at version 0.12.4+dfsg-4
+ (for use together with qemu-kvm and xen and, on ubuntu, qemu-linaro).
+
+ And qemu-utils become a separate package (look when? since the beginning?)
+
+ Now it is a metapackage and a placeholder for some docs
+
+qemu-system: was a package with all qemu-system-* binaries.
+
+ Were split into individual qemu-system-foo and qemu-system-common at version
+ 1.3.0+dfsg-5, so qemu-system becomes a metapackage without its own files.
+
+ The split introduced a bunch of qemu-system-* conflicting+replacing
+ qemu-system<<1.3.0+dfsg-5.
+
+ At version 1.3.0+dfsg-4exp (before split, in experimental), /usr/bin/kvm was
+ a part of qemu-system (and later qemu-system-x86)/
+
+ At the same version, virtfs-proxy-helper binary has been moved from qemu-utils
+ to qemu-system (and later to qemu-system-common).
+
+qemu-system-common: appeared at 1.3.0+dfsg-5, files common for all qemu-system*
+
+ briefly (>=1.3.0+dfsg-4exp, <<1.3.0+dfsg-5), qemu-utils had
+ virtfs-proxy-helper binary which is in qemu-system-common
+
+qemu-keymaps: keymap definition for qemu, qemu-kvm and xen.
+
+ Can be merged into qemu-system-common now, or after qemu-linaro.
+
+ Were split out of qemu at version 0.12.4+dfsg-4
+
+qemu-utils: common utilities (part of qemu-common in ubuntu?)
+
+ In versions between 1.3.0+dfsg-1~exp1 and 1.3.0+dfsg-4exp, wrongly shipped
+ virtfs-proxy-helper binary
+
+qemu-user, qemu-user-static: user-mode qemu emulation
+
+ Were split out of qemu at verson 0.11.0-1 (pre-squeeze),
+ do not conflict/replace anything anymore.
+
+qemu-common: ubuntu package
diff --git a/debian/TODO b/debian/TODO
new file mode 100644
index 00000000..5efed04b
--- /dev/null
+++ b/debian/TODO
@@ -0,0 +1,16 @@
+* fix other binaries (s390-zipl, ppc_rom)
+
+* permissions/ownership for /dev/vhost_net???
+
+* startup script for qemu-guest-agent: check dependencies & runlevels.
+
+* maybe provide activation for udev & systemd:
+
+ SUBSYSTEM=="virtio-ports", ATTR{name}=="org.qemu.guest_agent.0", \
+ TAG+="systemd" ENV{SYSTEMD_WANTS}="qemu-guest-agent.service"
+
+ and dev-virtio/ports-org.qemu.guest_agent.0.device activation
+ for systemd.
+
+* decide what to do with qemu-bridge-helper (#691138)
+
diff --git a/debian/binfmt-install b/debian/binfmt-install
new file mode 100755
index 00000000..0f4f10ee
--- /dev/null
+++ b/debian/binfmt-install
@@ -0,0 +1,160 @@
+#!/bin/sh
+set -e
+
+PACKAGE="$1"
+case "$#$PACKAGE" in
+ 1qemu-user-static) SUFFIX=-static; FIX_BINARY=yes; FIXB=F ;;
+ 1qemu-user-binfmt) SUFFIX=; FIX_BINARY=no; FIXB= ;;
+ *) echo "usage: $0 <qemu-user-binfmt|qemu-user-static>"; exit 1 ;;
+esac
+
+fmts="aarch64 alpha arm armeb cris hexagon hppa i386 loongarch64 m68k microblaze mips mipsel mipsn32 mipsn32el mips64 mips64el ppc ppc64 ppc64le riscv32 riscv64 s390x sh4 sh4eb sparc sparc32plus sparc64 x86_64 xtensa xtensaeb"
+removed_fmts="ppc64abi32"
+
+# linux ELF_OSABI(byte7) can be 0 (traditional,SYSV) or 3 (GNU/LINUX extensions)
+# binfmt registration does not allow a enum, only value&mask. So we use broader mask
+# to allow both 0 and 3 here, this also lets 1 (HPUX) and 2 (NETBSD) - 0xfc not 0xff
+# alternative is to create 2 magic/mask pairs instead of one
+
+ aarch64_magic='\x7f\x45\x4c\x46\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xb7\x00'
+ aarch64_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff'
+ alpha_magic='\x7f\x45\x4c\x46\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x26\x90'
+ alpha_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff'
+ arm_magic='\x7f\x45\x4c\x46\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28\x00'
+ arm_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff'
+ armeb_magic='\x7f\x45\x4c\x46\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28'
+ armeb_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff'
+ cris_magic='\x7f\x45\x4c\x46\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x4c\x00'
+ cris_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff'
+ hexagon_magic='\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xa4\x00'
+ hexagon_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff'
+ hppa_magic='\x7f\x45\x4c\x46\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x0f'
+ hppa_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff'
+ i386_magic='\x7f\x45\x4c\x46\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x03\x00'
+ i386_mask='\xff\xff\xff\xff\xff\xfe\xfe\xfc\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff'
+loongarch64_magic='\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x02\x01'
+ loongarch64_mask='\xff\xff\xff\xff\xff\xff\xff\xfc\x00\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff'
+ m68k_magic='\x7f\x45\x4c\x46\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x04'
+ m68k_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff'
+ microblaze_magic='\x7f\x45\x4c\x46\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\xba\xab'
+ microblaze_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff'
+ mips_magic='\x7f\x45\x4c\x46\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
+ mips_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20'
+ mipsel_magic='\x7f\x45\x4c\x46\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
+ mipsel_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xfe\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20'
+ mipsn32_magic='\x7f\x45\x4c\x46\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20'
+ mipsn32_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20'
+ mipsn32el_magic='\x7f\x45\x4c\x46\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20'
+ mipsn32el_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xfe\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20'
+ mips64_magic='\x7f\x45\x4c\x46\x02\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08'
+ mips64_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff'
+ mips64el_magic='\x7f\x45\x4c\x46\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08\x00'
+ mips64el_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xfe\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff'
+ ppc_magic='\x7f\x45\x4c\x46\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x14'
+ ppc_mask='\xff\xff\xff\xff\xff\xff\xff\xfc\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff'
+ ppc64_magic='\x7f\x45\x4c\x46\x02\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x15'
+ ppc64_mask='\xff\xff\xff\xff\xff\xff\xff\xfc\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff'
+ ppc64le_magic='\x7f\x45\x4c\x46\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x15\x00'
+ ppc64le_mask='\xff\xff\xff\xff\xff\xff\xff\xfc\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\x00'
+ riscv32_magic='\x7f\x45\x4c\x46\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xf3\x00'
+ riscv32_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff'
+ riscv64_magic='\x7f\x45\x4c\x46\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xf3\x00'
+ riscv64_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff'
+ s390x_magic='\x7f\x45\x4c\x46\x02\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x16'
+ s390x_mask='\xff\xff\xff\xff\xff\xff\xff\xfc\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff'
+ sh4_magic='\x7f\x45\x4c\x46\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x2a\x00'
+ sh4_mask='\xff\xff\xff\xff\xff\xff\xff\xfc\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff'
+ sh4eb_magic='\x7f\x45\x4c\x46\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x2a'
+ sh4eb_mask='\xff\xff\xff\xff\xff\xff\xff\xfc\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff'
+ sparc_magic='\x7f\x45\x4c\x46\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x02'
+ sparc_mask='\xff\xff\xff\xff\xff\xff\xff\xfc\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff'
+sparc32plus_magic='\x7f\x45\x4c\x46\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x12'
+ sparc32plus_mask='\xff\xff\xff\xff\xff\xff\xff\xfc\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff'
+ sparc64_magic='\x7f\x45\x4c\x46\x02\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x2b'
+ sparc64_mask='\xff\xff\xff\xff\xff\xff\xff\xfc\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff'
+ x86_64_magic='\x7f\x45\x4c\x46\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x3e\x00'
+ x86_64_mask='\xff\xff\xff\xff\xff\xfe\xfe\xfc\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff'
+ xtensa_magic='\x7f\x45\x4c\x46\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x5e\x00'
+ xtensa_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff'
+ xtensaeb_magic='\x7f\x45\x4c\x46\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x5e'
+ xtensaeb_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff'
+
+: ${DEB_HOST_ARCH:=$(dpkg-architecture -qDEB_HOST_ARCH)}
+
+# find which fmts needs to be filtered out, which is arch-dependent.
+# Drop support for emulating amd64 on i386, http://bugs.debian.org/604712
+case "$DEB_HOST_ARCH" in
+ amd64 | i386 | x32) omit="i386|x86_64|x32" ;;
+ arm | armel | armhf | arm64) omit="arm|aarch64" ;;
+ ppc64 | powerpc) omit="ppc|ppc64|ppc64abi32" ;;
+ ppc64el) omit="ppc64le" ;;
+ riscv64) omit="riscv32|riscv64" ;;
+ s390x) omit="s390x" ;;
+ sparc | sparc64) omit="sparc|sparc32plus|sparc64" ;;
+ *) omit="$DEB_HOST_ARCH" ;;
+esac
+
+mkdir -p debian/$PACKAGE/usr/share/binfmts
+mkdir -p debian/$PACKAGE/usr/libexec/qemu-binfmt
+mkdir -p debian/$PACKAGE/usr/lib/binfmt.d
+installed_fmts=
+for fmt in $fmts ; do
+ eval "case $fmt in $omit) magic= ;; *) magic=\"\$${fmt}_magic\" mask=\"\$${fmt}_mask\" ;; esac"
+ [ -z "$magic" ] && continue
+ installed_fmts="$installed_fmts $fmt"
+ # use a special name ending with -binfmt-P so qemu-user
+ # knows it is run by kernel binfmt with P (preserve) flag
+ ln -sf ../../bin/qemu-$fmt$SUFFIX debian/$PACKAGE/usr/libexec/qemu-binfmt/$fmt-binfmt-P
+ cat >debian/$PACKAGE/usr/share/binfmts/qemu-$fmt <<EOF
+package $PACKAGE
+interpreter /usr/libexec/qemu-binfmt/$fmt-binfmt-P
+magic $magic
+offset 0
+mask $mask
+credentials yes
+fix_binary $FIX_BINARY
+preserve yes
+EOF
+ echo ":qemu-$fmt:M::$magic:$mask:/usr/libexec/qemu-binfmt/$fmt-binfmt-P:OCP${FIXB}" \
+ >debian/$PACKAGE/usr/lib/binfmt.d/qemu-$fmt.conf
+
+done
+
+# generate postinst and prerm fragments
+for action in postinst:configure:import prerm:remove:unimport
+do
+
+ ifs="$IFS"; IFS=:; set $action; IFS="$ifs"
+ cat >>debian/$PACKAGE.$1.debhelper <<EOF
+binfmt_update() {
+ test $2 = "\$1" || return 0
+ command -v update-binfmts >/dev/null || return 0
+ # do not touch binfmts inside a container
+ # should this be done by update-binfmts instead?
+ if command -v systemd-detect-virt >/dev/null; then
+ systemd-detect-virt --quiet --container && return 0
+ fi
+ grep -zqs ^container= /proc/1/environ && return 0
+ for fmt in $installed_fmts; do
+ update-binfmts --$3 qemu-\$fmt
+ done
+}
+binfmt_update "\$1"
+EOF
+done
+# also generate a preinst script to unregister removed fmts if any
+cat >>debian/$PACKAGE.preinst.debhelper <<EOF
+binfmt_update() {
+ test upgrade = "\$1" || return 0
+ dpkg --compare-versions "\$2" le "1:5.2+dfsg-3~" || return 0
+ command -v update-binfmts >/dev/null || return 0
+ for fmt in $removed_fmts; do
+ if [ -f /var/lib/binfmts/qemu-\$fmt ]; then
+ [ -f /usr/bin/qemu-\$fmt$SUFFIX ] ||
+ echo "$PACKAGE.preinst: note: the warning from update-binfmts about missing qemu-\$fmt$SUFFIX is okay" >&2
+ update-binfmts --package $PACKAGE --remove qemu-\$fmt /usr/bin/qemu-\$fmt$SUFFIX
+ fi
+ done
+}
+binfmt_update "\$1" "\$2"
+EOF
diff --git a/debian/changelog b/debian/changelog
new file mode 100644
index 00000000..eecb5856
--- /dev/null
+++ b/debian/changelog
@@ -0,0 +1,5965 @@
+qemu (1:7.2+dfsg-7+deb12u13) bookworm; urgency=medium
+
+ * v7.2.17:
+ - Update version for 7.2.17 release
+ - hw/misc/aspeed_hace: Fix buffer overflow in has_padding function
+ - target/ppc: Fix e200 duplicate SPRs
+ - vdpa: Allow vDPA to work on big-endian machine
+ - vdpa: Fix endian bugs in shadow virtqueue
+ - target/arm: Simplify pstate_sm check in sve_access_check
+ - target/arm: Make DisasContext.{fp, sve}_access_checked tristate
+ - util/cacheflush: Make first DSB unconditional on aarch64
+ - ui/cocoa: Temporarily ignore annoying deprecated declaration warnings
+ - docs: Rename default-configs to configs
+ - block: Zero block driver state before reopening
+ - hw/net/smc91c111: Don't allow data register access to overrun buffer
+ - hw/net/smc91c111: Sanitize packet length on tx
+ - hw/net/smc91c111: Sanitize packet numbers
+ - hw/net/smc91c111: Ignore attempt to pop from empty RX fifo
+ - ppc/pnv/occ: Fix common area sensor offsets
+ - hw/gpio: npcm7xx: fixup out-of-bounds access
+ - block/qed: fix use-after-free by nullifying timer pointer after free
+ - goldfish_rtc: Fix tick_offset migration
+ - target/riscv: throw debug exception before page fault
+ - target/riscv/debug.c: use wp size = 4 for 32-bit CPUs
+ - target/riscv: rvv: Fix unexpected behavior of vector reduction
+ instructions when vl is 0
+ - cryptodev/vhost: allocate CryptoDevBackendVhost using g_mem0()
+ - amd_iommu: Use correct bitmask to set capability BAR
+ - hw/i386/amd_iommu: Explicit use of AMDVI_BASE_ADDR in amdvi_init
+ - amd_iommu: Use correct DTE field for interrupt passthrough
+ - Kconfig: Extract CONFIG_USB_CHIPIDEA from CONFIG_IMX
+ - hw/intc/arm_gicv3_cpuif: Don't downgrade monitor traps for AArch32 EL3
+ - target/arm: Make CP_ACCESS_TRAPs to AArch32 EL3 be Monitor traps
+ - target/arm: Report correct syndrome for UNDEFINED LOR sysregs when NS=0
+ - target/arm: Report correct syndrome for UNDEFINED S1E2 AT ops at EL3
+ - target/arm: Report correct syndrome for UNDEFINED CNTPS_*_EL1
+ from EL2 and NS EL1
+ - target/sparc: Fix gdbstub incorrectly handling registers f32-f62
+ - ui/sdl2: reenable the SDL2 Windows keyboard hook procedure
+ - linux-user: Do not define struct sched_attr if libc headers do
+ * v7.2.16:
+ - Update version for 7.2.16 release
+ - hw/usb/canokey: Fix buffer overflow for OUT packet
+ - target/arm: arm_reset_sve_state() should set FPSR, not FPCR
+ - tests: acpi: update expected blobs
+ - pci: acpi: Windows 'PCI Label Id' bug workaround
+ - tests: acpi: whitelist expected blobs
+ - pci/msix: Fix msix pba read vector poll end calculation
+ - pci: ensure valid link status bits for downstream ports
+ - hw/usb/hcd-xhci-pci: Use modulo to select MSI vector as per spec
+ - backends/cryptodev-vhost-user: Fix local_error leaks
+ - target/i386/cpu: Fix notes for CPU models
+ - docs: Correct release of TCG trace-events removal
+ - s390x/s390-virtio-ccw: don't crash on weird RAM sizes
+ - meson.build: Disallow libnfs v6 to fix the broken macOS build
+ - hw/intc/arm_gicv3_its: Zero initialize local DTEntry etc structs
+ - x86/loader: only patch linux kernels
+ - fuzz: specify audiodev for usb-audio
+ - tcg/riscv: Fix StoreStore barrier generation
+ - hw/openrisc/openrisc_sim: keep serial@90000000 as default
+ - target/ppc: Fix non-maskable interrupt while halted
+ - tests/9p: also check 'Tgetattr' in 'use-after-unlink' test
+ - 9pfs: fix 'Tgetattr' after unlink
+ - 9pfs: remove obsolete comment in v9fs_getattr()
+ - tests/9p: add 'use-after-unlink' test
+ - tests/9p: add missing Rgetattr response name
+ - tests/9p: fix Rreaddir response name
+ - scsi: megasas: Internal cdbs have 16-byte length
+ - ssh: Do not switch session to non-blocking mode
+ - qdev: Fix set_pci_devfn() to visit option only once
+ - virtio-net: Fix size check in dhclient workaround
+ - cirrus-ci: Remove MSYS2 jobs duplicated with gitlab-ci
+ - hw/intc/loongarch_extioi: Use set_bit32() and clear_bit32() for s->isr
+ - bitops.h: Define bit operations on 'uint32_t' arrays
+ - hw/intc/openpic: Avoid taking address of out-of-bounds array index
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Sat, 03 May 2025 12:06:15 +0300
+
+qemu (1:7.2+dfsg-7+deb12u12) bookworm; urgency=medium
+
+ * mark-internal-codegen-functions-hidden.patch:
+ make GOT on AArch64 to fit. See comment in the patch for details.
+ * Revert "d/rules: disable capstone for static-user build on aarch64"
+ Re-enable capstone usage on aarch64, restore the status quo.
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Sat, 04 Jan 2025 17:47:54 +0300
+
+qemu (1:7.2+dfsg-7+deb12u11) bookworm; urgency=medium
+
+ * disable capstone for qemu-user-static buildi on arm64. See
+ https://gitlab.com/qemu-project/qemu/-/issues/1129 for details.
+ The choice is to disable either capstone or pie, and it is better
+ to keep pie enabled because it helps with guest/host address conflicts.
+ Capstone is used to produce disassembler output of guest code, it is
+ nice to have it but it is not required for normal operations.
+ * skip +deb12u11 release due to a typo
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Fri, 03 Jan 2025 19:53:54 +0300
+
+qemu (1:7.2+dfsg-7+deb12u9) bookworm; urgency=medium
+
+ * re-enable (upstream default) --static-pie linking for qemu-user-static
+ binaries. This has been disabled due to a mistake (LP:#1908331), has been
+ re-enabled in later debian qemu releases. Disabling static-pie leads to
+ qemu binaries using fixed address which has high chance to clash with
+ something in the emulated binary address space, and hence makes qemu-user
+ generally crashy. But this change has been forgotten in bookworm. With
+ recent bookworm kernel updates (6.1.112, with changes to KASLR), these
+ qemu-user-static crashes has become too common. Also add lintian-override
+ about not-static-enough binaries.
+ Closes: #1087822, #1053101
+ * update to upstream 7.2.15 stable/bugfix release, v7.2.15.diff,
+ https://gitlab.com/qemu-project/qemu/-/commits/v7.2.15 :
+ - Update version for 7.2.15 release
+ - usb-hub: Fix handling port power control messages
+ - hw/audio/hda: fix memory leak on audio setup
+ - hw/misc/mos6522: Fix bad class definition of the MOS6522 device
+ - tcg: Allow top bit of SIMD_DATA_BITS to be set in simd_desc()
+ - target/arm: Drop user-only special case in sve_stN_r
+ - linux-user: Fix setreuid and setregid to use direct syscalls
+ - target/i386: Fix legacy page table walk
+ - 9pfs: fix crash on 'Treaddir' request
+ - hw/nvme: fix handling of over-committed queues
+ - target/arm: Fix SVE SDOT/UDOT/USDOT (4-way, indexed)
+ - target/ppc: Set ctx->opcode for decode_insn32()
+ - target/riscv: Fix vcompress with rvv_ta_all_1s
+ - hw/intc/riscv_aplic: Check and update pending when write sourcecfg
+ - hw/intc/riscv_aplic: Fix in_clrip[x] read emulation
+ - target/riscv: Set vtype.vill on CPU reset
+ - hw/intc: Don't clear pending bits on IRQ lowering
+ - target/riscv: Correct SXL return value for RV32 in RV64 QEMU
+ - target/riscv/csr.c: Fix an access to VXSAT
+ - target/arm: Don't assert in regime_is_user() for E10 mmuidx values
+ - net/tap-win32: Fix gcc 14 format truncation errors
+ - Fix calculation of minimum in colo_compare_tcp
+ - gitlab: make check-[dco|patch] a little more verbose
+ - linux-user/ppc: Fix sigmask endianness issue in sigreturn
+ - target/i386: Walk NPT in guest real mode
+ - target/i386: Avoid unreachable variable declaration in mmu_translate()
+ - tcg: Reset data_gen_ptr correctly
+ - raw-format: Fix error message for invalid offset/size
+ - tests: Wait for migration completion on destination QEMU
+ to avoid failures
+ - KVM: Dynamic sized kvm memslots array
+ - hw/audio/hda: free timer on exit
+ - hw/intc/arm_gicv3_cpuif: Add cast to match the documentation
+ - scsi: fetch unit attention when creating the request
+ - linux-user: Fix parse_elf_properties GNU0_MAGIC check
+ - linux-user/flatload: Take mmap_lock in load_flt_binary()
+ - tracetool: avoid invalid escape in Python string
+ - fuzz: disable leak-detection for oss-fuzz builds
+ - block/reqlist: allow adding overlapping requests
+ - target/ppc: Fix lxvx/stxvx facility check
+ - softmmu/physmem.c: Keep transaction attribute in address_space_map()
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Mon, 25 Nov 2024 20:37:50 +0300
+
+qemu (1:7.2+dfsg-7+deb12u8) bookworm; urgency=medium
+
+ * update to upstream 7.2.14 stable/bugfix release, v7.2.14.diff,
+ https://gitlab.com/qemu-project/qemu/-/commits/v7.2.14 :
+ - Update version for 7.2.14 release
+ - hw/intc/arm_gic: fix spurious level triggered interrupts
+ - tests/docker: remove debian-armel-cross
+ - hw/display/vhost-user-gpu.c: fix vhost_user_gpu_chr_read()
+ - crypto: check gnutls & gcrypt support the requested pbkdf hash
+ - crypto: run qcrypto_pbkdf2_count_iters in a new thread
+ - softmmu/physmem: fix memory leak in dirty_memory_extend()
+ - gitlab: migrate the s390x custom machine to 22.04
+ - crypto/tlscredspsk: Free username on finalize
+ - module: Prevent crash by resetting local_err in module_load_qom_all()
+ - target/i386: Do not apply REX to MMX operands
+ - block/blkio: use FUA flag on write zeroes only if supported
+ - hw/core/ptimer: fix timer zero period condition for freq > 1GHz
+ - nbd/server: CVE-2024-7409: Avoid use-after-free when closing server
+ - nbd/server: CVE-2024-7409: Close stray clients at server-stop
+ - nbd/server: CVE-2024-7409: Drop non-negotiating clients
+ - nbd/server: CVE-2024-7409: Cap default max-connections to 100
+ - nbd/server: Plumb in new args to nbd_client_add()
+ - iotests: Add `vvfat` tests
+ - vvfat: Fix reading files with non-continuous clusters
+ - vvfat: Fix wrong checks for cluster mappings invariant
+ - vvfat: Fix usage of `info.file.offset`
+ - vvfat: Fix bug in writing to middle of file
+ - hw/sd/sdhci: Reset @data_count index on invalid ADMA transfers
+ - virtio-net: Fix network stall at the host side waiting for kick
+ - virtio-net: Ensure queue index fits with RSS
+ - target/arm: Handle denormals correctly for FMOPA (widening)
+ - hw/arm/mps2-tz.c: fix RX/TX interrupts order
+ - hw/i386/amd_iommu: Don't leak memory in amdvi_update_iotlb()
+ - docs/sphinx/depfile.py: Handle env.doc2path() returning a Path not a str
+ - target/arm: Ignore SMCR_EL2.LEN and SVCR_EL2.LEN if EL2 is not enabled
+ - target/arm: Avoid shifts by -1 in tszimm_shr() and tszimm_shl()
+ - target/arm: Fix UMOPA/UMOPS of 16-bit values
+ - target/arm: Don't assert for 128-bit tile accesses when SVL is 128
+ - hw/misc/bcm2835_property: Fix handling of FRAMEBUFFER_SET_PALETTE
+ - hw/char/bcm2835_aux: Fix assert when receive FIFO fills up
+ - target/rx: Use target_ulong for address in LI
+ - hw/virtio: Fix the de-initialization of vhost-user devices
+ - util/async.c: Forbid negative min/max
+ in aio_context_set_thread_pool_params()
+ - hw/intc/loongson_ipi: Access memory in little endian
+ - chardev/char-win-stdio.c: restore old console mode
+ - target/i386: do not crash if microvm guest uses SGX CPUID leaves
+ - intel_iommu: fix FRCD construction macro
+ - hw/cxl/cxl-host: Fix segmentation fault when getting cxl-fmw property
+ - hw/nvme: fix memory leak in nvme_dsm
+ - target/arm: Use FPST_F16 for SME FMOPA (widening)
+ - target/arm: Use float_status copy in sme_fmopa_s
+ - qapi/qom: Document feature unstable of @x-vfio-user-server
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Fri, 01 Nov 2024 16:50:46 +0300
+
+qemu (1:7.2+dfsg-7+deb12u7) bookworm; urgency=medium
+
+ * update to upstream 7.2.13 stable/bugfix release, v7.2.13.diff,
+ https://gitlab.com/qemu-project/qemu/-/commits/v7.2.13 :
+ - Update version for 7.2.13 release
+ - char-stdio: Restore blocking mode of stdout on exit
+ - virtio: remove virtio_tswap16s() call in vring_packed_event_read()
+ - block: Parse filenames only when explicitly requested
+ - iotests/270: Don't store data-file with json: prefix in image
+ - iotests/244: Don't store data-file with protocol in image
+ - qcow2: Don't open data_file with BDRV_O_NO_IO
+ (Closes: #1075824, CVE-2024-4467)
+ - target/arm: Fix VCMLA Dd, Dn, Dm[idx]
+ - i386/cpu: fixup number of addressable IDs for processor cores
+ in the physical package
+ - gitlab-ci: Disable the riscv64-debian-cross-container by default
+ - tests: don't run benchmarks for the tsan build
+ - tests: Update our CI to use CentOS Stream 9 instead of 8
+ - ci, docker: update CentOS and OpenSUSE Python to non-EOL versions
+ - Update lcitool and fedora to 37
+ - gitlab-ci.d/buildtest: Merge the --without-default-* jobs
+ - tcg/loongarch64: Fix tcg_out_movi vs some pcrel pointers
+ - linux-user: Make TARGET_NR_setgroups affect only the current thread
+ - stdvga: fix screen blanking
+ - virtio-net: drop too short packets early
+ - target/i386: fix size of EBP writeback in gen_enter()
+ * update to upstream 7.2.12 stable/bugfix release, v7.2.12.diff,
+ https://gitlab.com/qemu-project/qemu/-/commits/v7.2.12 :
+ - Update version for 7.2.12 release
+ - target/loongarch: fix a wrong print in cpu dump
+ - ui/sdl2: Allow host to power down screen
+ - target/i386: fix SSE and SSE2 feature check
+ - target/i386: fix xsave.flat from kvm-unit-tests
+ - disas/riscv: Decode all of the pmpcfg and pmpaddr CSRs
+ - hw/intc/riscv_aplic: APLICs should add child earlier than realize
+ - target/arm: Disable SVE extensions when SVE is disabled
+ - hw/intc/arm_gic: Fix handling of NS view of GICC_APR<n>
+ - hvf: arm: Fix encodings for ID_AA64PFR1_EL1 and debug System registers
+ - gitlab: Update msys2-64bit runner tags
+ - target/i386: no single-step exception after MOV or POP SS
+ - target/i386: disable jmp_opt if EFLAGS.RF is 1
+ - target-i386: hyper-v: Correct kvm_hv_handle_exit return value
+ - ui/gtk: Check if fence_fd is equal to or greater than 0
+ - ui/gtk: Fix mouse/motion event scaling issue with GTK display backend
+ - target/i386: rdpkru/wrpkru are no-prefix instructions
+ - target/i386: fix operand size for DATA16 REX.W POPCNT
+ - hw/remote/vfio-user: Fix config space access byte order
+ - target/i386: Give IRQs a chance when resetting HF_INHIBIT_IRQ_MASK
+ - hw/arm/npcm7xx: Store derivative OTP fuse key in little endian
+ - hw/dmax/xlnx_dpdma: fix handling of address_extension descriptor fields
+ - .gitlab-ci.d/cirrus.yml: Shorten the runtime of the macOS and FreeBSD jobs
+ - tests/avocado: update sunxi kernel from armbian to 6.6.16
+ - backends/cryptodev-builtin: Fix local_error leaks
+ - nbd/server: Mark negotiation functions as coroutine_fn
+ - nbd/server: do not poll within a coroutine context
+ - linux-user: do_setsockopt: fix SOL_ALG.ALG_SET_KEY
+ - gitlab/opensbi: Move to docker:stable
+ - gitlab-ci: Remove job building EDK2 firmware binaries
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Wed, 17 Jul 2024 14:27:14 +0300
+
+qemu (1:7.2+dfsg-7+deb12u6) bookworm; urgency=medium
+
+ * update to upstream 7.2.11 stable/bugfix release, v7.2.11.diff,
+ https://gitlab.com/qemu-project/qemu/-/commits/v7.2.11 :
+ - Update version for 7.2.11 release
+ - ppc/spapr: Initialize max_cpus limit to SPAPR_IRQ_NR_IPIS.
+ - ppc/spapr: Introduce SPAPR_IRQ_NR_IPIS to refer IRQ range for CPU IPIs.
+ - target/sh4: add missing CHECK_NOT_DELAY_SLOT
+ - hw/sd/sdhci: Do not update TRNMOD when Command Inhibit (DAT) is set
+ (Closes: #1068821, CVE-2024-3447)
+ - hw/net/lan9118: Replace magic '2048' value by MIL_TXFIFO_SIZE definition
+ - hw/net/lan9118: Fix overflow in MIL TX FIFO
+ - backends/cryptodev: Do not abort for invalid session ID
+ - hw/misc/applesmc: Fix memory leak in reset() handler
+ - hw/block/nand: Fix out-of-bound access in NAND block buffer
+ - hw/block/nand: Have blk_load() take unsigned offset and return boolean
+ - hw/block/nand: Factor nand_load_iolen() method out
+ - qemu-options: Fix CXL Fixed Memory Window interleave-granularity typo
+ - hw/virtio/virtio-crypto: Protect from DMA re-entrancy bugs
+ (Closes: #1068820, CVE-2024-3446)
+ - hw/char/virtio-serial-bus: Protect from DMA re-entrancy bugs
+ (Closes: #1068820, CVE-2024-3446)
+ - hw/display/virtio-gpu: Protect from DMA re-entrancy bugs
+ (Closes: #1068820, CVE-2024-3446)
+ - hw/virtio: Introduce virtio_bh_new_guarded() helper
+ - linux-user: Fix waitid return of siginfo_t and rusage
+ - tcg/optimize: Do not attempt to constant fold neg_vec
+ - hw/virtio: Fix packed virtqueue flush used_idx
+ - hw/net/virtio-net: fix qemu set used ring flag even vhost started
+ - hw/intc/arm_gicv3: ICC_HPPIR* return SPURIOUS if int group is disabled
+ - gitlab-ci/cirrus: switch from 'master' to 'latest'
+ - target/hppa: Clear psw_n for BE on use_nullify_skip path
+ - tcg/optimize: Fix sign_mask for logical right-shift
+ - virtio-net: Fix vhost virtqueue notifiers for RSS
+ - monitor/hmp-cmds-target: Append a space in error message in gpa2hva()
+ - hw/scsi/scsi-generic: Fix io_timeout property not applying
+ - target/loongarch: Fix qemu-system-loongarch64 assert failed
+ with the option '-d int'
+ - target/i386: Revert monitor_puts() in do_inject_x86_mce()
+ - target/i386: fix direction of "32-bit MMU" test
+ - target/i386: use separate MMU indexes for 32-bit accesses
+ - target/i386: introduce function to query MMU indices
+ - tests: Raise timeouts for bufferiszero and crypto-tlscredsx509
+ - tests/unit: Bump test-replication timeout to 60 seconds
+ - tests/unit: Bump test-crypto-block test timeout to 5 minutes
+ - tests/unit: Bump test-aio-multithread test timeout to 2 minutes
+ - migration: Skip only empty block devices
+ - hmat acpi: Fix out of bounds access due to missing use of indirection
+ - pcie_sriov: Validate NumVFs
+ (Closes: #1068819, CVE-2024-26327)
+ - hw/nvme: Use pcie_sriov_num_vfs()
+ (Closes: #1068819, CVE-2024-26328)
+ - pcie: Introduce pcie_sriov_num_vfs
+ - hw/nvme: add machine compatibility parameter to enable msix exclusive bar
+ - hw/nvme: generalize the mbar size helper
+ - hw/nvme: separate 'serial' property for VFs
+ - hw/nvme: cleanup error reporting in nvme_init_pci()
+ - hw/nvme: clean up confusing use of errp/local_err
+ - Avoid unaligned fetch in ladr_match()
+ - e1000e: fix link state on resume
+ - make-release: switch to .xz format by default
+ - hw/scsi/lsi53c895a: add timer to scripts processing
+ - hw/scsi/lsi53c895a: add missing decrement of reentrancy counter
+ - hw/scsi/lsi53c895a: stop script on phase mismatch
+ - system/qdev-monitor: move drain_call_rcu call
+ under if (!dev) in qmp_device_add()
+ - hw/rtc/sun4v-rtc: Relicense to GPLv2-or-later
+ - target/arm: Fix SME full tile indexing
+ - tests/tcg/aarch64/sysregs.c: Use S syntax for
+ id_aa64zfr0_el1 and id_aa64smfr0_el1
+ - target/arm: align exposed ID registers with Linux
+ - ui/cocoa: Fix window clipping on macOS 14
+ - gitlab: update FreeBSD Cirrus CI image to 13.3
+ * update to upstream 7.2.10 stable/bugfix release, v7.2.10.diff,
+ https://gitlab.com/qemu-project/qemu/-/commits/v7.2.10 :
+ - Update version for 7.2.10 release
+ - target/i386: the sgx_epc_get_section stub is reachable
+ - tests/unit/test-blockjob: Disable complete_in_standby test
+ - tests/qtest/display-vga-test: Add proper checks if a device is available
+ - test-vmstate: fix bad GTree usage, use-after-free
+ - tests/unit/test-util-sockets: Remove temporary file after test
+ - hw/usb/bus.c: PCAP adding 0xA in Windows version
+ - gitlab: force allow use of pip in Cirrus jobs
+ - tests/vm: avoid re-building the VM images all the time
+ - tests/vm: update openbsd image to 7.4
+ - target/i386: leave the A20 bit set in the final NPT walk
+ - target/i386: remove unnecessary/wrong application of the A20 mask
+ - target/i386: Fix physical address truncation
+ - target/i386: check validity of VMCB addresses
+ - target/i386: mask high bits of CR3 in 32-bit mode
+ - pl031: Update last RTCLR value on write in case it's read back
+ - hw/nvme: fix invalid endian conversion
+ - target/ppc: Fix lxv/stxv MSR facility check
+ - .gitlab-ci.d/windows.yml: Drop msys2-32bit job
+ - system/vl: Update description for input grab key
+ - docs/system: Update description for input grab key
+ - audio: Depend on dbus_display1_dep
+ - meson: ensure dbus-display generated code is built before other units
+ - ui/console: Fix console resize with placeholder surface
+ - ui/clipboard: add asserts for update and request
+ - ui/clipboard: mark type as not available when there is no data
+ (Closes: CVE-2023-6683, already fixed in debian)
+ - ui: reject extended clipboard message if not activated
+ - target/i386: Generate an illegal opcode exception on cmp instructions
+ with lock prefix
+ - i386/cpuid: Move leaf 7 to correct group
+ - i386/cpuid: Decrease cpuid_i when skipping CPUID leaf 1F
+ - i386/cpu: Mask with XCR0/XSS mask for FEAT_XSAVE_XCR0_HI and
+ FEAT_XSAVE_XSS_HI leafs
+ - i386/cpu: Clear FEAT_XSAVE_XSS_LO/HI leafs when CPUID_EXT_XSAVE
+ is not available
+ - iotests: Make 144 deterministic again
+ - target/arm: Don't get MDCR_EL2 in pmu_counter_enabled()
+ before checking ARM_FEATURE_PMU
+ - target/arm: Fix SVE/SME gross MTE suppression checks
+ - target/arm: Fix nregs computation in do_{ld,st}_zpa
+ - linux-user/aarch64: Choose SYNC as the preferred MTE mode
+ - tests/acpi: Update DSDT.cxl to reflect change _STA return value.
+ - hw/i386: Fix _STA return value for ACPI0017
+ - tests/acpi: Allow update of DSDT.cxl
+ - smmu: Clear SMMUPciBus pointer cache when system reset
+ - virtio_iommu: Clear IOMMUPciBus pointer cache when system reset
+ - hw/cxl: Pass CXLComponentState to cache_mem_ops
+ - cxl/cdat: Fix header sum value in CDAT checksum
+ - cxl/cdat: Handle cdat table build errors
+ - vhost-user.rst: Fix vring address description
+ - hw/smbios: Fix port connector option validation
+ - hw/smbios: Fix OEM strings table option validation
+ - pci-host: designware: Limit value range of iATU viewport register
+ - qemu-options.hx: Improve -serial option documentation
+ - system/vl.c: Fix handling of '-serial none -serial something'
+ - target/arm: fix exception syndrome for AArch32 bkpt insn
+ - block/blkio: Make s->mem_region_alignment be 64 bits
+ - qemu-docs: Update options for graphical frontends
+ - migration: Fix use-after-free of migration state object
+ * d/patches: remove
+ revert-monitor-only-run-coroutine-commands-in-qemu_aio_context.patch
+ This one turned out to be innocent, cryptsetup CI fails anyway.
+ * d/patches: remove now included upstream
+ ui-clipboard-mark-type-as-not-available-when-no-data-CVE-2023-6683.patch
+ * d/changelog: mention previous CVE fixes:
+ - CVE-2023-3019 fixed by 7.2+dfsg-7+deb12u4
+ - CVE-2024-24474 & CVE-2023-5088 fixed by 7.2+dfsg-7+deb12u3
+ - CVE-2023-3301 fixed by 7.2+dfsg-7+deb12u1
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Thu, 09 May 2024 08:44:38 +0300
+
+qemu (1:7.2+dfsg-7+deb12u5) bookworm; urgency=medium
+
+ * +revert-monitor-only-run-coroutine-commands-in-qemu_aio_context.patch
+ Revert a single upstream change in 7.2.9 which, while fixed a few qemu
+ lockup bugs, introduced a regression in suspend-resume-hibernate cycle
+ (triggered by cryptsetup autopkgtest)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Tue, 06 Feb 2024 20:38:06 +0300
+
+qemu (1:7.2+dfsg-7+deb12u4) bookworm; urgency=medium
+
+ [ Michael Tokarev ]
+ * update to upstream 7.2.9 stable/bugfix release, v7.2.9.diff,
+ https://gitlab.com/qemu-project/qemu/-/commits/v7.2.9 :
+ - Update version for 7.2.9 release
+ - target/xtensa: fix OOB TLB entry access
+ - qtest: bump aspeed_smc-test timeout to 6 minutes
+ - monitor: only run coroutine commands in qemu_aio_context
+ - iotests: port 141 to Python for reliable QMP testing
+ - iotests: add filter_qmp_generated_node_ids()
+ - block/blklogwrites: Fix a bug when logging "write zeroes" operations.
+ - virtio-net: correctly copy vnet header when flushing TX
+ Closes: CVE-2023-6693
+ - block/io: clear BDRV_BLOCK_RECURSE flag after recursing in
+ bdrv_co_block_status
+ - accel/tcg: Revert mapping of PCREL translation block to multiple
+ virtual addresses
+ - readthodocs: fully specify a build environment
+ - hw/scsi/esp-pci: set DMA_STAT_BCMBLT when BLAST command issued
+ - hw/scsi/esp-pci: synchronise setting of DMA_STAT_DONE with ESP
+ completion interrupt
+ - hw/scsi/esp-pci: generate PCI interrupt from separate ESP and PCI sources
+ - hw/scsi/esp-pci: use correct address register for PCI DMA transfers
+ - hw/pflash: implement update buffer for block writes
+ - hw/pflash: use ldn_{be,le}_p and stn_{be,le}_p
+ - hw/pflash: refactor pflash_data_write()
+ - target/i386: pcrel: store low bits of physical address in data[0]
+ - target/i386: fix incorrect EIP in PC-relative translation blocks
+ - target/i386: Do not re-compute new pc with CF_PCREL
+ - target/i386: Fix 32-bit wrapping of pc/eip computation
+ - load_elf: fix iterator's type for elf file processing
+ - .gitlab-ci.d/buildtest.yml: Work around htags bug when environment
+ is large
+ - target/s390x: Fix LAE setting a wrong access register
+ - hw/intc/arm_gicv3_cpuif: handle LPIs in the list registers
+ - chardev/char.c: fix "abstract device type" error message
+ - target/riscv: Fix mcycle/minstret increment behavior
+ - iotests: Basic tests for internal snapshots
+ - vl: Improve error message for conflicting -incoming and -loadvm
+ - block: Fix crash when loading snapshot on inactive node
+ * update to upstream 7.2.8 stable/bugfix release, v7.2.8.diff,
+ https://gitlab.com/qemu-project/qemu/-/commits/v7.2.8 :
+ - Update version for 7.2.8 release
+ - target/arm/helper: Propagate MDCR_EL2.HPMN into PMCR_EL0.N
+ - system/memory: use ldn_he_p/stn_he_p
+ - target/arm: Disable SME if SVE is disabled
+ - ui/vnc-clipboard: fix inflate_buffer
+ - ui/gtk-egl: move function calls back to regular code path
+ - ui/gtk-egl: Check EGLSurface before doing scanout
+ - msix: unset PCIDevice::msix_vector_poll_notifier in rollback
+ - hw/acpi/erst: Do not ignore Error* in realize handler
+ - pcie_sriov: Remove g_new assertion
+ - hw/audio/hda-codec: fix multiplication overflow
+ - hw/mips/malta: Fix the malta machine on big endian hosts
+ - vmdk: Don't corrupt desc file in vmdk_write_cid
+ - hw/virtio: Add VirtioPCIDeviceTypeInfo::instance_finalize field
+ - hw/nvram/xlnx-efuse-ctrl: Free XlnxVersalEFuseCtrl[] "pg0-lock" array
+ - hw/nvram/xlnx-efuse: Free XlnxEFuse::ro_bits[] array on finalize()
+ - hw/misc/mps2-scc: Free MPS2SCC::oscclk[] array on finalize()
+ - hw/virtio: Free VirtIOIOMMUPCI::vdev.reserved_regions[] on finalize()
+ - target/arm: Set IL bit for pauth, SVE access, BTI trap syndromes
+ - tests/avocado: Replace assertRegexpMatches() for Python 3.12 compatibility
+ - tests/avocado: Replace assertEquals() for Python 3.12 compatibility
+ - linux-user: Fix loaddr computation for some elf files
+ - net: Update MemReentrancyGuard for NIC
+ (Closes: #1041102, CVE-2023-3019)
+ - net: Provide MemReentrancyGuard * to qemu_new_nic()
+ - hw/ide/ahci: fix legacy software reset
+ - target/arm: Fix SME FMOPA (16-bit), BFMOPA
+ * remove patches included in 7.2.8:
+ - hw_mips_malta-Fix-malta-machine-on-big-endian-hosts.patch
+ - hw-ide-ahci-fix-legacy-software-reset.patch
+ * ui-clipboard-mark-type-as-not-available-when-no-data-CVE-2023-6683.patch
+ Closes: #1060749, CVE-2023-6683 (NULL deref in VNC clipboard code)
+
+ [ Sergio Durigan Junior ]
+ * d/rules: omit --no-start for qemu-guest-agent, this should
+ re-start it on upgrades. Closes: #1061588, #1061683
+ LP: #2028124
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Tue, 30 Jan 2024 19:15:04 +0300
+
+qemu (1:7.2+dfsg-7+deb12u3) bookworm; urgency=medium
+
+ * +hw-ide-ahci-fix-legacy-software-reset.patch - fix legacy ide regression
+ introduced in 7.2.6
+ * update to upstream 7.2.7 stable/bugfix release, v7.2.7.diff,
+ https://gitlab.com/qemu-project/qemu/-/commits/v7.2.7 :
+ - Update version for 7.2.7 release
+ - target/tricore: Rename tricore_feature
+ - tracetool: avoid invalid escape in Python string
+ - tests/tcg/s390x: Test LAALG with negative cc_src
+ - target/s390x: Fix LAALG not updating cc_src
+ - tests/qtest: ahci-test: add test exposing reset issue with pending callback
+ - hw/ide: reset: cancel async DMA operation before resetting state
+ (Closes: CVE-2023-5088)
+ - target/mips: Fix TX79 LQ/SQ opcodes
+ - target/mips: Fix MSA BZ/BNZ opcodes displacement
+ - ui/gtk-egl: apply scale factor when calculating window's dimension
+ - ui/gtk: force realization of drawing area
+ - ati-vga: Implement fallback for pixman routines
+ - block/nvme: nvme_process_completion() fix bound for cid
+ - target/arm: Correctly propagate stage 1 BTI guarded bit in a two-stage walk
+ - target/arm: Fix handling of SW and NSW bits for stage 2 walks
+ - target/arm: Don't allow stage 2 page table walks to downgrade to NS
+ - target/arm: Don't access TCG code when debugging with KVM
+ - Revert "linux-user: fix compat with glibc >= 2.36 sys/mount.h"
+ - Revert "linux-user: add more compat ioctl definitions"
+ - qemu-iotests: 024: add rebasing test case for overlay_size > backing_size
+ - qemu-img: rebase: stop when reaching EOF of old backing file
+ - tests/tcg: Add -fno-stack-protector
+ - tests/migration: Add -fno-stack-protector
+ - misc/led: LED state is set opposite of what is expected
+ - hw/sd/sdhci: Block Size Register bits [14:12] is lost
+ - lasips2: LASI PS/2 devices are not user-createable
+ - linux-user/sh4: Fix crashes on signal delivery
+ - linux-user/mips: fix abort on integer overflow
+ - migration: Fix analyze-migration read operation signedness
+ - hw/pvrdma: Protect against buggy or malicious guest driver
+ - disas/riscv: Fix the typo of inverted order of pmpaddr13 and pmpaddr14
+ - hw/audio/es1370: reset current sample counter
+ - migration/qmp: Fix crash on setting tls-authz with null
+ - amd_iommu: Fix APIC address check
+ - linux-user/hppa: Fix struct target_sigcontext layout
+ - chardev/char-pty: Avoid losing bytes when the other side just
+ (re-)connected
+ - hw/display/ramfb: plug slight guest-triggerable leak on mode setting
+ - target/i386: fix memory operand size for CVTPS2PD
+ - target/i386: generalize operand size "ph" for use in CVTPS2PD
+ - target/i386: Fix exception classes for MOVNTPS/MOVNTPD.
+ - target/i386: Fix exception classes for SSE/AVX instructions.
+ - target/i386: Fix and add some comments next to SSE/AVX instructions.
+ - tests/tcg/i386: correct mask for VPERM2F128/VPERM2I128
+ - target/i386: fix operand size of unary SSE operations
+ - scsi-disk: ensure that FORMAT UNIT commands are terminated
+ - esp: restrict non-DMA transfer length to that of available data
+ (Closes: CVE-2024-24474)
+ - esp: use correct type for esp_dma_enable() in sysbus_esp_gpio_demux()
+ - optionrom: Remove build-id section
+ - ui/vnc: fix handling of VNC_FEATURE_XVP
+ - ui/vnc: fix debug output for invalid audio message
+ - hw/scsi/scsi-disk: Disallow block sizes smaller than 512 [CVE-2023-42467]
+ - accel/tcg: mttcg remove false-negative halted assertion
+ - target/arm: Don't skip MTE checks for LDRT/STRT at EL0
+ - hw/cxl: Fix CFMW config memory leak
+ - linux-user/hppa: lock both words of function descriptor
+ - linux-user/hppa: clear the PSW 'N' bit when delivering signals
+ - hw/ppc: Always store the decrementer value
+ - target/ppc: Decrementer fix BookE semantics
+ - target/ppc: Sign-extend large decrementer to 64-bits
+ - hw/ppc: Avoid decrementer rounding errors
+ - hw/ppc: Round up the decrementer interval when converting to ns
+ - host-utils: Add muldiv64_round_up
+ - hw/ppc: Introduce functions for conversion between timebase and nanoseconds
+
+ * update to upstream 7.2.6 stable/bugfix release, v7.2.6.diff,
+ https://gitlab.com/qemu-project/qemu/-/commits/v7.2.6 :
+ - Update version for 7.2.6 release
+ - tpm: fix crash when FD >= 1024 and unnecessary errors due to EINTR
+ - s390x/ap: fix missing subsystem reset registration
+ - ui: fix crash when there are no active_console
+ - hw/tpm: TIS on sysbus: Remove unsupport ppi command line option
+ - target/riscv/pmp.c: respect mseccfg.RLB for pmpaddrX changes
+ - hw/riscv: virt: Fix riscv,pmu DT node path
+ - linux-user/riscv: Use abi type for target_ucontext
+ - hw/intc: Make rtc variable names consistent
+ - hw/intc: Fix upper/lower mtime write calculation
+ - hw/char/riscv_htif: Fix printing of console characters on big endian hosts
+ - arm64: Restore trapless ptimer access
+ - virtio: Drop out of coroutine context in virtio_load()
+ - qxl: don't assert() if device isn't yet initialized
+ - hw/net/vmxnet3: Fix guest-triggerable assert()
+ - docs tests: Fix use of migrate_set_parameter
+ - qemu-options.hx: Rephrase the descriptions of the -hd* and -cdrom options
+ - hw/i2c/aspeed: Fix TXBUF transmission start position error
+ - hw/i2c/aspeed: Fix Tx count and Rx size error in buffer pool mode
+ - hw/ide/ahci: fix broken SError handling
+ - hw/ide/ahci: fix ahci_write_fis_sdb()
+ - hw/ide/ahci: PxCI should not get cleared when ERR_STAT is set
+ - hw/ide/ahci: PxSACT and PxCI is cleared when PxCMD.ST is cleared
+ - hw/ide/ahci: simplify and document PxCI handling
+ - hw/ide/ahci: write D2H FIS when processing NCQ command
+ - hw/ide/core: set ERR_STAT in unsupported command completion
+ - target/ppc: Flush inputs to zero with NJ in ppc_store_vscr
+ - ppc/vof: Fix missed fields in VOF cleanup
+ - hw/ppc/e500: fix broken snapshot replay
+ - block-migration: Ensure we don't crash during migration cleanup
+ - docs/about/license: Update LICENSE URL
+ - target/arm: Fix 64-bit SSRA
+ - target/arm: Fix SME ST1Q
+ - accel/kvm: Specify default IPA size for arm64
+ - kvm: Introduce kvm_arch_get_default_type hook
+ - include/hw/virtio/virtio-gpu: Fix virtio-gpu with blob on big endian hosts
+ - target/s390x: Check reserved bits of VFMIN/VFMAX's M5
+ - target/s390x: Fix VSTL with a large length
+ - target/s390x: Use a 16-bit immediate in VREP
+ - target/s390x: Fix the "ignored match" case in VSTRS
+ - Fixed incorrect LLONG alignment for openrisc and cris
+ - include/exec/user: Set ABI_LLONG_ALIGNMENT to 4 for nios2
+ - include/exec/user: Set ABI_LLONG_ALIGNMENT to 4 for microblaze
+ - linux-user/elfload: Set V in ELF_HWCAP for RISC-V
+ - hw/nvme: fix CRC64 for guard tag
+ - dump: kdump-zlib data pages not dumped with pvtime/aarch64
+ - hw/smbios: Fix core count in type4
+ - hw/smbios: Fix thread count in type4
+ - hw/smbios: Fix smbios_smp_sockets caculation
+ - machine: Add helpers to get cores/threads per socket
+ - pnv_lpc: disable reentrancy detection for lpc-hc
+ - loongarch: mark loongarch_ipi_iocsr re-entrnacy safe
+ - apic: disable reentrancy detection for apic-msi
+ - raven: disable reentrancy detection for iomem
+ - bcm2835_property: disable reentrancy detection for iomem
+ - lsi53c895a: disable reentrancy detection for MMIO region, too
+ - lsi53c895a: disable reentrancy detection for script RAM
+ - hw: replace most qemu_bh_new calls with qemu_bh_new_guarded
+ - checkpatch: add qemu_bh_new/aio_bh_new checks
+ - async: avoid use-after-free on re-entrancy guard
+ - async: Add an optional reentrancy guard to the BH API
+ - memory: prevent dma-reentracy issues
+ - python: drop pipenv
+ - gitlab-ci: check-dco.py: switch from master to stable-7.2 branch
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Sun, 03 Dec 2023 15:36:08 +0300
+
+qemu (1:7.2+dfsg-7+deb12u2) bookworm; urgency=medium
+
+ * d/rules: add the forgotten --enable-virtfs for the xen build.
+ This makes 9pfs virtual filesystem available for xen hvm domUs.
+ This adds no new runtime dependencies. Closes: #1049925.
+ * update to upstream 7.2.5 stable/bugfix release, v7.2.5.diff,
+ https://gitlab.com/qemu-project/qemu/-/commits/v7.2.5 :
+ - hw/ide/piix: properly initialize the BMIBA register
+ - ui/vnc-clipboard: fix infinite loop in inflate_buffer (CVE-2023-3255)
+ - qemu-nbd: pass structure into nbd_client_thread instead of plain char*
+ - qemu-nbd: fix regression with qemu-nbd --fork run over ssh
+ - qemu-nbd: regression with arguments passing into nbd_client_thread()
+ - target/s390x: Make CKSM raise an exception if R2 is odd
+ - target/s390x: Fix CLM with M3=0
+ - target/s390x: Fix CONVERT TO LOGICAL/FIXED with out-of-range inputs
+ - target/s390x: Fix ICM with M3=0
+ - target/s390x: Make MC raise specification exception when class >= 16
+ - target/s390x: Fix assertion failure in VFMIN/VFMAX with type 13
+ - target/loongarch: Fix the CSRRD CPUID instruction on big endian hosts
+ - virtio-pci: add handling of PCI ATS and Device-TLB enable/disable
+ - vhost: register and change IOMMU flag depending on Device-TLB state
+ - virtio-net: pass Device-TLB enable/disable events to vhost
+ - hw/arm/smmu: Handle big-endian hosts correctly
+ - target/arm: Avoid writing to constant TCGv in trans_CSEL()
+ - target/ppc: Disable goto_tb with architectural singlestep
+ - linux-user/armeb: Fix __kernel_cmpxchg() for armeb
+ - qga/win32: Use rundll for VSS installation
+ - thread-pool: signal "request_cond" while locked
+ - xen-block: Avoid leaks on new error path
+ - io: remove io watch if TLS channel is closed during handshake
+ - target/nios2: Pass semihosting arg to exit
+ - target/nios2: Fix semihost lseek offset computation
+ - target/m68k: Fix semihost lseek offset computation
+ - hw/virtio-iommu: Fix potential OOB access in virtio_iommu_handle_command()
+ - virtio-crypto: verify src&dst buffer length for sym request
+ - target/hppa: Move iaoq registers and thus reduce generated code size
+ - pci: do not respond config requests after PCI device eject
+ - hw/i386/intel_iommu: Fix trivial endianness problems
+ - hw/i386/intel_iommu: Fix endianness problems related to VTD_IR_TableEntry
+ - hw/i386/intel_iommu: Fix struct VTDInvDescIEC on big endian hosts
+ - hw/i386/intel_iommu: Fix index calculation in vtd_interrupt_remap_msi()
+ - hw/i386/x86-iommu: Fix endianness issue in x86_iommu_irq_to_msi_message()
+ - include/hw/i386/x86-iommu: Fix struct X86IOMMU_MSIMessage for big endian hosts
+ - vfio/pci: Disable INTx in vfio_realize error path
+ - vdpa: Fix possible use-after-free for VirtQueueElement
+ - vdpa: Return -EIO if device ack is VIRTIO_NET_ERR in _load_mac()
+ - vdpa: Return -EIO if device ack is VIRTIO_NET_ERR in _load_mq()
+ - target/ppc: Implement ASDR register for ISA v3.0 for HPT
+ - target/ppc: Fix pending HDEC when entering PM state
+ - target/ppc: Fix VRMA page size for ISA v3.0
+ - target/i386: Check CR0.TS before enter_mmx
+ - Update version for 7.2.5 release
+ Closes: CVE-2023-3255, CVE-2023-3354, CVE-2023-3180
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Thu, 17 Aug 2023 12:33:57 +0300
+
+qemu (1:7.2+dfsg-7+deb12u1) bookworm; urgency=medium
+
+ * d/rules: add the forgotten --enable-libusb for the xen build.
+ This makes usb devices available for xen hvm domUs again,
+ as it has always been before. Closes: #1037341
+ * update to upstream 7.2.3 stable/bugfix release, v7.2.3.diff,
+ https://gitlab.com/qemu-project/qemu/-/commits/v7.2.3 :
+ - vnc: avoid underflow when accessing user-provided address
+ - target/i386: Change wrong XFRM value in SGX CPUID leaf
+ (was in debian already)
+ - acpi: pcihp: allow repeating hot-unplug requests
+ - qemu-options: finesse the recommendations around -blockdev
+ - docs/about/deprecated.rst: Add "since 7.1" tag to dtb-kaslr-seed
+ deprecation
+ - target/arm: Initialize debug capabilities only once
+ - hw/net/msf2-emac: Don't modify descriptor in-place in emac_store_desc()
+ - hw/arm/boot: Make write_bootloader() public as arm_write_bootloader()
+ - hw/arm/aspeed: Use arm_write_bootloader() to write the bootloader
+ - hw/arm/raspi: Use arm_write_bootloader() to write boot code
+ - hw/intc/allwinner-a10-pic: Don't use set_bit()/clear_bit()
+ - target/arm: Define and use new load_cpu_field_low32()
+ - hw/sd/allwinner-sdhost: Correctly byteswap descriptor fields
+ - hw/net/allwinner-sun8i-emac: Correctly byteswap descriptor fields
+ - softfloat: Fix the incorrect computation in float32_exp2
+ - meson: leave unnecessary modules out of the build
+ - block: Fix use after free in blockdev_mark_auto_del()
+ - target/riscv: Fix itrigger when icount is used
+ - accel/tcg: Fix atomic_mmu_lookup for reads
+ - ui: Fix pixel colour channel order for PNG screenshots
+ - async: Suppress GCC13 false positive in aio_bh_poll()
+ - tcg: ppc64: Fix mask generation for vextractdm
+ - hw/virtio/vhost-user: avoid using uninitialized errp
+ - virtio: fix reachable assertion due to stale value of cached region size
+ - block/monitor: Fix crash when executing HMP commit
+ - target/s390x: Fix EXECUTE of relative branches
+ - s390x/tcg: Fix LDER instruction format
+ - 9pfs/xen: Fix segfault on shutdown
+ - xen/pt: reserve PCI slot 2 for Intel igd-passthru
+ - Revert "vhost-user: Monitor slave channel in vhost_user_read()"
+ - Revert "vhost-user: Introduce nested event loop in vhost_user_read()"
+ - target/ppc: Fix helper_pminsn() prototype
+ - tests/docker: bump the xtensa base to debian:11-slim
+ - linux-user: Fix mips fp64 executables loading
+ - linux-user: fix getgroups/setgroups allocations
+ (was in debian already)
+ - migration: Handle block device inactivation failures better
+ - migration: Minor control flow simplification
+ - migration: Attempt disk reactivation in more failure scenarios
+ - target/arm: Fix vd == vm overlap in sve_ldff1_z
+ - scsi-generic: fix buffer overflow on block limits inquiry
+ - target/i386: fix operand size for VCOMI/VUCOMI instructions
+ - target/i386: fix avx2 instructions vzeroall and vpermdq
+ - vhost: fix possible wrap in SVQ descriptor ring
+ - virtio-net: not enable vq reset feature unconditionally
+ - virtio-crypto: fix NULL pointer dereference in virtio_crypto_free_request
+ - e1000: Count CRC in Tx statistics
+ - e1000e: Fix tx/rx counters
+ - rtl8139: fix large_send_mss divide-by-zero
+ (was in debian already)
+ - util/vfio-helpers: Use g_file_read_link()
+ - usb/ohci: Set pad to 0 after frame update
+ - hw/scsi/lsi53c895a: Fix reentrancy issues in the LSI controller
+ (Closes: #1029155, CVE-2023-0330)
+ - machine: do not crash if default RAM backend name has been stolen
+ - Update version for 7.2.3 release
+ * update to upstream 7.2.4 stable/bugfix release, v7.2.4.diff,
+ https://gitlab.com/qemu-project/qemu/-/commits/v7.2.4 :
+ - gitlab-ci: Avoid to re-run "configure" in the device-crash-test jobs
+ - scripts/device-crash-test: Add a parameter to run with TCG only
+ - hw/ppc/prep: Fix wiring of PIC -> CPU interrupt
+ - ui/gtk: fix passing y0_top parameter to scanout
+ - ui/gtk: use widget size for cursor motion event
+ - ui/gtk-egl: fix scaling for cursor position in scanout mode
+ - ui/sdl2: fix surface_gl_update_texture: Assertion 'gls' failed
+ - ui/sdl2: Grab Alt+Tab also in fullscreen mode
+ - ui/sdl2: Grab Alt+F4 also under Windows
+ - ui/sdl2: disable SDL_HINT_GRAB_KEYBOARD on Windows
+ - hw/dma/xilinx_axidma: Check DMASR.HALTED to prevent infinite loop.
+ - hw/arm/xlnx-zynqmp: fix unsigned error when checking the RPUs number
+ - target/arm: Explicitly select short-format FSR for M-profile
+ - target/s390x: Fix LCBB overwriting the top 32 bits
+ - tests/tcg/s390x: Test LCBB
+ - target/s390x: Fix LOCFHR taking the wrong half of R2
+ - tests/tcg/s390x: Test LOCFHR
+ - linux-user/s390x: Fix single-stepping SVC
+ - tests/tcg/s390x: Test single-stepping SVC
+ - s390x/tcg: Fix CPU address returned by STIDP
+ - docs: fix multi-process QEMU documentation
+ - qga: Fix suspend on Linux guests without systemd
+ - 9pfs: prevent opening special files (CVE-2023-2861)
+ - hw/remote: Fix vfu_cfg trace offset format
+ - vnc: move assert in vnc_worker_thread_loop
+ - target/ppc: Fix lqarx to set cpu_reserve
+ - target/ppc: Fix nested-hv HEAI delivery
+ - target/ppc: Fix PMU hflags calculation
+ - hw/riscv: qemu crash when NUMA nodes exceed available CPUs
+ - aspeed/hace: Initialize g_autofree pointer
+ - target/arm: Fix return value from LDSMIN/LDSMAX 8/16 bit atomics
+ - target/arm: Return correct result for LDG when ATA=0
+ - hw/intc/allwinner-a10-pic: Handle IRQ levels other than 0 or 1
+ - hw/timer/nrf51_timer: Don't lose time when timer is queried in tight loop
+ - host-utils: Avoid using __builtin_subcll on buggy versions of Apple Clang
+ - pc-bios/keymaps: Use the official xkb name for Arabic layout,
+ not the legacy synonym
+ - target/hppa: Fix OS reboot issues
+ - target/hppa: Provide qemu version via fw_cfg to firmware
+ - target/hppa: New SeaBIOS-hppa version 7
+ (minus the binary pc-bios/hppa-firmware.img changes)
+ - target/hppa: Update to SeaBIOS-hppa version 8
+ (minus the binary pc-bios/hppa-firmware.img changes)
+ - vhost: release memory_listener object in error path
+ - vdpa: fix not using CVQ buffer in case of error
+ - vhost-vdpa: do not cleanup the vdpa/vhost-net structures if peer nic
+ is present
+ (Closes: CVE-2023-3301)
+ - virtio-gpu: Make non-gl display updates work again when blob=true
+ - icount: don't adjust virtual time backwards after warp
+ - vdpa: mask _F_CTRL_GUEST_OFFLOADS for vhost vdpa devices
+ - target/ppc: Fix decrementer time underflow and infinite timer loop
+ - vfio/pci: Fix a segfault in vfio_realize
+ - vfio/pci: Call vfio_prepare_kvm_msi_virq_batch() in MSI retry path
+ - ui/gtk: set the area of the scanout texture correctly
+ - Update version for 7.2.4 release
+ * remove patches included in v7.2.4:
+ - linux-user-fix-getgroups-setgroups-allocations.patch
+ - rtl8139-fix-large_send_mss-divide-by-zero.patch
+ - target_i386-Change-wrong-XFRM-value.patch
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Tue, 11 Jul 2023 23:07:58 +0300
+
+qemu (1:7.2+dfsg-7) unstable; urgency=medium
+
+ * d/control: qemu-system-xen: add ipxe-qemu dependency (#1035676)
+
+ When installing qemu-system-xen on a new system, the boot roms are
+ not installed. Unfortunately this means HVM Xen DomUs can not be used
+ at all, because the boot roms are hard requiriment for qemu since 2014,
+ it fails to start without the boot roms even if (network) booting is
+ not requested.
+
+ Before bookworm, when qemu-system-xen was part of regular
+ qemu-system-x86 package, the dependency on ipxe-qemu was coming from
+ that package. But when splitting qemu-system-xen out of it, we forgot
+ that the boot roms are hard dependency now. This makes qemu-system-xen
+ unusable on a new install until ipxe-qemu is installed too.
+
+ An alternative would be to revert upstream commit 178e785fb
+ (from 2014) to make rom loading failure a non-fatal error.
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Sun, 14 May 2023 11:29:12 +0300
+
+qemu (1:7.2+dfsg-6) unstable; urgency=medium
+
+ [ Michael Tokarev ]
+ * sync with upstream v7.2.1 stable release, into d/patches/v7.2.1.diff.
+ All patches from 7.2.1 (besides stuff not relevant for linux, such
+ as mingw compilation fixes) has already been in d/patches/master/,
+ now they're in single upstream patch file
+ * v7.2.2.diff: upstream 7.2.2 stable/bugfix release
+ * hw-pvrdma-protect-against-guest-driver-CVE-2022-1050.patch:
+ remove, included in v7.2.2
+ * d/rules, d/qemu.desktop: provide an icon for gtk display (qemu.display)
+ * d/gbp.conf: set debian branch to debian-bookworm
+ * pick 3 more fixes from qemu-devel@:
+ rtl8139-fix-large_send_mss-divide-by-zero.patch
+ target_i386-Change-wrong-XFRM-value.patch
+ hw_mips_malta-Fix-malta-machine-on-big-endian-hosts.patch
+ * +linux-user-fix-getgroups-setgroups-allocations.patch (Closes: #811087)
+
+ [ Vagrant Cascadian ]
+ * debian/rules: Use 'printf' instead of 'echo' to avoid differences
+ in underlying /bin/sh implementations. Closes: #1034431
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Sat, 29 Apr 2023 13:02:55 +0300
+
+qemu (1:7.2+dfsg-5) unstable; urgency=medium
+
+ * d/qemu-guest-agent.udev: fix missing comma
+ (Christian Schneider <debian@c-schneider.net>, Closes: #1031838)
+ * remove qemu-make-debian-root.
+ Ths script debian/qemu-make-debian-root has been broken for ages.
+ In 2023, it creates /etc/fstab with a reference to /dev/hda1, and
+ edits /etc/inittab which does not exist. And no one noticed, - so
+ it's safe to assume it is not used anymore. Just remove it.
+ * re-pick qemu-stable patches from master (the same patch contents):
+ master/tests-tcg-i386-Introduce-and-use-reg_t-consistently.patch
+ master/target-i386-Fix-BEXTR-instruction.patch
+ master/target-i386-Fix-C-flag-for-BLSI-BLSMSK-BLSR.patch
+ master/target-i386-fix-ADOX-followed-by-ADCX.patch
+ * 20 more changes picked from upstream/master:
+ master/target-i386-Fix-BZHI-instruction.patch
+ master/block-iscsi-fix-double-free-on-BUSY-or-similar-status.patch
+ master/hw-smbios-fix-field-corruption-in-type-4-table.patch
+ master/Revert-x86-do-not-re-randomize-RNG-seed-on-snapshot-.patch
+ master/Revert-x86-re-initialize-RNG-seed-when-selecting-ker.patch
+ master/Revert-x86-reinitialize-RNG-seed-on-system-reboot.patch
+ master/Revert-x86-use-typedef-for-SetupData-struct.patch
+ master/Revert-x86-return-modified-setup_data-only-if-read-a.patch
+ master/Revert-hw-i386-pass-RNG-seed-via-setup_data-entry.patch
+ master/vhost-user-gpio-Configure-vhost_dev-when-connecting.patch
+ master/vhost-user-i2c-Back-up-vqs-before-cleaning-up-vhost_.patch
+ master/vhost-user-rng-Back-up-vqs-before-cleaning-up-vhost_.patch
+ master/virtio-rng-pci-fix-migration-compat-for-vectors.patch
+ master/virtio-rng-pci-fix-transitional-migration-compat-for.patch
+ master/hw-timer-hpet-Fix-expiration-time-overflow.patch
+ master/vdpa-stop-all-svq-on-device-deletion.patch
+ master/vhost-avoid-a-potential-use-of-an-uninitialized-vari.patch
+ master/libvhost-user-check-for-NULL-when-allocating-a-virtq.patch
+ master/chardev-char-socket-set-s-listener-NULL-in-char_sock.patch
+ master/intel-iommu-fail-MAP-notifier-without-caching-mode.patch
+ master/intel-iommu-fail-DEVIOTLB_UNMAP-without-dt-mode.patch
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Sun, 05 Mar 2023 20:09:04 +0300
+
+qemu (1:7.2+dfsg-4) unstable; urgency=medium
+
+ * block-fix-detect-zeroes-with-BDRV_REQ_REGISTERED_BUF.patch:
+ re-pick now from master (the same patch, moved to master/).
+ * revert x86-don-t-let-decompressed-kernel-image-clobber-setu.patch
+ Closes: ##1031682 .
+ This turned out to be wrong move, breaking more stuff than fixing.
+ Upstream is going to revert it too.
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Mon, 20 Feb 2023 21:00:18 +0300
+
+qemu (1:7.2+dfsg-3) unstable; urgency=medium
+
+ [ Paride Legovini ]
+ * Disable LTO on non-amd64 builds (LP: #1921664)
+
+ [ Michael Tokarev ]
+ * target-arm-Fix-physical-address-resolution-for-Stage2.patch:
+ re-fetch now from master branch
+ * 4 more patches picked from master:
+ x86-don-t-let-decompressed-kernel-image-clobber-setu.patch
+ migration-ram-Fix-error-handling-in-ram_write_tracki.patch
+ migration-ram-Fix-populate_read_range.patch
+ qcow2-Fix-theoretical-corruption-in-store_bitmap-err.patch
+ * 5 fixes picked from current pullreqs:
+ block-fix-detect-zeroes-with-BDRV_REQ_REGISTERED_BUF.patch
+ tests_tcg_i386-introduce-and-use-reg_t-consistently.patch
+ target_i386-fix-BEXTR-instruction.patch
+ target_i386-fix-C-flag-for-BLSI-BLSMSK-BLSR.patch
+ target_i386-fix-ADOX-followed-by-ADCX.patch
+ * disable dwz on certain architectures for older dwz
+ (FTBFS on bullseye, #968670)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Fri, 10 Feb 2023 14:29:12 +0300
+
+qemu (1:7.2+dfsg-2) unstable; urgency=medium
+
+ * d/rules: add -ffile-prefix-map when building skiboot
+ * d/control: provide qemu-kvm in qemu-system-misc on s390x
+ (Closes: #1029309)
+ * d/control: drop dependency of qemu-guest-agent on lsb-base
+ * Picked patches from qemu master branch tagged for qemu-stable
+ up to commit deabea6e88 (2023-02-02):
+ target-sh4-Mask-restore-of-env-flags-from-tb-flags.patch
+ vhost-fix-vq-dirty-bitmap-syncing-when-vIOMMU-is-ena.patch
+ virtio-mem-Fix-the-bitmap-index-of-the-section-offse.patch
+ virtio-mem-Fix-the-iterator-variable-in-a-vmem-rdl_l.patch
+ target-arm-fix-handling-of-HLT-semihosting-in-system.patch
+ meson-accept-relative-symlinks-in-meson-introspect-i.patch
+ target-riscv-Set-pc_succ_insn-for-rvc-illegal-insn.patch
+ acpi-cpuhp-fix-guest-visible-maximum-access-size-to-.patch
+ hw-nvme-fix-missing-endian-conversions-for-doorbell-.patch
+ hw-nvme-fix-missing-cq-eventidx-update.patch
+ configure-fix-GLIB_VERSION-for-cross-compilation.patch
+ target-arm-Fix-sve_probe_page.patch
+ target-arm-allow-writes-to-SCR_EL3.HXEn-bit-when-FEA.patch
+ target-arm-Fix-in_debug-path-in-S1_ptw_translate.patch
+ * Also: target-arm-Fix-physical-address-resolution-for-Stage.patch
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Thu, 02 Feb 2023 21:17:10 +0300
+
+qemu (1:7.2+dfsg-1) unstable; urgency=medium
+
+ * new upstream release
+ Closes: #1025123 CVE-2022-4172
+ (erst: undefined behavior in memcpy in write_erst_record)
+ Closes: #1021981 qemu-user: faccessat2 is not implemented
+ Closes: #1021019 CVE-2022-3165 (VNC: integer underflow in
+ vnc_client_cut_text_ext leads to CPU exhaustion)
+ * remove patches applied upstream
+ * refresh note-missing-module-pkg-name.diff
+ * slirp is always external package now, not a submodule anymore
+ * d/control: require meson >> 0.61.5~ for build
+ * spelling.diff: update with more spelling error
+ * add some lintian-overrides
+ * fix minor spelling errors in patches
+ * d/control: Bump Standards-Version to 4.6.1
+ * debian shell programs use "which" instead of the "command -v",
+ fix that (Closes: #1018254)
+ * Better fix for #1019011 (gcc ICE building palcode-clipper), use -O1
+ instead of -O2 for the failing compile when it actually fails
+ (no need to depend on gcc-11, Closes: #1011003)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Thu, 15 Dec 2022 17:17:28 +0300
+
+qemu (1:7.1+dfsg-2) unstable; urgency=medium
+
+ * tulip-restrict-DMA-engine-to-memories-CVE-2022-2962.patch
+ fix possible stack or heap overflow (tulip: DMA reentrancy issue)
+ Closes: #1018055, CVE-2022-2962
+ * hw-pvrdma-protect-against-guest-driver-CVE-2022-1050.patch
+ fix possible use-after-free in paravirtual RDMA device.
+ Closes: #1014589, CVE-2022-1050
+ * mention closing of #979677 (CVE-2020-14394) by 7.1
+ * d/rules: parametrify extra-cflags & extra-ldflags
+ * d/rules: explicitly disable pie on arm64 due to
+ https://sourceware.org/bugzilla/show_bug.cgi?id=29514
+ Fixes FTBFS.
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Tue, 13 Sep 2022 20:08:43 +0300
+
+qemu (1:7.1+dfsg-1) unstable; urgency=medium
+
+ * new upstream release (7.1)
+ Closes: #1014958, CVE-2022-35414
+ Closes: #1014590, CVE-2022-0216
+ Closes: #979677, CVE-2020-14394
+ Closes: #987410, CVE-2021-3507
+ Closes: #988333, #1018913
+ * d/copyright:
+ - remove mentions of slirp (packaged separately)
+ - blindly convert to dep-5 (it needs a complete rewrite)
+ - add Files-Excluded from d/get-orig-source.sh
+ * d/gbp.conf: remove filter= (and whole [import-orig])
+ * d/watch: verify upstream tarballs
+ * d/rules: stop faking skiboot version, it is now properly included in
+ roms/skiboot/.version file. Add a dependency on this file too
+ * d/patches:
+ - remove use-fixed-data-path.patch: not needed anymore
+ - linux-user-binfmt-P.diff: refresh
+ - remove patches applied upstream
+ * d/control:
+ - it is --enable-capstone now, not --enable-capstone=system
+ - it is --enable-png now, not --enable-vnc-png
+ * d/rules: fix --enable-vhost-* options
+ * d/rules: remove vnc-png for xen too
+ * openbios-array-bounds-gcc12.patch
+ * opensbi-fix-build-with-binutils-2.38.patch
+ * d/rules: adopt vof build changes
+ * d/qemu-system-data.docs: omit ccid.txt (removed)
+ * temporary workaround for gcc-12 bug #1019011: use gcc-11-alpha-linux-gnu
+ instead of gcc-alpha-linux-gnu (another option is to use -Os)
+ * d/control: temporarily build-depend on libva-dev till #1019485 is fixed
+ * add loongarch64 qemu-user and qemu-user arch
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Mon, 12 Sep 2022 11:50:53 +0300
+
+qemu (1:7.0+dfsg-7) unstable; urgency=medium
+
+ * d/tests/test-qemu-user: rework ls/glob test a bit
+ * d/tests/test-qemu-user: fix ppc64le qemu architecture name
+ * d/binfmt-install: use proper name for binfmt.d (*.conf)
+ Hopefully closes: #1011003
+ * two virtio-scsi bugfixes from upstream:
+ virtio-scsi-fix-ctrl-and-event-handler-functions-in-dataplane.patch
+ virtio-scsi-don-t-waste-CPU-polling-the-event-virtqueue.patch
+ * 3 patches from upstream to fix possible coroutine crashes:
+ coroutine-use-QEMU_DEFINE_STATIC_CO_TLS.patch
+ coroutine-rename-qemu_coroutine_inc-dec_pool_size.patch
+ coroutine-revert-to-constant-batch-size.patch
+ * target-i386-do-not-consult-nonexistent-host-leaves.patch
+ * d/control: stop suggesting sudo for qemu-user-static
+ * Revert "d/rules: do not try to enable tcg-interpreter on unsupported
+ targets, it does not help anymore" - it does help but it needs a bit
+ more work
+ * disable xen support for qemu-system-x86 build and create a wrapper
+ for -i386 to redirect xen-related usage to xen-specific binary
+ with a warning (for bookworm only)
+ * common-user-no-user.patch: fix one of FTBFS on unsupported architectures
+ * d/rules: use regular variable assignment for BUILD_PACKAGES
+ * two trivial patches to fix spelling in roms:
+ openbios-spelling-endianess.patch
+ slof-spelling-seperator.patch
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Sun, 15 May 2022 15:49:12 +0300
+
+qemu (1:7.0+dfsg-6) unstable; urgency=medium
+
+ * d/rules: the forgotten --enable-xen-pci-passthrough for the xen build
+ * d/tests/test-qemu-user: rewrite to be more robust and complete and
+ include test for qemu-user-static too.
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Mon, 09 May 2022 01:37:56 +0300
+
+qemu (1:7.0+dfsg-5) unstable; urgency=medium
+
+ * d/tests/test-qemu-user.sh: more arch-specific debugging/updates
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Sat, 07 May 2022 12:22:26 +0300
+
+qemu (1:7.0+dfsg-4) unstable; urgency=medium
+
+ * d/tests/: fix failing tests.
+ - test-qemu-user: depend on gcc for dpkg-architecture to work,
+ and print debugging info for future switch to uname -m
+ - test-qemu-img: switch from using file to qemu-img info
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Sat, 07 May 2022 11:33:23 +0300
+
+qemu (1:7.0+dfsg-3) unstable; urgency=medium
+
+ [ Michael Tokarev ]
+ * d/binfmt-install: also generate binfmt.d/ entries for systemd
+ * d/control: use systemd as preferred alternative to binfmt-support
+ hopefully Closes: #789011 (Minimal dependencies to register binfmt)
+ Closes: #985889 (make binfmt setup configurable)
+ * d/control: remove Riku Voipio from Uploaders. Thank you Riku!
+ * d/rules: simplify DEB_BUILD_OPTIONS=parallel=N parsing
+
+ [ Guido Günther ]
+ * Add minimal autopkgtest (Closes: #832982)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Sat, 07 May 2022 00:03:24 +0300
+
+qemu (1:7.0+dfsg-2) unstable; urgency=medium
+
+ * d/control: add Rules-Requires-Root: no
+ * d/control: switch to debhelper-compat=13
+ * d/control: drop "qemu" empty/dummy pseudopackage
+ * d/control: do not build linux-user* on ia64 and powerpc
+ (not supported by upstream anymore)
+ * d/control: add Breaks for qemu-system-data for other packages from which
+ it borrowed files in the past (Closes: #1008095)
+ * d/rules: switch to the dh sequence (but keep build-{arch,indep}),
+ rearrange some rules.
+ This brings us dh_dwz (very slow) and dh_strip_nondeterminism.
+ * d/rules: do not explicitly turn off slirp & capstone (now properly
+ controlled by --with[out]-default-features option)
+ * d/rules: do not try to enable tcg-interpreter on the unsupported
+ targets, it does not help to build tools anymore
+ * d/rules: do not chown -w d/control, it breaks dpkg-source
+ * d/rules: clean up the clean target
+ * d/not-installed: list many documentation files and qemu-plugin.h
+ * configure-make-fortify_source-yes-by-default.patch: enable
+ fortify-source for minimal builds too
+ * d/changelog: mention #990562 (CVE-2021-3611) closed by 7.0
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Sat, 30 Apr 2022 13:38:12 +0300
+
+qemu (1:7.0+dfsg-1) unstable; urgency=medium
+
+ * update to 7.0 release
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Thu, 21 Apr 2022 14:19:51 +0300
+
+qemu (1:7.0~rc4+dfsg-1) experimental; urgency=medium
+
+ * New upstream 7.0 (rc)
+ Closes: #990562, CVE-2021-3611
+ * remove patches applied upstream
+ * remove new binary file, pc-bios/edk2-x86_64-microvm.fd.bz2
+ * d/control: remove libxfs-dev build dependency,
+ the ioctl is implemented inline
+ * d/control: stop build-depend-indep on libc6.1-dev-alpha-cross,
+ not needed anymore
+ * d/rules: update skiboot version check (skiboot hasn't canged since 6.1)
+ * build & install vbootrom (npcm7xx_bootrom.bin), and
+ build-depend-indep on gcc-arm-none-eabi
+ * create a new binary package, qemu-system-xen, which provides
+ /usr/libexec/xen-qemu-system-i386 binary for use by xen only.
+ Once xen switches to use this binary instead of usual qemu-system-i386,
+ xen support will be removed from the regular qemu-system-x86 build
+ * use a fast inline version of /usr/share/dpkg/architecture.mk
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Sun, 17 Apr 2022 15:08:40 +0300
+
+qemu (1:6.2+dfsg-3) unstable; urgency=medium
+
+ [ Christian Ehrhardt ]
+ * d/rules: ensure xen is built on x86
+ * d/rules: xen libexec dir is no more versioned
+ * d/kvm-spice: fix when acceleration is already defined on the commandline
+
+ [ Michael Tokarev ]
+ * d/control, d/rules: do not compile xen support on i386,
+ since it is amd64-only now (since 4.16)
+ * d/control: add libbpf-dev & --enable-bpf for eBPF support
+ (Closes: #994573)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Fri, 25 Feb 2022 12:01:46 +0300
+
+qemu (1:6.2+dfsg-2) unstable; urgency=medium
+
+ * bump meson build-dep to 0.59.3
+ * build & include multiboot_dma.bin (Closes: #1003930)
+ * libxml2 is not needed for parallels.
+ Enable parallels block image format (Closes: #1003162)
+ * acpi-validate-hotplug-selector-on-access-CVE-2021-4158.patch
+ Closes: CVE-2021-4158
+ * acpi-fix-QEMU-crash-when-started-with-SLIC-table.patch
+ (Closes: #1004017)
+ * acpi-fix-OEM_ID-padding.patch
+ * debian/get-orig-source.sh: repack dfsg archive differently
+ * mention closing of a few CVEs by 6.2.0
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Thu, 20 Jan 2022 10:52:19 +0300
+
+qemu (1:6.2+dfsg-1) unstable; urgency=medium
+
+ [ Christian Ehrhardt ]
+ * 6.2.0 upstream release
+ Closes: #984452, CVE-2021-20203
+ (integer overflow issue in the vmxnet3 NIC emulator)
+ Closes: #984453, CVE-2021-20196
+ (fdc: check drive block device before usage)
+ Closes: #984451, CVE-2021-20255
+ (infinite recursion / DMA reentrancy in eepro100 i8255x device emulator)
+ * d/get-orig-source.sh: remove pc-bios/multiboot_dma.bin in dfsg-clean
+ * Drop patches upstream in v6.2.0
+ * d/p/spelling.diff: update for v6.2.0 (partially accepted)
+ * d/rules: use new --disable-install-blobs build arg
+ * Revert "make fuse debian-only, since libfuse3 in ubuntu is in universe",
+ it is now in main (LP: #1934510)
+ * d/rules: bump skiboot version for qemu v6.2.0
+ * d/p/ignore-roms-dependency-in-qtest.patch: fix meson issue
+ due to dfsg removal of blobs
+ * d/rules: drop --disable-fdt on microvm builds
+ (now strictly required on any x86 build)
+ * d/rules: select default PARISC config for hppa-firmware
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Sun, 09 Jan 2022 12:52:10 +0300
+
+qemu (1:6.1+dfsg-8) unstable; urgency=medium
+
+ * fix keymaps definitions placement in last upload
+ (Closes: #997925, #997926)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Wed, 27 Oct 2021 13:27:09 +0300
+
+qemu (1:6.1+dfsg-7) unstable; urgency=medium
+
+ * qemu-system-data: do not install qemu.desktop (Closes: #995628)
+ * remove qemu-user-static.README.Debian (#995633)
+ * d/rules: update configure rules for different qemu builds
+ * qemu-system-x86-xen: install only -i386 link to xen path, not -x86_64
+ * promote qemu-system-x86-xen package on ubuntu to be like qemu-system-x86
+ since it uses the same modules actually
+ * enable zstd compression support (Build-Depends)
+ * qemu-system-data: install usr/share/icons/hicolor/32x32/apps/qemu.bmp
+ for the sdl ui
+ * d/control: fix wrong relation (< vs <<)
+ * d/control: use :native version of python3-sphynx (Closes: #995622)
+ * do not make qemu-system-gui Multi-Arch:same due to vhost-user-gpu
+ * quieten gcc11 warnings/errors so roms will compile (Closes: #997082)
+ * move d/qemu-system-data.install to d/rules
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Tue, 26 Oct 2021 10:35:02 +0300
+
+qemu (1:6.1+dfsg-6) unstable; urgency=medium
+
+ * virtio-net-fix-use-after-unmap-free-for-sg-CVE-2021-3748.patch
+ Closes: #993401, CVE-2021-3748: use-after-free in virtio_net_receive_rcu
+ * ati_2d-fix-buffer-overflow-in-ati_2d_blt-CVE-2021-3638.patch
+ Closes: #992726, CVE-2021-3638:
+ inconsistent check in ati_2d_blt() may lead to out-of-bounds write
+ * refresh uas-add-stream-number-sanity-checks-CVE-2021-3713{.diff=>.patch}
+ from upstream
+ * hmp-unbreak-change-vnc.patch from upstream
+ to fix 'change vnc passwd' command
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Wed, 29 Sep 2021 13:41:47 +0300
+
+qemu (1:6.1+dfsg-5) unstable; urgency=medium
+
+ * updated debian/patches/linux-user-binfmt-P.diff
+ to work with in-kernel code
+ Closes: #993658
+ * d/rules: do not mark configure target as .PHONY
+ since it is a real file
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Mon, 06 Sep 2021 01:20:59 +0300
+
+qemu (1:6.1+dfsg-4) unstable; urgency=medium
+
+ * qemu-sockets-fix-unix-socket-path-copy-again.patch
+ replacing socket-unix-maxlen.patch
+ Closes: #993145
+ * enable more devices for the microvm build:
+ virtio-gpu & vhost-user-gpu
+ virtio-input-host & vhost_user_input
+ * move vhost-user-gpu files from qemu-system-common to qemu-system-gui
+ this elminates X11 dependencies from non-gui qemu-system install
+ * build and install vof.bin firmware
+ * rearrange d/rules a bit to make different qemu builds
+ to be consistent with sysdata-components
+ * move ppc dtb firmware files from qemu-system-ppc to qemu-system-data
+ * device-tree-compiler is now needed in build-indep-depends,
+ not in build-depends
+ * d/rules: use CROSSPFX variables
+ * ubuntu only:
+ - Revert commit from the previous release which restores
+ relation between qemu-system-xen and qemu-system-gui
+ since -xen is not compatible with -gui modules
+ - qemu-system-xen does not suggest qemu-block-extra (incompatible too)
+ - qemu-system-s390x recommends qemu-block-extra not suggests it
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Tue, 31 Aug 2021 22:27:25 +0300
+
+qemu (1:6.1+dfsg-3) unstable; urgency=medium
+
+ * fix brown-paper bag in last upload (--enable-libudev)
+ * ubuntu only: restore relations (depends/recommends)
+ between qemu-system-gui and qemu-system-xen since -xen
+ replaces full qemu-system-x86 and acts the same way
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Tue, 31 Aug 2021 02:50:52 +0300
+
+qemu (1:6.1+dfsg-2) unstable; urgency=medium
+
+ * rearrange d/rules to be able to configure/build/install
+ various different kinds of qemu builds (main/microvm/xen/static)
+ separately, by splitting targets of d/rules into subtargets
+ * enable many virtio devices for microvm build (Closes: #992029)
+ * disable libudev and fuse for microvm build
+ * rearrange options for microvm build in d/rules
+ * tidy newly added assert in unix-domain socket handling code
+ to account for extra \0 terminator for socket pathname,
+ socket-unix-maxlen.patch (Closes: #993145)
+ * upstream qemu added ignoring of *.patch to .gitignore,
+ unignore them in d/.gitignore
+ * re-add 4 patches which were lost from git
+ during preparation for 6.1
+ (not affecting the source package)
+ * uas-add-stream-number-sanity-checks-CVE-2021-3713.diff
+ Closes: #992727, CVE-2021-3713
+ * Mention (some) bugs closed by 6.1 upstream
+ * Mention closing of #947349
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Tue, 31 Aug 2021 02:01:51 +0300
+
+qemu (1:6.1+dfsg-1) unstable; urgency=medium
+
+ * new upstream release (6.1.0)
+ Closes: CVE-2021-3607 (pvrdma: ensure correct input on ring init)
+ Closes: CVE-2021-3608 (pvrdma: unmap initialized dma address)
+ Closes: #989042, CVE-2021-3544 (vhost-user-gpu resource leaks)
+ Closes: #989042, CVE-2021-3545 (vhost-user-gpu memory disclosure)
+ Closes: #989042, CVE-2021-3546 (vhost-user-gpu OOBwr virgl_cmd_get_capset)
+ Closes: #991911, CVE-2021-3682 (pvrdma: possible mremap overflow)
+ * refresh patches, remove patches which were applied upstream
+ * remove newly appeared pc-bios/vof.bin in dfsg-clean
+ * add python3-sphinx-rtd-theme to build-depends
+ * removed qemu-system-moxie arch
+ * actually build many qemu modules as modules, and install
+ them in qemu-system-common.
+ * make strong versioned dependency between various qemu-system-*
+ packages, so that modules works correctly.
+ * drop very old versions from Build-Depends, Depends and Recommends
+ for packages which long has much more recent versions in debian
+ * up qemu-block-extra dependecy level from Suggests to Recommends
+ * d/control: stop suggesting sgabios by qemu-system-x86
+ * (experimental for now, needs more work) print name of the package
+ name for a module which can't be loaded, to give a clue what other
+ package one may need to install for the requested functionality
+ * fix some spelling mistakes in visible messages (spelling.diff)
+ * enable jack audio backend (in qemu-system-gui) (Closes: #984726)
+ * other small/internal changes in packaging:
+ - removed --disable-sheepdog which were dropped upstream
+ - install gui modules in d/rules not in d/q-s-gui.install
+ to be able to use wildcard in d/q-s-common.install
+ - recommend qemu-block-extra, not suggest it and not depend on it (ubuntu)
+ for qemu-system-* and qemu-utils
+ - reformat qemu "deps" for qemu-system-gui, stop listing -xen there
+ (it can not satisfy -gui), qemu-system-s390x is :ubuntu:-only
+ - d/control: stop recommending -gui for xen package
+ (it is of no use for xen)
+ - d/control: reformat Depends for qemu-block-extra, do not include -xen
+ version there, mark -x390x as ubuntu-only,
+ and allow qemu-utils to satisfy the dependency
+ - do not install docs which does not exist anymore
+ - stop omiting Changelog from dh_installchangelog: the file is long gone
+ - d/rules: explicitly state version of skiboot as it is stored
+ in a git tag only, or else skiboot does not build (hack)
+ - put (new in 6.1, new in debian) hw-display-virtio-gpu-gl.so
+ to qemu-system-gui as it pulls in X11
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Wed, 25 Aug 2021 15:59:26 +0300
+
+qemu (1:6.0+dfsg-4) unstable; urgency=medium
+
+ * d/rules: fix last ubuntu merge, xen is x86-only, not all-debian
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Tue, 17 Aug 2021 19:04:30 +0300
+
+qemu (1:6.0+dfsg-3) unstable; urgency=medium
+
+ [ Michael Tokarev ]
+ * enable /run/qemu mount on ubuntu only
+ * usbredir-fix-free-call-CVE-2021-3682.patchi
+ Closes: #991911, CVE-2021-3682
+
+ [ Christian Ehrhardt ]
+ * ubuntu-only changes:
+ - d/control-in: Make Ubuntu qemu-utils depend on qemu-block-extra
+ - d/control-in: Make Ubuntu qemu-system-common depend on qemu-block-extra
+ - d/control*, d/rules: disable xen by default, but provide universe package
+ qemu-system-x86-xen as alternative
+ * d/p/target-s390x-Fix-translation-exception-on-illegal-in.patch:
+ avoid segfaults by uretprobes (LP 1929926)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Tue, 17 Aug 2021 17:49:10 +0300
+
+qemu (1:6.0+dfsg-2exp) experimental; urgency=medium
+
+ [ Christian Ehrhardt ]
+ * qemu 6.0 broke libvirt <7.2, add a Breaks
+ to avoid partial upgrade issues (LP: #1932264)
+ * enable SDL as secondary UI backend (LP: #1256185) (Closes: #947349)
+ * clear all (current and former) modules on purge
+ * only save modules if /run/qemu isn't noexec
+ * provide run-qemu.mount in qemu-block-extra
+ (disabled in debian for now)
+ * Disable capstone disassembler library support in ubuntu (universe)
+
+ [ Michael Tokarev ]
+ * qemu does not ship Changelog file anymore
+ * drop version from libfuse-dev build-depends (noticed by Ville Skyttä)
+ * a few patches from upstream stable:
+ - target-ppc-fix-load-endianness-for-lxvwsx-lxvdsx.patch
+ fix various crashes in ppc system emulation.
+ Thanks to Christian Ehrhardt for pointing this out
+ - pvrdma-fix-possible-mremap-overflow-in-pvrdma-device-CVE-2021-3582.patch
+ (Closes: #990565, CVE-2021-3582)
+ - pvrdma-ensure-correct-input-on-ring-init-CVE-2021-3607.patch
+ (Closes: #990564, CVE-2021-3607)
+ - pvrdma-fix-the-ring-init-error-flow-CVE-2021-3608.patch
+ (Closes: #990563, CVE-2021-3608)
+ - usb-limit-combined-packets-to-1-MiB-CVE-2021-3527.patch
+ usb-redir-avoid-dynamic-stack-allocation-CVE-2021-3527.patch
+ (Closes: #988157, CVE-2021-3527)
+ * mention closing of 3 bugs in am53c974 (ESP) device emulation by 6.0
+ (Closes: #979679, CVE-2020-35504)
+ (Closes: #984455, CVE-2020-35505)
+ (Closes: #984454, CVE-2020-35506)
+ * make fuse debian-only, since libfuse3 in ubuntu is in universe
+ * fix microvm default machine type for a new build system (LP: #1936894)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Wed, 21 Jul 2021 19:43:37 +0300
+
+qemu (1:6.0+dfsg-1~exp0) experimental; urgency=medium
+
+ * new upstream release
+ Closes: #979679, CVE-2020-35504
+ Closes: #984455, CVE-2020-35505
+ Closes: #984454, CVE-2020-35506
+ * remove obsolete patches, refresh use-fixed-data-path.patch
+ * use libncurses-dev, not old libncursesw5-dev
+ * enable fuse export (and build-depend on libfuse3-dev)
+ * install (new) manpages for qemu-storage-daemon
+ * enable new hexagon qemu-user target
+ * two patches to fix 3 new spelling mistakes
+ * remove now-unused shared-library-lacks-prerequisites lintian-overrides
+ for qemu-user-static
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Sat, 08 May 2021 10:16:05 +0300
+
+qemu (1:5.2+dfsg-11) unstable; urgency=medium
+
+ * i386-acpi-restore-device-paths-for-pre-5.1-vms.patch
+ This fixes a serious issue in some VMs (in particuar, Windows & MacOS)
+ when migrating from buster qemu to bullseye qemu.
+ (Closes: #990675)
+ * pvrdma-fix-possible-mremap-overflow-in-pvrdma-device-CVE-2021-3582.patch
+ (Closes: #990565, CVE-2021-3582)
+ * pvrdma-ensure-correct-input-on-ring-init-CVE-2021-3607.patch
+ (Closes: #990564, CVE-2021-3607)
+ * pvrdma-fix-the-ring-init-error-flow-CVE-2021-3608.patch
+ (Closes: #990563, CVE-2021-3608)
+ * ide-atapi-check-logical-block-address-and-read-size-CVE-2020-29443.patch
+ (Closes: #983575, CVE-2020-29443)
+ * usb-limit-combined-packets-to-1-MiB-CVE-2021-3527.patch
+ usb-redir-avoid-dynamic-stack-allocation-CVE-2021-3527.patch
+ (Closes: #988157, CVE-2021-3527)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Sun, 18 Jul 2021 16:14:41 +0300
+
+qemu (1:5.2+dfsg-10) unstable; urgency=medium
+
+ * 5 sdhci fixes from upstream:
+ dont-transfer-any-data-when-command-time-out.patch
+ dont-write-to-SDHC_SYSAD-register-when-transfer-is-in-progress.patch
+ correctly-set-the-controller-status-for-ADMA.patch
+ limit-block-size-only-when-SDHC_BLKSIZE-register-is-writable.patch
+ reset-the-data-pointer-of-s-fifo_buffer-when-a-different-block-size...patch
+ (Closes: #986795, #970937, CVE-2021-3409, CVE-2020-17380, CVE-2020-25085)
+ * mptsas-remove-unused-MPTSASState.pending-CVE-2021-3392.patch
+ fix possible use-after-free in mptsas_free_request
+ (Cloese: #984449, CVE-2021-3392)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Fri, 16 Apr 2021 12:43:36 +0300
+
+qemu (1:5.2+dfsg-9) unstable; urgency=medium
+
+ * do not make qemu-system-data dependent on qemu-system-foo
+ (Closes: #985040)
+ * CVE-2021-20263 - implement dropping security.capability xattr
+ This adds two patches from upstream:
+ virtiofsd-save-error-code-early-at-the-failure-callsite.patch
+ virtiofsd-drop-remapped-security.capability-..-needed-CVE-2021-20263.patch
+ Closes: #985083, CVE-2021-20263
+ * CVE-2021-3416 fix from upstream
+ Fixes infinite loop in loopback mode of various network devices,
+ adding 10 patches from upstream
+ Closes: #984448, CVE-2021-3416
+ * net-e1000-fail-early-for-evil-descriptor-CVE-2021-20257.patch
+ Fix CVE-2021-20257 from upstream: e1000: infinite loop while processing
+ transmit descriptors
+ Closes: #984450, CVE-2021-20257
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Wed, 17 Mar 2021 21:02:30 +0300
+
+qemu (1:5.2+dfsg-8) unstable; urgency=medium
+
+ * a no-change upload to fix broken previous upload
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Sun, 14 Mar 2021 12:21:37 +0300
+
+qemu (1:5.2+dfsg-7) unstable; urgency=high
+
+ * do not make qemu-system-common dependent on qemu-system-foo.
+ We removed modules from qemu-system-common for now, so there's no
+ need for it to depend on any of qemu-system-foo of the same version.
+ Among other things this fixes #983756 (which should be fixes some
+ other way anyway, but it should be ok for now).
+ Closes: #983756, #983921, #985195
+ Urgency is high because a single bin-NMU of qemu package made it
+ uninstallable.
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Sun, 14 Mar 2021 11:32:54 +0300
+
+qemu (1:5.2+dfsg-6) unstable; urgency=medium
+
+ * deprecate qemu-debootstrap. It is not needed anymore with
+ binfmt F flag, since everything now works without --foreign
+ debootstrap argument and copying the right qemu binary into
+ the chroot. Closes: #901197
+ * fix the brown-paper bag bug: wrong argument order
+ in the linux-user-binfmt patch (really closes: #970460)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Tue, 16 Feb 2021 12:11:20 +0300
+
+qemu (1:5.2+dfsg-5) unstable; urgency=medium
+
+ * d/rules: ensure b/ subdir exists before building palcode and qboot
+ * d/changelog: #959530 is not fixed by 5.2+dfsg-4
+ * 3 virtiofsd patches Closes: #980814, CVE-2020-35517
+ virtiofsd: potential privileged host device access from guest
+ - virtiofsd-extract-lo_do_open-from-lo_open.patch
+ - virtiofsd-optionally-return-inode-pointer-from-lo_do_lookup.patch
+ - virtiofsd-prevent-opening-of-special-files-CVE-2020-35517.patch
+ -- Michael Tokarev <mjt@tls.msk.ru> Sun, 14 Feb 2021 17:44:06 +0300
+
+qemu (1:5.2+dfsg-4) unstable; urgency=medium
+
+ [ Michael Tokarev ]
+ * require libfdt >= 1.5.0-2 due to #931046
+ * qemu-user: attempt to preserve argv[0] when run under binfmt
+ (Closes: #970460)
+ This changes the enterpreter name for all linux-user registered
+ binfmts, so it potentially can break stuff. The actual binary
+ being registered now is /usr/libexec/qemu-binfmt/foo-binfmt-P,
+ which is a symlink to actual /usr/lib/qemu-foo[-static].
+ * ignore .git-submodule-status when building source
+ * some security fixes from upstream:
+ o arm_gic-fix-interrupt-ID-in-GICD_SGIR-CVE-2021-20221.patch
+ Closes: CVE-2021-20221
+ GIC (armv7): out-of-bound heap buffer access via an interrupt ID field
+ o 9pfs-Fully-restart-unreclaim-loop-CVE-2021-20181.patch
+ Closes: CVE-2021-20181
+ * non-security fixes from upstream:
+ pc-bios-descriptors-fix-paths-in-json-files.patch - fixes wrong paths
+ in edk2-firmware-related json files introduced in 5.2
+
+ [ Christian Ehrhardt ]
+ * d/control-in: avoid version mismatch of installed binaries
+ (Closes: #956377)
+
+ [ Dan Streetman ]
+ * Backport configure param --with-git-submodules and set to 'ignore'
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Sun, 14 Feb 2021 16:52:10 +0300
+
+qemu (1:5.2+dfsg-3) unstable; urgency=medium
+
+ [ Christian Ehrhardt ]
+ * d/rules: fix qemu-user-static to really be static (LP: #1908331)
+
+ [ Michael Tokarev ]
+ * build most modules statically (besides block and gui parts).
+ This makes qemu-system-common package to be of less strict dependency
+ for other qemu-system-* packages, and also Closes: #977301, #978131
+ * especially remove removed binfmts in qemu-user-{static,binfmt}.preinst
+ (really Closes: #977015)
+ * memory-clamp-cached-translation-MMIO-region-CVE-2020-27821.patch
+ (Closes: #977616, CVE-2020-27821)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Tue, 29 Dec 2020 15:07:03 +0300
+
+qemu (1:5.2+dfsg-2) unstable; urgency=medium
+
+ * move ui-opengl.so module from qemu-system-gui to qemu-system-common,
+ as other modules want it (Closes: #976996, #977022)
+ * do not install dropped ppc64abi32 binfmt for qemu-user[-static]
+ (Closes: #977015)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Thu, 10 Dec 2020 11:15:43 +0300
+
+qemu (1:5.2+dfsg-1) unstable; urgency=medium
+
+ * new upstream release
+ Closes: #965978, CVE-2020-15859 (22dc8663d9fc7baa22100544c600b6285a63c7a3)
+ Closes: #970539, CVE-2020-25084 (21bc31524e8ca487e976f713b878d7338ee00df2)
+ Closes: #970540, CVE-2020-25085 (dfba99f17feb6d4a129da19d38df1bcd8579d1c3)
+ Closes: #970541, CVE-2020-25624 (1328fe0c32d5474604105b8105310e944976b058)
+ Closes: #970542, CVE-2020-25625 (1be90ebecc95b09a2ee5af3f60c412b45a766c4f)
+ Closes: #974687, CVE-2020-25707 (c2cb511634012344e3d0fe49a037a33b12d8a98a)
+ Closes: #975276, CVE-2020-25723 (2fdb42d840400d58f2e706ecca82c142b97bcbd6)
+ Closes: #975265, CVE-2020-27616 (ca1f9cbfdce4d63b10d57de80fef89a89d92a540)
+ Closes: #973324, CVE-2020-27617 (7564bf7701f00214cdc8a678a9f7df765244def1)
+ Closes: #972864, CVE-2020-27661 (bea2a9e3e00b275dc40cfa09c760c715b8753e03)
+ Closes: CVE-2020-27821 (1370d61ae3c9934861d2349349447605202f04e9)
+ Closes: #976388, CVE-2020-28916 (c2cb511634012344e3d0fe49a037a33b12d8a98a)
+ * remove obsolete patches
+ * refresh use-fixed-data-path.patch and debian/get-orig-source.sh
+ * bump minimum meson version required for build to 0.55.3
+ * update build rules for several components
+ * remove deprecated lm32 and unicore32 system emulators
+ * remove deprecated ppc64abi32 and tilegx linux-user emulators
+ * install ui-spice-core.so & chardev-spice.so in qemu-system-common
+ * install ui-egl-headless.so in qemu-system-common
+ * install hw-display-virtio-*.so in qemu-system-common
+ * install ui-opengl.so in qemu-system-gui
+ * install qemu-pr-helper.8 in qemu-system-common
+ * qemu-pr-helper moved to usr/bin/ again
+ * qboot.rom renamed from bios-microvm.bin
+ * remove several unused lintian overrides
+ * add spelling.diff patch to fix a few spelling errors
+ * update Standards-Version to 4.5.1
+ * fix a few trailing whitespaces in d/control and d/changelog
+ * require libcapstone >= 4.0.2 (v4) for build
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Wed, 09 Dec 2020 08:57:41 +0300
+
+qemu (1:5.1+dfsg-4) unstable; urgency=high
+
+ * mention closing of CVE-2020-16092 by 5.1
+ * usb-fix-setup_len-init-CVE-2020-14364.patch
+ Closes: #968947, CVE-2020-14364
+ (OOB r/w access in USB emulation)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Wed, 02 Sep 2020 16:14:52 +0300
+
+qemu (1:5.1+dfsg-3) unstable; urgency=medium
+
+ * fix one more issue in last upload. This is what happens when
+ you do "obvious" stuff in a hurry without proper testing..
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Mon, 17 Aug 2020 22:19:55 +0300
+
+qemu (1:5.1+dfsg-2) unstable; urgency=medium
+
+ * fix brown-paper bag bug in last upload
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Mon, 17 Aug 2020 20:58:52 +0300
+
+qemu (1:5.1+dfsg-1) unstable; urgency=medium
+
+ * hw-display-qxl.so depends on spice so install it
+ only if it is built just like ui-spice-app
+ * note #931046 for libfdt
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Mon, 17 Aug 2020 18:57:14 +0300
+
+qemu (1:5.1+dfsg-0exp1) experimental; urgency=medium
+
+ * new upstream release 5.1.0. Make source DFSG-clean again
+ Closes: #968088
+ Closes: CVE-2020-16092 (net_tx_pkt_add_raw_fragment in e1000e & vmxnet3)
+ * remove all patches which are applied upstream
+ * do not install non-existing doc/qemu/*-ref.*
+ * qemu-pr-helper is now in /usr/lib/qemu not /usr/bin
+ * virtfs-proxy-helper is in /usr/lib/qemu now, not /usr/bin
+ * new architecture: qemu-system-avr
+ * refresh d/get-orig-source.sh
+ * d/get-orig-source.sh: report already removed files in dfsg-clean
+ * install common modules in qemu-system-common
+ * lintian tag renamed: shared-lib-without-dependency-information to
+ shared-library-lacks-prerequisites
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Wed, 12 Aug 2020 19:09:24 +0300
+
+qemu (1:5.0-14) unstable; urgency=high
+
+ * this is a bugfix release before breaking toys with the new upstream
+ * riscv-allow-64-bit-access-to-SiFive-CLINT.patch
+ (another fix for revert-memory-accept-..-CVE-2020-13754)
+ * install /usr/lib/*/qemu/ui-curses.so in qemu-system-common
+ Closes: #966517
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Fri, 31 Jul 2020 11:45:25 +0300
+
+qemu (1:5.0-13) unstable; urgency=medium
+
+ * seabios-hppa-fno-ipa-sra.patch
+ fix ftbfs with gcc-10
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Wed, 22 Jul 2020 22:16:41 +0300
+
+qemu (1:5.0-12) unstable; urgency=medium
+
+ * acpi-accept-byte-and-word-access-to-core-ACPI-registers.patch
+ this replace cpi-allow-accessing-acpi-cnt-register-by-byte.patch
+ and acpi-tmr-allow-2-byte-reads.patch, a more complete fix
+ * xhci-fix-valid.max_access_size-to-access-address-registers.patch
+ fix one more incarnation of the breakage after the CVE-2020-13754 fix
+ * do not install outdated (0.12 and before) Changelog (Closes: #965381)
+ * xgmac-fix-buffer-overflow-in-xgmac_enet_send-CVE-2020-15863.patch
+ ARM-only XGMAC NIC, possible buffer overflow during packet transmission
+ Closes: CVE-2020-15863
+ * sm501 OOB read/write due to integer overflow in sm501_2d_operation()
+ List of patches:
+ sm501-convert-printf-abort-to-qemu_log_mask.patch
+ sm501-shorten-long-variable-names-in-sm501_2d_operation.patch
+ sm501-use-BIT-macro-to-shorten-constant.patch
+ sm501-clean-up-local-variables-in-sm501_2d_operation.patch
+ sm501-replace-hand-written-implementation-with-pixman-CVE-2020-12829.patch
+ Closes: #961451, CVE-2020-12829
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Wed, 22 Jul 2020 19:42:29 +0300
+
+qemu (1:5.0-11) unstable; urgency=high
+
+ * d/control-in: only enable opengl (libdrm&Co) on linux
+ * d/control-in: spice: drop versioned deps (even jessie version is enough),
+ drop libspice-protocol-dev (automatically pulled by libspice-server-dev),
+ and build on more architectures
+ * change from debhelper versioned dependency to debhelper-compat (=12)
+ * acpi-allow-accessing-acpi-cnt-register-by-byte.patch' (Closes: #964793)
+ This is another incarnation of the recent bugfix which actually enabled
+ memory access constraints, like #964247
+ Urgency = high due to this issue.
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Mon, 20 Jul 2020 18:41:17 +0300
+
+qemu (1:5.0-10) unstable; urgency=medium
+
+ * fix the wrong $(if) construct for s390x kvm link (FTBFS on s390x)
+ * use the same $(if) construct to simplify #ifdeffery
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Sat, 18 Jul 2020 10:02:41 +0300
+
+qemu (1:5.0-9) unstable; urgency=medium
+
+ * move kvm executable/script from qemu-kvm to qemu-system-foo,
+ make it multi-arch, and remove qemu-kvm package
+ * remove libcacard leftovers from d/.gitignore
+ * linux-user-refactor-ipc-syscall-and-support-of-semtimedop.patch
+ (Closes: #965109)
+ * linux-user-add-netlink-RTM_SETLINK-command.patch (Closes: #964289)
+ * libudev is linux-specific, do not build-depend on it
+ on kfreebsd and others
+ * install virtiofsd in d/rules (!sparc64) instead of
+ d/qemu-system-common.install (fixes FTBFS on sparc64)
+ * confirm -static-pie not working today still
+ * d/control: since qemu-system-data now contains module(s),
+ it can't be multi-arch. Ditto for qemu-block-extra.
+ * qemu-system-foo: depend on exact version of qemu-system-data,
+ due to the latter having modules
+ * build all modules since there are modules anyway,
+ no need to hack them in d/rules
+ * fix spelling in a patch name/subject inlast upload
+ * d/rules: do not use dh_install and dh_movefiles for individual
+ pkgs, open-code mkdir+cp/mv, b/c dh_install acts on all files
+ listed in d/foo.install too, in addition to given on command-line
+ * remove trailing whitespace from d/changelog
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Sat, 18 Jul 2020 08:29:38 +0300
+
+qemu (1:5.0-8) unstable; urgency=medium
+
+ * d/control: rdma is linux-only, do not enable it on kfreebsd & hurd
+ * add comment about virtiofsd conditional to d/qemu-system-common.install
+ Now qemu FTBFS on sparc64 since virtiofsd is not built due to missing
+ seccomp onn that platform, we should either make virtiofsd conditional
+ (!sparc64) or fix seccomp on sparc64 and build-depend on it
+ * openbios-use-source_date_epoch-in-makefile.patch (Closes: #963466)
+ * seabios-hppa-use-consistant-date-and-remove-hostname.patch (Closes: #963467)
+ * slof-remove-user-and-host-from-release-version.patch (Closes: #963472)
+ * slof-ensure-ld-is-called-with-C-locale.patch (Closes: #963470)
+ * update previous changelog, mention #945997
+ * reapply CVE-2020-13253 fixed from upstream:
+ sdcard-simplify-realize-a-bit.patch (preparation for the next patch)
+ sdcard-dont-allow-invalid-SD-card-sizes.patch (half part of CVE-2020-13253)
+ sdcard-update-coding-style-to-make-checkpatch-happy.patch (preparational)
+ sdcard-dont-switch-to-ReceivingData-if-address-is-in..-CVE-2020-13253.patch
+ Closes: #961297, CVE-2020-13253
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Fri, 17 Jul 2020 09:12:43 +0300
+
+qemu (1:5.0-7) unstable; urgency=medium
+
+ * Revert "d/rules: report config log from the correct subdir - base build"
+ * Revert "d/rules: report config log from the correct subdir - microvm build"
+ * acpi-tmr-allow-2-byte-reads.patch (Closes: #964247)
+ * remove sdcard-dont-switch-to-ReceivingData-if-add...-CVE-2020-13253.patch -
+ upstream decided to fix it differently (Reopens: #961297, CVE-2020-13253)
+ * explicitly specify --enable-tools on hppa and do the same trick
+ with --enable-tcg-interpreter --enable-tools on a few other unsupported
+ arches (Closes: #964372, #945997)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Thu, 16 Jul 2020 18:36:08 +0300
+
+qemu (1:5.0-6) unstable; urgency=medium
+
+ [ Christian Ehrhardt ]
+ * d/control-in: disable pmem on ppc64 as it is currently considered
+ experimental on that architecture
+ * d/rules: makefile definitions can't be recursive - sys_systems for s390x
+ * d/rules: report config log from the correct subdir - base build
+ * d/rules: report config log from the correct subdir - microvm build
+ * d/control-in: disable rbd support unavailable on riscv
+ * fix assert in qemu guest agent that crashes on shutdown (LP: #1878973)
+ * d/control-in: build-dep libcap is no more needed
+ * d/rules: update -spice compat (Ubuntu only)
+
+ [ Michael Tokarev ]
+ * save block modules on upgrades (LP: #1847361)
+ After upgrade a still running qemu of a former version can't load the
+ new modules e.g. for extended storage support. Qemu 5.0 has the code to
+ allow defining a path that it will load these modules from.
+ * ati-vga-check-mm_index-before-recursive-call-CVE-2020-13800.patch
+ Closes: CVE-2020-13800, ati-vga allows guest OS users to trigger
+ infinite recursion via a crafted mm_index value during
+ ati_mm_read or ati_mm_write call.
+ * revert-memory-accept-mismatching-sizes-in-memory_region_access_valid...patch
+ Closes: CVE-2020-13754, possible OOB memory accesses in a bunch of qemu
+ devices which uses min_access_size and max_access_size Memory API fields.
+ Also closes: CVE-2020-13791
+ * exec-set-map-length-to-zero-when-returning-NULL-CVE-2020-13659.patch
+ CVE-2020-13659: address_space_map in exec.c can trigger
+ a NULL pointer dereference related to BounceBuffer
+ * megasas-use-unsigned-type-for-reply_queue_head-and-check-index...patch
+ Closes: #961887, CVE-2020-13362, megasas_lookup_frame in hw/scsi/megasas.c
+ has an OOB read via a crafted reply_queue_head field from a guest OS user
+ * megasas-use-unsigned-type-for-positive-numeric-fields.patch
+ fix other possible cases like in CVE-2020-13362 (#961887)
+ * megasas-fix-possible-out-of-bounds-array-access.patch
+ Some tracepoints use a guest-controlled value as an index into the
+ mfi_frame_desc[] array. Thus a malicious guest could cause a very low
+ impact OOB errors here
+ * nbd-server-avoid-long-error-message-assertions-CVE-2020-10761.patch
+ Closes: CVE-2020-10761, An assertion failure issue in the QEMU NBD Server.
+ This flaw occurs when an nbd-client sends a spec-compliant request that is
+ near the boundary of maximum permitted request length. A remote nbd-client
+ could use this flaw to crash the qemu-nbd server resulting in a DoS.
+ * es1370-check-total-frame-count-against-current-frame-CVE-2020-13361.patch
+ Closes: CVE-2020-13361, es1370_transfer_audio in hw/audio/es1370.c does not
+ properly validate the frame count, which allows guest OS users to trigger
+ an out-of-bounds access during an es1370_write() operation
+ * sdcard-dont-switch-to-ReceivingData-if-address-is-in...-CVE-2020-13253.patch
+ CVE-2020-13253: sd_wp_addr in hw/sd/sd.c in QEMU 4.2.0 uses an unvalidated
+ address, which leads to an out-of-bounds read during sdhci_write()
+ operations. A guest OS user can crash the QEMU process.
+ And a preparational patch,
+ sdcard-update-coding-style-to-make-checkpatch-happy.patch
+ * a few patches from the stable series:
+ - fix-tulip-breakage.patch
+ The tulip network driver in a qemu-system-hppa emulation is broken in
+ the sense that bigger network packages aren't received any longer and
+ thus even running e.g. "apt update" inside the VM fails. Fix this.
+ - 9p-lock-directory-streams-with-a-CoMutex.patch
+ Prevent deadlocks in 9pfs readdir code
+ - net-do-not-include-a-newline-in-the-id-of-nic-device.patch
+ Fix newline accidentally sneaked into id string of a nic
+ - qemu-nbd-close-inherited-stderr.patch
+ - virtio-balloon-fix-free-page-hinting-check-on-unreal.patch
+ - virtio-balloon-fix-free-page-hinting-without-an-iothread.patch
+ - virtio-balloon-unref-the-iothread-when-unrealizing.patch
+
+ [ Aurelien Jarno ]
+ * Remove myself from maintainers
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Fri, 03 Jul 2020 18:24:48 +0300
+
+qemu (1:5.0-5) unstable; urgency=medium
+
+ * more binfmt-install updates
+ * CVE-2020-10717 fix from upstream:
+ virtiofsd-add-rlimit-nofile-NUM-option.patch (preparational) and
+ virtiofsd-stay-below-fs.file-max-CVE-2020-10717.patch
+ (Closes: #959746, CVE-2020-10717)
+ * 2 patches from upstream/stable to fix io_uring fd set buildup:
+ aio-posix-dont-duplicate-fd-handler-deletion-in-fdmon_io_uring_destroy.patch
+ aio-posix-disable-fdmon-io_uring-when-GSource-is-used.patch
+ * upstream stable fix: hostmem-dont-use-mbind-if-host-nodes-is-empty.patch
+ * upstream stable fix:
+ net-use-peer-when-purging-queue-in-qemu_flush_or_purge_queue_packets.patch
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Wed, 13 May 2020 12:57:19 +0300
+
+qemu (1:5.0-4) unstable; urgency=medium
+
+ * fix binfmt registration (Closes: #959222)
+ * disable PIE for user-static build on x32 too, not only i386
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Fri, 01 May 2020 13:30:43 +0300
+
+qemu (1:5.0-3) unstable; urgency=medium
+
+ * do not explicitly enable -static-pie on non-i386 architectures.
+ Apparenly only amd64 actually support -static-pie for now, and
+ it is correctly detected.
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Thu, 30 Apr 2020 08:05:31 +0300
+
+qemu (1:5.0-2) unstable; urgency=medium
+
+ * (temporarily) disable pie on i386 static build
+ For now -static-pie fails on i386 with the following error message:
+ /usr/bin/ld: /usr/lib/i386-linux-gnu/libc.a(memset_chk-nonshared.o):
+ unsupported non-PIC call to IFUNC `memset'
+ * install qemu-system docs in qemu-system-common, not qemu-system-data,
+ since docs require ./configure run
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Wed, 29 Apr 2020 23:41:04 +0300
+
+qemu (1:5.0-1) unstable; urgency=medium
+
+ * new upstream release (5.0)
+ Closes: #958926
+ Closes: CVE-2020-11869
+ * refresh patches, remove patches applied upstream
+ * do not mention openhackware, it is not used anymore
+ * do not disable bluez (support removed)
+ * new system arch "rx"
+ * dont install qemu-doc.* for now,
+ but install virtiofsd & qemu-storage-daemon
+ * add shared-lib-without-dependency-information tag
+ to qemu-user-static.lintian-overrides
+ * add html docs to qemu-system-data (to /usr/share/doc/qemu-system-common)
+ * do not install usr/share/doc/qemu/specs & usr/share/doc/qemu/tools
+ * install qemu-user html docs for qemu-user & qemu-user-static
+ * build hppa-firmware.img from roms/seabios-hppa
+ (and Build-Depeds-Indep on gcc-hppa-linux-gnu)
+ * enable liburing on linux (build-depend on liburing-dev)
+ * add upstream signing-key.asc (Michael Roth <flukshun@gmail.com>)
+ * build opensbi firmware
+ (for riscv64 only, riscv32 is possible with compiler flags)
+ * add source-level lintian-overrides for binaries-without-sources
+ (lintian can't find sources for a few firmware images which are in roms/)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Wed, 29 Apr 2020 12:00:12 +0300
+
+qemu (1:4.2-7) unstable; urgency=medium
+
+ * qemu-system-gui: Multi-Arch=same, not foreign (Closes: #956763)
+ * x32 arch is in the same family as i386 & x86_64, omit binfmt registration
+ * check systemd-detect-virt before running update-binfmt
+ * gluster is de-facto linux-only, do not build-depend on it on non-linux
+ * virglrenderer is also essentially linux-specific
+ * qemu-user-static does not depend on shlibs
+ * disable parallel building of targets of d/rules
+ * add lintian overrides (arch-dependent static binaries) for openbios binaries
+ * separate binary-indep target into install-indep-prep and binary-indep
+ * split out various components of qemu-system-data into independent
+ build/install rules and add infrastructure for more components:
+ x86-optionrom, sgabios, qboot, openbios, skiboot, palcode-clipper,
+ slof, s390x-fw
+ * iscsi-fix-heap-buffer-overflow-in-iscsi_aio_ioctl_cb.patch
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Mon, 20 Apr 2020 18:30:00 +0300
+
+qemu (1:4.2-6) unstable; urgency=medium
+
+ * d/rules: fix FTBFS (brown-paper-bag bug) in last upload
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Tue, 14 Apr 2020 17:08:45 +0300
+
+qemu (1:4.2-5) unstable; urgency=medium
+
+ * no error-out on address-of-packet-member in openbios
+ * install ui-spice-app.so only if built, spice is optional
+ * arm-fix-PAuth-sbox-functions-CVE-2020-10702.patch -
+ Closes: CVE-2020-10702, weak signature generation
+ in Pointer Authentication support for ARM
+ * (temporarily) enable seccomp only on architectures where it can be built
+ (Closes: #956624)
+ * seccomp has grown up, no need in versioned build-dep
+ * do not list librados-dev in build-dep as we only use librbd-dev
+ and the latter depends on the former
+ * only enable librbd on architectures where it is buildable
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Tue, 14 Apr 2020 15:47:40 +0300
+
+qemu (1:4.2-4) unstable; urgency=medium
+
+ [ Michael Tokarev ]
+ * d/rules: build minimal configuration for qboot/microvm usage
+ * set microvm to be the default machine type for microvm case
+ * install ui-spice-app.so in qemu-system-common
+ * do not depend on libattr-dev, functions are now in libc6 (Closes: #953910)
+ * net-tulip-check-frame-size-and-r-w-data-length-CVE-2020-11102.patch
+ (Closes: #956145, CVE-2020-11102, tulip nic buffer overflow)
+ * qemu-system-data: s/highcolor/hicolor/ (Closes: #955741)
+ * switch binfmt registration to use update-binfmts --[un]import
+ (Closes: #866756)
+ * build openbios-ppc & openbios-sparc binaries in qemu-system-data,
+ and replace corresponding binary packages.
+ Add gcc-sparc64-linux-gnu, fcode-utils & xsltproc to build-depend-indep
+ * build and provide/replace qemu-slof too
+
+ [ Aurelien Jarno ]
+ * enable support for riscv64 hosts
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Tue, 14 Apr 2020 12:44:43 +0300
+
+qemu (1:4.2-3) unstable; urgency=medium
+
+ * mention closing of #909743 in previous changelog (Closes: #909743)
+ * do not link to qemu-skiboot from qemu-system-ppc (Closes: #950431)
+ * provide+conflict qemu-skiboot from qemu-system-data,
+ as we are not using this package anymore
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Sat, 01 Feb 2020 22:10:57 +0300
+
+qemu (1:4.2-2) unstable; urgency=medium
+
+ [ Fabrice Bauzac ]
+ * Fix a typo in the description of the qemu binary package
+
+ [ Frédéric Bonnard ]
+ * Enable powernv emulation with skiboot firmware
+
+ [ Michael R. Crusoe ]
+ * Modernize watch file (Closes: #909743)
+
+ [ Christian Ehrhardt ]
+ * d/control-in: promote qemu-efi/ovmf in Ubuntu
+ * d/control-in: bump debhelper build-dep for compat 12
+ * - d/control-in: update VCS links
+ * - d/control-in: disable bluetooth being deprecated
+ * d/not-installed: ignore new interop docs and extra icons for now
+ * do not install elf2dmp until namespaced
+ * d/control-in: Enable numa support for s390x
+ * Create qemu-system-s390x package (Ubuntu only for now)
+
+ [ Michael Tokarev ]
+ * stop using inttypes.h in qboot code;
+ this makes dependency on libc6-dev-i386 to be unnecessary
+ * qboot-no-jump-tables.diff - use #pragma for one file in qboot
+ * do not install qemu-edid and qemu-keymap for now
+ * no need in bluetooth patches as bluetooth is disabled
+ * scsi-cap-block-count-from-GET-LBA-STATUS-CVE-2020-1711.patch
+ (Closes: #949731, CVE-2020-1711)
+ * enable libpmem support on amd64|arm64|ppc64el (Closes: #935327)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Fri, 31 Jan 2020 23:51:09 +0300
+
+qemu (1:4.2-1) unstable; urgency=medium
+
+ * new upstream release (4.2.0)
+ * removed patches: v4.1.1.diff, enable-pschange-mc-no.patch
+ * do not make sgabios.bin executable (lintian)
+ * add s390-netboot.img lintian overrides for qemu-system-data
+ * build qboot (bios-microvm.bin)
+ * build-depend-indep on libc6-dev-i386 for qboot
+ (includes some system headers)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Sat, 14 Dec 2019 14:07:27 +0300
+
+qemu (1:4.1-3) unstable; urgency=medium
+
+ * mention #939869 (CVE-2019-15890) in previous changelog entry
+ * add Provides: sgabios to qemu-data (Closes: #945924)
+ * fix qemu-debootsrtap (add hppa arch, print correct error message)
+ thanks to Helge Deller (Closes: #923410)
+ * enable long binfmt masks again for mips/mips32 (Closes: #829243)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Mon, 02 Dec 2019 13:24:58 +0300
+
+qemu (1:4.1-2) unstable; urgency=medium
+
+ * build sgabios in build-indep, conflict with sgabios package
+ * qemu-system-ppc: build and install canyonlands.dtb in addition to bamboo.dtb
+ * remove duplicated CVE-2018-20123 & CVE-2018-20124 in prev changelog
+ * move s390 firmware build rules to debian/s390fw.mak, build s390-netboot.img
+ * imported v4.1.1.diff - upstream stable branch
+ Closes: CVE-2019-12068
+ Closes: #945258, #945072
+ * enable-pschange-mc-no.patch: i386: add PSCHANGE_MC_NO feature
+ to allow disabling ITLB multihit mitigations in nested hypervisors
+ Closes: #944623
+ * build-depend on nettle-dev, enable nettle, and clarify --enable-lzo
+ * switch to system libslirp, build-depend on libslirp-dev
+ Closes: #939869, CVE-2019-15890
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Mon, 25 Nov 2019 12:54:05 +0300
+
+qemu (1:4.1-1) unstable; urgency=medium
+
+ * new upstream release v4.1
+ Closes: #933741, CVE-2019-14378 (slirp buff overflow in packet reassembly)
+ (use internal slirp copy for now)
+ Closes: #931351, CVE-2019-13164 (qemu-bridge-helper long IFNAME)
+ Closes: #922923, CVE-2019-8934 (ppc64 emulator leaks hw identity)
+ Closes: #916442, CVE-2018-20123 (pvrdma memory leak in device hotplug)
+ Closes: #922461, CVE-2018-20124 (pvrdma num_sge can exceed MAX_SGE)
+ Closes: #927924 (new upstream version)
+ Closes: #897054 (AMD Zen CPU support)
+ Closes: #935324 (FTBFS due to gluster API change)
+ Closes: CVE-2018-20125 (pvrdma: DoS in create_cq_ring|create_qp_rings)
+ Closes: CVE-2018-20126 (pvrdma: memleaks in create_cq_ring|create_qp_rings)
+ Closes: CVE-2018-20191 (pvrdma: DoS due to missing read operation impl.)
+ Closes: CVE-2018-20216 (pvrdma: infinite loop in pvrdma_dev_ring.c)
+ * remove patches which are applied upstream, refresh remaining patches
+ (bt-use-size_t-...-CVE-2018-19665.patch hasn't been applied upstream,
+ bluetooth subsystem is going to be removed, we keep it for now)
+ * debian/source/options: ignore slirp/ submodule
+ * use python3 for building, not python
+ * debian/optionrom.mk: add pvh.bin
+ * switch from libssh2 to libssh, and enable libssh support in ubuntu
+ * bump spice version requiriment to 0.12.5
+ * enable pvrdma
+ * debian/control-in: remove reference to libsdl
+ * debian/rules: add new objects for s390-ccw fw
+ * debian/control: add build dependency on python3-sphinx for docs
+ * install ui/icons/qemu.svg and qemu.desktop
+ * debian/rules: remove pc-bios/bamboo.dtb before building it
+ * install vhost-user-gpu binary and 50-qemu-gpu.json
+ * debian/rules: remove old maintscript-helper invocations, not needed anymore
+ * remove +dfsg for now, upload whole upstream source, will trim it later
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Tue, 27 Aug 2019 12:43:43 +0300
+
+qemu (1:3.1+dfsg-8) unstable; urgency=high
+
+ * sun4u-add-power_mem_read-routine-CVE-2019-5008.patch
+ fixes a null-pointer dereference in sparc/sun4u emulated hw
+ Closes: #927439, CVE-2019-5008
+ * enable-md-no.patch & enable-md-clear.patch
+ mitigation for MDS (Microarchitectural Data Sampling) issues
+ Closes: #929067,
+ CVE-2018-12126, CVE-2018-12127, CVE-2018-12130, CVE-2019-11091
+ * qxl-check-release-info-object-CVE-2019-12155.patch
+ fixes null-pointer deref in qxl cleanup code
+ Closes: #929353, CVE-2019-12155
+ * aarch32-exception-return-to-switch-from-hyp-mon.patch
+ fixes booting U-Boot in UEFI mode on aarch32
+ Closes: #927763
+ * stop qemu-system-common pre-depending on adduser
+ Closes: #929261
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Mon, 27 May 2019 07:49:25 +0300
+
+qemu (1:3.1+dfsg-7) unstable; urgency=high
+
+ [ Michael Tokarev ]
+ * device_tree-don-t-use-load_image-CVE-2018-20815.patch
+ fix heap buffer overflow while loading device tree blob
+ (Closes: CVE-2018-20815)
+
+ [ Christian Ehrhardt ]
+ * qemu-guest-agent: fix path of fsfreeze-hook (LP: #1820291)
+ - d/qemu-guest-agent.install: use correct path for fsfreeze-hook
+ - d/qemu-guest-agent.pre{rm|inst}/.postrm: special handling for
+ mv_conffile since the new path is a directory in the old package
+ version which can not be handled by mv_conffile.
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Wed, 27 Mar 2019 14:24:06 +0300
+
+qemu (1:3.1+dfsg-6) unstable; urgency=high
+
+ * slirp-check-sscanf-result-when-emulating-ident-CVE-2019-9824.patch
+ fix information leakage in slirp code (Closes: CVE-2019-9824)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Mon, 18 Mar 2019 14:41:51 +0300
+
+qemu (1:3.1+dfsg-5) unstable; urgency=high
+
+ * i2c-ddc-fix-oob-read-CVE-2019-3812.patch fixes
+ OOB read in hw/i2c/i2c-ddc.c which allows for memory disclosure.
+ Closes: #922635, CVE-2019-3812
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Mon, 11 Mar 2019 14:30:44 +0300
+
+qemu (1:3.1+dfsg-4) unstable; urgency=medium
+
+ * mention closing of #855043 by 3.1+dfsg-3
+ * disable pvrdma for now, it is a bit too buggy.
+ Besides several security holes there are many other bugs there as well,
+ and the amount of patches applied upstream after 3.1 release is large
+ (Closes, or really makes unimportant again: CVE-2018-20123 CVE-2018-20124
+ CVE-2018-20125 CVE-2018-20126 CVE-2018-20191 CVE-2018-20216)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Mon, 11 Feb 2019 14:00:09 +0300
+
+qemu (1:3.1+dfsg-3) unstable; urgency=medium
+
+ [ Michael Tokarev ]
+ * mention #696289 closed by 2.10
+ * move ovmf to recommends on debian and update aarch ovmf refs
+ (Closes: #889885, #855043)
+ * remove /dev/kvm permission handling (moved to systemd 239-6)
+ (Closes: #892945)
+ * build qemu-palcode using alpha cross-compiler
+ (Closes: #913103)
+ * fix path in qemu-guest-agent.service (#918378), fixs Bind[s]To
+ (Closes: #918378
+ * use int for sparc64 timeval.tv_usec
+ (Closes: #920032)
+ * build-depend on libglusterfs-dev not glusterfs-common
+ (Closes: #919668, #881527)
+ * add breaks: qemu-system-data to qemu-system-common,
+ to close #916279 completely (all this can be removed after buster)
+ (Closes: #916279)
+ * scsi-generic-avoid-possible-oob-access-to-r-buf-CVE-2019-6501.patch
+ (Closes: #920222, CVE-2019-6501)
+ * slirp-check-data-length-while-emulating-ident-function-CVE-2019-6778.patch
+ (Closes: #921525)
+ * pvrdma-release-device-resources-on-error-CVE-2018-20123.patch
+ (Closes: #916442, CVE-2018-20123)
+ * enable rdma and pvrdma, build-depend on
+ librdmacm-dev, libibverbs-dev, libibumad-dev
+ * sync debian/qemu-user-static.1 and debian/qemu-user.1 generate the latter
+ from the former (finally Closes: #901407)
+ * move ivshmem-server & ivshmem-client from qemu-utils to qemu-system-common
+ (the binaries are also specific to qemu-system, not useable alone)
+ * move qemu-pr-helper from qemu-utils to qemu-system-common -
+ this is an internal qemu-system helper, with possible socket activation,
+ not intended for use outside of qemu-system
+
+ [ Christian Ehrhardt ]
+ * qemu-guest-agent: freeze-hook to ignore dpkg files (packaging changes)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Wed, 06 Feb 2019 12:23:01 +0300
+
+qemu (1:3.1+dfsg-2) unstable; urgency=medium
+
+ * d/rules: split arch and indep builds
+ * enable s390x cross-compiler and build s390-ccw.img (Closes: #684909)
+ * build x86 optionrom in qemu-system-data (was in seabios/debian/)
+ * qemu-system-data: Multi-Arch: allowed=>foreign (Closes: #903562)
+ * fix Replaces: version for qemu-system-common (Closes: #916279)
+ * add simple udev rules file for systemd guest agent (Closes: #916674)
+ * usb-mtp-use-O_NOFOLLOW-and-O_CLOEXEC-CVE-2018-16872.patch
+ Race condition in usb_mtp implementation (Closes: #916397)
+ * bt-use-size_t-type-for-length-parameters-instead-of-int-CVE-2018-19665.patch
+ Memory corruption in bluetooth subsystem (Closes: #916278)
+ * hw_usb-fix-mistaken-de-initialization-of-CCID-state.patch (Closes: #917007)
+ * bump debhelper compat to 12 (>>11)
+ * d/rules: use dh_missing instead of dh_install --list-missing (compat=12)
+ * use dh_installsystemd for guest agent (Closes: #916625)
+ * mention closing by 3.1: Closes: #912655, CVE-2018-16847
+ * mention closing by 2.10:
+ Closes: #849798, CVE-2016-10028
+ Closes: CVE-2017-9060
+ Closes: CVE-2017-8284
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Fri, 21 Dec 2018 16:51:39 +0300
+
+qemu (1:3.1+dfsg-1) unstable; urgency=medium
+
+ * new upstream release (3.1)
+ * Security bugs fixed by upstream:
+ Closes: #910431, CVE-2018-10839:
+ integer overflow leads to buffer overflow issue
+ Closes: #911468, CVE-2018-17962
+ pcnet: integer overflow leads to buffer overflow
+ Closes: #911469, CVE-2018-17963
+ net: ignore packets with large size
+ Closes: #908682, CVE-2018-3639
+ qemu should be able to pass the ssbd cpu flag
+ Closes: #901017, CVE-2018-11806
+ m_cat in slirp/mbuf.c in Qemu has a heap-based buffer overflow
+ via incoming fragmented datagrams
+ Closes: #902725, CVE-2018-12617
+ qmp_guest_file_read in qemu-ga has an integer overflow
+ Closes: #907500, CVE-2018-15746
+ qemu-seccomp might allow local OS guest users to cause a denial of service
+ Closes: #915884, CVE-2018-16867
+ dev-mtp: path traversal in usb_mtp_write_data of the MTP
+ Closes: #911499, CVE-2018-17958
+ Buffer Overflow in rtl8139_do_receive in hw/net/rtl8139.c
+ because an incorrect integer data type is used
+ Closes: #911470, CVE-2018-18438
+ integer overflows because IOReadHandler and its associated functions
+ use a signed integer data type for a size value
+ Closes: #912535, CVE-2018-18849
+ lsi53c895a: OOB msg buffer access leads to DoS
+ Closes: #914604, CVE-2018-18954
+ pnv_lpc_do_eccb function in hw/ppc/pnv_lpc.c in Qemu before 3.1
+ allows out-of-bounds write or read access to PowerNV memory
+ Closes: #914599, CVE-2018-19364
+ Use-after-free due to race condition while updating fid path
+ Closes: #914727, CVE-2018-19489
+ 9pfs: crash due to race condition in renaming files
+ Closes: #912655, CVE-2018-16847
+ Out-of-bounds r/w buffer access in cmb operations
+ * remove patches which were applied upstream
+ * add new manpage qemu-cpu-models.7
+ * qemu-system-ppcemb is gone, use qemu-system-ppc[64]
+ * do-not-link-everything-with-xen.patch (trivial)
+ * get-orig-source: handle 3.x and 4.x, and remove roms again, as
+ upstream wants us to use separate source packages for that stuff
+ * move generated data from qemu-system-data back to qemu-system-common
+ * d/control: enable spice on arm64 (Closes: #902501)
+ (probably should enable on all)
+ * d/control: change git@salsa urls to https
+ * add qemu-guest-agent.service (Closes: #795486)
+ * enable opengl support and virglrenderer (Closes: #813658)
+ * simplify d/rules just a little bit
+ * build-depend on libudev-dev, for qga
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Sun, 02 Dec 2018 19:10:27 +0300
+
+qemu (1:2.12+dfsg-3) unstable; urgency=medium
+
+ * make qemu-system-foo depending
+ on qemu-system-data >>ver~, not >>ver
+ (Closes: #900585)
+ * do not build qemu-system-gui on hppa
+ * use dh_lintian for lintian overrides
+ * update VCS fields to point to salsa.debian.org
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Fri, 01 Jun 2018 21:42:29 +0300
+
+qemu (1:2.12+dfsg-2) unstable; urgency=medium
+
+ * create new package, qemu-system-gui,
+ and package GTK module and audio modules in there
+ Closes: #850584
+ * add an item about qemu-system-gui to debian/qemu-system-common.NEWS
+ * qemu-system-*: require more recent qemu-system-common
+ * switch all builds to be in a single b/ subdir
+ * d/get-orig-source: remove .oco (object) files from roms/SLOF/
+ * refresh patches/use-fixed-data-path.patch: remove now-unused local var too
+ * ccid-card-passthru-fix-regression-in-realize.patch (Closes: #900006)
+ * debian/control-in: enable seccomp on linux-any (Closes: #900055)
+ * create new arch-indep package qemu-system-data, for data and firmware files.
+ Move common data files from qemu-system-common to it, for now
+ * fix sata/ahci stalls (ahci-fix-PxCI-register-race.patch)
+ * tcg-i386-Fix-dup_vec-in-non-AVX2-codepath.patch (Closes: #900372)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Thu, 31 May 2018 13:22:55 +0300
+
+qemu (1:2.12+dfsg-1) unstable; urgency=medium
+
+ * new upstream release
+ * get-orig-source: do not remove roms/* directories,
+ since we will use these to build the roms
+ * disable building on hppa arch (not supported upstream since ong time)
+ * Use https://download.qemu.org to download new tarballs (Closes: #895067)
+ * add Breaks: binfmt-support (<<2.1.7) so that --fix-binary works;
+ also fix qemu-user-static description (Closes: #896478)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Thu, 26 Apr 2018 20:29:36 +0300
+
+qemu (1:2.12~rc3+dfsg-2) unstable; urgency=medium
+
+ * fix typo in previous changelog entry
+ * add riscv32/riscv64 to qemu-debootstrap
+ * install gtk message catalogs into qemu-system-common (Closes: #878130)
+ (and install-gtk-message-catalogs-if-CONFIG_GTK.patch)
+ * tcg_mips-handle-large-offsets-from-target-env-to-tlb_table.patch:
+ fix FTBFS on mips targets
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Sat, 14 Apr 2018 17:01:24 +0300
+
+qemu (1:2.12~rc3+dfsg-1) unstable; urgency=medium
+
+ * new upstream 2.12 release (Release Candidate 3)
+ Closes: #892041, CVE-2018-7550
+ Closes: #884806, CVE-2017-15124
+ Closes: #887392, CVE-2018-5683
+ Closes: #892497, CVE-2018-7858
+ Closes: #882136, CVE-2017-16845
+ Closes: #886532, #892947, #891375, #887892, #860822, #851694
+ * refresh local debian patches
+ * d/rules: enable new system (hppa riscv32 riscv64) and
+ user (aarch64_be xtensa xtensaeb riscv32 riscv64) targets
+ Closes: #893767
+ * fix d/source/options to match current reality
+ * drop use-data-path.patch, upstream now has --firmwarepath= option
+ * enable capstone disassembler library support
+ (build-depend on libcapstone-dev)
+ * debian/extract-config-opts: use tab for option / condition separator
+ * qemu-block-extra: install only block modules
+ * make `qemu' metapackage to be dummy, to remove it in a future release
+ * do not suggest kmod, it is pointless
+ * install /usr/bin/qemu-pr-helper to qemu-utils package
+ * switch from sdl2 to gtk ui
+ Closes: #839695, #886671, #879536, #879534, #879532, #879193, #894852
+ * qemu-system-ppc: forgotten qemu-system-ppc64le.1 link
+ * mention closing of #880582 by 2.11
+ * package will built against spice 0.14, so Closes: #854959
+ * check sfdisk presence in qemu-make-debian-root (Closes: #872098)
+ * check mke2fs presence in qemu-make-debian-root (Closes: #887207)
+ * debian/binfmt-update-in: include forgotten hppa (Closes: #891261)
+ * debian/TODO: removed some old ToDo items
+ * use binfmt-support --fix-binary option (Closes: #868030)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Thu, 12 Apr 2018 19:04:03 +0300
+
+qemu (1:2.11+dfsg-1) unstable; urgency=medium
+
+ [ Michael Tokarev ]
+ * update to new upstream (2.11) release
+ Closes: #883625, CVE-2017-17381
+ Closes: #880832, CVE-2017-15289
+ Closes: #880836, CVE-2017-15268
+ Closes: #883399, CVE-2017-15119
+ Closes: #883406, CVE-2017-15118
+ Closes: #880582
+ * update to new upstream, remove old patches, refresh debian patches
+ * disable sdl audio driver (pulse or oss should work fine)
+ * do not build-depend on libx11-dev (libsdl2-dev already depends on it)
+ * move libpulse-dev build-dep to a better place
+ * clean up d/control from various old conflicts/replaces/provides
+ * remove --with-system-pixman, not used anymore
+ * remove ubuntu-specific qemu-system-aarch64 transitional package (trusty)
+ * remove ubuntu-specific mentions of old qemu-kvm-spice package (precise)
+ * remove old comment about /etc/kvm from qemu-kvm description
+ * add Suggests: openbios-sparc for qemu-system-sparc on ubuntu
+ (similar to what is done for qemu-system-ppc)
+ * update get-orig-source.sh with new blobs/submodules
+ * update debian/watch a bit
+
+ [ Aurelien Jarno ]
+ * debian/control-in: build qemu-system and qemu-user on mips64 and
+ mips64el. Closes: #880485.
+
+ [ Christian Ehrhardt ]
+ * ppc64[le]: provide symlink matching arch name
+ * d/control-in: Enable seccomp for ppc64el,
+ this bumps minimum libseccomp version
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Thu, 11 Jan 2018 14:42:12 +0300
+
+qemu (1:2.10.0+dfsg-2) unstable; urgency=medium
+
+ * update to upstream 2.10.1 point release
+ Closes: #877160
+ Closes: CVE-2017-13673
+ * remove 3 patches included upstream:
+ multiboot-validate-multiboot-header-address-values-CVE-2017-14167.patch
+ vga-stop-passing-pointers-to-vga_draw_line-functions-CVE-2017-13672.patch
+ slirp-fix-clearing-ifq_so-from-pending-packets-CVE-2017-13711.patch
+ * 9pfs-use-g_malloc0-to-allocate-space-for-xattr-CVE-2017-15038.patch
+ Closes: #877890, CVE-2017-15038
+ * remove-trailing-whitespace-from-qemu-options.hx.patch
+ Closes: #875711
+ * drop dh_makeshlibs call (was for libcacard)
+ * drop linux-libc-dev build-dependency (it gets pulled by libc-dev)
+ * switch from sdl1 to sdl2 (Closes: #870025)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Sun, 08 Oct 2017 12:51:09 +0300
+
+qemu (1:2.10.0+dfsg-1) unstable; urgency=medium
+
+ * remove blobs, to DFSG'ify it again (there's still
+ no source for some blobs included in upstream tarball)
+ There's no way to revert to 2-number version due to prev. upload
+ * update from upstream git (no changes but include date & commit-id):
+ multiboot-validate-multiboot-header-address-values-CVE-2017-14167.patch
+ * update previous changelog entry (fix bug/closes refs):
+ Closes: #873851, CVE-2017-13672
+ Closes: #874606, CVE-2017-14167
+ Closes: #873875, CVE-2017-13711
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Mon, 25 Sep 2017 09:46:53 +0300
+
+qemu (1:2.10.0-1) unstable; urgency=medium
+
+ * new upstream release, 2.10
+ Closes: #865754, CVE-2017-9503
+ Closes: #864219, CVE-2017-9375
+ Closes: #869945
+ Closes: #867978
+ Closes: #871648, #871702, #872257
+ Closes: #851694
+ Closes: #696289
+ Closed in this upstream release:
+ #865755, CVE-2017-9524
+ #863840, CVE-2017-9310
+ #863943, CVE-2017-9330
+ #864216, CVE-2017-9373
+ #864568, CVE-2017-9374
+ #869171, CVE-2017-11434
+ #869173, CVE-2017-11334
+ #869706, CVE-2017-10911
+ #867751, CVE-2017-10806
+ #866674, CVE-2017-10664
+ #873849, CVE-2017-12809
+ #849798, CVE-2016-10028
+ CVE-2017-9060
+ CVE-2017-8284
+ * dropped all fixes, applied upstream
+ * dropped 02_kfreebsd.patch - apparently not relevant anymore
+ * dropped +dfsg, use upstream tarball directly: we do not use
+ binaries shipped there, and even for those, upstream tarball
+ contains the sources
+ * refreshed list of targets:
+ qemu-or32, qemu-system-or32 => qemu-or1k, qemu-system-or1k
+ +qemu-nios2, qemu-system-nios2
+ +qemu-hppa
+ * added hppa binfmt entry
+ * refreshed docs lists for various packages
+ * new (security) patches:
+ vga-stop-passing-pointers-to-vga_draw_line-functions-CVE-2017-13672.patch
+ Closes: #873851, CVE-2017-13672
+ multiboot-validate-multiboot-header-address-values-CVE-2017-14167.patch
+ Closes: #874606, CVE-2017-14167
+ slirp-fix-clearing-ifq_so-from-pending-packets-CVE-2017-13711.patch
+ Closes: #873875, CVE-2017-13711
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Sat, 23 Sep 2017 16:47:02 +0300
+
+qemu (1:2.8+dfsg-7) unstable; urgency=medium
+
+ * uploading to unstable all fixes which went to stretch-security
+ (exactly the same as 2.8+dfsg-6+deb9u2)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Sat, 05 Aug 2017 16:35:01 +0300
+
+qemu (1:2.8+dfsg-6+deb9u2) stretch-security; urgency=high
+
+ * actually apply the nbd server patches, not only include in debian/patches/
+ Really closes: #865755, CVE-2017-9524
+ * slirp-check-len-against-dhcp-options-array-end-CVE-2017-11434.patch
+ Closes: #869171, CVE-2017-11434
+ * exec-use-qemu_ram_ptr_length-to-access-guest-ram-CVE-2017-11334.patch
+ Closes: #869173, CVE-2017-11334
+ * usb-redir-fix-stack-overflow-in-usbredir_log_data-CVE-2017-10806.patch
+ Closes: #867751, CVE-2017-10806
+ * add reference to #869706 to
+ xen-disk-don-t-leak-stack-data-via-response-ring-CVE-2017-10911.patch
+ * disable xhci recursive calls fix for now, as it causes instant crash
+ (xhci-guard-xhci_kick_epctx-against-recursive-calls-CVE-2017-9375.patch)
+ Reopens: #864219, CVE-2017-9375
+ Closes: #869945
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Wed, 02 Aug 2017 16:57:34 +0300
+
+qemu (1:2.8+dfsg-6+deb9u1) stretch-security; urgency=high
+
+ * net-e1000e-fix-an-infinite-loop-issue-CVE-2017-9310.patch
+ Closes: #863840, CVE-2017-9310
+ * usb-ohci-fix-error-return-code-in-servicing-iso-td-CVE-2017-9330.patch
+ Closes: #863943, CVE-2017-9330
+ * ide-ahci-call-cleanup-function-in-ahci-unit-CVE-2017-9373.patch
+ Closes: #864216, CVE-2017-9373
+ * xhci-guard-xhci_kick_epctx-against-recursive-calls-CVE-2017-9375.patch
+ Closes: #864219, CVE-2017-9375
+ * usb-ehci-fix-memory-leak-in-ehci-CVE-2017-9374.patch
+ Closes: #864568, CVE-2017-9374
+ * nbd-ignore-SIGPIPE-CVE-2017-10664.patch
+ Closes: #866674, CVE-2017-10664
+ * nbd-fully-initialize-client-in-case-of-failed-negotiation-CVE-2017-9524.patch
+ nbd-fix-regression-on-resiliency-to-port-scan-CVE-2017-9524.patch
+ Closes: #865755, CVE-2017-9524
+ * xen-disk-don-t-leak-stack-data-via-response-ring-CVE-2017-10911.patch
+ Closes: CVE-2017-10911
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Wed, 12 Jul 2017 11:05:16 +0300
+
+qemu (1:2.8+dfsg-6) unstable; urgency=high
+
+ * 9pfs-local-forbid-client-access-to-metadata-CVE-2017-7493.patch
+ Closes: CVE-2017-7493
+ * group all 9p patches together
+ * drop obsolete comment about libiscsi on ubuntu from d/control
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Tue, 23 May 2017 09:58:03 +0300
+
+qemu (1:2.8+dfsg-5) unstable; urgency=high
+
+ * Security fix release
+ * 9pfs-local-set-path-of-export-root-to-dot-CVE-2017-7471.patch
+ Closes: #860785, CVE-2017-7471
+ * 9pfs-xattr-fix-memory-leak-in-v9fs_list_xattr-CVE-2017-8086.patch
+ Closes: #861348, CVE-2017-8086
+ * vmw_pvscsi-check-message-ring-page-count-at-init-CVE-2017-8112.patch
+ Closes: #861351, CVE-2017-8112
+ * scsi-avoid-an-off-by-one-error-in-megasas_mmio_write-CVE-2017-8380.patch
+ Closes: #862282, CVE-2017-8380
+ * input-limit-kbd-queue-depth-CVE-2017-8379.patch
+ Closes: #862289, CVE-2017-8379
+ * audio-release-capture-buffers-CVE-2017-8309.patch
+ Closes: #862280, CVE-2017-8309
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Wed, 17 May 2017 09:01:24 +0300
+
+qemu (1:2.8+dfsg-4) unstable; urgency=high
+
+ * usb-ohci-limit-the-number-of-link-eds-CVE-2017-6505.patch
+ Closes: #856969, CVE-2017-6505
+ * linux-user-fix-apt-get-update-on-linux-user-hppa.patch
+ Closes: #846084
+ * update to 2.8.1 upstream stable/bugfix release
+ (v2.8.1.diff from upstream, except of seabios blob bits).
+ Closes: #857744, CVE-2016-9603
+ Patches dropped because they're included in 2.8.1 release:
+ 9pfs-symlink-attack-fixes-CVE-2016-9602.patch
+ char-fix-ctrl-a-b-not-working.patch
+ cirrus-add-blit_is_unsafe-to-cirrus_bitblt_cputovideo-CVE-2017-2620.patch
+ cirrus-fix-oob-access-issue-CVE-2017-2615.patch
+ cirrus-ignore-source-pitch-as-needed-in-blit_is_unsafe.patch
+ linux-user-fix-s390x-safe-syscall-for-z900.patch
+ nbd_client-fix-drop_sync-CVE-2017-2630.patch
+ s390x-use-qemu-cpu-model-in-user-mode.patch
+ sd-sdhci-check-data-length-during-dma_memory_read-CVE-2017-5667.patch
+ virtio-crypto-fix-possible-integer-and-heap-overflow-CVE-2017-5931.patch
+ vmxnet3-fix-memory-corruption-on-vlan-header-stripping-CVE-2017-6058.patch
+ * bump seabios dependency to 1.10.2 due to ahci fix in 2.8.1
+ * 9pfs-fix-file-descriptor-leak-CVE-2017-7377.patch
+ (Closes: #859854, CVE-2017-7377)
+ * dma-rc4030-limit-interval-timer-reload-value-CVE-2016-8667.patch
+ Closes: #840950, CVE-2016-8667
+ * make d/control un-writable to stop users from changing a generated file
+ * two patches from upstream to fix user-mode network with IPv6
+ slirp-make-RA-build-more-flexible.patch
+ slirp-send-RDNSS-in-RA-only-if-host-has-an-IPv6-DNS.patch
+ (Closes: #844566)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Mon, 03 Apr 2017 16:28:49 +0300
+
+qemu (1:2.8+dfsg-3) unstable; urgency=high
+
+ * urgency high due to security fixes
+
+ [ Michael Tokarev ]
+ * serial-fix-memory-leak-in-serial-exit-CVE-2017-5579.patch
+ Closes: #853002, CVE-2017-5579
+ * cirrus-ignore-source-pitch-as-needed-in-blit_is_unsafe.patch
+ (needed for the next patch, CVE-2017-2620 fix)
+ * cirrus-add-blit_is_unsafe-to-cirrus_bitblt_cputovideo-CVE-2017-2620.patch
+ Closes: #855791, CVE-2017-2620
+ * nbd_client-fix-drop_sync-CVE-2017-2630.diff
+ Closes: #855227, CVE-2017-2630
+ * sd-sdhci-check-transfer-mode-register-in-multi-block-CVE-2017-5987.patch
+ Closes: #855159, CVE-2017-5987
+ * vmxnet3-fix-memory-corruption-on-vlan-header-stripping-CVE-2017-6058.patch
+ Closes: #855616, CVE-2017-6058
+ * 3 CVE fixes from upstream for #853996:
+ sd-sdhci-check-data-length-during-dma_memory_read-CVE-2017-5667.patch
+ megasas-fix-guest-triggered-memory-leak-CVE-2017-5856.patch
+ virtio-gpu-fix-resource-leak-in-virgl_cmd_resource-CVE-2017-5857.patch
+ Closes: #853996, CVE-2017-5667, CVE-2017-5856, CVE-2017-5857
+ * usb-ccid-check-ccid-apdu-length-CVE-2017-5898.patch
+ Closes: #854729, CVE-2017-5898
+ * virtio-crypto-fix-possible-integer-and-heap-overflow-CVE-2017-5931.patch
+ Closes: #854730, CVE-2017-5931
+ * xhci-apply-limits-to-loops-CVE-2017-5973.patch
+ Closes: #855611, CVE-2017-5973
+ * net-imx-limit-buffer-descriptor-count-CVE-2016-7907.patch
+ Closes: #839986, CVE-2016-7907
+ * cirrus-fix-oob-access-issue-CVE-2017-2615.patch
+ Closes: #854731, CVE-2017-2615
+ * 9pfs-symlink-attack-fixes-CVE-2016-9602.patch
+ Closes: #853006
+ * vnc-do-not-disconnect-on-EAGAIN.patch
+ Closes: #854032
+ * xhci-fix-event-queue-IRQ-handling.patch (win7 xhci issue fix)
+ * xhci-only-free-completed-transfers.patch
+ Closes: #855659
+ * char-fix-ctrl-a-b-not-working.patch
+ Closes: https://bugs.launchpad.net/bugs/1654137
+ * char-drop-data-written-to-a-disconnected-pty.patch
+ Closes: https://bugs.launchpad.net/bugs/1667033
+ * s390x-use-qemu-cpu-model-in-user-mode.patch
+ Closes: #854893
+ * d/control is autogenerated, add comment
+ * check if debootstrap is available in qemu-debootstrap
+ Closes: #846497
+
+ [ Christian Ehrhardt ]
+ * (ubuntu) no more skip enable libiscsi (now in main)
+ * (ubuntu) Disable glusterfs (Universe dependency)
+ * (ubuntu) have qemu-system-arm suggest: qemu-efi;
+ this should be a stronger relationship, but qemu-efi is still
+ in universe right now.
+ * (ubuntu) change dependencies for fix of wrong acl for newly
+ created device node on ubuntu
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Tue, 28 Feb 2017 11:40:18 +0300
+
+qemu (1:2.8+dfsg-2) unstable; urgency=medium
+
+ * Revert "update binfmt registration for mipsn32"
+ Reopens: #829243
+ Closes: #843032
+ Will re-enable it for stretch+1, since for now upgrades
+ from jessie are broken (jessie comes with 3.16 kernel),
+ and there's no easy fix for this
+ * Revert "enable virtio gpu (virglrenderer) and opengl support"
+ Revert "switch from sdl1 to gtk3"
+ Revert other gtk2/drm/vte/virgl-related changes
+ Reopens: #813658, #839695
+ The change were too close to stretch release and too large,
+ bringing too much graphics stuff for headless servers,
+ will re-think this for stretch+1.
+ sdl1 back: Closes: #851509
+ virtio-3d bugs: Closes: #849798, #852119
+ * mention closing of #769983 (multi-threaded linux-user) by 2.7
+ * mention closing of #842455, CVE-2016-9101 by 2.8
+ * audio-ac97-add-exit-function-CVE-2017-5525.patch (Closes: #852021)
+ * audio-es1370-add-exit-function-CVE-2017-5526.patch (Closes: #851910)
+ * watchdog-6300esb-add-exit-function-CVE-2016-10155.patch (Closes: #852232)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Mon, 23 Jan 2017 14:06:54 +0300
+
+qemu (1:2.8+dfsg-1) unstable; urgency=medium
+
+ * new upstream release
+ Closes: #837191, CVE-2016-7156
+ Closes: #837316, CVE-2016-7170
+ Closes: #839835, CVE-2016-7908
+ Closes: #839834, CVE-2016-7909
+ Closes: #840228, CVE-2016-7994
+ Closes: #840236, CVE-2016-7995
+ Closes: #840343, CVE-2016-8576
+ Closes: #840341, CVE-2016-8577
+ Closes: #840340, CVE-2016-8578
+ Closes: #840948, CVE-2016-8668
+ Closes: #840945, CVE-2016-8669
+ Closes: #841950, CVE-2016-8909
+ Closes: #841955, CVE-2016-8910
+ Closes: #842463, CVE-2016-9102 CVE-2016-9103 CVE-2016-9104
+ CVE-2016-9105 CVE-2016-9106
+ Closes: #846797, CVE-2016-9776
+ Closes: #847381, CVE-2016-9845
+ Closes: #847382, CVE-2017-9846
+ Closes: #847953, CVE-2016-9907
+ Closes: #847400, CVE-2016-9908
+ Closes: #847951, CVE-2016-9911
+ Closes: #847391, CVE-2016-9912
+ Closes: #847496, CVE-2016-9913 CVE-2016-9914 CVE-2016-9915 CVE-2016-9916
+ Closes: #847960, CVE-2016-9921 CVE-2016-9922
+ Closes: #847957, CVE-2016-9923
+ Closes: #842455, CVE-2016-9101 (git2634ab7fe29b3f75d0865b719caf8f310d634aae)
+ Closes: #819755, #833162
+ Hopefully closes: #844361
+ * remove unicore32 linux-user target, removed upstream
+ * remove all patches which were applied upstream (most of them)
+ * actually fix #841060
+ * doc-don-t-mention-memory-it-is-m.patch, Closes: #833619
+ * don't pass --enable-uuid (always enabled)
+ * build-depend on libncursesw5-dev, not libncurses5-dev
+ * install trace-events-all in qemu-system-common
+ * do not install qemu-tech.html (not provided by upstream anymore)
+ * switch from sdl1 to gtk3 (Closes: #839695)
+ * enable virtio gpu (virglrenderer) and opengl support (Closes: #813658)
+ * strip out -ldrm out of OPENGL_LIBS, since libdrm is actually not needed
+ * enable nfs support (libnfs-dev), in qemu-block-extra
+ * enable glusterfs support (glusterfs-common), in qemu-block-extra
+ (Closes: #775431)
+ * enable numa support (libnuma-dev) (Closes: #758189)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Wed, 28 Dec 2016 15:31:37 +0300
+
+qemu (1:2.7+dfsg-3) unstable; urgency=medium
+
+ * add PIE.patch to change loadable modules linker flags, from Adrian
+ (Closes: #837574)
+ * linux-user-fix-s390x-safe-syscall-for-z900.patch - fix FTBFS on s390x
+ * mention CVE-2016-7466 for 2.7+dfsg-1 (Closes: #838687, CVE-2016-7466)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Thu, 27 Oct 2016 19:38:01 +0300
+
+qemu (1:2.7+dfsg-2) unstable; urgency=medium
+
+ * fix distribution field in previous changelog entry
+ * add depends: on seabios >= 1.9 with linuxboot_dma.bin
+ (Closes: #840853, #841060, #842161)
+ * add more links for openbios-sparc to qemu-system-sparc,
+ bump dependency (Closes: #827456)
+ * include license for qemu logo files (Closes: #785362)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Wed, 26 Oct 2016 20:04:15 +0300
+
+qemu (1:2.7+dfsg-1) unstable; urgency=medium
+
+ * Acknowledge the previous NMU. Thank you Andrew!
+ * New upstream release, 2.7 (Closes: #748043, #839292)
+ Closes: #838850, CVE-2016-7161
+ Closes: #473240 (qcow encryption support has been removed)
+ Closes: #769983 (multi-threaded linux-user)
+ * removed patches which went upstream, refreshed use-data-path.patch
+ * renamed remaining patches to include CVE#s and added Bug-Debian headers
+ * added Depends on lsb-base to qemu-guest-agent (Closes: #840740)
+ * update binfmt registration for mipsn32 (Closes: #829243)
+ Thank you Adam Borowski for investigation and the patch
+ * replace CVE-2016-7156 (#837339) patch with actual code from upstream
+ * scsi-mptsas-use-g_new0-to-allocate-MPTSASRequest-obj-CVE-2016-7423.patch
+ (Closes: #838145, CVE-2016-7423)
+ * virtio-add-check-for-descriptor-s-mapped-address-CVE-2016-7422.patch
+ (Closes: #838146, CVE-2016-7422)
+ * scsi-pvscsi-limit-process-IO-loop-to-ring-size-CVE-2016-7421.patch
+ (Closes: #838147, CVE-2016-7421)
+ * usb-xhci-fix-memory-leak-in-usb_xhci_exit-CVE-2016-7466.patch
+ (Closes: #838687, CVE-2016-7466)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Fri, 14 Oct 2016 13:31:40 +0300
+
+qemu (1:2.6+dfsg-3.1) unstable; urgency=high
+
+ * Non-maintainer upload.
+ * Security fixes from upstream:
+ - virtio-error-out-if-guest-exceeds-virtqueue-size-CVE-2015-5403.patch
+ (Closes: #832619, CVE-2015-5403)
+ - scsi-pvscsi-avoid-infinite-loop-while-building-SG-list.patch
+ (Closes: #837339, CVE-2016-7156)
+ - scsi-pvscsi-check-page-count-while-initialising-descriptor-rings.patch
+ (Closes: #837174, CVE-2016-7155)
+ - CVE-2016-6351: scsi-esp-make-cmdbuf-big-enough-for-maximum-CDB-size.patch
+ and scsi-esp-fix-migration.patch (Closes: #832621, CVE-2016-6351)
+ - virtio-check-vring-descriptor-buffer-length.patch
+ (Closes: #832767, CVE-2016-6490)
+ - net-vmxnet3-check-for-device_active-before-write.patch
+ (Closes: #834904, CVE-2016-6833)
+ - net-check-fragment-length-during-fragmentation.patch
+ (Closes: #834905, CVE-2016-6834)
+ - net-vmxnet-check-IP-header-length.patch (Closes: #835031, CVE-2016-6835)
+ - net-vmxnet-initialise-local-tx-descriptor.patch
+ (Closes: #834944, CVE-2016-6836)
+ - net-vmxnet-use-g_new-for-pkt-initialisation.patch
+ (Closes: #834902, CVE-2016-6888)
+ - CVE-2016-7116: 9pfs-forbid-.-and-.-in-file-names.patch,
+ 9pfs-forbid-illegal-path-names.patch and
+ 9pfs-handle-walk-of-.-in-the-root-directory.patch
+ (Closes: #836502, CVE-2016-7116)
+ - CVE-2016-7157: scsi-mptconfig-fix-an-assert-expression.patch and
+ scsi-mptconfig-fix-misuse-of-MPTSAS_CONFIG_PACK.patch
+ (Closes: #837603, CVE-2016-7157)
+
+ -- Andrew James <ajames@hpe.com> Wed, 14 Sep 2016 00:56:18 -0600
+
+qemu (1:2.6+dfsg-3) unstable; urgency=high
+
+ * more security fixes picked from upstream:
+ - CVE-2016-4454 fix (vmsvga) (Closes: CVE-2016-4454)
+ vmsvga-add-more-fifo-checks-CVE-2016-4454.patch
+ vmsvga-move-fifo-sanity-checks-to-vmsvga_fifo_length-CVE-2016-4454.patch
+ vmsvga-shadow-fifo-registers-CVE-2016-4454.patch
+ - vmsvga-don-t-process-more-than-1024-fifo-commands-at-once-CVE-2016-4453.patch
+ (Closes: CVE-2016-4453)
+ - scsi-check-buffer-length-before-reading-scsi-command-CVE-2016-5238.patch
+ (Closes: #826152, CVE-2016-5238)
+ * set urgency to high due to the amount of
+ security fixes accumulated so far
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Wed, 15 Jun 2016 08:54:12 +0300
+
+qemu (1:2.6+dfsg-2) unstable; urgency=medium
+
+ * add missing log entries for previous upload,
+ remove closing of #807006 (it is not closed)
+ * Added vga-add-sr_vbe-register-set.patch from upstream
+ This fixes regression (in particular with win7 installer)
+ introduced by the fix for CVE-2016-3712 (commit fd3c136)
+ * fix-linking-relocatable-objects-on-sparc.patch (Closes: #807006)
+ * Lots of security patches from upstream:
+ - net-mipsnet-check-packet-length-against-buffer-CVE-2016-4002.patch
+ (Closes: #821061, CVE-2016-4002)
+ - i386-kvmvapic-initialise-imm32-variable-CVE-2016-4020.patch
+ (Closes: #821062, CVE-2016-4020)
+ - esp-check-command-buffer-length-before-write-CVE-2016-4439.patch,
+ esp-check-dma-length-before-reading-scsi-command-CVE-2016-4441.patch
+ (Closes: #824856, CVE-2016-4439, CVE-2016-4441)
+ - scsi-mptsas-infinite-loop-while-fetching-requests-CVE-2016-4964.patch
+ (Closes: #825207, CVE-2016-4964)
+ - scsi-pvscsi-check-command-descriptor-ring-buffer-size-CVE-2016-4952.patch
+ (Closes: #825210, CVE-2016-4952)
+ - scsi-megasas-use-appropriate-property-buffer-size-CVE-2016-5106.patch
+ (Closes: #825615, CVE-2016-5106)
+ - scsi-megasas-initialise-local-configuration-data-buffer-CVE-2016-5105.patch
+ (Closes: #825614, CVE-2016-5105)
+ - scsi-megasas-check-read_queue_head-index-value-CVE-2016-5107.patch
+ (Closes: #825616, CVE-2016-5107)
+ - block-iscsi-avoid-potential-overflow-of-acb-task-cdb-CVE-2016-5126.patch
+ (Closes: #826151, CVE-2016-5126)
+ - scsi-esp-check-TI-buffer-index-before-read-write-CVE-2016-5338.patch
+ (Closes: #827024, CVE-2016-5338)
+ - scsi-megasas-null-terminate-bios-version-buffer-CVE-2016-5337.patch
+ (Closes: #827026, CVE-2016-5337)
+ * hw-dma-omap-spelling-fix-endianness.patch (lintian)
+ * arm-spelling-fix-mismatch.patch (lintian)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Mon, 13 Jun 2016 12:10:44 +0300
+
+qemu (1:2.6+dfsg-1) unstable; urgency=medium
+
+ * new upstream release
+ Closes: #799115
+ Closes: #822369, #823588
+ Closes: #813698
+ Closes: #805827
+ Closes: #813585
+ Closes: #823830 CVE-2016-3710 CVE-2016-3712
+ Closes: #813193 CVE-2016-2198
+ Closes: #813194 CVE-2016-2197
+ Closes: #815008 CVE-2016-2392
+ Closes: #815009 CVE-2016-2391
+ Closes: #815680 CVE-2016-2538
+ Closes: #821038 CVE-2016-4001
+ Closes: #822344 CVE-2016-4037
+ Closes: #817181 CVE-2016-2841
+ Closes: #817182 CVE-2016-2857
+ Closes: #817183 CVE-2016-2858
+ - removed all patches applied upstream
+ - removed mjt-set-oem-in-rsdt-like-slic.diff, feature has been
+ implemented in upstream differently
+ - refreshed local patches
+ * do not recommend sharutils for qemu-utils anymore (Closes: #820449)
+ * typo fix in qemu-system-misc description (Closes: #822883)
+ * allow qemu-debootstrap to create mips64el chroot (Closes: #817234)
+ * switch VCS URLs from http to https (lintian)
+ * Bump Standards-Version to 3.9.8 (no changes)
+ * code spelling fixes from upstream
+ * added s390x-virtio-ccw-fix-spelling.patch from upstream
+ * added hw-ipmi-fix-spelling.patch from upstream
+ * added docs-specify-spell-fix.patch from upstream
+ * added fsdev-spelling-fix.patch from upstream
+ * fold long list of supported arches in package descriptions
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Wed, 18 May 2016 14:44:14 +0300
+
+qemu (1:2.5+dfsg-5) unstable; urgency=medium
+
+ * fix misspellings in previous debian/changelog entry
+ * e1000-eliminate-infinite-loops-on-out-of-bounds-start-CVE-2016-1981.patch
+ (Closes: #812307, CVE-2016-1981)
+ * hmp-fix-sendkey-out-of-bounds-write-CVE-2015-8619.patch
+ (Closes: #809237, CVE-2015-8619)
+ * use `command -v' instead of `type' to check for command existence
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Thu, 28 Jan 2016 18:39:21 +0300
+
+qemu (1:2.5+dfsg-4) unstable; urgency=medium
+
+ * change misspelling of won't in NEWS (lintian)
+ * two patches from upstream to enable sigaltstack syscall (linux-user)
+ (Closes: #805826)
+ * word-wrapped last entry in debian/changelog
+ * use type to find out whenever update-binfmts is available
+ * fw_cfg-add-check-to-validate-current-entry-value-CVE-2016-1714.patch
+ (Partial) patch targeted 2.3 which fixes the read side of the issue
+ (Closes: CVE-2016-1714)
+ * i386-avoid-null-pointer-dereference-CVE-2016-1922.patch
+ (Closes: #811201, CVE-2016-1922)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Thu, 21 Jan 2016 13:06:06 +0300
+
+qemu (1:2.5+dfsg-3) unstable; urgency=high
+
+ [ Aurelien Jarno ]
+ * debian/copyright:
+ fix a spelling error reported by lintian: dependecy -> dependency.
+
+ [ Michael Tokarev ]
+ * net-vmxnet3-avoid-memory-leakage-in-activate_device patch
+ (Closes: #808145, CVE-2015-8567, CVE-2015-8568)
+ * scsi-initialise-info-object-with-appropriate-size-CVE-2015-8613.patch
+ (Closes: #809232, CVE-2015-8613)
+ * net-rocker-fix-an-incorrect-array-bounds-check-CVE-2015-8701.patch
+ (Closes: #809313, CVE-2015-8701)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Sun, 10 Jan 2016 10:59:46 +0300
+
+qemu (1:2.5+dfsg-2) unstable; urgency=high
+
+ * ehci-make-idt-processing-more-robust-CVE-2015-8558.patch
+ (Closes: #808144, CVE-2015-8558)
+ * virtio-9p-use-accessor-to-get-thread_pool.patch (Closes: #808357)
+ * two upstream patches from xsa-155 fixing unsafe shared memory access in xen
+ (Closes: #809229, CVE-2015-8550)
+ * net-ne2000-fix-bounds-check-in-ioport-operations-CVE-2015-8743.patch
+ (Closes: #810519, CVE-2015-8743)
+ * ide-ahci-reset-ncq-object-to-unused-on-error-CVE-2016-1568.patch
+ (Closes: #810527, CVE-2016-1568)
+ * changed build-depends from libpng12-dev to libpng-dev (Closes: #810205)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Sat, 09 Jan 2016 21:40:43 +0300
+
+qemu (1:2.5+dfsg-1) unstable; urgency=medium
+
+ * new upstream release
+ (Closes: #801158)
+ Closes: #806373 CVE-2015-8345
+ Closes: #806742 CVE-2015-7504
+ Closes: #806741 CVE-2015-7512
+ Closes: #808131 CVE-2015-7549
+ Closes: #808130 CVE-2015-8504
+ * adopt for the new upstream:
+ - removed patches which are upstream now
+ - build-depend on libcacard-dev and stop requiring libtool
+ - removed libcacard refs from debian/qemu-system-common.docs
+ - moved qmp docs out of subdir following upstream
+ - removed pc-bios/vgabios-virtio.bin
+ * enable new linux-user target: tilegx
+ * install qemu-ga manpage
+ * install ivshmem-server and ivshmem-client to qemu-utils
+ * stop using cylinders/heads/sectors for sfdisk
+ in qemu-make-debian-root (Closes: #785470)
+ * modify qemu-make-debian-root to use some current tools
+ (this simplifies things, removes usage of uudecode)
+ (usefulness of this utility is questionable anyway)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Wed, 16 Dec 2015 20:00:04 +0300
+
+qemu (1:2.4+dfsg-5) unstable; urgency=medium
+
+ * trace-remove-malloc-tracing.patch from upstream.
+ (Closes: #802633)
+ * stop building libcacard, as it is now in its own separate
+ source package and has been removed from upstream qemu in 2.5.
+ Here we just stop producing libcacard binaries, but still use
+ embedded libcacard source to link with it statically. In 2.5
+ we will switch to external libcacard. (Closes: #805410)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Sun, 29 Nov 2015 12:22:52 +0300
+
+qemu (1:2.4+dfsg-4) unstable; urgency=medium
+
+ * applied 3 patches from upstream to fix virtio-net
+ possible remote DoS (Closes: #799452 CVE-2015-7295)
+ * remove now-unused /etc/qemu too (Closes: #797608)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Thu, 08 Oct 2015 20:30:03 +0300
+
+qemu (1:2.4+dfsg-3) unstable; urgency=high
+
+ * ne2000-add-checks-to-validate-ring-buffer-pointers-CVE-2015-5279.patch
+ fix for Heap overflow vulnerability in ne2000_receive() function
+ (Closes: #799074 CVE-2015-5279)
+ * ne2000-avoid-infinite-loop-when-receiving-packets-CVE-2015-5278.patch
+ (Closes: #799073 CVE-2015-5278)
+ * some binfmt reorg:
+ - extend aarch64 to include one more byte as other arches do
+ - set OSABI mask to 0xfc for i386, ppc*, s390x, sparc*, to recognize
+ OSABI=3 (GNU/Linux) in addition to NONE/SysV
+ (Closes: #784605, #794737)
+ - tighten sh4 & sh4eb, fixing OSABI mask to be \xfc not 0
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Tue, 15 Sep 2015 19:30:18 +0300
+
+qemu (1:2.4+dfsg-2) unstable; urgency=high
+
+ * Add e1000-avoid-infinite-loop-in-transmit-CVE-2015-6815.patch.
+ CVE-2015-6815: net: e1000 infinite loop issue in processing transmit
+ descriptor. (Closes: #798101 CVE-2015-6815)
+ * Add ide-fix-ATAPI-command-permissions-CVE-2015-6855.patch.
+ CVE-2015-6855: ide: qemu allows arbitrary commands to be sent to an ATAPI
+ device from guest, while illegal comands might have security impact,
+ f.e. WIN_READ_NATIVE_MAX results in divide by zero error.
+ (Closes: CVE-2015-6855)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Fri, 11 Sep 2015 19:54:07 +0300
+
+qemu (1:2.4+dfsg-1a) unstable; urgency=medium
+
+ * new upstream (2.4.0) release
+ Closes: #795461, #793811, #794610, #795087, #794611, #793388
+ CVE-2015-3214 CVE-2015-5154 CVE-2015-5165 CVE-2015-5745
+ CVE-2015-5166 CVE-2015-5158
+ Closes: #793817
+ * removed all upstreamed patches
+ * remove --enable-vnc-ws option (not used anymore)
+ * update mjt-set-oem-in-rsdt-like-slic.diff
+ * vnc-fix-memory-corruption-CVE-2015-5225.patch from upstream
+ Closes: #796465 CVE-2015-5225
+ * remove now-unused /etc/qemu/target-x86_64.conf
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Mon, 31 Aug 2015 16:28:08 +0300
+
+qemu (1:2.3+dfsg-6a) unstable; urgency=medium
+
+ * fix d/copyright leftover in previous upload
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Thu, 11 Jun 2015 20:31:07 +0300
+
+qemu (1:2.3+dfsg-6) unstable; urgency=high
+
+ * pcnet-force-buffer-access-to-be-in-bounds-CVE-2015-3209.patch
+ from upstream (Closes: #788460 CVE-2015-3209)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Thu, 11 Jun 2015 20:03:40 +0300
+
+qemu (1:2.3+dfsg-5) unstable; urgency=high
+
+ * slirp-use-less-predictable-directory-name-in-tmp-CVE-2015-4037.patch
+ (Closes: CVE-2015-4037)
+ * 11 patches for XEN PCI pass-through issues
+ (Closes: #787547 CVE-2015-4103 CVE-2015-4104 CVE-2015-4105 CVE-2015-4106)
+ * kbd-add-brazil-kbd-keys-*.patch, adding two keys found on Brazilian
+ keyboards (Closes: #772422)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Wed, 03 Jun 2015 17:18:58 +0300
+
+qemu (1:2.3+dfsg-4) unstable; urgency=medium
+
+ * rules.mak-force-CFLAGS-for-all-objects-in-DSO.patch:
+ patch from upstream to fix FTBFS on some arches
+ * libcacard-dev: depend on libnss3-dev (Closes: #785798)
+ * libcacard-dev: do not depend on pkg-config
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Wed, 20 May 2015 14:21:09 +0300
+
+qemu (1:2.3+dfsg-3) unstable; urgency=high
+
+ * fdc-force-the-fifo-access-to-be-in-bounds-CVE-2015-3456.patch
+ (Closes: CVE-2015-3456)
+ * fix the OSABI binfmt mask for x86_64 arch, to actually fix #763043.
+ Original fix didn't work, because "someone" forgot arithmetics.
+ (Really Closes: #763043)
+ * align binfmt magics/masks to be in single column
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Tue, 12 May 2015 23:02:29 +0300
+
+qemu (1:2.3+dfsg-2) unstable; urgency=medium
+
+ * do not install upstream changelog file, it is unused for a long time
+ * mention closing of #781250 #769299 by 2.3
+ * mention qemu-block-extra split in NEWS files
+ * fix spelling prob in the manpage
+ * bump Standards-Version to 3.9.6 (no changes needed)
+ * add mips64 and mips64el binfmt registration (Closes: #778624)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Mon, 04 May 2015 13:01:03 +0300
+
+qemu (1:2.3+dfsg-1) unstable; urgency=medium
+
+ * new upstream release (2.3)
+ (Closes: #781250 #769299 #781250 #769299)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Fri, 24 Apr 2015 17:33:46 +0300
+
+qemu (1:2.2+dfsg-6exp) experimental; urgency=medium
+
+ * qemu 2.2.1 stable/bugfix release (remove included upstream
+ exec-change-default-exception_index-value-for-migration-to--1.patch)
+ * added mips64(el) to list of architectures where qemu-utils is built
+ (Closes: #780200)
+ * added kvm-on-x32.patch from Adam Borowski (Closes: #778737)
+ * create qemu-block-extra package
+ * rules.mak-fix-module-build.patch from upstream to fix module build
+ * pass --enable-modules to configure
+ * pass multiarch --libdir to configure
+ * mjt-set-oem-in-rsdt-like-slic.diff: update FACP table too,
+ not only RSDT. FACP is needed for win7 booting in UEFI mode.
+ * enable libcacard (closes: #764971)
+ - build-depend on libnss3-dev & libtool-bin
+ - --enable-smartcard-nss
+ - run dh_makeshlibs
+ - rm libcacard.la
+ - add libcacard0, libcacard-dev and libcacard-tools packages
+ - add libcacard*.install and libcacard0.symbols
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Fri, 17 Apr 2015 21:54:53 +0300
+
+qemu (1:2.2+dfsg-5exp) experimental; urgency=medium
+
+ * fix initscript removal once again
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Fri, 23 Jan 2015 15:05:46 +0300
+
+qemu (1:2.2+dfsg-4exp) experimental; urgency=medium
+
+ * fix a brown-paper bag bug removing the qemu-system-x86 initscript
+ (Closes: #776004)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Thu, 22 Jan 2015 20:33:38 +0300
+
+qemu (1:2.2+dfsg-3exp) experimental; urgency=medium
+
+ * mention closing of #753887 by 2.2
+ * install only specific bamboo.dtb for ppc, not *.dtb
+ (Closes: #773033)
+ * install qemu-system-misc firmware in d/*.install not d/rules,
+ as other firmware files
+ * exec-change-default-exception_index-value-for-migration-to--1.patch:
+ cherry-picked commit adee64249ee37e from upstream
+ * stop messing up with alternatives (qemu for qemu-system-*)
+ * stop shipping qemu-system-x86 initscript to load kvm modules
+ (kernel since 3.4 does that automatically) (Closes: #751754)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Thu, 22 Jan 2015 09:28:01 +0300
+
+qemu (1:2.2+dfsg-2exp) experimental; urgency=medium
+
+ * and finally uploading to experimental as it should be
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Wed, 10 Dec 2014 00:58:32 +0300
+
+qemu (2.2+dfsg-1exp) unstable; urgency=medium
+
+ * new upstream release 2.2.0 (Closes: #751078, #726629, #753887)
+ * removed all patches which was cherry-picked from upstream,
+ only keeping debian-specific changes
+ * refreshed mjt-set-oem-in-rsdt-like-slic.diff
+ * added tricore to qemu-system-misc package (new arch)
+ * restore upstream pc-bios/petalogix-*.dtb "blobs":
+ upstream says it is the canonical form, dtc is used
+ to convert from dts to dtb and back, the conversion
+ is reversible
+ * install petalogix firmware for microblaze (Closes: #769068)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Tue, 09 Dec 2014 23:09:26 +0300
+
+qemu (1:2.1+dfsg-11) unstable; urgency=medium
+
+ * bump epoch and reupload to cancel 2.2+dfsg-1exp upload
+ mistakenly done to unstable. No other changes.
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Wed, 10 Dec 2014 00:52:28 +0300
+
+qemu (2.1+dfsg-10) unstable; urgency=medium
+
+ * make (debian-specific) x86 data path (with seabios and ipxe
+ in it) non-x86-specific, since other arches use firmware
+ files too (Closes: #772127)
+ * add seabios to Recommends to qemu-system-misc, qemu-system-mips,
+ qemu-system-ppc and qemu-system-sparc packages, because these
+ packages contains emulators using vgabios which is part of
+ seabios package (#772127).
+ * add ipxe-qemu to Recommends to qemu-system-misc, qemu-system-arm,
+ qemu-system-mips, qemu-system-ppc, qemu-system-sparc packages,
+ because these packages contains emulators using network boot
+ roms (#772127), in a similar way.
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Tue, 09 Dec 2014 13:47:36 +0300
+
+qemu (2.1+dfsg-9) unstable; urgency=high
+
+ * apply upstream patches for CVE-2014-8106
+ (cirrus: insufficient blit region checks)
+ (Closes: #772025 CVE-2014-8106)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Thu, 04 Dec 2014 00:10:43 +0300
+
+qemu (2.1+dfsg-8) unstable; urgency=low
+
+ [ Michael Tokarev ]
+ * add Built-Using control field for qemu-user-static package:
+ take contents of qemu-user ${shlibs:Depends} and transform it
+ into list of source packages with versions. (Closes: #768926)
+ * run remove-alternatives in qemu-system.postinst (the metapkg)
+ too, not only in qemu-system-XX.postinst, to handle upgrades
+ from wheezy (Closes: #768244)
+ * several fixes for debian/qemu-user.1 manpage. It needs more
+ work, but at least some easy and obvious errors are fixed now.
+ (Closes: #763841)
+ * migration-fix-parameter-validation-on-ram-load.patch from upstream
+ (Closes: #769451 CVE-2014-7840)
+ * fix x86_64 binfmt mask to allow more values in ELF_OSABI field
+ (byte7). Current gcc/binfmt sometimes produces binaries with
+ this field set to 3 (OSABI_GNU) not 0 (OSABI_SYSV) as used to be.
+ Set mask to 0xfb not 0xff here, to allow 0 (traditional SYSV),
+ 1 (HPUX), 2 (NETBSD) or 3 (GNU). This lets 2 more types than
+ necessary, but qemu will reject wrong types so no harm is done.
+ Some other binfmts ignore this field completely (with mask=0).
+ Maybe some day we'll have 2 different binfmt registrations for
+ the 2 different ABI types. (Closes: #763043)
+ * usb-host-fix-usb_host_speed_compat-tyops.patch -- fix host usb devices
+ attach, without this patch many USB devices does not work
+ * qdev-monitor-fix-segmentation-fault-on-qdev_device_h.patch - trivial
+ patch from upstream to fix segfault in -device foo,help (Closes: #770880)
+
+ [ Aurelien Jarno ]
+ * Add tcg-mips-fix-store-softmmu-slow-path.patch from upstream to fix
+ TCG support on mips/mipsel hosts (Closes: #769470).
+
+ [ Ian Campbell ]
+ * Backport patch to fix unmapping of persistent grants in the Xen qdisk
+ backend (Closes: #770468).
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Thu, 27 Nov 2014 18:32:45 +0300
+
+qemu (2.1+dfsg-7) unstable; urgency=high
+
+ * urgency is high due to 2 security fixes
+ (one current and one forgotten in previous release)
+ and because of possible data corruption bugfix
+ * vnc-sanitize-bits_per_pixel-from-the-client-CVE-2014-7815.patch
+ from upstream (Closes: CVE-2014-7815)
+ * fix spelling mistake in previous changelog entry
+ * add two patches from upstream for block/raw-posix.c to work around
+ probs in FS_IOC_FIEMAP ioctl and to prefer seek_hole over fiemap.
+ This should fix a long-standing ghost data corruption observed
+ in various places.
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Mon, 03 Nov 2014 18:44:34 +0300
+
+qemu (2.1+dfsg-6) unstable; urgency=medium
+
+ * mention closing of CVE-2014-3615 by 2.1.2 (2.1+dfsg-5)
+ * 9p-use-little-endian-format-for-xattr-values.patch (Closes: #755740)
+ * mention closing of #760386
+ * mention closing of more CVEs by 2.1+dfsg-1
+ * recognize ppc64el in qemu-debootstrap (Luca Falavigna) (Closes: #760949)
+ * use dpkg-vendor to let derived distros to use our d/rules
+ * use /usr/share/dpkg/architecture.mk to get DEB_HOST_* and DEB_BUILD_*
+ variables. This restores cross building support.
+ * use /usr/share/dpkg/buildflags.mk for CFLAGS LDFLAGS &Co
+ * pass -DVENDOR_{DEBIAN,UBUNTU} to compiler
+ * do not treat ppc* and ppc*le as compatible for binfmt registrations
+ * mention ACPI SLIC to RSDT id copying if slic table is supplied,
+ thank you Tim Small for the patch (Closes: #765075)
+ * apply 5 patches from upstream to fix a security issue in
+ vmware-vga (Closes: #765496 CVE-2014-3689)
+ * apply two patches from upstream to make qemu to work with samba4
+ (Closes: #747636)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Mon, 03 Nov 2014 18:07:48 +0300
+
+qemu (2.1+dfsg-5) unstable; urgency=medium
+
+ * upstream bugfix release v2.1.2
+ (Closes: #762532 CVE-2014-3640 CVE-2014-5388 CVE-2014-3615)
+ * Add x32 to the list of supported architectures
+ (patch by Thorsten Glaser) (Closes: #760386)
+ * fix wrong reference in kvm.1 (Closes: #761137)
+ * removed patches (applied upstream):
+ l2tp-linux-only.patch
+ ide-only-constrain-read_write-requests-to-drive-size.diff
+ pc-reserve-more-memory-for-acpi.patch
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Fri, 26 Sep 2014 17:43:26 +0400
+
+qemu (2.1+dfsg-4) unstable; urgency=medium
+
+ * mention libnuma-dev but not enable for now
+ * 9p-readdir.patch: fix readdir in 9p mapped mode (Closes: #755738)
+ * pc-reserve-more-memory-for-acpi.patch: fix linux -kernel not working
+ with new qemu (Closes: #759522)
+ * qemu-options-add-missing--drive-discard-option-to-cmdline-help.diff -
+ documentation fix
+ * mention that 2.1 closed #754336.
+ * move qemu-bridge-helper to /usr/lib/qemu/ subdir (lintian)
+ * debian/binfmt-update-in (Serge Hallyn):
+ - don't run in a container
+ - add ppc64le as target
+ * add apport hook from ubuntu package (ubuntu-only for now)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Sun, 31 Aug 2014 09:32:59 +0400
+
+qemu (2.1+dfsg-3) unstable; urgency=medium
+
+ * set SHELL = /bin/sh -e, so that more complex shell constructs
+ in d/rules will fail if any command fail inside
+ * check for pipe2() being a stub too, like utimensat() etc
+ * build-depend on gnutls-dev, not libgnutls*-dev, so the
+ buuld system will pick default gnutls impl (so it works for
+ backports and future versions)
+ * build-depend on libjpeg-dev not libjpeg8-dev
+ * minimum version of seabios is 1.7.5 (Closes: #757958)
+ * ide-only-constrain-read_write-requests-to-drive-size.diff
+ (Closes: #757927)
+ * added use-arch-data-path.patch, to be able to search for binary
+ blobs in several (arch-specific) data directories instead of just one.
+ * removed all blob/firmware symlinks from qemu-system-x86, using
+ arch-specific datapath instead (/usr/share/seabios:/usr/lib/ipxe/qemu)
+ * removed retry-pxe-after-efi.patch and depend on ipxe-qemu which
+ introduced efi boot roms. qemu should not try to load "wrong"
+ ROM, or else migration will fail due to rom size mismatch.
+ * include /usr/lib/qemu-bridge-helper binary, but not make it setuid
+ due to security concerns outlined in #691138 (Closes: #691138)
+ * make vnc-jpeg not debian-specific
+ * install kvm-spice symlinks on ubuntu
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Thu, 14 Aug 2014 14:30:24 +0400
+
+qemu (2.1+dfsg-2) unstable; urgency=medium
+
+ * l2tp-linux-only.patch: fix FTBFS on kfreebsd
+ * imx_timer_TIMER_MAX_clash.diff: fix ITIMER_MAX definition clash
+ * remove kfreebsd hack which disabled usb support on this platform
+ since qemu-1.3: it isn't needed anymore
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Sat, 02 Aug 2014 00:51:04 +0400
+
+qemu (2.1+dfsg-1) unstable; urgency=medium
+
+ * new upstream release
+ Closes: #739589:
+ CVE-2013-4148 CVE-2013-4149 CVE-2013-4150 CVE-2013-4151
+ CVE-2013-4526 CVE-2013-4527 CVE-2013-4528
+ CVE-2013-4530 CVE-2013-4531 CVE-2013-4532 CVE-2013-4533 CVE-2013-4534
+ CVE-2013-4535 CVE-2013-4536 CVE-2013-4537 CVE-2013-4538 CVE-2013-4539
+ CVE-2013-4540 CVE-2013-4541 CVE-2013-4542
+ CVE-2013-6399 CVE-2014-0182 CVE-2014-3461
+ Closes: #735618
+ Closes: #754336
+ Closes: CVE-2014-3471 (pcie hotplug/hotunplug)
+ * versioned build-depend on libiscsi-dev (>>1.9.0~)
+ * added ppc64le user target
+ * fix description of qemu-user-binfmt wrt "empty" (Closes: #755988)
+ * use /usr/share/dpkg/pkg-info.mk instead of inventing the same locally
+ * added debian/get-orig-source.sh (and a d/rules target)
+ * set ubuntu vcs branch to ubuntu-utopic
+ * binfmt-update-in: make sure to filter out compat arches
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Fri, 01 Aug 2014 20:06:22 +0400
+
+qemu (2.0.0+dfsg-7) unstable; urgency=medium
+
+ * clarify description of qemu-user-binfmt a bit
+ * build-depend on acpica-tools (iasl) in order to rebuild .dsl files
+ * remove qemu-keymaps package, since it is not used by other tools
+ anymore, and ship keymaps in qemu-system-common.
+ * remove (and break by qemu-system-common) old qemu-common for
+ ubuntu too, since it was transitional-to-qemu-keymaps pkg
+ * reorganize docs (Closes: #751376):
+ - do not ship docs in qemu (meta)package, except of qemu-doc.html
+ - ship most of docs/* in qemu-system-common in /usr/share/doc/q-s-c/
+ - make symlinks from /usr/share/doc/qemu-system-foo/common to ../q-s-c/
+ - ship doc-base file for qemu-system-common too (for qemu-doc.html)
+ - rename qemu.1 manpage to qemu-system.1
+ * qemu-user-static & qemu-user-binfmt conflict with each other, not break.
+ * mention that qemu-user-binfmt is empty package (lintian)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Thu, 24 Jul 2014 16:51:16 +0400
+
+qemu (2.0.0+dfsg-6) unstable; urgency=medium
+
+ * build-depend on libgnutls28-dev not libgnutls-dev
+ * added qcow1 block format validation patches from upstream:
+ block-fmt-validation/qcow1-check-maximum-cluster-size.patch
+ block-fmt-validation/qcow1-stricter-backing-file-length-check.patch
+ block-fmt-validation/qcow1-validate-image-size-CVE-2014-0223.patch
+ block-fmt-validation/qcow1-validate-L2-table-size-CVE-2014-0222.patch
+ (Finally closes: #742730, CVE-2014-0222, CVE-2014-0223)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Fri, 23 May 2014 12:12:38 +0400
+
+qemu (2.0.0+dfsg-5) unstable; urgency=medium
+
+ * re-re-enable rbd (ceph) support again (Closes: #689239)
+ Should watch for breakage and for runtime dependencies closely from now on.
+ * fix qemu-kvm package description (stop mentioning it is transitional)
+ * move all binfmt handling from many files to d/binfmt-update-in
+ * introduce qemu-user-binfmt (dummy) package to support binfmt
+ registration of qemu-user binaries (Closes: #677529)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Tue, 13 May 2014 21:15:48 +0400
+
+qemu (2.0.0+dfsg-4) unstable; urgency=medium
+
+ * suggests ovmf, not recommends it as it is not in -main (Closes: #745698)
+ * cputlb-fix-regression-with-TCG-interpreter.patch (Closes: #744342)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Wed, 30 Apr 2014 10:03:55 +0400
+
+qemu (2.0.0+dfsg-3) unstable; urgency=low
+
+ * 2.0.0 closed #744213 (CVE-2013-4544) and #745157 (CVE-2014-2894)
+ * mjt-set-oem-in-rsdt-like-slic.diff: apply a (hackish) patch to simplify
+ running OEM versions of windows vista and 7 in qemu using SLIC table
+ from current hardware.
+ * set VENDOR in d/rules
+ * added forgotten qemu-kvm Pre-Depends field
+ * switch back from sdl2 to sdl1, as the former apparently isn't ready yet
+ (Closes: #745269)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Mon, 21 Apr 2014 12:34:03 +0400
+
+qemu (2.0.0+dfsg-2) unstable; urgency=medium
+
+ * resurrect 02_kfreebsd.patch, -- without it qemu FTBFS on current
+ Debian kFreeBSD system still.
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Thu, 17 Apr 2014 22:04:38 +0400
+
+qemu (2.0.0+dfsg-1) unstable; urgency=low
+
+ * new upstream major release
+ Closes: #744213 CVE-2013-4544
+ Closes: #745157 CVE-2014-2894
+ * 2.0 actually does not close #739589,
+ remove it from from last changelog entry
+ * mention closing of #707629 by 2.0
+ * mention a list of CVE IDs closed by #742730
+ * mention closing of CVE-2013-4377 by 1.7.0-6
+ * do not set --enable-uname-release=2.6.32 for qemu-user anymore
+ (was needed for old ubuntu builders)
+ * removed 02_kfreebsd.patch: it adds configure check for futimens() and
+ futimesat() syscalls on FreeBSD, however futimens() appeared in FreeBSD
+ 5.0, and futimesat() in 8.0, and 8.0 is the earliest supported version
+ * kmod dependency is linux-any
+ * doc-grammify-allows-to.patch: fix some lintian warnings
+ * remove alternatives for qemu: different architectures
+ aren't really alternatives and never had been
+ * update Standards-Version to 3.9.5 (no changes needed)
+ * exec-limit-translation-limiting-in-address_space_translate-to-xen.diff -
+ fixes windows BSOD with virtio-scsi when upgrading from 1.7.0 to 1.7.1
+ or 2.0, among other things
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Thu, 17 Apr 2014 18:27:15 +0400
+
+qemu (2.0.0~rc1+dfsg-1exp) experimental; urgency=low
+
+ * new upstream release candidate (2.0-rc1)
+ Closes: #742730 -- image format processing issues:
+ CVE-2014-0142 CVE-2014-0143 CVE-2014-0144 CVE-2014-0145
+ CVE-2014-0146 CVE-2014-0147 CVE-2014-0148
+ Closes: #743235, #707629
+ * refreshed patches:
+ 02_kfreebsd.patch
+ retry-pxe-after-efi.patch
+ use-fixed-data-path.patch
+ * removed patches applied upstream:
+ qemu-1.7.1.diff
+ address_space_translate-do-not-cross-page-boundaries.diff
+ fix-smb-security-share.patch
+ slirp-smb-redirect-port-445-too.patch
+ implement-posix-timers.diff
+ linux-user-fixed-s390x-clone-argument-order.patch
+ * added bios-256k.bin symlink and bump seabios dependency to >= 1.7.4-2
+ * recommend ovmf package for qemu-system-x86 to support UEFI boot
+ (Closes: #714249)
+ * switch from sdl1 to sdl2 (build-depend on libsdl2-dev)
+ * output last 50 lines of config.log in case configure failed
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Sat, 05 Apr 2014 16:23:48 +0400
+
+qemu (1.7.0+dfsg-9) unstable; urgency=medium
+
+ * remove rbd/rados/ceph support *again*, till they'll actually provide
+ some symbol/library version mechanism
+ (Closes: #744364, Reopens: #729961, #689239)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Sun, 13 Apr 2014 18:49:46 +0400
+
+qemu (1.7.0+dfsg-8) unstable; urgency=low
+
+ * fix a brown-paper-bag bug in the previous upload
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Fri, 11 Apr 2014 22:01:32 +0400
+
+qemu (1.7.0+dfsg-7) unstable; urgency=high
+
+ * fix guest-triggerable buffer overrun in virtio-net device
+ (Closes: #744221 CVE-2014-0150)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Fri, 11 Apr 2014 20:27:16 +0400
+
+qemu (1.7.0+dfsg-6) unstable; urgency=medium
+
+ * make ceph (rbd) support linux-only, since it exists only on linux
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Sat, 05 Apr 2014 13:59:48 +0400
+
+qemu (1.7.0+dfsg-5) unstable; urgency=medium
+
+ * remove OVMF.fd symlink added in -4, it belongs to ovmf (Closes: #741494)
+ * qemu-debootstrap: add support for arm64 architecture (Closes: #740112)
+ * mention closing of #725176 by 1.7.0
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Thu, 13 Mar 2014 06:21:01 +0400
+
+qemu (1.7.0+dfsg-4) unstable; urgency=medium
+
+ [ Michael Tokarev ]
+ * 1.7.1 stable upstream release (Closes: #719633)
+ Closes: CVE-2013-4377
+ * implement-posix-timers.diff from upstream (Closes: #732258)
+ * address_space_translate-do-not-cross-page-boundaries.diff -
+ upstream bugfix for xen
+ * break libvirt << 1.2, not just 1.0, we need 1.2+ after qemu-1.6.
+ * add linux-user-fixed-s390x-clone-argument-order.patch (Closes: #739800)
+ * re-enable cepth (rbd) support (Closes: #729961, #689239)
+
+ [ Steve Langasek ]
+ * (from Ubuntu) add symlink for OVMF.fd, which is now available in Debian
+ non-free.
+ * libusbredir is enabled in Ubuntu too, so sync debian/control.
+ * Enable building for ppc64el (in both Debian and Ubuntu): Debian does not
+ have a ppc64el port yet, but qemu builds out of the box there so it's
+ safe/appropriate to enable.
+ * Merge in Ubuntu-specific (and Ubuntu-tagged) debian/control changes.
+ * Enable building for arm64; the arm64 target is not yet merged, but the
+ package doesn't need arm64 target support to build for an arm64 host.
+
+ [ Riku Voipio ]
+ * control: build-depend on python:any (change originally made
+ in Aug-2013 but reverted by mjt later)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Wed, 12 Mar 2014 18:34:03 +0400
+
+qemu (1.7.0+dfsg-3) unstable; urgency=low
+
+ * qemu-kvm: fix versions for Breaks/Replaces/Depends on qemu-system-x86
+ * qemu-system-ppc: depend on openbios-ppc >= 1.1+svn1229 to fix boot issues
+ * qemu-system-sparc: depend on openbios-sparc >= 1.1+svn1229 too
+ * remove unused lintian overrides for qemu-user from qemu (meta)package
+ * qemu-system-*: depend on unversioned qemu-keymaps and qemu-system-common
+ packages (no particular version of any is hard-required)
+ * remove debian/README.source (was from quilt)
+ * add myself to debian/copyright
+ * reorder d/control to have Recommends:/Suggests: closer to Depends.
+ * rename d/control to d/control-in and add a d/rules rule to build it
+ based on ${VENDOR}
+ * allow different content in d/control for debian/ubuntu
+ * added debian/README-components-versions
+ * fixed qemu-armeb binfmt (Closes: #735078)
+ * added powerpcspe host arch (Closes: #734696)
+ * do not check for presence of update-alternatives which is part of dpkg
+ (Closes: #733222)
+ * do not call update-alternative --remove from postrm:remove
+ (lintian complains about this)
+ * add efi netrom links. This requires new ipxe-qemu.
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Thu, 16 Jan 2014 15:17:46 +0400
+
+qemu (1.7.0+dfsg-2) unstable; urgency=low
+
+ * switch from vgabios to seavgabios
+ * rework update-alternatives handling for qemu-system (Closes: #722914)
+ * mention closing of #326886, #390444, #706237 and CVE-2013-4375 for 1.7.0
+ * rearrange libvte-dev build-dependency to come together with gtk, and
+ comment it out (since gtk frontend isn't being built)
+ * re-introduce qemu-kvm package with just a wrapper (/usr/bin/kvm)
+ and make this wrapper to force kvm mode (Closes: #727762)
+ * use less strict dependency on qemu-keymaps
+ * added fix-smb-security-share.patch by Michael Büsch (Closes: #727756)
+ * added move-ncalrpc-dir-to-tmp.patch by Michael Büsch (Closes: #728876)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Fri, 29 Nov 2013 00:16:44 +0400
+
+qemu (1.7.0+dfsg-1) unstable; urgency=low
+
+ * new upstream release (Closes: #724758, #326886, #390444, #706237, #725176)
+ Also fixes CVE-2013-4375 (xen-specific qemu disk backend (qdisk)
+ resource leak)
+ * tweak kvm loading script to not load module for 3.4+ kernel
+ (kernel autoloads kvm modules since 3.4) (Closes: #717811)
+ * mention closing of #721713, #710971, #674201
+ * refresh use-fixed-data-path.patch to contain just the min. changes
+ * fix pxe-eepro100.rom link (never worked in qemu due to wrong name)
+ * remove old $Id$ line from debian/rules
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Thu, 28 Nov 2013 03:14:21 +0400
+
+qemu (1.6.0+dfsg-2) unstable; urgency=low
+
+ * Build-depend in seccomp again once it is in -testing
+ * 1.6.1 upstream bugfix release (Closes: #725944, #721713, #710971)
+ * fix "allows [one] to" in qemu-ga description
+ * fix descriptions for qemu-system and qemu-system-common packages
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Fri, 11 Oct 2013 01:15:48 +0400
+
+qemu (1.6.0+dfsg-1) unstable; urgency=low
+
+ * final upstream v1.6.0 (Closes: #718180, #714273, #605525, #701855, #674201)
+ * removed configure-explicitly-disable-virtfs-if-softmmu=no.patch
+ * mention closing of #717724 by 1.6
+ * mention closing of #710971 by 1.5 (which disabled gtk support)
+
+ [ Riku Voipio ]
+ * - set --cross-prefix in debian/rules when cross-compiling
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Mon, 02 Sep 2013 15:18:49 +0400
+
+qemu (1.6.0~rc0+dfsg-1exp) experimental; urgency=low
+
+ * uploading to experimental (rc0)
+ * new upstream release (release candidate) (Closes: #718016, #717724)
+ * removed patches:
+ - qemu-1.5.1.diff
+ - sparc-linux-user-fix-missing-symbols-in-.rel-.rela.plt-sections.patch
+ * refreshed use-fixed-data-path.patch
+ * ship new qemu_logo_no_text.svg
+ * stop shipping sgabios symlink, it is moved to sgabios package
+ * bump version of libseccomp build dependency to 2.1 (minimum
+ required to build) and disable libseccomp for now (because it
+ isn't available in debian yet)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Wed, 31 Jul 2013 10:49:30 +0400
+
+qemu (1.5.0+dfsg-5) unstable; urgency=low
+
+ * new upstream 1.5.1 stable/bugfix release (as qemu-1.5.1.diff)
+ removed qemu_openpty_raw-helper.patch (included upstream)
+ * configure-explicitly-disable-virtfs-if-softmmu=no.patch -- do not
+ build virtfs-proxy-helper stuff if not building system emulator
+ (fix FTBFS on s390)
+ * disable gtk ui and build dependencies, as it adds almost nothing
+ compared with sdl (well, except bugs and limitations), and has
+ lots of additional dependencies (Closes: #710971)
+ * remove obsolete /etc/init.d/qemu-kvm (Closes: #712898)
+ * fix versions of obsolete qemu-kvm conffiles to be removed
+ * provide manpage for obsolete kvm (Closes: #716891, #586973)
+ * add --daemonize option to the guest-agent startup script (Closes: #715502)
+ * clarify what qemu-guest-agent does (Closes: #714270) and provide
+ its json schema as a doc
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Tue, 23 Jul 2013 22:39:54 +0400
+
+qemu (1.5.0+dfsg-4) unstable; urgency=medium
+
+ * urgency is medium to make it go faster because, on one hand, we've
+ been in unstable for quite a bit longer than needed already and
+ have nothing but (build) fixes in there, but on the other hand
+ we're holding migration of other packages which are waiting for
+ us, again, for too long already
+ * added qemu_openpty_raw-helper.patch - a cleanup patch submitted upstream
+ which removes #include <termios.h> from common header and hence works
+ around FTBFS problem on debian sparc where somehow, <termios.h> conflicts
+ with <linux/termio.h>.
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Thu, 06 Jun 2013 01:50:32 +0400
+
+qemu (1.5.0+dfsg-3) unstable; urgency=low
+
+ * fix sections: misc => otherosfs
+ * remove obsolete conffiles (kvm-ifup, kvm-ifdown, target-x86_64.conf)
+ from /etc/kvm/ in qemu-kvm (Closes: #710328)
+ * rework debian/rules a bit, to build various bits depending on
+ which packages are requested, not depending on ad-hoc host/arch
+ logic
+ * do not fail at install if kvm module loading failed on x86 or
+ if modprobe isn't installed (Closes: #710496)
+ * also suggest kmod to be able to load x86 kvm modules
+ * suggest sgabios for qemu-system-x86 and put a symlink to sgabios.bin
+ (Closes: #696985)
+ * add rules to build just one of arch/indep parts, to make
+ buildd log scanner happier (E-binary-arch-produces-all)
+ * use verbose build by default (V=1) and let it to be overridden
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Sun, 02 Jun 2013 01:49:47 +0400
+
+qemu (1.5.0+dfsg-2) unstable; urgency=low
+
+ * merged development history of wheezy and experimental branches.
+ Now the history is ordered by version, but is not chronological.
+ As a base we now have wheezy (1.1.2+dfsg-6a) version.
+ * removed trailing whitespaces from changelog file
+ * run dh_installinit properly (Closes: #709199)
+ * run dh_installman (Closes: #709241)
+ * remove build-dependendy on texi2html, upstream switched to makeinfo
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Tue, 28 May 2013 10:48:41 +0400
+
+qemu (1.5.0+dfsg-1) unstable; urgency=low
+
+ * update to 1.5.0 (Closes: #707732)
+ * upload to unstable
+ * mention that 1.5 closes #697641 and #705544
+ * bump dependency on openbios (openbios-ppc for qemu-system-ppc,
+ openbios-sparc for qemu-system-sparc) from 1.0+svn1060 to 1.1
+ (Closes: #707727)
+ * bump dependency on seabios to be >= 1.7.2-2
+ * add retry-pxe-after-efi.patch to try pxe-XXXX.rom after unsuccessfully
+ trying efi-XXXX.rom - this is for NICs, until pxe-qemu package will be
+ able to provide necessary efi-XXXX.rom files.
+ * add (versioned) dependency on libusb-1.0 now when the right version
+ is available in debian
+ * use-fixed-data-path.patch: do not try to derive data path from
+ executable location, always use /usr/share/qemu
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Tue, 21 May 2013 00:49:47 +0400
+
+qemu (1.5.0~rc0+dfsg-1) experimental; urgency=low
+
+ * update to new upstream release candidate (1.5.0-rc0)
+ (Closes: #697641, #705544)
+ * remove --audio-card-list
+ * added new moxie system target
+ * added new linux-user targets: mips64 mips64el mipsn32 mipsn32el
+ * add libgtk2 and libvte to dependencies (new UI)
+ * added libssh2 to dependencies (new block device)
+ * s/libvdeplug2-dev/libvdeplug-dev/
+ * define localstatedir (for guest-agent)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Wed, 08 May 2013 01:01:01 +0400
+
+qemu (1.4.0+dfsg-2exp) experimental; urgency=low
+
+ [ Michael Tokarev ]
+ * set qemu-kvm priority to extra
+ * fix distribution field in last qemu-system.NEWS entry
+ * bump Standards-Version to 3.9.4 (no changes needed)
+ * fix update-rc.d args for qemu-system-x86
+ * pre-Depend on adduser for qemu-system-common (Closes: #700840)
+ * move guest agent binary (qemu-ga) to /usr/sbin
+ * add versioned build-depends on libspice-protocol-dev (>= 0.12.3)
+ * refresh qemu-ifunc-sparc.patch, use proper submission from patchwork
+ (sparc-linux-user-fix-missing-symbols...) instead.
+ * apply 1.4.1 upstream stable patch
+ * release as 1.4.0
+
+ [ Aurelien Jarno ]
+ * debian/rules: don't build spapr-rtas.bin from .hex file.
+ * qemu-system-ppc: add a depends on qemu-slof and add the corresponding
+ links (Closes: #686979).
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Thu, 18 Apr 2013 14:45:30 +0400
+
+qemu (1.4.0+dfsg-1exp) experimental; urgency=low
+
+ [ Michael Tokarev ]
+ * 1.4.0 final release
+ * remove fix-virtio-net-for-win-guests.patch (upstream now has better fix)
+ * fix debian/control arch fields. Build-Depends: foo [bar]
+ means foo will be selected for build on LINUX-bar, not any-bar.
+ So stop using [bar], always use [linux-bar] or [any-bar],
+ as appropriate. This fix spice and xen (non)selection on
+ kfreebsd-{i386,amd64}.
+ * fix manpage "links" generation (man qemu-system-* was broken)
+ * change Vcs fields to point to anonscm.debian.org (lintian)
+ * add a check for (lxc) container to qemu-system-x86 initscript
+
+ [ Steve Langasek ]
+ * Pass --enable-uname-release=2.6.32 for the user emulation builds, so that
+ we have a sensible baseline kernel value regardless of what the
+ underlying host kernel is. This makes eglibc happier when running under
+ emulation on a very old kernel for instance (whose host syscall ABI has
+ nothing to do with what emulated syscalls are supported), and probably
+ also lets us steer clear for the moment of code that has problem with
+ the new kernel upstream versioning convention. LP: #921078.
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Sat, 16 Feb 2013 12:34:54 +0400
+
+qemu (1.4.0~rc0+dfsg-1exp) experimental; urgency=low
+
+ * new upstream 1.4.0-rc0 (first release candidate).
+ (Closes: #549195)
+ * remove patches included upstream:
+ e1000-discard-oversized-packets-based-on-SBP_LPE.patch
+ link-seccomp-only-with-softmmu-targets.patch
+ revert-serial-fix-retry-logic.patch
+ savevm.c-cleanup-system-includes.patch
+ * refresh qemu-ifunc-sparc.patch
+ * add fix-virtio-net-for-win-guests.patch bandaid to make virtio-net
+ in windows guest to work again
+ * don't install virtfs-proxy-helper in its own subdir in /usr/bin
+ * add qemu-io manpage. Thank you Asias He for the work!
+ (Closes: #652518)
+ * move config options from debian/configure-opts into debian/control,
+ to keep list of build-deps & corresponding config flags in one place
+ * use initscript from old qemu-kvm package to load kvm modules for
+ qemu-system-x86, and clean it up (Closes: #699404)
+ * load vhost_net module in the initscript too
+ * mention default NIC change in qemu-kvm.NEWS and old conffiles
+ * remove mentions of (ubuntu-specific) qemu-common from debian/control
+ for now, as it does not help anyway (other changes are needed anyway
+ and it is better to keep them in one place)
+ * add a (preliminary) qemu-guest-agent startup script
+ * qemu-system-x86 break libvirt0 << 1.0, because older versions
+ didn't work with qemu 1.3+ correctly
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Sat, 02 Feb 2013 21:05:28 +0400
+
+qemu (1.3.0+dfsg-5exp) experimental; urgency=low
+
+ * qemu-system-split: split qemu-system into several target-specific packages:
+ qemu-system-arm, qemu-system-mips, qemu-system-ppc, qemu-system-sparc,
+ qemu-system-x86, and qemu-system-misc, plus qemu-system-common.
+ (Closes: #636000)
+ * add initial qemu-guest-agent package (just the binary for now,
+ no startup script) (Closes: #676959)
+ * do not try to install (linux-specific) virtfs-proxy-helper on kfreebsd
+ * change order of audio drivers, in particular put pulseaudio (pa) first
+ * ship OS-specific qemu-ifup (use trivial ifconfig invocation on kfreebsd)
+ * qemu-system replaces qemu-utils due to virtfs-proxy-helper binary
+ * chmod +x qemu-ifdown
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Mon, 28 Jan 2013 15:05:57 +0400
+
+qemu (1.3.0+dfsg-4exp) experimental; urgency=low
+
+ * install forgotten /etc/qemu-ifdown (dummy, but qemu complains without it)
+ * install virtfs-proxy-helper in qemu-system not qemu-utils
+ * add qemu-kvm.NEWS mentioning transition from qemu-kvm to qemu-system-x86_64.
+ * do not pass -cpu kvm64 to qemu in kvm wrapper script, previous qemu-kvm
+ used qemu64 cpu instead - the same as new qemu uses.
+ * install kvm wrapper on x86 only, and install it as /usr/bin/kvm not
+ /usr/bin/kvm/kvm (Closes: #698736).
+ * stop shipping /usr/share/qemu/vapic.bin link (qemu uses kvmvapic.bin)
+ * stop shipping /usr/share/qemu/vgabios.bin link (qemu uses vgabios-*.bin)
+ * enable all guest audio devices
+ * add breaks/replaces/provides/conflicts with kvm (very old package),
+ qemu-kvm, and ubuntu's qemu-common.
+ * stop caring about old (pre-squeeze) qemu
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Wed, 23 Jan 2013 11:08:47 +0400
+
+qemu (1.3.0+dfsg-3exp) experimental; urgency=low
+
+ * add ability to specify os-arch in configure-opts
+ * libseccomp is linux-x86 not linux-any
+ * e1000-discard-oversized-packets-based-on-SBP_LPE.patch
+ CVE-2012-6075 (Closes: #696051)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Mon, 21 Jan 2013 02:54:15 +0400
+
+qemu (1.3.0+dfsg-2exp) experimental; urgency=low
+
+ * qemu-nbd and qemu-io should be installed on kFreeBSD too
+ * install qemu-system docs into /usr/share/doc/qemu-system,
+ not .../qemu (Closes: #697085)
+ * do not depend on ipxe, it does not provide our ROMs
+ * move vde2 from Recommends to Suggests, since it isn't
+ used often
+ * require libspice-server-dev >= 0.12.2 and require it on i386 too,
+ enable spice support
+ * require libusbredirparser-dev >= 0.6, enable usb-redir
+ * enable xen explicitly on amd64|i386
+ * enable xfsctl explicitly on linux
+ * sort build-deps in debian/control and add comments
+ * set permissions of /dev/kvm in qemu-system.postinst
+ the same way it is done in old qemu-kvm package
+ * set --localstatedir=/var (will be used later by guest agent)
+ * bump qemu-system dependency on seabios to 1.7.2
+ and add symlinks for acpi-dsdt.aml and q35-acpi-dsdt.aml
+ * import qemu-ifup and qemu-ifdown scripts from qemu-kvm,
+ and modify qemu-ifup to allow usage of just `ip' command
+ from iproute package (if installed) instead of old brctl+ifconfig.
+ Add Breaks: for old iproute without bridge controls.
+ Add iproute to Recomments, so that the scripts will actually work
+ (previous script used sudo which should be in recommends too)
+ * enable seccomp (and libseccomp-dev b-d) on linux,
+ and add link-seccomp-only-with-softmmu-targets.patch
+ * use $(MAKE) not make when building spapr-rtas.bin
+ * update debian/watch (new place and new extensions)
+ * add qemu-kvm package (transitional, depends on qemu-system),
+ and add /usr/bin/kvm wrapper that calls qemu-system-x86_64
+ with some arguments to match original qemu-kvm behavour.
+ (Closes: #560853)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Sun, 20 Jan 2013 22:12:11 +0400
+
+qemu (1.3.0+dfsg-1~exp3) experimental; urgency=low
+
+ * enable vde on kFreebsd too (no idea why it was disabled)
+ * bluez (libbluetooth) is linux-specific
+ * savevm.c-cleanup-system-includes.patch: remove excessive #includes
+ from savevm.c (fixes FTBFS on kFreebsd due to wrong #include)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Mon, 31 Dec 2012 15:52:23 +0400
+
+qemu (1.3.0+dfsg-1~exp2) experimental; urgency=low
+
+ * mention that 1.3: Closes #622319, #597527, #593547, #660154
+ * libcap and libcap-ng are linux-specific
+ * include spapr-rtas.bin file in a pre-compiled pseudo-hex-with-assembly
+ form in debian/spapr-rtas.hex, "compile" it (using sed magic) in
+ build step and compare the result with the actually built binary
+ on ppc. This binary is needed for ppc system emulation (qemu-system-ppc*).
+ (Closes: #670909).
+ * rename system-build to qemu-build, and merge user-build to qemu-build,
+ building qemu-system and qemu-user in one go. Only qemu-system-static
+ is left in separate build dir. Note that current qemu-user is
+ linux-specific, even if qemu has bsd-user targets.
+ * add or32 user target
+ * debian/configure-opts - list of (possible arch- or os-specific)
+ features to enable/disable. This is in order to ensure we always
+ build with specific options enabled and error out if new upstream
+ will dislike our dependencies, or if the deps will not work.
+ Move config_audio_drv from debian/rules to this file too.
+ For now do not explicitly enable xen, spice, usb-redir, since
+ these requires some more work.
+ Also pass $(QEMU_CONFIGURE_OPTIONS) to qemu configure line,
+ to be able to quickly override some options.
+ * do not build-depend on sharutils, since no uuencoded binaries
+ are shipped anymore
+ * do not build-depend on nasm, we don't compile from assembly anymore
+ * remove libgpmg1-dev from build-depends. It was due to #267174,
+ because of static link of qemu with libsdl. Now only qemu-user-static
+ is linked statically, and this one does not use libsdl.
+ * add myself to uploaders, and remove dm-upload-allowed
+ * added main docs to qemu-system package
+ * specify --libexecdir=/usr/lib to configure
+ * mark all packages as Multi-Arch: foreign
+ (at least it is possible to install i386 versions on amd64 arch)
+ * replace "flags OC" with "credentials yes" in debian/binfmts/*,
+ since that's the format update-binfmts expects to enable setuid
+ binaries. (Closes: #683205)
+ * build-depend on debhelper 9, and set debian/compat to 9
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Mon, 31 Dec 2012 01:40:35 +0400
+
+qemu (1.3.0+dfsg-1~exp1) experimental; urgency=low
+
+ [ Michael Tokarev ]
+ * new upstream version (1.3.0)
+ (Closes: #676374, #622319, #597527, #593547, #660154)
+ - Removed patches included upstream:
+ do-not-include-libutil.h.patch
+ configure-nss-usbredir.patch
+ tcg_s390-fix-ld_st-with-CONFIG_TCG_PASS_AREG0.patch
+ net-add--netdev-options-to-man-page.patch
+ - update 02_kfreebsd.patch
+ - do not build mpc8544ds.dtb
+ - include new targets
+ * Cleaned up the build system ALOT. Larger changes:
+ - used explicit lists of emulated targets in debian/rules
+ and generate everything else from there, instead of repeating
+ these lists in lots of places.
+ - stop using debian/$pkg.manpages and other auxilary files like this,
+ moving eveything to debian/$pkg.install, because with the number
+ of packages growing, amount of these small files becomes very
+ large and the result is difficult to maintain.
+ * ship forgotten target-x86_64.conf in qemu-system.
+ * ship virtfs-proxy-helper in qemu-utils.
+ * stop shipping tundev.c, since it does not reflect the reality for
+ a long time now (Closes: #325761, #325754).
+ * re-introduce support parallel build using DEB_BUILD_OPTIONS=parallel=N,
+ this time by adding to $MAKEFLAGS instead of passing down to submakes
+ * build-depend on libcap-ng-dev (for virtfs-proxy-helper)
+
+ [ Vagrant Cascadian ]
+ * Add libcap-dev to Build-Depends to support virtfs-proxy-helper.
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Sun, 30 Dec 2012 01:52:21 +0400
+
+qemu (1.1.2+dfsg-6a) unstable; urgency=low
+
+ * reupload to remove two unrelated files slipped in debian/
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Mon, 18 Mar 2013 10:09:37 +0400
+
+qemu (1.1.2+dfsg-6) unstable; urgency=low
+
+ * another bugfix for USB, upstream from early days of past-1.1.
+ usb-split-endpoint-init-and-reset.patch. With certain redirected
+ to guest USB devices, qemu process may crash:
+
+ usb_packet_complete: Assertion `((&ep->queue)->tqh_first) == p' failed.
+
+ The patch fixes this by de-coupling reset and complete paths.
+ Big thanks goes to Joseph Price who found the fix by doing a
+ reverse git bisection.
+ (Closes: #701926)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Mon, 18 Mar 2013 09:07:24 +0400
+
+qemu (1.1.2+dfsg-5) unstable; urgency=low
+
+ * fix USB regression introduced in 1.1 (Closes: #683983)
+ uhci-don-t-queue-up-packets-after-one-with-the-SPD-flag-set.patch
+ Big thanks to Peter Schaefer (https://bugs.launchpad.net/bugs/1033727)
+ for the help identifying the fix.
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Mon, 14 Jan 2013 12:20:29 +0400
+
+qemu (1.1.2+dfsg-4) unstable; urgency=medium
+
+ * linux-user-fix-mips-32-on-64-prealloc-case.patch (Closes: #668658)
+ * e1000-discard-oversized-packets-based-on-SBP_LPE.patch: the second
+ half of the fix for CVE-2012-6075. (Finally Closes: #696051)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Wed, 09 Jan 2013 23:05:17 +0400
+
+qemu (1.1.2+dfsg-3) unstable; urgency=low
+
+ * add build-dependency on libcap-dev [linux-any] to enable virtfs support
+ which has been dropped in 1.1. (Closes: #677654)
+ * intel_hda-do-not-call-msi_reset-when-only-device-state-needs-resetting.patch
+ patch to fix Fixing reset of MSI function in intel-hda virtual device.
+ The fix (applied to stable-1.1.1) was partially wrong, as it actually
+ added the msi_reset() call to two code paths instead of one as planned.
+ Fix this by splitting the function in question into two parts.
+ (Closes: #688964)
+ * blockdev-preserve-readonly-and-snapshot-states-across-media-changes.patch:
+ allow opening of read-only cdrom images/devices (Closes: #686776)
+ * ahci-properly-reset-PxCMD-on-HBA-reset.patch: fix windows install on ahci
+ (Closes: #696052)
+ * e1000-discard-packets-that-are-too-long-if-not-SBP-and-not-LPE.patch:
+ discard too long rx packets which may overflow guest buffer
+ (Closes: #696051)
+ * eepro100-fix-network-hang-when-rx-buffers-run-out.patch:
+ fix e100 stall (Closes: #696061)
+ * fix possible network stalls/slowness in e1000 device emulation:
+ net-notify-iothread-after-flushing-queue.patch
+ e1000-flush-queue-whenever-can_receive-can-go-from-false-to-true.patch
+ (Closes: #696063)
+ * fixes-related-to-processing-of-qemu-s-numa-option.patch:
+ fixes numa handling (Closes: #691343)
+ * qcow2-fix-avail_sectors-in-cluster-allocation-code.patch:
+ fixes data corruption in stacked qcow2 (Closes: #695905)
+ * qcow2-fix-refcount-table-size-calculation.patch: another possible
+ corruption or crash in qcow2 (Closes: #691569)
+ * tap-reset-vnet-header-size-on-open.patch: always ensure tap device is
+ in known state initially (Closes: #696057)
+ * vmdk-fix-data-corruption-bug-in-WRITE-and-READ-handling.patch:
+ possible data corruption bug in vmdk image format (Closes: #696050)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Sun, 16 Dec 2012 23:08:40 +0400
+
+qemu (1.1.2+dfsg-2) unstable; urgency=low
+
+ * remove debian/patches/fix-armhf-prctl.patch, it is included
+ upstream in 1.1.0 version and is misapplied since 1.1.0~rc3+dfsg-1.
+ * drop -jN passing to downstream makes, as it breaks dpkg-buildpackage -j
+ and actually breaks build (Closes: #597524 - said to be fixed in 0.14.1
+ but was still present)
+ * add revert-serial-fix-retry-logic.patch that restores
+ old (semi-)working behavour of a virtual serial port.
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Wed, 19 Sep 2012 13:54:05 +0400
+
+qemu (1.1.2+dfsg-1) unstable; urgency=low
+
+ [Michael Tokarev]
+ * new upstream stable/bugfix release, fixing a LOT of bugs,
+ including CVE-2012-3515 (Closes: #686973, #681985)
+ * bump versioned depends of seabios to 1.7.0~, since this version ships
+ kvmvapic.bin.
+ * ship /usr/share/qemu/qemu-icon.bmp (Closes: #681317)
+ * do not build-depend on ceph (librbd-dev librados-dev), since ceph is
+ having longstanding issues in wheezy.
+ * add tcg_s390-fix-ld_st-with-CONFIG_TCG_PASS_AREG0.patch - upstream fix
+ to un-break s390[x] emulation code. Similar fixes were included for
+ other platforms in 1.1.2 changeset. Without this fix, qemu is basically
+ useless on s390.
+ * document -netdev option in the manpage, a long-standing omission
+ (net-add--netdev-options-to-man-page.patch)
+
+ [Vagrant Cascadian]
+ * qemu-system: Add symlinks for extboot.bin, kvmvapic.bin and vapic.bin to
+ binaries shipped in seabios. Closes: #678217, #679004.
+ * qemu-system: Remove dead link for ne2k_isa.rom, which is not included in
+ ipxe. Closes: #679004.
+ * qemu-system: Bump versioned openbios-sparc and openbios-ppc Depends to
+ 1.0+svn1060, to ensure we use at least version which is used by upstream.
+ Wheezy already has the right version, but we should not break partial
+ upgrades.
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Sun, 09 Sep 2012 18:52:57 +0400
+
+qemu (1.1.0+dfsg-1) unstable; urgency=low
+
+ [ Vagrant Cascadian ]
+ * New upstream release. (Closes: #655604, #655145)
+
+ [ Michael Tokarev ]
+ * do-not-include-libutil.h.patch - don't include libutil.h&Co when not
+ needed. Fixes FTBFS on kFreebsd with recent libbsd-dev.
+ * drop libbsd-dev support on kFreebsd - no longer needed.
+ * do not build USB host support on kFreebsd (qemu uses obsolete,
+ now removed, USB API). Use the same hack/technique as FreeBSD
+ qemu port does -- changing HOST_USB to "stub" after configure run.
+
+ -- Vagrant Cascadian <vagrant@debian.org> Thu, 07 Jun 2012 13:44:26 -0700
+
+qemu (1.1.0~rc3+dfsg-1) experimental; urgency=low
+
+ * New upstream release candidate.
+ * debian/patches:
+ - Update 02_kfreebsd.
+ - Remove dont-block-sigchld, applied upstream.
+ - Update configure-nss-usbredir.
+ - Update fix-armhf-prctl.
+ * debian/rules: Remove --disable-darwin-user from configure, as it is no
+ longer present.
+ * Apply patch to qemu-make-debian-root to improve argument handling.
+ (Closes: #671723). Thanks to Askar Safin.
+ * qemu-utils: Add recommends on sharutils, used by qemu-make-debian-root
+ (Closes: #660296).
+ * Add Build-Depends on libusbredirparser-dev to support usbredir protocol.
+ * Add Build-Depends on libbsd-dev for kfreebsd.
+
+ -- Vagrant Cascadian <vagrant@debian.org> Wed, 30 May 2012 20:24:59 -0700
+
+qemu (1.0.1+dfsg-1) unstable; urgency=low
+
+ [ Aurelien Jarno ]
+ * New upstream stable version:
+ - remove debian/patches/fix-malta-i8259
+ - remove debian/patches/qemu-ifunc-ppc.patch
+ - remove debian/patches/x86-fix-cmpxchg.patch
+
+ [ Michael Tokarev ]
+ * apply patch to change backticks `` in debian/rules variables
+ to $(shell) construct, by Allard Hoeve. (Closes: #660133)
+ * depend on vgabios >= 0.6c-3~ not 0.6c-3, to assist backporting
+
+ [ Hector Oron ]
+ * Fix prctl syscall (Closes: #656926, #651083).
+
+ [ Vagrant Cascadian ]
+ * Update to Standards-Version 3.9.3, no changes necessary.
+
+ -- Vagrant Cascadian <vagrant@debian.org> Mon, 05 Mar 2012 13:05:14 -0800
+
+qemu (1.0+dfsg-3) unstable; urgency=low
+
+ [ Aurelien Jarno ]
+ * Add a build-depends on libfdt-dev to enable some more emulated machines.
+ * Really add binfmt support for s390x.
+
+ [ Michael Tokarev ]
+ * Depend on ipxe-qemu | ipxe (<< 1.0.0+git-20120202.f6840ba-2)
+ after ipxe package split. This will probably need to be changed
+ to just ipxe-qemu once it will be landed properly.
+
+ [ Vagrant Cascadian ]
+ * Apply patch to use dpkg-buildflags (Closes: #656276).
+ Thanks to Moritz Muehlenhoff.
+
+ -- Vagrant Cascadian <vagrant@debian.org> Mon, 06 Feb 2012 17:56:15 -0800
+
+qemu (1.0+dfsg-2) unstable; urgency=low
+
+ [ Aurelien Jarno ]
+ * Add patch from upstream to fix cmpxchg on x86.
+ * Add patch to not link user builds with NSS (Closes: #648202).
+ * Add binfmt support for s390x.
+ * Bump depends on openbios-ppc and openbios-sparc on versions
+ compatible with version 1.0.
+ * Build on s390x (Closes: #651048).
+
+ [ Vagrant Cascadian ]
+ * qemu-make-debian-root: Fix argument processing to handle when both -s and
+ -k are specified. Thanks to Mats Erik Andersson (Closes: #638047).
+ * Add Patch from upstream to fix regression on malta with i8259 interrupts.
+ * qemu-debootstrap: Add support for armhf and s390x.
+ * debian/rules: remove config.log in the clean target.
+ * qemu-make-debian-root: Use debootstrap's minbase variant, instead of a
+ long list of excludes.
+
+ -- Vagrant Cascadian <vagrant@debian.org> Mon, 09 Jan 2012 16:01:17 -0800
+
+qemu (1.0+dfsg-1) experimental; urgency=low
+
+ * New upstream version.
+ * Add build-dep on libxen-dev to enable xen support.
+ * Add build-dep on libiscsi-dev to enable iscsi support.
+ * Add patch from upstream to not block SIGCHLD (Closes: #618743).
+
+ -- Vagrant Cascadian <vagrant@debian.org> Fri, 30 Dec 2011 16:12:03 -0800
+
+qemu (1.0~rc4+dfsg-1) experimental; urgency=low
+
+ * New upstream version:
+ - Fixes CVE-2011-4111.
+ * remove patches applied upstream:
+ - security/leftover.patch
+ - Move_QEMU_INCLUDES_before_QEMU_CFLAGS
+ - runnning-typo.patch
+ * Install new qemu-system variants:
+ xtensa, xtensaeb, alpha
+ * debian/rules: Drop hack to rename "qemu" binary to "qemu-system-i386", as
+ upstream now does the same.
+ * Enable spice support on amd64:
+ - Add Build-Depends: libspice-server-dev, libspice-protocol-dev
+ * debian/rules: use dh_prep instead of "dh_clean -k", which is deprecated.
+ * qemu-system: Bump dependency on seabios to 1.6.3~.
+
+ -- Vagrant Cascadian <vagrant@debian.org> Mon, 28 Nov 2011 23:40:24 -0800
+
+qemu (0.15.1+dfsg-3) unstable; urgency=low
+
+ * Add patch from upstream to fix FTBFS on ia64.
+
+ -- Vagrant Cascadian <vagrant@debian.org> Fri, 09 Dec 2011 23:48:21 -0800
+
+qemu (0.15.1+dfsg-2) unstable; urgency=low
+
+ * Add patch that fixes a buffer overrun (CVE-2011-4111).
+ * Enable spice support on amd64:
+ - Add Build-Depends: libspice-server-dev, libspice-protocol-dev
+ * debian/rules: Use dh_prep instead of "dh_clean -k", which is deprecated.
+
+ -- Vagrant Cascadian <vagrant@debian.org> Mon, 28 Nov 2011 20:34:50 -0800
+
+qemu (0.15.1+dfsg-1) unstable; urgency=low
+
+ * New upstream version.
+
+ -- Vagrant Cascadian <vagrant@debian.org> Sun, 06 Nov 2011 10:37:31 -0800
+
+qemu (0.15.0+dfsg-1) unstable; urgency=low
+
+ * New upstream version.
+ * Install new qemu-system, qemu-user and qemu-user-static variants:
+ lm32, microblazeel, s390x, unicore32
+ * Patch from upstream to set QEMU_INCLUDES before QEMU_CFLAGS.
+ * Update debian/watch to check http://qemu.org/download.
+
+ -- Vagrant Cascadian <vagrant@debian.org> Mon, 03 Oct 2011 12:29:18 -0700
+
+qemu (0.15.0~rc2+dfsg-1) experimental; urgency=low
+
+ * New upstream version.
+ * qemu-debootstrap: Return the exit status of debootstrap instead of
+ hard-coding a sucessful exit status.
+ * Build-depend on librbd-dev.
+ * Remove qemu-mipsel-debian-rootfs.patch, a variation was applied upstream.
+ * Remove pcnet-ipxe patch, applied upstream.
+ * Add Build-Depends on python.
+ * Rename pxe rom symlinks to match upstream rename.
+
+ -- Vagrant Cascadian <vagrant@debian.org> Sun, 07 Aug 2011 13:27:43 +0200
+
+qemu (0.14.1+dfsg-3) unstable; urgency=low
+
+ [ Aurelien Jarno ]
+ * Add patches/qemu-ifunc-ppc.patch and patches/qemu-ifunc-sparc.patch
+ to fix FTBFS on ppc and sparc.
+
+ [ Vagrant Cascadian ]
+ * Apply patch to fix qemu-user-static mipsel emulation (Closes: #562887).
+ * Drop support for esd (Closes: #633390). Thanks to Adrian Bunk.
+ * Add dummy debian/rules build-indep/build-arch targets to resolve lintian
+ warnings and future policy requirements.
+ * Remove needless mention of "Author(s)" which triggers a lintian warning.
+ * Fix maintainer-script-without-set-e lintian checks.
+ * Fix hyphen-used-as-minus-sign lintian check for qemu-debootstrap manpage.
+
+ -- Vagrant Cascadian <vagrant@debian.org> Sat, 23 Jul 2011 10:18:37 +0200
+
+qemu (0.14.1+dfsg-2) unstable; urgency=low
+
+ * Add override for qemu-user-static binaries which embed needed libraries.
+ * Add qemu-debootstrap manpage.
+ * Add patch to fix typo in qemu-system-* (runnning -> running).
+ * Update to Standards-Version 3.9.2, no changes necessary.
+
+ -- Vagrant Cascadian <vagrant@debian.org> Sat, 02 Jul 2011 22:29:17 -0700
+
+qemu (0.14.1+dfsg-1) unstable; urgency=low
+
+ * New upstream version.
+ * Depend on ipxe instead of etherboot-qemu.
+ * Add pcnet-ipxe.patch from upstream to fix ipxe with pcnet nic.
+ * Add symlink for network boot with eepro100 cards (i82551, i82557b,
+ i82559er).
+ * Drop 01_rdb.patch, applied upstream.
+ * Add support for building on armhf architecture.
+ * Support debootstrap options that require arguments in qemu-debootstrap.
+ Thanks to Stefano Rivera for the patch. Closes: #605660.
+
+ -- Vagrant Cascadian <vagrant@debian.org> Fri, 01 Jul 2011 22:49:40 -0700
+
+qemu (0.14.0+dfsg-5.1) unstable; urgency=low
+
+ * Non-maintainer upload.
+ * Replace "librados1-dev" by "librados-dev" in Build-Dependencies.
+
+ -- Mehdi Dogguy <mehdi@debian.org> Fri, 29 Apr 2011 17:45:05 +0200
+
+qemu (0.14.0+dfsg-5) unstable; urgency=low
+
+ * Don't register qemu-mips(el) with binfmt on mips(el). Closes:
+ #618369.
+
+ -- Aurelien Jarno <aurel32@debian.org> Thu, 17 Mar 2011 20:13:27 +0100
+
+qemu (0.14.0+dfsg-4) unstable; urgency=low
+
+ * Reupload without automatically generated patch
+ debian-changes-0.14.0+dfsg-3.
+
+ -- Aurelien Jarno <aurel32@debian.org> Mon, 28 Feb 2011 15:10:04 +0100
+
+qemu (0.14.0+dfsg-3) unstable; urgency=low
+
+ [ Aurelien Jarno ]
+ * Depends on vgabios (>= 0.6c-3) and add symlinks for qxl, stdvga and
+ vmware bioses. Closes: #614252, #614169.
+ * Tighten build-depends on linux-libc-dev to (>= 2.6.34), to get
+ vhost-net support.
+ * Build-depends on xfslibs-dev in order to get TRIM support on XFS
+ filesystems.
+ * Build-depends on librados1-dev to get rdb support. Closes: #614150.
+
+ -- Aurelien Jarno <aurel32@debian.org> Mon, 28 Feb 2011 09:06:00 +0100
+
+qemu (0.14.0+dfsg-2) unstable; urgency=low
+
+ [ Aurelien Jarno ]
+ * Tighten dependencies on openbios-ppc, openbios-sparc and seabios to
+ the versions in upstream 0.14.0.
+ * patches/02_kfreebsd.patch: don't consider futimens/utimensat available
+ if it is a stub.
+
+ -- Aurelien Jarno <aurel32@debian.org> Sun, 20 Feb 2011 00:36:20 +0100
+
+qemu (0.14.0+dfsg-1) unstable; urgency=low
+
+ [ Vagrant Cascadian ]
+ * New upstream release candidate version.
+ * qemu-user-static:
+ - Drop binfmt support for emulating amd64 on i386, as it is broken and
+ including it interferes with environments capable of running amd64
+ natively. Closes: #604712.
+ - Remove binfmt support for installed targets in postinst before installing
+ supported targets, to ensure no-longer-supported targets are actually
+ removed.
+ - Remove binfmt support for installed targets in prerm.
+
+ [ Aurelien Jarno ]
+ * Fix configuration files directory. Closes: #600735.
+ * Enable AIO support.
+
+ [ Vagrant Cascadian ]
+ * Update debian/copyright to refer to upstream git repositry and clarify
+ which binary blobs are removed to make the dfsg-free tarball.
+ * Refresh debian/patches/security/leftover.patch.
+
+ -- Vagrant Cascadian <vagrant@debian.org> Fri, 18 Feb 2011 21:07:01 -0800
+
+qemu (0.13.0+dfsg-2) experimental; urgency=low
+
+ * Fix Build-Depends to exclude kfreebsd-any wildcards where appropriate.
+ Thanks to Jon Severinsson. Closes: #592215
+
+ -- Vagrant Cascadian <vagrant@debian.org> Sun, 24 Oct 2010 09:02:27 -0700
+
+qemu (0.13.0+dfsg-1) experimental; urgency=low
+
+ [ Aurelien Jarno ]
+ * mips/mipsel binfmt registration: also match EI_ABIVERSION=1, used by
+ OpenWRT. Closes: #591543.
+ * Build-depends on libattr1-dev to enable VirtFS (9p) support. Closes:
+ #592215.
+ * Use architecture wildcards instead of explicit architecture list.
+
+ [ Vagrant Cascadian ]
+ * Switch to source format 3.0 (quilt).
+ * New upstream version.
+ * Drop 99_stable.diff, applied in new upstream version.
+ * debian/watch: update to properly handle upstream rc versions.
+
+ -- Vagrant Cascadian <vagrant@debian.org> Mon, 18 Oct 2010 10:22:44 -0700
+
+qemu (0.13.0~rc0+dfsg-2) experimental; urgency=low
+
+ [ Aurelien Jarno ]
+ * Add ia64 to the list of supported architectures.
+ * Bump Standards-Version to 3.9.1 (no changes).
+ * Update seabios, openbios-ppc and openbios-sparc dependencies.
+ * Add 99_stable.diff to update from the stable-0.13 branch:
+ - Fix sparc FTBFS. Closes: #591249.
+ * Add qemu-debootstrap from Loïc Minier in qemu-static. Closes:
+ #572952.
+
+ -- Aurelien Jarno <aurel32@debian.org> Tue, 03 Aug 2010 07:25:06 +0200
+
+qemu (0.13.0~rc0+dfsg-1) experimental; urgency=low
+
+ * New upstream release candidate version.
+ * Do not configure audio drivers for qemu-user and qemu-user-static targets.
+ * Remove patches:
+ - 05_bochs_vbe, applied upstream.
+ - 06_sh4, applied upstream.
+ - 03_support_pselect_in_linux_user_arm, upstream implemented a simpler
+ workaround.
+ * Add Build-Depends on texinfo.
+ * Drop libqemu-dev package.
+
+ -- Vagrant Cascadian <vagrant@debian.org> Thu, 29 Jul 2010 19:51:01 -0400
+
+qemu (0.12.5+dfsg-3) unstable; urgency=medium
+
+ * qemu-user-static:
+ - Drop binfmt support for emulating amd64 on i386, as it is broken and
+ including it interferes with environments capable of running amd64
+ natively. Closes: #604712.
+ - Remove binfmt support for installed targets in postinst before installing
+ supported targets, to ensure no-longer-supported targets are actually
+ removed.
+ - Remove binfmt support for installed targets in prerm.
+
+ -- Vagrant Cascadian <vagrant@debian.org> Sun, 28 Nov 2010 15:57:11 -0800
+
+qemu (0.12.5+dfsg-2) unstable; urgency=low
+
+ * mips/mipsel binfmt registration: also match EI_ABIVERSION=1, used by
+ OpenWRT. Closes: #591543.
+ * Update 99_stable.diff from the stable branch:
+ - Fix windows XP boot with libvirt. Closes: bug#579166.
+
+ -- Aurelien Jarno <aurel32@debian.org> Tue, 17 Aug 2010 12:56:30 +0200
+
+qemu (0.12.5+dfsg-1) unstable; urgency=low
+
+ * New upstream stable version.
+ * qemu-system: don't suggests kqemu-source. Closes: bug#589217.
+ * qemu-keymaps: fix short description.
+
+ -- Aurelien Jarno <aurel32@debian.org> Fri, 23 Jul 2010 19:02:14 +0200
+
+qemu (0.12.4+dfsg-4) unstable; urgency=high
+
+ * Update debian/copyright. Closes: bug#588911.
+ * Update 99_stable.diff from the stable branch:
+ - Add documentation for the stdio signal option. Closes: bug#588514.
+ * Split out keymaps in the qemu-keymaps package. Closes: bug#559174.
+ * Bump Standards-Version to 3.9.0 (no changes).
+
+ -- Aurelien Jarno <aurel32@debian.org> Wed, 14 Jul 2010 15:13:04 +0200
+
+qemu (0.12.4+dfsg-3) unstable; urgency=low
+
+ * Update 99_stable.diff from the stable branch.
+
+ -- Aurelien Jarno <aurel32@debian.org> Wed, 16 Jun 2010 23:07:36 +0200
+
+qemu (0.12.4+dfsg-2) unstable; urgency=low
+
+ [ Vagrant Cascadian ]
+ * qemu-system: Depend on etherboot-qemu package for PXE roms.
+ Closes: #552406.
+
+ [ Aurelien Jarno ]
+ * Add 99_stable.diff to update from the stable branch.
+ * Use --with-pkgversion to set the packaging version.
+
+ -- Aurelien Jarno <aurel32@debian.org> Wed, 02 Jun 2010 21:24:26 +0200
+
+qemu (0.12.4+dfsg-1) unstable; urgency=low
+
+ * New upstream stable version:
+ - remove debian/patches/01_redir_doc.patch
+ - remove debian/patches/04_cmd646.patch
+ - update debian/patches/06_sh4.diff
+
+ -- Aurelien Jarno <aurel32@debian.org> Fri, 07 May 2010 19:43:48 +0200
+
+qemu (0.12.3+dfsg-4) unstable; urgency=low
+
+ * Add 05_bochs_vbe.diff backported from uptream to support vgabios
+ 0.6c.
+ * Add 06_sh4.diff containing a few SH4 specific fixes backported from
+ upstream.
+
+ -- Aurelien Jarno <aurel32@debian.org> Fri, 09 Apr 2010 01:44:38 +0200
+
+qemu (0.12.3+dfsg-3) unstable; urgency=low
+
+ * Add symlink for seabios's multiboot.bin.
+ * Change configure-stamp depends to non-phony target $(QUILT_STAMPFN).
+ Closes: #574444.
+ * Fix a crash in cmd646 bmdma code that can be triggered by the guest.
+ Closes: #574539.
+ * Explain that KQEMU support has been removed in qemu-system.NEWS.
+ * Build-Conflicts with oss4-dev, as this package install a broken
+ <linux/soundcard.h> header. Closes: #575320.
+
+ -- Aurelien Jarno <aurel32@debian.org> Sat, 03 Apr 2010 17:07:23 +0200
+
+qemu (0.12.3+dfsg-2) unstable; urgency=low
+
+ [ Aurelien Jarno ]
+ * Disable KVM support on PowerPC, as it needs at least 2.6.33 kernel
+ headers.
+
+ [ Vagrant Cascadian ]
+ * Support pselect for linux-user arm target. Patch by Michael Casadevall.
+ * Add symlink for seabios's linuxboot.bin to fix -kernel option. Thanks to
+ Sami Liedes. Closes: #574174.
+ * qemu-system: Switch back to using versioned dependencies for vgabios,
+ bochsbios, openhackware, openbios-ppc and openbios-sparc rather than
+ recommends/conflicts, to ensure a proper upgrade path. Closes: #573397.
+ Reopens: #436094.
+
+ -- Vagrant Cascadian <vagrant@debian.org> Fri, 19 Mar 2010 09:31:29 -0700
+
+qemu (0.12.3+dfsg-1) unstable; urgency=low
+
+ [ Vagrant Cascadian ]
+ * New upstream version:
+ - Fix access to block devices on GNU/kFreeBSD. Closes: #558447.
+ - Correctly update clock when waking up from sleep. Closes: #414165.
+ - Slirp works with other network interfaces. Closes: #407702.
+ - Add the possibility to specify a host to bind to with the -redir
+ option. Closes: #366847.
+ - Fix cirrus graphics card with windows 98. Closes: #522124.
+ * Indicate repackaged upstream tarball by adding "+dfsg" to the version.
+ Closes: #388740.
+ * Remove second libgnutls-dev from build depends.
+ * Update debian/watch with current location of tarball releases.
+ * Drop binutils-gold patch, applied upstream.
+ * Switch from bochsbios to seabios. Update bios.bin symlink and
+ recommends/conflicts.
+ * Bump Standards-Version to 3.8.4 (no changes).
+ * Update my email address to vagrant@debian.org.
+
+ [ Aurelien Jarno ]
+ * Create a kvm group in postinst and set the group of /dev/kvm to kvm.
+ Closes: #570544.
+ * Add mips and mipsel to the list of supported architectures.
+ * Add patches/01_redir_doc.patch to fix a mistake in the redirection
+ documentation.
+ * Add patches/02_kfreebsd.patch to use the legacy USB stack on
+ GNU/kFreeBSD.
+ * Force the depends from qemu on qemu-system, qemu-user and qemu-utils
+ to (>= {source:Version}).
+ * Update openbios related conflicts.
+
+ -- Vagrant Cascadian <vagrant@debian.org> Sun, 07 Mar 2010 09:20:43 -0800
+
+qemu (0.11.1-2) unstable; urgency=low
+
+ * Add versioned build-depends on etherboot.
+ * Add PXE boot support for virtio network adapters.
+ * Move qemu-make-debian-root to qemu-utils package, as it only produces disk
+ images not useable by qemu-user. Lower recommends on debootstrap to
+ suggests. Add Conflicts and Replaces on older versions of qemu-user.
+ * Register /usr/bin/qemu with the alternatives system. Closes: #413840.
+ * qemu: Add ${misc:Depends} so that debhelper can add dependencies if needed.
+
+ -- Vagrant Cascadian <vagrant@freegeek.org> Fri, 08 Jan 2010 09:26:11 -0800
+
+qemu (0.11.1-1) unstable; urgency=low
+
+ [ Aurelien Jarno ]
+ * New upstream version.
+ * Drop build-depends on libfreebsd-dev on GNU/kFreeBSD.
+ * qemu: suggests qemu-user-static.
+ * qemu-user-static: register QEMU with binfmt mecanism. Closes:
+ #306637.
+ * Bump conflicts on openbios-ppc to (<< 1.0+svn505-1).
+ * Add 01-binutils-gold.diff to fix FTBFS with binutils-gold. Closes:
+ #556301.
+ * Add sparc64 support.
+ * Use new roms location in etherboot package.
+
+ [ Vagrant Cascadian ]
+ * qemu-utils, qemu-user, qemu-system: Set both Conflicts and Replaces for
+ older versions of qemu to ensure proper upgrade path.
+ * Add versioned build-dep on linux-libc-dev to ensure that KVM support is
+ enabled.
+ * qemu-system: Lower dependencies on vgabios, bochsbios, openhackware,
+ openbios-ppc and openbios-sparc to recommends. Conflict with versions that
+ are incompatible. Closes: #436094.
+ * qemu-utils: Tighten the versioned conflicts with kvm, as not all older
+ versions actually conflict.
+ * qemu-make-debian-root: Apply modified patch from Nicolas Boulenguez that
+ documents usage of -s, exits on error, and mentions that it is normally
+ run as root. Closes: #447034.
+
+ -- Aurelien Jarno <aurel32@debian.org> Sun, 27 Dec 2009 12:09:11 +0100
+
+qemu (0.11.0-6) unstable; urgency=low
+
+ * Update from stable-0.11 branch.
+ * qemu-utils: add Replaces: qemu (<< 0.11.0-2). Closes: #556627,
+ #556860.
+
+ -- Aurelien Jarno <aurel32@debian.org> Fri, 20 Nov 2009 08:24:32 +0100
+
+qemu (0.11.0-5) unstable; urgency=low
+
+ * Change the Conflicts: into Replaces: to handle the move of /etc/ifup
+ from one package to another correctly. Tighten the version. Closes:
+ #556627.
+
+ -- Aurelien Jarno <aurel32@debian.org> Wed, 18 Nov 2009 16:30:39 +0000
+
+qemu (0.11.0-4) unstable; urgency=low
+
+ [ Aurelien Jarno ]
+ * Update from stable-0.11 branch.
+ * Default to alsa before OSS. Closes: #451234.
+
+ [ Vagrant Cascadian ]
+ * Updated Vcs-Git to a url more likely to work with debcommit.
+
+ -- Aurelien Jarno <aurel32@debian.org> Wed, 18 Nov 2009 16:26:17 +0100
+
+qemu (0.11.0-3) unstable; urgency=low
+
+ * qemu-system, qemu-user: fix conflicts version. Closes: #556627.
+ * qemu-utils: conflicts with kvm (<= 85+dfsg-4.1), as it also provides
+ qemu-io.
+
+ -- Aurelien Jarno <aurel32@debian.org> Tue, 17 Nov 2009 09:49:24 +0100
+
+qemu (0.11.0-2) unstable; urgency=low
+
+ * Update from stable-0.11 branch.
+ * Move qemu-user.1 and qemu-make-debian-root.8 to the qemu-user
+ package.
+ * Add build-depends on uuid-dev.
+ * Use a specific install file for qemu-utils on GNU/kFreeBSD.
+ * Call dh_install with -s.
+
+ -- Aurelien Jarno <aurel32@debian.org> Tue, 17 Nov 2009 09:11:29 +0100
+
+qemu (0.11.0-1) unstable; urgency=low
+
+ [ Aurelien Jarno ]
+ * New upstream version.
+ - Documents virtio NIC. Closes: #541182.
+ - Increase the maximum TCG op a target instruction op can expand to.
+ Closes: #530645, #542297.
+ - KVM is enabled by default. Closes: #520894.
+ - Fix CVE-2009-3616. Closes: #553589.
+ * Drop 65_kfreebsd.patch.
+ * Split the qemu package and use out of tree building. Based on a patch
+ from Vagrant Cascadian. Closes: #524774.
+ * Only recommends debootstrap for qemu-user and qemu-user static. Closes:
+ #543356.
+ * Remove /usr/share/qemu/proll.elf. Closes: bug#542247.
+ * Add build-depends on libcurl4-gnutls-dev, libgnutls-dev and libsasl2-dev
+ to enable new upstream features.
+ * Bump Standards-Version to 3.8.3 (no changes).
+ * Update Vcs-* fields to point to the new git repository.
+ * Add Vagrant Cascadian <vagrant@freegeek.org> to uploaders, and set
+ DM-Upload-Allowed to yes.
+
+ -- Aurelien Jarno <aurel32@debian.org> Mon, 26 Oct 2009 10:17:57 +0000
+
+qemu (0.10.50+git20090729-1) experimental; urgency=low
+
+ [ Josh Triplett ]
+ * Remove myself from Uploaders.
+
+ [ Riku Voipio ]
+ * new upstream RC version
+ * nuke all linux-user patches (applied upstream)
+ 06_exit_segfault
+ 12_signal_powerpc_support
+ 21_net_soopts
+ 30_syscall_ipc
+ 32_syscall_sysctl
+ 35_syscall_sockaddr
+ 48_signal_terminate
+ 55_unmux_socketcall
+ * nuke all other applied-upstream patches
+ 01_nostrip (better version upstream)
+ 07_i386_exec_name (can be reintroduced in debian/rules)
+ 50_linuxbios_isa_bios_ram (shouldn't be needed anymore)
+ 51_linuxbios_piix_ram_size (applied)
+ 56_dhcp (crap)
+ 60_ppc_ld (reintroduce if needed)
+ 64_ppc_asm_constraints (ditto)
+ 66_tls_ld.patch (ditto)
+ 81_compile_dtb.patch (applied upstream)
+ 82_qemu-img_decimal (ditto)
+ * move to git
+ * simplify build rules
+ * Correct my email address
+
+ -- Riku Voipio <riku.voipio@iki.fi> Wed, 29 Jul 2009 13:28:05 +0300
+
+qemu (0.10.6-1) unstable; urgency=low
+
+ [ Josh Triplett ]
+ * Remove myself from Uploaders.
+
+ [ Aurelien Jarno ]
+ * New upstream version.
+ * Bump Standards-Version to 3.8.2 (no changes).
+ * Update debian/watch (closes: bug#538781).
+
+ -- Aurelien Jarno <aurel32@debian.org> Fri, 31 Jul 2009 15:25:36 +0200
+
+qemu (0.10.5-1) unstable; urgency=low
+
+ * New upstream version.
+
+ -- Aurelien Jarno <aurel32@debian.org> Sun, 24 May 2009 16:15:35 +0200
+
+qemu (0.10.4-1) unstable; urgency=low
+
+ * New upstream version.
+ * debian/NEWS.Debian: new file, describing the cache policy options
+ (closes: bug#526832).
+ * debian/patches/70_versatile_memsize.patch: new patch to set a upper
+ limit on the memory size of the versatile boards (closes:
+ bug#527264).
+
+ -- Aurelien Jarno <aurel32@debian.org> Tue, 12 May 2009 18:31:29 +0200
+
+qemu (0.10.3-1) unstable; urgency=low
+
+ * New upstream version.
+ * Tighten dependency on bochsbios.
+
+ -- Aurelien Jarno <aurel32@debian.org> Sat, 02 May 2009 10:14:21 +0200
+
+qemu (0.10.2-2) unstable; urgency=low
+
+ * Add missing comma in build-depends (closes: bug#524207).
+ * Tighten dependency on vgabios.
+
+ -- Aurelien Jarno <aurel32@debian.org> Wed, 15 Apr 2009 22:30:43 +0200
+
+qemu (0.10.2-1) unstable; urgency=low
+
+ [ Aurelien Jarno ]
+ * New upstream stable release.
+
+ -- Aurelien Jarno <aurel32@debian.org> Tue, 07 Apr 2009 07:37:15 +0200
+
+qemu (0.10.1-1) unstable; urgency=low
+
+ [ Aurelien Jarno ]
+ * New upstream stable release:
+ - patches/80_stable-branch.patch: remove.
+ * debian/control:
+ - Remove depends on proll.
+ - Move depends on device-tree-compiler to build-depends.
+ - Bump Standards-Version to 3.8.1 (no changes).
+ * patches/82_qemu-img_decimal.patch: new patch from upstream to make
+ qemu-img accept sizes with decimal values (closes: bug#501400).
+
+ -- Aurelien Jarno <aurel32@debian.org> Sun, 22 Mar 2009 10:13:17 +0100
+
+qemu (0.10.0-1) unstable; urgency=low
+
+ [ Aurelien Jarno ]
+ * New upstream release:
+ - Fix fr-be keyboard mapping (closes: bug#514462).
+ - Fix stat64 structure on ppc-linux-user (closes: bug#470231).
+ - Add a chroot option (closes: bug#415996).
+ - Add evdev support (closes: bug#513210).
+ - Fix loop on symlinks in user mode (closes: bug#297572).
+ - Bump depends on openbios-sparc.
+ - Depends on openbios-ppc.
+ - Update 12_signal_powerpc_support.patch.
+ - Update 21_net_soopts.patch.
+ - Drop 44_socklen_t_check.patch (merged upstream).
+ - Drop 49_null_check.patch (merged upstream).
+ - Update 64_ppc_asm_constraints.patch.
+ - Drop security/CVE-2008-0928-fedora.patch (merged upstream).
+ - Drop security/CVE-2007-5730.patch (merged upstream).
+ * patches/80_stable-branch.patch: add patches from stable branch:
+ - Fix race condition between signal handler/execution loop (closes:
+ bug#474386, bug#501731).
+ * debian/copyright: update.
+ * Compile and install .dtb files:
+ - debian/control: build-depends on device-tree-compiler.
+ - debian/patches/81_compile_dtb.patch: new patch from upstream.
+ - debian/rules: compile and install bamboo.dtb and mpc8544.dtb.
+
+ -- Aurelien Jarno <aurel32@debian.org> Sat, 07 Mar 2009 06:20:34 +0100
+
+qemu (0.9.1+svn20090104-1) experimental; urgency=low
+
+ [ Aurelien Jarno ]
+ * New upstream snapshot.
+ * Disable security/CVE-2008-0928-fedora.patch, it still breaks qcow
+ format.
+
+ -- Aurelien Jarno <aurel32@debian.org> Sun, 04 Jan 2009 16:31:40 +0100
+
+qemu (0.9.1+svn20081223-1) experimental; urgency=low
+
+ [ Aurelien Jarno ]
+ * New upstream snapshot.
+ - Fix CVE-2008-2382
+ * Update patches/48_signal_terminate.patch.
+ * debian/rules: remove upstream flags from CFLAGS.
+
+ -- Aurelien Jarno <aurel32@debian.org> Tue, 23 Dec 2008 14:51:25 +0100
+
+qemu (0.9.1+svn20081214-1) experimental; urgency=low
+
+ [ Aurelien Jarno ]
+ * New upstream snapshot.
+ - Fix jmp im on x86_64 when executing 32-bit code. Fix grub
+ installation (Closes: bug#467148).
+
+ -- Aurelien Jarno <aurel32@debian.org> Sun, 14 Dec 2008 23:26:04 +0100
+
+qemu (0.9.1+svn20081207-1) experimental; urgency=low
+
+ [ Aurelien Jarno ]
+ * New upstream snapshot.
+ - Do not depend on gcc-3.4 anymore (Closes: bug#440425, bug#463066).
+ - Fix broken display introduced by CVE-2007-1320 (Closes: bug#422578).
+ * debian/control: remove build-dependency on gcc-3.4.
+ * debian/rules: remove code for dyngen targets.
+ * Split 90_security.patch into
+ - security/CVE-2007-5730.patch
+ - security/leftover.patch
+ * Replace 91_security.patch by security/CVE-2008-0928-fedora.patch taken
+ from fedora repository and enable it (Closes: #469649).
+
+ [ Riku Voipio ]
+ * 2 patches gone, 19 to go:
+ - 10_signal_jobs.patch: drop, merged upstream
+ - 11_signal_sigaction.patch: drop, merged upstream
+ - series: update
+
+ -- Aurelien Jarno <aurel32@debian.org> Sun, 07 Dec 2008 19:40:09 +0100
+
+qemu (0.9.1+svn20081128-1) experimental; urgency=low
+
+ [ Aurelien Jarno ]
+ * New upstream snapshot.
+ - Include documentation for network downscript option (Closes:
+ bug#506994).
+ - Drop 00_bios.patch and pass --disable-blobs instead.
+ - Update 12_signal_powerpc_support.patch.
+
+ [ Riku Voipio ]
+ * Drop 31_syscalls.patch as it makes no sense using host uselib to
+ load target code into qemu's host memoryspace.
+
+ -- Aurelien Jarno <aurel32@debian.org> Sat, 29 Nov 2008 09:04:41 +0100
+
+qemu (0.9.1+svn20081112-1) experimental; urgency=low
+
+ [ Aurelien Jarno ]
+ * New upstream snapshot.
+ - does not need a disk image anymore (Closes: bug#260935).
+ - 53_openbios_size.patch: drop (merged upstream).
+ - 90_security: update.
+ * debian/control: depend on openbios-sparc (>= 1.0~alpha2+20081109)
+ (Closes: bug#502411, bug#502414).
+
+ -- Aurelien Jarno <aurel32@debian.org> Sun, 09 Nov 2008 14:42:37 +0100
+
+qemu (0.9.1+svn20081101-1) experimental; urgency=low
+
+ [ Aurelien Jarno ]
+ * New upstream snapshot.
+ - fix a heap overflow in Cirrus emulation (CVE-2008-4539).
+ - 50_linuxbios_isa_bios_ram.patch: update.
+ - 90_security.patch: update.
+
+ -- Aurelien Jarno <aurel32@debian.org> Sat, 01 Nov 2008 09:26:45 +0100
+
+qemu (0.9.1+svn20081023-1) experimental; urgency=low
+
+ [ Aurelien Jarno ]
+ * New upstream snapshot.
+ - 12_signal_powerpc_support.patch: update.
+ - 50_linuxbios_isa_bios_ram.patch: update.
+
+ -- Aurelien Jarno <aurel32@debian.org> Thu, 23 Oct 2008 21:34:26 +0200
+
+qemu (0.9.1+svn20081016-1) experimental; urgency=low
+
+ [ Aurelien Jarno ]
+ * New upstream snapshot.
+ * patches/31_syscalls.patch: remove parts merged upstream.
+ * debian/qemu-make-debian-root:
+ - Fix bug introduced when fixing bug#496394 (Closes: bug#502325).
+
+ -- Aurelien Jarno <aurel32@debian.org> Mon, 13 Oct 2008 23:11:15 +0200
+
+qemu (0.9.1+svn20081012-1) experimental; urgency=low
+
+ [ Riku Voipio ]
+ * Add a bunch of patches from scratchbox
+ - 44_socklen_t_check work better with badbehavin net apps
+ - 48_signal_terminate make qemu binary terminate on signals as expected
+ - 49_null_checks don't bother some syscalls when null/zero is passed
+
+ [ Aurelien Jarno ]
+ * New upstream snapshot.
+ - alpha is now a TCG target.
+ - comma has been added to sendkey (closes: bug#414342).
+ * patches/31_syscalls.patch: remove parts merged upstream.
+ * patches/39_syscall_fadvise64.patch: remove (merged upstream).
+ * patches/90_security.patch: remove parts merged upstream.
+ * debian/control: build-depends on libbluetooth-dev.
+
+ -- Aurelien Jarno <aurel32@debian.org> Sun, 12 Oct 2008 18:46:54 +0200
+
+qemu (0.9.1+svn20080905-1) experimental; urgency=low
+
+ * New upstream snapshot.
+ - SH4 is now a TCG target.
+ * debian/watch: update URL location.
+
+ -- Aurelien Jarno <aurel32@debian.org> Tue, 02 Sep 2008 01:43:24 +0200
+
+qemu (0.9.1+svn20080826-1) experimental; urgency=low
+
+ * New upstream snapshot.
+ * debian/qemu-make-debian-root:
+ - Use mktemp instead of $$ to create temporary directories (Closes:
+ bug#496394).
+ * Ship a libqemu-dev package (Closes: bug#451618).
+
+ -- Aurelien Jarno <aurel32@debian.org> Tue, 26 Aug 2008 09:55:36 +0200
+
+qemu (0.9.1+svn20080822-1) experimental; urgency=low
+
+ * New upstream snapshot.
+ - Focus to monitor to ask password (Closes: bug#473240).
+ - TCG SPARC host support (Closes: bug#450817).
+ - Check KQEMU availability before allocating memory (Closes: bug#414566).
+ - Fix dead keys (Closes: bug#489594).
+ - Fix ES1370 emulation (Closes: bug#494462).
+ - New USB UHCI implemnation (Closes: bug#457651).
+ - Add debian/patches/00_bios.patch.
+ - Remove debian/patches/02_snapshot_use_tmpdir.patch (merged).
+ - Remove debian/patches/04_do_not_print_rtc_freq_if_ok.patch (merged).
+ - Remove patches/05_non-fatal_if_linux_hd_missing.patch (merged).
+ - Update debian/patches/07_i386_exec_name.patch
+ - Update debian/patches/12_signal_powerpc_support.patch
+ - Remove debian/patches/33_syscall_ppc_clone.patch (merged differently).
+ - Remove debian/patches/41_arm_fpa_sigfpe.patch (merged).
+ - Remove debian/patches/42_arm_tls.patch (merged differently).
+ - Update debian/patches/55_unmux_socketcall.patch.
+ - Remove debian/patches/63_sparc_build.patch (useless).
+ - Update debian/patches/65_kfreebsd.patch.
+ - Update debian/patches/66_tls_ld.patch.
+ - Remove debian/patches/70_manpage.patch (merged).
+ - Remove debian/patches/71_doc.patch (merged).
+ - Remove debian/patches/80_ui_curses.patch (merged).
+ - Remove debian/patches/81_mips32r2_fpu.patch (merged).
+ - Remove debian/patches/82_mips_abs.patch (merged).
+ - Remove debian/patches/83_usb-serial.patch (merged).
+ - Remove debian/patches/84_rtl8139.patch (merged).
+ - Remove debian/patches/85_vvfat.patch (merged).
+ - Remove debian/patches/86_df.patch (merged).
+ - Remove debian/patches/87_eoi.patch (merged).
+ - Remove debian/patches/88_dma.patch (merged).
+ - Remove debian/patches/89_braille.patch (merged).
+ - Remove debian/patches/92_no_shutdown.patch (merged).
+ - Remove debian/patches/93_tmpfs.patch (merged).
+ - Remove debian/patches/94_security.patch (merged).
+ * debian/README.source: new file.
+ * debian/patches/*: convert to patchlevel 1 (Closes: bug#484963).
+ * debian/control:
+ - Add build-depends on libesd0-dev.
+ - Add build-depends on libpulse-dev.
+ - Add build-depends on libvdeplug2-dev.
+ - Add build-depends on etherboot.
+ - Update list of supported targets (Closes: bug#488339).
+ - Suggests kqemu-source.
+ - Bump Standards-Version to 3.8.0.
+ * debian/links:
+ - Add missing manpage symlinks.
+ * debian/rules:
+ - Enable audio drivers depending on the system.
+ - Enable DYNGEN targets depending on the system.
+ - Install PXE bios from etherboot (Closes: bug#412010).
+ - Don't ignore make clean errors.
+ - Don't build DYNGEN targets on kfreebsd-amd64 (Closes: bug#494353).
+ * debian/patches/22_net_tuntap_stall.patch: remove (outdated).
+
+ -- Aurelien Jarno <aurel32@debian.org> Fri, 22 Aug 2008 01:00:54 +0200
+
+qemu (0.9.1-5) unstable; urgency=high
+
+ [ Guillem Jover ]
+ * Add Homepage field.
+ * Add Vcs-Browser and Vcs-Svn fields.
+ * Remove packaging repository information from debian/copyright.
+ * Add former package co-maintainers to debian/copyright.
+ * Serialize patch and configure steps in debian/rules to support parallel
+ builds, as we are patching configure.
+ * Remove myself from Uploaders.
+
+ [ Aurelien Jarno ]
+ * debian/patches/70_manpage.patch: remove curses documentation, it is already
+ in debian/patches/80_ui_curses.patch (Closes: bug#477369).
+ * debian/patches/94_security.patch: add format= to drive options
+ (CVE-2008-2004).
+
+ -- Aurelien Jarno <aurel32@debian.org> Mon, 28 Apr 2008 21:54:12 +0200
+
+qemu (0.9.1-4) unstable; urgency=high
+
+ * debian/patches/52_ne2000_return.patch: drop, the patch is wrong.
+ * Backports from upstream:
+ - Typo in curses_keys.h
+ - Documentation for the -curses option
+ - Fix broken absoluteness check for cabs.d.*.
+ - USB-to-serial device.
+ - rtl8139: fix endianness on big endian targets
+ - restore rw support for vvfat
+ - x86-64: recompute DF after eflags has been modified when emulating
+ SYSCALL
+ - ignore reads to the EOI register
+ - IDE: Improve DMA transfers by increasing the buffer size
+ - Braille device support
+ - Add -no-shutdown option (Closes: #326406)
+ - Ask to use "mount -o remount" instead of "umount" and "mount"
+ /dev/shm (Closes: #476539).
+ * debian/qemu.doc-base: fix section.
+
+ -- Aurelien Jarno <aurel32@debian.org> Sun, 20 Apr 2008 23:29:42 +0200
+
+qemu (0.9.1-3) unstable; urgency=low
+
+ [ Aurelien Jarno ]
+ * debian/patches/42_arm_tls.patch: fix to get qemu-system-arm working
+ again. (Closes: #471722).
+ * debian/patches/56_dhcp.patch: fix DHCP server to correctly support
+ MS-Windows guests. (Closes: #471452).
+
+ -- Aurelien Jarno <aurel32@debian.org> Wed, 19 Mar 2008 18:58:29 +0100
+
+qemu (0.9.1-2) unstable; urgency=low
+
+ [ Aurelien Jarno ]
+ * debian/patches/80_ui_curses.patch: pull new patch from upstream CVS
+ (Closes: #442274).
+ * debian/patches/65_kfreebsd.patch: link with -lfreebsd. (Closes:
+ #465932).
+ * debian/patches/81_mips32r2_fpu.patch: patch pulled from upstream
+ to fix FPU issue on MIPS32R2.
+ * debian/patches/42_arm_tls.patch: reenable, mistakenly disabled in the
+ previous upload. (Closes: #469743).
+ * debian/rules: fix parallel building. (Closes: #469981).
+ * debian/patches/07_i386_exec_name.patch: install the i386 emulator as
+ qemu-system-i386, and change qemu into a link pointing to the i386
+ version.
+ * debian/README.Debian: add notes about qemu-system-ppc and video.x
+ (Closes: #388735).
+ * debian/patches/70_manpage.patch: describe the -curses option.
+ (Closes: #433658).
+ * debian/patches/71_doc.patch: fix the monitor change option. (Closes:
+ #467106).
+ * debian/patches/35_syscall_sockaddr.patch: fix sockaddr (Closes:
+ #469351).
+ * debian/patches/43_arm_cpustate.patch: disable (Closes: #444171).
+
+ -- Aurelien Jarno <aurel32@debian.org> Mon, 17 Mar 2008 01:29:03 +0100
+
+qemu (0.9.1-1) unstable; urgency=low
+
+ [ Aurelien Jarno ]
+ * New upstream version. (Closes: #459801)
+ - Supports s390 host. (Closes: #441119)
+ - Fix PCI bar allocation. (Closes: #413315)
+ - Fix typo in keys name. (Closes: #426181)
+ - Fix segfault of qemu-i386 (Closes: #446868).
+ - debian/control: bump depends on openbios-sparc to
+ >= 1.0~alpha2+20080106.
+ - debian/patches/02_snapshot_use_tmpdir.patch: Refreshed.
+ - debian/patches/04_do_not_print_rtc_freq_if_ok.patch: Likewise.
+ - debian/patches/05_non-fatal_if_linux_hd_missing.patch: Likewise.
+ - debian/patches/06_exit_segfault.patch: Likewise.
+ - debian/patches/10_signal_jobs.patch: Likewise.
+ - debian/patches/11_signal_sigaction.patch: Likewise.
+ - debian/patches/12_signal_powerpc_support.patch: Likewise.
+ - debian/patches/21_net_soopts.patch: Likewise.
+ - debian/patches/30_syscall_ipc.patch: Likewise.
+ - debian/patches/31_syscalls.patch: Likewise.
+ - debian/patches/32_syscall_sysctl.patch: Likewise.
+ - debian/patches/33_syscall_ppc_clone.patch: Likewise.
+ - debian/patches/35_syscall_sockaddr.patch: Likewise.
+ - debian/patches/41_arm_fpa_sigfpe.patch: Likewise.
+ - debian/patches/42_arm_tls.patch: Likewise.
+ - debian/patches/50_linuxbios_isa_bios_ram.patch: Likewise
+ - debian/patches/51_linuxbios_piix_ram_size.patch: Likewise
+ - debian/patches/61_safe_64bit_int.patch: Removed, merged upstream.
+ - debian/patches/63_sparc_build.patch: Refreshed.
+ - debian/patches/80_ui_curses.patch: Likewise.
+ * debian/patches/90_security.patch: fix 64-bit overflow. (Closes:
+ #425634)
+ * debian/qemu-make-debian-root: add a -s option to create sparse
+ image. (Closes: #322325)
+ * debian/control: bump depends on bochsbios to >= 2.3.5-1. Use
+ BIOS-qemu-latest instead of BIOS-bochs-latest. (Closes: #402289,
+ #442822)
+ * debian/rules: build the non-dyngen part with default gcc.
+ * debian/rules: support DEB_BUILD_OPTIONS="parallel=n".
+ * debian/patches/70_manpage.patch: describe the arguments of the
+ -usbdevice option in the manpage. (Closes: #443801)
+ * debian/control: now using Standards-Version 3.7.3 (no changes needed).
+ * debian/control: build-depends on libgnutls-dev to enable TLS support
+ in VNC.
+ * debian/patches/01_nostrip.patch: don't strip binaries during make
+ install. (Closes: #437866)
+ * debian/patches/53_openbios_size.patch: increase maximum prom size to
+ support latest openbios.
+
+ -- Aurelien Jarno <aurel32@debian.org> Mon, 28 Jan 2008 21:24:14 +0100
+
+qemu (0.9.0+20070816-1) unstable; urgency=low
+
+ [ Guillem Jover ]
+ * New upstream snapshot.
+ - Fix hang on ARM during Etch installation. (Closes: #430164)
+ - Fix data corruption with qcow 2. (Closes: #440296)
+ - Fix errors with raw images > 4 GiB. (Closes: #425634)
+ - debian/patches/01_typo_qemu-img.patch: Removed, merged upstream.
+ - debian/patches/03_machines_list_no_error.patch: Likewise.
+ - debian/patches/36_syscall_prctl.patch: Likewise.
+ - debian/patches/37_syscall_mount.patch: Likewise.
+ - debian/patches/38_syscall_semctl.patch: Likewise.
+ - debian/patches/40_sparc_fp_to_int.patch: Likewise.
+ - debian/patches/44_arm_eabi_built_on_64bit_arches.patch: Likewise.
+ - debian/patches/62_linux_boot_nasm.patch: Likewise.
+ - debian/patches/04_do_not_print_rtc_freq_if_ok.patch: Synced.
+ - debian/patches/05_non-fatal_if_linux_hd_missing.patch: Likewise.
+ - debian/patches/31_syscalls.patch: Likewise.
+ - debian/patches/35_syscall_sockaddr.patch: Likewise.
+ - debian/patches/42_arm_tls.patch: Likewise.
+ - debian/patches/43_arm_cpustate.patch: Likewise.
+ - debian/patches/51_linuxbios_piix_ram_size.patch: Likewise.
+ - debian/patches/55_unmux_socketcall.patch: Likewise.
+ - debian/patches/60_ppc_ld.patch: Likewise.
+ - debian/patches/65_kfreebsd.patch: Likewise.
+ - debian/patches/80_ui_curses.patch: Likewise.
+ - debian/patches/90_security.patch: Likewise.
+ * Remove Elrond and Guilherme de S. Pastore from Uploaders, with their
+ permission, and add Aurelien Jarno and Riku Voipio.
+ * Remove Tag field, this is better maintained outside of the package.
+ * Add openbios-sparc64 to qemu_bios_files in debian/rules.
+
+ [ Aurelien Jarno ]
+ * Fix FTBFS on amd64. (Closes: #434296)
+ - Drop debian/patches/34_syscalls_types.patch
+ * debian/control:
+ - Suggest samba. (Closes: #430368)
+ * Add OpenBIOS for sparc. (Closes: #407076)
+ - debian/control: depends on openbios-sparc.
+ - debian/links: provide symlinks in /usr/share/qemu.
+
+ -- Guillem Jover <guillem@debian.org> Tue, 04 Sep 2007 04:04:47 +0300
+
+qemu (0.9.0-2) unstable; urgency=high
+
+ [ Guillem Jover ]
+ * Fix several security issues. (Closes: #424070)
+ Thanks to Tavis Ormandy <taviso@google.com>.
+ - Cirrus LGD-54XX "bitblt" heap overflow. CVE-2007-1320
+ - NE2000 "mtu" heap overflow.
+ - QEMU "net socket" heap overflow.
+ - QEMU NE2000 "receive" integer signedness error. CVE-2007-1321
+ - Infinite loop in the emulated SB16 device.
+ - Unprivileged "aam" instruction does not correctly handle the
+ undocumented divisor operand. CVE-2007-1322
+ - Unprivileged "icebp" instruction will halt emulation. CVE-2007-1322
+ - debian/patches/90_security.patch: New file.
+ * Enable adlib audio emulation. (Closes: #419170)
+ * Fix structure padding for target_eabi_flock64 when built for a 64 bit
+ architecture. (Closes: #414799)
+ Thanks to Stuart Anderson <anderson@netsweng.com>.
+ - debian/patches/44_arm_eabi_built_on_64bit_arches.patch: New file.
+ * Fix qemu to be able to use LinuxBios. (Closes: #412212)
+ Thanks to Ed Swierk <eswierk@cs.stanford.edu>.
+ - debian/patches/50_linuxbios_isa_bios_ram.patch: New file.
+ - 51_linuxbios_piix_ram_size.patch: Likewise.
+ * Fix segfault when booting a Linux kernel w/o a disk image, by exiting but
+ clarifying the message, as to use '/dev/null'. (Closes: #409817, #411780)
+ Thanks to Robert Millan <rmh@aybabtu.com>.
+ - debian/patches/05_non-fatal_if_linux_hd_missing.patch: Updated.
+ * Fix segfault by using addrlen instead of target_addrlen in
+ do_getpeername()/do_getsockname(). (Closes: #411910)
+ Thanks to Stuart Anderson <anderson@netsweng.com>.
+ - debian/patches/35_syscall_sockaddr.patch: Updated.
+ * Fix semctl() for 32 bit targets on 64 bit hosts. (Closes: #414809)
+ Thanks to Stuart Anderson <anderson@netsweng.com>.
+ - debian/patches/38_syscall_semctl.patch: New file.
+ * Remove Elrond from Uploaders with consent, always welcome to join
+ back anytime.
+
+ -- Guillem Jover <guillem@debian.org> Wed, 16 May 2007 08:08:31 +0300
+
+qemu (0.9.0-1) experimental; urgency=low
+
+ [ Guillem Jover ]
+ * New upstream release. (Closes: #409989)
+ - Support for relative paths in backing files for disk images.
+ (Closes: #390446)
+ - debian/patches/01_doc_typos.patch: Removed, merged upstream.
+ - debian/patches/38_syscall_arm_statfs64.patch: Likewise.
+ - debian/patches/51_serial_small_divider.patch: Likewise.
+ - debian/patches/67_ppc_ftbfs.patch: Likewise.
+ - debian/patches/21_net_soopts.patch: Synced.
+ - debian/patches/30_syscall_ipc.patch: Likewise.
+ - debian/patches/31_syscalls.patch: Likewise.
+ - debian/patches/35_syscall_sockaddr.patch: Likewise.
+ - debian/patches/39_syscall_fadvise64.patch: Likewise.
+ - debian/patches/42_arm_tls.patch: Likewise.
+ - debian/patches/55_unmux_socketcall.patch: Likewise.
+ - debian/patches/80_ui_curses.patch: Likewise.
+ * Update the copyright information.
+ * The ACPI initialization code has been moved to bochsbios.
+ - debian/patches/acpi-dsdt.hex: Removed.
+ - debian/rules: Do not install acpi-dsdt.hex.
+ * Add more files to the list of roms removed from the tarball needed to
+ be touched so that upstream 'make install' does not fail.
+ * Added armeb and armel to Architecture fields and libgpmg1-dev
+ Build-Depends.
+ * Recommend vde2 instead of the transitional vde package. (Closes: #407251)
+ * Fix typo in qemu-img output. (Closes: #408542)
+ - debian/patches/01_typo_qemu-img.patch: New file.
+ Thanks to Adam Buchbinder <adam.buchbinder@gmail.com>.
+ * Symlink qemu-user(1) to qemu-m68k(1).
+ * Reduce redundancy in qemu-user(1) synopsis.
+ * Fix rounding in sparc floating point to integer conversions.
+ - debian/patches/40_sparc_fp_to_int.patch: New file.
+ Thanks to Aurelien Jarno <aurelien@aurel32.net>.
+
+ -- Guillem Jover <guillem@debian.org> Thu, 8 Feb 2007 01:01:29 +0200
+
+qemu (0.8.2-5) unstable; urgency=low
+
+ [ Guillem Jover ]
+ * Added a missing part to the ARM NPTL support patch, initially lost.
+ - debian/patches/42_arm_tls.patch: Updated.
+
+ -- Guillem Jover <guillem@debian.org> Tue, 16 Jan 2007 11:44:00 +0200
+
+qemu (0.8.2-4) unstable; urgency=medium
+
+ [ Guillem Jover ]
+ * Disable using iasl for now until it's ported to big-endian systems and
+ include a locally built acpi-dsdt.hex file.
+
+ -- Guillem Jover <guillem@debian.org> Sun, 3 Dec 2006 21:10:23 +0200
+
+qemu (0.8.2-3) unstable; urgency=low
+
+ [ Guillem Jover ]
+ * Hopefully really fix powerpc FTBFS.
+
+ -- Guillem Jover <guillem@debian.org> Sun, 5 Nov 2006 17:09:53 +0200
+
+qemu (0.8.2-2) unstable; urgency=low
+
+ [ Guillem Jover ]
+ * Update Tag field to match new debtags vocabulary.
+ * Clean properly. (Closes: #390166)
+ - Remove the acpi generated files and the docs.
+ - Revert the docs regeneration forcing logic.
+ Thanks to Anderson Lizardo <anderson.lizardo@gmail.com>.
+ * On install use DESTDIR instead of specifying all paths. (Closes: #396139)
+ Thanks to Anderson Lizardo <anderson.lizardo@gmail.com>.
+ * Port to GNU/kFreeBSD. (Closes: #327622)
+ - Disable ALSA on non-linux systems.
+ - Add a Build-Depends on libfreebsd-dev on kfreebsd systems.
+ - Add kfreebsd-i386 and kfreebsd-amd64 to the Architecture field.
+ - debian/patches/65_kfreebsd.patch: New file.
+ Thanks Petr Salinger <Petr.Salinger@seznam.cz>.
+ * In qemu-make-debian-root do not explicitely install in aptitude and
+ libsigc++-1.2-5c102, they are pulled now by default. And do not remove
+ aptitude afterwards. (Closes: #392481)
+ Thanks to Ted Percival <ted@midg3t.net>.
+ * Add experimental ncurses ui support. (Closes: #369462)
+ - debian/patches/80_ui_curses.patch: New file.
+ Thanks to Andrzej Zaborowski <balrog@zabor.org>.
+ * Add SO_PEERCRED and SO_SNDTIMEO support, and fix accept syscall when
+ being passed NULL pointers.
+ - debian/patches/21_net_sockopts.patch: Renamed to ...
+ - debian/patches/21_net_soopts.patch: ... here. Modify.
+ Thanks to Pablo Virolainen.
+ * Add a fadvise64 syscall stub.
+ - debian/patches/39_syscall_fadvise64.patch: New file.
+ Thanks to Pablo Virolainen.
+ * Add EABI unmuxed socket syscalls.
+ - debian/patches/55_unmux_socketcall.patch: New file.
+ Thanks to Riku Voipio.
+ * Add TLS sections to the ARM and x86 linker scripts so that qemu user
+ emulators can be linked statically.
+ - debian/patches/66_tls_ld.patch: New file.
+ * Move the documentation of the binary blob removals from the original
+ upstream tarball from README.Debian to debian/copyright.
+ * Reword the emphasis on "FAST!" from the package description.
+ * Fix FTBFS on powerpc by adding the missing fp_status variable to the
+ int32_to_float32 function calls.
+ - debian/patches/67_ppc_ftbfs.patch: New file.
+
+ -- Guillem Jover <guillem@debian.org> Sun, 5 Nov 2006 08:48:27 +0200
+
+qemu (0.8.2-1) unstable; urgency=low
+
+ [ Guillem Jover ]
+ * New upstream release. (Closes: #379461, #385029, #388810)
+ - Add ACPI BIOS emulation support. (Closes: #372533)
+ - Fix mouse invisible wall when using Windows XP. (Closes: #384666)
+ - debian/patches/01_doc_typos.patch: Sync.
+ - debian/patches/03_machines_list_no_error.patch: Likewise.
+ - debian/patches/04_do_not_print_rtc_freq_if_ok.patch: Likewise.
+ - debian/patches/05_non-fatal_if_linux_hd_missing.patch: Likewise.
+ - debian/patches/06_exit_segfault.patch: Likewise.
+ - debian/patches/12_signal_powerpc_support.patch: Likewise.
+ - debian/patches/21_net_sockopt.patch: Likewise.
+ - debian/patches/22_net_tuntap_stall.patch: Likewise.
+ - debian/patches/30_syscall_ipc.patch: Likewise.
+ - debian/patches/31_syscalls.patch: Likewise.
+ - debian/patches/32_syscall_sysctl.patch: Likewise.
+ - debian/patches/33_syscall_ppc_clone.patch: Likewise.
+ - debian/patches/35_syscall_sockaddr.patch: Likewise.
+ - debian/patches/36_syscall_prctl.patch: Likewise.
+ - debian/patches/37_syscall_mount.patch: Likewise.
+ - debian/patches/41_arm_fpa_sigfpe.patch: Likewise.
+ - debian/patches/42_arm_tls.patch: Likewise.
+ - debian/patches/61_safe_64bit_int.patch: Likewise.
+ - debian/patches/63_sparc_build.patch: Likewise.
+ - debian/patches/50_missing_keycodes.patch: Removed, integrated upstream.
+ * Switch to quilt:
+ - debian/control: Add quilt (>= 0.40) to Build-Depends.
+ - debian/patches/series: New file.
+ - debian/patch.mk: Removed.
+ - debian/rules: Include '/usr/share/quilt/quilt.make' instead of
+ 'debian/patch.mk'.
+ * Build the ACPI Source Language files with iasl.
+ * Add a Tag field to the binary package, using data from debtags.
+ * Add 2006 to the debian/copyright years.
+ * Add a Recommends on vde. (Closes: #386780)
+ * Fix spelling error in package description (peripherials -> peripherals).
+ (Closes: #388700)
+ Thanks to Rakesh 'arky' Ambati <rakesh_ambati@yahoo.com>.
+ * Fix ne2000_can_receive return code to 0 when the command is STOP.
+ (Closes: #386209)
+ - debian/patches/52_ne2000_return.patch: New file.
+ Thanks to Samuel Thibault <samuel.thibault@ens-lyon.org>.
+ * Document the binary blob removals from the original upstream tarball in
+ README.Debian. (Closes: #388740)
+
+ -- Guillem Jover <guillem@debian.org> Mon, 25 Sep 2006 04:16:25 +0300
+
+qemu (0.8.1-1) unstable; urgency=low
+
+ [ Guillem Jover ]
+ * New upstream release. (Closes: #366955, #366637)
+ - debian/patches/01_doc_typos.patch: Sync.
+ - debian/patches/04_do_not_print_rtc_freq_if_ok.patch: Likewise.
+ - debian/patches/05_non-fatal_if_linux_hd_missing.patch: Likewise.
+ - debian/patches/12_signal_powerpc_support.patch: Likewise.
+ - debian/patches/21_net_sockopt.patch: Likewise.
+ - debian/patches/22_net_tuntap_stall.patch: Likewise.
+ - debian/patches/30_syscall_ipc.patch: Likewise.
+ - debian/patches/31_syscalls.patch: Likewise.
+ - debian/patches/32_syscall_sysctl.patch: Likewise.
+ - debian/patches/33_syscall_ppc_clone.patch: Likewise.
+ - debian/patches/35_syscall_sockaddr.patch: Likewise.
+ - debian/patches/36_syscall_prctl.patch: Likewise.
+ - debian/patches/37_syscall_mount.patch: Likewise.
+ - debian/patches/41_arm_fpa_sigfpe.patch: Likewise.
+ - debian/patches/42_arm_tls.patch: Likewise.
+ - debian/patches/43_arm_cpustate.patch: Likewise.
+ - debian/patches/50_missing_keycodes.patch: Likewise.
+ - debian/patches/51_serial_small_divider.patch: Likewise.
+ - debian/patches/61_safe_64bit_int.patch: Likewise.
+ - debian/patches/63_sparc_build.patch: Likewise.
+ - debian/patches/40_arm_nwfpe_cpsr.patch: Removed, integrated upstream.
+ * Make the patch system apply the patch on the first run.
+ - debian/patches/64_ppc_asm_constraints.patch: Add DPATCHLEVEL.
+ * Document how to use the images created with qemu-make-debian-root in the
+ man page. Thanks to Jacobo <jacobo221@hotmail.com>. (Closes: #343450)
+ * Add support for the -snapshot option to use the TMPDIR evironment
+ variable. (Closes: #353880)
+ - debian/patches/02_snapshot_use_tmpdir.patch: New file.
+ * Do not exit with an error when using '-M ?'. (Closes: #365209)
+ - debian/patches/03_machines_list_no_error.patch: New file.
+ * Added symlink for system-mipsel emulator man page.
+ * Build and clean the pc-bios directory.
+ * Avoid segfaulting by using _exit(2) instead of exit(3) in qemu user
+ emulators. (Closes: #338289)
+ - debian/patches/06_exit_segfault.patch: New file.
+ * Enable ALSA audio support and add libasound2-dev to the Build-Depends.
+ * Now using Standards-Version 3.7.2 (no changes needed).
+
+ -- Guillem Jover <guillem@debian.org> Sun, 28 May 2006 20:51:10 +0300
+
+qemu (0.8.0-3) unstable; urgency=low
+
+ [ Josh Triplett ]
+ * Fix FTBFS on PowerPC caused by asm constraint problem. (Closes: #361727)
+ - debian/patches/64_ppc_asm_constraints.patch.
+
+ [ Guillem Jover ]
+ * Clamp addrlen from host to target when using AF_UNIX. This fixes
+ socket problems when using EABI.
+ - debian/patches/35_syscall_sockaddr.patch: New file.
+ * Fix floating point comparison on ARM NWFPE, due to glue code missmatch.
+ (Closes: #356287)
+ - debian/patches/40_arm_nwfpe_cpsr.patch: New file.
+ - debian/patches/40_fpu_arm_sigfpe.patch: Rename to ...
+ - debian/patches/41_arm_fpa_sigfpe.patch: ... this. Resync.
+ Thanks to Ulrich Hecht.
+ * Fix POSIX threads creation on ARM hanging when initializing the cpu
+ structure being it cyclic.
+ - debian/patches/43_arm_cpustate.patch: New file.
+ * Add TLS support for ARM. Stolen from Scratchbox.
+ - debian/patches/42_arm_tls.patch: New file.
+ * Fix sysctl endian problem.
+ - debian/patches/32_syscall_sysctl.patch: Update.
+ Thanks to Timo Savola <tsavola@movial.fi>.
+ * Remove now default '--enable-slirp' build option. (Closes: #356284)
+ Thanks to Anderson Lizardo <anderson.lizardo@gmail.com>.
+ * Remove unused sharedir to 'make install'. (Closes: #356418)
+ Thanks to Anderson Lizardo <anderson.lizardo@gmail.com>.
+ * Fix package not cleaning properly. (Closes: #356279)
+ Thanks to Anderson Lizardo <anderson.lizardo@gmail.com> for the initial
+ patch.
+ * Add needed syscalls to make debootstrap work. (Closes: #356291)
+ - debian/patches/36_syscall_prctl.patch: New file.
+ - debian/patches/37_syscall_mount.patch: Likewise.
+ - debian/patches/38_syscall_arm_statfs64.patch: Likewise.
+ Thanks to Anderson Lizardo <anderson.lizardo@gmail.com>.
+ * Remove obsolete Build-Dependency xlibs-dev.
+
+ -- Guillem Jover <guillem@debian.org> Thu, 13 Apr 2006 11:53:00 +0300
+
+qemu (0.8.0-2) unstable; urgency=low
+
+ [ Guillem Jover ]
+ * Switch away from cdbs to plain debhelper.
+ * Upgrade to debhelper compat level 5.
+ * Allow overriding CC compiler variable. (Closes: #345772)
+ * Do not redefine 64 bit types on 64 bit arches.
+ - debian/patches/61_safe_64bit_int.patch: New file.
+ * Allow linux_boot.bin to be built on any arch by switching to nasm,
+ and Build-Depending on it.
+ - debian/patches/62_linux_boot_nasm.patch: New file.
+ * The serial hw driver uses a small divider that gets zeroed when shifting
+ bits to the right. (Closes: #276276, #348098)
+ - debian/patches/51_serial_small_divider.patch: New file.
+ Thanks to Samuel Thibault <samuel.thibault@ens-lyon.org>.
+ * Escaped hyphens in qemu-user manpage, use italics for filenames and
+ parameters and bold for options.
+ * Partial build failure fix for Sparc. (Bugs: #317145, #336970)
+ Thanks to Jurij Smakov <jurij@wooyd.org>.
+
+ -- Guillem Jover <guillem@debian.org> Mon, 20 Feb 2006 09:17:46 +0200
+
+qemu (0.8.0-1) unstable; urgency=low
+
+ [ Guillem Jover ]
+ * New upstream release. (Closes: #344339)
+ - Added support for Virtual FAT. (Closes: #313123)
+ - Emulate repeated keystrokes when holding a key. (Closes: #298864)
+ - debian/patches/01_doc_typos.patch: Sync.
+ - debian/patches/04_do_not_print_rtc_freq_if_ok.patch: Likewise.
+ - debian/patches/05_non-fatal_if_linux_hd_missing.patch: Likewise.
+ - debian/patches/12_signal_powerpc_support.patch: Likewise.
+ - debian/patches/21_net_sockopt.patch: Likewise.
+ - debian/patches/22_net_tuntap_stall.patch: Likewise.
+ - debian/patches/30_syscall_ipc.patch: Likewise.
+ - debian/patches/31_syscalls.patch: Likewise.
+ - debian/patches/32_syscall_sysctl.patch: Likewise.
+ - debian/patches/33_syscall_ppc_clone.patch: Likewise.
+ - debian/patches/40_fpu_arm_sigfpe.patch: Likewise.
+ - debian/patches/50_missing_keycodes.patch: Likewise.
+ * Added mips and mipsel to the lintian overrides for the user emulators
+ being shlib-with-non-pic-code.
+ * Added symlinks for mips, mipsel and system-arm emulator manpages.
+
+ -- Guillem Jover <guillem@debian.org> Fri, 30 Dec 2005 05:44:53 +0200
+
+qemu (0.7.2-2) unstable; urgency=low
+
+ [ Josh Triplett ]
+ * Add support for signal handling on PowerPC. (Closes: #335509)
+ - debian/patches/12_signal_powerpc_support.patch: New file.
+
+ [ Guillem Jover ]
+ * Add Josh Triplett <josh@psas.pdx.edu> to Uploaders and packaging team.
+ * Fix PowerPC build failure by reintroducing the ppc linker script and
+ adding the missing _SDA_BASE_ and _SDA2_BASE_ symbols. (Closes: #336983)
+ * Remove invalid patch making X11 fail at runtime.
+ - debian/patches/20_net_socket.patch: Remove.
+ - debian/patches/32_syscall_sysctl.patch: Sync.
+ Thanks to Daniel Gimpelevich <daniel@gimpelevich.san-francisco.ca.us>.
+ * Avoid the patch system to try until it applies.
+ - debian/patches/05_non-fatal_if_linux_hd_missing.patch: Added patch level.
+ - debian/patches/12_signal_powerpc_support.patch: Likewise.
+
+ -- Guillem Jover <guillem@debian.org> Wed, 21 Dec 2005 22:11:34 +0200
+
+qemu (0.7.2-1) unstable; urgency=low
+
+ [ Guillem Jover ]
+ * New upstream release. (Closes: #321232, #327168)
+ - debian/patches/12_signal_silent.patch: Integrated upstream, remove.
+ - debian/patches/50_ppc_ldscript.patch: Likewise.
+ - debian/patches/33_syscall_truncate64.patch: Likewise.
+ - debian/patches/01_doc_typos.patch: Resync with upstream.
+ - debian/patches/04_do_not_print_rtc_freq_if_ok.patch: Likewise.
+ - debian/patches/05_non-fatal_if_linux_hd_missing.patch: Likewise.
+ - debian/patches/10_signal_jobs.patch: Likewise.
+ - debian/patches/11_signal_sigaction.patch: Likewise.
+ - debian/patches/20_net_socket.patch: Likewise.
+ - debian/patches/21_net_sockopt.patch: Likewise.
+ - debian/patches/22_net_tuntap_stall.patch: Likewise.
+ - debian/patches/30_syscall_ipc.patch: Likewise.
+ - debian/patches/31_syscalls.patch: Likewise.
+ - debian/patches/32_syscall_sysctl.patch: Likewise.
+ - debian/patches/40_fpu_arm_sigfpe.patch: Likewise.
+ * Repackaged upstream source to deal with binaries w/o sources.
+ - pc-bios/video.x: New file removed.
+ * Create a new qemu-user(1) manpage and link all user emulator manpages
+ to it. (Closes: #335163)
+ * Add missing '-' and '=' keycodes for sendkey command.
+ - debian/patches/50_missing_keycodes.patch: New file. (Closes: #334071)
+ Thanks to Robert Millan <rmh@aybabtu.com>.
+ * Add manpage link for qemu-system-mips.
+ * Make sysctl byte-swap the name values.
+ - debian/patches/32_syscall_sysctl.patch: Merge patch. (Closes: #334458)
+ Thanks to Josh Triplett <josh@psas.pdx.edu>.
+ * Change documentation menu section to "Apps/Emulators". (Closes: #335062)
+ Thanks to Frans Pop <aragorn@tiscali.nl>.
+ * On PowerPC, do not zero registers r7-r31 in do_fork and zero register r3.
+ Fixing segfaults on programs using the clone syscall.
+ - debian/patches/33_syscall_ppc_clone.patch: New file. (Closes: #335159)
+ Thanks to Josh Triplett <josh@psas.pdx.edu>
+ and Paul Brook <paul@codesourcery.com>.
+ * Tighten vgabios and bochsbios versioned Depends.
+ * Add video.x to the list of roms to touch to make qemu Makefile happy.
+ * Add lintian overrides for the user emulators being shlib-with-non-pic-code.
+ * Wrap lines in debian/control fields (knowingly breaking policy).
+
+ [ Guilherme de S. Pastore ]
+ * debian/control:
+ - Updated my e-mail address.
+ * debian/copyright:
+ - Dropped André from team members list, not a single contribution ever.
+
+ -- Guillem Jover <guillem@debian.org> Mon, 31 Oct 2005 05:01:45 +0200
+
+qemu (0.7.0-4) unstable; urgency=low
+
+ [ Guillem Jover ]
+ * Rebuild source with locally deborked dpkg-source. (Closes: #321019)
+ * Added the location of the Subversion repo used for the packages and
+ fixed the upstream URL in debian/copyright.
+ * Lower case title header in qemu-make-debian-root man page.
+ * Use dd instead of cat to generate the qemu debian root image.
+ (Closes: #315952)
+
+ -- Guillem Jover <guillem@debian.org> Wed, 3 Aug 2005 05:53:30 +0300
+
+qemu (0.7.0-3) unstable; urgency=low
+
+ [ Guillem Jover ]
+ * Update watch file to version 3, use perlre and new upstream site.
+ * Now using Standards-Version 3.6.2 (no changes needed).
+ * Fix TUN/TAP network interface stalling the connection. (Closes: #290569)
+ Thanks to Vitaly Belostotsky <byly.useless@tochka.ru>.
+ * Link against librt, needed by the new clock_gettime syscall.
+ - debian/patches/31_syscalls.patch: Update. (Closes: #315388)
+ Thanks to Timo Savola <tsavola@movial.fi> for noticing.
+ * Force Build-Dependency on binutils >= 2.16-1 needed by the amd64 and
+ powerpc linker scripts. (Closes: #262655)
+ * Force usage of gcc-3.4. (Closes: #319527)
+ * Add missing Build-Dependency on zlib1g-dev.
+ Thanks to Reinhard Tartler <siretart@tauware.de>.
+ * Include <linux/types.h> in syscall.c to avoid the broken headers in
+ linux-kernel-headers 2.6.12.
+ - debian/patches/34_syscalls_types.patch: New file.
+ Thanks to Octavian Cerna <tavy@ylabs.com>.
+ * Fix powerpc linker script.
+ - debian/patches/50_ppc_ldscript.patch: New file.
+ Thanks to Octavian Cerna <tavy@ylabs.com>.
+
+ -- Guillem Jover <guillem@debian.org> Mon, 1 Aug 2005 02:48:09 +0300
+
+qemu (0.7.0-2) unstable; urgency=low
+
+ [ Guillem Jover ]
+ * Add alpha, sparc, arm and s390 to Architectures (and to the
+ libgpmg1-dev Build-Depends).
+
+ * Forward SIGSTOP and SIGCONT sent to QEMU to the emulated application.
+ - debian/patches/10_signal_jobs.patch: New file.
+ Thanks to Ulrich Hecht.
+ * Return EINVAL on emulated sigaction when given invalid signal
+ parameters SIGKILL and SIGSTOP.
+ - debian/patches/11_signal_sigaction.patch: New fle.
+ Thanks to Valtteri Rahkonen.
+ * Do not print messsages for uncaught signal, thus fixing the case
+ were some applications want to kill their siblings.
+ - debian/patches/12_signal_silent.patch: New file.
+ Thanks to Valtteri Rahkonen
+
+ * Fix Unix sockets by handling correctly AF_UNIX socket address
+ structure length.
+ - debian/patches/20_net_socket.patch: New file.
+ Thanks to Timo Savola.
+ * Implement SO_LINGER, SO_RCVTIMEO, SO_SNDTIMEO, SO_PEERNAME and
+ SO_PEERCRED getsockoptions.
+ - debian/patches/21_net_sockopt.patch: New file.
+ Thanks to Valtteri Rahkonen.
+
+ * Implement SysV IPC message and semaphore syscalls.
+ - debian/patches/30_syscall_ipc.patch: New file.
+ Thanks to Valtteri Rahkonen.
+ * Implement acct, umount2, uselib, swapon, syslog, ftruncate64,
+ mincore, madvise, readahead and clock_gettime syscalls.
+ - debian/patches/31_syscalls.patch: New file.
+ Thanks to Ulrich Hecht.
+ * Implement sysctl CTL_KERN/KERN_VERSION
+ - debian/patches/32_syscall_sysctl.patch: New file.
+ Thanks to Timo Savola.
+ * Implement truncate64 syscall.
+ - debian/patches/33_syscall_truncate64.patch: New file.
+ Thanks to Valtteri Rahkonen.
+
+ * Implement ARM floating point exeption emulation.
+ - debian/patches/40_fpu_arm_sigfpe.patch: New file.
+ Thanks to Ulrich Hecht.
+
+ -- Guillem Jover <guillem@debian.org> Sun, 19 Jun 2005 15:05:37 +0300
+
+qemu (0.7.0-1) experimental; urgency=low
+
+ [ Guillem Jover ]
+ * New upstream release. (Closes: #308459, #308494)
+ * Do not require a disk image when booting a Linux kernel. (Closes: #260935)
+ Thanks to Jonas Smedegaard <dr@jones.dk>.
+
+ [ Guilherme de S. Pastore ]
+ * Rewrote README.Debian for more clarity
+ * Add support for amd64 as a host architecture. (Closes: #262655)
+ - Add build-depend on libgpmg1-dev on amd64.
+ * Fixed qemu-make-debian-root so that it shows the name by which
+ it was called on the usage notice, not "%s". (Closes: #303507)
+ Thanks to Micah Anderson <micah@riseup.net>.
+
+ [ Elrond ]
+ * Clean up more files, so they don't end up in the final .diff.gz
+ * Switch to external proll and openhackware:
+ - Instead of patching qemu's Makefile, trick it by giving it empty
+ files to install and remove them straight after install.
+ - Don't ship the roms in debian/roms any more!
+ - Instead add more symlinks.
+ - Update Depends: apropiately.
+
+ -- Guillem Jover <guillem@debian.org> Fri, 27 May 2005 02:06:20 +0300
+
+qemu (0.6.1+20050407-1) unstable; urgency=low
+
+ [ Guillem Jover ]
+ * New upstream snapshot.
+ - Fix -user-net. (Closes: #295019)
+ - Fix win2k and winxp image booting. (Closes: #285170, #292707)
+ - Fix installation of outdated documentation. (Closes: #286931)
+ - Provide qemu-img instead of qemu-mkcow. (Closes: #290713)
+ - Remove debian/patches/05_fix_openpic_timer_test.patch, integrated
+ upstream.
+ - Remove debian/patches/02_selectable_sdl_keyboard.patch, superseded
+ by new keyboard implementation. (Closes: #284510, #299432)
+ - Remove debian/patches/01_mkcow_section_and_hyphens.patch.
+ - Conditionalize qemu -g option for some architectures. (Closes: #298988)
+ * Added new copyright year to debian/copyright.
+ * Added initial qemu-make-debian-root man page. (Closes: #286932)
+ * Fixed typos in qemu documentation. (Closes: #301933)
+ Thanks to A Costa <agcosta@gis.net>.
+ * Added Elrond <elrond@samba-tng.org> to Uploaders and packaging team.
+ * Use the default target list:
+ - Do not build qemu-fast anymore as it is deprecated upstream anyway.
+ (Closes: #278602, #281510)
+ - New targets armeb and system-x86_64.
+ * Updated ROM images under debian/roms/:
+ - OpenHackWare 0.4.
+ - Proll 18 with qemu specific patches.
+ * Remove uudecoded files from pc-bios/ on clean.
+ * Fix qemu-make-debian-root to behave correctly even if the needed
+ Recommends are not installed.
+
+ [ Guilherme de S. Pastore ]
+ * Create a doc-base entry for the package (Closes: #290669)
+ * debian/control:
+ - Add debootstrap to the 'Recommends: ' line, as needed by
+ qemu-make-debian-root (Closes: #302848)
+ - Moved sharutils from dependency to recommendation, as it is only
+ needed by qemu-make-debian-root
+ * debian/docs:
+ - Do not include README.distrib in the binary package (Closes: #302853)
+
+ [ Elrond ]
+ * Replace "libgpmg1-dev | not+linux-gnu" by "libgpmg1-dev [i386 powerpc]"
+ in Build-Depends. qemu should not need to build-depend on it anyway, the
+ real problem is described in Bug#267174. When it is solved, we can
+ remove our dependency. Until then please remember to add any arch, which
+ we will build on and that has gpm. This change hopefully calms:
+ <http://qa.debian.org/debcheck.php?dist=unstable&package=qemu>
+ * Add versions to the dependencies on bochsbios and vgabios
+ (Closes: #288997):
+ - vgabios: Use the current version from testing/unstable (0.4c+20041014-1),
+ according to Frans Pop <aragorn@tiscali.nl>, this fixed those
+ "blank screen" problems.
+ - bochsbios: Use the current version from unstable (2.1.1+20041109-3), as
+ Guillem Jover fixed the networking in that version.
+
+ -- Guillem Jover <guillem@debian.org> Thu, 7 Apr 2005 01:26:01 +0300
+
+qemu (0.6.1-1) unstable; urgency=low
+
+ [ Guillem Jover ]
+ * New upstream release. (Closes: #281626)
+ - Booting from drive b is not supported anymore. (Closes: #275679)
+ - Fix ne2k network interface that was not working in some situations.
+ (Closes: #281862)
+ - Remove debian/patches/06_build_gcc3.4.patch, fixed upstream.
+ - Remove debian/patches/04_lfs.patch, fixed upstream.
+ - Remove debian/patches/02_fix_powerpc_FTBFS.patch, fixed upstream.
+ - Remove debian/patches/00_escape_manpage_hyphens.patch, not needed.
+ - Sync debian/patches/03_use_external_bios.patch.
+ * Include uuencoded source for proll 18, some build fixes and its binary
+ proll.bin on debian/roms/.
+ * Suggests sudo to be used by the qemu-ifup script.
+ Thanks to Elrond <elrond@samba-tng.org>.
+ * Make sudo in qemu-ifup explain what the password is for. (Closes: #281380)
+ * Add an option to select the method to convert keyevent to keycode
+ in the SDL keyboard handling code. Added support for Right Shift in the
+ generic handler. (Closes: #282658)
+ Thanks to Elrond <elrond@samba-tng.org>.
+ * Do not set RTC frequency to 1024 or warn about this if it has already
+ the correct value. (Closes: #281403)
+ * Enabled sparc-softmmu support.
+
+ -- Guillem Jover <guillem@debian.org> Sat, 27 Nov 2004 23:23:49 +0100
+
+qemu (0.6.0.dfsg.2-1) unstable; urgency=low
+
+ [ Guillem Jover ]
+ * Repackaged upstream source to remove external included files.
+ - pc-bios/ppc-rom.bin: Removed.
+ - pc-bios/OpenHackWare_0.3.tar.bz2: Likewise.
+ - pc-bios/vgabios.bin: Likewise.
+ - pc-bios/vgabios-cirrus.bin: Likewise.
+ - pc-bios/vgabios-cvs-2004-06-17.tgz: Likewise.
+ * Include uuencoded source for OpenHackWare 0.3.1 and its binary
+ ppc-rom.bin on debian/roms/. Add a Build-Depends on sharutils.
+ * Update tundev.c. Pass -tun-dev to qemu without the equal sign.
+ Thanks to Isaac Clerencia <isaac@sindominio.net>.
+ * Fix README.Debian to point to the renamed qemu-make-debian-root.
+ * Add Depends on sharutils needed by qemu-make-debian-root.
+ (Closes: #272130)
+ * Use and depend on vgabios package, which is in sync with bochsbios
+ that checks for rom bios checksums. (Closes: #281202)
+ * Enable LFS globally, thus fixing problems with qemu-mkcow when using
+ an existing large image.
+ (Closes: #279925)
+ * Fix openpic timer write test, catched from a warning about a constant
+ value larger than the type it was casted to.
+ * Fix build failure with gcc 3.4. Patch stolen from Gentoo BTS.
+
+ -- Guillem Jover <guillem@debian.org> Mon, 15 Nov 2004 10:46:54 +0100
+
+qemu (0.6.0.dfsg.1-1) unstable; urgency=high
+
+ [ Guillem Jover ]
+ * Repackaged upstream source to deal with binaries w/o sources.
+ (Closes: #268780)
+ - pc-bios/bios.bin: Removed binary without source. Now using
+ bochsbios package.
+ - pc-bios/vgabios.bin: Rebuilt from vgabios cvs 2004-06-17 snapshot,
+ source included.
+ - pc-bios/vgabios-cirrus.bin: Likewise.
+ - pc-bios/ppc-rom.bin: Rebuilt on voltaire, source included.
+ - pc-bios/linux_boot.bin: Rebuilt from source.
+ * Move make-debian-root.sh to /usr/sbin/qemu-make-debian-root.
+ (Closes: #268705)
+
+ -- Guillem Jover <guillem@debian.org> Mon, 13 Sep 2004 01:28:54 +0200
+
+qemu (0.6.0-2) unstable; urgency=high
+
+ [ Guilherme de S. Pastore ]
+ * Fixed dangling symlinks under /usr/share/man/man1. (Closes: #264764)
+
+ [ Guillem Jover ]
+ * Fix FTBFS on powerpc.
+ - debian/patches/02_fix_powerpc_FTBFS.patch: New file.
+
+ -- Guillem Jover <guillem@debian.org> Wed, 18 Aug 2004 15:50:43 +0200
+
+qemu (0.6.0-1) unstable; urgency=medium
+
+ * New maintainers. (Closes: #258900)
+ * New upstream release. (Closes: #258732)
+ - Installs ppc BIOS ROM file. (Closes: #257492)
+ - Builds with -fno-strict-aliasing. (Closes: #257123)
+
+ [ Guilherme de S. Pastore ]
+ * debian/rules:
+ - Cleaned up.
+ - Ported to use CDBS.
+ * 00_escape_manpage_hyphens.patch:
+ - Correct a little typo and escape hyphens in upstream manpage.
+ * 01_mkcow_section_and_hyphens.patch:
+ - Fix section mismatch and escape hyphens in the qemu-mkcow manpage.
+ * Added simple /etc/qemu-ifup helper script. (Closes: #245281)
+ Thanks to Martin Michlmayr <tbm@cyrius.com>.
+ * Cleaned debian/watch.
+ * UTF-8'ed debian/changelog.
+ * Updated Standards-Version to 3.6.1.1.
+ * Removed outdated and unnecessary debian/qemu-i386.sgml.
+ - Removed build dependency on docbook-to-man.
+ * Removed "x86" part from the description (hey, qemu is not x86-only
+ in any way). Deserves a complete rewrite, shall be done soon.
+
+ [ Guillem Jover ]
+ * Lower-case package short description.
+ * Added missing CPU emulations to the description.
+ * Cleaned and updated debian/copyright.
+ * Removed manually added libx11-6 dependency.
+ * Only Build-Depends on libgpmg1-dev on GNU/Linux systems.
+ * Cosmetic unification to debian/changelog.
+ * debian/rules:
+ - Remove generated files.
+ - Give exec perms to qemu-ifup.
+
+ -- Guillem Jover <guillem@debian.org> Sun, 8 Aug 2004 17:24:08 +0200
+
+qemu (0.5.5-2) unstable; urgency=low
+
+ * Re-enable SDL disabled while I was bugchasing. (Closes: #255014)
+ * Yes, this is really 0.5.5. (Closes: #254655)
+ * Enable slirp networking. (Closes: #253573)
+ * Add Build-Depends on libgpmg1-dev (found by Bastian Blank, probably breaks
+ Hurd but that's a problem for another day).
+
+ -- Paul Russell <prussell@debian.org> Thu, 24 Jun 2004 06:26:42 +0200
+
+qemu (0.5.5-1) unstable; urgency=low
+
+ * New upstream release. (Closes: #237556, #237556)
+ * Applied patch to add options to make_debian_root.sh. (Closes: #238787)
+ * Applied patch for other archs: hmmm... (Closes: #251420)
+ * Do umount -d in make_debian_root.sh. (Closes: #251775)
+
+ -- Paul Russell <prussell@debian.org> Tue, 1 Jun 2004 03:50:05 +0200
+
+qemu (0.5.4-1) unstable; urgency=low
+
+ * New upstream release. (Closes: #246634)
+ * qemu-mkcow included in upstream.
+ * Added tundev program source in doc, to see if people find it useful.
+
+ -- Paul Russell <prussell@debian.org> Mon, 3 May 2004 08:14:49 +0200
+
+qemu (0.5.3-1) unstable; urgency=low
+
+ * New upstream release. (Closes: #237556)
+ * Use aalib-config --static-libs. (Closes: #243325)
+ * Document Control-Shift to release mouse pointer. (Closes: #238074)
+
+ -- Paul Russell <prussell@debian.org> Tue, 13 Apr 2004 02:58:49 +0200
+
+qemu (0.5.2-4) unstable; urgency=low
+
+ * Fix PPC install (Michel Daenzer patch). (Closes: #238431)
+ * Simplify deps (might be wrong, but it's neater). (Closes: #238430)
+
+ -- Paul Russell <prussell@debian.org> Wed, 17 Mar 2004 01:35:47 +0100
+
+qemu (0.5.2-3) unstable; urgency=low
+
+ * Make compile on woody. (Closes: #238163)
+ * Include qemu-doc.html. (Closes: #238076)
+ * Wrote qemu-i386 man page. (Closes: #238077)
+
+ -- Paul Russell <prussell@debian.org> Mon, 15 Mar 2004 23:56:25 +0100
+
+qemu (0.5.2-2) unstable; urgency=low
+
+ * Fix build problem so bios.bin etc. can be found. (Closes: #237553)
+
+ -- Paul Russell <prussell@debian.org> Fri, 12 Mar 2004 05:43:00 +0100
+
+qemu (0.5.2-1) unstable; urgency=low
+
+ * Initial Release. (Closes: #187407)
+
+ -- Paul Russell <prussell@debian.org> Wed, 3 Mar 2004 02:18:54 +0100
diff --git a/debian/control b/debian/control
new file mode 100644
index 00000000..9a5a3fab
--- /dev/null
+++ b/debian/control
@@ -0,0 +1,514 @@
+# autogenerated file, please edit debian/control-in
+Source: qemu
+Section: otherosfs
+Priority: optional
+Maintainer: Debian QEMU Team <pkg-qemu-devel@lists.alioth.debian.org>
+Uploaders: Michael Tokarev <mjt@tls.msk.ru>
+Build-Depends: debhelper-compat (= 13),
+# In comments below we also specify (system-specific) arguments
+# to qemu's configure script, -- optional features which depend
+# on build-dependencies.
+ python3:any,
+ ninja-build, meson (>> 0.61.5~),
+# --enable-docs
+# for python3-sphinx:native see #995622
+ texinfo, python3-sphinx:native, python3-sphinx-rtd-theme,
+# iasl (from acpica-tools) is used only in a single test these days, not for building
+# acpica-tools,
+# libcapstone is in universe in ubuntu
+# --enable-capstone
+ libcapstone-dev (>> 4.0.2~),
+# --enable-linux-aio linux-*
+ libaio-dev [linux-any],
+ libjack-dev [linux-any],
+# --audio-drv-list=pa,alsa,jack,oss,sdl linux-*
+# --audio-drv-list=pa,oss kfreebsd-*
+ libpulse-dev,
+ libasound2-dev [linux-any],
+# for virtfs (now in libc6)
+# --enable-attr
+# --enable-bpf linux-*
+ libbpf-dev [linux-any],
+# --enable-brlapi
+ libbrlapi-dev,
+# --enable-virtfs linux-*
+# needed for virtfs
+# --enable-cap-ng linux-*
+ libcap-ng-dev [linux-any],
+# --enable-curl
+ libcurl4-gnutls-dev,
+# --enable-fdt
+# libfdt #931046
+ libfdt-dev (>> 1.5.0-2~),
+# --enable-fuse
+ libfuse3-dev,
+# --enable-gnutls
+ gnutls-dev,
+# --enable-gtk --enable-vte
+ libgtk-3-dev, libvte-2.91-dev,
+# --enable-libiscsi
+ libiscsi-dev (>> 1.9.0~),
+# --enable-curses
+ libncurses-dev,
+# --enable-virglrenderer linux-*
+ libvirglrenderer-dev [linux-any],
+# libvirglrenderer-dev bug #1019485: libva-dev build-dep is only a temp workaround
+ libva-dev [linux-any],
+# --enable-opengl linux-*
+ libepoxy-dev [linux-any], libdrm-dev [linux-any], libgbm-dev [linux-any],
+# --enable-libnfs
+ libnfs-dev,
+# --enable-numa i386|amd64|ia64|mips|mipsel|powerpc|powerpcspe|x32|ppc64|ppc64el|arm64|sparc|s390x|riscv64
+ libnuma-dev [i386 amd64 ia64 mips mipsel mips64 mips64el powerpc powerpcspe x32 ppc64 ppc64el arm64 sparc s390x riscv64],
+# --enable-smartcard
+ libcacard-dev,
+ libpixman-1-dev,
+# --enable-rbd amd64|arm64|armel|armhf|i386|mips64el|mipsel|ppc64el|s390x|ppc64|sparc64
+ librbd-dev [amd64 arm64 armel armhf i386 mips64el mipsel ppc64el s390x ppc64 sparc64],
+# before buster it was glusterfs-common so keep it for now for bpo
+# --enable-glusterfs linux-any
+ libglusterfs-dev [linux-any] | glusterfs-common [linux-any],
+# --enable-vnc-sasl
+ libsasl2-dev,
+# --enable-sdl
+ libsdl2-dev,
+# --enable-seccomp amd64|arm64|armel|armhf|i386|mips64el|mipsel|ppc64el|s390x|hppa|powerpc|ppc64|riscv64|x32
+ libseccomp-dev [amd64 arm64 armel armhf i386 mips64el mipsel ppc64el s390x hppa powerpc ppc64 riscv64 x32],
+# --enable-slirp
+ libslirp-dev,
+# --enable-spice linux-amd64|linux-i386|linux-arm64|linux-armel|linux-armhf|linux-mips64el|linux-mipsel|ppc64el|sh4|x32
+ libspice-server-dev [linux-amd64 linux-i386 linux-arm64 linux-armel linux-armhf linux-mips64el linux-mipsel ppc64el sh4 x32],
+# --enable-rdma linux-*
+ librdmacm-dev [linux-any], libibverbs-dev [linux-any], libibumad-dev [linux-any],
+# --enable-linux-io-uring linux-*
+ liburing-dev [linux-any],
+# --enable-libusb linux-*
+ libusb-1.0-0-dev [linux-any],
+# --enable-usb-redir linux-*
+ libusbredirparser-dev [linux-any],
+# --enable-libssh
+ libssh-dev,
+# --enable-zstd
+ libzstd-dev,
+# vde is debian-only since ubuntu/vde2 is in universe
+# --enable-vde
+ libvdeplug-dev,
+ libxen-dev [linux-amd64],
+# --enable-nettle
+ nettle-dev,
+## always enabled: --enable-uuid
+ uuid-dev,
+# always needed
+ zlib1g-dev,
+# other optional features we enable
+# --enable-libudev
+# needed for qga?
+ libudev-dev [linux-any],
+# --enable-vnc
+# --enable-vnc-jpeg
+ libjpeg-dev,
+# --enable-png
+ libpng-dev,
+# --enable-libpmem linux-amd64|linux-arm64
+ libpmem-dev [linux-amd64 linux-arm64],
+# --enable-kvm linux-*
+# --enable-vhost-net linux-* # is it really linux-specific?
+##--enable-lzo todo, for (memory) dumps
+##--enable-netmap todo bsd
+##--enable-xen-pci-passthrough todo
+##--with-iconv (libiconv for curses wide char support)
+## auth-pam - for auth for vnc&Co using PAM
+## gio-2.0 - for -display=spice-app
+Build-Depends-Indep:
+# pc-bios/*.dts => *.dtb (PPC firmware)
+ device-tree-compiler,
+ gcc-s390x-linux-gnu,
+# qemu-palcode/palcode-clipper
+ gcc-alpha-linux-gnu,
+# skiboot firmware, openbios
+ gcc-powerpc64-linux-gnu,
+# openbios
+ gcc-sparc64-linux-gnu, fcode-utils, xsltproc,
+# hppa-firmware
+ gcc-hppa-linux-gnu,
+# opensbi
+ gcc-riscv64-linux-gnu,
+# vbootrom/npcm7xx_bootrom
+ gcc-arm-none-eabi,
+Build-Conflicts: oss4-dev
+Standards-Version: 4.6.1
+Homepage: http://www.qemu.org/
+Rules-Requires-Root: no
+Vcs-Browser: https://salsa.debian.org/qemu-team/qemu
+Vcs-Git: https://salsa.debian.org/qemu-team/qemu.git
+
+Package: qemu-system
+Architecture: amd64 arm arm64 armel armhf i386 ia64 kfreebsd-amd64 kfreebsd-i386 mips mipsel mips64 mips64el powerpc powerpcspe ppc64 ppc64el riscv64 s390x sparc sparc64 x32
+Multi-Arch: foreign
+Depends: ${misc:Depends},
+ qemu-system-arm,
+ qemu-system-mips,
+ qemu-system-ppc,
+ qemu-system-sparc,
+ qemu-system-x86,
+ qemu-system-misc
+Description: QEMU full system emulation binaries
+ QEMU is a fast processor emulator: currently the package supports
+ ARM, CRIS, i386, M68k (ColdFire), MicroBlaze, MIPS, PowerPC, SH4,
+ SPARC and x86-64 emulation. By using dynamic translation it achieves
+ reasonable speed while being easy to port on new host CPUs.
+ .
+ This metapackage provides the full system emulation binaries for all supported
+ targets, by depending on all per-architecture system emulation packages which
+ QEMU supports.
+
+Package: qemu-block-extra
+Architecture: amd64 arm arm64 armel armhf hppa i386 ia64 kfreebsd-amd64 kfreebsd-i386 mips mipsel mips64 mips64el powerpc powerpcspe ppc64 ppc64el riscv64 s390x sparc sparc64 x32
+Multi-Arch: no
+Depends: ${misc:Depends}, ${shlibs:Depends},
+ qemu-system-x86 (= ${binary:Version})
+ |qemu-system-arm (= ${binary:Version})
+ |qemu-system-mips (= ${binary:Version})
+ |qemu-system-ppc (= ${binary:Version})
+ |qemu-system-sparc (= ${binary:Version})
+ |qemu-system-misc (= ${binary:Version})
+ |qemu-utils (= ${binary:Version}),
+Enhances: qemu-utils, qemu-system-misc,
+ qemu-system-arm, qemu-system-mips, qemu-system-sparc, qemu-system-x86,
+Description: extra block backend modules for qemu-system and qemu-utils
+ QEMU is a fast processor emulator: currently the package supports
+ ARM, CRIS, i386, M68k (ColdFire), MicroBlaze, MIPS, PowerPC, SH4,
+ SPARC and x86-64 emulation. By using dynamic translation it achieves
+ reasonable speed while being easy to port on new host CPUs.
+ .
+ This package provides extra block device backend modules for qemu-system
+ emulation and qemu-img from qemu-utils package, which are rarely used and
+ has extra dependencies.
+
+Package: qemu-system-data
+Architecture: all
+Multi-Arch: foreign
+Conflicts: sgabios, qemu-skiboot, openbios-sparc, openbios-ppc, qemu-slof,
+Replaces: sgabios, openbios-sparc, openbios-ppc, qemu-slof,
+ qemu-system-common (<< 1:2.12+dfsg-2~),
+ qemu-system-sparc (<< 1:4.2-4~), qemu-system-ppc (<< 1:6.1-4~),
+Breaks:
+ qemu-system-common (<< 1:2.12+dfsg-2~),
+ qemu-system-sparc (<< 1:4.2-4~), qemu-system-ppc (<< 1:6.1-4~),
+Provides: qemu-keymaps, sgabios, qemu-skiboot, openbios-sparc, openbios-ppc, qemu-slof,
+Depends: ${misc:Depends}
+Description: QEMU full system emulation (data files)
+ This package provides architecture-neutral data files
+ (such as keyboard definitions, icons) for system-mode
+ QEMU emulation (qemu-system-*) packages.
+
+Package: qemu-system-common
+Architecture: amd64 arm arm64 armel armhf i386 ia64 kfreebsd-amd64 kfreebsd-i386 mips mipsel mips64 mips64el powerpc powerpcspe ppc64 ppc64el riscv64 s390x sparc sparc64 x32
+Multi-Arch: no
+Replaces: qemu-system-data (<< 1:3.1+dfsg-1~), qemu-utils (<< 1:3.1+dfsg-3~)
+Breaks: qemu-system-data (<< 1:3.1+dfsg-1~), qemu-utils (<< 1:3.1+dfsg-3~), libvirt-daemon (<< 7.2.0-1)
+Depends: ${misc:Depends}, ${shlibs:Depends},
+# to fix wrong acl for newly created device node on ubuntu:
+Description: QEMU full system emulation binaries (common files)
+ QEMU is a fast processor emulator: currently the package supports
+ ARM, CRIS, i386, M68k (ColdFire), MicroBlaze, MIPS, PowerPC, SH4,
+ SPARC and x86-64 emulation. By using dynamic translation it achieves
+ reasonable speed while being easy to port on new host CPUs.
+ .
+ This package provides common files needed for target-specific
+ full system emulation (qemu-system-*) packages.
+
+Package: qemu-system-gui
+Architecture: amd64 arm arm64 armel armhf i386 ia64 kfreebsd-amd64 kfreebsd-i386 mips mipsel mips64 mips64el powerpc powerpcspe ppc64 ppc64el riscv64 s390x sparc sparc64 x32
+#XXX M-A: same does not really work for now due to /usr/lib/qemu/vhost-user-gpu
+#XXX we'll deal with this if some actual need arises,
+#XXX by moving that binary back to q-s-common or packaging it separately
+#Multi-Arch: same
+Depends: ${misc:Depends}, ${shlibs:Depends},
+ qemu-system-x86 (= ${binary:Version})
+ |qemu-system-arm (= ${binary:Version})
+ |qemu-system-mips (= ${binary:Version})
+ |qemu-system-ppc (= ${binary:Version})
+ |qemu-system-sparc (= ${binary:Version})
+ |qemu-system-misc (= ${binary:Version}),
+# libgl1 is dynamically loaded by sdl display code
+ libgl1,
+# we moved vhost-user-gpu files here from qemu-system-common at 6.1-4
+Replaces: qemu-system-common (<< 1:6.1+dfsg-4~)
+Description: QEMU full system emulation binaries (user interface and audio support)
+ This package provides local graphical user interface (currently GTK)
+ and audio backends for full system emulation (qemu-system-*) packages.
+ .
+ The default GTK based qemu-system-gui is generally better and recommended,
+ but a few corner cases still need SDL which is therefore provided as well.
+
+Package: qemu-system-misc
+Architecture: amd64 arm arm64 armel armhf i386 ia64 kfreebsd-amd64 kfreebsd-i386 mips mipsel mips64 mips64el powerpc powerpcspe ppc64 ppc64el riscv64 s390x sparc sparc64 x32
+Multi-Arch: foreign
+Depends: ${shlibs:Depends}, ${misc:Depends}, qemu-system-common (= ${binary:Version}), qemu-system-data (>> ${source:Upstream-Version}~),
+Recommends: qemu-system-gui (= ${binary:Version}), qemu-utils,
+# alpha uses vgabios
+# alpha m68k sh4 uses bootroms
+ seabios, ipxe-qemu,
+ qemu-block-extra (= ${binary:Version}),
+Suggests: samba, vde2,
+Provides: ${sysprovides:misc},
+ qemu-kvm [s390x],
+Description: QEMU full system emulation binaries (miscellaneous)
+ QEMU is a fast processor emulator: currently the package supports
+ ARM, CRIS, M68k (ColdFire), MicroBlaze, and SH4
+ emulation. By using dynamic translation it achieves
+ reasonable speed while being easy to port on new host CPUs.
+ .
+ This package provides the full system emulation binaries to emulate
+ various other hardware which did not made into separate packages.
+ Emulators for the following architectures are provided:
+ ${sysarch:misc}.
+ .
+ In system emulation mode QEMU emulates a full system, including a processor
+ and various peripherals. It enables easier testing and debugging of system
+ code. It can also be used to provide virtual hosting of several virtual
+ machines on a single server.
+
+Package: qemu-system-arm
+Architecture: amd64 arm arm64 armel armhf i386 ia64 kfreebsd-amd64 kfreebsd-i386 mips mipsel mips64 mips64el powerpc powerpcspe ppc64 ppc64el riscv64 s390x sparc sparc64 x32
+Multi-Arch: foreign
+Depends: ${shlibs:Depends}, ${misc:Depends}, qemu-system-common (= ${binary:Version}), qemu-system-data (>> ${source:Upstream-Version}~),
+Recommends: qemu-system-gui (= ${binary:Version}), qemu-utils,
+# aarch64 arm uses bootroms
+ ipxe-qemu,
+ qemu-efi-aarch64, qemu-efi-arm,
+ qemu-block-extra (= ${binary:Version}),
+Suggests: samba, vde2,
+Provides: qemu-kvm [linux-arm64 linux-armhf linux-armel], ${sysprovides:arm}
+Breaks: qemu-kvm [linux-arm64 linux-armhf linux-armel]
+Replaces: qemu-kvm [linux-arm64 linux-armhf linux-armel]
+Description: QEMU full system emulation binaries (arm)
+ QEMU is a fast processor emulator: currently the package supports
+ ARM emulation. By using dynamic translation it achieves
+ reasonable speed while being easy to port on new host CPUs.
+ .
+ This package provides the full system emulation binaries to emulate
+ the following arm hardware: ${sysarch:arm}.
+ .
+ In system emulation mode QEMU emulates a full system, including a processor
+ and various peripherals. It enables easier testing and debugging of system
+ code. It can also be used to provide virtual hosting of several virtual
+ machines on a single server.
+
+Package: qemu-system-mips
+Architecture: amd64 arm arm64 armel armhf i386 ia64 kfreebsd-amd64 kfreebsd-i386 mips mipsel mips64 mips64el powerpc powerpcspe ppc64 ppc64el riscv64 s390x sparc sparc64 x32
+Multi-Arch: foreign
+Depends: ${shlibs:Depends}, ${misc:Depends}, qemu-system-common (= ${binary:Version}), qemu-system-data (>> ${source:Upstream-Version}~),
+Recommends: qemu-system-gui (= ${binary:Version}), qemu-utils,
+# all mips targets uses vgabios and bootroms
+ seabios, ipxe-qemu,
+ qemu-block-extra (= ${binary:Version}),
+Suggests: samba, vde2,
+Provides: ${sysprovides:mips}
+Description: QEMU full system emulation binaries (mips)
+ QEMU is a fast processor emulator: currently the package supports
+ MIPS emulation. By using dynamic translation it achieves
+ reasonable speed while being easy to port on new host CPUs.
+ .
+ This package provides the full system emulation binaries to emulate
+ the following mips hardware: ${sysarch:mips}.
+ .
+ In system emulation mode QEMU emulates a full system, including a processor
+ and various peripherals. It enables easier testing and debugging of system
+ code. It can also be used to provide virtual hosting of several virtual
+ machines on a single server.
+
+Package: qemu-system-ppc
+Architecture: amd64 arm arm64 armel armhf i386 ia64 kfreebsd-amd64 kfreebsd-i386 mips mipsel mips64 mips64el powerpc powerpcspe ppc64 ppc64el riscv64 s390x sparc sparc64 x32
+Multi-Arch: foreign
+Depends: ${shlibs:Depends}, ${misc:Depends}, qemu-system-common (= ${binary:Version}), qemu-system-data (>> ${source:Upstream-Version}~),
+Recommends: qemu-system-gui (= ${binary:Version}), qemu-utils,
+# ppc targets use vgabios-stdvga and bootroms
+ seabios, ipxe-qemu,
+ qemu-block-extra (= ${binary:Version}),
+Suggests: samba, vde2,
+Provides: qemu-kvm [linux-ppc64 linux-ppc64el linux-powerpc], ${sysprovides:ppc}
+Breaks: qemu-kvm [linux-ppc64 linux-ppc64el linux-powerpc]
+Replaces: qemu-kvm [linux-ppc64 linux-ppc64el linux-powerpc]
+Description: QEMU full system emulation binaries (ppc)
+ QEMU is a fast processor emulator: currently the package supports
+ PowerPC emulation. By using dynamic translation it achieves
+ reasonable speed while being easy to port on new host CPUs.
+ .
+ This package provides the full system emulation binaries to emulate
+ the following PowerPC hardware: ${sysarch:ppc}.
+ .
+ In system emulation mode QEMU emulates a full system, including a processor
+ and various peripherals. It enables easier testing and debugging of system
+ code. It can also be used to provide virtual hosting of several virtual
+ machines on a single server.
+
+Package: qemu-system-sparc
+Architecture: amd64 arm arm64 armel armhf i386 ia64 kfreebsd-amd64 kfreebsd-i386 mips mipsel mips64 mips64el powerpc powerpcspe ppc64 ppc64el riscv64 s390x sparc sparc64 x32
+Multi-Arch: foreign
+Depends: ${shlibs:Depends}, ${misc:Depends}, qemu-system-common (= ${binary:Version}), qemu-system-data (>> ${source:Upstream-Version}~),
+Recommends: qemu-system-gui (= ${binary:Version}), qemu-utils,
+# sparc64 uses vgabios-stdvga and bootroms
+ seabios, ipxe-qemu,
+ qemu-block-extra (= ${binary:Version}),
+Suggests: samba, vde2,
+Provides: ${sysprovides:sparc}
+Description: QEMU full system emulation binaries (sparc)
+ QEMU is a fast processor emulator: currently the package supports
+ SPARC emulation. By using dynamic translation it achieves
+ reasonable speed while being easy to port on new host CPUs.
+ .
+ This package provides the full system emulation binaries to emulate
+ the following sparc hardware: ${sysarch:sparc}.
+ .
+ In system emulation mode QEMU emulates a full system, including a processor
+ and various peripherals. It enables easier testing and debugging of system
+ code. It can also be used to provide virtual hosting of several virtual
+ machines on a single server.
+
+Package: qemu-system-x86
+Architecture: amd64 arm arm64 armel armhf i386 ia64 kfreebsd-amd64 kfreebsd-i386 mips mipsel mips64 mips64el powerpc powerpcspe ppc64 ppc64el riscv64 s390x sparc sparc64 x32
+Multi-Arch: foreign
+Depends: ${shlibs:Depends}, ${misc:Depends}, qemu-system-common (= ${binary:Version}), qemu-system-data (>> ${source:Upstream-Version}~),
+ seabios, ipxe-qemu,
+Recommends: qemu-system-gui (= ${binary:Version}), qemu-utils,
+ ovmf,
+ qemu-block-extra (= ${binary:Version}),
+Suggests: samba, vde2,
+Provides: qemu-kvm [linux-amd64 linux-i386], ${sysprovides:x86}
+Breaks: qemu-kvm [linux-amd64 linux-i386]
+Replaces: qemu-kvm [linux-amd64 linux-i386]
+Description: QEMU full system emulation binaries (x86)
+ QEMU is a fast processor emulator: currently the package supports
+ i386 and x86-64 emulation. By using dynamic translation it achieves
+ reasonable speed while being easy to port on new host CPUs.
+ .
+ This package provides the full system emulation binaries to emulate
+ the following x86 hardware: ${sysarch:x86}.
+ .
+ In system emulation mode QEMU emulates a full system, including a processor
+ and various peripherals. It enables easier testing and debugging of system
+ code. It can also be used to provide virtual hosting of several virtual
+ machines on a single server.
+ .
+ On x86 host hardware this package also enables KVM kernel virtual machine
+ usage on systems which supports it.
+
+Package: qemu-system-xen
+Architecture: amd64
+Multi-Arch: no
+# do we really need qemu-system-data? keymaps only?
+Depends: ${shlibs:Depends}, ${misc:Depends}, qemu-system-data (>> ${source:Upstream-Version}~),
+ seabios, ipxe-qemu
+Recommends: qemu-utils,
+ ovmf,
+Description: QEMU full system emulation (Xen helper package)
+ This package provides the i386 system emulation binary to work
+ together with the Xen hypervisor for some types of DomUs.
+ This package is not useful by its own.
+
+Package: qemu-user
+Architecture: amd64 arm arm64 armel armhf i386 mips mipsel mips64 mips64el ppc64 ppc64el riscv64 s390x sparc sparc64 x32
+Multi-Arch: foreign
+Depends: ${shlibs:Depends}, ${misc:Depends}
+Recommends: qemu-user-binfmt
+Description: QEMU user mode emulation binaries
+ QEMU is a fast processor emulator: currently the package supports
+ ARM, CRIS, i386, M68k (ColdFire), MicroBlaze, MIPS, PowerPC, SH4,
+ SPARC and x86-64 emulation. By using dynamic translation it achieves
+ reasonable speed while being easy to port on new host CPUs.
+ .
+ This package provides the user mode emulation binaries. In this mode
+ QEMU can launch Linux processes compiled for one CPU on another CPU.
+ .
+ If qemu-user-binfmt package is also installed, it will register binary
+ format handlers from this qemu-user package with the kernel so it will
+ be possible to run foreign binaries directly. However, this might not
+ be suitable for using inside foreign chroots, in which case it is
+ possible to use qemu-user-static package instead of qemu-user-binmft, --
+ qemu-user-static will register statically linked binfmt handlers instead.
+
+Package: qemu-user-static
+Architecture: amd64 arm arm64 armel armhf i386 mips mipsel mips64 mips64el ppc64 ppc64el riscv64 s390x sparc sparc64 x32
+Built-Using: ${built-using}
+Multi-Arch: foreign
+Depends: ${misc:Depends}
+Recommends: systemd | binfmt-support
+Breaks: binfmt-support (<< 2.1.7~)
+Provides: qemu-user-binfmt
+Conflicts: qemu-user-binfmt
+Description: QEMU user mode emulation binaries (static version)
+ QEMU is a fast processor emulator: currently the package supports
+ ARM, CRIS, i386, M68k (ColdFire), MicroBlaze, MIPS, PowerPC, SH4,
+ SPARC and x86-64 emulation. By using dynamic translation it achieves
+ reasonable speed while being easy to port on new host CPUs.
+ .
+ This package provides the user mode emulation binaries, built
+ statically. In this mode QEMU can launch Linux processes compiled for
+ one CPU on another CPU.
+ .
+ qemu-user-static package will register binary formats which the provided
+ emulators can handle, so that it will be possible to run foreign binaries
+ directly.
+
+Package: qemu-user-binfmt
+Architecture: amd64 arm arm64 armel armhf i386 mips mipsel mips64 mips64el ppc64 ppc64el riscv64 s390x sparc sparc64 x32
+Multi-Arch: foreign
+Depends: ${misc:Depends}, qemu-user (= ${binary:Version}), systemd | binfmt-support
+Breaks: binfmt-support (<< 2.1.7~)
+Conflicts: qemu-user-static
+Description: QEMU user mode binfmt registration for qemu-user
+ QEMU is a fast processor emulator: currently the package supports
+ ARM, CRIS, i386, M68k (ColdFire), MicroBlaze, MIPS, PowerPC, SH4,
+ SPARC and x86-64 emulation. By using dynamic translation it achieves
+ reasonable speed while being easy to port on new host CPUs.
+ .
+ This package provides binfmt support registration for the user mode
+ emulation binaries from qemu-user. This is an empty package, it does
+ not contain any additional files, only registration scripts which run
+ at install and remove times.
+
+Package: qemu-utils
+Architecture: amd64 arm arm64 armel armhf hppa i386 ia64 kfreebsd-amd64 kfreebsd-i386 mips mipsel mips64 mips64el powerpc powerpcspe ppc64 ppc64el riscv64 s390x sparc sparc64 x32
+Multi-Arch: foreign
+Breaks: qemu-system-common (<< 1:3.1+dfsg-3~)
+Depends: ${shlibs:Depends}, ${misc:Depends},
+Recommends:
+ qemu-block-extra (= ${binary:Version}),
+Description: QEMU utilities
+ QEMU is a fast processor emulator: currently the package supports
+ ARM, CRIS, i386, M68k (ColdFire), MicroBlaze, MIPS, PowerPC, SH4,
+ SPARC and x86-64 emulation. By using dynamic translation it achieves
+ reasonable speed while being easy to port on new host CPUs.
+ .
+ This package provides QEMU related utilities:
+ * qemu-img: QEMU disk image utility
+ * qemu-io: QEMU disk exerciser
+ * qemu-nbd: QEMU disk network block device server
+
+Package: qemu-guest-agent
+Architecture: any
+Multi-Arch: foreign
+Depends: ${shlibs:Depends}, ${misc:Depends}
+Pre-Depends: ${misc:Pre-Depends}
+Description: Guest-side qemu-system agent
+ QEMU is a fast processor emulator: currently the package supports
+ ARM, CRIS, i386, M68k (ColdFire), MicroBlaze, MIPS, PowerPC, SH4,
+ SPARC and x86-64 emulation. By using dynamic translation it achieves
+ reasonable speed while being easy to port on new host CPUs.
+ .
+ This package provides a daemon (agent) to run inside qemu-system
+ guests (full system emulation). It communicates with the host using
+ a virtio-serial channel org.qemu.guest_agent.0, and allows one to perform
+ some functions in the guest from the host, including:
+ - querying and setting guest system time
+ - performing guest filesystem sync operation
+ - initiating guest shutdown or suspend to ram
+ - accessing guest files
+ - freezing/thawing guest filesystem operations
+ - others.
+ .
+ Install this package on a system which is running as guest inside
+ qemu virtual machine. It is not used on the host.
+
diff --git a/debian/control-in b/debian/control-in
new file mode 100644
index 00000000..0ca274b5
--- /dev/null
+++ b/debian/control-in
@@ -0,0 +1,565 @@
+Source: qemu
+Section: otherosfs
+Priority: optional
+:debian:Maintainer: Debian QEMU Team <pkg-qemu-devel@lists.alioth.debian.org>
+:ubuntu:Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
+:ubuntu:XSBC-Original-Maintainer: Debian QEMU Team <pkg-qemu-devel@lists.alioth.debian.org>
+Uploaders: Michael Tokarev <mjt@tls.msk.ru>
+Build-Depends: debhelper-compat (= 13),
+# In comments below we also specify (system-specific) arguments
+# to qemu's configure script, -- optional features which depend
+# on build-dependencies.
+ python3:any,
+ ninja-build, meson (>> 0.61.5~),
+# --enable-docs
+# for python3-sphinx:native see #995622
+ texinfo, python3-sphinx:native, python3-sphinx-rtd-theme,
+# iasl (from acpica-tools) is used only in a single test these days, not for building
+# acpica-tools,
+# libcapstone is in universe in ubuntu
+:debian:# --enable-capstone
+:debian: libcapstone-dev (>> 4.0.2~),
+# --enable-linux-aio linux-*
+ libaio-dev [linux-any],
+ libjack-dev [linux-any],
+# --audio-drv-list=pa,alsa,jack,oss,sdl linux-*
+# --audio-drv-list=pa,oss kfreebsd-*
+ libpulse-dev,
+ libasound2-dev [linux-any],
+# for virtfs (now in libc6)
+# --enable-attr
+# --enable-bpf linux-*
+ libbpf-dev [linux-any],
+# --enable-brlapi
+ libbrlapi-dev,
+# --enable-virtfs linux-*
+# needed for virtfs
+# --enable-cap-ng linux-*
+ libcap-ng-dev [linux-any],
+# --enable-curl
+ libcurl4-gnutls-dev,
+# --enable-fdt
+# libfdt #931046
+ libfdt-dev (>> 1.5.0-2~),
+# --enable-fuse
+ libfuse3-dev,
+# --enable-gnutls
+ gnutls-dev,
+# --enable-gtk --enable-vte
+ libgtk-3-dev, libvte-2.91-dev,
+# --enable-libiscsi
+ libiscsi-dev (>> 1.9.0~),
+# --enable-curses
+ libncurses-dev,
+# --enable-virglrenderer linux-*
+ libvirglrenderer-dev [linux-any],
+# libvirglrenderer-dev bug #1019485: libva-dev build-dep is only a temp workaround
+ libva-dev [linux-any],
+# --enable-opengl linux-*
+ libepoxy-dev [linux-any], libdrm-dev [linux-any], libgbm-dev [linux-any],
+:debian:# --enable-libnfs
+:debian: libnfs-dev,
+# --enable-numa i386|amd64|ia64|mips|mipsel|powerpc|powerpcspe|x32|ppc64|ppc64el|arm64|sparc|s390x|riscv64
+ libnuma-dev [i386 amd64 ia64 mips mipsel mips64 mips64el powerpc powerpcspe x32 ppc64 ppc64el arm64 sparc s390x riscv64],
+# --enable-smartcard
+ libcacard-dev,
+ libpixman-1-dev,
+# --enable-rbd amd64|arm64|armel|armhf|i386|mips64el|mipsel|ppc64el|s390x|ppc64|sparc64
+ librbd-dev [amd64 arm64 armel armhf i386 mips64el mipsel ppc64el s390x ppc64 sparc64],
+# before buster it was glusterfs-common so keep it for now for bpo
+# --enable-glusterfs linux-any
+ libglusterfs-dev [linux-any] | glusterfs-common [linux-any],
+# --enable-vnc-sasl
+ libsasl2-dev,
+# --enable-sdl
+ libsdl2-dev,
+# --enable-seccomp amd64|arm64|armel|armhf|i386|mips64el|mipsel|ppc64el|s390x|hppa|powerpc|ppc64|riscv64|x32
+ libseccomp-dev [amd64 arm64 armel armhf i386 mips64el mipsel ppc64el s390x hppa powerpc ppc64 riscv64 x32],
+# --enable-slirp
+ libslirp-dev,
+# --enable-spice linux-amd64|linux-i386|linux-arm64|linux-armel|linux-armhf|linux-mips64el|linux-mipsel|ppc64el|sh4|x32
+ libspice-server-dev [linux-amd64 linux-i386 linux-arm64 linux-armel linux-armhf linux-mips64el linux-mipsel ppc64el sh4 x32],
+# --enable-rdma linux-*
+ librdmacm-dev [linux-any], libibverbs-dev [linux-any], libibumad-dev [linux-any],
+# --enable-linux-io-uring linux-*
+ liburing-dev [linux-any],
+# --enable-libusb linux-*
+ libusb-1.0-0-dev [linux-any],
+# --enable-usb-redir linux-*
+ libusbredirparser-dev [linux-any],
+# --enable-libssh
+ libssh-dev,
+# --enable-zstd
+ libzstd-dev,
+# vde is debian-only since ubuntu/vde2 is in universe
+:debian:# --enable-vde
+:debian: libvdeplug-dev,
+ libxen-dev [linux-amd64],
+# --enable-nettle
+ nettle-dev,
+## always enabled: --enable-uuid
+ uuid-dev,
+# always needed
+ zlib1g-dev,
+# other optional features we enable
+# --enable-libudev
+# needed for qga?
+ libudev-dev [linux-any],
+# --enable-vnc
+# --enable-vnc-jpeg
+ libjpeg-dev,
+# --enable-png
+ libpng-dev,
+# --enable-libpmem linux-amd64|linux-arm64
+ libpmem-dev [linux-amd64 linux-arm64],
+# --enable-kvm linux-*
+# --enable-vhost-net linux-* # is it really linux-specific?
+##--enable-lzo todo, for (memory) dumps
+##--enable-netmap todo bsd
+##--enable-xen-pci-passthrough todo
+##--with-iconv (libiconv for curses wide char support)
+## auth-pam - for auth for vnc&Co using PAM
+## gio-2.0 - for -display=spice-app
+Build-Depends-Indep:
+# pc-bios/*.dts => *.dtb (PPC firmware)
+ device-tree-compiler,
+ gcc-s390x-linux-gnu,
+# qemu-palcode/palcode-clipper
+ gcc-alpha-linux-gnu,
+# skiboot firmware, openbios
+ gcc-powerpc64-linux-gnu,
+# openbios
+ gcc-sparc64-linux-gnu, fcode-utils, xsltproc,
+# hppa-firmware
+ gcc-hppa-linux-gnu,
+# opensbi
+ gcc-riscv64-linux-gnu,
+# vbootrom/npcm7xx_bootrom
+ gcc-arm-none-eabi,
+Build-Conflicts: oss4-dev
+Standards-Version: 4.6.1
+Homepage: http://www.qemu.org/
+Rules-Requires-Root: no
+:debian:Vcs-Browser: https://salsa.debian.org/qemu-team/qemu
+:debian:Vcs-Git: https://salsa.debian.org/qemu-team/qemu.git
+:ubuntu:XS-Debian-Vcs-Browser: https://salsa.debian.org/qemu-team/qemu
+:ubuntu:XS-Debian-Vcs-Git: https://salsa.debian.org/qemu-team/qemu.git
+:ubuntu:Vcs-Browser: https://git.launchpad.net/ubuntu/+source/qemu
+:ubuntu:Vcs-Git: https://git.launchpad.net/ubuntu/+source/qemu
+
+Package: qemu-system
+Architecture: amd64 arm arm64 armel armhf i386 ia64 kfreebsd-amd64 kfreebsd-i386 mips mipsel mips64 mips64el powerpc powerpcspe ppc64 ppc64el riscv64 s390x sparc sparc64 x32
+Multi-Arch: foreign
+Depends: ${misc:Depends},
+ qemu-system-arm,
+ qemu-system-mips,
+ qemu-system-ppc,
+ qemu-system-sparc,
+ qemu-system-x86,
+:ubuntu: qemu-system-s390x,
+ qemu-system-misc
+Description: QEMU full system emulation binaries
+ QEMU is a fast processor emulator: currently the package supports
+ ARM, CRIS, i386, M68k (ColdFire), MicroBlaze, MIPS, PowerPC, SH4,
+ SPARC and x86-64 emulation. By using dynamic translation it achieves
+ reasonable speed while being easy to port on new host CPUs.
+ .
+ This metapackage provides the full system emulation binaries for all supported
+ targets, by depending on all per-architecture system emulation packages which
+ QEMU supports.
+
+Package: qemu-block-extra
+Architecture: amd64 arm arm64 armel armhf hppa i386 ia64 kfreebsd-amd64 kfreebsd-i386 mips mipsel mips64 mips64el powerpc powerpcspe ppc64 ppc64el riscv64 s390x sparc sparc64 x32
+Multi-Arch: no
+Depends: ${misc:Depends}, ${shlibs:Depends},
+ qemu-system-x86 (= ${binary:Version})
+ |qemu-system-arm (= ${binary:Version})
+ |qemu-system-mips (= ${binary:Version})
+ |qemu-system-ppc (= ${binary:Version})
+ |qemu-system-sparc (= ${binary:Version})
+:ubuntu: |qemu-system-s390x (= ${binary:Version})
+ |qemu-system-misc (= ${binary:Version})
+ |qemu-utils (= ${binary:Version}),
+Enhances: qemu-utils, qemu-system-misc,
+ qemu-system-arm, qemu-system-mips, qemu-system-sparc, qemu-system-x86,
+Description: extra block backend modules for qemu-system and qemu-utils
+ QEMU is a fast processor emulator: currently the package supports
+ ARM, CRIS, i386, M68k (ColdFire), MicroBlaze, MIPS, PowerPC, SH4,
+ SPARC and x86-64 emulation. By using dynamic translation it achieves
+ reasonable speed while being easy to port on new host CPUs.
+ .
+ This package provides extra block device backend modules for qemu-system
+ emulation and qemu-img from qemu-utils package, which are rarely used and
+ has extra dependencies.
+
+Package: qemu-system-data
+Architecture: all
+Multi-Arch: foreign
+Conflicts: sgabios, qemu-skiboot, openbios-sparc, openbios-ppc, qemu-slof,
+Replaces: sgabios, openbios-sparc, openbios-ppc, qemu-slof,
+ qemu-system-common (<< 1:2.12+dfsg-2~),
+ qemu-system-sparc (<< 1:4.2-4~), qemu-system-ppc (<< 1:6.1-4~),
+:ubuntu: qemu-system-s390x (<< 1:3.1+dfsg-2ubuntu1~)
+Breaks:
+ qemu-system-common (<< 1:2.12+dfsg-2~),
+ qemu-system-sparc (<< 1:4.2-4~), qemu-system-ppc (<< 1:6.1-4~),
+:ubuntu: qemu-system-s390x (<< 1:3.1+dfsg-2ubuntu1~)
+Provides: qemu-keymaps, sgabios, qemu-skiboot, openbios-sparc, openbios-ppc, qemu-slof,
+Depends: ${misc:Depends}
+Description: QEMU full system emulation (data files)
+ This package provides architecture-neutral data files
+ (such as keyboard definitions, icons) for system-mode
+ QEMU emulation (qemu-system-*) packages.
+
+Package: qemu-system-common
+Architecture: amd64 arm arm64 armel armhf i386 ia64 kfreebsd-amd64 kfreebsd-i386 mips mipsel mips64 mips64el powerpc powerpcspe ppc64 ppc64el riscv64 s390x sparc sparc64 x32
+Multi-Arch: no
+Replaces: qemu-system-data (<< 1:3.1+dfsg-1~), qemu-utils (<< 1:3.1+dfsg-3~)
+Breaks: qemu-system-data (<< 1:3.1+dfsg-1~), qemu-utils (<< 1:3.1+dfsg-3~), libvirt-daemon (<< 7.2.0-1)
+Depends: ${misc:Depends}, ${shlibs:Depends},
+# to fix wrong acl for newly created device node on ubuntu:
+:ubuntu: acl
+Description: QEMU full system emulation binaries (common files)
+ QEMU is a fast processor emulator: currently the package supports
+ ARM, CRIS, i386, M68k (ColdFire), MicroBlaze, MIPS, PowerPC, SH4,
+ SPARC and x86-64 emulation. By using dynamic translation it achieves
+ reasonable speed while being easy to port on new host CPUs.
+ .
+ This package provides common files needed for target-specific
+ full system emulation (qemu-system-*) packages.
+
+Package: qemu-system-gui
+Architecture: amd64 arm arm64 armel armhf i386 ia64 kfreebsd-amd64 kfreebsd-i386 mips mipsel mips64 mips64el powerpc powerpcspe ppc64 ppc64el riscv64 s390x sparc sparc64 x32
+#XXX M-A: same does not really work for now due to /usr/lib/qemu/vhost-user-gpu
+#XXX we'll deal with this if some actual need arises,
+#XXX by moving that binary back to q-s-common or packaging it separately
+#Multi-Arch: same
+Depends: ${misc:Depends}, ${shlibs:Depends},
+ qemu-system-x86 (= ${binary:Version})
+ |qemu-system-arm (= ${binary:Version})
+ |qemu-system-mips (= ${binary:Version})
+ |qemu-system-ppc (= ${binary:Version})
+ |qemu-system-sparc (= ${binary:Version})
+:ubuntu: |qemu-system-s390x (= ${binary:Version})
+ |qemu-system-misc (= ${binary:Version}),
+# libgl1 is dynamically loaded by sdl display code
+ libgl1,
+# we moved vhost-user-gpu files here from qemu-system-common at 6.1-4
+Replaces: qemu-system-common (<< 1:6.1+dfsg-4~)
+Description: QEMU full system emulation binaries (user interface and audio support)
+ This package provides local graphical user interface (currently GTK)
+ and audio backends for full system emulation (qemu-system-*) packages.
+ .
+ The default GTK based qemu-system-gui is generally better and recommended,
+ but a few corner cases still need SDL which is therefore provided as well.
+
+Package: qemu-system-misc
+Architecture: amd64 arm arm64 armel armhf i386 ia64 kfreebsd-amd64 kfreebsd-i386 mips mipsel mips64 mips64el powerpc powerpcspe ppc64 ppc64el riscv64 s390x sparc sparc64 x32
+Multi-Arch: foreign
+Depends: ${shlibs:Depends}, ${misc:Depends}, qemu-system-common (= ${binary:Version}), qemu-system-data (>> ${source:Upstream-Version}~),
+Recommends: qemu-system-gui (= ${binary:Version}), qemu-utils,
+# alpha uses vgabios
+# alpha m68k sh4 uses bootroms
+ seabios, ipxe-qemu,
+ qemu-block-extra (= ${binary:Version}),
+Suggests: samba, vde2,
+Provides: ${sysprovides:misc},
+:debian: qemu-kvm [s390x],
+Description: QEMU full system emulation binaries (miscellaneous)
+ QEMU is a fast processor emulator: currently the package supports
+ ARM, CRIS, M68k (ColdFire), MicroBlaze, and SH4
+ emulation. By using dynamic translation it achieves
+ reasonable speed while being easy to port on new host CPUs.
+ .
+ This package provides the full system emulation binaries to emulate
+ various other hardware which did not made into separate packages.
+ Emulators for the following architectures are provided:
+ ${sysarch:misc}.
+ .
+ In system emulation mode QEMU emulates a full system, including a processor
+ and various peripherals. It enables easier testing and debugging of system
+ code. It can also be used to provide virtual hosting of several virtual
+ machines on a single server.
+
+Package: qemu-system-arm
+Architecture: amd64 arm arm64 armel armhf i386 ia64 kfreebsd-amd64 kfreebsd-i386 mips mipsel mips64 mips64el powerpc powerpcspe ppc64 ppc64el riscv64 s390x sparc sparc64 x32
+Multi-Arch: foreign
+Depends: ${shlibs:Depends}, ${misc:Depends}, qemu-system-common (= ${binary:Version}), qemu-system-data (>> ${source:Upstream-Version}~),
+Recommends: qemu-system-gui (= ${binary:Version}), qemu-utils,
+# aarch64 arm uses bootroms
+ ipxe-qemu,
+ qemu-efi-aarch64, qemu-efi-arm,
+ qemu-block-extra (= ${binary:Version}),
+Suggests: samba, vde2,
+Provides: qemu-kvm [linux-arm64 linux-armhf linux-armel], ${sysprovides:arm}
+Breaks: qemu-kvm [linux-arm64 linux-armhf linux-armel]
+Replaces: qemu-kvm [linux-arm64 linux-armhf linux-armel]
+Description: QEMU full system emulation binaries (arm)
+ QEMU is a fast processor emulator: currently the package supports
+ ARM emulation. By using dynamic translation it achieves
+ reasonable speed while being easy to port on new host CPUs.
+ .
+ This package provides the full system emulation binaries to emulate
+ the following arm hardware: ${sysarch:arm}.
+ .
+ In system emulation mode QEMU emulates a full system, including a processor
+ and various peripherals. It enables easier testing and debugging of system
+ code. It can also be used to provide virtual hosting of several virtual
+ machines on a single server.
+
+Package: qemu-system-mips
+Architecture: amd64 arm arm64 armel armhf i386 ia64 kfreebsd-amd64 kfreebsd-i386 mips mipsel mips64 mips64el powerpc powerpcspe ppc64 ppc64el riscv64 s390x sparc sparc64 x32
+Multi-Arch: foreign
+Depends: ${shlibs:Depends}, ${misc:Depends}, qemu-system-common (= ${binary:Version}), qemu-system-data (>> ${source:Upstream-Version}~),
+Recommends: qemu-system-gui (= ${binary:Version}), qemu-utils,
+# all mips targets uses vgabios and bootroms
+ seabios, ipxe-qemu,
+ qemu-block-extra (= ${binary:Version}),
+Suggests: samba, vde2,
+Provides: ${sysprovides:mips}
+Description: QEMU full system emulation binaries (mips)
+ QEMU is a fast processor emulator: currently the package supports
+ MIPS emulation. By using dynamic translation it achieves
+ reasonable speed while being easy to port on new host CPUs.
+ .
+ This package provides the full system emulation binaries to emulate
+ the following mips hardware: ${sysarch:mips}.
+ .
+ In system emulation mode QEMU emulates a full system, including a processor
+ and various peripherals. It enables easier testing and debugging of system
+ code. It can also be used to provide virtual hosting of several virtual
+ machines on a single server.
+
+Package: qemu-system-ppc
+Architecture: amd64 arm arm64 armel armhf i386 ia64 kfreebsd-amd64 kfreebsd-i386 mips mipsel mips64 mips64el powerpc powerpcspe ppc64 ppc64el riscv64 s390x sparc sparc64 x32
+Multi-Arch: foreign
+Depends: ${shlibs:Depends}, ${misc:Depends}, qemu-system-common (= ${binary:Version}), qemu-system-data (>> ${source:Upstream-Version}~),
+Recommends: qemu-system-gui (= ${binary:Version}), qemu-utils,
+# ppc targets use vgabios-stdvga and bootroms
+ seabios, ipxe-qemu,
+ qemu-block-extra (= ${binary:Version}),
+Suggests: samba, vde2,
+Provides: qemu-kvm [linux-ppc64 linux-ppc64el linux-powerpc], ${sysprovides:ppc}
+Breaks: qemu-kvm [linux-ppc64 linux-ppc64el linux-powerpc]
+Replaces: qemu-kvm [linux-ppc64 linux-ppc64el linux-powerpc]
+Description: QEMU full system emulation binaries (ppc)
+ QEMU is a fast processor emulator: currently the package supports
+ PowerPC emulation. By using dynamic translation it achieves
+ reasonable speed while being easy to port on new host CPUs.
+ .
+ This package provides the full system emulation binaries to emulate
+ the following PowerPC hardware: ${sysarch:ppc}.
+ .
+ In system emulation mode QEMU emulates a full system, including a processor
+ and various peripherals. It enables easier testing and debugging of system
+ code. It can also be used to provide virtual hosting of several virtual
+ machines on a single server.
+
+Package: qemu-system-sparc
+Architecture: amd64 arm arm64 armel armhf i386 ia64 kfreebsd-amd64 kfreebsd-i386 mips mipsel mips64 mips64el powerpc powerpcspe ppc64 ppc64el riscv64 s390x sparc sparc64 x32
+Multi-Arch: foreign
+Depends: ${shlibs:Depends}, ${misc:Depends}, qemu-system-common (= ${binary:Version}), qemu-system-data (>> ${source:Upstream-Version}~),
+Recommends: qemu-system-gui (= ${binary:Version}), qemu-utils,
+# sparc64 uses vgabios-stdvga and bootroms
+ seabios, ipxe-qemu,
+ qemu-block-extra (= ${binary:Version}),
+Suggests: samba, vde2,
+Provides: ${sysprovides:sparc}
+Description: QEMU full system emulation binaries (sparc)
+ QEMU is a fast processor emulator: currently the package supports
+ SPARC emulation. By using dynamic translation it achieves
+ reasonable speed while being easy to port on new host CPUs.
+ .
+ This package provides the full system emulation binaries to emulate
+ the following sparc hardware: ${sysarch:sparc}.
+ .
+ In system emulation mode QEMU emulates a full system, including a processor
+ and various peripherals. It enables easier testing and debugging of system
+ code. It can also be used to provide virtual hosting of several virtual
+ machines on a single server.
+
+Package: qemu-system-x86
+Architecture: amd64 arm arm64 armel armhf i386 ia64 kfreebsd-amd64 kfreebsd-i386 mips mipsel mips64 mips64el powerpc powerpcspe ppc64 ppc64el riscv64 s390x sparc sparc64 x32
+Multi-Arch: foreign
+Depends: ${shlibs:Depends}, ${misc:Depends}, qemu-system-common (= ${binary:Version}), qemu-system-data (>> ${source:Upstream-Version}~),
+ seabios, ipxe-qemu,
+Recommends: qemu-system-gui (= ${binary:Version}), qemu-utils,
+ ovmf,
+ qemu-block-extra (= ${binary:Version}),
+:ubuntu: cpu-checker,
+Suggests: samba, vde2,
+Provides: qemu-kvm [linux-amd64 linux-i386], ${sysprovides:x86}
+Breaks: qemu-kvm [linux-amd64 linux-i386]
+Replaces: qemu-kvm [linux-amd64 linux-i386]
+Description: QEMU full system emulation binaries (x86)
+ QEMU is a fast processor emulator: currently the package supports
+ i386 and x86-64 emulation. By using dynamic translation it achieves
+ reasonable speed while being easy to port on new host CPUs.
+ .
+ This package provides the full system emulation binaries to emulate
+ the following x86 hardware: ${sysarch:x86}.
+ .
+ In system emulation mode QEMU emulates a full system, including a processor
+ and various peripherals. It enables easier testing and debugging of system
+ code. It can also be used to provide virtual hosting of several virtual
+ machines on a single server.
+ .
+ On x86 host hardware this package also enables KVM kernel virtual machine
+ usage on systems which supports it.
+
+Package: qemu-system-xen
+Architecture: amd64
+Multi-Arch: no
+# do we really need qemu-system-data? keymaps only?
+Depends: ${shlibs:Depends}, ${misc:Depends}, qemu-system-data (>> ${source:Upstream-Version}~),
+ seabios, ipxe-qemu
+Recommends: qemu-utils,
+ ovmf,
+:ubuntu:# For the transition from the former qemu-system-x86-xen name
+:ubuntu:Breaks: qemu-system-x86-xen (<<1:7.0+dfsg-7ubuntu1)
+:ubuntu:Replaces: qemu-system-x86-xen (<<1:7.0+dfsg-7ubuntu1)
+:ubuntu:Provides: qemu-system-x86-xen
+Description: QEMU full system emulation (Xen helper package)
+ This package provides the i386 system emulation binary to work
+ together with the Xen hypervisor for some types of DomUs.
+ This package is not useful by its own.
+
+Package: qemu-user
+Architecture: amd64 arm arm64 armel armhf i386 mips mipsel mips64 mips64el ppc64 ppc64el riscv64 s390x sparc sparc64 x32
+Multi-Arch: foreign
+Depends: ${shlibs:Depends}, ${misc:Depends}
+Recommends: qemu-user-binfmt
+Description: QEMU user mode emulation binaries
+ QEMU is a fast processor emulator: currently the package supports
+ ARM, CRIS, i386, M68k (ColdFire), MicroBlaze, MIPS, PowerPC, SH4,
+ SPARC and x86-64 emulation. By using dynamic translation it achieves
+ reasonable speed while being easy to port on new host CPUs.
+ .
+ This package provides the user mode emulation binaries. In this mode
+ QEMU can launch Linux processes compiled for one CPU on another CPU.
+ .
+ If qemu-user-binfmt package is also installed, it will register binary
+ format handlers from this qemu-user package with the kernel so it will
+ be possible to run foreign binaries directly. However, this might not
+ be suitable for using inside foreign chroots, in which case it is
+ possible to use qemu-user-static package instead of qemu-user-binmft, --
+ qemu-user-static will register statically linked binfmt handlers instead.
+
+Package: qemu-user-static
+Architecture: amd64 arm arm64 armel armhf i386 mips mipsel mips64 mips64el ppc64 ppc64el riscv64 s390x sparc sparc64 x32
+Built-Using: ${built-using}
+Multi-Arch: foreign
+Depends: ${misc:Depends}
+Recommends: systemd | binfmt-support
+Breaks: binfmt-support (<< 2.1.7~)
+Provides: qemu-user-binfmt
+Conflicts: qemu-user-binfmt
+Description: QEMU user mode emulation binaries (static version)
+ QEMU is a fast processor emulator: currently the package supports
+ ARM, CRIS, i386, M68k (ColdFire), MicroBlaze, MIPS, PowerPC, SH4,
+ SPARC and x86-64 emulation. By using dynamic translation it achieves
+ reasonable speed while being easy to port on new host CPUs.
+ .
+ This package provides the user mode emulation binaries, built
+ statically. In this mode QEMU can launch Linux processes compiled for
+ one CPU on another CPU.
+ .
+ qemu-user-static package will register binary formats which the provided
+ emulators can handle, so that it will be possible to run foreign binaries
+ directly.
+
+Package: qemu-user-binfmt
+Architecture: amd64 arm arm64 armel armhf i386 mips mipsel mips64 mips64el ppc64 ppc64el riscv64 s390x sparc sparc64 x32
+Multi-Arch: foreign
+Depends: ${misc:Depends}, qemu-user (= ${binary:Version}), systemd | binfmt-support
+Breaks: binfmt-support (<< 2.1.7~)
+Conflicts: qemu-user-static
+Description: QEMU user mode binfmt registration for qemu-user
+ QEMU is a fast processor emulator: currently the package supports
+ ARM, CRIS, i386, M68k (ColdFire), MicroBlaze, MIPS, PowerPC, SH4,
+ SPARC and x86-64 emulation. By using dynamic translation it achieves
+ reasonable speed while being easy to port on new host CPUs.
+ .
+ This package provides binfmt support registration for the user mode
+ emulation binaries from qemu-user. This is an empty package, it does
+ not contain any additional files, only registration scripts which run
+ at install and remove times.
+
+Package: qemu-utils
+Architecture: amd64 arm arm64 armel armhf hppa i386 ia64 kfreebsd-amd64 kfreebsd-i386 mips mipsel mips64 mips64el powerpc powerpcspe ppc64 ppc64el riscv64 s390x sparc sparc64 x32
+Multi-Arch: foreign
+Breaks: qemu-system-common (<< 1:3.1+dfsg-3~)
+Depends: ${shlibs:Depends}, ${misc:Depends},
+Recommends:
+ qemu-block-extra (= ${binary:Version}),
+Description: QEMU utilities
+ QEMU is a fast processor emulator: currently the package supports
+ ARM, CRIS, i386, M68k (ColdFire), MicroBlaze, MIPS, PowerPC, SH4,
+ SPARC and x86-64 emulation. By using dynamic translation it achieves
+ reasonable speed while being easy to port on new host CPUs.
+ .
+ This package provides QEMU related utilities:
+ * qemu-img: QEMU disk image utility
+ * qemu-io: QEMU disk exerciser
+ * qemu-nbd: QEMU disk network block device server
+
+Package: qemu-guest-agent
+Architecture: any
+Multi-Arch: foreign
+Depends: ${shlibs:Depends}, ${misc:Depends}
+Pre-Depends: ${misc:Pre-Depends}
+Description: Guest-side qemu-system agent
+ QEMU is a fast processor emulator: currently the package supports
+ ARM, CRIS, i386, M68k (ColdFire), MicroBlaze, MIPS, PowerPC, SH4,
+ SPARC and x86-64 emulation. By using dynamic translation it achieves
+ reasonable speed while being easy to port on new host CPUs.
+ .
+ This package provides a daemon (agent) to run inside qemu-system
+ guests (full system emulation). It communicates with the host using
+ a virtio-serial channel org.qemu.guest_agent.0, and allows one to perform
+ some functions in the guest from the host, including:
+ - querying and setting guest system time
+ - performing guest filesystem sync operation
+ - initiating guest shutdown or suspend to ram
+ - accessing guest files
+ - freezing/thawing guest filesystem operations
+ - others.
+ .
+ Install this package on a system which is running as guest inside
+ qemu virtual machine. It is not used on the host.
+:ubuntu:
+:ubuntu:Package: qemu-system-s390x
+:ubuntu:Architecture: amd64 arm arm64 armel armhf hppa i386 ia64 kfreebsd-amd64 kfreebsd-i386 mips mipsel powerpc powerpcspe ppc64 ppc64el riscv64 s390x sparc sparc64
+:ubuntu:Multi-Arch: foreign
+:ubuntu:Depends: ${shlibs:Depends}, ${misc:Depends}, qemu-system-common (= ${binary:Version}), qemu-system-data (>> ${source:Upstream-Version}~),
+:ubuntu:Recommends: qemu-utils,
+:ubuntu: qemu-block-extra (= ${binary:Version}),
+:ubuntu:Provides: qemu-kvm [linux-s390x], ${sysprovides:s390x}
+:ubuntu:Breaks: qemu-kvm [linux-s390x], qemu-system-misc (<< 1:2.5+dfsg-5ubuntu8~)
+:ubuntu:Replaces: qemu-kvm [linux-s390x], qemu-system-misc (<< 1:2.5+dfsg-5ubuntu8~)
+:ubuntu:Description: QEMU full system emulation binaries (s390x)
+:ubuntu: QEMU is a fast processor emulator: currently the package supports
+:ubuntu: s390x emulation. By using dynamic translation it achieves reasonable
+:ubuntu: speed while being easy to port on new host CPUs.
+:ubuntu: .
+:ubuntu: This package provides the full system emulation binaries to emulate
+:ubuntu: the following s390x hardware: ${sysarch:s390x}.
+:ubuntu: .
+:ubuntu: In system emulation mode QEMU emulates a full system, including a processor
+:ubuntu: and various peripherals. It enables easier testing and debugging of system
+:ubuntu: code. It can also be used to provide virtual hosting of several virtual
+:ubuntu: machines on a single server.
+
+:ubuntu:# xen support generally is disabled on ubuntu, for a while we used
+:ubuntu:# an extra build with xen enabled. In the meantime Debian followed that
+:ubuntu:# approach but with a different name, so add a transitional until
+:ubuntu:# after 24.04
+:ubuntu:Package: qemu-system-x86-xen
+:ubuntu:Architecture: amd64
+:ubuntu:Multi-Arch: foreign
+:ubuntu:Section: oldlibs
+:ubuntu:Depends: qemu-system-xen (>= 1:7.0+dfsg-7ubuntu1), ${misc:Depends}
+:ubuntu:Description: QEMU full system emulation binaries (x86)
+:ubuntu: The former qemu-system-x86-xen binaries are now in qemu-system-xen.
+:ubuntu: .
+:ubuntu: This is a transitional package. You can safely remove it.
diff --git a/debian/copyright b/debian/copyright
new file mode 100644
index 00000000..c0567dec
--- /dev/null
+++ b/debian/copyright
@@ -0,0 +1,532 @@
+Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
+Files-Excluded:
+ dtc
+ meson
+ roms/QemuMacDrivers
+ roms/edk2
+ roms/ipxe
+ roms/seabios
+ roms/u-boot
+ slirp
+#
+ roms/SLOF/board-js2x/rtas/i2c_bmc.oco
+ roms/SLOF/board-js2x/rtas/ipmi_oem.oco
+ roms/SLOF/clients/takeover/takeover.oco
+ roms/SLOF/lib/libipmi/libipmi.oco
+#
+ pc-bios/QEMU,*.bin
+ pc-bios/bamboo.dtb pc-bios/canyonlands.dtb
+ pc-bios/bios.bin
+ pc-bios/bios-256k.bin
+ pc-bios/bios-microvm.bin
+ pc-bios/edk2-*.fd.bz2
+ pc-bios/efi-*.rom
+ pc-bios/pxe-*.rom
+ pc-bios/hppa-firmware.img
+ pc-bios/kvmvapic.bin
+ pc-bios/linuxboot.bin
+ pc-bios/linuxboot_dma.bin
+ pc-bios/multiboot.bin
+ pc-bios/multiboot_dma.bin
+ pc-bios/openbios-ppc
+ pc-bios/openbios-sparc32
+ pc-bios/openbios-sparc64
+ pc-bios/opensbi-*.bin
+ pc-bios/palcode-clipper
+ pc-bios/pvh.bin
+ pc-bios/qboot.rom
+ pc-bios/qemu_vga.ndrv
+ pc-bios/s390-ccw.img
+ pc-bios/s390-netboot.img
+ pc-bios/sgabios.bin
+ pc-bios/skiboot.lid
+ pc-bios/slof.bin
+ pc-bios/u-boot-sam460-20100605.bin
+ pc-bios/u-boot.e500
+ pc-bios/vgabios.bin
+ pc-bios/vgabios-*.bin
+ pc-bios/vof.bin
+
+Files: *
+Copyright:
+ Copyright (C) 1982, 1986, 1988-1994 The Regents of the University of California
+ Copyright (C) 1986-2007 Free Software Foundation Inc.
+ Copyright (C) 1988-1992 Richard Outerbridge
+ Copyright (C) 1991-1992, 1996 Linus Torvalds
+ Copyright (C) 1992 Graven Imagery
+ Copyright (C) 1995 Danny Gasparovski
+ Copyright (C) 1996-1999 Eduardo Horvath
+ Copyright (C) 1996 Paul Mackerras
+ Copyright (C) 1997-1999, 2001, 2006-2009 Red Hat Inc.
+ Copyright (C) 1998-1999 Philip Blundell
+ Copyright (C) 1998-2001, 2003, 2006 Thomas Sailer <t.sailer@alumni.ethz.ch>
+ Copyright (C) 1998, 2003-2008 Fabrice Bellard
+ Copyright (C) 1998-2004 Samuel Rydh <samuel@ibrium.se>
+ Copyright (C) 1998 Kenneth Albanowski <kjahds@kjahds.com>
+ Copyright (C) 1998 The Silver Hammer Group Ltd.
+ Copyright (C) 1999-2000, 2002-2003 Maxim Krasnyansky <maxk@qualcomm.com>
+ Copyright (C) 1999-2000 Tatsuyuki Satoh
+ Copyright (C) 1999-2006, 2008 Intel Corporation
+ Copyright (C) 1999 AT&T Laboratories Cambridge
+ Copyright (C) 2000-2001 Qualcomm Incorporated
+ Copyright (C) 2000-2002, 2004-2009 Axis Communications AB.
+ Copyright (C) 2000-2003, 2005 Martin Schwidefsky
+ Copyright (C) 2000-2003 David McCullough <davidm@snapgear.com> <davidm@lineo.com>
+ Copyright (C) 2000-2005 All Rights Reserved.
+ Copyright (C) 2000-2005 DENX Software Engineering <wd@denx.de.>
+ Copyright (C) 2000-2005 Silicon Graphics Inc.
+ Copyright (C) 2000-2005 Wolfgang Denk
+ Copyright (C) 2000-2007 Tibor "TS" Schütz
+ Copyright (C) 2001 OKTET Ltd.
+ Copyright (C) 2001 Xilinx Inc.
+ Copyright (C) 2002-2005 Vassili Karpov
+ Copyright (C) 2002-2006 Marcel Holtmann <marcel@holtmann.org>
+ Copyright (C) 2002 Greg Ungerer <gerg@snapgear.com>
+ Copyright (C) 2002 Paul Dale <pauli@snapgear.com>
+ Copyright (C) 2003-2004 James Yonan
+ Copyright (C) 2003-2007 Jocelyn Mayer
+ Copyright (C) 2003 Damion K. Wilson
+ Copyright (C) 2003 Thomas M. Ogrisegg <tom@fnord.at>
+ Copyright (C) 2004-2005 Johannes E. Schindelin
+ Copyright (C) 2004, 2007 Magnus Damm <damm@opensource.se>
+ Copyright (C) 2004 Antony T Curtis
+ Copyright (C) 2004 Gianni Tedesco
+ Copyright (C) 2004 Johannes Schindelin
+ Copyright (C) 2004 Makoto Suzuki
+ Copyright (C) 2005, 2007 Alex Beregszaszi
+ Copyright (C) 2005-2007 Anthony Liguori <aliguori@us.ibm.com> <anthony@codemonkey.ws>
+ Copyright (C) 2005-2008 Andrzej Zaborowski <balrog@zabor.org> <andrew@openedhand.com>
+ Copyright (C) 2005-2009 Paul Brook <paul@codesourcery.com>
+ Copyright (C) 2005 Anthony Liguori <aliguori@us.ibm.com>
+ Copyright (C) 2005 Filip Navara
+ Copyright (C) 2005 International Business Machines Corp.
+ Copyright (C) 2005 LLC. Written
+ Copyright (C) 2005 Mike Kronenberg
+ Copyright (C) 2005 Samuel Tardieu
+ Copyright (C) 2006-2007, 2009 Aurelien Jarno <aurelien@aurel32.net>
+ Copyright (C) 2006-2007, 2009 Stefan Weil
+ Copyright (C) 2006-2007 Thiemo Seufer
+ Copyright (C) 2006-2007 Thorsten Zitterell <info@bitmux.org>
+ Copyright (C) 2006-2008 Openedhand Ltd.
+ Copyright (C) 2006-2008 Qumranet Technologies
+ Copyright (C) 2006 Frederick Reeve
+ Copyright (C) 2006 Igor Kovalenko
+ Copyright (C) 2006 InnoTek Systemberatung GmbH
+ Copyright (C) 2006 Joachim Henke
+ Copyright (C) 2006 Lonnie Mendez
+ Copyright (C) 2006 Marius Groeger
+ Copyright (C) 2007-2008 Bull S.A.S.
+ Copyright (C) 2007-2008 IBM Corporation
+ Copyright (C) 2007-2008 Lauro Ramos Venancio <lauro.venancio@indt.org.br>
+ Copyright (C) 2007-2008 Nokia Corporation
+ Copyright (C) 2007-2008 OpenMoko Inc. <andrew@openedhand.com>
+ Copyright (C) 2007, 2009 Alexander Graf <agraf@suse.de>
+ Copyright (C) 2007-2009 Edgar E. Iglesias <edgar.iglesias@gmail.com>
+ Copyright (C) 2007-2009 Herve Poussineau
+ Copyright (C) 2007 Arastra Inc.
+ Copyright (C) 2007 Armin Kuster <akuster@mvista.com>
+ Copyright (C) 2007 Dan Aloni
+ Copyright (C) 2007 Marko Kohtala
+ Copyright (C) 2007 MontaVista Software Inc.
+ Copyright (C) 2007 Robert Reif
+ Copyright (C) 2007 Vladimir Ananiev <vovan888@gmail.com>
+ Copyright (C) 2008-2009 Arnaud Patard <arnaud.patard@rtp-net.org>
+ Copyright (C) 2008-2009 Citrix Systems Inc.
+ Copyright (C) 2008-2009 Gerd Hoffmann <kraxel@redhat.com>
+ Copyright (C) 2008 Dell MessageOne
+ Copyright (C) 2008 Dmitry Baryshkov
+ Copyright (C) 2008 Gleb Natapov
+ Copyright (C) 2008 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ Copyright (C) 2008 Lubomir Rintel
+ Copyright (C) 2008 Max Krasnyansky
+ Copyright (C) 2008 Paul Mundt
+ Copyright (C) 2008 Samuel Thibault <samuel.thibault@ens-lyon.org>
+ Copyright (C) 2008 Shin-ichiro KAWASAKI
+ Copyright (C) 2008 Takashi YOSHII
+ Copyright (C) 2008 TJ <linux@tjworld.net>
+ Copyright (C) 2009 CodeSourcery
+ Copyright (C) 2009 Freescale Semiconductor Inc.
+ Copyright (C) 2009 Hewlett-Packard Development Company
+ Copyright (C) 2009 Isaku Yamahata <yamahata@valinux.co.jp>
+ Copyright (C) 2009 Kevin Wolf <kwolf@redhat.com> <kwolf@suse.de>
+ Copyright (C) 2009 Laurent Vivier <laurent.vivier@bull.net>
+ Copyright (C) 2009 Michael S. Tsirkin <mst@redhat.com>
+ Copyright (C) 2009 Novell Inc.
+ Copyright (C) 2009 Ulrich Hecht <uli@suse.de>
+ Copyright (C) 2009 VA Linux Systems Japan
+
+License:
+ QEMU as a whole is released under the GNU General Public License version 2.
+ On Debian systems, the complete text of the GNU General Public License
+ version 2 can be found in the file /usr/share/common-licenses/GPL-2.
+ .
+ Parts of QEMU have specific licenses which are compatible with the
+ GNU General Public License. Hence each source file contains its own
+ licensing information.
+ .
+ In particular, the QEMU virtual CPU core library (libqemu.a) is
+ released under the GNU Lesser General Public License version 2 or later.
+ On Debian systems, the complete text of the GNU Lesser General Public
+ License can be found in the file /usr/share/common-licenses/LGPL-2.
+ .
+ The BSD emulator is released under the following BSD license:
+ .
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ .
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ SUCH DAMAGE.
+ .
+ The TCG code and many hardware device emulation sources are released under the
+ following MIT license:
+ .
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ .
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ .
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ .
+ The QEMU Logo, pc-bios/qemu_logo*.svg, and also icons and pictures derived from
+ it, pc-bios/qemu-icon.bmp, pc-bios/qemu-nsis.*, are licensed under Creative
+ Commons Attribution license version 3.0 (CC-BY-3.0):
+ .
+ Attribution 3.0 Unported
+ .
+ CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
+ LEGAL SERVICES. DISTRIBUTION OF THIS LICENSE DOES NOT CREATE AN
+ ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
+ INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
+ REGARDING THE INFORMATION PROVIDED, AND DISCLAIMS LIABILITY FOR
+ DAMAGES RESULTING FROM ITS USE.
+ .
+ License
+ .
+ THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE
+ COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY
+ COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS
+ AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.
+ .
+ BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE
+ TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY
+ BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS
+ CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND
+ CONDITIONS.
+ .
+ 1. Definitions
+ .
+ a. "Adaptation" means a work based upon the Work, or upon the Work and
+ other pre-existing works, such as a translation, adaptation,
+ derivative work, arrangement of music or other alterations of a
+ literary or artistic work, or phonogram or performance and includes
+ cinematographic adaptations or any other form in which the Work may be
+ recast, transformed, or adapted including in any form recognizably
+ derived from the original, except that a work that constitutes a
+ Collection will not be considered an Adaptation for the purpose of
+ this License. For the avoidance of doubt, where the Work is a musical
+ work, performance or phonogram, the synchronization of the Work in
+ timed-relation with a moving image ("synching") will be considered an
+ Adaptation for the purpose of this License.
+ b. "Collection" means a collection of literary or artistic works, such as
+ encyclopedias and anthologies, or performances, phonograms or
+ broadcasts, or other works or subject matter other than works listed
+ in Section 1(f) below, which, by reason of the selection and
+ arrangement of their contents, constitute intellectual creations, in
+ which the Work is included in its entirety in unmodified form along
+ with one or more other contributions, each constituting separate and
+ independent works in themselves, which together are assembled into a
+ collective whole. A work that constitutes a Collection will not be
+ considered an Adaptation (as defined above) for the purposes of this
+ License.
+ c. "Distribute" means to make available to the public the original and
+ copies of the Work or Adaptation, as appropriate, through sale or
+ other transfer of ownership.
+ d. "Licensor" means the individual, individuals, entity or entities that
+ offer(s) the Work under the terms of this License.
+ e. "Original Author" means, in the case of a literary or artistic work,
+ the individual, individuals, entity or entities who created the Work
+ or if no individual or entity can be identified, the publisher; and in
+ addition (i) in the case of a performance the actors, singers,
+ musicians, dancers, and other persons who act, sing, deliver, declaim,
+ play in, interpret or otherwise perform literary or artistic works or
+ expressions of folklore; (ii) in the case of a phonogram the producer
+ being the person or legal entity who first fixes the sounds of a
+ performance or other sounds; and, (iii) in the case of broadcasts, the
+ organization that transmits the broadcast.
+ f. "Work" means the literary and/or artistic work offered under the terms
+ of this License including without limitation any production in the
+ literary, scientific and artistic domain, whatever may be the mode or
+ form of its expression including digital form, such as a book,
+ pamphlet and other writing; a lecture, address, sermon or other work
+ of the same nature; a dramatic or dramatico-musical work; a
+ choreographic work or entertainment in dumb show; a musical
+ composition with or without words; a cinematographic work to which are
+ assimilated works expressed by a process analogous to cinematography;
+ a work of drawing, painting, architecture, sculpture, engraving or
+ lithography; a photographic work to which are assimilated works
+ expressed by a process analogous to photography; a work of applied
+ art; an illustration, map, plan, sketch or three-dimensional work
+ relative to geography, topography, architecture or science; a
+ performance; a broadcast; a phonogram; a compilation of data to the
+ extent it is protected as a copyrightable work; or a work performed by
+ a variety or circus performer to the extent it is not otherwise
+ considered a literary or artistic work.
+ g. "You" means an individual or entity exercising rights under this
+ License who has not previously violated the terms of this License with
+ respect to the Work, or who has received express permission from the
+ Licensor to exercise rights under this License despite a previous
+ violation.
+ h. "Publicly Perform" means to perform public recitations of the Work and
+ to communicate to the public those public recitations, by any means or
+ process, including by wire or wireless means or public digital
+ performances; to make available to the public Works in such a way that
+ members of the public may access these Works from a place and at a
+ place individually chosen by them; to perform the Work to the public
+ by any means or process and the communication to the public of the
+ performances of the Work, including by public digital performance; to
+ broadcast and rebroadcast the Work by any means including signs,
+ sounds or images.
+ i. "Reproduce" means to make copies of the Work by any means including
+ without limitation by sound or visual recordings and the right of
+ fixation and reproducing fixations of the Work, including storage of a
+ protected performance or phonogram in digital form or other electronic
+ medium.
+ .
+ 2. Fair Dealing Rights. Nothing in this License is intended to reduce,
+ limit, or restrict any uses free from copyright or rights arising from
+ limitations or exceptions that are provided for in connection with the
+ copyright protection under copyright law or other applicable laws.
+ .
+ 3. License Grant. Subject to the terms and conditions of this License,
+ Licensor hereby grants You a worldwide, royalty-free, non-exclusive,
+ perpetual (for the duration of the applicable copyright) license to
+ exercise the rights in the Work as stated below:
+ .
+ a. to Reproduce the Work, to incorporate the Work into one or more
+ Collections, and to Reproduce the Work as incorporated in the
+ Collections;
+ b. to create and Reproduce Adaptations provided that any such Adaptation,
+ including any translation in any medium, takes reasonable steps to
+ clearly label, demarcate or otherwise identify that changes were made
+ to the original Work. For example, a translation could be marked "The
+ original work was translated from English to Spanish," or a
+ modification could indicate "The original work has been modified.";
+ c. to Distribute and Publicly Perform the Work including as incorporated
+ in Collections; and,
+ d. to Distribute and Publicly Perform Adaptations.
+ e. For the avoidance of doubt:
+ .
+ i. Non-waivable Compulsory License Schemes. In those jurisdictions in
+ which the right to collect royalties through any statutory or
+ compulsory licensing scheme cannot be waived, the Licensor
+ reserves the exclusive right to collect such royalties for any
+ exercise by You of the rights granted under this License;
+ ii. Waivable Compulsory License Schemes. In those jurisdictions in
+ which the right to collect royalties through any statutory or
+ compulsory licensing scheme can be waived, the Licensor waives the
+ exclusive right to collect such royalties for any exercise by You
+ of the rights granted under this License; and,
+ iii. Voluntary License Schemes. The Licensor waives the right to
+ collect royalties, whether individually or, in the event that the
+ Licensor is a member of a collecting society that administers
+ voluntary licensing schemes, via that society, from any exercise
+ by You of the rights granted under this License.
+ .
+ The above rights may be exercised in all media and formats whether now
+ known or hereafter devised. The above rights include the right to make
+ such modifications as are technically necessary to exercise the rights in
+ other media and formats. Subject to Section 8(f), all rights not expressly
+ granted by Licensor are hereby reserved.
+ .
+ 4. Restrictions. The license granted in Section 3 above is expressly made
+ subject to and limited by the following restrictions:
+ .
+ a. You may Distribute or Publicly Perform the Work only under the terms
+ of this License. You must include a copy of, or the Uniform Resource
+ Identifier (URI) for, this License with every copy of the Work You
+ Distribute or Publicly Perform. You may not offer or impose any terms
+ on the Work that restrict the terms of this License or the ability of
+ the recipient of the Work to exercise the rights granted to that
+ recipient under the terms of the License. You may not sublicense the
+ Work. You must keep intact all notices that refer to this License and
+ to the disclaimer of warranties with every copy of the Work You
+ Distribute or Publicly Perform. When You Distribute or Publicly
+ Perform the Work, You may not impose any effective technological
+ measures on the Work that restrict the ability of a recipient of the
+ Work from You to exercise the rights granted to that recipient under
+ the terms of the License. This Section 4(a) applies to the Work as
+ incorporated in a Collection, but this does not require the Collection
+ apart from the Work itself to be made subject to the terms of this
+ License. If You create a Collection, upon notice from any Licensor You
+ must, to the extent practicable, remove from the Collection any credit
+ as required by Section 4(b), as requested. If You create an
+ Adaptation, upon notice from any Licensor You must, to the extent
+ practicable, remove from the Adaptation any credit as required by
+ Section 4(b), as requested.
+ b. If You Distribute, or Publicly Perform the Work or any Adaptations or
+ Collections, You must, unless a request has been made pursuant to
+ Section 4(a), keep intact all copyright notices for the Work and
+ provide, reasonable to the medium or means You are utilizing: (i) the
+ name of the Original Author (or pseudonym, if applicable) if supplied,
+ and/or if the Original Author and/or Licensor designate another party
+ or parties (e.g., a sponsor institute, publishing entity, journal) for
+ attribution ("Attribution Parties") in Licensor's copyright notice,
+ terms of service or by other reasonable means, the name of such party
+ or parties; (ii) the title of the Work if supplied; (iii) to the
+ extent reasonably practicable, the URI, if any, that Licensor
+ specifies to be associated with the Work, unless such URI does not
+ refer to the copyright notice or licensing information for the Work;
+ and (iv) , consistent with Section 3(b), in the case of an Adaptation,
+ a credit identifying the use of the Work in the Adaptation (e.g.,
+ "French translation of the Work by Original Author," or "Screenplay
+ based on original Work by Original Author"). The credit required by
+ this Section 4 (b) may be implemented in any reasonable manner;
+ provided, however, that in the case of a Adaptation or Collection, at
+ a minimum such credit will appear, if a credit for all contributing
+ authors of the Adaptation or Collection appears, then as part of these
+ credits and in a manner at least as prominent as the credits for the
+ other contributing authors. For the avoidance of doubt, You may only
+ use the credit required by this Section for the purpose of attribution
+ in the manner set out above and, by exercising Your rights under this
+ License, You may not implicitly or explicitly assert or imply any
+ connection with, sponsorship or endorsement by the Original Author,
+ Licensor and/or Attribution Parties, as appropriate, of You or Your
+ use of the Work, without the separate, express prior written
+ permission of the Original Author, Licensor and/or Attribution
+ Parties.
+ c. Except as otherwise agreed in writing by the Licensor or as may be
+ otherwise permitted by applicable law, if You Reproduce, Distribute or
+ Publicly Perform the Work either by itself or as part of any
+ Adaptations or Collections, You must not distort, mutilate, modify or
+ take other derogatory action in relation to the Work which would be
+ prejudicial to the Original Author's honor or reputation. Licensor
+ agrees that in those jurisdictions (e.g. Japan), in which any exercise
+ of the right granted in Section 3(b) of this License (the right to
+ make Adaptations) would be deemed to be a distortion, mutilation,
+ modification or other derogatory action prejudicial to the Original
+ Author's honor and reputation, the Licensor will waive or not assert,
+ as appropriate, this Section, to the fullest extent permitted by the
+ applicable national law, to enable You to reasonably exercise Your
+ right under Section 3(b) of this License (right to make Adaptations)
+ but not otherwise.
+ .
+ 5. Representations, Warranties and Disclaimer
+ .
+ UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING, LICENSOR
+ OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY
+ KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE,
+ INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY,
+ FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF
+ LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS,
+ WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION
+ OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU.
+ .
+ 6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE
+ LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR
+ ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES
+ ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS
+ BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ .
+ 7. Termination
+ .
+ a. This License and the rights granted hereunder will terminate
+ automatically upon any breach by You of the terms of this License.
+ Individuals or entities who have received Adaptations or Collections
+ from You under this License, however, will not have their licenses
+ terminated provided such individuals or entities remain in full
+ compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will
+ survive any termination of this License.
+ b. Subject to the above terms and conditions, the license granted here is
+ perpetual (for the duration of the applicable copyright in the Work).
+ Notwithstanding the above, Licensor reserves the right to release the
+ Work under different license terms or to stop distributing the Work at
+ any time; provided, however that any such election will not serve to
+ withdraw this License (or any other license that has been, or is
+ required to be, granted under the terms of this License), and this
+ License will continue in full force and effect unless terminated as
+ stated above.
+ .
+ 8. Miscellaneous
+ .
+ a. Each time You Distribute or Publicly Perform the Work or a Collection,
+ the Licensor offers to the recipient a license to the Work on the same
+ terms and conditions as the license granted to You under this License.
+ b. Each time You Distribute or Publicly Perform an Adaptation, Licensor
+ offers to the recipient a license to the original Work on the same
+ terms and conditions as the license granted to You under this License.
+ c. If any provision of this License is invalid or unenforceable under
+ applicable law, it shall not affect the validity or enforceability of
+ the remainder of the terms of this License, and without further action
+ by the parties to this agreement, such provision shall be reformed to
+ the minimum extent necessary to make such provision valid and
+ enforceable.
+ d. No term or provision of this License shall be deemed waived and no
+ breach consented to unless such waiver or consent shall be in writing
+ and signed by the party to be charged with such waiver or consent.
+ e. This License constitutes the entire agreement between the parties with
+ respect to the Work licensed here. There are no understandings,
+ agreements or representations with respect to the Work not specified
+ here. Licensor shall not be bound by any additional provisions that
+ may appear in any communication from You. This License may not be
+ modified without the mutual written agreement of the Licensor and You.
+ f. The rights granted under, and the subject matter referenced, in this
+ License were drafted utilizing the terminology of the Berne Convention
+ for the Protection of Literary and Artistic Works (as amended on
+ September 28, 1979), the Rome Convention of 1961, the WIPO Copyright
+ Treaty of 1996, the WIPO Performances and Phonograms Treaty of 1996
+ and the Universal Copyright Convention (as revised on July 24, 1971).
+ These rights and subject matter take effect in the relevant
+ jurisdiction in which the License terms are sought to be enforced
+ according to the corresponding provisions of the implementation of
+ those treaty provisions in the applicable national law. If the
+ standard suite of rights granted under applicable copyright law
+ includes additional rights not granted under this License, such
+ additional rights are deemed to be included in the License; this
+ License is not intended to restrict the license of any rights under
+ applicable law.
+ .
+ Creative Commons Notice
+ .
+ Creative Commons is not a party to this License, and makes no warranty
+ whatsoever in connection with the Work. Creative Commons will not be
+ liable to You or any party on any legal theory for any damages
+ whatsoever, including without limitation any general, special,
+ incidental or consequential damages arising in connection to this
+ license. Notwithstanding the foregoing two (2) sentences, if Creative
+ Commons has expressly identified itself as the Licensor hereunder, it
+ shall have all rights and obligations of Licensor.
+ .
+ Except for the limited purpose of indicating to the public that the
+ Work is licensed under the CCPL, Creative Commons does not authorize
+ the use by either party of the trademark "Creative Commons" or any
+ related trademark or logo of Creative Commons without the prior
+ written consent of Creative Commons. Any permitted use will be in
+ compliance with Creative Commons' then-current trademark usage
+ guidelines, as may be published on its website or otherwise made
+ available upon request from time to time. For the avoidance of doubt,
+ this trademark restriction does not form part of this License.
+ .
+ Creative Commons may be contacted at https://creativecommons.org/.
diff --git a/debian/extract-config-opts b/debian/extract-config-opts
new file mode 100755
index 00000000..3ca2d15a
--- /dev/null
+++ b/debian/extract-config-opts
@@ -0,0 +1,11 @@
+#! /bin/sh
+
+# This is a trivial script to parse comments in debian/control
+# into a set of system-specific configure options.
+# Usage: ./debian/extract-config-opts $OS-$ARCH debian/control
+
+sed -n 's/^# \?--/--/p' $2 | \
+while IFS=' ' read f p x; do
+ [ -n "$p" ] || p="*"
+ eval "case \$1 in ($p) echo \$f;; esac"
+done
diff --git a/debian/gbp.conf b/debian/gbp.conf
new file mode 100644
index 00000000..7ba007a6
--- /dev/null
+++ b/debian/gbp.conf
@@ -0,0 +1,4 @@
+[DEFAULT]
+sign-tags = True
+pristine-tar = True
+debian-branch = debian-bookworm
diff --git a/debian/get-orig-source.sh b/debian/get-orig-source.sh
new file mode 100755
index 00000000..799d9b19
--- /dev/null
+++ b/debian/get-orig-source.sh
@@ -0,0 +1,141 @@
+#! /bin/sh
+
+set -e
+
+base=https://download.qemu.org/
+comp=.xz
+
+dir() {
+ if [ -d $1 ]; then
+ echo removing $1/...
+ rm -rf $1
+ else
+ echo $1/ already removed
+ fi
+}
+
+file() {
+ for f in "$@"; do
+ if [ -f "$f" ]; then
+ rm -vf -- "$f"
+ else
+ echo "$f already removed"
+ fi
+ done
+}
+
+clean_dfsg() {
+# remove only those blobs which does not have packaged source
+# remove all other blobs too
+
+file pc-bios/bios.bin # roms/seabios/
+file pc-bios/bios-256k.bin # roms/seabios/
+file pc-bios/bios-microvm.bin # roms/qboot/ (old)
+file pc-bios/qboot.rom # roms/qboot/
+file pc-bios/hppa-firmware.img # roms/seabios-hppa/
+file pc-bios/sgabios.bin # roms/sgabios/
+file pc-bios/slof.bin # roms/SLOF/
+file pc-bios/vgabios*.bin # roms/vgabios/
+file pc-bios/pxe-*.rom # roms/ipxe/
+file pc-bios/efi-*.rom # roms/ipxe/
+file pc-bios/edk2-*.fd.bz2 # roms/edk2/
+file pc-bios/bamboo.dtb # pc-bios/bamboo.dts
+file pc-bios/canyonlands.dtb
+file pc-bios/openbios-* # roms/openbios/
+file pc-bios/opensbi-*.bin # roms/opensbi/
+file pc-bios/opensbi-*.elf # roms/opensbi/
+file pc-bios/palcode-clipper # roms/qemu-palcode/ alpha palcode
+file pc-bios/s390-ccw.img # pc-bios/s390-ccw/
+file pc-bios/s390-netboot.img # pc-bios/s390-ccw/
+file pc-bios/kvmvapic.bin # pc-bios/optionrom/
+file pc-bios/linuxboot*.bin # ditto
+file pc-bios/multiboot.bin # ditto
+file pc-bios/multiboot_dma.bin # ditto
+file pc-bios/pvh.bin # ditto
+file pc-bios/skiboot.lid # roms/skiboot/
+file pc-bios/u-boot.e500 # roms/u-boot/
+file pc-bios/u-boot-sam460-20100605.bin # roms/u-boot-sam460ex/
+file pc-bios/QEMU,*.bin # roms/openbios/
+file pc-bios/qemu_vga.ndrv # roms/QemuMacDrivers/
+file pc-bios/vof.bin # pc-bios/vof/
+
+# remove other software (git submodules)
+dir roms/ipxe # separate package
+dir roms/seabios # separate package
+file roms/SLOF/board-js2x/rtas/i2c_bmc.oco
+file roms/SLOF/board-js2x/rtas/ipmi_oem.oco
+file roms/SLOF/clients/takeover/takeover.oco
+file roms/SLOF/lib/libipmi/libipmi.oco
+dir roms/edk2 # separate package
+dir roms/u-boot # separate package
+file roms/u-boot.tar.*
+#dir roms/u-boot-sam460ex # this one is not built by u-boot and requires older compiler
+dir roms/QemuMacDrivers
+
+dir dtc # system dtc exists and used
+dir capstone # system capstone exists and used
+dir slirp # system libslirp exists and used
+dir meson # meson build system
+
+}
+
+case "$#$1" in
+ 1clean | 1dfsg | 1dfsg[-_]clean)
+ if [ -f softmmu/vl.c -a -f hw/block/block.c -a -d pc-bios ]; then
+ clean_dfsg
+ exit 0
+ fi
+ echo "apparently not a qemu source dir" >&2; exit 1
+ ;;
+
+ 1[2-6].*) ;;
+
+ *)
+ echo "unknown arguments. Should be either 'dfsg' or a version number" >&2
+ exit 1
+ ;;
+esac
+
+deb="${1%-*}" # strip debian revision number
+upstream="${deb%+dfsg}"
+case "$upstream" in
+ *~rc*) upstream=$(echo "$upstream" | sed 's/~rc/-rc/') ;;
+esac
+case "$upstream" in
+ [2-6].[0-9] | [2-6].[0-9][!0-9.]* ) # add .0 to a version number
+ upstream=$(echo "$upstream" | sed 's/^.\../&.0/') ;;
+esac
+
+basetar=qemu-$upstream.tar$comp
+basedir=qemu-$deb
+debtar=qemu_$deb.orig.tar.xz
+
+if [ ! -f $basetar ]; then
+
+ echo getting upstream version $upstream ...
+ wget -Nc $base/$basetar
+
+fi
+
+if [ ! -f $debtar ]; then
+
+ if [ -e $basedir ]; then
+ echo "$basedir already exists, please move it away" >&2
+ exit 1
+ fi
+
+ echo extracting source in $basedir and cleaning up ...
+ mkdir $basedir
+ cd $basedir
+ tar -x -f ../$basetar --strip-components=1
+ clean_dfsg
+
+ cd ..
+ echo repacking to $debtar ...
+ XZ_OPT="-v6" \
+ tar -caf $debtar --owner=root --group=root --mode=a+rX --sort=name \
+ $basedir
+
+ rm -rf $basedir
+
+fi
diff --git a/debian/kvm-spice b/debian/kvm-spice
new file mode 100755
index 00000000..55f910d1
--- /dev/null
+++ b/debian/kvm-spice
@@ -0,0 +1,10 @@
+#! /bin/sh
+echo "$0: W: this is an old compat wrapper script for kvm-spice" >&2
+echo "$0: W: please use qemu-system-x86_64 instead of $0" >&2
+
+if echo "$@" | grep -q -E -e '(^|\s)-machine\s.*accel=' -e '(^|\s)-accel\s'; then
+ # acceleration already set via commandline option - adding -enable-kvm would conflic"
+ exec qemu-system-x86_64 "$@"
+else
+ exec qemu-system-x86_64 -enable-kvm "$@"
+fi
diff --git a/debian/kvm-spice.1 b/debian/kvm-spice.1
new file mode 100644
index 00000000..896daab2
--- /dev/null
+++ b/debian/kvm-spice.1
@@ -0,0 +1,17 @@
+.TH kvm-spice 1 2020-07 "5.0" Ubuntu
+.SH NAME
+kvm-spice, qemu-system-x86_64-spice \- compatibility names for qemu-system-x86_64
+.SH DESCRIPTION
+The two names are aliases for
+.BR qemu-system-x86_64 ,
+where kvm-spice enables kvm native hardware mode by default.
+These names are kept for backward compatibility
+wih old package, when spice-enabled qemu were packaged
+separately. Now main qemu-system has spice functionality
+built in. Please use
+.B qemu-system-x86_64
+instead of the old compat names.
+.SH SEE ALSO
+.BR qemu-system-x86_64 (1).
+.SH AUTHOR
+This manual page was written by Michael Tokarev <mjt@tls.msk.ru>.
diff --git a/debian/kvm.1 b/debian/kvm.1
new file mode 100644
index 00000000..0b272026
--- /dev/null
+++ b/debian/kvm.1
@@ -0,0 +1,20 @@
+.TH kvm 1 2020-07 "5.0" Debian
+.SH NAME
+kvm \- kvm-enabling link for qemu-system-@ARCH@
+.SH DESCRIPTION
+When executed as
+.BR kvm ,
+qemu-system is run with preference to native hardware-based
+virtualization, instead of relying solely on emulation.
+Essentially
+.B kvm
+is equivalent to
+.B qemu-system-@ARCH@
+.I -machine accel=kvm:tcg
+so when the host CPU support the kvm mode, native hardware
+virtualization is enabled, or qemu-system-@ARCH@ falls back
+to the emulation (TCG) mode.
+.SH SEE ALSO
+.BR qemu-system-@ARCH@ (1).
+.SH AUTHOR
+This manual page was written by Michael Tokarev <mjt@tls.msk.ru>.
diff --git a/debian/microvm-devices.mak b/debian/microvm-devices.mak
new file mode 100644
index 00000000..1512d34a
--- /dev/null
+++ b/debian/microvm-devices.mak
@@ -0,0 +1,26 @@
+# see configs/devices/i386-softmmu/default.mak
+# for additional devices which can be disabled
+#
+CONFIG_PCI_DEVICES=n
+
+# we can't disable all machine types (boards) as of 6.1
+# since the resulting binary fails to link
+#CONFIG_ISAPC=y
+#CONFIG_I440FX=y
+CONFIG_Q35=y
+CONFIG_MICROVM=y
+
+CONFIG_VIRTIO_BLK=y
+CONFIG_VIRTIO_SERIAL=y
+CONFIG_VIRTIO_INPUT=y
+CONFIG_VIRTIO_INPUT_HOST=y
+CONFIG_VHOST_USER_INPUT=y
+CONFIG_VIRTIO_NET=y
+CONFIG_VIRTIO_SCSI=y
+CONFIG_VIRTIO_RNG=y
+CONFIG_VIRTIO_CRYPTO=y
+CONFIG_VIRTIO_BALLOON=y
+CONFIG_VIRTIO_MEM=y
+CONFIG_VIRTIO_PMEM=y
+CONFIG_VIRTIO_GPU=y
+CONFIG_VHOST_USER_GPU=y
diff --git a/debian/not-installed b/debian/not-installed
new file mode 100644
index 00000000..b691757c
--- /dev/null
+++ b/debian/not-installed
@@ -0,0 +1,17 @@
+usr/include/qemu-plugin.h
+usr/share/doc/qemu/_static
+usr/share/doc/qemu/about
+usr/share/doc/qemu/devel
+usr/share/doc/qemu/interop
+usr/share/doc/qemu/specs
+usr/share/doc/qemu/tools
+usr/share/doc/qemu/*.*
+usr/share/doc/qemu/.buildinfo
+usr/share/icons
+usr/share/applications/qemu.desktop
+usr/bin/elf2dmp
+# test tool
+usr/bin/qemu-edid
+# this one might be helpful for qemu-system -k <lang>
+# but is -k flag useful these days?
+usr/bin/qemu-keymap
diff --git a/debian/optionrom.mak b/debian/optionrom.mak
new file mode 100644
index 00000000..27dc7249
--- /dev/null
+++ b/debian/optionrom.mak
@@ -0,0 +1,31 @@
+LD = ld
+OBJCOPY = objcopy
+CC = cc
+CFLAGS = -O2 -m16 -Wa,-32 -march=i486 \
+ -ffreestanding -fno-stack-protector -fno-pie \
+ -I${SRC_PATH}/include
+VPATH = ${SRC_PATH}/pc-bios/optionrom
+
+BINS = kvmvapic.bin linuxboot.bin linuxboot_dma.bin \
+ multiboot.bin multiboot_dma.bin pvh.bin
+all: ${BINS}
+
+%.o: %.S
+ ${CC} ${CFLAGS} -c -o $@ $<
+%.o: %.c
+ ${CC} ${CFLAGS} -c -o $@ $<
+%.img: %.o
+ ${LD} -m elf_i386 -T ${SRC_PATH}/pc-bios/optionrom/flat.lds -s -o $@ $^
+pvh.img: pvh.o pvh_main.o
+%.raw: %.img
+ ${OBJCOPY} -O binary -j .text $< $@
+%.bin: %.raw
+ python3 ${SRC_PATH}/scripts/signrom.py $< $@
+
+clean:
+ rm -f ${BINS}
+
+install: ${BINS}
+ install -m 0644 -t "${DESTDIR}" ${BINS}
+
+.PHONY: all clean install
diff --git a/debian/patches/ignore-roms-dependency-in-qtest.patch b/debian/patches/ignore-roms-dependency-in-qtest.patch
new file mode 100644
index 00000000..53bf1af2
--- /dev/null
+++ b/debian/patches/ignore-roms-dependency-in-qtest.patch
@@ -0,0 +1,20 @@
+Description: roms as dependencies won't be available in packaged qemu
+ Due to the removal of blobs the packaging will not have the roms
+ dependency set and would fail at configure stage with:
+ ../../tests/qtest/meson.build:272:2: ERROR: Unknown variable "roms".
+ Switch it back to the former empty initializer.
+Forwarded: no
+Author: Christian Ehrhardt <christian.ehrhardt@canonical.com>
+Last-Update: 2022-01-05
+--- a/tests/qtest/meson.build
++++ b/tests/qtest/meson.build
+@@ -269,7 +269,8 @@ foreach dir : target_dirs
+ qtest_emulator = emulators['qemu-system-' + target_base]
+ target_qtests = get_variable('qtests_' + target_base, []) + qtests_generic
+
+- test_deps = roms
++ # roms as dependencies won't be available in packaged qemu
++ test_deps = []
+ qtest_env = environment()
+ if have_tools
+ qtest_env.set('QTEST_QEMU_IMG', './qemu-img')
diff --git a/debian/patches/linux-user-binfmt-P.diff b/debian/patches/linux-user-binfmt-P.diff
new file mode 100644
index 00000000..dd680235
--- /dev/null
+++ b/debian/patches/linux-user-binfmt-P.diff
@@ -0,0 +1,90 @@
+Subject: [PATCH, HACK]: linux-user: handle binfmt-misc P flag as a separate exe name
+From: Michael Tokarev <mjt@tls.msk.ru>
+Date: Sat, 13 Feb 2021 13:57:52 +0300
+Updated: Wed, 31 Aug 2022 12:30:17 +0300
+
+A hackish way to distinguish the case when qemu-user binary is executed
+using in-kernel binfmt-misc subsystem with P flag (preserve argv).
+We register binfmt interpreter under name /usr/libexec/qemu-binfmt/qemu-foo-binfmt-P
+(which is just a symlink to ../../bin/qemu-foo), and if run like that,
+qemu-user binary will "know" it should interpret argv[1] & argv[2]
+in a special way.
+
+diff --git a/linux-user/main.c b/linux-user/main.c
+index e44bdb17b8..587bd02db2 100644
+--- a/linux-user/main.c
++++ b/linux-user/main.c
+@@ -562,7 +562,7 @@ static void usage(int exitcode)
+ exit(exitcode);
+ }
+
+-static int parse_args(int argc, char **argv)
++static int parse_args(int argc, char **argv, bool *preserve_argv0)
+ {
+ const char *r;
+ int optind;
+@@ -579,6 +579,28 @@ static int parse_args(int argc, char **argv)
+ }
+ }
+
++ /* HACK alert.
++ * when run as an interpreter using kernel's binfmt-misc mechanism,
++ * we have to know where are we (our own binary), where's the binary being run,
++ * and what it's argv[0] element.
++ * Only with the P interpreter flag kernel passes all 3 elements as first 3 argv[],
++ * but we can't distinguish if we were run with or without this P flag.
++ * So we register a special name with binfmt-misc system, a name which ends up
++ * in "-binfmt-P", and if our argv[0] ends up with that, we assume we were run
++ * from kernel's binfmt with P flag and our first 3 args are from kernel.
++ */
++ if (strlen(argv[0]) > sizeof("binfmt-P") &&
++ strcmp(argv[0] + strlen(argv[0]) - sizeof("binfmt-P"), "-binfmt-P") == 0) {
++ if (argc < 3) {
++ (void) fprintf(stderr, "qemu: %s has to be run using kernel binfmt-misc subsystem\n", argv[0]);
++ exit(EXIT_FAILURE);
++ }
++ exec_path = argv[1];
++ handle_arg_argv0(argv[2]);
++ *preserve_argv0 = true;
++ return 2;
++ }
++
+ optind = 1;
+ for (;;) {
+ if (optind >= argc) {
+@@ -648,7 +670,7 @@ int main(int argc, char **argv, char **envp)
+ int ret;
+ int execfd;
+ unsigned long max_reserved_va;
+- bool preserve_argv0;
++ bool preserve_argv0 = 0;
+
+ error_init(argv[0]);
+ module_call_init(MODULE_INIT_TRACE);
+@@ -678,7 +700,7 @@ int main(int argc, char **argv, char **envp)
+ qemu_add_opts(&qemu_trace_opts);
+ qemu_plugin_add_opts();
+
+- optind = parse_args(argc, argv);
++ optind = parse_args(argc, argv, &preserve_argv0);
+
+ qemu_set_log_filename_flags(last_log_filename,
+ last_log_mask | (enable_strace * LOG_STRACE),
+@@ -717,7 +739,9 @@ int main(int argc, char **argv, char **envp)
+
+ /*
+ * get binfmt_misc flags
++ * but only if not already done by parse_args() above
+ */
++ if (!preserve_argv0) {
+ preserve_argv0 = !!(qemu_getauxval(AT_FLAGS) & AT_FLAGS_PRESERVE_ARGV0);
+
+ /*
+@@ -728,6 +752,7 @@ int main(int argc, char **argv, char **envp)
+ if (optind + 1 < argc && preserve_argv0) {
+ optind++;
+ }
++ }
+
+ if (cpu_model == NULL) {
+ cpu_model = cpu_get_model(get_elf_eflags(execfd));
diff --git a/debian/patches/mark-internal-codegen-functions-hidden.patch b/debian/patches/mark-internal-codegen-functions-hidden.patch
new file mode 100644
index 00000000..b779959f
--- /dev/null
+++ b/debian/patches/mark-internal-codegen-functions-hidden.patch
@@ -0,0 +1,50 @@
+From: Michael Tokarev <mjt@tls.msk.ru>
+Subject: mark internal codegen helpers to be hidden
+Date: Sat, 04 Jan 2025 13:53:36 +0300
+Forwarded: not-needed
+
+QEMU TCG uses arrays of pointers to functions for its
+code generator. In 7.2, these functions are declared as
+static inline. However, at least on some platforms, GCC
+tries to make these functions visible to be used in a DSO.
+And this makes the linker to fail at least on some platforms,
+https://gitlab.com/qemu-project/qemu/-/issues/1129.
+
+Mark the internal generated helper functions to have hidden
+visibility, so gcc does not generate code for sharing them,
+which makes GOT significantly smaller (and the actual code
+to access these functions a bit more efficient too).
+
+In later versions, qemu changed this place to use different
+way, so this problem does not exist in more recent qemu.
+
+diff --git a/include/exec/helper-gen.h b/include/exec/helper-gen.h
+--- a/include/exec/helper-gen.h
++++ b/include/exec/helper-gen.h
+@@ -78,9 +78,11 @@ static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
+ tcg_gen_callN(HELPER(name), dh_retvar(ret), 7, args); \
+ }
+
++#pragma GCC visibility push(hidden)
+ #include "helper.h"
+ #include "accel/tcg/tcg-runtime.h"
+ #include "accel/tcg/plugin-helpers.h"
++#pragma GCC visibility pop
+
+ #undef DEF_HELPER_FLAGS_0
+ #undef DEF_HELPER_FLAGS_1
+diff --git a/include/exec/helper-proto.h b/include/exec/helper-proto.h
+--- a/include/exec/helper-proto.h
++++ b/include/exec/helper-proto.h
+@@ -37,9 +37,11 @@ dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), dh_ctype(t3), \
+
+ #define IN_HELPER_PROTO
+
++#pragma GCC visibility push(hidden)
+ #include "helper.h"
+ #include "accel/tcg/tcg-runtime.h"
+ #include "accel/tcg/plugin-helpers.h"
++#pragma GCC visibility pop
+
+ #undef IN_HELPER_PROTO
+
diff --git a/debian/patches/microvm-default-machine-type.patch b/debian/patches/microvm-default-machine-type.patch
new file mode 100644
index 00000000..3f33d976
--- /dev/null
+++ b/debian/patches/microvm-default-machine-type.patch
@@ -0,0 +1,31 @@
+Subject: set default machine type to be microvm if CONFIG_MICROVM is defined
+Debian-Specific: yes
+From: Michael Tokarev <mjt@tls.msk.ru>
+Date: Sat, 22 Feb 2020 16:19:11 +0300
+
+diff --git a/hw/i386/microvm.c b/hw/i386/microvm.c
+index def37e60f79..35b948ffb11 100644
+--- a/hw/i386/microvm.c
++++ b/hw/i386/microvm.c
+@@ -495,6 +495,9 @@ static void microvm_class_init(ObjectClass *oc, void *data)
+
+ mc->family = "microvm_i386";
+ mc->desc = "microvm (i386)";
++#ifdef CONFIG_MICROVM_DEFAULT
++ mc->is_default = true;
++#endif
+ mc->units_per_default_bus = 1;
+ mc->no_floppy = 1;
+ mc->max_cpus = 288;
+diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
+index 22dee0e76c6..8115ff855d9 100644
+--- a/hw/i386/pc_piix.c
++++ b/hw/i386/pc_piix.c
+@@ -427,2 +427,7 @@ static void pc_i440fx_5_0_machine_options(MachineClass *m)
+ m->is_default = true;
++#ifdef CONFIG_MICROVM_DEFAULT
++ m->is_default = false;
++#else
++ m->is_default = true;
++#endif
+ pcmc->default_cpu_version = 1;
diff --git a/debian/patches/note-missing-module-pkg-name.diff b/debian/patches/note-missing-module-pkg-name.diff
new file mode 100644
index 00000000..eee95aa1
--- /dev/null
+++ b/debian/patches/note-missing-module-pkg-name.diff
@@ -0,0 +1,38 @@
+Date: Sun, 22 Aug 2021 15:16:25 +0300
+Updated: Thu, 15 Dec 2022 14:23:16 +0300
+From: Michael Tokarev <mjt@tls.msk.ru>
+Subject: Note missing module package name
+
+Debian ships different modules in different packages.
+By default qemu ignores the fact that it can not load
+a module, pretending this module never existed.
+Give a useful hint about the package where the module
+in question resides.
+
+This is a hack, but it makes qemu a bit more user-friendly.
+
+diff --git a/util/module.c b/util/module.c
+index 32e263163c..2f3e35f781 100644
+--- a/util/module.c
++++ b/util/module.c
+@@ -303,6 +303,20 @@ int module_load(const char *prefix, const char *name, Error **errp)
+ }
+ rv = 0; /* module not found */
+
++ { /* notify user about extra package to install */
++ const char *pkg = NULL;
++ if (!strcmp(prefix, "block-"))
++ pkg = "qemu-block-extra";
++ else if (!strcmp(prefix, "ui-")
++ || !strcmp(prefix, "audio-")
++ || !strcmp(module_name, "virtio-gpu-gl"))
++ pkg = "qemu-system-gui";
++ if (pkg)
++ fprintf(stderr,
++ "qemu: module %s%s not found, do you want to install %s package?\n",
++ prefix, module_name, pkg);
++ }
++
+ out:
+ if (rv <= 0) {
+ g_hash_table_remove(loaded_modules, module_name);
diff --git a/debian/patches/openbios-address-of-packet-member.patch b/debian/patches/openbios-address-of-packet-member.patch
new file mode 100644
index 00000000..73b9f137
--- /dev/null
+++ b/debian/patches/openbios-address-of-packet-member.patch
@@ -0,0 +1,11 @@
+diff --git a/roms/openbios/drivers/usbohci.c b/roms/openbios/drivers/usbohci.c
+index 774164b..42788a2 100644
+--- a/roms/openbios/drivers/usbohci.c
++++ b/roms/openbios/drivers/usbohci.c
+@@ -44,4 +44,6 @@
+ #include "usbohci.h"
+
++#pragma GCC diagnostic warning "-Waddress-of-packed-member"
++
+ static void ohci_start (hci_t *controller);
+ static void ohci_stop (hci_t *controller);
diff --git a/debian/patches/openbios-array-bounds-gcc12.patch b/debian/patches/openbios-array-bounds-gcc12.patch
new file mode 100644
index 00000000..a96048b1
--- /dev/null
+++ b/debian/patches/openbios-array-bounds-gcc12.patch
@@ -0,0 +1,25 @@
+Subject: openbios: do not error-out array-bounds warning
+From: Michael Tokarev <mjt@tls.msk.ru>
+Date: Fri, 02 Sep 2022 18:35:30 +0300
+
+gcc-12.2 produces an apparently wrong warning for this file:
+
+roms/openbios/arch/ppc/qemu/init.c:400:10: error: \
+ array subscript 0 is outside array bounds of ‘uint32_t[0]’ {aka ‘unsigned int[]’} \
+ [-Werror=array-bounds]
+ 400 | *dsi = 0x48002002;
+ | =====^===========
+
+Turn this particular -Werror back into warning. Gcc is apparently wrong here.
+
+index e40385a70b..2e214aa079 100644
+--- a/roms/openbios/arch/ppc/qemu/init.c
++++ b/roms/openbios/arch/ppc/qemu/init.c
+@@ -397,4 +397,7 @@ ppc64_patch_handlers(void)
+ uint32_t *isi = (uint32_t *)0x400UL;
+
++#pragma GCC diagnostic warning "-Warray-bounds"
++/* gcc-12 misreports array-bounds error in the following two assignments: */
++
+ // Patch the first DSI handler instruction to: ba 0x2000
+ *dsi = 0x48002002;
diff --git a/debian/patches/openbios-array-bounds.diff b/debian/patches/openbios-array-bounds.diff
new file mode 100644
index 00000000..1152b5d3
--- /dev/null
+++ b/debian/patches/openbios-array-bounds.diff
@@ -0,0 +1,11 @@
+diff --git a/roms/openbios/drivers/usb.c b/roms/openbios/drivers/usb.c
+index 88b7580..03f6ebb 100644
+--- a/roms/openbios/drivers/usb.c
++++ b/roms/openbios/drivers/usb.c
+@@ -32,4 +32,6 @@
+ */
+
++#pragma GCC diagnostic warning "-Warray-bounds"
++
+ #include "config.h"
+ #include "drivers/usb.h"
diff --git a/debian/patches/openbios-spelling-endianess.patch b/debian/patches/openbios-spelling-endianess.patch
new file mode 100644
index 00000000..baefabcc
--- /dev/null
+++ b/debian/patches/openbios-spelling-endianess.patch
@@ -0,0 +1,24 @@
+diff --git a/roms/openbios/kernel/bootstrap.c b/roms/openbios/kernel/bootstrap.c
+index b7658ab..fb4506e 100644
+--- a/roms/openbios/kernel/bootstrap.c
++++ b/roms/openbios/kernel/bootstrap.c
+@@ -174 +174 @@ static void write_dictionary(const char *filename)
+- .endianess = -1,
++ .endianness = -1,
+@@ -176 +176 @@ static void write_dictionary(const char *filename)
+- .endianess = 0,
++ .endianness = 0,
+diff --git a/roms/openbios/kernel/dict.c b/roms/openbios/kernel/dict.c
+index 0986cb1..51afc67 100644
+--- a/roms/openbios/kernel/dict.c
++++ b/roms/openbios/kernel/dict.c
+@@ -255 +255 @@ void dump_header(dictionary_header_t *header)
+- printk(" endianess: %s\n", header->endianess?"big":"little");
++ printk(" endianness: %s\n", header->endianness?"big":"little");
+diff --git a/roms/openbios/kernel/include/dict.h b/roms/openbios/kernel/include/dict.h
+index 749fd6f..1e735fa 100644
+--- a/roms/openbios/kernel/include/dict.h
++++ b/roms/openbios/kernel/include/dict.h
+@@ -30 +30 @@ typedef struct dictionary_header {
+- u8 endianess;
++ u8 endianness;
diff --git a/debian/patches/openbios-use-source_date_epoch-in-makefile.patch b/debian/patches/openbios-use-source_date_epoch-in-makefile.patch
new file mode 100644
index 00000000..492939d6
--- /dev/null
+++ b/debian/patches/openbios-use-source_date_epoch-in-makefile.patch
@@ -0,0 +1,34 @@
+From: Vagrant Cascadian <vagrant@reproducible-builds.org>
+Date: Sun, 21 Jun 2020 19:27:11 +0000
+X-Dgit-Generated: 1:5.0-6~0~20200621~20 0b5923e6cc49abffd582177ba8558cfb6c7f10ce
+Subject: roms/openbios: Use SOURCE_DATE_EPOCH in Makefile.
+
+Embedding the build time breaks reproducibility. Instead, use the date
+specified by the SOURCE_DATE_EPOCH environment variable:
+
+ https://reproducible-builds.org/docs/source-date-epoch/
+
+This patch relies on features of GNU date, and will need further
+changes for portability to other systems.
+
+---
+
+--- qemu-5.0.orig/roms/openbios/Makefile.target
++++ qemu-5.0/roms/openbios/Makefile.target
+@@ -54,14 +54,14 @@ versions: $(ODIR)/target/include/openbio
+
+ $(ODIR)/forth/version.fs:
+ $(call quiet-command,true, " GEN $(TARGET_DIR)$@")
+- @DATE="$(shell echo `LC_ALL=C TZ=UTC date +'%b %e %Y %H:%M'`)" ; \
++ @DATE="$(shell echo `LC_ALL=C date --utc --date=@$(SOURCE_DATE_EPOCH) +'%b %e %Y %H:%M'`)" ; \
+ ( echo ": builddate \" $$DATE\" ; " ; \
+ echo ": version \" $(VERSION)\" ; " ; ) \
+ > $(dir $@)/version.fs
+
+ $(ODIR)/target/include/openbios-version.h:
+ $(call quiet-command,true, " GEN $(TARGET_DIR)$@")
+- @DATE="$(shell echo `LC_ALL=C TZ=UTC date +'%b %e %Y %H:%M'`)" ; \
++ @DATE="$(shell echo `LC_ALL=C date --utc --date=@$(SOURCE_DATE_EPOCH) +'%b %e %Y %H:%M'`)" ; \
+ ( echo "#define OPENBIOS_BUILD_DATE \"$$DATE\"" ; \
+ echo "#define OPENBIOS_VERSION_STR \"$(VERSION)\"" ; ) \
+ > $(dir $@)/openbios-version.h
diff --git a/debian/patches/seabios-hppa-use-consistent-date-and-remove-hostname.patch b/debian/patches/seabios-hppa-use-consistent-date-and-remove-hostname.patch
new file mode 100644
index 00000000..982f1208
--- /dev/null
+++ b/debian/patches/seabios-hppa-use-consistent-date-and-remove-hostname.patch
@@ -0,0 +1,32 @@
+From: Vagrant Cascadian <vagrant@reproducible-builds.org>
+Date: Sun, 21 Jun 2020 19:38:39 +0000
+X-Dgit-Generated: 1:5.0-6~0~20200621~20 92cdacf1c512114ca313800748a5fc162775f51e
+Subject: roms/seabios-hppa: Use consistent date and remove hostname.
+
+Two issues break reproducibility; the time and hostname get embedded
+in the resulting seabios binary.
+
+Simply drop the hostname from the embedded version string, as it
+shouldn't be needed in Debian package builds.
+
+Use the SOURCE_DATE_EPOCH environment variable to set the build date
+rather than the current time:
+
+ https://reproducible-builds.org/docs/source-date-epoch/
+
+---
+
+--- qemu-5.0.orig/roms/seabios-hppa/scripts/buildversion.py
++++ qemu-5.0/roms/seabios-hppa/scripts/buildversion.py
+@@ -125,9 +125,8 @@ def main():
+ if not ver:
+ ver = "?"
+ if not cleanbuild:
+- btime = time.strftime("%Y%m%d_%H%M%S")
+- hostname = socket.gethostname()
+- ver = "%s-%s-%s" % (ver, btime, hostname)
++ btime = time.strftime("%Y%m%d_%H%M%S", time.gmtime(int(os.environ.get('SOURCE_DATE_EPOCH', time.time()))))
++ ver = "%s-%s" % (ver, btime)
+ write_version(outfile, ver + options.extra, toolstr)
+
+ if __name__ == '__main__':
diff --git a/debian/patches/series b/debian/patches/series
new file mode 100644
index 00000000..86c0078d
--- /dev/null
+++ b/debian/patches/series
@@ -0,0 +1,34 @@
+v7.2.1.diff
+v7.2.2.diff
+v7.2.3.diff
+v7.2.4.diff
+v7.2.5.diff
+v7.2.6.diff
+v7.2.7.diff
+v7.2.8.diff
+v7.2.9.diff
+v7.2.10.diff
+v7.2.11.diff
+v7.2.12.diff
+v7.2.13.diff
+v7.2.14.diff
+v7.2.15.diff
+v7.2.16.diff
+v7.2.17.diff
+microvm-default-machine-type.patch
+skip-meson-pc-bios.diff
+linux-user-binfmt-P.diff
+note-missing-module-pkg-name.diff
+#
+openbios-address-of-packet-member.patch
+openbios-array-bounds.diff
+openbios-array-bounds-gcc12.patch
+openbios-use-source_date_epoch-in-makefile.patch
+seabios-hppa-use-consistent-date-and-remove-hostname.patch
+slof-remove-user-and-host-from-release-version.patch
+slof-ensure-ld-is-called-with-C-locale.patch
+spelling.diff
+openbios-spelling-endianess.patch
+slof-spelling-seperator.patch
+ignore-roms-dependency-in-qtest.patch
+mark-internal-codegen-functions-hidden.patch
diff --git a/debian/patches/skip-meson-pc-bios.diff b/debian/patches/skip-meson-pc-bios.diff
new file mode 100644
index 00000000..974cd9d8
--- /dev/null
+++ b/debian/patches/skip-meson-pc-bios.diff
@@ -0,0 +1,14 @@
+From: Michael Tokarev <mjt@tls.msk.ru>
+Subject: do not include pc-bios/meson.build from main build as we build all firmware separately
+
+pc-bios/meson.build tries to link various firmware files to the build
+directory, but we DFSG-removed them so the build fails to find them.
+Just disable entering the subdir entirely since we buile all the
+necessary firmware in d/rules anyway.
+
+diff --git a/meson.build b/meson.build
+--- a/meson.build
++++ b/meson.build
+@@ -2787 +2787 @@ subdir('tools')
+-subdir('pc-bios')
++#subdir('pc-bios')
diff --git a/debian/patches/slof-ensure-ld-is-called-with-C-locale.patch b/debian/patches/slof-ensure-ld-is-called-with-C-locale.patch
new file mode 100644
index 00000000..ed8018ca
--- /dev/null
+++ b/debian/patches/slof-ensure-ld-is-called-with-C-locale.patch
@@ -0,0 +1,20 @@
+From: Vagrant Cascadian <vagrant@reproducible-builds.org>
+Date: Mon, 22 Jun 2020 00:40:39 +0000
+X-Dgit-Generated: 1:5.0-6~0~20200622~0 973dc2cba2b12d0fc4706ad75af36abcab4f6da9
+Subject: slof/Makefile.gen: Ensure ld is called with the C locale.
+
+The output of "ld -V" changes based on the environment's locale.
+
+---
+
+--- qemu-5.0.orig/roms/SLOF/Makefile.gen
++++ qemu-5.0/roms/SLOF/Makefile.gen
+@@ -62,7 +62,7 @@ romfs_build:
+ ../build_info.img:
+ @echo "$(CC)" > ../build_info.img
+ @$(CC) -v >> ../build_info.img 2>&1
+- @$(LD) -V >> ../build_info.img 2>&1
++ @LC_ALL=C $(LD) -V >> ../build_info.img 2>&1
+
+ ../$(SUBBOARD).dtb:
+ @if [ -e dts/$(SUBBOARD).dts ]; then \
diff --git a/debian/patches/slof-remove-user-and-host-from-release-version.patch b/debian/patches/slof-remove-user-and-host-from-release-version.patch
new file mode 100644
index 00000000..38f99a7c
--- /dev/null
+++ b/debian/patches/slof-remove-user-and-host-from-release-version.patch
@@ -0,0 +1,21 @@
+From: Vagrant Cascadian <vagrant@reproducible-builds.org>
+Date: Mon, 22 Jun 2020 03:48:55 +0000
+X-Dgit-Generated: 1:5.0-6~0~20200622~4 7ad3e07212ae4baf17ca3734670f0774d06403a7
+Subject: roms/SLOF/Makefile.gen: Remove user and host from release version.
+
+This version string ends up in the slof.bin, leading to
+reproducibility issues.
+
+---
+
+--- qemu-5.0.orig/roms/SLOF/Makefile.gen
++++ qemu-5.0/roms/SLOF/Makefile.gen
+@@ -26,7 +26,7 @@ RELEASE=git-$(shell git rev-parse --shor
+ export DRIVER_NAME=git-$(shell git rev-parse --short=12 HEAD)
+ else
+ ifneq (,$(shell cat ../VERSION))
+-RELEASE="$(USER)@$(HOSTNAME) release $(shell cat ../VERSION)"
++RELEASE="release $(shell cat ../VERSION)"
+ export DRIVER_NAME=HEAD
+ else
+ RELEASE="$(USER)@$(HOSTNAME)(private build)"
diff --git a/debian/patches/slof-spelling-seperator.patch b/debian/patches/slof-spelling-seperator.patch
new file mode 100644
index 00000000..e7d8bd0c
--- /dev/null
+++ b/debian/patches/slof-spelling-seperator.patch
@@ -0,0 +1,7 @@
+diff --git a/roms/SLOF/lib/libnet/tftp.c b/roms/SLOF/lib/libnet/tftp.c
+index 9a5817a..71ea6ae 100644
+--- a/roms/SLOF/lib/libnet/tftp.c
++++ b/roms/SLOF/lib/libnet/tftp.c
+@@ -660 +660 @@ int parse_tftp_args(char buffer[], char *server_ip, char filename[], int fd,
+- printf("\n missing . seperator in %s\n", raw);
++ printf("\n missing . separator in %s\n", raw);
diff --git a/debian/patches/spelling.diff b/debian/patches/spelling.diff
new file mode 100644
index 00000000..614d64ad
--- /dev/null
+++ b/debian/patches/spelling.diff
@@ -0,0 +1,73 @@
+From 2401281d60491cf071e27c60079b7e6a61aa2378 Mon Sep 17 00:00:00 2001
+From: Michael Tokarev <mjt@tls.msk.ru>
+Date: Sat, 5 Nov 2022 14:45:24 +0300
+Subject: [PATCH 2/3] hw/virtio/virtio.c: spelling: suppoted
+
+Fixes: f3034ad71fcd0a6a58bc37830f182b307f089159
+Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
+Reviewed-by: Stefan Weil <sw@weilnetz.de>
+---
+ hw/virtio/virtio.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
+index 808446b4c9..e76218bdd5 100644
+--- a/hw/virtio/virtio.c
++++ b/hw/virtio/virtio.c
+@@ -343 +343 @@ qmp_virtio_feature_map_t virtio_scsi_feature_map[] = {
+- "buffers suppoted"),
++ "buffers supported"),
+--
+2.30.2
+
+
+From e6a27467dc8d03639e4e7207bd4841b840ad5942 Mon Sep 17 00:00:00 2001
+From: Michael Tokarev <mjt@tls.msk.ru>
+Date: Sat, 5 Nov 2022 14:51:31 +0300
+Subject: [PATCH 3/3] hw/ssi/sifive_spi.c: spelling: reigster
+
+Fixes: 0694dabe9763847f3010b54ab3ec7d367d2f0ff0
+Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
+Reviewed-by: Stefan Weil <sw@weilnetz.de>
+---
+ hw/ssi/sifive_spi.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/hw/ssi/sifive_spi.c b/hw/ssi/sifive_spi.c
+index 03540cf5ca..1b4a401ca1 100644
+--- a/hw/ssi/sifive_spi.c
++++ b/hw/ssi/sifive_spi.c
+@@ -270 +270 @@ static void sifive_spi_write(void *opaque, hwaddr addr,
+- "%s: invalid write to read-only reigster 0x%"
++ "%s: invalid write to read-only register 0x%"
+--
+2.30.2
+
+From 4ed607f64d4a684c9ab6b25dcc9e72fd69cc51c2 Mon Sep 17 00:00:00 2001
+From: Michael Tokarev <mjt@tls.msk.ru>
+Date: Thu, 15 Dec 2022 15:35:35 +0300
+Subject: [PATCH Trivial] hw/cxl/cxl-cdat.c: spelling: missmatch
+
+Introduced by: aba578bdace5303a441f8a37aad781b5cb06f38c
+
+Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
+---
+ hw/cxl/cxl-cdat.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/hw/cxl/cxl-cdat.c b/hw/cxl/cxl-cdat.c
+index 3653aa56f0..137abd0992 100644
+--- a/hw/cxl/cxl-cdat.c
++++ b/hw/cxl/cxl-cdat.c
+@@ -146,7 +146,7 @@ static void ct3_load_cdat(CDATObject *cdat, Error **errp)
+ num_ent++;
+ }
+ if (i != file_size) {
+- error_setg(errp, "CDAT: File length missmatch");
++ error_setg(errp, "CDAT: File length mismatch");
+ return;
+ }
+
+--
+2.30.2
+
diff --git a/debian/patches/v7.2.1.diff b/debian/patches/v7.2.1.diff
new file mode 100644
index 00000000..a980f89e
--- /dev/null
+++ b/debian/patches/v7.2.1.diff
@@ -0,0 +1,1945 @@
+Subject: v7.2.1
+Date: Wed Apr 5 14:37:42 2023 +0300
+From: Michael Tokarev <mjt@tls.msk.ru>
+Forwarded: not-needed
+
+This is a difference between upstream qemu v7.2.0
+and upstream qemu v7.2.1.
+
+ VERSION | 2 +-
+ block/curl.c | 44 +++++--
+ block/io.c | 3 +
+ block/iscsi.c | 1 +
+ block/qcow2-bitmap.c | 5 +-
+ chardev/char-socket.c | 1 +
+ configure | 2 +-
+ hw/acpi/cpu_hotplug.c | 3 +
+ hw/core/machine.c | 3 +
+ hw/i386/intel_iommu.c | 15 +++
+ hw/i386/microvm.c | 2 +-
+ hw/i386/pc.c | 4 +-
+ hw/i386/pc_piix.c | 2 -
+ hw/i386/pc_q35.c | 2 -
+ hw/i386/x86.c | 88 +++----------
+ hw/nvme/ctrl.c | 32 ++++-
+ hw/nvram/fw_cfg.c | 12 +-
+ hw/smbios/smbios.c | 8 +-
+ hw/timer/hpet.c | 19 ++-
+ hw/virtio/vhost-shadow-virtqueue.c | 2 +-
+ hw/virtio/vhost-user-gpio.c | 10 +-
+ hw/virtio/vhost-user-i2c.c | 5 +-
+ hw/virtio/vhost-user-rng.c | 5 +-
+ hw/virtio/vhost-vdpa.c | 17 +--
+ hw/virtio/vhost.c | 84 ++++++++++---
+ hw/virtio/virtio-mem.c | 6 +-
+ include/hw/i386/pc.h | 3 -
+ include/hw/i386/x86.h | 3 +-
+ include/hw/nvram/fw_cfg.h | 22 ----
+ include/hw/virtio/vhost-user-gpio.h | 2 +-
+ meson.build | 2 +-
+ migration/ram.c | 9 +-
+ scripts/shaderinclude.pl | 16 ---
+ scripts/shaderinclude.py | 26 ++++
+ scripts/symlink-install-tree.py | 1 -
+ subprojects/libvhost-user/libvhost-user.c | 7 ++
+ target/arm/helper.c | 3 +
+ target/arm/ptw.c | 6 +-
+ target/arm/sve_helper.c | 14 ++-
+ target/arm/translate.c | 2 +-
+ target/i386/tcg/emit.c.inc | 59 +++++----
+ target/riscv/translate.c | 12 +-
+ target/sh4/cpu.c | 2 +-
+ tests/tcg/Makefile.target | 2 +
+ tests/tcg/i386/Makefile.target | 6 +-
+ tests/tcg/i386/test-i386-adcox.c | 75 ++++++++++++
+ tests/tcg/i386/test-i386-bmi2.c | 197 ++++++++++++++++--------------
+ tests/tcg/multiarch/linux/linux-test.c | 6 +-
+ tests/tcg/riscv64/Makefile.target | 6 +
+ tests/tcg/riscv64/test-noc.S | 32 +++++
+ 50 files changed, 548 insertions(+), 342 deletions(-)
+
+diff --git a/VERSION b/VERSION
+index 0ee843cc60..b26a34e470 100644
+--- a/VERSION
++++ b/VERSION
+@@ -1 +1 @@
+-7.2.0
++7.2.1
+diff --git a/block/curl.c b/block/curl.c
+index cba4c4cac7..0b125095e3 100644
+--- a/block/curl.c
++++ b/block/curl.c
+@@ -37,8 +37,15 @@
+
+ // #define DEBUG_VERBOSE
+
++/* CURL 7.85.0 switches to a string based API for specifying
++ * the desired protocols.
++ */
++#if LIBCURL_VERSION_NUM >= 0x075500
++#define PROTOCOLS "HTTP,HTTPS,FTP,FTPS"
++#else
+ #define PROTOCOLS (CURLPROTO_HTTP | CURLPROTO_HTTPS | \
+ CURLPROTO_FTP | CURLPROTO_FTPS)
++#endif
+
+ #define CURL_NUM_STATES 8
+ #define CURL_NUM_ACB 8
+@@ -509,9 +516,18 @@ static int curl_init_state(BDRVCURLState *s, CURLState *state)
+ * obscure protocols. For example, do not allow POP3/SMTP/IMAP see
+ * CVE-2013-0249.
+ *
+- * Restricting protocols is only supported from 7.19.4 upwards.
++ * Restricting protocols is only supported from 7.19.4 upwards. Note:
++ * version 7.85.0 deprecates CURLOPT_*PROTOCOLS in favour of a string
++ * based CURLOPT_*PROTOCOLS_STR API.
+ */
+-#if LIBCURL_VERSION_NUM >= 0x071304
++#if LIBCURL_VERSION_NUM >= 0x075500
++ if (curl_easy_setopt(state->curl,
++ CURLOPT_PROTOCOLS_STR, PROTOCOLS) ||
++ curl_easy_setopt(state->curl,
++ CURLOPT_REDIR_PROTOCOLS_STR, PROTOCOLS)) {
++ goto err;
++ }
++#elif LIBCURL_VERSION_NUM >= 0x071304
+ if (curl_easy_setopt(state->curl, CURLOPT_PROTOCOLS, PROTOCOLS) ||
+ curl_easy_setopt(state->curl, CURLOPT_REDIR_PROTOCOLS, PROTOCOLS)) {
+ goto err;
+@@ -669,7 +685,12 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags,
+ const char *file;
+ const char *cookie;
+ const char *cookie_secret;
+- double d;
++ /* CURL >= 7.55.0 uses curl_off_t for content length instead of a double */
++#if LIBCURL_VERSION_NUM >= 0x073700
++ curl_off_t cl;
++#else
++ double cl;
++#endif
+ const char *secretid;
+ const char *protocol_delimiter;
+ int ret;
+@@ -796,27 +817,36 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags,
+ }
+ if (curl_easy_perform(state->curl))
+ goto out;
+- if (curl_easy_getinfo(state->curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &d)) {
++ /* CURL 7.55.0 deprecates CURLINFO_CONTENT_LENGTH_DOWNLOAD in favour of
++ * the *_T version which returns a more sensible type for content length.
++ */
++#if LIBCURL_VERSION_NUM >= 0x073700
++ if (curl_easy_getinfo(state->curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD_T, &cl)) {
++ goto out;
++ }
++#else
++ if (curl_easy_getinfo(state->curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &cl)) {
+ goto out;
+ }
++#endif
+ /* Prior CURL 7.19.4 return value of 0 could mean that the file size is not
+ * know or the size is zero. From 7.19.4 CURL returns -1 if size is not
+ * known and zero if it is really zero-length file. */
+ #if LIBCURL_VERSION_NUM >= 0x071304
+- if (d < 0) {
++ if (cl < 0) {
+ pstrcpy(state->errmsg, CURL_ERROR_SIZE,
+ "Server didn't report file size.");
+ goto out;
+ }
+ #else
+- if (d <= 0) {
++ if (cl <= 0) {
+ pstrcpy(state->errmsg, CURL_ERROR_SIZE,
+ "Unknown file size or zero-length file.");
+ goto out;
+ }
+ #endif
+
+- s->len = d;
++ s->len = cl;
+
+ if ((!strncasecmp(s->url, "http://", strlen("http://"))
+ || !strncasecmp(s->url, "https://", strlen("https://")))
+diff --git a/block/io.c b/block/io.c
+index b9424024f9..bbaa0d1b2d 100644
+--- a/block/io.c
++++ b/block/io.c
+@@ -2087,6 +2087,9 @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child,
+ if (bs->detect_zeroes == BLOCKDEV_DETECT_ZEROES_OPTIONS_UNMAP) {
+ flags |= BDRV_REQ_MAY_UNMAP;
+ }
++
++ /* Can't use optimization hint with bufferless zero write */
++ flags &= ~BDRV_REQ_REGISTERED_BUF;
+ }
+
+ if (ret < 0) {
+diff --git a/block/iscsi.c b/block/iscsi.c
+index a316d46d96..1bba42a71b 100644
+--- a/block/iscsi.c
++++ b/block/iscsi.c
+@@ -268,6 +268,7 @@ iscsi_co_generic_cb(struct iscsi_context *iscsi, int status,
+ timer_mod(&iTask->retry_timer,
+ qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + retry_time);
+ iTask->do_retry = 1;
++ return;
+ } else if (status == SCSI_STATUS_CHECK_CONDITION) {
+ int error = iscsi_translate_sense(&task->sense);
+ if (error == EAGAIN) {
+diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
+index bcad567c0c..3dff99ba06 100644
+--- a/block/qcow2-bitmap.c
++++ b/block/qcow2-bitmap.c
+@@ -115,7 +115,7 @@ static int update_header_sync(BlockDriverState *bs)
+ return bdrv_flush(bs->file->bs);
+ }
+
+-static inline void bitmap_table_to_be(uint64_t *bitmap_table, size_t size)
++static inline void bitmap_table_bswap_be(uint64_t *bitmap_table, size_t size)
+ {
+ size_t i;
+
+@@ -1401,9 +1401,10 @@ static int store_bitmap(BlockDriverState *bs, Qcow2Bitmap *bm, Error **errp)
+ goto fail;
+ }
+
+- bitmap_table_to_be(tb, tb_size);
++ bitmap_table_bswap_be(tb, tb_size);
+ ret = bdrv_pwrite(bs->file, tb_offset, tb_size * sizeof(tb[0]), tb, 0);
+ if (ret < 0) {
++ bitmap_table_bswap_be(tb, tb_size);
+ error_setg_errno(errp, -ret, "Failed to write bitmap '%s' to file",
+ bm_name);
+ goto fail;
+diff --git a/chardev/char-socket.c b/chardev/char-socket.c
+index 879564aa8a..b00efb1482 100644
+--- a/chardev/char-socket.c
++++ b/chardev/char-socket.c
+@@ -1065,6 +1065,7 @@ static void char_socket_finalize(Object *obj)
+ qio_net_listener_set_client_func_full(s->listener, NULL, NULL,
+ NULL, chr->gcontext);
+ object_unref(OBJECT(s->listener));
++ s->listener = NULL;
+ }
+ if (s->tls_creds) {
+ object_unref(OBJECT(s->tls_creds));
+diff --git a/configure b/configure
+index 26c7bc5154..5f1828f1ec 100755
+--- a/configure
++++ b/configure
+@@ -2416,7 +2416,7 @@ echo "QEMU_OBJCFLAGS=$QEMU_OBJCFLAGS" >> $config_host_mak
+ echo "GLIB_CFLAGS=$glib_cflags" >> $config_host_mak
+ echo "GLIB_LIBS=$glib_libs" >> $config_host_mak
+ echo "GLIB_BINDIR=$glib_bindir" >> $config_host_mak
+-echo "GLIB_VERSION=$(pkg-config --modversion glib-2.0)" >> $config_host_mak
++echo "GLIB_VERSION=$($pkg_config --modversion glib-2.0)" >> $config_host_mak
+ echo "QEMU_LDFLAGS=$QEMU_LDFLAGS" >> $config_host_mak
+ echo "EXESUF=$EXESUF" >> $config_host_mak
+
+diff --git a/hw/acpi/cpu_hotplug.c b/hw/acpi/cpu_hotplug.c
+index 53654f8638..ff14c3f410 100644
+--- a/hw/acpi/cpu_hotplug.c
++++ b/hw/acpi/cpu_hotplug.c
+@@ -52,6 +52,9 @@ static const MemoryRegionOps AcpiCpuHotplug_ops = {
+ .endianness = DEVICE_LITTLE_ENDIAN,
+ .valid = {
+ .min_access_size = 1,
++ .max_access_size = 4,
++ },
++ .impl = {
+ .max_access_size = 1,
+ },
+ };
+diff --git a/hw/core/machine.c b/hw/core/machine.c
+index 8d34caa31d..035d078a74 100644
+--- a/hw/core/machine.c
++++ b/hw/core/machine.c
+@@ -42,6 +42,9 @@
+
+ GlobalProperty hw_compat_7_1[] = {
+ { "virtio-device", "queue_reset", "false" },
++ { "virtio-rng-pci", "vectors", "0" },
++ { "virtio-rng-pci-transitional", "vectors", "0" },
++ { "virtio-rng-pci-non-transitional", "vectors", "0" },
+ };
+ const size_t hw_compat_7_1_len = G_N_ELEMENTS(hw_compat_7_1);
+
+diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
+index a08ee85edf..d025ef2873 100644
+--- a/hw/i386/intel_iommu.c
++++ b/hw/i386/intel_iommu.c
+@@ -3179,6 +3179,7 @@ static int vtd_iommu_notify_flag_changed(IOMMUMemoryRegion *iommu,
+ {
+ VTDAddressSpace *vtd_as = container_of(iommu, VTDAddressSpace, iommu);
+ IntelIOMMUState *s = vtd_as->iommu_state;
++ X86IOMMUState *x86_iommu = X86_IOMMU_DEVICE(s);
+
+ /* TODO: add support for VFIO and vhost users */
+ if (s->snoop_control) {
+@@ -3186,6 +3187,20 @@ static int vtd_iommu_notify_flag_changed(IOMMUMemoryRegion *iommu,
+ "Snoop Control with vhost or VFIO is not supported");
+ return -ENOTSUP;
+ }
++ if (!s->caching_mode && (new & IOMMU_NOTIFIER_MAP)) {
++ error_setg_errno(errp, ENOTSUP,
++ "device %02x.%02x.%x requires caching mode",
++ pci_bus_num(vtd_as->bus), PCI_SLOT(vtd_as->devfn),
++ PCI_FUNC(vtd_as->devfn));
++ return -ENOTSUP;
++ }
++ if (!x86_iommu->dt_supported && (new & IOMMU_NOTIFIER_DEVIOTLB_UNMAP)) {
++ error_setg_errno(errp, ENOTSUP,
++ "device %02x.%02x.%x requires device IOTLB mode",
++ pci_bus_num(vtd_as->bus), PCI_SLOT(vtd_as->devfn),
++ PCI_FUNC(vtd_as->devfn));
++ return -ENOTSUP;
++ }
+
+ /* Update per-address-space notifier flags */
+ vtd_as->notifier_flags = new;
+diff --git a/hw/i386/microvm.c b/hw/i386/microvm.c
+index 170a331e3f..b231ceda9a 100644
+--- a/hw/i386/microvm.c
++++ b/hw/i386/microvm.c
+@@ -330,7 +330,7 @@ static void microvm_memory_init(MicrovmMachineState *mms)
+ rom_set_fw(fw_cfg);
+
+ if (machine->kernel_filename != NULL) {
+- x86_load_linux(x86ms, fw_cfg, 0, true, false);
++ x86_load_linux(x86ms, fw_cfg, 0, true);
+ }
+
+ if (mms->option_roms) {
+diff --git a/hw/i386/pc.c b/hw/i386/pc.c
+index 546b703cb4..ec5a10534b 100644
+--- a/hw/i386/pc.c
++++ b/hw/i386/pc.c
+@@ -799,7 +799,7 @@ void xen_load_linux(PCMachineState *pcms)
+ rom_set_fw(fw_cfg);
+
+ x86_load_linux(x86ms, fw_cfg, pcmc->acpi_data_size,
+- pcmc->pvh_enabled, pcmc->legacy_no_rng_seed);
++ pcmc->pvh_enabled);
+ for (i = 0; i < nb_option_roms; i++) {
+ assert(!strcmp(option_rom[i].name, "linuxboot.bin") ||
+ !strcmp(option_rom[i].name, "linuxboot_dma.bin") ||
+@@ -1119,7 +1119,7 @@ void pc_memory_init(PCMachineState *pcms,
+
+ if (linux_boot) {
+ x86_load_linux(x86ms, fw_cfg, pcmc->acpi_data_size,
+- pcmc->pvh_enabled, pcmc->legacy_no_rng_seed);
++ pcmc->pvh_enabled);
+ }
+
+ for (i = 0; i < nb_option_roms; i++) {
+diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
+index 0ad0ed1603..24616bf924 100644
+--- a/hw/i386/pc_piix.c
++++ b/hw/i386/pc_piix.c
+@@ -449,11 +449,9 @@ DEFINE_I440FX_MACHINE(v7_2, "pc-i440fx-7.2", NULL,
+
+ static void pc_i440fx_7_1_machine_options(MachineClass *m)
+ {
+- PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
+ pc_i440fx_7_2_machine_options(m);
+ m->alias = NULL;
+ m->is_default = false;
+- pcmc->legacy_no_rng_seed = true;
+ compat_props_add(m->compat_props, hw_compat_7_1, hw_compat_7_1_len);
+ compat_props_add(m->compat_props, pc_compat_7_1, pc_compat_7_1_len);
+ }
+diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
+index a496bd6e74..f522874add 100644
+--- a/hw/i386/pc_q35.c
++++ b/hw/i386/pc_q35.c
+@@ -383,10 +383,8 @@ DEFINE_Q35_MACHINE(v7_2, "pc-q35-7.2", NULL,
+
+ static void pc_q35_7_1_machine_options(MachineClass *m)
+ {
+- PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
+ pc_q35_7_2_machine_options(m);
+ m->alias = NULL;
+- pcmc->legacy_no_rng_seed = true;
+ compat_props_add(m->compat_props, hw_compat_7_1, hw_compat_7_1_len);
+ compat_props_add(m->compat_props, pc_compat_7_1, pc_compat_7_1_len);
+ }
+diff --git a/hw/i386/x86.c b/hw/i386/x86.c
+index 78cc131926..80be3032cc 100644
+--- a/hw/i386/x86.c
++++ b/hw/i386/x86.c
+@@ -26,7 +26,6 @@
+ #include "qemu/cutils.h"
+ #include "qemu/units.h"
+ #include "qemu/datadir.h"
+-#include "qemu/guest-random.h"
+ #include "qapi/error.h"
+ #include "qapi/qmp/qerror.h"
+ #include "qapi/qapi-visit-common.h"
+@@ -37,7 +36,6 @@
+ #include "sysemu/whpx.h"
+ #include "sysemu/numa.h"
+ #include "sysemu/replay.h"
+-#include "sysemu/reset.h"
+ #include "sysemu/sysemu.h"
+ #include "sysemu/cpu-timers.h"
+ #include "sysemu/xen.h"
+@@ -657,12 +655,12 @@ DeviceState *ioapic_init_secondary(GSIState *gsi_state)
+ return dev;
+ }
+
+-typedef struct SetupData {
++struct setup_data {
+ uint64_t next;
+ uint32_t type;
+ uint32_t len;
+ uint8_t data[];
+-} __attribute__((packed)) SetupData;
++} __attribute__((packed));
+
+
+ /*
+@@ -769,35 +767,10 @@ static bool load_elfboot(const char *kernel_filename,
+ return true;
+ }
+
+-typedef struct SetupDataFixup {
+- void *pos;
+- hwaddr orig_val, new_val;
+- uint32_t addr;
+-} SetupDataFixup;
+-
+-static void fixup_setup_data(void *opaque)
+-{
+- SetupDataFixup *fixup = opaque;
+- stq_p(fixup->pos, fixup->new_val);
+-}
+-
+-static void reset_setup_data(void *opaque)
+-{
+- SetupDataFixup *fixup = opaque;
+- stq_p(fixup->pos, fixup->orig_val);
+-}
+-
+-static void reset_rng_seed(void *opaque)
+-{
+- SetupData *setup_data = opaque;
+- qemu_guest_getrandom_nofail(setup_data->data, le32_to_cpu(setup_data->len));
+-}
+-
+ void x86_load_linux(X86MachineState *x86ms,
+ FWCfgState *fw_cfg,
+ int acpi_data_size,
+- bool pvh_enabled,
+- bool legacy_no_rng_seed)
++ bool pvh_enabled)
+ {
+ bool linuxboot_dma_enabled = X86_MACHINE_GET_CLASS(x86ms)->fwcfg_dma_enabled;
+ uint16_t protocol;
+@@ -805,17 +778,16 @@ void x86_load_linux(X86MachineState *x86ms,
+ int dtb_size, setup_data_offset;
+ uint32_t initrd_max;
+ uint8_t header[8192], *setup, *kernel;
+- hwaddr real_addr, prot_addr, cmdline_addr, initrd_addr = 0, first_setup_data = 0;
++ hwaddr real_addr, prot_addr, cmdline_addr, initrd_addr = 0;
+ FILE *f;
+ char *vmode;
+ MachineState *machine = MACHINE(x86ms);
+- SetupData *setup_data;
++ struct setup_data *setup_data;
+ const char *kernel_filename = machine->kernel_filename;
+ const char *initrd_filename = machine->initrd_filename;
+ const char *dtb_filename = machine->dtb;
+ const char *kernel_cmdline = machine->kernel_cmdline;
+ SevKernelLoaderContext sev_load_ctx = {};
+- enum { RNG_SEED_LENGTH = 32 };
+
+ /* Align to 16 bytes as a paranoia measure */
+ cmdline_size = (strlen(kernel_cmdline) + 16) & ~15;
+@@ -1092,41 +1064,19 @@ void x86_load_linux(X86MachineState *x86ms,
+ }
+
+ setup_data_offset = QEMU_ALIGN_UP(kernel_size, 16);
+- kernel_size = setup_data_offset + sizeof(SetupData) + dtb_size;
++ kernel_size = setup_data_offset + sizeof(struct setup_data) + dtb_size;
+ kernel = g_realloc(kernel, kernel_size);
+
++ stq_p(header + 0x250, prot_addr + setup_data_offset);
+
+- setup_data = (SetupData *)(kernel + setup_data_offset);
+- setup_data->next = cpu_to_le64(first_setup_data);
+- first_setup_data = prot_addr + setup_data_offset;
++ setup_data = (struct setup_data *)(kernel + setup_data_offset);
++ setup_data->next = 0;
+ setup_data->type = cpu_to_le32(SETUP_DTB);
+ setup_data->len = cpu_to_le32(dtb_size);
+
+ load_image_size(dtb_filename, setup_data->data, dtb_size);
+ }
+
+- if (!legacy_no_rng_seed) {
+- setup_data_offset = QEMU_ALIGN_UP(kernel_size, 16);
+- kernel_size = setup_data_offset + sizeof(SetupData) + RNG_SEED_LENGTH;
+- kernel = g_realloc(kernel, kernel_size);
+- setup_data = (SetupData *)(kernel + setup_data_offset);
+- setup_data->next = cpu_to_le64(first_setup_data);
+- first_setup_data = prot_addr + setup_data_offset;
+- setup_data->type = cpu_to_le32(SETUP_RNG_SEED);
+- setup_data->len = cpu_to_le32(RNG_SEED_LENGTH);
+- qemu_guest_getrandom_nofail(setup_data->data, RNG_SEED_LENGTH);
+- qemu_register_reset_nosnapshotload(reset_rng_seed, setup_data);
+- fw_cfg_add_bytes_callback(fw_cfg, FW_CFG_KERNEL_DATA, reset_rng_seed, NULL,
+- setup_data, kernel, kernel_size, true);
+- } else {
+- fw_cfg_add_bytes(fw_cfg, FW_CFG_KERNEL_DATA, kernel, kernel_size);
+- }
+-
+- fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, prot_addr);
+- fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size);
+- sev_load_ctx.kernel_data = (char *)kernel;
+- sev_load_ctx.kernel_size = kernel_size;
+-
+ /*
+ * If we're starting an encrypted VM, it will be OVMF based, which uses the
+ * efi stub for booting and doesn't require any values to be placed in the
+@@ -1135,20 +1085,16 @@ void x86_load_linux(X86MachineState *x86ms,
+ * file the user passed in.
+ */
+ if (!sev_enabled()) {
+- SetupDataFixup *fixup = g_malloc(sizeof(*fixup));
+-
+ memcpy(setup, header, MIN(sizeof(header), setup_size));
+- /* Offset 0x250 is a pointer to the first setup_data link. */
+- fixup->pos = setup + 0x250;
+- fixup->orig_val = ldq_p(fixup->pos);
+- fixup->new_val = first_setup_data;
+- fixup->addr = cpu_to_le32(real_addr);
+- fw_cfg_add_bytes_callback(fw_cfg, FW_CFG_SETUP_ADDR, fixup_setup_data, NULL,
+- fixup, &fixup->addr, sizeof(fixup->addr), true);
+- qemu_register_reset(reset_setup_data, fixup);
+- } else {
+- fw_cfg_add_i32(fw_cfg, FW_CFG_SETUP_ADDR, real_addr);
+ }
++
++ fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, prot_addr);
++ fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size);
++ fw_cfg_add_bytes(fw_cfg, FW_CFG_KERNEL_DATA, kernel, kernel_size);
++ sev_load_ctx.kernel_data = (char *)kernel;
++ sev_load_ctx.kernel_size = kernel_size;
++
++ fw_cfg_add_i32(fw_cfg, FW_CFG_SETUP_ADDR, real_addr);
+ fw_cfg_add_i32(fw_cfg, FW_CFG_SETUP_SIZE, setup_size);
+ fw_cfg_add_bytes(fw_cfg, FW_CFG_SETUP_DATA, setup, setup_size);
+ sev_load_ctx.setup_data = (char *)setup;
+diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c
+index e54276dc1d..1d3e058452 100644
+--- a/hw/nvme/ctrl.c
++++ b/hw/nvme/ctrl.c
+@@ -1331,10 +1331,23 @@ static inline void nvme_blk_write(BlockBackend *blk, int64_t offset,
+ }
+ }
+
++static void nvme_update_cq_eventidx(const NvmeCQueue *cq)
++{
++ uint32_t v = cpu_to_le32(cq->head);
++
++ //not in 7.2: trace_pci_nvme_update_cq_eventidx(cq->cqid, cq->head);
++
++ pci_dma_write(PCI_DEVICE(cq->ctrl), cq->ei_addr, &v, sizeof(v));
++}
++
+ static void nvme_update_cq_head(NvmeCQueue *cq)
+ {
+- pci_dma_read(&cq->ctrl->parent_obj, cq->db_addr, &cq->head,
+- sizeof(cq->head));
++ uint32_t v;
++
++ pci_dma_read(&cq->ctrl->parent_obj, cq->db_addr, &v, sizeof(v));
++
++ cq->head = le32_to_cpu(v);
++
+ trace_pci_nvme_shadow_doorbell_cq(cq->cqid, cq->head);
+ }
+
+@@ -1351,6 +1364,7 @@ static void nvme_post_cqes(void *opaque)
+ hwaddr addr;
+
+ if (n->dbbuf_enabled) {
++ nvme_update_cq_eventidx(cq);
+ nvme_update_cq_head(cq);
+ }
+
+@@ -6141,15 +6155,21 @@ static uint16_t nvme_admin_cmd(NvmeCtrl *n, NvmeRequest *req)
+
+ static void nvme_update_sq_eventidx(const NvmeSQueue *sq)
+ {
+- pci_dma_write(&sq->ctrl->parent_obj, sq->ei_addr, &sq->tail,
+- sizeof(sq->tail));
++ uint32_t v = cpu_to_le32(sq->tail);
++
++ pci_dma_write(&sq->ctrl->parent_obj, sq->ei_addr, &v, sizeof(v));
++
+ trace_pci_nvme_eventidx_sq(sq->sqid, sq->tail);
+ }
+
+ static void nvme_update_sq_tail(NvmeSQueue *sq)
+ {
+- pci_dma_read(&sq->ctrl->parent_obj, sq->db_addr, &sq->tail,
+- sizeof(sq->tail));
++ uint32_t v;
++
++ pci_dma_read(&sq->ctrl->parent_obj, sq->db_addr, &v, sizeof(v));
++
++ sq->tail = le32_to_cpu(v);
++
+ trace_pci_nvme_shadow_doorbell_sq(sq->sqid, sq->tail);
+ }
+
+diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c
+index 6edf5ea3e9..371a45dfe2 100644
+--- a/hw/nvram/fw_cfg.c
++++ b/hw/nvram/fw_cfg.c
+@@ -693,12 +693,12 @@ static const VMStateDescription vmstate_fw_cfg = {
+ }
+ };
+
+-void fw_cfg_add_bytes_callback(FWCfgState *s, uint16_t key,
+- FWCfgCallback select_cb,
+- FWCfgWriteCallback write_cb,
+- void *callback_opaque,
+- void *data, size_t len,
+- bool read_only)
++static void fw_cfg_add_bytes_callback(FWCfgState *s, uint16_t key,
++ FWCfgCallback select_cb,
++ FWCfgWriteCallback write_cb,
++ void *callback_opaque,
++ void *data, size_t len,
++ bool read_only)
+ {
+ int arch = !!(key & FW_CFG_ARCH_LOCAL);
+
+diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c
+index b4243de735..66a020999b 100644
+--- a/hw/smbios/smbios.c
++++ b/hw/smbios/smbios.c
+@@ -749,14 +749,16 @@ static void smbios_build_type_4_table(MachineState *ms, unsigned instance)
+ t->core_count = (ms->smp.cores > 255) ? 0xFF : ms->smp.cores;
+ t->core_enabled = t->core_count;
+
+- t->core_count2 = t->core_enabled2 = cpu_to_le16(ms->smp.cores);
+-
+ t->thread_count = (ms->smp.threads > 255) ? 0xFF : ms->smp.threads;
+- t->thread_count2 = cpu_to_le16(ms->smp.threads);
+
+ t->processor_characteristics = cpu_to_le16(0x02); /* Unknown */
+ t->processor_family2 = cpu_to_le16(0x01); /* Other */
+
++ if (tbl_len == SMBIOS_TYPE_4_LEN_V30) {
++ t->core_count2 = t->core_enabled2 = cpu_to_le16(ms->smp.cores);
++ t->thread_count2 = cpu_to_le16(ms->smp.threads);
++ }
++
+ SMBIOS_BUILD_TABLE_POST;
+ smbios_type4_count++;
+ }
+diff --git a/hw/timer/hpet.c b/hw/timer/hpet.c
+index 9520471be2..5f88ffdef8 100644
+--- a/hw/timer/hpet.c
++++ b/hw/timer/hpet.c
+@@ -352,6 +352,16 @@ static const VMStateDescription vmstate_hpet = {
+ }
+ };
+
++static void hpet_arm(HPETTimer *t, uint64_t ticks)
++{
++ if (ticks < ns_to_ticks(INT64_MAX / 2)) {
++ timer_mod(t->qemu_timer,
++ qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + ticks_to_ns(ticks));
++ } else {
++ timer_del(t->qemu_timer);
++ }
++}
++
+ /*
+ * timer expiration callback
+ */
+@@ -374,13 +384,11 @@ static void hpet_timer(void *opaque)
+ }
+ }
+ diff = hpet_calculate_diff(t, cur_tick);
+- timer_mod(t->qemu_timer,
+- qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + (int64_t)ticks_to_ns(diff));
++ hpet_arm(t, diff);
+ } else if (t->config & HPET_TN_32BIT && !timer_is_periodic(t)) {
+ if (t->wrap_flag) {
+ diff = hpet_calculate_diff(t, cur_tick);
+- timer_mod(t->qemu_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
+- (int64_t)ticks_to_ns(diff));
++ hpet_arm(t, diff);
+ t->wrap_flag = 0;
+ }
+ }
+@@ -407,8 +415,7 @@ static void hpet_set_timer(HPETTimer *t)
+ t->wrap_flag = 1;
+ }
+ }
+- timer_mod(t->qemu_timer,
+- qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + (int64_t)ticks_to_ns(diff));
++ hpet_arm(t, diff);
+ }
+
+ static void hpet_del_timer(HPETTimer *t)
+diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c
+index 5bd14cad96..a723073747 100644
+--- a/hw/virtio/vhost-shadow-virtqueue.c
++++ b/hw/virtio/vhost-shadow-virtqueue.c
+@@ -522,7 +522,7 @@ static void vhost_svq_flush(VhostShadowVirtqueue *svq,
+ size_t vhost_svq_poll(VhostShadowVirtqueue *svq)
+ {
+ int64_t start_us = g_get_monotonic_time();
+- uint32_t len;
++ uint32_t len = 0;
+
+ do {
+ if (vhost_svq_more_used(svq)) {
+diff --git a/hw/virtio/vhost-user-gpio.c b/hw/virtio/vhost-user-gpio.c
+index b7b82a1099..97145376eb 100644
+--- a/hw/virtio/vhost-user-gpio.c
++++ b/hw/virtio/vhost-user-gpio.c
+@@ -16,6 +16,7 @@
+ #include "trace.h"
+
+ #define REALIZE_CONNECTION_RETRIES 3
++#define VHOST_NVQS 2
+
+ /* Features required from VirtIO */
+ static const int feature_bits[] = {
+@@ -198,8 +199,7 @@ static void do_vhost_user_cleanup(VirtIODevice *vdev, VHostUserGPIO *gpio)
+ {
+ virtio_delete_queue(gpio->command_vq);
+ virtio_delete_queue(gpio->interrupt_vq);
+- g_free(gpio->vhost_dev.vqs);
+- gpio->vhost_dev.vqs = NULL;
++ g_free(gpio->vhost_vqs);
+ virtio_cleanup(vdev);
+ vhost_user_cleanup(&gpio->vhost_user);
+ }
+@@ -219,6 +219,9 @@ static int vu_gpio_connect(DeviceState *dev, Error **errp)
+ vhost_dev_set_config_notifier(vhost_dev, &gpio_ops);
+ gpio->vhost_user.supports_config = true;
+
++ gpio->vhost_dev.nvqs = VHOST_NVQS;
++ gpio->vhost_dev.vqs = gpio->vhost_vqs;
++
+ ret = vhost_dev_init(vhost_dev, &gpio->vhost_user,
+ VHOST_BACKEND_TYPE_USER, 0, errp);
+ if (ret < 0) {
+@@ -337,10 +340,9 @@ static void vu_gpio_device_realize(DeviceState *dev, Error **errp)
+
+ virtio_init(vdev, VIRTIO_ID_GPIO, sizeof(gpio->config));
+
+- gpio->vhost_dev.nvqs = 2;
+ gpio->command_vq = virtio_add_queue(vdev, 256, vu_gpio_handle_output);
+ gpio->interrupt_vq = virtio_add_queue(vdev, 256, vu_gpio_handle_output);
+- gpio->vhost_dev.vqs = g_new0(struct vhost_virtqueue, gpio->vhost_dev.nvqs);
++ gpio->vhost_vqs = g_new0(struct vhost_virtqueue, VHOST_NVQS);
+
+ gpio->connected = false;
+
+diff --git a/hw/virtio/vhost-user-i2c.c b/hw/virtio/vhost-user-i2c.c
+index dc5c828ba6..60eaf0d95b 100644
+--- a/hw/virtio/vhost-user-i2c.c
++++ b/hw/virtio/vhost-user-i2c.c
+@@ -143,8 +143,6 @@ static void do_vhost_user_cleanup(VirtIODevice *vdev, VHostUserI2C *i2c)
+ vhost_user_cleanup(&i2c->vhost_user);
+ virtio_delete_queue(i2c->vq);
+ virtio_cleanup(vdev);
+- g_free(i2c->vhost_dev.vqs);
+- i2c->vhost_dev.vqs = NULL;
+ }
+
+ static int vu_i2c_connect(DeviceState *dev)
+@@ -228,6 +226,7 @@ static void vu_i2c_device_realize(DeviceState *dev, Error **errp)
+ ret = vhost_dev_init(&i2c->vhost_dev, &i2c->vhost_user,
+ VHOST_BACKEND_TYPE_USER, 0, errp);
+ if (ret < 0) {
++ g_free(i2c->vhost_dev.vqs);
+ do_vhost_user_cleanup(vdev, i2c);
+ }
+
+@@ -239,10 +238,12 @@ static void vu_i2c_device_unrealize(DeviceState *dev)
+ {
+ VirtIODevice *vdev = VIRTIO_DEVICE(dev);
+ VHostUserI2C *i2c = VHOST_USER_I2C(dev);
++ struct vhost_virtqueue *vhost_vqs = i2c->vhost_dev.vqs;
+
+ /* This will stop vhost backend if appropriate. */
+ vu_i2c_set_status(vdev, 0);
+ vhost_dev_cleanup(&i2c->vhost_dev);
++ g_free(vhost_vqs);
+ do_vhost_user_cleanup(vdev, i2c);
+ }
+
+diff --git a/hw/virtio/vhost-user-rng.c b/hw/virtio/vhost-user-rng.c
+index 201a39e220..efc54cd3fb 100644
+--- a/hw/virtio/vhost-user-rng.c
++++ b/hw/virtio/vhost-user-rng.c
+@@ -229,6 +229,7 @@ static void vu_rng_device_realize(DeviceState *dev, Error **errp)
+ return;
+
+ vhost_dev_init_failed:
++ g_free(rng->vhost_dev.vqs);
+ virtio_delete_queue(rng->req_vq);
+ virtio_add_queue_failed:
+ virtio_cleanup(vdev);
+@@ -239,12 +240,12 @@ static void vu_rng_device_unrealize(DeviceState *dev)
+ {
+ VirtIODevice *vdev = VIRTIO_DEVICE(dev);
+ VHostUserRNG *rng = VHOST_USER_RNG(dev);
++ struct vhost_virtqueue *vhost_vqs = rng->vhost_dev.vqs;
+
+ vu_rng_set_status(vdev, 0);
+
+ vhost_dev_cleanup(&rng->vhost_dev);
+- g_free(rng->vhost_dev.vqs);
+- rng->vhost_dev.vqs = NULL;
++ g_free(vhost_vqs);
+ virtio_delete_queue(rng->req_vq);
+ virtio_cleanup(vdev);
+ vhost_user_cleanup(&rng->vhost_user);
+diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c
+index 7468e44b87..03c78d25d8 100644
+--- a/hw/virtio/vhost-vdpa.c
++++ b/hw/virtio/vhost-vdpa.c
+@@ -707,26 +707,11 @@ static int vhost_vdpa_get_device_id(struct vhost_dev *dev,
+ return ret;
+ }
+
+-static void vhost_vdpa_reset_svq(struct vhost_vdpa *v)
+-{
+- if (!v->shadow_vqs_enabled) {
+- return;
+- }
+-
+- for (unsigned i = 0; i < v->shadow_vqs->len; ++i) {
+- VhostShadowVirtqueue *svq = g_ptr_array_index(v->shadow_vqs, i);
+- vhost_svq_stop(svq);
+- }
+-}
+-
+ static int vhost_vdpa_reset_device(struct vhost_dev *dev)
+ {
+- struct vhost_vdpa *v = dev->opaque;
+ int ret;
+ uint8_t status = 0;
+
+- vhost_vdpa_reset_svq(v);
+-
+ ret = vhost_vdpa_call(dev, VHOST_VDPA_SET_STATUS, &status);
+ trace_vhost_vdpa_reset_device(dev, status);
+ return ret;
+@@ -1088,6 +1073,8 @@ static void vhost_vdpa_svqs_stop(struct vhost_dev *dev)
+
+ for (unsigned i = 0; i < v->shadow_vqs->len; ++i) {
+ VhostShadowVirtqueue *svq = g_ptr_array_index(v->shadow_vqs, i);
++
++ vhost_svq_stop(svq);
+ vhost_vdpa_svq_unmap_rings(dev, svq);
+ }
+ }
+diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
+index 7fb008bc9e..fdcd1a8fdf 100644
+--- a/hw/virtio/vhost.c
++++ b/hw/virtio/vhost.c
+@@ -20,6 +20,7 @@
+ #include "qemu/range.h"
+ #include "qemu/error-report.h"
+ #include "qemu/memfd.h"
++#include "qemu/log.h"
+ #include "standard-headers/linux/vhost_types.h"
+ #include "hw/virtio/virtio-bus.h"
+ #include "hw/virtio/virtio-access.h"
+@@ -106,6 +107,24 @@ static void vhost_dev_sync_region(struct vhost_dev *dev,
+ }
+ }
+
++static bool vhost_dev_has_iommu(struct vhost_dev *dev)
++{
++ VirtIODevice *vdev = dev->vdev;
++
++ /*
++ * For vhost, VIRTIO_F_IOMMU_PLATFORM means the backend support
++ * incremental memory mapping API via IOTLB API. For platform that
++ * does not have IOMMU, there's no need to enable this feature
++ * which may cause unnecessary IOTLB miss/update transactions.
++ */
++ if (vdev) {
++ return virtio_bus_device_iommu_enabled(vdev) &&
++ virtio_host_has_feature(vdev, VIRTIO_F_IOMMU_PLATFORM);
++ } else {
++ return false;
++ }
++}
++
+ static int vhost_sync_dirty_bitmap(struct vhost_dev *dev,
+ MemoryRegionSection *section,
+ hwaddr first,
+@@ -137,8 +156,51 @@ static int vhost_sync_dirty_bitmap(struct vhost_dev *dev,
+ continue;
+ }
+
+- vhost_dev_sync_region(dev, section, start_addr, end_addr, vq->used_phys,
+- range_get_last(vq->used_phys, vq->used_size));
++ if (vhost_dev_has_iommu(dev)) {
++ IOMMUTLBEntry iotlb;
++ hwaddr used_phys = vq->used_phys, used_size = vq->used_size;
++ hwaddr phys, s, offset;
++
++ while (used_size) {
++ rcu_read_lock();
++ iotlb = address_space_get_iotlb_entry(dev->vdev->dma_as,
++ used_phys,
++ true,
++ MEMTXATTRS_UNSPECIFIED);
++ rcu_read_unlock();
++
++ if (!iotlb.target_as) {
++ qemu_log_mask(LOG_GUEST_ERROR, "translation "
++ "failure for used_iova %"PRIx64"\n",
++ used_phys);
++ return -EINVAL;
++ }
++
++ offset = used_phys & iotlb.addr_mask;
++ phys = iotlb.translated_addr + offset;
++
++ /*
++ * Distance from start of used ring until last byte of
++ * IOMMU page.
++ */
++ s = iotlb.addr_mask - offset;
++ /*
++ * Size of used ring, or of the part of it until end
++ * of IOMMU page. To avoid zero result, do the adding
++ * outside of MIN().
++ */
++ s = MIN(s, used_size - 1) + 1;
++
++ vhost_dev_sync_region(dev, section, start_addr, end_addr, phys,
++ range_get_last(phys, s));
++ used_size -= s;
++ used_phys += s;
++ }
++ } else {
++ vhost_dev_sync_region(dev, section, start_addr,
++ end_addr, vq->used_phys,
++ range_get_last(vq->used_phys, vq->used_size));
++ }
+ }
+ return 0;
+ }
+@@ -306,24 +368,6 @@ static inline void vhost_dev_log_resize(struct vhost_dev *dev, uint64_t size)
+ dev->log_size = size;
+ }
+
+-static bool vhost_dev_has_iommu(struct vhost_dev *dev)
+-{
+- VirtIODevice *vdev = dev->vdev;
+-
+- /*
+- * For vhost, VIRTIO_F_IOMMU_PLATFORM means the backend support
+- * incremental memory mapping API via IOTLB API. For platform that
+- * does not have IOMMU, there's no need to enable this feature
+- * which may cause unnecessary IOTLB miss/update transactions.
+- */
+- if (vdev) {
+- return virtio_bus_device_iommu_enabled(vdev) &&
+- virtio_host_has_feature(vdev, VIRTIO_F_IOMMU_PLATFORM);
+- } else {
+- return false;
+- }
+-}
+-
+ static void *vhost_memory_map(struct vhost_dev *dev, hwaddr addr,
+ hwaddr *plen, bool is_write)
+ {
+diff --git a/hw/virtio/virtio-mem.c b/hw/virtio/virtio-mem.c
+index ed170def48..56db586c89 100644
+--- a/hw/virtio/virtio-mem.c
++++ b/hw/virtio/virtio-mem.c
+@@ -235,7 +235,7 @@ static int virtio_mem_for_each_plugged_section(const VirtIOMEM *vmem,
+ uint64_t offset, size;
+ int ret = 0;
+
+- first_bit = s->offset_within_region / vmem->bitmap_size;
++ first_bit = s->offset_within_region / vmem->block_size;
+ first_bit = find_next_bit(vmem->bitmap, vmem->bitmap_size, first_bit);
+ while (first_bit < vmem->bitmap_size) {
+ MemoryRegionSection tmp = *s;
+@@ -267,7 +267,7 @@ static int virtio_mem_for_each_unplugged_section(const VirtIOMEM *vmem,
+ uint64_t offset, size;
+ int ret = 0;
+
+- first_bit = s->offset_within_region / vmem->bitmap_size;
++ first_bit = s->offset_within_region / vmem->block_size;
+ first_bit = find_next_zero_bit(vmem->bitmap, vmem->bitmap_size, first_bit);
+ while (first_bit < vmem->bitmap_size) {
+ MemoryRegionSection tmp = *s;
+@@ -341,7 +341,7 @@ static int virtio_mem_notify_plug(VirtIOMEM *vmem, uint64_t offset,
+ if (ret) {
+ /* Notify all already-notified listeners. */
+ QLIST_FOREACH(rdl2, &vmem->rdl_list, next) {
+- MemoryRegionSection tmp = *rdl->section;
++ MemoryRegionSection tmp = *rdl2->section;
+
+ if (rdl2 == rdl) {
+ break;
+diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
+index c95333514e..0c76e82626 100644
+--- a/include/hw/i386/pc.h
++++ b/include/hw/i386/pc.h
+@@ -128,9 +128,6 @@ struct PCMachineClass {
+
+ /* create kvmclock device even when KVM PV features are not exposed */
+ bool kvmclock_create_always;
+-
+- /* skip passing an rng seed for legacy machines */
+- bool legacy_no_rng_seed;
+ };
+
+ #define TYPE_PC_MACHINE "generic-pc-machine"
+diff --git a/include/hw/i386/x86.h b/include/hw/i386/x86.h
+index 62fa5774f8..df82c5fd42 100644
+--- a/include/hw/i386/x86.h
++++ b/include/hw/i386/x86.h
+@@ -126,8 +126,7 @@ void x86_bios_rom_init(MachineState *ms, const char *default_firmware,
+ void x86_load_linux(X86MachineState *x86ms,
+ FWCfgState *fw_cfg,
+ int acpi_data_size,
+- bool pvh_enabled,
+- bool legacy_no_rng_seed);
++ bool pvh_enabled);
+
+ bool x86_machine_is_smm_enabled(const X86MachineState *x86ms);
+ bool x86_machine_is_acpi_enabled(const X86MachineState *x86ms);
+diff --git a/include/hw/nvram/fw_cfg.h b/include/hw/nvram/fw_cfg.h
+index 2e503904dc..c1f81a5f13 100644
+--- a/include/hw/nvram/fw_cfg.h
++++ b/include/hw/nvram/fw_cfg.h
+@@ -117,28 +117,6 @@ struct FWCfgMemState {
+ */
+ void fw_cfg_add_bytes(FWCfgState *s, uint16_t key, void *data, size_t len);
+
+-/**
+- * fw_cfg_add_bytes_callback:
+- * @s: fw_cfg device being modified
+- * @key: selector key value for new fw_cfg item
+- * @select_cb: callback function when selecting
+- * @write_cb: callback function after a write
+- * @callback_opaque: argument to be passed into callback function
+- * @data: pointer to start of item data
+- * @len: size of item data
+- * @read_only: is file read only
+- *
+- * Add a new fw_cfg item, available by selecting the given key, as a raw
+- * "blob" of the given size. The data referenced by the starting pointer
+- * is only linked, NOT copied, into the data structure of the fw_cfg device.
+- */
+-void fw_cfg_add_bytes_callback(FWCfgState *s, uint16_t key,
+- FWCfgCallback select_cb,
+- FWCfgWriteCallback write_cb,
+- void *callback_opaque,
+- void *data, size_t len,
+- bool read_only);
+-
+ /**
+ * fw_cfg_add_string:
+ * @s: fw_cfg device being modified
+diff --git a/include/hw/virtio/vhost-user-gpio.h b/include/hw/virtio/vhost-user-gpio.h
+index a9305c5e6c..a9d3f9b049 100644
+--- a/include/hw/virtio/vhost-user-gpio.h
++++ b/include/hw/virtio/vhost-user-gpio.h
+@@ -23,7 +23,7 @@ struct VHostUserGPIO {
+ VirtIODevice parent_obj;
+ CharBackend chardev;
+ struct virtio_gpio_config config;
+- struct vhost_virtqueue *vhost_vq;
++ struct vhost_virtqueue *vhost_vqs;
+ struct vhost_dev vhost_dev;
+ VhostUserState vhost_user;
+ VirtQueue *command_vq;
+diff --git a/meson.build b/meson.build
+index 5c6b5a1c75..b88867ca9d 100644
+--- a/meson.build
++++ b/meson.build
+@@ -2777,7 +2777,7 @@ config_host_data.set('CONFIG_SLIRP', slirp.found())
+ genh += configure_file(output: 'config-host.h', configuration: config_host_data)
+
+ hxtool = find_program('scripts/hxtool')
+-shaderinclude = find_program('scripts/shaderinclude.pl')
++shaderinclude = find_program('scripts/shaderinclude.py')
+ qapi_gen = find_program('scripts/qapi-gen.py')
+ qapi_gen_depends = [ meson.current_source_dir() / 'scripts/qapi/__init__.py',
+ meson.current_source_dir() / 'scripts/qapi/commands.py',
+diff --git a/migration/ram.c b/migration/ram.c
+index 1338e47665..f25ebd9620 100644
+--- a/migration/ram.c
++++ b/migration/ram.c
+@@ -1765,13 +1765,15 @@ out:
+ static inline void populate_read_range(RAMBlock *block, ram_addr_t offset,
+ ram_addr_t size)
+ {
++ const ram_addr_t end = offset + size;
++
+ /*
+ * We read one byte of each page; this will preallocate page tables if
+ * required and populate the shared zeropage on MAP_PRIVATE anonymous memory
+ * where no page was populated yet. This might require adaption when
+ * supporting other mappings, like shmem.
+ */
+- for (; offset < size; offset += block->page_size) {
++ for (; offset < end; offset += block->page_size) {
+ char tmp = *((char *)block->host + offset);
+
+ /* Don't optimize the read out */
+@@ -1885,13 +1887,14 @@ int ram_write_tracking_start(void)
+ block->max_length, UFFDIO_REGISTER_MODE_WP, NULL)) {
+ goto fail;
+ }
++ block->flags |= RAM_UF_WRITEPROTECT;
++ memory_region_ref(block->mr);
++
+ /* Apply UFFD write protection to the block memory range */
+ if (uffd_change_protection(rs->uffdio_fd, block->host,
+ block->max_length, true, false)) {
+ goto fail;
+ }
+- block->flags |= RAM_UF_WRITEPROTECT;
+- memory_region_ref(block->mr);
+
+ trace_ram_write_tracking_ramblock_start(block->idstr, block->page_size,
+ block->host, block->max_length);
+diff --git a/scripts/shaderinclude.pl b/scripts/shaderinclude.pl
+deleted file mode 100644
+index cd3bb40b12..0000000000
+--- a/scripts/shaderinclude.pl
++++ /dev/null
+@@ -1,16 +0,0 @@
+-#!/usr/bin/env perl
+-use strict;
+-use warnings;
+-
+-my $file = shift;
+-open FILE, "<", $file or die "open $file: $!";
+-my $name = $file;
+-$name =~ s|.*/||;
+-$name =~ s/[-.]/_/g;
+-print "static GLchar ${name}_src[] =\n";
+-while (<FILE>) {
+- chomp;
+- printf " \"%s\\n\"\n", $_;
+-}
+-print " \"\\n\";\n";
+-close FILE;
+diff --git a/scripts/shaderinclude.py b/scripts/shaderinclude.py
+new file mode 100644
+index 0000000000..ab2aade2cd
+--- /dev/null
++++ b/scripts/shaderinclude.py
+@@ -0,0 +1,26 @@
++#!/usr/bin/env python3
++#
++# Copyright (C) 2023 Red Hat, Inc.
++#
++# SPDX-License-Identifier: GPL-2.0-or-later
++
++import sys
++import os
++
++
++def main(args):
++ file_path = args[1]
++ basename = os.path.basename(file_path)
++ varname = basename.replace('-', '_').replace('.', '_')
++
++ with os.fdopen(sys.stdout.fileno(), "wt", closefd=False, newline='\n') as stdout:
++ with open(file_path, "r", encoding='utf-8') as file:
++ print(f'static GLchar {varname}_src[] =', file=stdout)
++ for line in file:
++ line = line.rstrip()
++ print(f' "{line}\\n"', file=stdout)
++ print(' "\\n";', file=stdout)
++
++
++if __name__ == '__main__':
++ sys.exit(main(sys.argv))
+diff --git a/scripts/symlink-install-tree.py b/scripts/symlink-install-tree.py
+index a5bf0b0d6d..67cb86dd52 100644
+--- a/scripts/symlink-install-tree.py
++++ b/scripts/symlink-install-tree.py
+@@ -17,7 +17,6 @@ def destdir_join(d1: str, d2: str) -> str:
+ out = subprocess.run([*introspect.split(' '), '--installed'],
+ stdout=subprocess.PIPE, check=True).stdout
+ for source, dest in json.loads(out).items():
+- assert os.path.isabs(source)
+ bundle_dest = destdir_join('qemu-bundle', dest)
+ path = os.path.dirname(bundle_dest)
+ try:
+diff --git a/subprojects/libvhost-user/libvhost-user.c b/subprojects/libvhost-user/libvhost-user.c
+index d6ee6e7d91..b17e82b2b0 100644
+--- a/subprojects/libvhost-user/libvhost-user.c
++++ b/subprojects/libvhost-user/libvhost-user.c
+@@ -2547,6 +2547,10 @@ virtqueue_alloc_element(size_t sz,
+
+ assert(sz >= sizeof(VuVirtqElement));
+ elem = malloc(out_sg_end);
++ if (!elem) {
++ DPRINT("%s: failed to malloc virtqueue element\n", __func__);
++ return NULL;
++ }
+ elem->out_num = out_num;
+ elem->in_num = in_num;
+ elem->in_sg = (void *)elem + in_sg_ofs;
+@@ -2633,6 +2637,9 @@ vu_queue_map_desc(VuDev *dev, VuVirtq *vq, unsigned int idx, size_t sz)
+
+ /* Now copy what we have collected and mapped */
+ elem = virtqueue_alloc_element(sz, out_num, in_num);
++ if (!elem) {
++ return NULL;
++ }
+ elem->index = idx;
+ for (i = 0; i < out_num; i++) {
+ elem->out_sg[i] = iov[i];
+diff --git a/target/arm/helper.c b/target/arm/helper.c
+index d8c8223ec3..22bc935242 100644
+--- a/target/arm/helper.c
++++ b/target/arm/helper.c
+@@ -1820,6 +1820,9 @@ static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
+ if (cpu_isar_feature(aa64_sme, cpu)) {
+ valid_mask |= SCR_ENTP2;
+ }
++ if (cpu_isar_feature(aa64_hcx, cpu)) {
++ valid_mask |= SCR_HXEN;
++ }
+ } else {
+ valid_mask &= ~(SCR_RW | SCR_ST);
+ if (cpu_isar_feature(aa32_ras, cpu)) {
+diff --git a/target/arm/ptw.c b/target/arm/ptw.c
+index f812734bfb..0b16068557 100644
+--- a/target/arm/ptw.c
++++ b/target/arm/ptw.c
+@@ -238,8 +238,8 @@ static bool S1_ptw_translate(CPUARMState *env, S1Translate *ptw,
+ };
+ GetPhysAddrResult s2 = { };
+
+- if (!get_phys_addr_lpae(env, &s2ptw, addr, MMU_DATA_LOAD,
+- false, &s2, fi)) {
++ if (get_phys_addr_lpae(env, &s2ptw, addr, MMU_DATA_LOAD,
++ false, &s2, fi)) {
+ goto fail;
+ }
+ ptw->out_phys = s2.f.phys_addr;
+@@ -266,7 +266,7 @@ static bool S1_ptw_translate(CPUARMState *env, S1Translate *ptw,
+ if (unlikely(flags & TLB_INVALID_MASK)) {
+ goto fail;
+ }
+- ptw->out_phys = full->phys_addr;
++ ptw->out_phys = full->phys_addr | (addr & ~TARGET_PAGE_MASK);
+ ptw->out_rw = full->prot & PAGE_WRITE;
+ pte_attrs = full->pte_attrs;
+ pte_secure = full->attrs.secure;
+diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
+index 1afeadf9c8..521fc9b969 100644
+--- a/target/arm/sve_helper.c
++++ b/target/arm/sve_helper.c
+@@ -5354,15 +5354,10 @@ bool sve_probe_page(SVEHostPage *info, bool nofault, CPUARMState *env,
+ #ifdef CONFIG_USER_ONLY
+ flags = probe_access_flags(env, addr, access_type, mmu_idx, nofault,
+ &info->host, retaddr);
+- memset(&info->attrs, 0, sizeof(info->attrs));
+- /* Require both ANON and MTE; see allocation_tag_mem(). */
+- info->tagged = (flags & PAGE_ANON) && (flags & PAGE_MTE);
+ #else
+ CPUTLBEntryFull *full;
+ flags = probe_access_full(env, addr, access_type, mmu_idx, nofault,
+ &info->host, &full, retaddr);
+- info->attrs = full->attrs;
+- info->tagged = full->pte_attrs == 0xf0;
+ #endif
+ info->flags = flags;
+
+@@ -5371,6 +5366,15 @@ bool sve_probe_page(SVEHostPage *info, bool nofault, CPUARMState *env,
+ return false;
+ }
+
++#ifdef CONFIG_USER_ONLY
++ memset(&info->attrs, 0, sizeof(info->attrs));
++ /* Require both ANON and MTE; see allocation_tag_mem(). */
++ info->tagged = (flags & PAGE_ANON) && (flags & PAGE_MTE);
++#else
++ info->attrs = full->attrs;
++ info->tagged = full->pte_attrs == 0xf0;
++#endif
++
+ /* Ensure that info->host[] is relative to addr, not addr + mem_off. */
+ info->host -= mem_off;
+ return true;
+diff --git a/target/arm/translate.c b/target/arm/translate.c
+index 74a903072f..1dcaefb8e7 100644
+--- a/target/arm/translate.c
++++ b/target/arm/translate.c
+@@ -1184,7 +1184,7 @@ static inline void gen_hlt(DisasContext *s, int imm)
+ * semihosting, to provide some semblance of security
+ * (and for consistency with our 32-bit semihosting).
+ */
+- if (semihosting_enabled(s->current_el != 0) &&
++ if (semihosting_enabled(s->current_el == 0) &&
+ (imm == (s->thumb ? 0x3c : 0xf000))) {
+ gen_exception_internal_insn(s, EXCP_SEMIHOST);
+ return;
+diff --git a/target/i386/tcg/emit.c.inc b/target/i386/tcg/emit.c.inc
+index 7037ff91c6..7296f3952c 100644
+--- a/target/i386/tcg/emit.c.inc
++++ b/target/i386/tcg/emit.c.inc
+@@ -1015,6 +1015,7 @@ VSIB_AVX(VPGATHERQ, vpgatherq)
+
+ static void gen_ADCOX(DisasContext *s, CPUX86State *env, MemOp ot, int cc_op)
+ {
++ int opposite_cc_op;
+ TCGv carry_in = NULL;
+ TCGv carry_out = (cc_op == CC_OP_ADCX ? cpu_cc_dst : cpu_cc_src2);
+ TCGv zero;
+@@ -1022,14 +1023,8 @@ static void gen_ADCOX(DisasContext *s, CPUX86State *env, MemOp ot, int cc_op)
+ if (cc_op == s->cc_op || s->cc_op == CC_OP_ADCOX) {
+ /* Re-use the carry-out from a previous round. */
+ carry_in = carry_out;
+- cc_op = s->cc_op;
+- } else if (s->cc_op == CC_OP_ADCX || s->cc_op == CC_OP_ADOX) {
+- /* Merge with the carry-out from the opposite instruction. */
+- cc_op = CC_OP_ADCOX;
+- }
+-
+- /* If we don't have a carry-in, get it out of EFLAGS. */
+- if (!carry_in) {
++ } else {
++ /* We don't have a carry-in, get it out of EFLAGS. */
+ if (s->cc_op != CC_OP_ADCX && s->cc_op != CC_OP_ADOX) {
+ gen_compute_eflags(s);
+ }
+@@ -1053,7 +1048,14 @@ static void gen_ADCOX(DisasContext *s, CPUX86State *env, MemOp ot, int cc_op)
+ tcg_gen_add2_tl(s->T0, carry_out, s->T0, carry_out, s->T1, zero);
+ break;
+ }
+- set_cc_op(s, cc_op);
++
++ opposite_cc_op = cc_op == CC_OP_ADCX ? CC_OP_ADOX : CC_OP_ADCX;
++ if (s->cc_op == CC_OP_ADCOX || s->cc_op == opposite_cc_op) {
++ /* Merge with the carry-out from the opposite instruction. */
++ set_cc_op(s, CC_OP_ADCOX);
++ } else {
++ set_cc_op(s, cc_op);
++ }
+ }
+
+ static void gen_ADCX(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+@@ -1078,30 +1080,30 @@ static void gen_ANDN(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+ static void gen_BEXTR(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+ {
+ MemOp ot = decode->op[0].ot;
+- TCGv bound, zero;
++ TCGv bound = tcg_constant_tl(ot == MO_64 ? 63 : 31);
++ TCGv zero = tcg_constant_tl(0);
++ TCGv mone = tcg_constant_tl(-1);
+
+ /*
+ * Extract START, and shift the operand.
+ * Shifts larger than operand size get zeros.
+ */
+ tcg_gen_ext8u_tl(s->A0, s->T1);
++ if (TARGET_LONG_BITS == 64 && ot == MO_32) {
++ tcg_gen_ext32u_tl(s->T0, s->T0);
++ }
+ tcg_gen_shr_tl(s->T0, s->T0, s->A0);
+
+- bound = tcg_constant_tl(ot == MO_64 ? 63 : 31);
+- zero = tcg_constant_tl(0);
+ tcg_gen_movcond_tl(TCG_COND_LEU, s->T0, s->A0, bound, s->T0, zero);
+
+ /*
+- * Extract the LEN into a mask. Lengths larger than
+- * operand size get all ones.
++ * Extract the LEN into an inverse mask. Lengths larger than
++ * operand size get all zeros, length 0 gets all ones.
+ */
+ tcg_gen_extract_tl(s->A0, s->T1, 8, 8);
+- tcg_gen_movcond_tl(TCG_COND_LEU, s->A0, s->A0, bound, s->A0, bound);
+-
+- tcg_gen_movi_tl(s->T1, 1);
+- tcg_gen_shl_tl(s->T1, s->T1, s->A0);
+- tcg_gen_subi_tl(s->T1, s->T1, 1);
+- tcg_gen_and_tl(s->T0, s->T0, s->T1);
++ tcg_gen_shl_tl(s->T1, mone, s->A0);
++ tcg_gen_movcond_tl(TCG_COND_LEU, s->T1, s->A0, bound, s->T1, zero);
++ tcg_gen_andc_tl(s->T0, s->T0, s->T1);
+
+ gen_op_update1_cc(s);
+ set_cc_op(s, CC_OP_LOGICB + ot);
+@@ -1111,6 +1113,7 @@ static void gen_BLSI(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+ {
+ MemOp ot = decode->op[0].ot;
+
++ tcg_gen_mov_tl(cpu_cc_src, s->T0);
+ tcg_gen_neg_tl(s->T1, s->T0);
+ tcg_gen_and_tl(s->T0, s->T0, s->T1);
+ tcg_gen_mov_tl(cpu_cc_dst, s->T0);
+@@ -1121,6 +1124,7 @@ static void gen_BLSMSK(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode
+ {
+ MemOp ot = decode->op[0].ot;
+
++ tcg_gen_mov_tl(cpu_cc_src, s->T0);
+ tcg_gen_subi_tl(s->T1, s->T0, 1);
+ tcg_gen_xor_tl(s->T0, s->T0, s->T1);
+ tcg_gen_mov_tl(cpu_cc_dst, s->T0);
+@@ -1131,6 +1135,7 @@ static void gen_BLSR(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+ {
+ MemOp ot = decode->op[0].ot;
+
++ tcg_gen_mov_tl(cpu_cc_src, s->T0);
+ tcg_gen_subi_tl(s->T1, s->T0, 1);
+ tcg_gen_and_tl(s->T0, s->T0, s->T1);
+ tcg_gen_mov_tl(cpu_cc_dst, s->T0);
+@@ -1140,20 +1145,20 @@ static void gen_BLSR(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+ static void gen_BZHI(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+ {
+ MemOp ot = decode->op[0].ot;
+- TCGv bound;
++ TCGv bound = tcg_constant_tl(ot == MO_64 ? 63 : 31);
++ TCGv zero = tcg_constant_tl(0);
++ TCGv mone = tcg_constant_tl(-1);
+
+- tcg_gen_ext8u_tl(s->T1, cpu_regs[s->vex_v]);
+- bound = tcg_constant_tl(ot == MO_64 ? 63 : 31);
++ tcg_gen_ext8u_tl(s->T1, s->T1);
+
+ /*
+ * Note that since we're using BMILG (in order to get O
+ * cleared) we need to store the inverse into C.
+ */
+- tcg_gen_setcond_tl(TCG_COND_LT, cpu_cc_src, s->T1, bound);
+- tcg_gen_movcond_tl(TCG_COND_GT, s->T1, s->T1, bound, bound, s->T1);
++ tcg_gen_setcond_tl(TCG_COND_LEU, cpu_cc_src, s->T1, bound);
+
+- tcg_gen_movi_tl(s->A0, -1);
+- tcg_gen_shl_tl(s->A0, s->A0, s->T1);
++ tcg_gen_shl_tl(s->A0, mone, s->T1);
++ tcg_gen_movcond_tl(TCG_COND_LEU, s->A0, s->T1, bound, s->A0, zero);
+ tcg_gen_andc_tl(s->T0, s->T0, s->A0);
+
+ gen_op_update1_cc(s);
+diff --git a/target/riscv/translate.c b/target/riscv/translate.c
+index db123da5ec..1ed4bb5ec3 100644
+--- a/target/riscv/translate.c
++++ b/target/riscv/translate.c
+@@ -1064,14 +1064,10 @@ static void decode_opc(CPURISCVState *env, DisasContext *ctx, uint16_t opcode)
+
+ /* Check for compressed insn */
+ if (insn_len(opcode) == 2) {
+- if (!has_ext(ctx, RVC)) {
+- gen_exception_illegal(ctx);
+- } else {
+- ctx->opcode = opcode;
+- ctx->pc_succ_insn = ctx->base.pc_next + 2;
+- if (decode_insn16(ctx, opcode)) {
+- return;
+- }
++ ctx->opcode = opcode;
++ ctx->pc_succ_insn = ctx->base.pc_next + 2;
++ if (has_ext(ctx, RVC) && decode_insn16(ctx, opcode)) {
++ return;
+ }
+ } else {
+ uint32_t opcode32 = opcode;
+diff --git a/target/sh4/cpu.c b/target/sh4/cpu.c
+index 453268392b..827cee25af 100644
+--- a/target/sh4/cpu.c
++++ b/target/sh4/cpu.c
+@@ -47,7 +47,7 @@ static void superh_cpu_synchronize_from_tb(CPUState *cs,
+ SuperHCPU *cpu = SUPERH_CPU(cs);
+
+ cpu->env.pc = tb_pc(tb);
+- cpu->env.flags = tb->flags;
++ cpu->env.flags = tb->flags & TB_FLAG_ENVFLAGS_MASK;
+ }
+
+ static void superh_restore_state_to_opc(CPUState *cs,
+diff --git a/tests/tcg/Makefile.target b/tests/tcg/Makefile.target
+index 75257f2b29..14bc013181 100644
+--- a/tests/tcg/Makefile.target
++++ b/tests/tcg/Makefile.target
+@@ -117,6 +117,8 @@ endif
+
+ %: %.c
+ $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $< -o $@ $(LDFLAGS)
++%: %.S
++ $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $< -o $@ $(LDFLAGS)
+ else
+ # For softmmu targets we include a different Makefile fragement as the
+ # build options for bare programs are usually pretty different. They
+diff --git a/tests/tcg/i386/Makefile.target b/tests/tcg/i386/Makefile.target
+index 81831cafbc..bafd8c2180 100644
+--- a/tests/tcg/i386/Makefile.target
++++ b/tests/tcg/i386/Makefile.target
+@@ -14,7 +14,7 @@ config-cc.mak: Makefile
+ I386_SRCS=$(notdir $(wildcard $(I386_SRC)/*.c))
+ ALL_X86_TESTS=$(I386_SRCS:.c=)
+ SKIP_I386_TESTS=test-i386-ssse3 test-avx test-3dnow test-mmx
+-X86_64_TESTS:=$(filter test-i386-bmi2 $(SKIP_I386_TESTS), $(ALL_X86_TESTS))
++X86_64_TESTS:=$(filter test-i386-adcox test-i386-bmi2 $(SKIP_I386_TESTS), $(ALL_X86_TESTS))
+
+ test-i386-sse-exceptions: CFLAGS += -msse4.1 -mfpmath=sse
+ run-test-i386-sse-exceptions: QEMU_OPTS += -cpu max
+@@ -28,6 +28,10 @@ test-i386-bmi2: CFLAGS=-O2
+ run-test-i386-bmi2: QEMU_OPTS += -cpu max
+ run-plugin-test-i386-bmi2-%: QEMU_OPTS += -cpu max
+
++test-i386-adcox: CFLAGS=-O2
++run-test-i386-adcox: QEMU_OPTS += -cpu max
++run-plugin-test-i386-adcox-%: QEMU_OPTS += -cpu max
++
+ #
+ # hello-i386 is a barebones app
+ #
+diff --git a/tests/tcg/i386/test-i386-adcox.c b/tests/tcg/i386/test-i386-adcox.c
+new file mode 100644
+index 0000000000..16169efff8
+--- /dev/null
++++ b/tests/tcg/i386/test-i386-adcox.c
+@@ -0,0 +1,75 @@
++/* See if various BMI2 instructions give expected results */
++#include <assert.h>
++#include <stdint.h>
++#include <stdio.h>
++
++#define CC_C 1
++#define CC_O (1 << 11)
++
++#ifdef __x86_64__
++#define REG uint64_t
++#else
++#define REG uint32_t
++#endif
++
++void test_adox_adcx(uint32_t in_c, uint32_t in_o, REG adcx_operand, REG adox_operand)
++{
++ REG flags;
++ REG out_adcx, out_adox;
++
++ asm("pushf; pop %0" : "=r"(flags));
++ flags &= ~(CC_C | CC_O);
++ flags |= (in_c ? CC_C : 0);
++ flags |= (in_o ? CC_O : 0);
++
++ out_adcx = adcx_operand;
++ out_adox = adox_operand;
++ asm("push %0; popf;"
++ "adox %3, %2;"
++ "adcx %3, %1;"
++ "pushf; pop %0"
++ : "+r" (flags), "+r" (out_adcx), "+r" (out_adox)
++ : "r" ((REG)-1), "0" (flags), "1" (out_adcx), "2" (out_adox));
++
++ assert(out_adcx == in_c + adcx_operand - 1);
++ assert(out_adox == in_o + adox_operand - 1);
++ assert(!!(flags & CC_C) == (in_c || adcx_operand));
++ assert(!!(flags & CC_O) == (in_o || adox_operand));
++}
++
++void test_adcx_adox(uint32_t in_c, uint32_t in_o, REG adcx_operand, REG adox_operand)
++{
++ REG flags;
++ REG out_adcx, out_adox;
++
++ asm("pushf; pop %0" : "=r"(flags));
++ flags &= ~(CC_C | CC_O);
++ flags |= (in_c ? CC_C : 0);
++ flags |= (in_o ? CC_O : 0);
++
++ out_adcx = adcx_operand;
++ out_adox = adox_operand;
++ asm("push %0; popf;"
++ "adcx %3, %1;"
++ "adox %3, %2;"
++ "pushf; pop %0"
++ : "+r" (flags), "+r" (out_adcx), "+r" (out_adox)
++ : "r" ((REG)-1), "0" (flags), "1" (out_adcx), "2" (out_adox));
++
++ assert(out_adcx == in_c + adcx_operand - 1);
++ assert(out_adox == in_o + adox_operand - 1);
++ assert(!!(flags & CC_C) == (in_c || adcx_operand));
++ assert(!!(flags & CC_O) == (in_o || adox_operand));
++}
++
++int main(int argc, char *argv[]) {
++ /* try all combinations of input CF, input OF, CF from op1+op2, OF from op2+op1 */
++ int i;
++ for (i = 0; i <= 15; i++) {
++ printf("%d\n", i);
++ test_adcx_adox(!!(i & 1), !!(i & 2), !!(i & 4), !!(i & 8));
++ test_adox_adcx(!!(i & 1), !!(i & 2), !!(i & 4), !!(i & 8));
++ }
++ return 0;
++}
++
+diff --git a/tests/tcg/i386/test-i386-bmi2.c b/tests/tcg/i386/test-i386-bmi2.c
+index 5fadf47510..0244df7987 100644
+--- a/tests/tcg/i386/test-i386-bmi2.c
++++ b/tests/tcg/i386/test-i386-bmi2.c
+@@ -3,34 +3,40 @@
+ #include <stdint.h>
+ #include <stdio.h>
+
++#ifdef __x86_64
++typedef uint64_t reg_t;
++#else
++typedef uint32_t reg_t;
++#endif
++
+ #define insn1q(name, arg0) \
+-static inline uint64_t name##q(uint64_t arg0) \
++static inline reg_t name##q(reg_t arg0) \
+ { \
+- uint64_t result64; \
++ reg_t result64; \
+ asm volatile (#name "q %1, %0" : "=r"(result64) : "rm"(arg0)); \
+ return result64; \
+ }
+
+ #define insn1l(name, arg0) \
+-static inline uint32_t name##l(uint32_t arg0) \
++static inline reg_t name##l(reg_t arg0) \
+ { \
+- uint32_t result32; \
++ reg_t result32; \
+ asm volatile (#name "l %k1, %k0" : "=r"(result32) : "rm"(arg0)); \
+ return result32; \
+ }
+
+ #define insn2q(name, arg0, c0, arg1, c1) \
+-static inline uint64_t name##q(uint64_t arg0, uint64_t arg1) \
++static inline reg_t name##q(reg_t arg0, reg_t arg1) \
+ { \
+- uint64_t result64; \
++ reg_t result64; \
+ asm volatile (#name "q %2, %1, %0" : "=r"(result64) : c0(arg0), c1(arg1)); \
+ return result64; \
+ }
+
+ #define insn2l(name, arg0, c0, arg1, c1) \
+-static inline uint32_t name##l(uint32_t arg0, uint32_t arg1) \
++static inline reg_t name##l(reg_t arg0, reg_t arg1) \
+ { \
+- uint32_t result32; \
++ reg_t result32; \
+ asm volatile (#name "l %k2, %k1, %k0" : "=r"(result32) : c0(arg0), c1(arg1)); \
+ return result32; \
+ }
+@@ -65,130 +71,143 @@ insn1l(blsr, src)
+ int main(int argc, char *argv[]) {
+ uint64_t ehlo = 0x202020204f4c4845ull;
+ uint64_t mask = 0xa080800302020001ull;
+- uint32_t result32;
++ reg_t result;
+
+ #ifdef __x86_64
+- uint64_t result64;
+-
+ /* 64 bits */
+- result64 = andnq(mask, ehlo);
+- assert(result64 == 0x002020204d4c4844);
++ result = andnq(mask, ehlo);
++ assert(result == 0x002020204d4c4844);
++
++ result = pextq(ehlo, mask);
++ assert(result == 133);
+
+- result64 = pextq(ehlo, mask);
+- assert(result64 == 133);
++ result = pdepq(result, mask);
++ assert(result == (ehlo & mask));
+
+- result64 = pdepq(result64, mask);
+- assert(result64 == (ehlo & mask));
++ result = pextq(-1ull, mask);
++ assert(result == 511); /* mask has 9 bits set */
+
+- result64 = pextq(-1ull, mask);
+- assert(result64 == 511); /* mask has 9 bits set */
++ result = pdepq(-1ull, mask);
++ assert(result == mask);
+
+- result64 = pdepq(-1ull, mask);
+- assert(result64 == mask);
++ result = bextrq(mask, 0x3f00);
++ assert(result == (mask & ~INT64_MIN));
+
+- result64 = bextrq(mask, 0x3f00);
+- assert(result64 == (mask & ~INT64_MIN));
++ result = bextrq(mask, 0x1038);
++ assert(result == 0xa0);
+
+- result64 = bextrq(mask, 0x1038);
+- assert(result64 == 0xa0);
++ result = bextrq(mask, 0x10f8);
++ assert(result == 0);
+
+- result64 = bextrq(mask, 0x10f8);
+- assert(result64 == 0);
++ result = bextrq(0xfedcba9876543210ull, 0x7f00);
++ assert(result == 0xfedcba9876543210ull);
+
+- result64 = blsiq(0x30);
+- assert(result64 == 0x10);
++ result = blsiq(0x30);
++ assert(result == 0x10);
+
+- result64 = blsiq(0x30ull << 32);
+- assert(result64 == 0x10ull << 32);
++ result = blsiq(0x30ull << 32);
++ assert(result == 0x10ull << 32);
+
+- result64 = blsmskq(0x30);
+- assert(result64 == 0x1f);
++ result = blsmskq(0x30);
++ assert(result == 0x1f);
+
+- result64 = blsrq(0x30);
+- assert(result64 == 0x20);
++ result = blsrq(0x30);
++ assert(result == 0x20);
+
+- result64 = blsrq(0x30ull << 32);
+- assert(result64 == 0x20ull << 32);
++ result = blsrq(0x30ull << 32);
++ assert(result == 0x20ull << 32);
+
+- result64 = bzhiq(mask, 0x3f);
+- assert(result64 == (mask & ~INT64_MIN));
++ result = bzhiq(mask, 0x3f);
++ assert(result == (mask & ~INT64_MIN));
+
+- result64 = bzhiq(mask, 0x1f);
+- assert(result64 == (mask & ~(-1 << 30)));
++ result = bzhiq(mask, 0x1f);
++ assert(result == (mask & ~(-1 << 30)));
+
+- result64 = rorxq(0x2132435465768798, 8);
+- assert(result64 == 0x9821324354657687);
++ result = bzhiq(mask, 0x40);
++ assert(result == mask);
+
+- result64 = sarxq(0xffeeddccbbaa9988, 8);
+- assert(result64 == 0xffffeeddccbbaa99);
++ result = rorxq(0x2132435465768798, 8);
++ assert(result == 0x9821324354657687);
+
+- result64 = sarxq(0x77eeddccbbaa9988, 8 | 64);
+- assert(result64 == 0x0077eeddccbbaa99);
++ result = sarxq(0xffeeddccbbaa9988, 8);
++ assert(result == 0xffffeeddccbbaa99);
+
+- result64 = shrxq(0xffeeddccbbaa9988, 8);
+- assert(result64 == 0x00ffeeddccbbaa99);
++ result = sarxq(0x77eeddccbbaa9988, 8 | 64);
++ assert(result == 0x0077eeddccbbaa99);
+
+- result64 = shrxq(0x77eeddccbbaa9988, 8 | 192);
+- assert(result64 == 0x0077eeddccbbaa99);
++ result = shrxq(0xffeeddccbbaa9988, 8);
++ assert(result == 0x00ffeeddccbbaa99);
+
+- result64 = shlxq(0xffeeddccbbaa9988, 8);
+- assert(result64 == 0xeeddccbbaa998800);
++ result = shrxq(0x77eeddccbbaa9988, 8 | 192);
++ assert(result == 0x0077eeddccbbaa99);
++
++ result = shlxq(0xffeeddccbbaa9988, 8);
++ assert(result == 0xeeddccbbaa998800);
+ #endif
+
+ /* 32 bits */
+- result32 = andnl(mask, ehlo);
+- assert(result32 == 0x04d4c4844);
++ result = andnl(mask, ehlo);
++ assert(result == 0x04d4c4844);
++
++ result = pextl((uint32_t) ehlo, mask);
++ assert(result == 5);
++
++ result = pdepl(result, mask);
++ assert(result == (uint32_t)(ehlo & mask));
++
++ result = pextl(-1u, mask);
++ assert(result == 7); /* mask has 3 bits set */
+
+- result32 = pextl((uint32_t) ehlo, mask);
+- assert(result32 == 5);
++ result = pdepl(-1u, mask);
++ assert(result == (uint32_t)mask);
+
+- result32 = pdepl(result32, mask);
+- assert(result32 == (uint32_t)(ehlo & mask));
++ result = bextrl(mask, 0x1f00);
++ assert(result == (mask & ~INT32_MIN));
+
+- result32 = pextl(-1u, mask);
+- assert(result32 == 7); /* mask has 3 bits set */
++ result = bextrl(ehlo, 0x1018);
++ assert(result == 0x4f);
+
+- result32 = pdepl(-1u, mask);
+- assert(result32 == (uint32_t)mask);
++ result = bextrl(mask, 0x1038);
++ assert(result == 0);
+
+- result32 = bextrl(mask, 0x1f00);
+- assert(result32 == (mask & ~INT32_MIN));
++ result = bextrl((reg_t)0x8f635a775ad3b9b4ull, 0x3018);
++ assert(result == 0x5a);
+
+- result32 = bextrl(ehlo, 0x1018);
+- assert(result32 == 0x4f);
++ result = bextrl((reg_t)0xfedcba9876543210ull, 0x7f00);
++ assert(result == 0x76543210u);
+
+- result32 = bextrl(mask, 0x1038);
+- assert(result32 == 0);
++ result = bextrl(-1, 0);
++ assert(result == 0);
+
+- result32 = blsil(0xffff);
+- assert(result32 == 1);
++ result = blsil(0xffff);
++ assert(result == 1);
+
+- result32 = blsmskl(0x300);
+- assert(result32 == 0x1ff);
++ result = blsmskl(0x300);
++ assert(result == 0x1ff);
+
+- result32 = blsrl(0xffc);
+- assert(result32 == 0xff8);
++ result = blsrl(0xffc);
++ assert(result == 0xff8);
+
+- result32 = bzhil(mask, 0xf);
+- assert(result32 == 1);
++ result = bzhil(mask, 0xf);
++ assert(result == 1);
+
+- result32 = rorxl(0x65768798, 8);
+- assert(result32 == 0x98657687);
++ result = rorxl(0x65768798, 8);
++ assert(result == 0x98657687);
+
+- result32 = sarxl(0xffeeddcc, 8);
+- assert(result32 == 0xffffeedd);
++ result = sarxl(0xffeeddcc, 8);
++ assert(result == 0xffffeedd);
+
+- result32 = sarxl(0x77eeddcc, 8 | 32);
+- assert(result32 == 0x0077eedd);
++ result = sarxl(0x77eeddcc, 8 | 32);
++ assert(result == 0x0077eedd);
+
+- result32 = shrxl(0xffeeddcc, 8);
+- assert(result32 == 0x00ffeedd);
++ result = shrxl(0xffeeddcc, 8);
++ assert(result == 0x00ffeedd);
+
+- result32 = shrxl(0x77eeddcc, 8 | 128);
+- assert(result32 == 0x0077eedd);
++ result = shrxl(0x77eeddcc, 8 | 128);
++ assert(result == 0x0077eedd);
+
+- result32 = shlxl(0xffeeddcc, 8);
+- assert(result32 == 0xeeddcc00);
++ result = shlxl(0xffeeddcc, 8);
++ assert(result == 0xeeddcc00);
+
+ return 0;
+ }
+diff --git a/tests/tcg/multiarch/linux/linux-test.c b/tests/tcg/multiarch/linux/linux-test.c
+index 5a2a4f2258..64f57cb287 100644
+--- a/tests/tcg/multiarch/linux/linux-test.c
++++ b/tests/tcg/multiarch/linux/linux-test.c
+@@ -354,13 +354,17 @@ static void test_pipe(void)
+ if (FD_ISSET(fds[0], &rfds)) {
+ chk_error(read(fds[0], &ch, 1));
+ rcount++;
+- if (rcount >= WCOUNT_MAX)
++ if (rcount >= WCOUNT_MAX) {
+ break;
++ }
+ }
+ if (FD_ISSET(fds[1], &wfds)) {
+ ch = 'a';
+ chk_error(write(fds[1], &ch, 1));
+ wcount++;
++ if (wcount >= WCOUNT_MAX) {
++ break;
++ }
+ }
+ }
+ }
+diff --git a/tests/tcg/riscv64/Makefile.target b/tests/tcg/riscv64/Makefile.target
+index b5b89dfb0e..cc3ed65ffd 100644
+--- a/tests/tcg/riscv64/Makefile.target
++++ b/tests/tcg/riscv64/Makefile.target
+@@ -4,3 +4,9 @@
+ VPATH += $(SRC_PATH)/tests/tcg/riscv64
+ TESTS += test-div
+ TESTS += noexec
++
++# Disable compressed instructions for test-noc
++TESTS += test-noc
++test-noc: LDFLAGS = -nostdlib -static
++run-test-noc: QEMU_OPTS += -cpu rv64,c=false
++run-plugin-test-noc-%: QEMU_OPTS += -cpu rv64,c=false
+diff --git a/tests/tcg/riscv64/test-noc.S b/tests/tcg/riscv64/test-noc.S
+new file mode 100644
+index 0000000000..e29d60c8b3
+--- /dev/null
++++ b/tests/tcg/riscv64/test-noc.S
+@@ -0,0 +1,32 @@
++#include <asm/unistd.h>
++
++ .text
++ .globl _start
++_start:
++ .option norvc
++ li a0, 4 /* SIGILL */
++ la a1, sa
++ li a2, 0
++ li a3, 8
++ li a7, __NR_rt_sigaction
++ scall
++
++ .option rvc
++ li a0, 1
++ j exit
++ .option norvc
++
++pass:
++ li a0, 0
++exit:
++ li a7, __NR_exit
++ scall
++
++ .data
++ /* struct kernel_sigaction sa = { .sa_handler = pass }; */
++ .type sa, @object
++ .size sa, 32
++sa:
++ .dword pass
++ .zero 24
++
diff --git a/debian/patches/v7.2.10.diff b/debian/patches/v7.2.10.diff
new file mode 100644
index 00000000..dfb4a952
--- /dev/null
+++ b/debian/patches/v7.2.10.diff
@@ -0,0 +1,1444 @@
+Subject: v7.2.10
+Date: Mon Mar 4 15:14:39 2024 +0300
+From: Michael Tokarev <mjt@tls.msk.ru>
+Forwarded: not-needed
+
+This is a difference between upstream qemu v7.2.9
+and upstream qemu v7.2.10.
+
+ .gitlab-ci.d/cirrus/build.yml | 2 +-
+ .gitlab-ci.d/windows.yml | 34 ------------------
+ VERSION | 2 +-
+ audio/meson.build | 3 +-
+ block/blkio.c | 2 +-
+ docs/interop/vhost-user.rst | 6 ++--
+ docs/system/keys.rst.inc | 13 +++----
+ hw/arm/smmu-common.c | 2 ++
+ hw/cxl/cxl-cdat.c | 11 ++++--
+ hw/cxl/cxl-component-utils.c | 2 +-
+ hw/i386/acpi-build.c | 2 +-
+ hw/i386/sgx-stub.c | 2 +-
+ hw/nvme/ctrl.c | 2 +-
+ hw/pci-host/designware.c | 2 ++
+ hw/rtc/pl031.c | 1 +
+ hw/smbios/smbios.c | 12 +++++++
+ hw/usb/bus.c | 5 +--
+ hw/virtio/virtio-iommu.c | 4 +--
+ linux-user/aarch64/target_prctl.h | 29 +++++++++-------
+ migration/migration.c | 2 ++
+ qemu-options.hx | 14 ++++++--
+ softmmu/vl.c | 24 +++++++------
+ target/arm/helper.c | 30 ++++++++++++++--
+ target/arm/sme_helper.c | 8 ++---
+ target/arm/sve_helper.c | 12 +++----
+ target/arm/syndrome.h | 8 +++++
+ target/arm/translate-sve.c | 16 ++++-----
+ target/i386/cpu.c | 6 ++--
+ target/i386/cpu.h | 6 ++++
+ target/i386/kvm/kvm.c | 3 +-
+ target/i386/tcg/sysemu/excp_helper.c | 45 +++++++++++-------------
+ target/i386/tcg/sysemu/misc_helper.c | 3 ++
+ target/i386/tcg/sysemu/svm_helper.c | 27 +++++++++++----
+ target/i386/tcg/translate.c | 11 +++---
+ target/ppc/translate/vsx-impl.c.inc | 2 +-
+ tests/data/acpi/q35/DSDT.cxl | Bin 9636 -> 9637 bytes
+ tests/qemu-iotests/144 | 12 ++++++-
+ tests/qemu-iotests/144.out | 2 +-
+ tests/qtest/display-vga-test.c | 65 ++++++++++++++---------------------
+ tests/unit/test-blockjob.c | 9 ++++-
+ tests/unit/test-util-sockets.c | 1 +
+ tests/unit/test-vmstate.c | 5 ++-
+ tests/vm/Makefile.include | 2 +-
+ tests/vm/basevm.py | 4 +--
+ tests/vm/openbsd | 9 ++---
+ ui/clipboard.c | 26 ++++++++++++--
+ ui/console.c | 2 +-
+ ui/meson.build | 6 ++--
+ ui/vnc.c | 5 +++
+ 49 files changed, 299 insertions(+), 202 deletions(-)
+
+diff --git a/.gitlab-ci.d/cirrus/build.yml b/.gitlab-ci.d/cirrus/build.yml
+index 7ef6af8d33..d8cf08dc14 100644
+--- a/.gitlab-ci.d/cirrus/build.yml
++++ b/.gitlab-ci.d/cirrus/build.yml
+@@ -19,7 +19,7 @@ build_task:
+ install_script:
+ - @UPDATE_COMMAND@
+ - @INSTALL_COMMAND@ @PKGS@
+- - if test -n "@PYPI_PKGS@" ; then @PIP3@ install @PYPI_PKGS@ ; fi
++ - if test -n "@PYPI_PKGS@" ; then PYLIB=$(@PYTHON@ -c 'import sysconfig; print(sysconfig.get_path("stdlib"))'); rm -f $PYLIB/EXTERNALLY-MANAGED; @PIP3@ install @PYPI_PKGS@ ; fi
+ clone_script:
+ - git clone --depth 100 "$CI_REPOSITORY_URL" .
+ - git fetch origin "$CI_COMMIT_REF_NAME"
+diff --git a/.gitlab-ci.d/windows.yml b/.gitlab-ci.d/windows.yml
+index a3e7a37022..0180261b7f 100644
+--- a/.gitlab-ci.d/windows.yml
++++ b/.gitlab-ci.d/windows.yml
+@@ -63,37 +63,3 @@ msys2-64bit:
+ --enable-capstone --without-default-devices'
+ - .\msys64\usr\bin\bash -lc 'make'
+ - .\msys64\usr\bin\bash -lc 'make check || { cat build/meson-logs/testlog.txt; exit 1; } ;'
+-
+-msys2-32bit:
+- extends: .shared_msys2_builder
+- script:
+- - .\msys64\usr\bin\bash -lc "pacman -Sy --noconfirm --needed
+- bison diffutils flex
+- git grep make sed
+- mingw-w64-i686-capstone
+- mingw-w64-i686-curl
+- mingw-w64-i686-cyrus-sasl
+- mingw-w64-i686-gcc
+- mingw-w64-i686-glib2
+- mingw-w64-i686-gnutls
+- mingw-w64-i686-gtk3
+- mingw-w64-i686-libgcrypt
+- mingw-w64-i686-libjpeg-turbo
+- mingw-w64-i686-libssh
+- mingw-w64-i686-libtasn1
+- mingw-w64-i686-libusb
+- mingw-w64-i686-lzo2
+- mingw-w64-i686-ninja
+- mingw-w64-i686-pixman
+- mingw-w64-i686-pkgconf
+- mingw-w64-i686-python
+- mingw-w64-i686-snappy
+- mingw-w64-i686-usbredir "
+- - $env:CHERE_INVOKING = 'yes' # Preserve the current working directory
+- - $env:MSYSTEM = 'MINGW32' # Start a 32-bit MinG environment
+- - $env:MSYS = 'winsymlinks:native' # Enable native Windows symlink
+- - mkdir output
+- - cd output
+- - ..\msys64\usr\bin\bash -lc "../configure --target-list=ppc64-softmmu"
+- - ..\msys64\usr\bin\bash -lc 'make'
+- - ..\msys64\usr\bin\bash -lc 'make check || { cat meson-logs/testlog.txt; exit 1; } ;'
+diff --git a/VERSION b/VERSION
+index 672f66a613..6bfb3a0ba9 100644
+--- a/VERSION
++++ b/VERSION
+@@ -1 +1 @@
+-7.2.9
++7.2.10
+diff --git a/audio/meson.build b/audio/meson.build
+index 34aed78342..ce171f710d 100644
+--- a/audio/meson.build
++++ b/audio/meson.build
+@@ -29,7 +29,8 @@ endforeach
+
+ if dbus_display
+ module_ss = ss.source_set()
+- module_ss.add(when: gio, if_true: files('dbusaudio.c'))
++ module_ss.add(when: [gio, dbus_display1_dep],
++ if_true: files('dbusaudio.c'))
+ audio_modules += {'dbus': module_ss}
+ endif
+
+diff --git a/block/blkio.c b/block/blkio.c
+index 5eae3adfaf..cb66160268 100644
+--- a/block/blkio.c
++++ b/block/blkio.c
+@@ -74,7 +74,7 @@ typedef struct {
+ CoQueue bounce_available;
+
+ /* The value of the "mem-region-alignment" property */
+- size_t mem_region_alignment;
++ uint64_t mem_region_alignment;
+
+ /* Can we skip adding/deleting blkio_mem_regions? */
+ bool needs_mem_regions;
+diff --git a/docs/interop/vhost-user.rst b/docs/interop/vhost-user.rst
+index 3f18ab424e..936de705e1 100644
+--- a/docs/interop/vhost-user.rst
++++ b/docs/interop/vhost-user.rst
+@@ -111,9 +111,9 @@ A vring state description
+ A vring address description
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+-+-------+-------+------+------------+------+-----------+-----+
+-| index | flags | size | descriptor | used | available | log |
+-+-------+-------+------+------------+------+-----------+-----+
+++-------+-------+------------+------+-----------+-----+
++| index | flags | descriptor | used | available | log |
+++-------+-------+------------+------+-----------+-----+
+
+ :index: a 32-bit vring index
+
+diff --git a/docs/system/keys.rst.inc b/docs/system/keys.rst.inc
+index bd9b8e5f6f..59966a3fe7 100644
+--- a/docs/system/keys.rst.inc
++++ b/docs/system/keys.rst.inc
+@@ -1,8 +1,9 @@
+-During the graphical emulation, you can use special key combinations to
+-change modes. The default key mappings are shown below, but if you use
+-``-alt-grab`` then the modifier is Ctrl-Alt-Shift (instead of Ctrl-Alt)
+-and if you use ``-ctrl-grab`` then the modifier is the right Ctrl key
+-(instead of Ctrl-Alt):
++During the graphical emulation, you can use special key combinations from
++the following table to change modes. By default the modifier is Ctrl-Alt
++(used in the table below) which can be changed with ``-display`` suboption
++``mod=`` where appropriate. For example, ``-display sdl,
++grab-mod=lshift-lctrl-lalt`` changes the modifier key to Ctrl-Alt-Shift,
++while ``-display sdl,grab-mod=rctrl`` changes it to the right Ctrl key.
+
+ Ctrl-Alt-f
+ Toggle full screen
+@@ -28,7 +29,7 @@ Ctrl-Alt-n
+ *3*
+ Serial port
+
+-Ctrl-Alt
++Ctrl-Alt-g
+ Toggle mouse and keyboard grab.
+
+ In the virtual consoles, you can use Ctrl-Up, Ctrl-Down, Ctrl-PageUp and
+diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
+index bbca3a8db3..7abc166eb3 100644
+--- a/hw/arm/smmu-common.c
++++ b/hw/arm/smmu-common.c
+@@ -529,6 +529,8 @@ static void smmu_base_reset(DeviceState *dev)
+ {
+ SMMUState *s = ARM_SMMU(dev);
+
++ memset(s->smmu_pcibus_by_bus_num, 0, sizeof(s->smmu_pcibus_by_bus_num));
++
+ g_hash_table_remove_all(s->configs);
+ g_hash_table_remove_all(s->iotlb);
+ }
+diff --git a/hw/cxl/cxl-cdat.c b/hw/cxl/cxl-cdat.c
+index 3653aa56f0..0cde11854e 100644
+--- a/hw/cxl/cxl-cdat.c
++++ b/hw/cxl/cxl-cdat.c
+@@ -49,6 +49,7 @@ static void ct3_build_cdat(CDATObject *cdat, Error **errp)
+ g_autofree CDATTableHeader *cdat_header = NULL;
+ g_autofree CDATEntry *cdat_st = NULL;
+ uint8_t sum = 0;
++ uint8_t *hdr_buf;
+ int ent, i;
+
+ /* Use default table if fopen == NULL */
+@@ -62,7 +63,7 @@ static void ct3_build_cdat(CDATObject *cdat, Error **errp)
+
+ cdat->built_buf_len = cdat->build_cdat_table(&cdat->built_buf, cdat->private);
+
+- if (!cdat->built_buf_len) {
++ if (cdat->built_buf_len <= 0) {
+ /* Build later as not all data available yet */
+ cdat->to_update = true;
+ return;
+@@ -94,8 +95,12 @@ static void ct3_build_cdat(CDATObject *cdat, Error **errp)
+ /* For now, no runtime updates */
+ cdat_header->sequence = 0;
+ cdat_header->length += sizeof(CDATTableHeader);
+- sum += cdat_header->revision + cdat_header->sequence +
+- cdat_header->length;
++
++ hdr_buf = (uint8_t *)cdat_header;
++ for (i = 0; i < sizeof(*cdat_header); i++) {
++ sum += hdr_buf[i];
++ }
++
+ /* Sum of all bytes including checksum must be 0 */
+ cdat_header->checksum = ~sum + 1;
+
+diff --git a/hw/cxl/cxl-component-utils.c b/hw/cxl/cxl-component-utils.c
+index 3edd303a33..5934b95848 100644
+--- a/hw/cxl/cxl-component-utils.c
++++ b/hw/cxl/cxl-component-utils.c
+@@ -126,7 +126,7 @@ void cxl_component_register_block_init(Object *obj,
+ /* io registers controls link which we don't care about in QEMU */
+ memory_region_init_io(&cregs->io, obj, NULL, cregs, ".io",
+ CXL2_COMPONENT_IO_REGION_SIZE);
+- memory_region_init_io(&cregs->cache_mem, obj, &cache_mem_ops, cregs,
++ memory_region_init_io(&cregs->cache_mem, obj, &cache_mem_ops, cxl_cstate,
+ ".cache_mem", CXL2_COMPONENT_CM_REGION_SIZE);
+
+ memory_region_add_subregion(&cregs->component_registers, 0, &cregs->io);
+diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
+index d9eaa5fc4d..f9cdacadb1 100644
+--- a/hw/i386/acpi-build.c
++++ b/hw/i386/acpi-build.c
+@@ -1311,7 +1311,7 @@ static void build_acpi0017(Aml *table)
+ aml_append(dev, aml_name_decl("_HID", aml_string("ACPI0017")));
+
+ method = aml_method("_STA", 0, AML_NOTSERIALIZED);
+- aml_append(method, aml_return(aml_int(0x01)));
++ aml_append(method, aml_return(aml_int(0x0B)));
+ aml_append(dev, method);
+
+ aml_append(scope, dev);
+diff --git a/hw/i386/sgx-stub.c b/hw/i386/sgx-stub.c
+index 26833eb233..16b1dfd90b 100644
+--- a/hw/i386/sgx-stub.c
++++ b/hw/i386/sgx-stub.c
+@@ -34,5 +34,5 @@ void pc_machine_init_sgx_epc(PCMachineState *pcms)
+
+ bool sgx_epc_get_section(int section_nr, uint64_t *addr, uint64_t *size)
+ {
+- g_assert_not_reached();
++ return true;
+ }
+diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c
+index 4d29033556..a87f79296c 100644
+--- a/hw/nvme/ctrl.c
++++ b/hw/nvme/ctrl.c
+@@ -7140,7 +7140,7 @@ static void nvme_init_state(NvmeCtrl *n)
+ n->aer_reqs = g_new0(NvmeRequest *, n->params.aerl + 1);
+ QTAILQ_INIT(&n->aer_queue);
+
+- list->numcntl = cpu_to_le16(max_vfs);
++ list->numcntl = max_vfs;
+ for (i = 0; i < max_vfs; i++) {
+ sctrl = &list->sec[i];
+ sctrl->pcid = cpu_to_le16(n->cntlid);
+diff --git a/hw/pci-host/designware.c b/hw/pci-host/designware.c
+index bde3a343a2..c235b9daa3 100644
+--- a/hw/pci-host/designware.c
++++ b/hw/pci-host/designware.c
+@@ -340,6 +340,8 @@ static void designware_pcie_root_config_write(PCIDevice *d, uint32_t address,
+ break;
+
+ case DESIGNWARE_PCIE_ATU_VIEWPORT:
++ val &= DESIGNWARE_PCIE_ATU_REGION_INBOUND |
++ (DESIGNWARE_PCIE_NUM_VIEWPORTS - 1);
+ root->atu_viewport = val;
+ break;
+
+diff --git a/hw/rtc/pl031.c b/hw/rtc/pl031.c
+index b01d0e75d1..2f3cd04eeb 100644
+--- a/hw/rtc/pl031.c
++++ b/hw/rtc/pl031.c
+@@ -141,6 +141,7 @@ static void pl031_write(void * opaque, hwaddr offset,
+ g_autofree const char *qom_path = object_get_canonical_path(opaque);
+ struct tm tm;
+
++ s->lr = value;
+ s->tick_offset += value - pl031_get_count(s);
+
+ qemu_get_timedate(&tm, s->tick_offset);
+diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c
+index cd43185417..9f4d007d96 100644
+--- a/hw/smbios/smbios.c
++++ b/hw/smbios/smbios.c
+@@ -345,6 +345,11 @@ static const QemuOptDesc qemu_smbios_type4_opts[] = {
+ };
+
+ static const QemuOptDesc qemu_smbios_type8_opts[] = {
++ {
++ .name = "type",
++ .type = QEMU_OPT_NUMBER,
++ .help = "SMBIOS element type",
++ },
+ {
+ .name = "internal_reference",
+ .type = QEMU_OPT_STRING,
+@@ -365,9 +370,15 @@ static const QemuOptDesc qemu_smbios_type8_opts[] = {
+ .type = QEMU_OPT_NUMBER,
+ .help = "port type",
+ },
++ { /* end of list */ }
+ };
+
+ static const QemuOptDesc qemu_smbios_type11_opts[] = {
++ {
++ .name = "type",
++ .type = QEMU_OPT_NUMBER,
++ .help = "SMBIOS element type",
++ },
+ {
+ .name = "value",
+ .type = QEMU_OPT_STRING,
+@@ -378,6 +389,7 @@ static const QemuOptDesc qemu_smbios_type11_opts[] = {
+ .type = QEMU_OPT_STRING,
+ .help = "OEM string data from file",
+ },
++ { /* end of list */ }
+ };
+
+ static const QemuOptDesc qemu_smbios_type17_opts[] = {
+diff --git a/hw/usb/bus.c b/hw/usb/bus.c
+index 92d6ed5626..4d4c671913 100644
+--- a/hw/usb/bus.c
++++ b/hw/usb/bus.c
+@@ -273,13 +273,14 @@ static void usb_qdev_realize(DeviceState *qdev, Error **errp)
+ }
+
+ if (dev->pcap_filename) {
+- int fd = qemu_open_old(dev->pcap_filename, O_CREAT | O_WRONLY | O_TRUNC, 0666);
++ int fd = qemu_open_old(dev->pcap_filename,
++ O_CREAT | O_WRONLY | O_TRUNC | O_BINARY, 0666);
+ if (fd < 0) {
+ error_setg(errp, "open %s failed", dev->pcap_filename);
+ usb_qdev_unrealize(qdev);
+ return;
+ }
+- dev->pcap = fdopen(fd, "w");
++ dev->pcap = fdopen(fd, "wb");
+ usb_pcap_init(dev->pcap);
+ }
+ }
+diff --git a/hw/virtio/virtio-iommu.c b/hw/virtio/virtio-iommu.c
+index eb82462c95..95db19f144 100644
+--- a/hw/virtio/virtio-iommu.c
++++ b/hw/virtio/virtio-iommu.c
+@@ -1140,6 +1140,8 @@ static void virtio_iommu_system_reset(void *opaque)
+
+ trace_virtio_iommu_system_reset();
+
++ memset(s->iommu_pcibus_by_bus_num, 0, sizeof(s->iommu_pcibus_by_bus_num));
++
+ /*
+ * config.bypass is sticky across device reset, but should be restored on
+ * system reset
+@@ -1156,8 +1158,6 @@ static void virtio_iommu_device_realize(DeviceState *dev, Error **errp)
+
+ virtio_init(vdev, VIRTIO_ID_IOMMU, sizeof(struct virtio_iommu_config));
+
+- memset(s->iommu_pcibus_by_bus_num, 0, sizeof(s->iommu_pcibus_by_bus_num));
+-
+ s->req_vq = virtio_add_queue(vdev, VIOMMU_DEFAULT_QUEUE_SIZE,
+ virtio_iommu_handle_command);
+ s->event_vq = virtio_add_queue(vdev, VIOMMU_DEFAULT_QUEUE_SIZE, NULL);
+diff --git a/linux-user/aarch64/target_prctl.h b/linux-user/aarch64/target_prctl.h
+index 907c314146..d9f6648e27 100644
+--- a/linux-user/aarch64/target_prctl.h
++++ b/linux-user/aarch64/target_prctl.h
+@@ -171,21 +171,26 @@ static abi_long do_prctl_set_tagged_addr_ctrl(CPUArchState *env, abi_long arg2)
+ env->tagged_addr_enable = arg2 & PR_TAGGED_ADDR_ENABLE;
+
+ if (cpu_isar_feature(aa64_mte, cpu)) {
+- switch (arg2 & PR_MTE_TCF_MASK) {
+- case PR_MTE_TCF_NONE:
+- case PR_MTE_TCF_SYNC:
+- case PR_MTE_TCF_ASYNC:
+- break;
+- default:
+- return -EINVAL;
+- }
+-
+ /*
+ * Write PR_MTE_TCF to SCTLR_EL1[TCF0].
+- * Note that the syscall values are consistent with hw.
++ *
++ * The kernel has a per-cpu configuration for the sysadmin,
++ * /sys/devices/system/cpu/cpu<N>/mte_tcf_preferred,
++ * which qemu does not implement.
++ *
++ * Because there is no performance difference between the modes, and
++ * because SYNC is most useful for debugging MTE errors, choose SYNC
++ * as the preferred mode. With this preference, and the way the API
++ * uses only two bits, there is no way for the program to select
++ * ASYMM mode.
+ */
+- env->cp15.sctlr_el[1] =
+- deposit64(env->cp15.sctlr_el[1], 38, 2, arg2 >> PR_MTE_TCF_SHIFT);
++ unsigned tcf = 0;
++ if (arg2 & PR_MTE_TCF_SYNC) {
++ tcf = 1;
++ } else if (arg2 & PR_MTE_TCF_ASYNC) {
++ tcf = 2;
++ }
++ env->cp15.sctlr_el[1] = deposit64(env->cp15.sctlr_el[1], 38, 2, tcf);
+
+ /*
+ * Write PR_MTE_TAG to GCR_EL1[Exclude].
+diff --git a/migration/migration.c b/migration/migration.c
+index c8ca7927b4..9b496cce1d 100644
+--- a/migration/migration.c
++++ b/migration/migration.c
+@@ -572,6 +572,7 @@ static void process_incoming_migration_bh(void *opaque)
+ MIGRATION_STATUS_COMPLETED);
+ qemu_bh_delete(mis->bh);
+ migration_incoming_state_destroy();
++ object_unref(OBJECT(migrate_get_current()));
+ }
+
+ static void coroutine_fn
+@@ -638,6 +639,7 @@ process_incoming_migration_co(void *opaque)
+ goto fail;
+ }
+ mis->bh = qemu_bh_new(process_incoming_migration_bh, mis);
++ object_ref(OBJECT(migrate_get_current()));
+ qemu_bh_schedule(mis->bh);
+ mis->migration_incoming_co = NULL;
+ return;
+diff --git a/qemu-options.hx b/qemu-options.hx
+index 379692da86..7f798ce47e 100644
+--- a/qemu-options.hx
++++ b/qemu-options.hx
+@@ -3968,7 +3968,8 @@ SRST
+ This option can be used several times to simulate up to 4 serial
+ ports.
+
+- Use ``-serial none`` to disable all serial ports.
++ You can use ``-serial none`` to suppress the creation of default
++ serial devices.
+
+ Available character devices are:
+
+@@ -3990,10 +3991,17 @@ SRST
+ [Linux only] Pseudo TTY (a new PTY is automatically allocated)
+
+ ``none``
+- No device is allocated.
++ No device is allocated. Note that for machine types which
++ emulate systems where a serial device is always present in
++ real hardware, this may be equivalent to the ``null`` option,
++ in that the serial device is still present but all output
++ is discarded. For boards where the number of serial ports is
++ truly variable, this suppresses the creation of the device.
+
+ ``null``
+- void device
++ A guest will see the UART or serial device as present in the
++ machine, but all output is discarded, and there is no input.
++ Conceptually equivalent to redirecting the output to ``/dev/null``.
+
+ ``chardev:id``
+ Use a named character device defined with the ``-chardev``
+diff --git a/softmmu/vl.c b/softmmu/vl.c
+index ce88869618..38d76d6e51 100644
+--- a/softmmu/vl.c
++++ b/softmmu/vl.c
+@@ -856,7 +856,7 @@ static void help(int exitcode)
+ printf("\nDuring emulation, the following keys are useful:\n"
+ "ctrl-alt-f toggle full screen\n"
+ "ctrl-alt-n switch to virtual console 'n'\n"
+- "ctrl-alt toggle mouse and keyboard grab\n"
++ "ctrl-alt-g toggle mouse and keyboard grab\n"
+ "\n"
+ "When using -nographic, press 'ctrl-a h' to get some help.\n"
+ "\n"
+@@ -1363,18 +1363,22 @@ static void qemu_create_default_devices(void)
+ static int serial_parse(const char *devname)
+ {
+ int index = num_serial_hds;
+- char label[32];
+
+- if (strcmp(devname, "none") == 0)
+- return 0;
+- snprintf(label, sizeof(label), "serial%d", index);
+ serial_hds = g_renew(Chardev *, serial_hds, index + 1);
+
+- serial_hds[index] = qemu_chr_new_mux_mon(label, devname, NULL);
+- if (!serial_hds[index]) {
+- error_report("could not connect serial device"
+- " to character backend '%s'", devname);
+- return -1;
++ if (strcmp(devname, "none") == 0) {
++ /* Don't allocate a serial device for this index */
++ serial_hds[index] = NULL;
++ } else {
++ char label[32];
++ snprintf(label, sizeof(label), "serial%d", index);
++
++ serial_hds[index] = qemu_chr_new_mux_mon(label, devname, NULL);
++ if (!serial_hds[index]) {
++ error_report("could not connect serial device"
++ " to character backend '%s'", devname);
++ return -1;
++ }
+ }
+ num_serial_hds++;
+ return 0;
+diff --git a/target/arm/helper.c b/target/arm/helper.c
+index 02cfeece45..2e284e048c 100644
+--- a/target/arm/helper.c
++++ b/target/arm/helper.c
+@@ -1125,13 +1125,21 @@ static bool pmu_counter_enabled(CPUARMState *env, uint8_t counter)
+ bool enabled, prohibited = false, filtered;
+ bool secure = arm_is_secure(env);
+ int el = arm_current_el(env);
+- uint64_t mdcr_el2 = arm_mdcr_el2_eff(env);
+- uint8_t hpmn = mdcr_el2 & MDCR_HPMN;
++ uint64_t mdcr_el2;
++ uint8_t hpmn;
+
++ /*
++ * We might be called for M-profile cores where MDCR_EL2 doesn't
++ * exist and arm_mdcr_el2_eff() will assert, so this early-exit check
++ * must be before we read that value.
++ */
+ if (!arm_feature(env, ARM_FEATURE_PMU)) {
+ return false;
+ }
+
++ mdcr_el2 = arm_mdcr_el2_eff(env);
++ hpmn = mdcr_el2 & MDCR_HPMN;
++
+ if (!arm_feature(env, ARM_FEATURE_EL2) ||
+ (counter < hpmn || counter == 31)) {
+ e = env->cp15.c9_pmcr & PMCRE;
+@@ -9836,6 +9844,24 @@ static void arm_cpu_do_interrupt_aarch32(CPUState *cs)
+ }
+
+ if (env->exception.target_el == 2) {
++ /* Debug exceptions are reported differently on AArch32 */
++ switch (syn_get_ec(env->exception.syndrome)) {
++ case EC_BREAKPOINT:
++ case EC_BREAKPOINT_SAME_EL:
++ case EC_AA32_BKPT:
++ case EC_VECTORCATCH:
++ env->exception.syndrome = syn_insn_abort(arm_current_el(env) == 2,
++ 0, 0, 0x22);
++ break;
++ case EC_WATCHPOINT:
++ env->exception.syndrome = syn_set_ec(env->exception.syndrome,
++ EC_DATAABORT);
++ break;
++ case EC_WATCHPOINT_SAME_EL:
++ env->exception.syndrome = syn_set_ec(env->exception.syndrome,
++ EC_DATAABORT_SAME_EL);
++ break;
++ }
+ arm_cpu_do_interrupt_aarch32_hyp(cs);
+ return;
+ }
+diff --git a/target/arm/sme_helper.c b/target/arm/sme_helper.c
+index 8856773635..d592c78ec9 100644
+--- a/target/arm/sme_helper.c
++++ b/target/arm/sme_helper.c
+@@ -606,8 +606,8 @@ void sme_ld1_mte(CPUARMState *env, void *za, uint64_t *vg,
+ desc = extract32(desc, 0, SIMD_DATA_SHIFT + SVE_MTEDESC_SHIFT);
+
+ /* Perform gross MTE suppression early. */
+- if (!tbi_check(desc, bit55) ||
+- tcma_check(desc, bit55, allocation_tag_from_addr(addr))) {
++ if (!tbi_check(mtedesc, bit55) ||
++ tcma_check(mtedesc, bit55, allocation_tag_from_addr(addr))) {
+ mtedesc = 0;
+ }
+
+@@ -783,8 +783,8 @@ void sme_st1_mte(CPUARMState *env, void *za, uint64_t *vg, target_ulong addr,
+ desc = extract32(desc, 0, SIMD_DATA_SHIFT + SVE_MTEDESC_SHIFT);
+
+ /* Perform gross MTE suppression early. */
+- if (!tbi_check(desc, bit55) ||
+- tcma_check(desc, bit55, allocation_tag_from_addr(addr))) {
++ if (!tbi_check(mtedesc, bit55) ||
++ tcma_check(mtedesc, bit55, allocation_tag_from_addr(addr))) {
+ mtedesc = 0;
+ }
+
+diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
+index 27838fb6e2..45a93755fe 100644
+--- a/target/arm/sve_helper.c
++++ b/target/arm/sve_helper.c
+@@ -5803,8 +5803,8 @@ void sve_ldN_r_mte(CPUARMState *env, uint64_t *vg, target_ulong addr,
+ desc = extract32(desc, 0, SIMD_DATA_SHIFT + SVE_MTEDESC_SHIFT);
+
+ /* Perform gross MTE suppression early. */
+- if (!tbi_check(desc, bit55) ||
+- tcma_check(desc, bit55, allocation_tag_from_addr(addr))) {
++ if (!tbi_check(mtedesc, bit55) ||
++ tcma_check(mtedesc, bit55, allocation_tag_from_addr(addr))) {
+ mtedesc = 0;
+ }
+
+@@ -6159,8 +6159,8 @@ void sve_ldnfff1_r_mte(CPUARMState *env, void *vg, target_ulong addr,
+ desc = extract32(desc, 0, SIMD_DATA_SHIFT + SVE_MTEDESC_SHIFT);
+
+ /* Perform gross MTE suppression early. */
+- if (!tbi_check(desc, bit55) ||
+- tcma_check(desc, bit55, allocation_tag_from_addr(addr))) {
++ if (!tbi_check(mtedesc, bit55) ||
++ tcma_check(mtedesc, bit55, allocation_tag_from_addr(addr))) {
+ mtedesc = 0;
+ }
+
+@@ -6413,8 +6413,8 @@ void sve_stN_r_mte(CPUARMState *env, uint64_t *vg, target_ulong addr,
+ desc = extract32(desc, 0, SIMD_DATA_SHIFT + SVE_MTEDESC_SHIFT);
+
+ /* Perform gross MTE suppression early. */
+- if (!tbi_check(desc, bit55) ||
+- tcma_check(desc, bit55, allocation_tag_from_addr(addr))) {
++ if (!tbi_check(mtedesc, bit55) ||
++ tcma_check(mtedesc, bit55, allocation_tag_from_addr(addr))) {
+ mtedesc = 0;
+ }
+
+diff --git a/target/arm/syndrome.h b/target/arm/syndrome.h
+index 15334a3d15..75a3327a30 100644
+--- a/target/arm/syndrome.h
++++ b/target/arm/syndrome.h
+@@ -25,6 +25,8 @@
+ #ifndef TARGET_ARM_SYNDROME_H
+ #define TARGET_ARM_SYNDROME_H
+
++#include "qemu/bitops.h"
++
+ /* Valid Syndrome Register EC field values */
+ enum arm_exception_class {
+ EC_UNCATEGORIZED = 0x00,
+@@ -76,6 +78,7 @@ typedef enum {
+ SME_ET_InactiveZA,
+ } SMEExceptionType;
+
++#define ARM_EL_EC_LENGTH 6
+ #define ARM_EL_EC_SHIFT 26
+ #define ARM_EL_IL_SHIFT 25
+ #define ARM_EL_ISV_SHIFT 24
+@@ -87,6 +90,11 @@ static inline uint32_t syn_get_ec(uint32_t syn)
+ return syn >> ARM_EL_EC_SHIFT;
+ }
+
++static inline uint32_t syn_set_ec(uint32_t syn, uint32_t ec)
++{
++ return deposit32(syn, ARM_EL_EC_SHIFT, ARM_EL_EC_LENGTH, ec);
++}
++
+ /*
+ * Utility functions for constructing various kinds of syndrome value.
+ * Note that in general we follow the AArch64 syndrome values; in a
+diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
+index 621a2abb22..7388e1dbc7 100644
+--- a/target/arm/translate-sve.c
++++ b/target/arm/translate-sve.c
+@@ -4587,11 +4587,7 @@ static void do_mem_zpa(DisasContext *s, int zt, int pg, TCGv_i64 addr,
+ TCGv_ptr t_pg;
+ int desc = 0;
+
+- /*
+- * For e.g. LD4, there are not enough arguments to pass all 4
+- * registers as pointers, so encode the regno into the data field.
+- * For consistency, do this even for LD1.
+- */
++ assert(mte_n >= 1 && mte_n <= 4);
+ if (s->mte_active[0]) {
+ int msz = dtype_msz(dtype);
+
+@@ -4605,6 +4601,11 @@ static void do_mem_zpa(DisasContext *s, int zt, int pg, TCGv_i64 addr,
+ addr = clean_data_tbi(s, addr);
+ }
+
++ /*
++ * For e.g. LD4, there are not enough arguments to pass all 4
++ * registers as pointers, so encode the regno into the data field.
++ * For consistency, do this even for LD1.
++ */
+ desc = simd_desc(vsz, vsz, zt | desc);
+ t_pg = tcg_temp_new_ptr();
+
+@@ -4744,7 +4745,7 @@ static void do_ld_zpa(DisasContext *s, int zt, int pg,
+ * accessible via the instruction encoding.
+ */
+ assert(fn != NULL);
+- do_mem_zpa(s, zt, pg, addr, dtype, nreg, false, fn);
++ do_mem_zpa(s, zt, pg, addr, dtype, nreg + 1, false, fn);
+ }
+
+ static bool trans_LD_zprr(DisasContext *s, arg_rprr_load *a)
+@@ -5320,14 +5321,13 @@ static void do_st_zpa(DisasContext *s, int zt, int pg, TCGv_i64 addr,
+ if (nreg == 0) {
+ /* ST1 */
+ fn = fn_single[s->mte_active[0]][be][msz][esz];
+- nreg = 1;
+ } else {
+ /* ST2, ST3, ST4 -- msz == esz, enforced by encoding */
+ assert(msz == esz);
+ fn = fn_multiple[s->mte_active[0]][be][nreg - 1][msz];
+ }
+ assert(fn != NULL);
+- do_mem_zpa(s, zt, pg, addr, msz_dtype(s, msz), nreg, true, fn);
++ do_mem_zpa(s, zt, pg, addr, msz_dtype(s, msz), nreg + 1, true, fn);
+ }
+
+ static bool trans_ST_zprr(DisasContext *s, arg_rprr_store *a)
+diff --git a/target/i386/cpu.c b/target/i386/cpu.c
+index 0f71ff9fea..52a3020032 100644
+--- a/target/i386/cpu.c
++++ b/target/i386/cpu.c
+@@ -6114,6 +6114,8 @@ static void x86_cpu_enable_xsave_components(X86CPU *cpu)
+ if (!(env->features[FEAT_1_ECX] & CPUID_EXT_XSAVE)) {
+ env->features[FEAT_XSAVE_XCR0_LO] = 0;
+ env->features[FEAT_XSAVE_XCR0_HI] = 0;
++ env->features[FEAT_XSAVE_XSS_LO] = 0;
++ env->features[FEAT_XSAVE_XSS_HI] = 0;
+ return;
+ }
+
+@@ -6132,9 +6134,9 @@ static void x86_cpu_enable_xsave_components(X86CPU *cpu)
+ }
+
+ env->features[FEAT_XSAVE_XCR0_LO] = mask & CPUID_XSTATE_XCR0_MASK;
+- env->features[FEAT_XSAVE_XCR0_HI] = mask >> 32;
++ env->features[FEAT_XSAVE_XCR0_HI] = (mask & CPUID_XSTATE_XCR0_MASK) >> 32;
+ env->features[FEAT_XSAVE_XSS_LO] = mask & CPUID_XSTATE_XSS_MASK;
+- env->features[FEAT_XSAVE_XSS_HI] = mask >> 32;
++ env->features[FEAT_XSAVE_XSS_HI] = (mask & CPUID_XSTATE_XSS_MASK) >> 32;
+ }
+
+ /***** Steps involved on loading and filtering CPUID data
+diff --git a/target/i386/cpu.h b/target/i386/cpu.h
+index f67cee477a..7be047ce33 100644
+--- a/target/i386/cpu.h
++++ b/target/i386/cpu.h
+@@ -2195,6 +2195,12 @@ static inline int cpu_mmu_index(CPUX86State *env, bool ifetch)
+ ? MMU_KNOSMAP_IDX : MMU_KSMAP_IDX;
+ }
+
++static inline bool is_mmu_index_32(int mmu_index)
++{
++ assert(mmu_index < MMU_PHYS_IDX);
++ return mmu_index & 1;
++}
++
+ static inline int cpu_mmu_index_kernel(CPUX86State *env)
+ {
+ return !(env->hflags & HF_SMAP_MASK) ? MMU_KNOSMAP_IDX :
+diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
+index 002b699030..4d83bb5784 100644
+--- a/target/i386/kvm/kvm.c
++++ b/target/i386/kvm/kvm.c
+@@ -1859,6 +1859,7 @@ int kvm_arch_init_vcpu(CPUState *cs)
+ }
+ case 0x1f:
+ if (env->nr_dies < 2) {
++ cpuid_i--;
+ break;
+ }
+ /* fallthrough */
+@@ -1899,7 +1900,6 @@ int kvm_arch_init_vcpu(CPUState *cs)
+ c = &cpuid_data.entries[cpuid_i++];
+ }
+ break;
+- case 0x7:
+ case 0x12:
+ for (j = 0; ; j++) {
+ c->function = i;
+@@ -1919,6 +1919,7 @@ int kvm_arch_init_vcpu(CPUState *cs)
+ c = &cpuid_data.entries[cpuid_i++];
+ }
+ break;
++ case 0x7:
+ case 0x14:
+ case 0x1d:
+ case 0x1e: {
+diff --git a/target/i386/tcg/sysemu/excp_helper.c b/target/i386/tcg/sysemu/excp_helper.c
+index 55bd1194d3..5999cdedf5 100644
+--- a/target/i386/tcg/sysemu/excp_helper.c
++++ b/target/i386/tcg/sysemu/excp_helper.c
+@@ -133,7 +133,6 @@ static inline bool ptw_setl(const PTETranslate *in, uint32_t old, uint32_t set)
+ static bool mmu_translate(CPUX86State *env, const TranslateParams *in,
+ TranslateResult *out, TranslateFault *err)
+ {
+- const int32_t a20_mask = x86_get_a20_mask(env);
+ const target_ulong addr = in->addr;
+ const int pg_mode = in->pg_mode;
+ const bool is_user = (in->mmu_idx == MMU_USER_IDX);
+@@ -162,8 +161,7 @@ static bool mmu_translate(CPUX86State *env, const TranslateParams *in,
+ /*
+ * Page table level 5
+ */
+- pte_addr = ((in->cr3 & ~0xfff) +
+- (((addr >> 48) & 0x1ff) << 3)) & a20_mask;
++ pte_addr = (in->cr3 & ~0xfff) + (((addr >> 48) & 0x1ff) << 3);
+ if (!ptw_translate(&pte_trans, pte_addr)) {
+ return false;
+ }
+@@ -187,8 +185,7 @@ static bool mmu_translate(CPUX86State *env, const TranslateParams *in,
+ /*
+ * Page table level 4
+ */
+- pte_addr = ((pte & PG_ADDRESS_MASK) +
+- (((addr >> 39) & 0x1ff) << 3)) & a20_mask;
++ pte_addr = (pte & PG_ADDRESS_MASK) + (((addr >> 39) & 0x1ff) << 3);
+ if (!ptw_translate(&pte_trans, pte_addr)) {
+ return false;
+ }
+@@ -208,8 +205,7 @@ static bool mmu_translate(CPUX86State *env, const TranslateParams *in,
+ /*
+ * Page table level 3
+ */
+- pte_addr = ((pte & PG_ADDRESS_MASK) +
+- (((addr >> 30) & 0x1ff) << 3)) & a20_mask;
++ pte_addr = (pte & PG_ADDRESS_MASK) + (((addr >> 30) & 0x1ff) << 3);
+ if (!ptw_translate(&pte_trans, pte_addr)) {
+ return false;
+ }
+@@ -236,7 +232,7 @@ static bool mmu_translate(CPUX86State *env, const TranslateParams *in,
+ /*
+ * Page table level 3
+ */
+- pte_addr = ((in->cr3 & ~0x1f) + ((addr >> 27) & 0x18)) & a20_mask;
++ pte_addr = (in->cr3 & 0xffffffe0ULL) + ((addr >> 27) & 0x18);
+ if (!ptw_translate(&pte_trans, pte_addr)) {
+ return false;
+ }
+@@ -258,8 +254,7 @@ static bool mmu_translate(CPUX86State *env, const TranslateParams *in,
+ /*
+ * Page table level 2
+ */
+- pte_addr = ((pte & PG_ADDRESS_MASK) +
+- (((addr >> 21) & 0x1ff) << 3)) & a20_mask;
++ pte_addr = (pte & PG_ADDRESS_MASK) + (((addr >> 21) & 0x1ff) << 3);
+ if (!ptw_translate(&pte_trans, pte_addr)) {
+ return false;
+ }
+@@ -285,8 +280,7 @@ static bool mmu_translate(CPUX86State *env, const TranslateParams *in,
+ /*
+ * Page table level 1
+ */
+- pte_addr = ((pte & PG_ADDRESS_MASK) +
+- (((addr >> 12) & 0x1ff) << 3)) & a20_mask;
++ pte_addr = (pte & PG_ADDRESS_MASK) + (((addr >> 12) & 0x1ff) << 3);
+ if (!ptw_translate(&pte_trans, pte_addr)) {
+ return false;
+ }
+@@ -304,7 +298,7 @@ static bool mmu_translate(CPUX86State *env, const TranslateParams *in,
+ /*
+ * Page table level 2
+ */
+- pte_addr = ((in->cr3 & ~0xfff) + ((addr >> 20) & 0xffc)) & a20_mask;
++ pte_addr = (in->cr3 & 0xfffff000ULL) + ((addr >> 20) & 0xffc);
+ if (!ptw_translate(&pte_trans, pte_addr)) {
+ return false;
+ }
+@@ -333,7 +327,7 @@ static bool mmu_translate(CPUX86State *env, const TranslateParams *in,
+ /*
+ * Page table level 1
+ */
+- pte_addr = ((pte & ~0xfffu) + ((addr >> 10) & 0xffc)) & a20_mask;
++ pte_addr = (pte & ~0xfffu) + ((addr >> 10) & 0xffc);
+ if (!ptw_translate(&pte_trans, pte_addr)) {
+ return false;
+ }
+@@ -420,10 +414,13 @@ do_check_protect_pse36:
+ }
+ }
+
+- /* align to page_size */
+- paddr = (pte & a20_mask & PG_ADDRESS_MASK & ~(page_size - 1))
+- | (addr & (page_size - 1));
++ /* merge offset within page */
++ paddr = (pte & PG_ADDRESS_MASK & ~(page_size - 1)) | (addr & (page_size - 1));
+
++ /*
++ * Note that NPT is walked (for both paging structures and final guest
++ * addresses) using the address with the A20 bit set.
++ */
+ if (in->ptw_idx == MMU_NESTED_IDX) {
+ CPUTLBEntryFull *full;
+ int flags, nested_page_size;
+@@ -462,7 +459,7 @@ do_check_protect_pse36:
+ }
+ }
+
+- out->paddr = paddr;
++ out->paddr = paddr & x86_get_a20_mask(env);
+ out->prot = prot;
+ out->page_size = page_size;
+ return true;
+@@ -556,6 +553,10 @@ static bool get_physical_address(CPUX86State *env, vaddr addr,
+ break;
+
+ default:
++ if (is_mmu_index_32(mmu_idx)) {
++ addr = (uint32_t)addr;
++ }
++
+ if (likely(env->cr[0] & CR0_PG_MASK)) {
+ in.cr3 = env->cr[3];
+ in.mmu_idx = mmu_idx;
+@@ -579,14 +580,8 @@ static bool get_physical_address(CPUX86State *env, vaddr addr,
+ break;
+ }
+
+- /* Translation disabled. */
++ /* No translation needed. */
+ out->paddr = addr & x86_get_a20_mask(env);
+-#ifdef TARGET_X86_64
+- if (!(env->hflags & HF_LMA_MASK)) {
+- /* Without long mode we can only address 32bits in real mode */
+- out->paddr = (uint32_t)out->paddr;
+- }
+-#endif
+ out->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
+ out->page_size = TARGET_PAGE_SIZE;
+ return true;
+diff --git a/target/i386/tcg/sysemu/misc_helper.c b/target/i386/tcg/sysemu/misc_helper.c
+index e1528b7f80..1901712ece 100644
+--- a/target/i386/tcg/sysemu/misc_helper.c
++++ b/target/i386/tcg/sysemu/misc_helper.c
+@@ -201,6 +201,9 @@ void helper_wrmsr(CPUX86State *env)
+ tlb_flush(cs);
+ break;
+ case MSR_VM_HSAVE_PA:
++ if (val & (0xfff | ((~0ULL) << env_archcpu(env)->phys_bits))) {
++ goto error;
++ }
+ env->vm_hsave = val;
+ break;
+ #ifdef TARGET_X86_64
+diff --git a/target/i386/tcg/sysemu/svm_helper.c b/target/i386/tcg/sysemu/svm_helper.c
+index 2d27731b60..744aed4b31 100644
+--- a/target/i386/tcg/sysemu/svm_helper.c
++++ b/target/i386/tcg/sysemu/svm_helper.c
+@@ -164,14 +164,19 @@ void helper_vmrun(CPUX86State *env, int aflag, int next_eip_addend)
+ uint64_t new_cr3;
+ uint64_t new_cr4;
+
+- cpu_svm_check_intercept_param(env, SVM_EXIT_VMRUN, 0, GETPC());
+-
+ if (aflag == 2) {
+ addr = env->regs[R_EAX];
+ } else {
+ addr = (uint32_t)env->regs[R_EAX];
+ }
+
++ /* Exceptions are checked before the intercept. */
++ if (addr & (0xfff | ((~0ULL) << env_archcpu(env)->phys_bits))) {
++ raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC());
++ }
++
++ cpu_svm_check_intercept_param(env, SVM_EXIT_VMRUN, 0, GETPC());
++
+ qemu_log_mask(CPU_LOG_TB_IN_ASM, "vmrun! " TARGET_FMT_lx "\n", addr);
+
+ env->vm_vmcb = addr;
+@@ -465,14 +470,19 @@ void helper_vmload(CPUX86State *env, int aflag)
+ int mmu_idx = MMU_PHYS_IDX;
+ target_ulong addr;
+
+- cpu_svm_check_intercept_param(env, SVM_EXIT_VMLOAD, 0, GETPC());
+-
+ if (aflag == 2) {
+ addr = env->regs[R_EAX];
+ } else {
+ addr = (uint32_t)env->regs[R_EAX];
+ }
+
++ /* Exceptions are checked before the intercept. */
++ if (addr & (0xfff | ((~0ULL) << env_archcpu(env)->phys_bits))) {
++ raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC());
++ }
++
++ cpu_svm_check_intercept_param(env, SVM_EXIT_VMLOAD, 0, GETPC());
++
+ if (virtual_vm_load_save_enabled(env, SVM_EXIT_VMLOAD, GETPC())) {
+ mmu_idx = MMU_NESTED_IDX;
+ }
+@@ -521,14 +531,19 @@ void helper_vmsave(CPUX86State *env, int aflag)
+ int mmu_idx = MMU_PHYS_IDX;
+ target_ulong addr;
+
+- cpu_svm_check_intercept_param(env, SVM_EXIT_VMSAVE, 0, GETPC());
+-
+ if (aflag == 2) {
+ addr = env->regs[R_EAX];
+ } else {
+ addr = (uint32_t)env->regs[R_EAX];
+ }
+
++ /* Exceptions are checked before the intercept. */
++ if (addr & (0xfff | ((~0ULL) << env_archcpu(env)->phys_bits))) {
++ raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC());
++ }
++
++ cpu_svm_check_intercept_param(env, SVM_EXIT_VMSAVE, 0, GETPC());
++
+ if (virtual_vm_load_save_enabled(env, SVM_EXIT_VMSAVE, GETPC())) {
+ mmu_idx = MMU_NESTED_IDX;
+ }
+diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
+index 68c42fd9ff..abacb91ddf 100644
+--- a/target/i386/tcg/translate.c
++++ b/target/i386/tcg/translate.c
+@@ -1501,12 +1501,13 @@ static bool check_iopl(DisasContext *s)
+ /* if d == OR_TMP0, it means memory operand (address in A0) */
+ static void gen_op(DisasContext *s1, int op, MemOp ot, int d)
+ {
++ /* Invalid lock prefix when destination is not memory or OP_CMPL. */
++ if ((d != OR_TMP0 || op == OP_CMPL) && s1->prefix & PREFIX_LOCK) {
++ gen_illegal_opcode(s1);
++ return;
++ }
++
+ if (d != OR_TMP0) {
+- if (s1->prefix & PREFIX_LOCK) {
+- /* Lock prefix when destination is not memory. */
+- gen_illegal_opcode(s1);
+- return;
+- }
+ gen_op_mov_v_reg(s1, ot, s1->T0, d);
+ } else if (!(s1->prefix & PREFIX_LOCK)) {
+ gen_op_ld_v(s1, ot, s1->T0, s1->A0);
+diff --git a/target/ppc/translate/vsx-impl.c.inc b/target/ppc/translate/vsx-impl.c.inc
+index 4deb29ee42..de1709809d 100644
+--- a/target/ppc/translate/vsx-impl.c.inc
++++ b/target/ppc/translate/vsx-impl.c.inc
+@@ -2518,7 +2518,7 @@ static bool do_lstxv(DisasContext *ctx, int ra, TCGv displ,
+
+ static bool do_lstxv_D(DisasContext *ctx, arg_D *a, bool store, bool paired)
+ {
+- if (paired || a->rt >= 32) {
++ if (paired || a->rt < 32) {
+ REQUIRE_VSX(ctx);
+ } else {
+ REQUIRE_VECTOR(ctx);
+diff --git a/tests/data/acpi/q35/DSDT.cxl b/tests/data/acpi/q35/DSDT.cxl
+index f9c6dd4ee0..267709e4e4 100644
+Binary files a/tests/data/acpi/q35/DSDT.cxl and b/tests/data/acpi/q35/DSDT.cxl differ
+diff --git a/tests/qemu-iotests/144 b/tests/qemu-iotests/144
+index bdcc498fa2..d284a0e442 100755
+--- a/tests/qemu-iotests/144
++++ b/tests/qemu-iotests/144
+@@ -83,12 +83,22 @@ echo
+ echo === Performing block-commit on active layer ===
+ echo
+
++capture_events="BLOCK_JOB_READY JOB_STATUS_CHANGE"
++
+ # Block commit on active layer, push the new overlay into base
+ _send_qemu_cmd $h "{ 'execute': 'block-commit',
+ 'arguments': {
+ 'device': 'virtio0'
+ }
+- }" "READY"
++ }" "return"
++
++_wait_event $h "JOB_STATUS_CHANGE"
++_wait_event $h "JOB_STATUS_CHANGE"
++_wait_event $h "JOB_STATUS_CHANGE"
++
++_wait_event $h "BLOCK_JOB_READY"
++
++capture_events=
+
+ _send_qemu_cmd $h "{ 'execute': 'block-job-complete',
+ 'arguments': {
+diff --git a/tests/qemu-iotests/144.out b/tests/qemu-iotests/144.out
+index b3b4812015..2245ddfa10 100644
+--- a/tests/qemu-iotests/144.out
++++ b/tests/qemu-iotests/144.out
+@@ -25,9 +25,9 @@ Formatting 'TEST_DIR/tmp.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off co
+ 'device': 'virtio0'
+ }
+ }
++{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "virtio0"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "virtio0"}}
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "virtio0"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "virtio0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}}
+ { 'execute': 'block-job-complete',
+diff --git a/tests/qtest/display-vga-test.c b/tests/qtest/display-vga-test.c
+index ace3bb28e0..75b341a9c6 100644
+--- a/tests/qtest/display-vga-test.c
++++ b/tests/qtest/display-vga-test.c
+@@ -8,61 +8,46 @@
+ */
+
+ #include "qemu/osdep.h"
+-#include "libqtest-single.h"
+-
+-static void pci_cirrus(void)
+-{
+- qtest_start("-vga none -device cirrus-vga");
+- qtest_end();
+-}
+-
+-static void pci_stdvga(void)
+-{
+- qtest_start("-vga none -device VGA");
+- qtest_end();
+-}
+-
+-static void pci_secondary(void)
+-{
+- qtest_start("-vga none -device secondary-vga");
+- qtest_end();
+-}
++#include "libqtest.h"
+
+ static void pci_multihead(void)
+ {
+- qtest_start("-vga none -device VGA -device secondary-vga");
+- qtest_end();
+-}
++ QTestState *qts;
+
+-static void pci_virtio_gpu(void)
+-{
+- qtest_start("-vga none -device virtio-gpu-pci");
+- qtest_end();
++ qts = qtest_init("-vga none -device VGA -device secondary-vga");
++ qtest_quit(qts);
+ }
+
+-static void pci_virtio_vga(void)
++static void test_vga(gconstpointer data)
+ {
+- qtest_start("-vga none -device virtio-vga");
+- qtest_end();
++ QTestState *qts;
++
++ qts = qtest_initf("-vga none -device %s", (const char *)data);
++ qtest_quit(qts);
+ }
+
+ int main(int argc, char **argv)
+ {
+- const char *arch = qtest_get_arch();
++ static const char *devices[] = {
++ "cirrus-vga",
++ "VGA",
++ "secondary-vga",
++ "virtio-gpu-pci",
++ "virtio-vga"
++ };
+
+ g_test_init(&argc, &argv, NULL);
+
+- if (strcmp(arch, "alpha") == 0 || strcmp(arch, "i386") == 0 ||
+- strcmp(arch, "mips") == 0 || strcmp(arch, "x86_64") == 0) {
+- qtest_add_func("/display/pci/cirrus", pci_cirrus);
++ for (int i = 0; i < ARRAY_SIZE(devices); i++) {
++ if (qtest_has_device(devices[i])) {
++ char *testpath = g_strdup_printf("/display/pci/%s", devices[i]);
++ qtest_add_data_func(testpath, devices[i], test_vga);
++ g_free(testpath);
++ }
+ }
+- qtest_add_func("/display/pci/stdvga", pci_stdvga);
+- qtest_add_func("/display/pci/secondary", pci_secondary);
+- qtest_add_func("/display/pci/multihead", pci_multihead);
+- qtest_add_func("/display/pci/virtio-gpu", pci_virtio_gpu);
+- if (g_str_equal(arch, "i386") || g_str_equal(arch, "x86_64") ||
+- g_str_equal(arch, "hppa") || g_str_equal(arch, "ppc64")) {
+- qtest_add_func("/display/pci/virtio-vga", pci_virtio_vga);
++
++ if (qtest_has_device("secondary-vga")) {
++ qtest_add_func("/display/pci/multihead", pci_multihead);
+ }
+
+ return g_test_run();
+diff --git a/tests/unit/test-blockjob.c b/tests/unit/test-blockjob.c
+index c0426bd10c..a130f6fefb 100644
+--- a/tests/unit/test-blockjob.c
++++ b/tests/unit/test-blockjob.c
+@@ -531,6 +531,13 @@ int main(int argc, char **argv)
+ g_test_add_func("/blockjob/cancel/standby", test_cancel_standby);
+ g_test_add_func("/blockjob/cancel/pending", test_cancel_pending);
+ g_test_add_func("/blockjob/cancel/concluded", test_cancel_concluded);
+- g_test_add_func("/blockjob/complete_in_standby", test_complete_in_standby);
++
++ /*
++ * This test is flaky and sometimes fails in CI and otherwise:
++ * don't run unless user opts in via environment variable.
++ */
++ if (getenv("QEMU_TEST_FLAKY_TESTS")) {
++ g_test_add_func("/blockjob/complete_in_standby", test_complete_in_standby);
++ }
+ return g_test_run();
+ }
+diff --git a/tests/unit/test-util-sockets.c b/tests/unit/test-util-sockets.c
+index 63909ccb2b..4c9dd0b271 100644
+--- a/tests/unit/test-util-sockets.c
++++ b/tests/unit/test-util-sockets.c
+@@ -326,6 +326,7 @@ static void test_socket_unix_abstract(void)
+ test_socket_unix_abstract_row(&matrix[i]);
+ }
+
++ unlink(addr.u.q_unix.path);
+ g_free(addr.u.q_unix.path);
+ }
+
+diff --git a/tests/unit/test-vmstate.c b/tests/unit/test-vmstate.c
+index 541bb4f63e..aae32bbf91 100644
+--- a/tests/unit/test-vmstate.c
++++ b/tests/unit/test-vmstate.c
+@@ -1074,7 +1074,6 @@ static gboolean diff_tree(gpointer key, gpointer value, gpointer data)
+ struct match_node_data d = {tp->tree2, key, value};
+
+ g_tree_foreach(tp->tree2, tp->match_node, &d);
+- g_tree_remove(tp->tree1, key);
+ return false;
+ }
+
+@@ -1083,9 +1082,9 @@ static void compare_trees(GTree *tree1, GTree *tree2,
+ {
+ struct tree_cmp_data tp = {tree1, tree2, function};
+
++ assert(g_tree_nnodes(tree1) == g_tree_nnodes(tree2));
+ g_tree_foreach(tree1, diff_tree, &tp);
+- assert(g_tree_nnodes(tree1) == 0);
+- assert(g_tree_nnodes(tree2) == 0);
++ g_tree_destroy(g_tree_ref(tree1));
+ }
+
+ static void diff_domain(TestGTreeDomain *d1, TestGTreeDomain *d2)
+diff --git a/tests/vm/Makefile.include b/tests/vm/Makefile.include
+index 2cc2203d09..e332fd13c3 100644
+--- a/tests/vm/Makefile.include
++++ b/tests/vm/Makefile.include
+@@ -103,7 +103,7 @@ $(IMAGES_DIR)/%.img: $(SRC_PATH)/tests/vm/% \
+ $(if $(LOG_CONSOLE),--log-console) \
+ --source-path $(SRC_PATH) \
+ --image "$@" \
+- --force \
++ $(if $(filter-out check-venv, $?), --force) \
+ --build-image $@, \
+ " VM-IMAGE $*")
+
+diff --git a/tests/vm/basevm.py b/tests/vm/basevm.py
+index 2276364c42..6a54d9d4e0 100644
+--- a/tests/vm/basevm.py
++++ b/tests/vm/basevm.py
+@@ -634,9 +634,9 @@ def main(vmcls, config=None):
+ vm = vmcls(args, config=config)
+ if args.build_image:
+ if os.path.exists(args.image) and not args.force:
+- sys.stderr.writelines(["Image file exists: %s\n" % args.image,
++ sys.stderr.writelines(["Image file exists, skipping build: %s\n" % args.image,
+ "Use --force option to overwrite\n"])
+- return 1
++ return 0
+ return vm.build_image(args.image)
+ if args.build_qemu:
+ vm.add_source_dir(args.build_qemu)
+diff --git a/tests/vm/openbsd b/tests/vm/openbsd
+index eaeb201e91..f185aa96ab 100755
+--- a/tests/vm/openbsd
++++ b/tests/vm/openbsd
+@@ -22,8 +22,8 @@ class OpenBSDVM(basevm.BaseVM):
+ name = "openbsd"
+ arch = "x86_64"
+
+- link = "https://cdn.openbsd.org/pub/OpenBSD/7.2/amd64/install72.iso"
+- csum = "0369ef40a3329efcb978c578c7fdc7bda71e502aecec930a74b44160928c91d3"
++ link = "https://cdn.openbsd.org/pub/OpenBSD/7.4/amd64/install74.iso"
++ csum = "a1001736ed9fe2307965b5fcdb426ae11f9b80d26eb21e404a705144a0a224a0"
+ size = "20G"
+ pkgs = [
+ # tools
+@@ -97,10 +97,10 @@ class OpenBSDVM(basevm.BaseVM):
+ self.console_wait_send("(I)nstall", "i\n")
+ self.console_wait_send("Terminal type", "xterm\n")
+ self.console_wait_send("System hostname", "openbsd\n")
+- self.console_wait_send("Which network interface", "vio0\n")
++ self.console_wait_send("Network interface to configure", "vio0\n")
+ self.console_wait_send("IPv4 address", "autoconf\n")
+ self.console_wait_send("IPv6 address", "none\n")
+- self.console_wait_send("Which network interface", "done\n")
++ self.console_wait_send("Network interface to configure", "done\n")
+ self.console_wait("Password for root account")
+ self.console_send("%s\n" % self._config["root_pass"])
+ self.console_wait("Password for root account")
+@@ -123,6 +123,7 @@ class OpenBSDVM(basevm.BaseVM):
+ self.console_wait_send("Allow root ssh login", "yes\n")
+ self.console_wait_send("timezone", "UTC\n")
+ self.console_wait_send("root disk", "\n")
++ self.console_wait_send("Encrypt the root disk with a passphrase", "no\n")
+ self.console_wait_send("(W)hole disk", "\n")
+ self.console_wait_send("(A)uto layout", "\n")
+ self.console_wait_send("Location of sets", "cd0\n")
+diff --git a/ui/clipboard.c b/ui/clipboard.c
+index 3d14bffaf8..4264884a6c 100644
+--- a/ui/clipboard.c
++++ b/ui/clipboard.c
+@@ -65,12 +65,24 @@ bool qemu_clipboard_check_serial(QemuClipboardInfo *info, bool client)
+
+ void qemu_clipboard_update(QemuClipboardInfo *info)
+ {
++ uint32_t type;
+ QemuClipboardNotify notify = {
+ .type = QEMU_CLIPBOARD_UPDATE_INFO,
+ .info = info,
+ };
+ assert(info->selection < QEMU_CLIPBOARD_SELECTION__COUNT);
+
++ for (type = 0; type < QEMU_CLIPBOARD_TYPE__COUNT; type++) {
++ /*
++ * If data is missing, the clipboard owner's 'request' callback needs to
++ * be set. Otherwise, there is no way to get the clipboard data and
++ * qemu_clipboard_request() cannot be called.
++ */
++ if (info->types[type].available && !info->types[type].data) {
++ assert(info->owner && info->owner->request);
++ }
++ }
++
+ notifier_list_notify(&clipboard_notifiers, &notify);
+
+ if (cbinfo[info->selection] != info) {
+@@ -132,6 +144,8 @@ void qemu_clipboard_request(QemuClipboardInfo *info,
+ !info->owner)
+ return;
+
++ assert(info->owner->request);
++
+ info->types[type].requested = true;
+ info->owner->request(info, type);
+ }
+@@ -163,9 +177,15 @@ void qemu_clipboard_set_data(QemuClipboardPeer *peer,
+ }
+
+ g_free(info->types[type].data);
+- info->types[type].data = g_memdup(data, size);
+- info->types[type].size = size;
+- info->types[type].available = true;
++ if (size) {
++ info->types[type].data = g_memdup2(data, size);
++ info->types[type].size = size;
++ info->types[type].available = true;
++ } else {
++ info->types[type].data = NULL;
++ info->types[type].size = 0;
++ info->types[type].available = false;
++ }
+
+ if (update) {
+ qemu_clipboard_update(info);
+diff --git a/ui/console.c b/ui/console.c
+index 52414d6aa3..269cf27163 100644
+--- a/ui/console.c
++++ b/ui/console.c
+@@ -2583,7 +2583,7 @@ void qemu_console_resize(QemuConsole *s, int width, int height)
+ assert(s->console_type == GRAPHIC_CONSOLE);
+
+ if ((s->scanout.kind != SCANOUT_SURFACE ||
+- (surface && surface->flags & QEMU_ALLOCATED_FLAG)) &&
++ (surface && !is_buffer_shared(surface) && !is_placeholder(surface))) &&
+ qemu_console_get_width(s, -1) == width &&
+ qemu_console_get_height(s, -1) == height) {
+ return;
+diff --git a/ui/meson.build b/ui/meson.build
+index c1b137bf33..76c6644b3f 100644
+--- a/ui/meson.build
++++ b/ui/meson.build
+@@ -81,7 +81,9 @@ if dbus_display
+ '--interface-prefix', 'org.qemu.',
+ '--c-namespace', 'QemuDBus',
+ '--generate-c-code', '@BASENAME@'])
+- dbus_ss.add(when: [gio, pixman, opengl, gbm],
++ dbus_display1_lib = static_library('dbus-display1', dbus_display1, dependencies: gio)
++ dbus_display1_dep = declare_dependency(link_with: dbus_display1_lib, include_directories: include_directories('.'))
++ dbus_ss.add(when: [gio, pixman, opengl, gbm, dbus_display1_dep],
+ if_true: [files(
+ 'dbus-chardev.c',
+ 'dbus-clipboard.c',
+@@ -89,7 +91,7 @@ if dbus_display
+ 'dbus-error.c',
+ 'dbus-listener.c',
+ 'dbus.c',
+- ), dbus_display1])
++ )])
+ ui_modules += {'dbus' : dbus_ss}
+ endif
+
+diff --git a/ui/vnc.c b/ui/vnc.c
+index 1ca16c0ff6..629a500adc 100644
+--- a/ui/vnc.c
++++ b/ui/vnc.c
+@@ -2456,6 +2456,11 @@ static int protocol_client_msg(VncState *vs, uint8_t *data, size_t len)
+ }
+
+ if (read_s32(data, 4) < 0) {
++ if (!vnc_has_feature(vs, VNC_FEATURE_CLIPBOARD_EXT)) {
++ error_report("vnc: extended clipboard message while disabled");
++ vnc_client_error(vs);
++ break;
++ }
+ if (dlen < 4) {
+ error_report("vnc: malformed payload (header less than 4 bytes)"
+ " in extended clipboard pseudo-encoding.");
diff --git a/debian/patches/v7.2.11.diff b/debian/patches/v7.2.11.diff
new file mode 100644
index 00000000..d7bb53c4
--- /dev/null
+++ b/debian/patches/v7.2.11.diff
@@ -0,0 +1,2353 @@
+Subject: v7.2.11
+Date: Wed Apr 24 06:02:50 2024 +0300
+From: Michael Tokarev <mjt@tls.msk.ru>
+Forwarded: not-needed
+
+This is a difference between upstream qemu v7.2.10
+and upstream qemu v7.2.11.
+
+
+ .gitlab-ci.d/cirrus.yml | 4 +-
+ VERSION | 2 +-
+ backends/cryptodev-builtin.c | 4 +-
+ hw/acpi/hmat.c | 6 +-
+ hw/block/nand.c | 55 +++++++----
+ hw/char/virtio-serial-bus.c | 3 +-
+ hw/core/machine.c | 1 +
+ hw/display/virtio-gpu.c | 6 +-
+ hw/intc/arm_gicv3_cpuif.c | 4 +-
+ hw/misc/applesmc.c | 1 +
+ hw/net/e1000e_core.c | 60 ++----------
+ hw/net/e1000e_core.h | 2 -
+ hw/net/lan9118.c | 28 +++++-
+ hw/net/pcnet.c | 2 +-
+ hw/net/virtio-net.c | 8 +-
+ hw/nvme/ctrl.c | 178 +++++++++++++++++++----------------
+ hw/nvme/nvme.h | 1 +
+ hw/pci/pcie_sriov.c | 8 ++
+ hw/ppc/spapr.c | 9 +-
+ hw/ppc/spapr_irq.c | 6 +-
+ hw/rtc/sun4v-rtc.c | 2 +-
+ hw/scsi/lsi53c895a.c | 60 +++++++++---
+ hw/scsi/scsi-generic.c | 1 -
+ hw/scsi/trace-events | 2 +
+ hw/sd/sdhci.c | 8 ++
+ hw/virtio/virtio-crypto.c | 4 +-
+ hw/virtio/virtio.c | 22 ++++-
+ include/hw/pci/pcie_sriov.h | 3 +
+ include/hw/ppc/spapr_irq.h | 14 ++-
+ include/hw/rtc/sun4v-rtc.h | 2 +-
+ include/hw/virtio/virtio.h | 7 ++
+ linux-user/syscall.c | 22 +++--
+ migration/block.c | 5 +-
+ monitor/misc.c | 2 +-
+ qemu-options.hx | 6 +-
+ scripts/make-release | 2 +-
+ softmmu/qdev-monitor.c | 23 +++--
+ target/arm/helper.c | 96 +++++++++++++++----
+ target/arm/translate-sme.c | 24 +++--
+ target/hppa/translate.c | 1 +
+ target/i386/cpu-param.h | 2 +-
+ target/i386/cpu.h | 50 +++++++---
+ target/i386/helper.c | 2 +-
+ target/i386/tcg/sysemu/excp_helper.c | 7 +-
+ target/loongarch/cpu.c | 72 +++++++-------
+ target/sh4/translate.c | 3 +
+ tcg/optimize.c | 19 ++--
+ tests/tcg/aarch64/Makefile.target | 12 ++-
+ tests/tcg/aarch64/sme-outprod1.c | 83 ++++++++++++++++
+ tests/tcg/aarch64/sysregs.c | 27 ++++--
+ tests/tcg/aarch64/test-2150.c | 12 +++
+ tests/tcg/aarch64/test-2248.c | 28 ++++++
+ tests/unit/meson.build | 8 +-
+ ui/cocoa.m | 7 ++
+ 54 files changed, 708 insertions(+), 318 deletions(-)
+
+diff --git a/.gitlab-ci.d/cirrus.yml b/.gitlab-ci.d/cirrus.yml
+index 634a73a742..c86487da5b 100644
+--- a/.gitlab-ci.d/cirrus.yml
++++ b/.gitlab-ci.d/cirrus.yml
+@@ -13,7 +13,7 @@
+ .cirrus_build_job:
+ extends: .base_job_template
+ stage: build
+- image: registry.gitlab.com/libvirt/libvirt-ci/cirrus-run:master
++ image: registry.gitlab.com/libvirt/libvirt-ci/cirrus-run:latest
+ needs: []
+ timeout: 80m
+ allow_failure: true
+@@ -63,7 +63,7 @@ x64-freebsd-13-build:
+ NAME: freebsd-13
+ CIRRUS_VM_INSTANCE_TYPE: freebsd_instance
+ CIRRUS_VM_IMAGE_SELECTOR: image_family
+- CIRRUS_VM_IMAGE_NAME: freebsd-13-1
++ CIRRUS_VM_IMAGE_NAME: freebsd-13-3
+ CIRRUS_VM_CPUS: 8
+ CIRRUS_VM_RAM: 8G
+ UPDATE_COMMAND: pkg update
+diff --git a/VERSION b/VERSION
+index 6bfb3a0ba9..971381d35b 100644
+--- a/VERSION
++++ b/VERSION
+@@ -1 +1 @@
+-7.2.10
++7.2.11
+diff --git a/backends/cryptodev-builtin.c b/backends/cryptodev-builtin.c
+index cda6ca3b71..2e792be756 100644
+--- a/backends/cryptodev-builtin.c
++++ b/backends/cryptodev-builtin.c
+@@ -416,7 +416,9 @@ static int cryptodev_builtin_close_session(
+ CRYPTODEV_BACKEND_BUILTIN(backend);
+ CryptoDevBackendBuiltinSession *session;
+
+- assert(session_id < MAX_NUM_SESSIONS && builtin->sessions[session_id]);
++ if (session_id >= MAX_NUM_SESSIONS || !builtin->sessions[session_id]) {
++ return -VIRTIO_CRYPTO_INVSESS;
++ }
+
+ session = builtin->sessions[session_id];
+ if (session->cipher) {
+diff --git a/hw/acpi/hmat.c b/hw/acpi/hmat.c
+index 3a6d51282a..768038e0da 100644
+--- a/hw/acpi/hmat.c
++++ b/hw/acpi/hmat.c
+@@ -77,6 +77,7 @@ static void build_hmat_lb(GArray *table_data, HMAT_LB_Info *hmat_lb,
+ uint32_t *initiator_list)
+ {
+ int i, index;
++ uint32_t initiator_to_index[MAX_NODES] = {};
+ HMAT_LB_Data *lb_data;
+ uint16_t *entry_list;
+ uint32_t base;
+@@ -120,6 +121,8 @@ static void build_hmat_lb(GArray *table_data, HMAT_LB_Info *hmat_lb,
+ /* Initiator Proximity Domain List */
+ for (i = 0; i < num_initiator; i++) {
+ build_append_int_noprefix(table_data, initiator_list[i], 4);
++ /* Reverse mapping for array possitions */
++ initiator_to_index[initiator_list[i]] = i;
+ }
+
+ /* Target Proximity Domain List */
+@@ -131,7 +134,8 @@ static void build_hmat_lb(GArray *table_data, HMAT_LB_Info *hmat_lb,
+ entry_list = g_new0(uint16_t, num_initiator * num_target);
+ for (i = 0; i < hmat_lb->list->len; i++) {
+ lb_data = &g_array_index(hmat_lb->list, HMAT_LB_Data, i);
+- index = lb_data->initiator * num_target + lb_data->target;
++ index = initiator_to_index[lb_data->initiator] * num_target +
++ lb_data->target;
+
+ entry_list[index] = (uint16_t)(lb_data->data / hmat_lb->base);
+ }
+diff --git a/hw/block/nand.c b/hw/block/nand.c
+index 1aee1cb2b1..d994bfe372 100644
+--- a/hw/block/nand.c
++++ b/hw/block/nand.c
+@@ -84,7 +84,11 @@ struct NANDFlashState {
+
+ void (*blk_write)(NANDFlashState *s);
+ void (*blk_erase)(NANDFlashState *s);
+- void (*blk_load)(NANDFlashState *s, uint64_t addr, int offset);
++ /*
++ * Returns %true when block containing (@addr + @offset) is
++ * successfully loaded, otherwise %false.
++ */
++ bool (*blk_load)(NANDFlashState *s, uint64_t addr, unsigned offset);
+
+ uint32_t ioaddr_vmstate;
+ };
+@@ -243,9 +247,30 @@ static inline void nand_pushio_byte(NANDFlashState *s, uint8_t value)
+ }
+ }
+
++/*
++ * nand_load_block: Load block containing (s->addr + @offset).
++ * Returns length of data available at @offset in this block.
++ */
++static unsigned nand_load_block(NANDFlashState *s, unsigned offset)
++{
++ unsigned iolen;
++
++ if (!s->blk_load(s, s->addr, offset)) {
++ return 0;
++ }
++
++ iolen = (1 << s->page_shift);
++ if (s->gnd) {
++ iolen += 1 << s->oob_shift;
++ }
++ assert(offset <= iolen);
++ iolen -= offset;
++
++ return iolen;
++}
++
+ static void nand_command(NANDFlashState *s)
+ {
+- unsigned int offset;
+ switch (s->cmd) {
+ case NAND_CMD_READ0:
+ s->iolen = 0;
+@@ -271,12 +296,7 @@ static void nand_command(NANDFlashState *s)
+ case NAND_CMD_NOSERIALREAD2:
+ if (!(nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP))
+ break;
+- offset = s->addr & ((1 << s->addr_shift) - 1);
+- s->blk_load(s, s->addr, offset);
+- if (s->gnd)
+- s->iolen = (1 << s->page_shift) - offset;
+- else
+- s->iolen = (1 << s->page_shift) + (1 << s->oob_shift) - offset;
++ s->iolen = nand_load_block(s, s->addr & ((1 << s->addr_shift) - 1));
+ break;
+
+ case NAND_CMD_RESET:
+@@ -597,12 +617,7 @@ uint32_t nand_getio(DeviceState *dev)
+ if (!s->iolen && s->cmd == NAND_CMD_READ0) {
+ offset = (int) (s->addr & ((1 << s->addr_shift) - 1)) + s->offset;
+ s->offset = 0;
+-
+- s->blk_load(s, s->addr, offset);
+- if (s->gnd)
+- s->iolen = (1 << s->page_shift) - offset;
+- else
+- s->iolen = (1 << s->page_shift) + (1 << s->oob_shift) - offset;
++ s->iolen = nand_load_block(s, offset);
+ }
+
+ if (s->ce || s->iolen <= 0) {
+@@ -763,11 +778,15 @@ static void glue(nand_blk_erase_, NAND_PAGE_SIZE)(NANDFlashState *s)
+ }
+ }
+
+-static void glue(nand_blk_load_, NAND_PAGE_SIZE)(NANDFlashState *s,
+- uint64_t addr, int offset)
++static bool glue(nand_blk_load_, NAND_PAGE_SIZE)(NANDFlashState *s,
++ uint64_t addr, unsigned offset)
+ {
+ if (PAGE(addr) >= s->pages) {
+- return;
++ return false;
++ }
++
++ if (offset > NAND_PAGE_SIZE + OOB_SIZE) {
++ return false;
+ }
+
+ if (s->blk) {
+@@ -795,6 +814,8 @@ static void glue(nand_blk_load_, NAND_PAGE_SIZE)(NANDFlashState *s,
+ offset, NAND_PAGE_SIZE + OOB_SIZE - offset);
+ s->ioaddr = s->io;
+ }
++
++ return true;
+ }
+
+ static void glue(nand_init_, NAND_PAGE_SIZE)(NANDFlashState *s)
+diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c
+index dd619f0731..1221fb7f15 100644
+--- a/hw/char/virtio-serial-bus.c
++++ b/hw/char/virtio-serial-bus.c
+@@ -985,8 +985,7 @@ static void virtser_port_device_realize(DeviceState *dev, Error **errp)
+ return;
+ }
+
+- port->bh = qemu_bh_new_guarded(flush_queued_data_bh, port,
+- &dev->mem_reentrancy_guard);
++ port->bh = virtio_bh_new_guarded(dev, flush_queued_data_bh, port);
+ port->elem = NULL;
+ }
+
+diff --git a/hw/core/machine.c b/hw/core/machine.c
+index 19f42450f5..1daaace9a3 100644
+--- a/hw/core/machine.c
++++ b/hw/core/machine.c
+@@ -80,6 +80,7 @@ GlobalProperty hw_compat_5_2[] = {
+ { "PIIX4_PM", "smm-compat", "on"},
+ { "virtio-blk-device", "report-discard-granularity", "off" },
+ { "virtio-net-pci-base", "vectors", "3"},
++ { "nvme", "msix-exclusive-bar", "on"},
+ };
+ const size_t hw_compat_5_2_len = G_N_ELEMENTS(hw_compat_5_2);
+
+diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
+index 7c13b056b9..d353b99e93 100644
+--- a/hw/display/virtio-gpu.c
++++ b/hw/display/virtio-gpu.c
+@@ -1356,10 +1356,8 @@ void virtio_gpu_device_realize(DeviceState *qdev, Error **errp)
+
+ g->ctrl_vq = virtio_get_queue(vdev, 0);
+ g->cursor_vq = virtio_get_queue(vdev, 1);
+- g->ctrl_bh = qemu_bh_new_guarded(virtio_gpu_ctrl_bh, g,
+- &qdev->mem_reentrancy_guard);
+- g->cursor_bh = qemu_bh_new_guarded(virtio_gpu_cursor_bh, g,
+- &qdev->mem_reentrancy_guard);
++ g->ctrl_bh = virtio_bh_new_guarded(qdev, virtio_gpu_ctrl_bh, g);
++ g->cursor_bh = virtio_bh_new_guarded(qdev, virtio_gpu_cursor_bh, g);
+ QTAILQ_INIT(&g->reslist);
+ QTAILQ_INIT(&g->cmdq);
+ QTAILQ_INIT(&g->fenceq);
+diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
+index f71b3b07d8..ddfbc69d65 100644
+--- a/hw/intc/arm_gicv3_cpuif.c
++++ b/hw/intc/arm_gicv3_cpuif.c
+@@ -1065,7 +1065,7 @@ static uint64_t icc_hppir0_value(GICv3CPUState *cs, CPUARMState *env)
+ */
+ bool irq_is_secure;
+
+- if (cs->hppi.prio == 0xff) {
++ if (icc_no_enabled_hppi(cs)) {
+ return INTID_SPURIOUS;
+ }
+
+@@ -1102,7 +1102,7 @@ static uint64_t icc_hppir1_value(GICv3CPUState *cs, CPUARMState *env)
+ */
+ bool irq_is_secure;
+
+- if (cs->hppi.prio == 0xff) {
++ if (icc_no_enabled_hppi(cs)) {
+ return INTID_SPURIOUS;
+ }
+
+diff --git a/hw/misc/applesmc.c b/hw/misc/applesmc.c
+index 5f9c742e50..80642efc57 100644
+--- a/hw/misc/applesmc.c
++++ b/hw/misc/applesmc.c
+@@ -273,6 +273,7 @@ static void qdev_applesmc_isa_reset(DeviceState *dev)
+ /* Remove existing entries */
+ QLIST_FOREACH_SAFE(d, &s->data_def, node, next) {
+ QLIST_REMOVE(d, node);
++ g_free(d);
+ }
+ s->status = 0x00;
+ s->status_1e = 0x00;
+diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c
+index c71d82ce1d..742f5ec800 100644
+--- a/hw/net/e1000e_core.c
++++ b/hw/net/e1000e_core.c
+@@ -108,14 +108,6 @@ e1000e_intmgr_timer_resume(E1000IntrDelayTimer *timer)
+ }
+ }
+
+-static void
+-e1000e_intmgr_timer_pause(E1000IntrDelayTimer *timer)
+-{
+- if (timer->running) {
+- timer_del(timer->timer);
+- }
+-}
+-
+ static inline void
+ e1000e_intrmgr_stop_timer(E1000IntrDelayTimer *timer)
+ {
+@@ -397,24 +389,6 @@ e1000e_intrmgr_resume(E1000ECore *core)
+ }
+ }
+
+-static void
+-e1000e_intrmgr_pause(E1000ECore *core)
+-{
+- int i;
+-
+- e1000e_intmgr_timer_pause(&core->radv);
+- e1000e_intmgr_timer_pause(&core->rdtr);
+- e1000e_intmgr_timer_pause(&core->raid);
+- e1000e_intmgr_timer_pause(&core->tidv);
+- e1000e_intmgr_timer_pause(&core->tadv);
+-
+- e1000e_intmgr_timer_pause(&core->itr);
+-
+- for (i = 0; i < E1000E_MSIX_VEC_NUM; i++) {
+- e1000e_intmgr_timer_pause(&core->eitr[i]);
+- }
+-}
+-
+ static void
+ e1000e_intrmgr_reset(E1000ECore *core)
+ {
+@@ -3336,12 +3310,6 @@ e1000e_core_read(E1000ECore *core, hwaddr addr, unsigned size)
+ return 0;
+ }
+
+-static inline void
+-e1000e_autoneg_pause(E1000ECore *core)
+-{
+- timer_del(core->autoneg_timer);
+-}
+-
+ static void
+ e1000e_autoneg_resume(E1000ECore *core)
+ {
+@@ -3353,22 +3321,6 @@ e1000e_autoneg_resume(E1000ECore *core)
+ }
+ }
+
+-static void
+-e1000e_vm_state_change(void *opaque, bool running, RunState state)
+-{
+- E1000ECore *core = opaque;
+-
+- if (running) {
+- trace_e1000e_vm_state_running();
+- e1000e_intrmgr_resume(core);
+- e1000e_autoneg_resume(core);
+- } else {
+- trace_e1000e_vm_state_stopped();
+- e1000e_autoneg_pause(core);
+- e1000e_intrmgr_pause(core);
+- }
+-}
+-
+ void
+ e1000e_core_pci_realize(E1000ECore *core,
+ const uint16_t *eeprom_templ,
+@@ -3381,9 +3333,6 @@ e1000e_core_pci_realize(E1000ECore *core,
+ e1000e_autoneg_timer, core);
+ e1000e_intrmgr_pci_realize(core);
+
+- core->vmstate =
+- qemu_add_vm_change_state_handler(e1000e_vm_state_change, core);
+-
+ for (i = 0; i < E1000E_NUM_QUEUES; i++) {
+ net_tx_pkt_init(&core->tx[i].tx_pkt, core->owner,
+ E1000E_MAX_TX_FRAGS, core->has_vnet);
+@@ -3408,8 +3357,6 @@ e1000e_core_pci_uninit(E1000ECore *core)
+
+ e1000e_intrmgr_pci_unint(core);
+
+- qemu_del_vm_change_state_handler(core->vmstate);
+-
+ for (i = 0; i < E1000E_NUM_QUEUES; i++) {
+ net_tx_pkt_reset(core->tx[i].tx_pkt);
+ net_tx_pkt_uninit(core->tx[i].tx_pkt);
+@@ -3561,5 +3508,12 @@ e1000e_core_post_load(E1000ECore *core)
+ */
+ nc->link_down = (core->mac[STATUS] & E1000_STATUS_LU) == 0;
+
++ /*
++ * we need to restart intrmgr timers, as an older version of
++ * QEMU can have stopped them before migration
++ */
++ e1000e_intrmgr_resume(core);
++ e1000e_autoneg_resume(core);
++
+ return 0;
+ }
+diff --git a/hw/net/e1000e_core.h b/hw/net/e1000e_core.h
+index 4ddb4d2c39..f2a8ff4a33 100644
+--- a/hw/net/e1000e_core.h
++++ b/hw/net/e1000e_core.h
+@@ -100,8 +100,6 @@ struct E1000Core {
+ E1000IntrDelayTimer eitr[E1000E_MSIX_VEC_NUM];
+ bool eitr_intr_pending[E1000E_MSIX_VEC_NUM];
+
+- VMChangeStateEntry *vmstate;
+-
+ uint32_t itr_guest_value;
+ uint32_t eitr_guest_value[E1000E_MSIX_VEC_NUM];
+
+diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c
+index 00a6d82efb..f269d72d9e 100644
+--- a/hw/net/lan9118.c
++++ b/hw/net/lan9118.c
+@@ -155,6 +155,12 @@ do { fprintf(stderr, "lan9118: error: " fmt , ## __VA_ARGS__);} while (0)
+
+ #define GPT_TIMER_EN 0x20000000
+
++/*
++ * The MAC Interface Layer (MIL), within the MAC, contains a 2K Byte transmit
++ * and a 128 Byte receive FIFO which is separate from the TX and RX FIFOs.
++ */
++#define MIL_TXFIFO_SIZE 2048
++
+ enum tx_state {
+ TX_IDLE,
+ TX_B,
+@@ -171,7 +177,7 @@ typedef struct {
+ int32_t pad;
+ int32_t fifo_used;
+ int32_t len;
+- uint8_t data[2048];
++ uint8_t data[MIL_TXFIFO_SIZE];
+ } LAN9118Packet;
+
+ static const VMStateDescription vmstate_lan9118_packet = {
+@@ -187,7 +193,7 @@ static const VMStateDescription vmstate_lan9118_packet = {
+ VMSTATE_INT32(pad, LAN9118Packet),
+ VMSTATE_INT32(fifo_used, LAN9118Packet),
+ VMSTATE_INT32(len, LAN9118Packet),
+- VMSTATE_UINT8_ARRAY(data, LAN9118Packet, 2048),
++ VMSTATE_UINT8_ARRAY(data, LAN9118Packet, MIL_TXFIFO_SIZE),
+ VMSTATE_END_OF_LIST()
+ }
+ };
+@@ -549,7 +555,7 @@ static ssize_t lan9118_receive(NetClientState *nc, const uint8_t *buf,
+ return -1;
+ }
+
+- if (size >= 2048 || size < 14) {
++ if (size >= MIL_TXFIFO_SIZE || size < 14) {
+ return -1;
+ }
+
+@@ -798,8 +804,22 @@ static void tx_fifo_push(lan9118_state *s, uint32_t val)
+ /* Documentation is somewhat unclear on the ordering of bytes
+ in FIFO words. Empirical results show it to be little-endian.
+ */
+- /* TODO: FIFO overflow checking. */
+ while (n--) {
++ if (s->txp->len == MIL_TXFIFO_SIZE) {
++ /*
++ * No more space in the FIFO. The datasheet is not
++ * precise about this case. We choose what is easiest
++ * to model: the packet is truncated, and TXE is raised.
++ *
++ * Note, it could be a fragmented packet, but we currently
++ * do not handle that (see earlier TX_B case).
++ */
++ qemu_log_mask(LOG_GUEST_ERROR,
++ "MIL TX FIFO overrun, discarding %u byte%s\n",
++ n, n > 1 ? "s" : "");
++ s->int_sts |= TXE_INT;
++ break;
++ }
+ s->txp->data[s->txp->len] = val & 0xff;
+ s->txp->len++;
+ val >>= 8;
+diff --git a/hw/net/pcnet.c b/hw/net/pcnet.c
+index 56c3d14ad6..05ce8310ef 100644
+--- a/hw/net/pcnet.c
++++ b/hw/net/pcnet.c
+@@ -632,7 +632,7 @@ static inline int ladr_match(PCNetState *s, const uint8_t *buf, int size)
+ {
+ struct qemu_ether_header *hdr = (void *)buf;
+ if ((*(hdr->ether_dhost)&0x01) &&
+- ((uint64_t *)&s->csr[8])[0] != 0LL) {
++ (s->csr[8] | s->csr[9] | s->csr[10] | s->csr[11]) != 0) {
+ uint8_t ladr[8] = {
+ s->csr[8] & 0xff, s->csr[8] >> 8,
+ s->csr[9] & 0xff, s->csr[9] >> 8,
+diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
+index 412cba4927..b6177a6afe 100644
+--- a/hw/net/virtio-net.c
++++ b/hw/net/virtio-net.c
+@@ -2746,6 +2746,10 @@ static void virtio_net_handle_tx_bh(VirtIODevice *vdev, VirtQueue *vq)
+ VirtIONet *n = VIRTIO_NET(vdev);
+ VirtIONetQueue *q = &n->vqs[vq2q(virtio_get_queue_index(vq))];
+
++ if (unlikely(n->vhost_started)) {
++ return;
++ }
++
+ if (unlikely((n->status & VIRTIO_NET_S_LINK_UP) == 0)) {
+ virtio_net_drop_tx_queue_data(vdev, vq);
+ return;
+@@ -3307,7 +3311,7 @@ static bool virtio_net_guest_notifier_pending(VirtIODevice *vdev, int idx)
+ VirtIONet *n = VIRTIO_NET(vdev);
+ NetClientState *nc;
+ assert(n->vhost_started);
+- if (!virtio_vdev_has_feature(vdev, VIRTIO_NET_F_MQ) && idx == 2) {
++ if (!n->multiqueue && idx == 2) {
+ /* Must guard against invalid features and bogus queue index
+ * from being set by malicious guest, or penetrated through
+ * buggy migration stream.
+@@ -3330,7 +3334,7 @@ static void virtio_net_guest_notifier_mask(VirtIODevice *vdev, int idx,
+ VirtIONet *n = VIRTIO_NET(vdev);
+ NetClientState *nc;
+ assert(n->vhost_started);
+- if (!virtio_vdev_has_feature(vdev, VIRTIO_NET_F_MQ) && idx == 2) {
++ if (!n->multiqueue && idx == 2) {
+ /* Must guard against invalid features and bogus queue index
+ * from being set by malicious guest, or penetrated through
+ * buggy migration stream.
+diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c
+index a87f79296c..027d67f10b 100644
+--- a/hw/nvme/ctrl.c
++++ b/hw/nvme/ctrl.c
+@@ -6980,7 +6980,7 @@ static const MemoryRegionOps nvme_cmb_ops = {
+ },
+ };
+
+-static void nvme_check_constraints(NvmeCtrl *n, Error **errp)
++static bool nvme_check_params(NvmeCtrl *n, Error **errp)
+ {
+ NvmeParams *params = &n->params;
+
+@@ -6994,38 +6994,43 @@ static void nvme_check_constraints(NvmeCtrl *n, Error **errp)
+ if (n->namespace.blkconf.blk && n->subsys) {
+ error_setg(errp, "subsystem support is unavailable with legacy "
+ "namespace ('drive' property)");
+- return;
++ return false;
+ }
+
+ if (params->max_ioqpairs < 1 ||
+ params->max_ioqpairs > NVME_MAX_IOQPAIRS) {
+ error_setg(errp, "max_ioqpairs must be between 1 and %d",
+ NVME_MAX_IOQPAIRS);
+- return;
++ return false;
+ }
+
+ if (params->msix_qsize < 1 ||
+ params->msix_qsize > PCI_MSIX_FLAGS_QSIZE + 1) {
+ error_setg(errp, "msix_qsize must be between 1 and %d",
+ PCI_MSIX_FLAGS_QSIZE + 1);
+- return;
++ return false;
+ }
+
+ if (!params->serial) {
+ error_setg(errp, "serial property not set");
+- return;
++ return false;
+ }
+
+ if (n->pmr.dev) {
++ if (params->msix_exclusive_bar) {
++ error_setg(errp, "not enough BARs available to enable PMR");
++ return false;
++ }
++
+ if (host_memory_backend_is_mapped(n->pmr.dev)) {
+ error_setg(errp, "can't use already busy memdev: %s",
+ object_get_canonical_path_component(OBJECT(n->pmr.dev)));
+- return;
++ return false;
+ }
+
+ if (!is_power_of_2(n->pmr.dev->size)) {
+ error_setg(errp, "pmr backend size needs to be power of 2 in size");
+- return;
++ return false;
+ }
+
+ host_memory_backend_set_mapped(n->pmr.dev, true);
+@@ -7034,64 +7039,64 @@ static void nvme_check_constraints(NvmeCtrl *n, Error **errp)
+ if (n->params.zasl > n->params.mdts) {
+ error_setg(errp, "zoned.zasl (Zone Append Size Limit) must be less "
+ "than or equal to mdts (Maximum Data Transfer Size)");
+- return;
++ return false;
+ }
+
+ if (!n->params.vsl) {
+ error_setg(errp, "vsl must be non-zero");
+- return;
++ return false;
+ }
+
+ if (params->sriov_max_vfs) {
+ if (!n->subsys) {
+ error_setg(errp, "subsystem is required for the use of SR-IOV");
+- return;
++ return false;
+ }
+
+ if (params->sriov_max_vfs > NVME_MAX_VFS) {
+ error_setg(errp, "sriov_max_vfs must be between 0 and %d",
+ NVME_MAX_VFS);
+- return;
++ return false;
+ }
+
+ if (params->cmb_size_mb) {
+ error_setg(errp, "CMB is not supported with SR-IOV");
+- return;
++ return false;
+ }
+
+ if (n->pmr.dev) {
+ error_setg(errp, "PMR is not supported with SR-IOV");
+- return;
++ return false;
+ }
+
+ if (!params->sriov_vq_flexible || !params->sriov_vi_flexible) {
+ error_setg(errp, "both sriov_vq_flexible and sriov_vi_flexible"
+ " must be set for the use of SR-IOV");
+- return;
++ return false;
+ }
+
+ if (params->sriov_vq_flexible < params->sriov_max_vfs * 2) {
+ error_setg(errp, "sriov_vq_flexible must be greater than or equal"
+ " to %d (sriov_max_vfs * 2)", params->sriov_max_vfs * 2);
+- return;
++ return false;
+ }
+
+ if (params->max_ioqpairs < params->sriov_vq_flexible + 2) {
+ error_setg(errp, "(max_ioqpairs - sriov_vq_flexible) must be"
+ " greater than or equal to 2");
+- return;
++ return false;
+ }
+
+ if (params->sriov_vi_flexible < params->sriov_max_vfs) {
+ error_setg(errp, "sriov_vi_flexible must be greater than or equal"
+ " to %d (sriov_max_vfs)", params->sriov_max_vfs);
+- return;
++ return false;
+ }
+
+ if (params->msix_qsize < params->sriov_vi_flexible + 1) {
+ error_setg(errp, "(msix_qsize - sriov_vi_flexible) must be"
+ " greater than or equal to 1");
+- return;
++ return false;
+ }
+
+ if (params->sriov_max_vi_per_vf &&
+@@ -7099,7 +7104,7 @@ static void nvme_check_constraints(NvmeCtrl *n, Error **errp)
+ error_setg(errp, "sriov_max_vi_per_vf must meet:"
+ " (sriov_max_vi_per_vf - 1) %% %d == 0 and"
+ " sriov_max_vi_per_vf >= 1", NVME_VF_RES_GRANULARITY);
+- return;
++ return false;
+ }
+
+ if (params->sriov_max_vq_per_vf &&
+@@ -7108,9 +7113,11 @@ static void nvme_check_constraints(NvmeCtrl *n, Error **errp)
+ error_setg(errp, "sriov_max_vq_per_vf must meet:"
+ " (sriov_max_vq_per_vf - 1) %% %d == 0 and"
+ " sriov_max_vq_per_vf >= 2", NVME_VF_RES_GRANULARITY);
+- return;
++ return false;
+ }
+ }
++
++ return true;
+ }
+
+ static void nvme_init_state(NvmeCtrl *n)
+@@ -7219,13 +7226,18 @@ static void nvme_init_pmr(NvmeCtrl *n, PCIDevice *pci_dev)
+ memory_region_set_enabled(&n->pmr.dev->mr, false);
+ }
+
+-static uint64_t nvme_bar_size(unsigned total_queues, unsigned total_irqs,
+- unsigned *msix_table_offset,
+- unsigned *msix_pba_offset)
++static uint64_t nvme_mbar_size(unsigned total_queues, unsigned total_irqs,
++ unsigned *msix_table_offset,
++ unsigned *msix_pba_offset)
+ {
+- uint64_t bar_size, msix_table_size, msix_pba_size;
++ uint64_t bar_size, msix_table_size;
+
+ bar_size = sizeof(NvmeBar) + 2 * total_queues * NVME_DB_SIZE;
++
++ if (total_irqs == 0) {
++ goto out;
++ }
++
+ bar_size = QEMU_ALIGN_UP(bar_size, 4 * KiB);
+
+ if (msix_table_offset) {
+@@ -7240,11 +7252,10 @@ static uint64_t nvme_bar_size(unsigned total_queues, unsigned total_irqs,
+ *msix_pba_offset = bar_size;
+ }
+
+- msix_pba_size = QEMU_ALIGN_UP(total_irqs, 64) / 8;
+- bar_size += msix_pba_size;
++ bar_size += QEMU_ALIGN_UP(total_irqs, 64) / 8;
+
+- bar_size = pow2ceil(bar_size);
+- return bar_size;
++out:
++ return pow2ceil(bar_size);
+ }
+
+ static void nvme_init_sriov(NvmeCtrl *n, PCIDevice *pci_dev, uint16_t offset)
+@@ -7252,7 +7263,7 @@ static void nvme_init_sriov(NvmeCtrl *n, PCIDevice *pci_dev, uint16_t offset)
+ uint16_t vf_dev_id = n->params.use_intel_id ?
+ PCI_DEVICE_ID_INTEL_NVME : PCI_DEVICE_ID_REDHAT_NVME;
+ NvmePriCtrlCap *cap = &n->pri_ctrl_cap;
+- uint64_t bar_size = nvme_bar_size(le16_to_cpu(cap->vqfrsm),
++ uint64_t bar_size = nvme_mbar_size(le16_to_cpu(cap->vqfrsm),
+ le16_to_cpu(cap->vifrsm),
+ NULL, NULL);
+
+@@ -7286,15 +7297,14 @@ static int nvme_add_pm_capability(PCIDevice *pci_dev, uint8_t offset)
+ return 0;
+ }
+
+-static int nvme_init_pci(NvmeCtrl *n, PCIDevice *pci_dev, Error **errp)
++static bool nvme_init_pci(NvmeCtrl *n, PCIDevice *pci_dev, Error **errp)
+ {
++ ERRP_GUARD();
+ uint8_t *pci_conf = pci_dev->config;
+ uint64_t bar_size;
+- unsigned msix_table_offset, msix_pba_offset;
++ unsigned msix_table_offset = 0, msix_pba_offset = 0;
+ int ret;
+
+- Error *err = NULL;
+-
+ pci_conf[PCI_INTERRUPT_PIN] = 1;
+ pci_config_set_prog_interface(pci_conf, 0x2);
+
+@@ -7314,31 +7324,45 @@ static int nvme_init_pci(NvmeCtrl *n, PCIDevice *pci_dev, Error **errp)
+ pcie_ari_init(pci_dev, 0x100, 1);
+ }
+
+- /* add one to max_ioqpairs to account for the admin queue pair */
+- bar_size = nvme_bar_size(n->params.max_ioqpairs + 1, n->params.msix_qsize,
+- &msix_table_offset, &msix_pba_offset);
++ if (n->params.msix_exclusive_bar && !pci_is_vf(pci_dev)) {
++ bar_size = nvme_mbar_size(n->params.max_ioqpairs + 1, 0, NULL, NULL);
++ memory_region_init_io(&n->iomem, OBJECT(n), &nvme_mmio_ops, n, "nvme",
++ bar_size);
++ pci_register_bar(pci_dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY |
++ PCI_BASE_ADDRESS_MEM_TYPE_64, &n->iomem);
++ ret = msix_init_exclusive_bar(pci_dev, n->params.msix_qsize, 4, errp);
++ } else {
++ assert(n->params.msix_qsize >= 1);
+
+- memory_region_init(&n->bar0, OBJECT(n), "nvme-bar0", bar_size);
+- memory_region_init_io(&n->iomem, OBJECT(n), &nvme_mmio_ops, n, "nvme",
+- msix_table_offset);
+- memory_region_add_subregion(&n->bar0, 0, &n->iomem);
++ /* add one to max_ioqpairs to account for the admin queue pair */
++ bar_size = nvme_mbar_size(n->params.max_ioqpairs + 1,
++ n->params.msix_qsize, &msix_table_offset,
++ &msix_pba_offset);
+
+- if (pci_is_vf(pci_dev)) {
+- pcie_sriov_vf_register_bar(pci_dev, 0, &n->bar0);
+- } else {
+- pci_register_bar(pci_dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY |
+- PCI_BASE_ADDRESS_MEM_TYPE_64, &n->bar0);
+- }
+- ret = msix_init(pci_dev, n->params.msix_qsize,
+- &n->bar0, 0, msix_table_offset,
+- &n->bar0, 0, msix_pba_offset, 0, &err);
+- if (ret < 0) {
+- if (ret == -ENOTSUP) {
+- warn_report_err(err);
++ memory_region_init(&n->bar0, OBJECT(n), "nvme-bar0", bar_size);
++ memory_region_init_io(&n->iomem, OBJECT(n), &nvme_mmio_ops, n, "nvme",
++ msix_table_offset);
++ memory_region_add_subregion(&n->bar0, 0, &n->iomem);
++
++ if (pci_is_vf(pci_dev)) {
++ pcie_sriov_vf_register_bar(pci_dev, 0, &n->bar0);
+ } else {
+- error_propagate(errp, err);
+- return ret;
++ pci_register_bar(pci_dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY |
++ PCI_BASE_ADDRESS_MEM_TYPE_64, &n->bar0);
+ }
++
++ ret = msix_init(pci_dev, n->params.msix_qsize,
++ &n->bar0, 0, msix_table_offset,
++ &n->bar0, 0, msix_pba_offset, 0, errp);
++ }
++
++ if (ret == -ENOTSUP) {
++ /* report that msix is not supported, but do not error out */
++ warn_report_err(*errp);
++ *errp = NULL;
++ } else if (ret < 0) {
++ /* propagate error to caller */
++ return false;
+ }
+
+ nvme_update_msixcap_ts(pci_dev, n->conf_msix_qsize);
+@@ -7355,7 +7379,7 @@ static int nvme_init_pci(NvmeCtrl *n, PCIDevice *pci_dev, Error **errp)
+ nvme_init_sriov(n, pci_dev, 0x120);
+ }
+
+- return 0;
++ return true;
+ }
+
+ static void nvme_init_subnqn(NvmeCtrl *n)
+@@ -7509,21 +7533,24 @@ static void nvme_realize(PCIDevice *pci_dev, Error **errp)
+ {
+ NvmeCtrl *n = NVME(pci_dev);
+ NvmeNamespace *ns;
+- Error *local_err = NULL;
+ NvmeCtrl *pn = NVME(pcie_sriov_get_pf(pci_dev));
+
+ if (pci_is_vf(pci_dev)) {
+ /*
+ * VFs derive settings from the parent. PF's lifespan exceeds
+- * that of VF's, so it's safe to share params.serial.
++ * that of VF's.
+ */
+ memcpy(&n->params, &pn->params, sizeof(NvmeParams));
++
++ /*
++ * Set PF's serial value to a new string memory to prevent 'serial'
++ * property object release of PF when a VF is removed from the system.
++ */
++ n->params.serial = g_strdup(pn->params.serial);
+ n->subsys = pn->subsys;
+ }
+
+- nvme_check_constraints(n, &local_err);
+- if (local_err) {
+- error_propagate(errp, local_err);
++ if (!nvme_check_params(n, errp)) {
+ return;
+ }
+
+@@ -7531,11 +7558,10 @@ static void nvme_realize(PCIDevice *pci_dev, Error **errp)
+ &pci_dev->qdev, n->parent_obj.qdev.id);
+
+ if (nvme_init_subsys(n, errp)) {
+- error_propagate(errp, local_err);
+ return;
+ }
+ nvme_init_state(n);
+- if (nvme_init_pci(n, pci_dev, errp)) {
++ if (!nvme_init_pci(n, pci_dev, errp)) {
+ return;
+ }
+ nvme_init_ctrl(n, pci_dev);
+@@ -7622,6 +7648,8 @@ static Property nvme_props[] = {
+ params.sriov_max_vi_per_vf, 0),
+ DEFINE_PROP_UINT8("sriov_max_vq_per_vf", NvmeCtrl,
+ params.sriov_max_vq_per_vf, 0),
++ DEFINE_PROP_BOOL("msix-exclusive-bar", NvmeCtrl, params.msix_exclusive_bar,
++ false),
+ DEFINE_PROP_END_OF_LIST(),
+ };
+
+@@ -7676,36 +7704,26 @@ static void nvme_pci_reset(DeviceState *qdev)
+ nvme_ctrl_reset(n, NVME_RESET_FUNCTION);
+ }
+
+-static void nvme_sriov_pre_write_ctrl(PCIDevice *dev, uint32_t address,
+- uint32_t val, int len)
++static void nvme_sriov_post_write_config(PCIDevice *dev, uint16_t old_num_vfs)
+ {
+ NvmeCtrl *n = NVME(dev);
+ NvmeSecCtrlEntry *sctrl;
+- uint16_t sriov_cap = dev->exp.sriov_cap;
+- uint32_t off = address - sriov_cap;
+- int i, num_vfs;
+-
+- if (!sriov_cap) {
+- return;
+- }
++ int i;
+
+- if (range_covers_byte(off, len, PCI_SRIOV_CTRL)) {
+- if (!(val & PCI_SRIOV_CTRL_VFE)) {
+- num_vfs = pci_get_word(dev->config + sriov_cap + PCI_SRIOV_NUM_VF);
+- for (i = 0; i < num_vfs; i++) {
+- sctrl = &n->sec_ctrl_list.sec[i];
+- nvme_virt_set_state(n, le16_to_cpu(sctrl->scid), false);
+- }
+- }
++ for (i = pcie_sriov_num_vfs(dev); i < old_num_vfs; i++) {
++ sctrl = &n->sec_ctrl_list.sec[i];
++ nvme_virt_set_state(n, le16_to_cpu(sctrl->scid), false);
+ }
+ }
+
+ static void nvme_pci_write_config(PCIDevice *dev, uint32_t address,
+ uint32_t val, int len)
+ {
+- nvme_sriov_pre_write_ctrl(dev, address, val, len);
++ uint16_t old_num_vfs = pcie_sriov_num_vfs(dev);
++
+ pci_default_write_config(dev, address, val, len);
+ pcie_cap_flr_write_config(dev, address, val, len);
++ nvme_sriov_post_write_config(dev, old_num_vfs);
+ }
+
+ static const VMStateDescription nvme_vmstate = {
+diff --git a/hw/nvme/nvme.h b/hw/nvme/nvme.h
+index 7adf042ec3..4d5e42b669 100644
+--- a/hw/nvme/nvme.h
++++ b/hw/nvme/nvme.h
+@@ -427,6 +427,7 @@ typedef struct NvmeParams {
+ uint16_t sriov_vi_flexible;
+ uint8_t sriov_max_vq_per_vf;
+ uint8_t sriov_max_vi_per_vf;
++ bool msix_exclusive_bar;
+ } NvmeParams;
+
+ typedef struct NvmeCtrl {
+diff --git a/hw/pci/pcie_sriov.c b/hw/pci/pcie_sriov.c
+index 61a4e06768..0d58e4db43 100644
+--- a/hw/pci/pcie_sriov.c
++++ b/hw/pci/pcie_sriov.c
+@@ -176,6 +176,9 @@ static void register_vfs(PCIDevice *dev)
+
+ assert(sriov_cap > 0);
+ num_vfs = pci_get_word(dev->config + sriov_cap + PCI_SRIOV_NUM_VF);
++ if (num_vfs > pci_get_word(dev->config + sriov_cap + PCI_SRIOV_TOTAL_VF)) {
++ return;
++ }
+
+ dev->exp.sriov_pf.vf = g_new(PCIDevice *, num_vfs);
+
+@@ -299,3 +302,8 @@ PCIDevice *pcie_sriov_get_vf_at_index(PCIDevice *dev, int n)
+ }
+ return NULL;
+ }
++
++uint16_t pcie_sriov_num_vfs(PCIDevice *dev)
++{
++ return dev->exp.sriov_pf.num_vfs;
++}
+diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
+index 66b414d2e9..9e860f5047 100644
+--- a/hw/ppc/spapr.c
++++ b/hw/ppc/spapr.c
+@@ -4602,13 +4602,10 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data)
+ mc->block_default_type = IF_SCSI;
+
+ /*
+- * Setting max_cpus to INT32_MAX. Both KVM and TCG max_cpus values
+- * should be limited by the host capability instead of hardcoded.
+- * max_cpus for KVM guests will be checked in kvm_init(), and TCG
+- * guests are welcome to have as many CPUs as the host are capable
+- * of emulate.
++ * While KVM determines max cpus in kvm_init() using kvm_max_vcpus(),
++ * In TCG the limit is restricted by the range of CPU IPIs available.
+ */
+- mc->max_cpus = INT32_MAX;
++ mc->max_cpus = SPAPR_IRQ_NR_IPIS;
+
+ mc->no_parallel = 1;
+ mc->default_boot_order = "";
+diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c
+index a0d1e1298e..97b2fc42ab 100644
+--- a/hw/ppc/spapr_irq.c
++++ b/hw/ppc/spapr_irq.c
+@@ -23,6 +23,8 @@
+
+ #include "trace.h"
+
++QEMU_BUILD_BUG_ON(SPAPR_IRQ_NR_IPIS > SPAPR_XIRQ_BASE);
++
+ static const TypeInfo spapr_intc_info = {
+ .name = TYPE_SPAPR_INTC,
+ .parent = TYPE_INTERFACE,
+@@ -329,7 +331,7 @@ void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
+ int i;
+
+ dev = qdev_new(TYPE_SPAPR_XIVE);
+- qdev_prop_set_uint32(dev, "nr-irqs", smc->nr_xirqs + SPAPR_XIRQ_BASE);
++ qdev_prop_set_uint32(dev, "nr-irqs", smc->nr_xirqs + SPAPR_IRQ_NR_IPIS);
+ /*
+ * 8 XIVE END structures per CPU. One for each available
+ * priority
+@@ -356,7 +358,7 @@ void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
+ }
+
+ spapr->qirqs = qemu_allocate_irqs(spapr_set_irq, spapr,
+- smc->nr_xirqs + SPAPR_XIRQ_BASE);
++ smc->nr_xirqs + SPAPR_IRQ_NR_IPIS);
+
+ /*
+ * Mostly we don't actually need this until reset, except that not
+diff --git a/hw/rtc/sun4v-rtc.c b/hw/rtc/sun4v-rtc.c
+index e037acd1b5..ffcc0aa25d 100644
+--- a/hw/rtc/sun4v-rtc.c
++++ b/hw/rtc/sun4v-rtc.c
+@@ -5,7 +5,7 @@
+ *
+ * Copyright (c) 2016 Artyom Tarasenko
+ *
+- * This code is licensed under the GNU GPL v3 or (at your option) any later
++ * This code is licensed under the GNU GPL v2 or (at your option) any later
+ * version.
+ */
+
+diff --git a/hw/scsi/lsi53c895a.c b/hw/scsi/lsi53c895a.c
+index ca619ed564..48c85d479c 100644
+--- a/hw/scsi/lsi53c895a.c
++++ b/hw/scsi/lsi53c895a.c
+@@ -188,7 +188,7 @@ static const char *names[] = {
+ #define LSI_TAG_VALID (1 << 16)
+
+ /* Maximum instructions to process. */
+-#define LSI_MAX_INSN 10000
++#define LSI_MAX_INSN 100
+
+ typedef struct lsi_request {
+ SCSIRequest *req;
+@@ -205,6 +205,7 @@ enum {
+ LSI_WAIT_RESELECT, /* Wait Reselect instruction has been issued */
+ LSI_DMA_SCRIPTS, /* processing DMA from lsi_execute_script */
+ LSI_DMA_IN_PROGRESS, /* DMA operation is in progress */
++ LSI_WAIT_SCRIPTS, /* SCRIPTS stopped because of instruction count limit */
+ };
+
+ enum {
+@@ -224,6 +225,7 @@ struct LSIState {
+ MemoryRegion ram_io;
+ MemoryRegion io_io;
+ AddressSpace pci_io_as;
++ QEMUTimer *scripts_timer;
+
+ int carry; /* ??? Should this be an a visible register somewhere? */
+ int status;
+@@ -415,6 +417,7 @@ static void lsi_soft_reset(LSIState *s)
+ s->sbr = 0;
+ assert(QTAILQ_EMPTY(&s->queue));
+ assert(!s->current);
++ timer_del(s->scripts_timer);
+ }
+
+ static int lsi_dma_40bit(LSIState *s)
+@@ -570,8 +573,9 @@ static inline void lsi_set_phase(LSIState *s, int phase)
+ s->sstat1 = (s->sstat1 & ~PHASE_MASK) | phase;
+ }
+
+-static void lsi_bad_phase(LSIState *s, int out, int new_phase)
++static int lsi_bad_phase(LSIState *s, int out, int new_phase)
+ {
++ int ret = 0;
+ /* Trigger a phase mismatch. */
+ if (s->ccntl0 & LSI_CCNTL0_ENPMJ) {
+ if ((s->ccntl0 & LSI_CCNTL0_PMJCTL)) {
+@@ -584,8 +588,10 @@ static void lsi_bad_phase(LSIState *s, int out, int new_phase)
+ trace_lsi_bad_phase_interrupt();
+ lsi_script_scsi_interrupt(s, LSI_SIST0_MA, 0);
+ lsi_stop_script(s);
++ ret = 1;
+ }
+ lsi_set_phase(s, new_phase);
++ return ret;
+ }
+
+
+@@ -789,7 +795,7 @@ static int lsi_queue_req(LSIState *s, SCSIRequest *req, uint32_t len)
+ static void lsi_command_complete(SCSIRequest *req, size_t resid)
+ {
+ LSIState *s = LSI53C895A(req->bus->qbus.parent);
+- int out;
++ int out, stop = 0;
+
+ out = (s->sstat1 & PHASE_MASK) == PHASE_DO;
+ trace_lsi_command_complete(req->status);
+@@ -797,7 +803,10 @@ static void lsi_command_complete(SCSIRequest *req, size_t resid)
+ s->command_complete = 2;
+ if (s->waiting && s->dbc != 0) {
+ /* Raise phase mismatch for short transfers. */
+- lsi_bad_phase(s, out, PHASE_ST);
++ stop = lsi_bad_phase(s, out, PHASE_ST);
++ if (stop) {
++ s->waiting = 0;
++ }
+ } else {
+ lsi_set_phase(s, PHASE_ST);
+ }
+@@ -807,7 +816,9 @@ static void lsi_command_complete(SCSIRequest *req, size_t resid)
+ lsi_request_free(s, s->current);
+ scsi_req_unref(req);
+ }
+- lsi_resume_script(s);
++ if (!stop) {
++ lsi_resume_script(s);
++ }
+ }
+
+ /* Callback to indicate that the SCSI layer has completed a transfer. */
+@@ -1127,6 +1138,12 @@ static void lsi_wait_reselect(LSIState *s)
+ }
+ }
+
++static void lsi_scripts_timer_start(LSIState *s)
++{
++ trace_lsi_scripts_timer_start();
++ timer_mod(s->scripts_timer, qemu_clock_get_us(QEMU_CLOCK_VIRTUAL) + 500);
++}
++
+ static void lsi_execute_script(LSIState *s)
+ {
+ PCIDevice *pci_dev = PCI_DEVICE(s);
+@@ -1136,6 +1153,11 @@ static void lsi_execute_script(LSIState *s)
+ int insn_processed = 0;
+ static int reentrancy_level;
+
++ if (s->waiting == LSI_WAIT_SCRIPTS) {
++ timer_del(s->scripts_timer);
++ s->waiting = LSI_NOWAIT;
++ }
++
+ reentrancy_level++;
+
+ s->istat1 |= LSI_ISTAT1_SRUN;
+@@ -1143,8 +1165,8 @@ again:
+ /*
+ * Some windows drivers make the device spin waiting for a memory location
+ * to change. If we have executed more than LSI_MAX_INSN instructions then
+- * assume this is the case and force an unexpected device disconnect. This
+- * is apparently sufficient to beat the drivers into submission.
++ * assume this is the case and start a timer. Until the timer fires, the
++ * host CPU has a chance to run and change the memory location.
+ *
+ * Another issue (CVE-2023-0330) can occur if the script is programmed to
+ * trigger itself again and again. Avoid this problem by stopping after
+@@ -1152,13 +1174,9 @@ again:
+ * which should be enough for all valid use cases).
+ */
+ if (++insn_processed > LSI_MAX_INSN || reentrancy_level > 8) {
+- if (!(s->sien0 & LSI_SIST0_UDC)) {
+- qemu_log_mask(LOG_GUEST_ERROR,
+- "lsi_scsi: inf. loop with UDC masked");
+- }
+- lsi_script_scsi_interrupt(s, LSI_SIST0_UDC, 0);
+- lsi_disconnect(s);
+- trace_lsi_execute_script_stop();
++ s->waiting = LSI_WAIT_SCRIPTS;
++ lsi_scripts_timer_start(s);
++ reentrancy_level--;
+ return;
+ }
+ insn = read_dword(s, s->dsp);
+@@ -2196,6 +2214,9 @@ static int lsi_post_load(void *opaque, int version_id)
+ return -EINVAL;
+ }
+
++ if (s->waiting == LSI_WAIT_SCRIPTS) {
++ lsi_scripts_timer_start(s);
++ }
+ return 0;
+ }
+
+@@ -2293,6 +2314,15 @@ static const struct SCSIBusInfo lsi_scsi_info = {
+ .cancel = lsi_request_cancelled
+ };
+
++static void scripts_timer_cb(void *opaque)
++{
++ LSIState *s = opaque;
++
++ trace_lsi_scripts_timer_triggered();
++ s->waiting = LSI_NOWAIT;
++ lsi_execute_script(s);
++}
++
+ static void lsi_scsi_realize(PCIDevice *dev, Error **errp)
+ {
+ LSIState *s = LSI53C895A(dev);
+@@ -2312,6 +2342,7 @@ static void lsi_scsi_realize(PCIDevice *dev, Error **errp)
+ "lsi-ram", 0x2000);
+ memory_region_init_io(&s->io_io, OBJECT(s), &lsi_io_ops, s,
+ "lsi-io", 256);
++ s->scripts_timer = timer_new_us(QEMU_CLOCK_VIRTUAL, scripts_timer_cb, s);
+
+ /*
+ * Since we use the address-space API to interact with ram_io, disable the
+@@ -2336,6 +2367,7 @@ static void lsi_scsi_exit(PCIDevice *dev)
+ LSIState *s = LSI53C895A(dev);
+
+ address_space_destroy(&s->pci_io_as);
++ timer_del(s->scripts_timer);
+ }
+
+ static void lsi_class_init(ObjectClass *klass, void *data)
+diff --git a/hw/scsi/scsi-generic.c b/hw/scsi/scsi-generic.c
+index d513870181..87d84ee68e 100644
+--- a/hw/scsi/scsi-generic.c
++++ b/hw/scsi/scsi-generic.c
+@@ -765,7 +765,6 @@ static void scsi_generic_realize(SCSIDevice *s, Error **errp)
+
+ /* Only used by scsi-block, but initialize it nevertheless to be clean. */
+ s->default_scsi_version = -1;
+- s->io_timeout = DEFAULT_IO_TIMEOUT;
+ scsi_generic_read_device_inquiry(s);
+ }
+
+diff --git a/hw/scsi/trace-events b/hw/scsi/trace-events
+index ab238293f0..131af99d91 100644
+--- a/hw/scsi/trace-events
++++ b/hw/scsi/trace-events
+@@ -299,6 +299,8 @@ lsi_execute_script_stop(void) "SCRIPTS execution stopped"
+ lsi_awoken(void) "Woken by SIGP"
+ lsi_reg_read(const char *name, int offset, uint8_t ret) "Read reg %s 0x%x = 0x%02x"
+ lsi_reg_write(const char *name, int offset, uint8_t val) "Write reg %s 0x%x = 0x%02x"
++lsi_scripts_timer_triggered(void) "SCRIPTS timer triggered"
++lsi_scripts_timer_start(void) "SCRIPTS timer started"
+
+ # virtio-scsi.c
+ virtio_scsi_cmd_req(int lun, uint32_t tag, uint8_t cmd) "virtio_scsi_cmd_req lun=%u tag=0x%x cmd=0x%x"
+diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
+index ef60badc6b..abd503d168 100644
+--- a/hw/sd/sdhci.c
++++ b/hw/sd/sdhci.c
+@@ -473,6 +473,7 @@ static uint32_t sdhci_read_dataport(SDHCIState *s, unsigned size)
+ }
+
+ for (i = 0; i < size; i++) {
++ assert(s->data_count < s->buf_maxsz);
+ value |= s->fifo_buffer[s->data_count] << i * 8;
+ s->data_count++;
+ /* check if we've read all valid data (blksize bytes) from buffer */
+@@ -561,6 +562,7 @@ static void sdhci_write_dataport(SDHCIState *s, uint32_t value, unsigned size)
+ }
+
+ for (i = 0; i < size; i++) {
++ assert(s->data_count < s->buf_maxsz);
+ s->fifo_buffer[s->data_count] = value & 0xFF;
+ s->data_count++;
+ value >>= 8;
+@@ -1208,6 +1210,12 @@ sdhci_write(void *opaque, hwaddr offset, uint64_t val, unsigned size)
+ if (!(s->capareg & R_SDHC_CAPAB_SDMA_MASK)) {
+ value &= ~SDHC_TRNS_DMA;
+ }
++
++ /* TRNMOD writes are inhibited while Command Inhibit (DAT) is true */
++ if (s->prnsts & SDHC_DATA_INHIBIT) {
++ mask |= 0xffff;
++ }
++
+ MASKED_WRITE(s->trnmod, mask, value & SDHC_TRNMOD_MASK);
+ MASKED_WRITE(s->cmdreg, mask >> 16, value >> 16);
+
+diff --git a/hw/virtio/virtio-crypto.c b/hw/virtio/virtio-crypto.c
+index b2e0646d9a..ce995c66d8 100644
+--- a/hw/virtio/virtio-crypto.c
++++ b/hw/virtio/virtio-crypto.c
+@@ -1057,8 +1057,8 @@ static void virtio_crypto_device_realize(DeviceState *dev, Error **errp)
+ vcrypto->vqs[i].dataq =
+ virtio_add_queue(vdev, 1024, virtio_crypto_handle_dataq_bh);
+ vcrypto->vqs[i].dataq_bh =
+- qemu_bh_new_guarded(virtio_crypto_dataq_bh, &vcrypto->vqs[i],
+- &dev->mem_reentrancy_guard);
++ virtio_bh_new_guarded(dev, virtio_crypto_dataq_bh,
++ &vcrypto->vqs[i]);
+ vcrypto->vqs[i].vcrypto = vcrypto;
+ }
+
+diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
+index b7da7f074d..4a35d7cb0c 100644
+--- a/hw/virtio/virtio.c
++++ b/hw/virtio/virtio.c
+@@ -1367,12 +1367,20 @@ static void virtqueue_packed_flush(VirtQueue *vq, unsigned int count)
+ return;
+ }
+
++ /*
++ * For indirect element's 'ndescs' is 1.
++ * For all other elemment's 'ndescs' is the
++ * number of descriptors chained by NEXT (as set in virtqueue_packed_pop).
++ * So When the 'elem' be filled into the descriptor ring,
++ * The 'idx' of this 'elem' shall be
++ * the value of 'vq->used_idx' plus the 'ndescs'.
++ */
++ ndescs += vq->used_elems[0].ndescs;
+ for (i = 1; i < count; i++) {
+- virtqueue_packed_fill_desc(vq, &vq->used_elems[i], i, false);
++ virtqueue_packed_fill_desc(vq, &vq->used_elems[i], ndescs, false);
+ ndescs += vq->used_elems[i].ndescs;
+ }
+ virtqueue_packed_fill_desc(vq, &vq->used_elems[0], 0, true);
+- ndescs += vq->used_elems[0].ndescs;
+
+ vq->inuse -= ndescs;
+ vq->used_idx += ndescs;
+@@ -5021,3 +5029,13 @@ static void virtio_register_types(void)
+ }
+
+ type_init(virtio_register_types)
++
++QEMUBH *virtio_bh_new_guarded_full(DeviceState *dev,
++ QEMUBHFunc *cb, void *opaque,
++ const char *name)
++{
++ DeviceState *transport = qdev_get_parent_bus(dev)->parent;
++
++ return qemu_bh_new_full(cb, opaque, name,
++ &transport->mem_reentrancy_guard);
++}
+diff --git a/include/hw/pci/pcie_sriov.h b/include/hw/pci/pcie_sriov.h
+index 80f5c84e75..072a583405 100644
+--- a/include/hw/pci/pcie_sriov.h
++++ b/include/hw/pci/pcie_sriov.h
+@@ -74,4 +74,7 @@ PCIDevice *pcie_sriov_get_pf(PCIDevice *dev);
+ */
+ PCIDevice *pcie_sriov_get_vf_at_index(PCIDevice *dev, int n);
+
++/* Returns the current number of virtual functions. */
++uint16_t pcie_sriov_num_vfs(PCIDevice *dev);
++
+ #endif /* QEMU_PCIE_SRIOV_H */
+diff --git a/include/hw/ppc/spapr_irq.h b/include/hw/ppc/spapr_irq.h
+index c22a72c9e2..4fd2d5853d 100644
+--- a/include/hw/ppc/spapr_irq.h
++++ b/include/hw/ppc/spapr_irq.h
+@@ -14,9 +14,21 @@
+ #include "qom/object.h"
+
+ /*
+- * IRQ range offsets per device type
++ * The XIVE IRQ backend uses the same layout as the XICS backend but
++ * covers the full range of the IRQ number space. The IRQ numbers for
++ * the CPU IPIs are allocated at the bottom of this space, below 4K,
++ * to preserve compatibility with XICS which does not use that range.
++ */
++
++/*
++ * CPU IPI range (XIVE only)
+ */
+ #define SPAPR_IRQ_IPI 0x0
++#define SPAPR_IRQ_NR_IPIS 0x1000
++
++/*
++ * IRQ range offsets per device type
++ */
+
+ #define SPAPR_XIRQ_BASE XICS_IRQ_BASE /* 0x1000 */
+ #define SPAPR_IRQ_EPOW (SPAPR_XIRQ_BASE + 0x0000)
+diff --git a/include/hw/rtc/sun4v-rtc.h b/include/hw/rtc/sun4v-rtc.h
+index fc54dfcba4..26a9eb6196 100644
+--- a/include/hw/rtc/sun4v-rtc.h
++++ b/include/hw/rtc/sun4v-rtc.h
+@@ -5,7 +5,7 @@
+ *
+ * Copyright (c) 2016 Artyom Tarasenko
+ *
+- * This code is licensed under the GNU GPL v3 or (at your option) any later
++ * This code is licensed under the GNU GPL v2 or (at your option) any later
+ * version.
+ */
+
+diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
+index 96a56430a6..c1a7c9bd3b 100644
+--- a/include/hw/virtio/virtio.h
++++ b/include/hw/virtio/virtio.h
+@@ -23,6 +23,7 @@
+ #include "standard-headers/linux/virtio_ring.h"
+ #include "qom/object.h"
+ #include "hw/virtio/vhost.h"
++#include "block/aio.h"
+
+ /*
+ * A guest should never accept this. It implies negotiation is broken
+@@ -463,4 +464,10 @@ static inline bool virtio_device_disabled(VirtIODevice *vdev)
+ bool virtio_legacy_allowed(VirtIODevice *vdev);
+ bool virtio_legacy_check_disabled(VirtIODevice *vdev);
+
++QEMUBH *virtio_bh_new_guarded_full(DeviceState *dev,
++ QEMUBHFunc *cb, void *opaque,
++ const char *name);
++#define virtio_bh_new_guarded(dev, cb, opaque) \
++ virtio_bh_new_guarded_full((dev), (cb), (opaque), (stringify(cb)))
++
+ #endif
+diff --git a/linux-user/syscall.c b/linux-user/syscall.c
+index aead0f6ac9..41017b0df2 100644
+--- a/linux-user/syscall.c
++++ b/linux-user/syscall.c
+@@ -8759,14 +8759,24 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
+ #ifdef TARGET_NR_waitid
+ case TARGET_NR_waitid:
+ {
++ struct rusage ru;
+ siginfo_t info;
+- info.si_pid = 0;
+- ret = get_errno(safe_waitid(arg1, arg2, &info, arg4, NULL));
+- if (!is_error(ret) && arg3 && info.si_pid != 0) {
+- if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_siginfo_t), 0)))
++
++ ret = get_errno(safe_waitid(arg1, arg2, (arg3 ? &info : NULL),
++ arg4, (arg5 ? &ru : NULL)));
++ if (!is_error(ret)) {
++ if (arg3) {
++ p = lock_user(VERIFY_WRITE, arg3,
++ sizeof(target_siginfo_t), 0);
++ if (!p) {
++ return -TARGET_EFAULT;
++ }
++ host_to_target_siginfo(p, &info);
++ unlock_user(p, arg3, sizeof(target_siginfo_t));
++ }
++ if (arg5 && host_to_target_rusage(arg5, &ru)) {
+ return -TARGET_EFAULT;
+- host_to_target_siginfo(p, &info);
+- unlock_user(p, arg3, sizeof(target_siginfo_t));
++ }
+ }
+ }
+ return ret;
+diff --git a/migration/block.c b/migration/block.c
+index 4026b73f75..867901d2b1 100644
+--- a/migration/block.c
++++ b/migration/block.c
+@@ -415,7 +415,10 @@ static int init_blk_migration(QEMUFile *f)
+ }
+
+ sectors = bdrv_nb_sectors(bs);
+- if (sectors <= 0) {
++ if (sectors == 0) {
++ continue;
++ }
++ if (sectors < 0) {
+ ret = sectors;
+ bdrv_next_cleanup(&it);
+ goto out;
+diff --git a/monitor/misc.c b/monitor/misc.c
+index 205487e2b9..80dd1fa8e6 100644
+--- a/monitor/misc.c
++++ b/monitor/misc.c
+@@ -668,7 +668,7 @@ void *gpa2hva(MemoryRegion **p_mr, hwaddr addr, uint64_t size, Error **errp)
+ }
+
+ if (!memory_region_is_ram(mrs.mr) && !memory_region_is_romd(mrs.mr)) {
+- error_setg(errp, "Memory at address 0x%" HWADDR_PRIx "is not RAM", addr);
++ error_setg(errp, "Memory at address 0x%" HWADDR_PRIx " is not RAM", addr);
+ memory_region_unref(mrs.mr);
+ return NULL;
+ }
+diff --git a/qemu-options.hx b/qemu-options.hx
+index 7f798ce47e..2c00ceac83 100644
+--- a/qemu-options.hx
++++ b/qemu-options.hx
+@@ -149,14 +149,14 @@ SRST
+ platform and configuration dependent.
+
+ ``interleave-granularity=granularity`` sets the granularity of
+- interleave. Default 256KiB. Only 256KiB, 512KiB, 1024KiB, 2048KiB
+- 4096KiB, 8192KiB and 16384KiB granularities supported.
++ interleave. Default 256 (bytes). Only 256, 512, 1k, 2k,
++ 4k, 8k and 16k granularities supported.
+
+ Example:
+
+ ::
+
+- -machine cxl-fmw.0.targets.0=cxl.0,cxl-fmw.0.targets.1=cxl.1,cxl-fmw.0.size=128G,cxl-fmw.0.interleave-granularity=512k
++ -machine cxl-fmw.0.targets.0=cxl.0,cxl-fmw.0.targets.1=cxl.1,cxl-fmw.0.size=128G,cxl-fmw.0.interleave-granularity=512
+ ERST
+
+ DEF("M", HAS_ARG, QEMU_OPTION_M,
+diff --git a/scripts/make-release b/scripts/make-release
+index 05b14ecc95..43689064fb 100755
+--- a/scripts/make-release
++++ b/scripts/make-release
+@@ -34,5 +34,5 @@ git submodule update --init
+ CryptoPkg/Library/OpensslLib/openssl \
+ MdeModulePkg/Library/BrotliCustomDecompressLib/brotli)
+ popd
+-tar --exclude=.git -cjf ${destination}.tar.bz2 ${destination}
++tar --exclude=.git -cJf ${destination}.tar.xz ${destination}
+ rm -rf ${destination}
+diff --git a/softmmu/qdev-monitor.c b/softmmu/qdev-monitor.c
+index 4b0ef65780..f4348443b0 100644
+--- a/softmmu/qdev-monitor.c
++++ b/softmmu/qdev-monitor.c
+@@ -853,19 +853,18 @@ void qmp_device_add(QDict *qdict, QObject **ret_data, Error **errp)
+ return;
+ }
+ dev = qdev_device_add(opts, errp);
+-
+- /*
+- * Drain all pending RCU callbacks. This is done because
+- * some bus related operations can delay a device removal
+- * (in this case this can happen if device is added and then
+- * removed due to a configuration error)
+- * to a RCU callback, but user might expect that this interface
+- * will finish its job completely once qmp command returns result
+- * to the user
+- */
+- drain_call_rcu();
+-
+ if (!dev) {
++ /*
++ * Drain all pending RCU callbacks. This is done because
++ * some bus related operations can delay a device removal
++ * (in this case this can happen if device is added and then
++ * removed due to a configuration error)
++ * to a RCU callback, but user might expect that this interface
++ * will finish its job completely once qmp command returns result
++ * to the user
++ */
++ drain_call_rcu();
++
+ qemu_opts_del(opts);
+ return;
+ }
+diff --git a/target/arm/helper.c b/target/arm/helper.c
+index 2e284e048c..acc0470e86 100644
+--- a/target/arm/helper.c
++++ b/target/arm/helper.c
+@@ -7852,31 +7852,89 @@ void register_cp_regs_for_features(ARMCPU *cpu)
+ #ifdef CONFIG_USER_ONLY
+ static const ARMCPRegUserSpaceInfo v8_user_idregs[] = {
+ { .name = "ID_AA64PFR0_EL1",
+- .exported_bits = 0x000f000f00ff0000,
+- .fixed_bits = 0x0000000000000011 },
++ .exported_bits = R_ID_AA64PFR0_FP_MASK |
++ R_ID_AA64PFR0_ADVSIMD_MASK |
++ R_ID_AA64PFR0_SVE_MASK |
++ R_ID_AA64PFR0_DIT_MASK,
++ .fixed_bits = (0x1u << R_ID_AA64PFR0_EL0_SHIFT) |
++ (0x1u << R_ID_AA64PFR0_EL1_SHIFT) },
+ { .name = "ID_AA64PFR1_EL1",
+- .exported_bits = 0x00000000000000f0 },
++ .exported_bits = R_ID_AA64PFR1_BT_MASK |
++ R_ID_AA64PFR1_SSBS_MASK |
++ R_ID_AA64PFR1_MTE_MASK |
++ R_ID_AA64PFR1_SME_MASK },
+ { .name = "ID_AA64PFR*_EL1_RESERVED",
+- .is_glob = true },
+- { .name = "ID_AA64ZFR0_EL1" },
++ .is_glob = true },
++ { .name = "ID_AA64ZFR0_EL1",
++ .exported_bits = R_ID_AA64ZFR0_SVEVER_MASK |
++ R_ID_AA64ZFR0_AES_MASK |
++ R_ID_AA64ZFR0_BITPERM_MASK |
++ R_ID_AA64ZFR0_BFLOAT16_MASK |
++ R_ID_AA64ZFR0_SHA3_MASK |
++ R_ID_AA64ZFR0_SM4_MASK |
++ R_ID_AA64ZFR0_I8MM_MASK |
++ R_ID_AA64ZFR0_F32MM_MASK |
++ R_ID_AA64ZFR0_F64MM_MASK },
++ { .name = "ID_AA64SMFR0_EL1",
++ .exported_bits = R_ID_AA64SMFR0_F32F32_MASK |
++ R_ID_AA64SMFR0_B16F32_MASK |
++ R_ID_AA64SMFR0_F16F32_MASK |
++ R_ID_AA64SMFR0_I8I32_MASK |
++ R_ID_AA64SMFR0_F64F64_MASK |
++ R_ID_AA64SMFR0_I16I64_MASK |
++ R_ID_AA64SMFR0_FA64_MASK },
+ { .name = "ID_AA64MMFR0_EL1",
+- .fixed_bits = 0x00000000ff000000 },
+- { .name = "ID_AA64MMFR1_EL1" },
++ .exported_bits = R_ID_AA64MMFR0_ECV_MASK,
++ .fixed_bits = (0xfu << R_ID_AA64MMFR0_TGRAN64_SHIFT) |
++ (0xfu << R_ID_AA64MMFR0_TGRAN4_SHIFT) },
++ { .name = "ID_AA64MMFR1_EL1",
++ .exported_bits = R_ID_AA64MMFR1_AFP_MASK },
++ { .name = "ID_AA64MMFR2_EL1",
++ .exported_bits = R_ID_AA64MMFR2_AT_MASK },
+ { .name = "ID_AA64MMFR*_EL1_RESERVED",
+- .is_glob = true },
++ .is_glob = true },
+ { .name = "ID_AA64DFR0_EL1",
+- .fixed_bits = 0x0000000000000006 },
+- { .name = "ID_AA64DFR1_EL1" },
++ .fixed_bits = (0x6u << R_ID_AA64DFR0_DEBUGVER_SHIFT) },
++ { .name = "ID_AA64DFR1_EL1" },
+ { .name = "ID_AA64DFR*_EL1_RESERVED",
+- .is_glob = true },
++ .is_glob = true },
+ { .name = "ID_AA64AFR*",
+- .is_glob = true },
++ .is_glob = true },
+ { .name = "ID_AA64ISAR0_EL1",
+- .exported_bits = 0x00fffffff0fffff0 },
++ .exported_bits = R_ID_AA64ISAR0_AES_MASK |
++ R_ID_AA64ISAR0_SHA1_MASK |
++ R_ID_AA64ISAR0_SHA2_MASK |
++ R_ID_AA64ISAR0_CRC32_MASK |
++ R_ID_AA64ISAR0_ATOMIC_MASK |
++ R_ID_AA64ISAR0_RDM_MASK |
++ R_ID_AA64ISAR0_SHA3_MASK |
++ R_ID_AA64ISAR0_SM3_MASK |
++ R_ID_AA64ISAR0_SM4_MASK |
++ R_ID_AA64ISAR0_DP_MASK |
++ R_ID_AA64ISAR0_FHM_MASK |
++ R_ID_AA64ISAR0_TS_MASK |
++ R_ID_AA64ISAR0_RNDR_MASK },
+ { .name = "ID_AA64ISAR1_EL1",
+- .exported_bits = 0x000000f0ffffffff },
++ .exported_bits = R_ID_AA64ISAR1_DPB_MASK |
++ R_ID_AA64ISAR1_APA_MASK |
++ R_ID_AA64ISAR1_API_MASK |
++ R_ID_AA64ISAR1_JSCVT_MASK |
++ R_ID_AA64ISAR1_FCMA_MASK |
++ R_ID_AA64ISAR1_LRCPC_MASK |
++ R_ID_AA64ISAR1_GPA_MASK |
++ R_ID_AA64ISAR1_GPI_MASK |
++ R_ID_AA64ISAR1_FRINTTS_MASK |
++ R_ID_AA64ISAR1_SB_MASK |
++ R_ID_AA64ISAR1_BF16_MASK |
++ R_ID_AA64ISAR1_DGH_MASK |
++ R_ID_AA64ISAR1_I8MM_MASK },
++ { .name = "ID_AA64ISAR2_EL1",
++ .exported_bits = R_ID_AA64ISAR2_WFXT_MASK |
++ R_ID_AA64ISAR2_RPRES_MASK |
++ R_ID_AA64ISAR2_GPA3_MASK |
++ R_ID_AA64ISAR2_APA3_MASK },
+ { .name = "ID_AA64ISAR*_EL1_RESERVED",
+- .is_glob = true },
++ .is_glob = true },
+ };
+ modify_arm_cp_regs(v8_idregs, v8_user_idregs);
+ #endif
+@@ -8194,8 +8252,12 @@ void register_cp_regs_for_features(ARMCPU *cpu)
+ #ifdef CONFIG_USER_ONLY
+ static const ARMCPRegUserSpaceInfo id_v8_user_midr_cp_reginfo[] = {
+ { .name = "MIDR_EL1",
+- .exported_bits = 0x00000000ffffffff },
+- { .name = "REVIDR_EL1" },
++ .exported_bits = R_MIDR_EL1_REVISION_MASK |
++ R_MIDR_EL1_PARTNUM_MASK |
++ R_MIDR_EL1_ARCHITECTURE_MASK |
++ R_MIDR_EL1_VARIANT_MASK |
++ R_MIDR_EL1_IMPLEMENTER_MASK },
++ { .name = "REVIDR_EL1" },
+ };
+ modify_arm_cp_regs(id_v8_midr_cp_reginfo, id_v8_user_midr_cp_reginfo);
+ #endif
+diff --git a/target/arm/translate-sme.c b/target/arm/translate-sme.c
+index 7b87a9df63..65f8495bdd 100644
+--- a/target/arm/translate-sme.c
++++ b/target/arm/translate-sme.c
+@@ -103,6 +103,21 @@ static TCGv_ptr get_tile_rowcol(DisasContext *s, int esz, int rs,
+ return addr;
+ }
+
++/*
++ * Resolve tile.size[0] to a host pointer.
++ * Used by e.g. outer product insns where we require the entire tile.
++ */
++static TCGv_ptr get_tile(DisasContext *s, int esz, int tile)
++{
++ TCGv_ptr addr = tcg_temp_new_ptr();
++ int offset;
++
++ offset = tile * sizeof(ARMVectorReg) + offsetof(CPUARMState, zarray);
++
++ tcg_gen_addi_ptr(addr, cpu_env, offset);
++ return addr;
++}
++
+ static bool trans_ZERO(DisasContext *s, arg_ZERO *a)
+ {
+ if (!dc_isar_feature(aa64_sme, s)) {
+@@ -279,8 +294,7 @@ static bool do_adda(DisasContext *s, arg_adda *a, MemOp esz,
+ return true;
+ }
+
+- /* Sum XZR+zad to find ZAd. */
+- za = get_tile_rowcol(s, esz, 31, a->zad, false);
++ za = get_tile(s, esz, a->zad);
+ zn = vec_full_reg_ptr(s, a->zn);
+ pn = pred_full_reg_ptr(s, a->pn);
+ pm = pred_full_reg_ptr(s, a->pm);
+@@ -310,8 +324,7 @@ static bool do_outprod(DisasContext *s, arg_op *a, MemOp esz,
+ return true;
+ }
+
+- /* Sum XZR+zad to find ZAd. */
+- za = get_tile_rowcol(s, esz, 31, a->zad, false);
++ za = get_tile(s, esz, a->zad);
+ zn = vec_full_reg_ptr(s, a->zn);
+ zm = vec_full_reg_ptr(s, a->zm);
+ pn = pred_full_reg_ptr(s, a->pn);
+@@ -337,8 +350,7 @@ static bool do_outprod_fpst(DisasContext *s, arg_op *a, MemOp esz,
+ return true;
+ }
+
+- /* Sum XZR+zad to find ZAd. */
+- za = get_tile_rowcol(s, esz, 31, a->zad, false);
++ za = get_tile(s, esz, a->zad);
+ zn = vec_full_reg_ptr(s, a->zn);
+ zm = vec_full_reg_ptr(s, a->zm);
+ pn = pred_full_reg_ptr(s, a->pn);
+diff --git a/target/hppa/translate.c b/target/hppa/translate.c
+index 1af77473da..ee68d2f834 100644
+--- a/target/hppa/translate.c
++++ b/target/hppa/translate.c
+@@ -3473,6 +3473,7 @@ static bool trans_be(DisasContext *ctx, arg_be *a)
+ tcg_gen_addi_reg(cpu_iaoq_b, cpu_iaoq_f, 4);
+ tcg_gen_mov_i64(cpu_iasq_f, new_spc);
+ tcg_gen_mov_i64(cpu_iasq_b, cpu_iasq_f);
++ nullify_set(ctx, 0);
+ } else {
+ copy_iaoq_entry(cpu_iaoq_f, ctx->iaoq_b, cpu_iaoq_b);
+ if (ctx->iaoq_b == -1) {
+diff --git a/target/i386/cpu-param.h b/target/i386/cpu-param.h
+index f579b16bd2..e21e472e1e 100644
+--- a/target/i386/cpu-param.h
++++ b/target/i386/cpu-param.h
+@@ -23,7 +23,7 @@
+ # define TARGET_VIRT_ADDR_SPACE_BITS 32
+ #endif
+ #define TARGET_PAGE_BITS 12
+-#define NB_MMU_MODES 5
++#define NB_MMU_MODES 8
+
+ #ifndef CONFIG_USER_ONLY
+ # define TARGET_TB_PCREL 1
+diff --git a/target/i386/cpu.h b/target/i386/cpu.h
+index 7be047ce33..326649ca99 100644
+--- a/target/i386/cpu.h
++++ b/target/i386/cpu.h
+@@ -2182,17 +2182,42 @@ uint64_t cpu_get_tsc(CPUX86State *env);
+ #define cpu_list x86_cpu_list
+
+ /* MMU modes definitions */
+-#define MMU_KSMAP_IDX 0
+-#define MMU_USER_IDX 1
+-#define MMU_KNOSMAP_IDX 2
+-#define MMU_NESTED_IDX 3
+-#define MMU_PHYS_IDX 4
++#define MMU_KSMAP64_IDX 0
++#define MMU_KSMAP32_IDX 1
++#define MMU_USER64_IDX 2
++#define MMU_USER32_IDX 3
++#define MMU_KNOSMAP64_IDX 4
++#define MMU_KNOSMAP32_IDX 5
++#define MMU_PHYS_IDX 6
++#define MMU_NESTED_IDX 7
++
++#ifdef CONFIG_USER_ONLY
++#ifdef TARGET_X86_64
++#define MMU_USER_IDX MMU_USER64_IDX
++#else
++#define MMU_USER_IDX MMU_USER32_IDX
++#endif
++#endif
+
+ static inline int cpu_mmu_index(CPUX86State *env, bool ifetch)
+ {
+- return (env->hflags & HF_CPL_MASK) == 3 ? MMU_USER_IDX :
+- (!(env->hflags & HF_SMAP_MASK) || (env->eflags & AC_MASK))
+- ? MMU_KNOSMAP_IDX : MMU_KSMAP_IDX;
++ int mmu_index_32 = (env->hflags & HF_CS64_MASK) ? 0 : 1;
++ int mmu_index_base =
++ (env->hflags & HF_CPL_MASK) == 3 ? MMU_USER64_IDX :
++ !(env->hflags & HF_SMAP_MASK) ? MMU_KNOSMAP64_IDX :
++ (env->eflags & AC_MASK) ? MMU_KNOSMAP64_IDX : MMU_KSMAP64_IDX;
++
++ return mmu_index_base + mmu_index_32;
++}
++
++static inline bool is_mmu_index_smap(int mmu_index)
++{
++ return (mmu_index & ~1) == MMU_KSMAP64_IDX;
++}
++
++static inline bool is_mmu_index_user(int mmu_index)
++{
++ return (mmu_index & ~1) == MMU_USER64_IDX;
+ }
+
+ static inline bool is_mmu_index_32(int mmu_index)
+@@ -2203,9 +2228,12 @@ static inline bool is_mmu_index_32(int mmu_index)
+
+ static inline int cpu_mmu_index_kernel(CPUX86State *env)
+ {
+- return !(env->hflags & HF_SMAP_MASK) ? MMU_KNOSMAP_IDX :
+- ((env->hflags & HF_CPL_MASK) < 3 && (env->eflags & AC_MASK))
+- ? MMU_KNOSMAP_IDX : MMU_KSMAP_IDX;
++ int mmu_index_32 = (env->hflags & HF_LMA_MASK) ? 0 : 1;
++ int mmu_index_base =
++ !(env->hflags & HF_SMAP_MASK) ? MMU_KNOSMAP64_IDX :
++ ((env->hflags & HF_CPL_MASK) < 3 && (env->eflags & AC_MASK)) ? MMU_KNOSMAP64_IDX : MMU_KSMAP64_IDX;
++
++ return mmu_index_base + mmu_index_32;
+ }
+
+ #define CC_DST (env->cc_dst)
+diff --git a/target/i386/helper.c b/target/i386/helper.c
+index 0ac2da066d..290d9d309c 100644
+--- a/target/i386/helper.c
++++ b/target/i386/helper.c
+@@ -427,7 +427,7 @@ static void do_inject_x86_mce(CPUState *cs, run_on_cpu_data data)
+ if (need_reset) {
+ emit_guest_memory_failure(MEMORY_FAILURE_ACTION_RESET, ar,
+ recursive);
+- monitor_puts(params->mon, msg);
++ monitor_printf(params->mon, "%s", msg);
+ qemu_log_mask(CPU_LOG_RESET, "%s\n", msg);
+ qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
+ return;
+diff --git a/target/i386/tcg/sysemu/excp_helper.c b/target/i386/tcg/sysemu/excp_helper.c
+index 5999cdedf5..5f13252d68 100644
+--- a/target/i386/tcg/sysemu/excp_helper.c
++++ b/target/i386/tcg/sysemu/excp_helper.c
+@@ -135,7 +135,7 @@ static bool mmu_translate(CPUX86State *env, const TranslateParams *in,
+ {
+ const target_ulong addr = in->addr;
+ const int pg_mode = in->pg_mode;
+- const bool is_user = (in->mmu_idx == MMU_USER_IDX);
++ const bool is_user = is_mmu_index_user(in->mmu_idx);
+ const MMUAccessType access_type = in->access_type;
+ uint64_t ptep, pte, rsvd_mask;
+ PTETranslate pte_trans = {
+@@ -355,7 +355,7 @@ do_check_protect_pse36:
+ }
+
+ int prot = 0;
+- if (in->mmu_idx != MMU_KSMAP_IDX || !(ptep & PG_USER_MASK)) {
++ if (!is_mmu_index_smap(in->mmu_idx) || !(ptep & PG_USER_MASK)) {
+ prot |= PAGE_READ;
+ if ((ptep & PG_RW_MASK) || !(is_user || (pg_mode & PG_MODE_WP))) {
+ prot |= PAGE_WRITE;
+@@ -541,7 +541,8 @@ static bool get_physical_address(CPUX86State *env, vaddr addr,
+ if (likely(use_stage2)) {
+ in.cr3 = env->nested_cr3;
+ in.pg_mode = env->nested_pg_mode;
+- in.mmu_idx = MMU_USER_IDX;
++ in.mmu_idx =
++ env->nested_pg_mode & PG_MODE_LMA ? MMU_USER64_IDX : MMU_USER32_IDX;
+ in.ptw_idx = MMU_PHYS_IDX;
+
+ if (!mmu_translate(env, &in, out, err)) {
+diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
+index 46b04cbdad..92dd50e15e 100644
+--- a/target/loongarch/cpu.c
++++ b/target/loongarch/cpu.c
+@@ -33,31 +33,45 @@ const char * const fregnames[32] = {
+ "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
+ };
+
+-static const char * const excp_names[] = {
+- [EXCCODE_INT] = "Interrupt",
+- [EXCCODE_PIL] = "Page invalid exception for load",
+- [EXCCODE_PIS] = "Page invalid exception for store",
+- [EXCCODE_PIF] = "Page invalid exception for fetch",
+- [EXCCODE_PME] = "Page modified exception",
+- [EXCCODE_PNR] = "Page Not Readable exception",
+- [EXCCODE_PNX] = "Page Not Executable exception",
+- [EXCCODE_PPI] = "Page Privilege error",
+- [EXCCODE_ADEF] = "Address error for instruction fetch",
+- [EXCCODE_ADEM] = "Address error for Memory access",
+- [EXCCODE_SYS] = "Syscall",
+- [EXCCODE_BRK] = "Break",
+- [EXCCODE_INE] = "Instruction Non-Existent",
+- [EXCCODE_IPE] = "Instruction privilege error",
+- [EXCCODE_FPD] = "Floating Point Disabled",
+- [EXCCODE_FPE] = "Floating Point Exception",
+- [EXCCODE_DBP] = "Debug breakpoint",
+- [EXCCODE_BCE] = "Bound Check Exception",
++struct TypeExcp {
++ int32_t exccode;
++ const char * const name;
++};
++
++static const struct TypeExcp excp_names[] = {
++ {EXCCODE_INT, "Interrupt"},
++ {EXCCODE_PIL, "Page invalid exception for load"},
++ {EXCCODE_PIS, "Page invalid exception for store"},
++ {EXCCODE_PIF, "Page invalid exception for fetch"},
++ {EXCCODE_PME, "Page modified exception"},
++ {EXCCODE_PNR, "Page Not Readable exception"},
++ {EXCCODE_PNX, "Page Not Executable exception"},
++ {EXCCODE_PPI, "Page Privilege error"},
++ {EXCCODE_ADEF, "Address error for instruction fetch"},
++ {EXCCODE_ADEM, "Address error for Memory access"},
++ {EXCCODE_SYS, "Syscall"},
++ {EXCCODE_BRK, "Break"},
++ {EXCCODE_INE, "Instruction Non-Existent"},
++ {EXCCODE_IPE, "Instruction privilege error"},
++ {EXCCODE_FPD, "Floating Point Disabled"},
++ {EXCCODE_FPE, "Floating Point Exception"},
++ {EXCCODE_DBP, "Debug breakpoint"},
++ {EXCCODE_BCE, "Bound Check Exception"},
++ {EXCCODE_SXD, "128 bit vector instructions Disable exception"},
++ {EXCCODE_ASXD, "256 bit vector instructions Disable exception"},
++ {EXCP_HLT, "EXCP_HLT"},
+ };
+
+ const char *loongarch_exception_name(int32_t exception)
+ {
+- assert(excp_names[exception]);
+- return excp_names[exception];
++ int i;
++
++ for (i = 0; i < ARRAY_SIZE(excp_names); i++) {
++ if (excp_names[i].exccode == exception) {
++ return excp_names[i].name;
++ }
++ }
++ return "Unknown";
+ }
+
+ void G_NORETURN do_raise_exception(CPULoongArchState *env,
+@@ -66,7 +80,7 @@ void G_NORETURN do_raise_exception(CPULoongArchState *env,
+ {
+ CPUState *cs = env_cpu(env);
+
+- qemu_log_mask(CPU_LOG_INT, "%s: %d (%s)\n",
++ qemu_log_mask(CPU_LOG_INT, "%s: expection: %d (%s)\n",
+ __func__,
+ exception,
+ loongarch_exception_name(exception));
+@@ -143,22 +157,16 @@ static void loongarch_cpu_do_interrupt(CPUState *cs)
+ CPULoongArchState *env = &cpu->env;
+ bool update_badinstr = 1;
+ int cause = -1;
+- const char *name;
+ bool tlbfill = FIELD_EX64(env->CSR_TLBRERA, CSR_TLBRERA, ISTLBR);
+ uint32_t vec_size = FIELD_EX64(env->CSR_ECFG, CSR_ECFG, VS);
+
+ if (cs->exception_index != EXCCODE_INT) {
+- if (cs->exception_index < 0 ||
+- cs->exception_index >= ARRAY_SIZE(excp_names)) {
+- name = "unknown";
+- } else {
+- name = excp_names[cs->exception_index];
+- }
+-
+ qemu_log_mask(CPU_LOG_INT,
+ "%s enter: pc " TARGET_FMT_lx " ERA " TARGET_FMT_lx
+- " TLBRERA " TARGET_FMT_lx " %s exception\n", __func__,
+- env->pc, env->CSR_ERA, env->CSR_TLBRERA, name);
++ " TLBRERA " TARGET_FMT_lx " exception: %d (%s)\n",
++ __func__, env->pc, env->CSR_ERA, env->CSR_TLBRERA,
++ cs->exception_index,
++ loongarch_exception_name(cs->exception_index));
+ }
+
+ switch (cs->exception_index) {
+diff --git a/target/sh4/translate.c b/target/sh4/translate.c
+index 7db3468b01..8d6eae7ddf 100644
+--- a/target/sh4/translate.c
++++ b/target/sh4/translate.c
+@@ -528,6 +528,7 @@ static void _decode_opc(DisasContext * ctx)
+ tcg_gen_movi_i32(REG(B11_8), B7_0s);
+ return;
+ case 0x9000: /* mov.w @(disp,PC),Rn */
++ CHECK_NOT_DELAY_SLOT
+ {
+ TCGv addr = tcg_const_i32(ctx->base.pc_next + 4 + B7_0 * 2);
+ tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx, MO_TESW);
+@@ -535,6 +536,7 @@ static void _decode_opc(DisasContext * ctx)
+ }
+ return;
+ case 0xd000: /* mov.l @(disp,PC),Rn */
++ CHECK_NOT_DELAY_SLOT
+ {
+ TCGv addr = tcg_const_i32((ctx->base.pc_next + 4 + B7_0 * 4) & ~3);
+ tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx, MO_TESL);
+@@ -1295,6 +1297,7 @@ static void _decode_opc(DisasContext * ctx)
+ }
+ return;
+ case 0xc700: /* mova @(disp,PC),R0 */
++ CHECK_NOT_DELAY_SLOT
+ tcg_gen_movi_i32(REG(0), ((ctx->base.pc_next & 0xfffffffc) +
+ 4 + B7_0 * 4) & ~3);
+ return;
+diff --git a/tcg/optimize.c b/tcg/optimize.c
+index ae081ab29c..100b75efd8 100644
+--- a/tcg/optimize.c
++++ b/tcg/optimize.c
+@@ -1634,16 +1634,10 @@ static bool fold_nand(OptContext *ctx, TCGOp *op)
+ return false;
+ }
+
+-static bool fold_neg(OptContext *ctx, TCGOp *op)
++static bool fold_neg_no_const(OptContext *ctx, TCGOp *op)
+ {
+- uint64_t z_mask;
+-
+- if (fold_const1(ctx, op)) {
+- return true;
+- }
+-
+ /* Set to 1 all bits to the left of the rightmost. */
+- z_mask = arg_info(op->args[1])->z_mask;
++ uint64_t z_mask = arg_info(op->args[1])->z_mask;
+ ctx->z_mask = -(z_mask & -z_mask);
+
+ /*
+@@ -1654,6 +1648,11 @@ static bool fold_neg(OptContext *ctx, TCGOp *op)
+ return true;
+ }
+
++static bool fold_neg(OptContext *ctx, TCGOp *op)
++{
++ return fold_const1(ctx, op) || fold_neg_no_const(ctx, op);
++}
++
+ static bool fold_nor(OptContext *ctx, TCGOp *op)
+ {
+ if (fold_const2_commutative(ctx, op) ||
+@@ -1907,7 +1906,7 @@ static bool fold_shift(OptContext *ctx, TCGOp *op)
+ * will not reduced the number of input sign repetitions.
+ */
+ sign = (s_mask & -s_mask) >> 1;
+- if (!(z_mask & sign)) {
++ if (sign && !(z_mask & sign)) {
+ ctx->s_mask = s_mask;
+ }
+ break;
+@@ -1949,7 +1948,7 @@ static bool fold_sub_to_neg(OptContext *ctx, TCGOp *op)
+ if (have_neg) {
+ op->opc = neg_op;
+ op->args[1] = op->args[2];
+- return fold_neg(ctx, op);
++ return fold_neg_no_const(ctx, op);
+ }
+ return false;
+ }
+diff --git a/tests/tcg/aarch64/Makefile.target b/tests/tcg/aarch64/Makefile.target
+index a72578fccb..bd29446835 100644
+--- a/tests/tcg/aarch64/Makefile.target
++++ b/tests/tcg/aarch64/Makefile.target
+@@ -10,6 +10,7 @@ VPATH += $(AARCH64_SRC)
+
+ # Base architecture tests
+ AARCH64_TESTS=fcvt pcalign-a64
++AARCH64_TESTS += test-2248 test-2150
+
+ fcvt: LDFLAGS+=-lm
+
+@@ -23,7 +24,8 @@ config-cc.mak: Makefile
+ $(call cc-option,-march=armv8.1-a+sve2, CROSS_CC_HAS_SVE2); \
+ $(call cc-option,-march=armv8.3-a, CROSS_CC_HAS_ARMV8_3); \
+ $(call cc-option,-mbranch-protection=standard, CROSS_CC_HAS_ARMV8_BTI); \
+- $(call cc-option,-march=armv8.5-a+memtag, CROSS_CC_HAS_ARMV8_MTE)) 3> config-cc.mak
++ $(call cc-option,-march=armv8.5-a+memtag, CROSS_CC_HAS_ARMV8_MTE); \
++ $(call cc-option,-Wa$(COMMA)-march=armv9-a+sme, CROSS_AS_HAS_ARMV9_SME)) 3> config-cc.mak
+ -include config-cc.mak
+
+ # Pauth Tests
+@@ -50,11 +52,15 @@ AARCH64_TESTS += mte-1 mte-2 mte-3 mte-4 mte-5 mte-6 mte-7
+ mte-%: CFLAGS += -march=armv8.5-a+memtag
+ endif
+
+-ifneq ($(CROSS_CC_HAS_SVE),)
++# SME Tests
++ifneq ($(CROSS_AS_HAS_ARMV9_SME),)
++AARCH64_TESTS += sme-outprod1
++endif
++
+ # System Registers Tests
+ AARCH64_TESTS += sysregs
+-sysregs: CFLAGS+=-march=armv8.1-a+sve
+
++ifneq ($(CROSS_CC_HAS_SVE),)
+ # SVE ioctl test
+ AARCH64_TESTS += sve-ioctls
+ sve-ioctls: CFLAGS+=-march=armv8.1-a+sve
+diff --git a/tests/tcg/aarch64/sme-outprod1.c b/tests/tcg/aarch64/sme-outprod1.c
+new file mode 100644
+index 0000000000..6e5972d75e
+--- /dev/null
++++ b/tests/tcg/aarch64/sme-outprod1.c
+@@ -0,0 +1,83 @@
++/*
++ * SME outer product, 1 x 1.
++ * SPDX-License-Identifier: GPL-2.0-or-later
++ */
++
++#include <stdio.h>
++
++extern void foo(float *dst);
++
++asm(
++" .arch_extension sme\n"
++" .type foo, @function\n"
++"foo:\n"
++" stp x29, x30, [sp, -80]!\n"
++" mov x29, sp\n"
++" stp d8, d9, [sp, 16]\n"
++" stp d10, d11, [sp, 32]\n"
++" stp d12, d13, [sp, 48]\n"
++" stp d14, d15, [sp, 64]\n"
++" smstart\n"
++" ptrue p0.s, vl4\n"
++" fmov z0.s, #1.0\n"
++/*
++ * An outer product of a vector of 1.0 by itself should be a matrix of 1.0.
++ * Note that we are using tile 1 here (za1.s) rather than tile 0.
++ */
++" zero {za}\n"
++" fmopa za1.s, p0/m, p0/m, z0.s, z0.s\n"
++/*
++ * Read the first 4x4 sub-matrix of elements from tile 1:
++ * Note that za1h should be interchangable here.
++ */
++" mov w12, #0\n"
++" mova z0.s, p0/m, za1v.s[w12, #0]\n"
++" mova z1.s, p0/m, za1v.s[w12, #1]\n"
++" mova z2.s, p0/m, za1v.s[w12, #2]\n"
++" mova z3.s, p0/m, za1v.s[w12, #3]\n"
++/*
++ * And store them to the input pointer (dst in the C code):
++ */
++" st1w {z0.s}, p0, [x0]\n"
++" add x0, x0, #16\n"
++" st1w {z1.s}, p0, [x0]\n"
++" add x0, x0, #16\n"
++" st1w {z2.s}, p0, [x0]\n"
++" add x0, x0, #16\n"
++" st1w {z3.s}, p0, [x0]\n"
++" smstop\n"
++" ldp d8, d9, [sp, 16]\n"
++" ldp d10, d11, [sp, 32]\n"
++" ldp d12, d13, [sp, 48]\n"
++" ldp d14, d15, [sp, 64]\n"
++" ldp x29, x30, [sp], 80\n"
++" ret\n"
++" .size foo, . - foo"
++);
++
++int main()
++{
++ float dst[16];
++ int i, j;
++
++ foo(dst);
++
++ for (i = 0; i < 16; i++) {
++ if (dst[i] != 1.0f) {
++ break;
++ }
++ }
++
++ if (i == 16) {
++ return 0; /* success */
++ }
++
++ /* failure */
++ for (i = 0; i < 4; ++i) {
++ for (j = 0; j < 4; ++j) {
++ printf("%f ", (double)dst[i * 4 + j]);
++ }
++ printf("\n");
++ }
++ return 1;
++}
+diff --git a/tests/tcg/aarch64/sysregs.c b/tests/tcg/aarch64/sysregs.c
+index 40cf8d2877..d8eb06abcf 100644
+--- a/tests/tcg/aarch64/sysregs.c
++++ b/tests/tcg/aarch64/sysregs.c
+@@ -22,6 +22,18 @@
+ #define HWCAP_CPUID (1 << 11)
+ #endif
+
++/*
++ * Older assemblers don't recognize newer system register names,
++ * but we can still access them by the Sn_n_Cn_Cn_n syntax.
++ * This also means we don't need to specifically request that the
++ * assembler enables whatever architectural features the ID registers
++ * syntax might be gated behind.
++ */
++#define SYS_ID_AA64ISAR2_EL1 S3_0_C0_C6_2
++#define SYS_ID_AA64MMFR2_EL1 S3_0_C0_C7_2
++#define SYS_ID_AA64ZFR0_EL1 S3_0_C0_C4_4
++#define SYS_ID_AA64SMFR0_EL1 S3_0_C0_C4_5
++
+ int failed_bit_count;
+
+ /* Read and print system register `id' value */
+@@ -112,18 +124,21 @@ int main(void)
+ * minimum valid fields - for the purposes of this check allowed
+ * to have non-zero values.
+ */
+- get_cpu_reg_check_mask(id_aa64isar0_el1, _m(00ff,ffff,f0ff,fff0));
+- get_cpu_reg_check_mask(id_aa64isar1_el1, _m(0000,00f0,ffff,ffff));
++ get_cpu_reg_check_mask(id_aa64isar0_el1, _m(f0ff,ffff,f0ff,fff0));
++ get_cpu_reg_check_mask(id_aa64isar1_el1, _m(00ff,f0ff,ffff,ffff));
++ get_cpu_reg_check_mask(SYS_ID_AA64ISAR2_EL1, _m(0000,0000,0000,ffff));
+ /* TGran4 & TGran64 as pegged to -1 */
+- get_cpu_reg_check_mask(id_aa64mmfr0_el1, _m(0000,0000,ff00,0000));
+- get_cpu_reg_check_zero(id_aa64mmfr1_el1);
++ get_cpu_reg_check_mask(id_aa64mmfr0_el1, _m(f000,0000,ff00,0000));
++ get_cpu_reg_check_mask(id_aa64mmfr1_el1, _m(0000,f000,0000,0000));
++ get_cpu_reg_check_mask(SYS_ID_AA64MMFR2_EL1, _m(0000,000f,0000,0000));
+ /* EL1/EL0 reported as AA64 only */
+ get_cpu_reg_check_mask(id_aa64pfr0_el1, _m(000f,000f,00ff,0011));
+- get_cpu_reg_check_mask(id_aa64pfr1_el1, _m(0000,0000,0000,00f0));
++ get_cpu_reg_check_mask(id_aa64pfr1_el1, _m(0000,0000,0f00,0fff));
+ /* all hidden, DebugVer fixed to 0x6 (ARMv8 debug architecture) */
+ get_cpu_reg_check_mask(id_aa64dfr0_el1, _m(0000,0000,0000,0006));
+ get_cpu_reg_check_zero(id_aa64dfr1_el1);
+- get_cpu_reg_check_zero(id_aa64zfr0_el1);
++ get_cpu_reg_check_mask(SYS_ID_AA64ZFR0_EL1, _m(0ff0,ff0f,00ff,00ff));
++ get_cpu_reg_check_mask(SYS_ID_AA64SMFR0_EL1, _m(80f1,00fd,0000,0000));
+
+ get_cpu_reg_check_zero(id_aa64afr0_el1);
+ get_cpu_reg_check_zero(id_aa64afr1_el1);
+diff --git a/tests/tcg/aarch64/test-2150.c b/tests/tcg/aarch64/test-2150.c
+new file mode 100644
+index 0000000000..fb86c11958
+--- /dev/null
++++ b/tests/tcg/aarch64/test-2150.c
+@@ -0,0 +1,12 @@
++/* SPDX-License-Identifier: GPL-2.0-or-later */
++/* See https://gitlab.com/qemu-project/qemu/-/issues/2150 */
++
++int main()
++{
++ asm volatile(
++ "movi v6.4s, #1\n"
++ "movi v7.4s, #0\n"
++ "sub v6.2d, v7.2d, v6.2d\n"
++ : : : "v6", "v7");
++ return 0;
++}
+diff --git a/tests/tcg/aarch64/test-2248.c b/tests/tcg/aarch64/test-2248.c
+new file mode 100644
+index 0000000000..aac2e17836
+--- /dev/null
++++ b/tests/tcg/aarch64/test-2248.c
+@@ -0,0 +1,28 @@
++/* SPDX-License-Identifier: GPL-2.0-or-later */
++/* See https://gitlab.com/qemu-project/qemu/-/issues/2248 */
++
++#include <assert.h>
++
++__attribute__((noinline))
++long test(long x, long y, long sh)
++{
++ long r;
++ asm("cmp %1, %2\n\t"
++ "cset x12, lt\n\t"
++ "and w11, w12, #0xff\n\t"
++ "cmp w11, #0\n\t"
++ "csetm x14, ne\n\t"
++ "lsr x13, x14, %3\n\t"
++ "sxtb %0, w13"
++ : "=r"(r)
++ : "r"(x), "r"(y), "r"(sh)
++ : "x11", "x12", "x13", "x14");
++ return r;
++}
++
++int main()
++{
++ long r = test(0, 1, 2);
++ assert(r == -1);
++ return 0;
++}
+diff --git a/tests/unit/meson.build b/tests/unit/meson.build
+index b497a41378..ca44f45232 100644
+--- a/tests/unit/meson.build
++++ b/tests/unit/meson.build
+@@ -166,8 +166,12 @@ test_env.set('G_TEST_SRCDIR', meson.current_source_dir())
+ test_env.set('G_TEST_BUILDDIR', meson.current_build_dir())
+
+ slow_tests = {
+- 'test-crypto-tlscredsx509': 45,
+- 'test-crypto-tlssession': 45
++ 'test-aio-multithread' : 120,
++ 'test-bufferiszero': 60,
++ 'test-crypto-block' : 300,
++ 'test-crypto-tlscredsx509': 90,
++ 'test-crypto-tlssession': 90,
++ 'test-replication': 60,
+ }
+
+ foreach test_name, extra: tests
+diff --git a/ui/cocoa.m b/ui/cocoa.m
+index 660d3e0935..c41689e951 100644
+--- a/ui/cocoa.m
++++ b/ui/cocoa.m
+@@ -53,6 +53,10 @@
+ #define MAC_OS_X_VERSION_10_13 101300
+ #endif
+
++#ifndef MAC_OS_VERSION_14_0
++#define MAC_OS_VERSION_14_0 140000
++#endif
++
+ /* 10.14 deprecates NSOnState and NSOffState in favor of
+ * NSControlStateValueOn/Off, which were introduced in 10.13.
+ * Define for older versions
+@@ -361,6 +365,9 @@ - (id)initWithFrame:(NSRect)frameRect
+ screen.width = frameRect.size.width;
+ screen.height = frameRect.size.height;
+ kbd = qkbd_state_init(dcl.con);
++#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_VERSION_14_0
++ [self setClipsToBounds:YES];
++#endif
+
+ }
+ return self;
diff --git a/debian/patches/v7.2.12.diff b/debian/patches/v7.2.12.diff
new file mode 100644
index 00000000..3327a3e5
--- /dev/null
+++ b/debian/patches/v7.2.12.diff
@@ -0,0 +1,1516 @@
+Subject: v7.2.12
+Date: Sun Jun 9 00:23:52 2024 +0300
+From: Michael Tokarev <mjt@tls.msk.ru>
+Forwarded: not-needed
+
+This is a difference between upstream qemu v7.2.11
+and upstream qemu v7.2.12.
+
+
+.gitlab-ci.d/cirrus.yml | 2 +
+ .gitlab-ci.d/edk2.yml | 85 -------------------
+ .gitlab-ci.d/edk2/Dockerfile | 27 ------
+ .gitlab-ci.d/opensbi.yml | 4 +-
+ .gitlab-ci.d/opensbi/Dockerfile | 1 +
+ .gitlab-ci.d/qemu-project.yml | 1 -
+ .gitlab-ci.d/windows.yml | 4 +-
+ MAINTAINERS | 2 -
+ VERSION | 2 +-
+ backends/cryptodev-builtin.c | 9 +-
+ disas/riscv.c | 65 ++++++++++++++-
+ hw/arm/npcm7xx.c | 3 +-
+ hw/dma/xlnx_dpdma.c | 20 ++---
+ hw/intc/arm_gic.c | 4 +-
+ hw/intc/riscv_aplic.c | 6 +-
+ hw/remote/vfio-user-obj.c | 4 +-
+ linux-user/syscall.c | 9 +-
+ nbd/client.c | 28 ++++++-
+ nbd/common.c | 11 ---
+ nbd/nbd-internal.h | 10 ---
+ nbd/server.c | 130 ++++++++++++++++++-----------
+ target/arm/cpu64.c | 6 +-
+ target/arm/hvf/hvf.c | 160 ++++++++++++++++++------------------
+ target/i386/kvm/hyperv.c | 2 +-
+ target/i386/tcg/decode-new.c.inc | 4 +-
+ target/i386/tcg/fpu_helper.c | 5 ++
+ target/i386/tcg/translate.c | 31 +++----
+ target/loongarch/cpu.c | 2 +-
+ tests/avocado/boot_linux_console.py | 40 ++++-----
+ tests/avocado/replay_kernel.py | 8 +-
+ ui/gtk-egl.c | 2 +-
+ ui/gtk-gl-area.c | 2 +-
+ ui/gtk.c | 28 +++++--
+ ui/sdl2.c | 1 +
+ 34 files changed, 360 insertions(+), 358 deletions(-)
+
+diff --git a/.gitlab-ci.d/cirrus.yml b/.gitlab-ci.d/cirrus.yml
+index c86487da5b..f6e97c47f1 100644
+--- a/.gitlab-ci.d/cirrus.yml
++++ b/.gitlab-ci.d/cirrus.yml
+@@ -68,6 +68,7 @@ x64-freebsd-13-build:
+ CIRRUS_VM_RAM: 8G
+ UPDATE_COMMAND: pkg update
+ INSTALL_COMMAND: pkg install -y
++ CONFIGURE_ARGS: --target-list-exclude=arm-softmmu,i386-softmmu,microblaze-softmmu,mips64el-softmmu,mipsel-softmmu,mips-softmmu,ppc-softmmu,sh4eb-softmmu,xtensa-softmmu
+ TEST_TARGETS: check
+
+ aarch64-macos-12-base-build:
+@@ -83,6 +84,7 @@ aarch64-macos-12-base-build:
+ INSTALL_COMMAND: brew install
+ PATH_EXTRA: /opt/homebrew/ccache/libexec:/opt/homebrew/gettext/bin
+ PKG_CONFIG_PATH: /opt/homebrew/curl/lib/pkgconfig:/opt/homebrew/ncurses/lib/pkgconfig:/opt/homebrew/readline/lib/pkgconfig
++ CONFIGURE_ARGS: --target-list-exclude=arm-softmmu,i386-softmmu,microblazeel-softmmu,mips64-softmmu,mipsel-softmmu,mips-softmmu,ppc-softmmu,sh4-softmmu,xtensaeb-softmmu
+ TEST_TARGETS: check-unit check-block check-qapi-schema check-softfloat check-qtest-x86_64
+
+
+diff --git a/.gitlab-ci.d/edk2.yml b/.gitlab-ci.d/edk2.yml
+deleted file mode 100644
+index 314e101745..0000000000
+--- a/.gitlab-ci.d/edk2.yml
++++ /dev/null
+@@ -1,85 +0,0 @@
+-# All jobs needing docker-edk2 must use the same rules it uses.
+-.edk2_job_rules:
+- rules:
+- # Forks don't get pipelines unless QEMU_CI=1 or QEMU_CI=2 is set
+- - if: '$QEMU_CI != "1" && $QEMU_CI != "2" && $CI_PROJECT_NAMESPACE != "qemu-project"'
+- when: never
+-
+- # In forks, if QEMU_CI=1 is set, then create manual job
+- # if any of the files affecting the build are touched
+- - if: '$QEMU_CI == "1" && $CI_PROJECT_NAMESPACE != "qemu-project"'
+- changes:
+- - .gitlab-ci.d/edk2.yml
+- - .gitlab-ci.d/edk2/Dockerfile
+- - roms/edk2/*
+- when: manual
+-
+- # In forks, if QEMU_CI=1 is set, then create manual job
+- # if the branch/tag starts with 'edk2'
+- - if: '$QEMU_CI == "1" && $CI_PROJECT_NAMESPACE != "qemu-project" && $CI_COMMIT_REF_NAME =~ /^edk2/'
+- when: manual
+-
+- # In forks, if QEMU_CI=1 is set, then create manual job
+- # if last commit msg contains 'EDK2' (case insensitive)
+- - if: '$QEMU_CI == "1" && $CI_PROJECT_NAMESPACE != "qemu-project" && $CI_COMMIT_MESSAGE =~ /edk2/i'
+- when: manual
+-
+- # Run if any files affecting the build output are touched
+- - changes:
+- - .gitlab-ci.d/edk2.yml
+- - .gitlab-ci.d/edk2/Dockerfile
+- - roms/edk2/*
+- when: on_success
+-
+- # Run if the branch/tag starts with 'edk2'
+- - if: '$CI_COMMIT_REF_NAME =~ /^edk2/'
+- when: on_success
+-
+- # Run if last commit msg contains 'EDK2' (case insensitive)
+- - if: '$CI_COMMIT_MESSAGE =~ /edk2/i'
+- when: on_success
+-
+-docker-edk2:
+- extends: .edk2_job_rules
+- stage: containers
+- image: docker:19.03.1
+- services:
+- - docker:19.03.1-dind
+- variables:
+- GIT_DEPTH: 3
+- IMAGE_TAG: $CI_REGISTRY_IMAGE:edk2-cross-build
+- # We don't use TLS
+- DOCKER_HOST: tcp://docker:2375
+- DOCKER_TLS_CERTDIR: ""
+- before_script:
+- - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
+- script:
+- - docker pull $IMAGE_TAG || true
+- - docker build --cache-from $IMAGE_TAG --tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
+- --tag $IMAGE_TAG .gitlab-ci.d/edk2
+- - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
+- - docker push $IMAGE_TAG
+-
+-build-edk2:
+- extends: .edk2_job_rules
+- stage: build
+- needs: ['docker-edk2']
+- artifacts:
+- paths: # 'artifacts.zip' will contains the following files:
+- - pc-bios/edk2*bz2
+- - pc-bios/edk2-licenses.txt
+- - edk2-stdout.log
+- - edk2-stderr.log
+- image: $CI_REGISTRY_IMAGE:edk2-cross-build
+- variables:
+- GIT_DEPTH: 3
+- script: # Clone the required submodules and build EDK2
+- - git submodule update --init roms/edk2
+- - git -C roms/edk2 submodule update --init --
+- ArmPkg/Library/ArmSoftFloatLib/berkeley-softfloat-3
+- BaseTools/Source/C/BrotliCompress/brotli
+- CryptoPkg/Library/OpensslLib/openssl
+- MdeModulePkg/Library/BrotliCustomDecompressLib/brotli
+- - export JOBS=$(($(getconf _NPROCESSORS_ONLN) + 1))
+- - echo "=== Using ${JOBS} simultaneous jobs ==="
+- - make -j${JOBS} -C roms efi 2>&1 1>edk2-stdout.log | tee -a edk2-stderr.log >&2
+diff --git a/.gitlab-ci.d/edk2/Dockerfile b/.gitlab-ci.d/edk2/Dockerfile
+deleted file mode 100644
+index bbe50ff832..0000000000
+--- a/.gitlab-ci.d/edk2/Dockerfile
++++ /dev/null
+@@ -1,27 +0,0 @@
+-#
+-# Docker image to cross-compile EDK2 firmware binaries
+-#
+-FROM ubuntu:18.04
+-
+-MAINTAINER Philippe Mathieu-Daudé <f4bug@amsat.org>
+-
+-# Install packages required to build EDK2
+-RUN apt update \
+- && \
+- \
+- DEBIAN_FRONTEND=noninteractive \
+- apt install --assume-yes --no-install-recommends \
+- build-essential \
+- ca-certificates \
+- dos2unix \
+- gcc-aarch64-linux-gnu \
+- gcc-arm-linux-gnueabi \
+- git \
+- iasl \
+- make \
+- nasm \
+- python3 \
+- uuid-dev \
+- && \
+- \
+- rm -rf /var/lib/apt/lists/*
+diff --git a/.gitlab-ci.d/opensbi.yml b/.gitlab-ci.d/opensbi.yml
+index 04ed5a3ea1..9a651465d8 100644
+--- a/.gitlab-ci.d/opensbi.yml
++++ b/.gitlab-ci.d/opensbi.yml
+@@ -42,9 +42,9 @@
+ docker-opensbi:
+ extends: .opensbi_job_rules
+ stage: containers
+- image: docker:19.03.1
++ image: docker:stable
+ services:
+- - docker:19.03.1-dind
++ - docker:stable-dind
+ variables:
+ GIT_DEPTH: 3
+ IMAGE_TAG: $CI_REGISTRY_IMAGE:opensbi-cross-build
+diff --git a/.gitlab-ci.d/opensbi/Dockerfile b/.gitlab-ci.d/opensbi/Dockerfile
+index 4ba8a4de86..5ccf4151f4 100644
+--- a/.gitlab-ci.d/opensbi/Dockerfile
++++ b/.gitlab-ci.d/opensbi/Dockerfile
+@@ -15,6 +15,7 @@ RUN apt update \
+ ca-certificates \
+ git \
+ make \
++ python3 \
+ wget \
+ && \
+ \
+diff --git a/.gitlab-ci.d/qemu-project.yml b/.gitlab-ci.d/qemu-project.yml
+index 691d9bf5dc..a7ed447fe4 100644
+--- a/.gitlab-ci.d/qemu-project.yml
++++ b/.gitlab-ci.d/qemu-project.yml
+@@ -4,7 +4,6 @@
+ include:
+ - local: '/.gitlab-ci.d/base.yml'
+ - local: '/.gitlab-ci.d/stages.yml'
+- - local: '/.gitlab-ci.d/edk2.yml'
+ - local: '/.gitlab-ci.d/opensbi.yml'
+ - local: '/.gitlab-ci.d/containers.yml'
+ - local: '/.gitlab-ci.d/crossbuilds.yml'
+diff --git a/.gitlab-ci.d/windows.yml b/.gitlab-ci.d/windows.yml
+index 0180261b7f..dfa4eb84a7 100644
+--- a/.gitlab-ci.d/windows.yml
++++ b/.gitlab-ci.d/windows.yml
+@@ -1,9 +1,7 @@
+ .shared_msys2_builder:
+ extends: .base_job_template
+ tags:
+- - shared-windows
+- - windows
+- - windows-1809
++ - saas-windows-medium-amd64
+ cache:
+ key: "${CI_JOB_NAME}-cache"
+ paths:
+diff --git a/MAINTAINERS b/MAINTAINERS
+index 6966490c94..e688db1f55 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -3257,8 +3257,6 @@ F: roms/edk2
+ F: roms/edk2-*
+ F: tests/data/uefi-boot-images/
+ F: tests/uefi-test-tools/
+-F: .gitlab-ci.d/edk2.yml
+-F: .gitlab-ci.d/edk2/
+
+ VT-d Emulation
+ M: Michael S. Tsirkin <mst@redhat.com>
+diff --git a/VERSION b/VERSION
+index 971381d35b..4625f55e26 100644
+--- a/VERSION
++++ b/VERSION
+@@ -1 +1 @@
+-7.2.11
++7.2.12
+diff --git a/backends/cryptodev-builtin.c b/backends/cryptodev-builtin.c
+index 2e792be756..763e67dfd6 100644
+--- a/backends/cryptodev-builtin.c
++++ b/backends/cryptodev-builtin.c
+@@ -23,6 +23,7 @@
+
+ #include "qemu/osdep.h"
+ #include "sysemu/cryptodev.h"
++#include "qemu/error-report.h"
+ #include "qapi/error.h"
+ #include "standard-headers/linux/virtio_crypto.h"
+ #include "crypto/cipher.h"
+@@ -385,8 +386,8 @@ static int cryptodev_builtin_create_session(
+ case VIRTIO_CRYPTO_HASH_CREATE_SESSION:
+ case VIRTIO_CRYPTO_MAC_CREATE_SESSION:
+ default:
+- error_setg(&local_error, "Unsupported opcode :%" PRIu32 "",
+- sess_info->op_code);
++ error_report("Unsupported opcode :%" PRIu32 "",
++ sess_info->op_code);
+ return -VIRTIO_CRYPTO_NOTSUPP;
+ }
+
+@@ -546,8 +547,8 @@ static int cryptodev_builtin_operation(
+
+ if (op_info->session_id >= MAX_NUM_SESSIONS ||
+ builtin->sessions[op_info->session_id] == NULL) {
+- error_setg(&local_error, "Cannot find a valid session id: %" PRIu64 "",
+- op_info->session_id);
++ error_report("Cannot find a valid session id: %" PRIu64 "",
++ op_info->session_id);
+ return -VIRTIO_CRYPTO_INVSESS;
+ }
+
+diff --git a/disas/riscv.c b/disas/riscv.c
+index dee4e580a0..42399867a1 100644
+--- a/disas/riscv.c
++++ b/disas/riscv.c
+@@ -2159,7 +2159,22 @@ static const char *csr_name(int csrno)
+ case 0x0383: return "mibound";
+ case 0x0384: return "mdbase";
+ case 0x0385: return "mdbound";
+- case 0x03a0: return "pmpcfg3";
++ case 0x03a0: return "pmpcfg0";
++ case 0x03a1: return "pmpcfg1";
++ case 0x03a2: return "pmpcfg2";
++ case 0x03a3: return "pmpcfg3";
++ case 0x03a4: return "pmpcfg4";
++ case 0x03a5: return "pmpcfg5";
++ case 0x03a6: return "pmpcfg6";
++ case 0x03a7: return "pmpcfg7";
++ case 0x03a8: return "pmpcfg8";
++ case 0x03a9: return "pmpcfg9";
++ case 0x03aa: return "pmpcfg10";
++ case 0x03ab: return "pmpcfg11";
++ case 0x03ac: return "pmpcfg12";
++ case 0x03ad: return "pmpcfg13";
++ case 0x03ae: return "pmpcfg14";
++ case 0x03af: return "pmpcfg15";
+ case 0x03b0: return "pmpaddr0";
+ case 0x03b1: return "pmpaddr1";
+ case 0x03b2: return "pmpaddr2";
+@@ -2176,6 +2191,54 @@ static const char *csr_name(int csrno)
+ case 0x03bd: return "pmpaddr13";
+ case 0x03be: return "pmpaddr14";
+ case 0x03bf: return "pmpaddr15";
++ case 0x03c0: return "pmpaddr16";
++ case 0x03c1: return "pmpaddr17";
++ case 0x03c2: return "pmpaddr18";
++ case 0x03c3: return "pmpaddr19";
++ case 0x03c4: return "pmpaddr20";
++ case 0x03c5: return "pmpaddr21";
++ case 0x03c6: return "pmpaddr22";
++ case 0x03c7: return "pmpaddr23";
++ case 0x03c8: return "pmpaddr24";
++ case 0x03c9: return "pmpaddr25";
++ case 0x03ca: return "pmpaddr26";
++ case 0x03cb: return "pmpaddr27";
++ case 0x03cc: return "pmpaddr28";
++ case 0x03cd: return "pmpaddr29";
++ case 0x03ce: return "pmpaddr30";
++ case 0x03cf: return "pmpaddr31";
++ case 0x03d0: return "pmpaddr32";
++ case 0x03d1: return "pmpaddr33";
++ case 0x03d2: return "pmpaddr34";
++ case 0x03d3: return "pmpaddr35";
++ case 0x03d4: return "pmpaddr36";
++ case 0x03d5: return "pmpaddr37";
++ case 0x03d6: return "pmpaddr38";
++ case 0x03d7: return "pmpaddr39";
++ case 0x03d8: return "pmpaddr40";
++ case 0x03d9: return "pmpaddr41";
++ case 0x03da: return "pmpaddr42";
++ case 0x03db: return "pmpaddr43";
++ case 0x03dc: return "pmpaddr44";
++ case 0x03dd: return "pmpaddr45";
++ case 0x03de: return "pmpaddr46";
++ case 0x03df: return "pmpaddr47";
++ case 0x03e0: return "pmpaddr48";
++ case 0x03e1: return "pmpaddr49";
++ case 0x03e2: return "pmpaddr50";
++ case 0x03e3: return "pmpaddr51";
++ case 0x03e4: return "pmpaddr52";
++ case 0x03e5: return "pmpaddr53";
++ case 0x03e6: return "pmpaddr54";
++ case 0x03e7: return "pmpaddr55";
++ case 0x03e8: return "pmpaddr56";
++ case 0x03e9: return "pmpaddr57";
++ case 0x03ea: return "pmpaddr58";
++ case 0x03eb: return "pmpaddr59";
++ case 0x03ec: return "pmpaddr60";
++ case 0x03ed: return "pmpaddr61";
++ case 0x03ee: return "pmpaddr62";
++ case 0x03ef: return "pmpaddr63";
+ case 0x0780: return "mtohost";
+ case 0x0781: return "mfromhost";
+ case 0x0782: return "mreset";
+diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
+index d85cc02765..13d0b8bbb2 100644
+--- a/hw/arm/npcm7xx.c
++++ b/hw/arm/npcm7xx.c
+@@ -24,6 +24,7 @@
+ #include "hw/qdev-clock.h"
+ #include "hw/qdev-properties.h"
+ #include "qapi/error.h"
++#include "qemu/bswap.h"
+ #include "qemu/units.h"
+ #include "sysemu/sysemu.h"
+
+@@ -369,7 +370,7 @@ static void npcm7xx_init_fuses(NPCM7xxState *s)
+ * The initial mask of disabled modules indicates the chip derivative (e.g.
+ * NPCM750 or NPCM730).
+ */
+- value = tswap32(nc->disabled_modules);
++ value = cpu_to_le32(nc->disabled_modules);
+ npcm7xx_otp_array_write(&s->fuse_array, &value, NPCM7XX_FUSE_DERIVATIVE,
+ sizeof(value));
+ }
+diff --git a/hw/dma/xlnx_dpdma.c b/hw/dma/xlnx_dpdma.c
+index dd66be5265..06e187e99c 100644
+--- a/hw/dma/xlnx_dpdma.c
++++ b/hw/dma/xlnx_dpdma.c
+@@ -175,24 +175,24 @@ static uint64_t xlnx_dpdma_desc_get_source_address(DPDMADescriptor *desc,
+
+ switch (frag) {
+ case 0:
+- addr = desc->source_address
+- + (extract32(desc->address_extension, 16, 12) << 20);
++ addr = (uint64_t)desc->source_address
++ + (extract64(desc->address_extension, 16, 16) << 32);
+ break;
+ case 1:
+- addr = desc->source_address2
+- + (extract32(desc->address_extension_23, 0, 12) << 8);
++ addr = (uint64_t)desc->source_address2
++ + (extract64(desc->address_extension_23, 0, 16) << 32);
+ break;
+ case 2:
+- addr = desc->source_address3
+- + (extract32(desc->address_extension_23, 16, 12) << 20);
++ addr = (uint64_t)desc->source_address3
++ + (extract64(desc->address_extension_23, 16, 16) << 32);
+ break;
+ case 3:
+- addr = desc->source_address4
+- + (extract32(desc->address_extension_45, 0, 12) << 8);
++ addr = (uint64_t)desc->source_address4
++ + (extract64(desc->address_extension_45, 0, 16) << 32);
+ break;
+ case 4:
+- addr = desc->source_address5
+- + (extract32(desc->address_extension_45, 16, 12) << 20);
++ addr = (uint64_t)desc->source_address5
++ + (extract64(desc->address_extension_45, 16, 16) << 32);
+ break;
+ default:
+ addr = 0;
+diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c
+index 7a34bc0998..47f01e45e3 100644
+--- a/hw/intc/arm_gic.c
++++ b/hw/intc/arm_gic.c
+@@ -1658,7 +1658,7 @@ static MemTxResult gic_cpu_read(GICState *s, int cpu, int offset,
+ *data = s->h_apr[gic_get_vcpu_real_id(cpu)];
+ } else if (gic_cpu_ns_access(s, cpu, attrs)) {
+ /* NS view of GICC_APR<n> is the top half of GIC_NSAPR<n> */
+- *data = gic_apr_ns_view(s, regno, cpu);
++ *data = gic_apr_ns_view(s, cpu, regno);
+ } else {
+ *data = s->apr[regno][cpu];
+ }
+@@ -1746,7 +1746,7 @@ static MemTxResult gic_cpu_write(GICState *s, int cpu, int offset,
+ s->h_apr[gic_get_vcpu_real_id(cpu)] = value;
+ } else if (gic_cpu_ns_access(s, cpu, attrs)) {
+ /* NS view of GICC_APR<n> is the top half of GIC_NSAPR<n> */
+- gic_apr_write_ns_view(s, regno, cpu, value);
++ gic_apr_write_ns_view(s, cpu, regno, value);
+ } else {
+ s->apr[regno][cpu] = value;
+ }
+diff --git a/hw/intc/riscv_aplic.c b/hw/intc/riscv_aplic.c
+index cfd007e629..961caff7b6 100644
+--- a/hw/intc/riscv_aplic.c
++++ b/hw/intc/riscv_aplic.c
+@@ -957,13 +957,13 @@ DeviceState *riscv_aplic_create(hwaddr addr, hwaddr size,
+ qdev_prop_set_bit(dev, "msimode", msimode);
+ qdev_prop_set_bit(dev, "mmode", mmode);
+
+- sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
+- sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr);
+-
+ if (parent) {
+ riscv_aplic_add_child(parent, dev);
+ }
+
++ sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
++ sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr);
++
+ if (!msimode) {
+ for (i = 0; i < num_harts; i++) {
+ CPUState *cpu = qemu_get_cpu(hartid_base + i);
+diff --git a/hw/remote/vfio-user-obj.c b/hw/remote/vfio-user-obj.c
+index 4e36bb8bcf..973cebe785 100644
+--- a/hw/remote/vfio-user-obj.c
++++ b/hw/remote/vfio-user-obj.c
+@@ -273,7 +273,7 @@ static ssize_t vfu_object_cfg_access(vfu_ctx_t *vfu_ctx, char * const buf,
+ while (bytes > 0) {
+ len = (bytes > pci_access_width) ? pci_access_width : bytes;
+ if (is_write) {
+- memcpy(&val, ptr, len);
++ val = ldn_le_p(ptr, len);
+ pci_host_config_write_common(o->pci_dev, offset,
+ pci_config_size(o->pci_dev),
+ val, len);
+@@ -281,7 +281,7 @@ static ssize_t vfu_object_cfg_access(vfu_ctx_t *vfu_ctx, char * const buf,
+ } else {
+ val = pci_host_config_read_common(o->pci_dev, offset,
+ pci_config_size(o->pci_dev), len);
+- memcpy(ptr, &val, len);
++ stn_le_p(ptr, len, val);
+ trace_vfu_cfg_read(offset, val);
+ }
+ offset += len;
+diff --git a/linux-user/syscall.c b/linux-user/syscall.c
+index 41017b0df2..74240f99ad 100644
+--- a/linux-user/syscall.c
++++ b/linux-user/syscall.c
+@@ -2297,18 +2297,13 @@ static abi_long do_setsockopt(int sockfd, int level, int optname,
+ switch (optname) {
+ case ALG_SET_KEY:
+ {
+- char *alg_key = g_malloc(optlen);
+-
++ char *alg_key = lock_user(VERIFY_READ, optval_addr, optlen, 1);
+ if (!alg_key) {
+- return -TARGET_ENOMEM;
+- }
+- if (copy_from_user(alg_key, optval_addr, optlen)) {
+- g_free(alg_key);
+ return -TARGET_EFAULT;
+ }
+ ret = get_errno(setsockopt(sockfd, level, optname,
+ alg_key, optlen));
+- g_free(alg_key);
++ unlock_user(alg_key, optval_addr, optlen);
+ break;
+ }
+ case ALG_SET_AEAD_AUTHSIZE:
+diff --git a/nbd/client.c b/nbd/client.c
+index 30d5383cb1..15503d0928 100644
+--- a/nbd/client.c
++++ b/nbd/client.c
+@@ -596,13 +596,31 @@ static int nbd_request_simple_option(QIOChannel *ioc, int opt, bool strict,
+ return 1;
+ }
+
++/* Callback to learn when QIO TLS upgrade is complete */
++struct NBDTLSClientHandshakeData {
++ bool complete;
++ Error *error;
++ GMainLoop *loop;
++};
++
++static void nbd_client_tls_handshake(QIOTask *task, void *opaque)
++{
++ struct NBDTLSClientHandshakeData *data = opaque;
++
++ qio_task_propagate_error(task, &data->error);
++ data->complete = true;
++ if (data->loop) {
++ g_main_loop_quit(data->loop);
++ }
++}
++
+ static QIOChannel *nbd_receive_starttls(QIOChannel *ioc,
+ QCryptoTLSCreds *tlscreds,
+ const char *hostname, Error **errp)
+ {
+ int ret;
+ QIOChannelTLS *tioc;
+- struct NBDTLSHandshakeData data = { 0 };
++ struct NBDTLSClientHandshakeData data = { 0 };
+
+ ret = nbd_request_simple_option(ioc, NBD_OPT_STARTTLS, true, errp);
+ if (ret <= 0) {
+@@ -619,18 +637,20 @@ static QIOChannel *nbd_receive_starttls(QIOChannel *ioc,
+ return NULL;
+ }
+ qio_channel_set_name(QIO_CHANNEL(tioc), "nbd-client-tls");
+- data.loop = g_main_loop_new(g_main_context_default(), FALSE);
+ trace_nbd_receive_starttls_tls_handshake();
+ qio_channel_tls_handshake(tioc,
+- nbd_tls_handshake,
++ nbd_client_tls_handshake,
+ &data,
+ NULL,
+ NULL);
+
+ if (!data.complete) {
++ data.loop = g_main_loop_new(g_main_context_default(), FALSE);
+ g_main_loop_run(data.loop);
++ assert(data.complete);
++ g_main_loop_unref(data.loop);
+ }
+- g_main_loop_unref(data.loop);
++
+ if (data.error) {
+ error_propagate(errp, data.error);
+ object_unref(OBJECT(tioc));
+diff --git a/nbd/common.c b/nbd/common.c
+index ddfe7d1183..c201b58a83 100644
+--- a/nbd/common.c
++++ b/nbd/common.c
+@@ -47,17 +47,6 @@ int nbd_drop(QIOChannel *ioc, size_t size, Error **errp)
+ }
+
+
+-void nbd_tls_handshake(QIOTask *task,
+- void *opaque)
+-{
+- struct NBDTLSHandshakeData *data = opaque;
+-
+- qio_task_propagate_error(task, &data->error);
+- data->complete = true;
+- g_main_loop_quit(data->loop);
+-}
+-
+-
+ const char *nbd_opt_lookup(uint32_t opt)
+ {
+ switch (opt) {
+diff --git a/nbd/nbd-internal.h b/nbd/nbd-internal.h
+index 1b2141ab4b..c18554cb87 100644
+--- a/nbd/nbd-internal.h
++++ b/nbd/nbd-internal.h
+@@ -71,16 +71,6 @@ static inline int nbd_write(QIOChannel *ioc, const void *buffer, size_t size,
+ return qio_channel_write_all(ioc, buffer, size, errp) < 0 ? -EIO : 0;
+ }
+
+-struct NBDTLSHandshakeData {
+- GMainLoop *loop;
+- bool complete;
+- Error *error;
+-};
+-
+-
+-void nbd_tls_handshake(QIOTask *task,
+- void *opaque);
+-
+ int nbd_drop(QIOChannel *ioc, size_t size, Error **errp);
+
+ #endif
+diff --git a/nbd/server.c b/nbd/server.c
+index ada16089f3..74edb2815b 100644
+--- a/nbd/server.c
++++ b/nbd/server.c
+@@ -189,8 +189,9 @@ static inline void set_be_option_rep(NBDOptionReply *rep, uint32_t option,
+
+ /* Send a reply header, including length, but no payload.
+ * Return -errno on error, 0 on success. */
+-static int nbd_negotiate_send_rep_len(NBDClient *client, uint32_t type,
+- uint32_t len, Error **errp)
++static coroutine_fn int
++nbd_negotiate_send_rep_len(NBDClient *client, uint32_t type,
++ uint32_t len, Error **errp)
+ {
+ NBDOptionReply rep;
+
+@@ -205,15 +206,15 @@ static int nbd_negotiate_send_rep_len(NBDClient *client, uint32_t type,
+
+ /* Send a reply header with default 0 length.
+ * Return -errno on error, 0 on success. */
+-static int nbd_negotiate_send_rep(NBDClient *client, uint32_t type,
+- Error **errp)
++static coroutine_fn int
++nbd_negotiate_send_rep(NBDClient *client, uint32_t type, Error **errp)
+ {
+ return nbd_negotiate_send_rep_len(client, type, 0, errp);
+ }
+
+ /* Send an error reply.
+ * Return -errno on error, 0 on success. */
+-static int G_GNUC_PRINTF(4, 0)
++static coroutine_fn int G_GNUC_PRINTF(4, 0)
+ nbd_negotiate_send_rep_verr(NBDClient *client, uint32_t type,
+ Error **errp, const char *fmt, va_list va)
+ {
+@@ -253,7 +254,7 @@ nbd_sanitize_name(const char *name)
+
+ /* Send an error reply.
+ * Return -errno on error, 0 on success. */
+-static int G_GNUC_PRINTF(4, 5)
++static coroutine_fn int G_GNUC_PRINTF(4, 5)
+ nbd_negotiate_send_rep_err(NBDClient *client, uint32_t type,
+ Error **errp, const char *fmt, ...)
+ {
+@@ -269,7 +270,7 @@ nbd_negotiate_send_rep_err(NBDClient *client, uint32_t type,
+ /* Drop remainder of the current option, and send a reply with the
+ * given error type and message. Return -errno on read or write
+ * failure; or 0 if connection is still live. */
+-static int G_GNUC_PRINTF(4, 0)
++static coroutine_fn int G_GNUC_PRINTF(4, 0)
+ nbd_opt_vdrop(NBDClient *client, uint32_t type, Error **errp,
+ const char *fmt, va_list va)
+ {
+@@ -282,7 +283,7 @@ nbd_opt_vdrop(NBDClient *client, uint32_t type, Error **errp,
+ return ret;
+ }
+
+-static int G_GNUC_PRINTF(4, 5)
++static coroutine_fn int G_GNUC_PRINTF(4, 5)
+ nbd_opt_drop(NBDClient *client, uint32_t type, Error **errp,
+ const char *fmt, ...)
+ {
+@@ -296,7 +297,7 @@ nbd_opt_drop(NBDClient *client, uint32_t type, Error **errp,
+ return ret;
+ }
+
+-static int G_GNUC_PRINTF(3, 4)
++static coroutine_fn int G_GNUC_PRINTF(3, 4)
+ nbd_opt_invalid(NBDClient *client, Error **errp, const char *fmt, ...)
+ {
+ int ret;
+@@ -313,8 +314,9 @@ nbd_opt_invalid(NBDClient *client, Error **errp, const char *fmt, ...)
+ * If @check_nul, require that no NUL bytes appear in buffer.
+ * Return -errno on I/O error, 0 if option was completely handled by
+ * sending a reply about inconsistent lengths, or 1 on success. */
+-static int nbd_opt_read(NBDClient *client, void *buffer, size_t size,
+- bool check_nul, Error **errp)
++static coroutine_fn int
++nbd_opt_read(NBDClient *client, void *buffer, size_t size,
++ bool check_nul, Error **errp)
+ {
+ if (size > client->optlen) {
+ return nbd_opt_invalid(client, errp,
+@@ -337,7 +339,8 @@ static int nbd_opt_read(NBDClient *client, void *buffer, size_t size,
+ /* Drop size bytes from the unparsed payload of the current option.
+ * Return -errno on I/O error, 0 if option was completely handled by
+ * sending a reply about inconsistent lengths, or 1 on success. */
+-static int nbd_opt_skip(NBDClient *client, size_t size, Error **errp)
++static coroutine_fn int
++nbd_opt_skip(NBDClient *client, size_t size, Error **errp)
+ {
+ if (size > client->optlen) {
+ return nbd_opt_invalid(client, errp,
+@@ -360,8 +363,9 @@ static int nbd_opt_skip(NBDClient *client, size_t size, Error **errp)
+ * Return -errno on I/O error, 0 if option was completely handled by
+ * sending a reply about inconsistent lengths, or 1 on success.
+ */
+-static int nbd_opt_read_name(NBDClient *client, char **name, uint32_t *length,
+- Error **errp)
++static coroutine_fn int
++nbd_opt_read_name(NBDClient *client, char **name, uint32_t *length,
++ Error **errp)
+ {
+ int ret;
+ uint32_t len;
+@@ -396,8 +400,8 @@ static int nbd_opt_read_name(NBDClient *client, char **name, uint32_t *length,
+
+ /* Send a single NBD_REP_SERVER reply to NBD_OPT_LIST, including payload.
+ * Return -errno on error, 0 on success. */
+-static int nbd_negotiate_send_rep_list(NBDClient *client, NBDExport *exp,
+- Error **errp)
++static coroutine_fn int
++nbd_negotiate_send_rep_list(NBDClient *client, NBDExport *exp, Error **errp)
+ {
+ ERRP_GUARD();
+ size_t name_len, desc_len;
+@@ -438,7 +442,8 @@ static int nbd_negotiate_send_rep_list(NBDClient *client, NBDExport *exp,
+
+ /* Process the NBD_OPT_LIST command, with a potential series of replies.
+ * Return -errno on error, 0 on success. */
+-static int nbd_negotiate_handle_list(NBDClient *client, Error **errp)
++static coroutine_fn int
++nbd_negotiate_handle_list(NBDClient *client, Error **errp)
+ {
+ NBDExport *exp;
+ assert(client->opt == NBD_OPT_LIST);
+@@ -453,7 +458,8 @@ static int nbd_negotiate_handle_list(NBDClient *client, Error **errp)
+ return nbd_negotiate_send_rep(client, NBD_REP_ACK, errp);
+ }
+
+-static void nbd_check_meta_export(NBDClient *client)
++static coroutine_fn void
++nbd_check_meta_export(NBDClient *client)
+ {
+ if (client->exp != client->export_meta.exp) {
+ client->export_meta.count = 0;
+@@ -462,8 +468,9 @@ static void nbd_check_meta_export(NBDClient *client)
+
+ /* Send a reply to NBD_OPT_EXPORT_NAME.
+ * Return -errno on error, 0 on success. */
+-static int nbd_negotiate_handle_export_name(NBDClient *client, bool no_zeroes,
+- Error **errp)
++static coroutine_fn int
++nbd_negotiate_handle_export_name(NBDClient *client, bool no_zeroes,
++ Error **errp)
+ {
+ ERRP_GUARD();
+ g_autofree char *name = NULL;
+@@ -523,9 +530,9 @@ static int nbd_negotiate_handle_export_name(NBDClient *client, bool no_zeroes,
+ /* Send a single NBD_REP_INFO, with a buffer @buf of @length bytes.
+ * The buffer does NOT include the info type prefix.
+ * Return -errno on error, 0 if ready to send more. */
+-static int nbd_negotiate_send_info(NBDClient *client,
+- uint16_t info, uint32_t length, void *buf,
+- Error **errp)
++static coroutine_fn int
++nbd_negotiate_send_info(NBDClient *client, uint16_t info, uint32_t length,
++ void *buf, Error **errp)
+ {
+ int rc;
+
+@@ -552,7 +559,8 @@ static int nbd_negotiate_send_info(NBDClient *client,
+ * -errno transmission error occurred or @fatal was requested, errp is set
+ * 0 error message successfully sent to client, errp is not set
+ */
+-static int nbd_reject_length(NBDClient *client, bool fatal, Error **errp)
++static coroutine_fn int
++nbd_reject_length(NBDClient *client, bool fatal, Error **errp)
+ {
+ int ret;
+
+@@ -570,7 +578,8 @@ static int nbd_reject_length(NBDClient *client, bool fatal, Error **errp)
+ /* Handle NBD_OPT_INFO and NBD_OPT_GO.
+ * Return -errno on error, 0 if ready for next option, and 1 to move
+ * into transmission phase. */
+-static int nbd_negotiate_handle_info(NBDClient *client, Error **errp)
++static coroutine_fn int
++nbd_negotiate_handle_info(NBDClient *client, Error **errp)
+ {
+ int rc;
+ g_autofree char *name = NULL;
+@@ -729,15 +738,33 @@ static int nbd_negotiate_handle_info(NBDClient *client, Error **errp)
+ return rc;
+ }
+
++/* Callback to learn when QIO TLS upgrade is complete */
++struct NBDTLSServerHandshakeData {
++ bool complete;
++ Error *error;
++ Coroutine *co;
++};
++
++static void
++nbd_server_tls_handshake(QIOTask *task, void *opaque)
++{
++ struct NBDTLSServerHandshakeData *data = opaque;
++
++ qio_task_propagate_error(task, &data->error);
++ data->complete = true;
++ if (!qemu_coroutine_entered(data->co)) {
++ aio_co_wake(data->co);
++ }
++}
+
+ /* Handle NBD_OPT_STARTTLS. Return NULL to drop connection, or else the
+ * new channel for all further (now-encrypted) communication. */
+-static QIOChannel *nbd_negotiate_handle_starttls(NBDClient *client,
+- Error **errp)
++static coroutine_fn QIOChannel *
++nbd_negotiate_handle_starttls(NBDClient *client, Error **errp)
+ {
+ QIOChannel *ioc;
+ QIOChannelTLS *tioc;
+- struct NBDTLSHandshakeData data = { 0 };
++ struct NBDTLSServerHandshakeData data = { 0 };
+
+ assert(client->opt == NBD_OPT_STARTTLS);
+
+@@ -758,17 +785,18 @@ static QIOChannel *nbd_negotiate_handle_starttls(NBDClient *client,
+
+ qio_channel_set_name(QIO_CHANNEL(tioc), "nbd-server-tls");
+ trace_nbd_negotiate_handle_starttls_handshake();
+- data.loop = g_main_loop_new(g_main_context_default(), FALSE);
++ data.co = qemu_coroutine_self();
+ qio_channel_tls_handshake(tioc,
+- nbd_tls_handshake,
++ nbd_server_tls_handshake,
+ &data,
+ NULL,
+ NULL);
+
+ if (!data.complete) {
+- g_main_loop_run(data.loop);
++ qemu_coroutine_yield();
++ assert(data.complete);
+ }
+- g_main_loop_unref(data.loop);
++
+ if (data.error) {
+ object_unref(OBJECT(tioc));
+ error_propagate(errp, data.error);
+@@ -784,10 +812,9 @@ static QIOChannel *nbd_negotiate_handle_starttls(NBDClient *client,
+ *
+ * For NBD_OPT_LIST_META_CONTEXT @context_id is ignored, 0 is used instead.
+ */
+-static int nbd_negotiate_send_meta_context(NBDClient *client,
+- const char *context,
+- uint32_t context_id,
+- Error **errp)
++static coroutine_fn int
++nbd_negotiate_send_meta_context(NBDClient *client, const char *context,
++ uint32_t context_id, Error **errp)
+ {
+ NBDOptionReplyMetaContext opt;
+ struct iovec iov[] = {
+@@ -812,8 +839,9 @@ static int nbd_negotiate_send_meta_context(NBDClient *client,
+ * Return true if @query matches @pattern, or if @query is empty when
+ * the @client is performing _LIST_.
+ */
+-static bool nbd_meta_empty_or_pattern(NBDClient *client, const char *pattern,
+- const char *query)
++static coroutine_fn bool
++nbd_meta_empty_or_pattern(NBDClient *client, const char *pattern,
++ const char *query)
+ {
+ if (!*query) {
+ trace_nbd_negotiate_meta_query_parse("empty");
+@@ -830,7 +858,8 @@ static bool nbd_meta_empty_or_pattern(NBDClient *client, const char *pattern,
+ /*
+ * Return true and adjust @str in place if it begins with @prefix.
+ */
+-static bool nbd_strshift(const char **str, const char *prefix)
++static coroutine_fn bool
++nbd_strshift(const char **str, const char *prefix)
+ {
+ size_t len = strlen(prefix);
+
+@@ -846,8 +875,9 @@ static bool nbd_strshift(const char **str, const char *prefix)
+ * Handle queries to 'base' namespace. For now, only the base:allocation
+ * context is available. Return true if @query has been handled.
+ */
+-static bool nbd_meta_base_query(NBDClient *client, NBDExportMetaContexts *meta,
+- const char *query)
++static coroutine_fn bool
++nbd_meta_base_query(NBDClient *client, NBDExportMetaContexts *meta,
++ const char *query)
+ {
+ if (!nbd_strshift(&query, "base:")) {
+ return false;
+@@ -866,8 +896,9 @@ static bool nbd_meta_base_query(NBDClient *client, NBDExportMetaContexts *meta,
+ * and qemu:allocation-depth contexts are available. Return true if @query
+ * has been handled.
+ */
+-static bool nbd_meta_qemu_query(NBDClient *client, NBDExportMetaContexts *meta,
+- const char *query)
++static coroutine_fn bool
++nbd_meta_qemu_query(NBDClient *client, NBDExportMetaContexts *meta,
++ const char *query)
+ {
+ size_t i;
+
+@@ -931,8 +962,9 @@ static bool nbd_meta_qemu_query(NBDClient *client, NBDExportMetaContexts *meta,
+ *
+ * Return -errno on I/O error, 0 if option was completely handled by
+ * sending a reply about inconsistent lengths, or 1 on success. */
+-static int nbd_negotiate_meta_query(NBDClient *client,
+- NBDExportMetaContexts *meta, Error **errp)
++static coroutine_fn int
++nbd_negotiate_meta_query(NBDClient *client,
++ NBDExportMetaContexts *meta, Error **errp)
+ {
+ int ret;
+ g_autofree char *query = NULL;
+@@ -971,8 +1003,9 @@ static int nbd_negotiate_meta_query(NBDClient *client,
+ * Handle NBD_OPT_LIST_META_CONTEXT and NBD_OPT_SET_META_CONTEXT
+ *
+ * Return -errno on I/O error, or 0 if option was completely handled. */
+-static int nbd_negotiate_meta_queries(NBDClient *client,
+- NBDExportMetaContexts *meta, Error **errp)
++static coroutine_fn int
++nbd_negotiate_meta_queries(NBDClient *client,
++ NBDExportMetaContexts *meta, Error **errp)
+ {
+ int ret;
+ g_autofree char *export_name = NULL;
+@@ -1096,7 +1129,8 @@ static int nbd_negotiate_meta_queries(NBDClient *client,
+ * 1 if client sent NBD_OPT_ABORT, i.e. on valid disconnect,
+ * errp is not set
+ */
+-static int nbd_negotiate_options(NBDClient *client, Error **errp)
++static coroutine_fn int
++nbd_negotiate_options(NBDClient *client, Error **errp)
+ {
+ uint32_t flags;
+ bool fixedNewstyle = false;
+diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
+index 3d74f134f5..037e9d9feb 100644
+--- a/target/arm/cpu64.c
++++ b/target/arm/cpu64.c
+@@ -190,7 +190,11 @@ void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp)
+ * No explicit bits enabled, and no implicit bits from sve-max-vq.
+ */
+ if (!cpu_isar_feature(aa64_sve, cpu)) {
+- /* SVE is disabled and so are all vector lengths. Good. */
++ /*
++ * SVE is disabled and so are all vector lengths. Good.
++ * Disable all SVE extensions as well.
++ */
++ cpu->isar.id_aa64zfr0 = 0;
+ return;
+ }
+
+diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c
+index 060aa0ccf4..047cb8fc50 100644
+--- a/target/arm/hvf/hvf.c
++++ b/target/arm/hvf/hvf.c
+@@ -187,85 +187,85 @@ struct hvf_sreg_match {
+ };
+
+ static struct hvf_sreg_match hvf_sreg_match[] = {
+- { HV_SYS_REG_DBGBVR0_EL1, HVF_SYSREG(0, 0, 14, 0, 4) },
+- { HV_SYS_REG_DBGBCR0_EL1, HVF_SYSREG(0, 0, 14, 0, 5) },
+- { HV_SYS_REG_DBGWVR0_EL1, HVF_SYSREG(0, 0, 14, 0, 6) },
+- { HV_SYS_REG_DBGWCR0_EL1, HVF_SYSREG(0, 0, 14, 0, 7) },
+-
+- { HV_SYS_REG_DBGBVR1_EL1, HVF_SYSREG(0, 1, 14, 0, 4) },
+- { HV_SYS_REG_DBGBCR1_EL1, HVF_SYSREG(0, 1, 14, 0, 5) },
+- { HV_SYS_REG_DBGWVR1_EL1, HVF_SYSREG(0, 1, 14, 0, 6) },
+- { HV_SYS_REG_DBGWCR1_EL1, HVF_SYSREG(0, 1, 14, 0, 7) },
+-
+- { HV_SYS_REG_DBGBVR2_EL1, HVF_SYSREG(0, 2, 14, 0, 4) },
+- { HV_SYS_REG_DBGBCR2_EL1, HVF_SYSREG(0, 2, 14, 0, 5) },
+- { HV_SYS_REG_DBGWVR2_EL1, HVF_SYSREG(0, 2, 14, 0, 6) },
+- { HV_SYS_REG_DBGWCR2_EL1, HVF_SYSREG(0, 2, 14, 0, 7) },
+-
+- { HV_SYS_REG_DBGBVR3_EL1, HVF_SYSREG(0, 3, 14, 0, 4) },
+- { HV_SYS_REG_DBGBCR3_EL1, HVF_SYSREG(0, 3, 14, 0, 5) },
+- { HV_SYS_REG_DBGWVR3_EL1, HVF_SYSREG(0, 3, 14, 0, 6) },
+- { HV_SYS_REG_DBGWCR3_EL1, HVF_SYSREG(0, 3, 14, 0, 7) },
+-
+- { HV_SYS_REG_DBGBVR4_EL1, HVF_SYSREG(0, 4, 14, 0, 4) },
+- { HV_SYS_REG_DBGBCR4_EL1, HVF_SYSREG(0, 4, 14, 0, 5) },
+- { HV_SYS_REG_DBGWVR4_EL1, HVF_SYSREG(0, 4, 14, 0, 6) },
+- { HV_SYS_REG_DBGWCR4_EL1, HVF_SYSREG(0, 4, 14, 0, 7) },
+-
+- { HV_SYS_REG_DBGBVR5_EL1, HVF_SYSREG(0, 5, 14, 0, 4) },
+- { HV_SYS_REG_DBGBCR5_EL1, HVF_SYSREG(0, 5, 14, 0, 5) },
+- { HV_SYS_REG_DBGWVR5_EL1, HVF_SYSREG(0, 5, 14, 0, 6) },
+- { HV_SYS_REG_DBGWCR5_EL1, HVF_SYSREG(0, 5, 14, 0, 7) },
+-
+- { HV_SYS_REG_DBGBVR6_EL1, HVF_SYSREG(0, 6, 14, 0, 4) },
+- { HV_SYS_REG_DBGBCR6_EL1, HVF_SYSREG(0, 6, 14, 0, 5) },
+- { HV_SYS_REG_DBGWVR6_EL1, HVF_SYSREG(0, 6, 14, 0, 6) },
+- { HV_SYS_REG_DBGWCR6_EL1, HVF_SYSREG(0, 6, 14, 0, 7) },
+-
+- { HV_SYS_REG_DBGBVR7_EL1, HVF_SYSREG(0, 7, 14, 0, 4) },
+- { HV_SYS_REG_DBGBCR7_EL1, HVF_SYSREG(0, 7, 14, 0, 5) },
+- { HV_SYS_REG_DBGWVR7_EL1, HVF_SYSREG(0, 7, 14, 0, 6) },
+- { HV_SYS_REG_DBGWCR7_EL1, HVF_SYSREG(0, 7, 14, 0, 7) },
+-
+- { HV_SYS_REG_DBGBVR8_EL1, HVF_SYSREG(0, 8, 14, 0, 4) },
+- { HV_SYS_REG_DBGBCR8_EL1, HVF_SYSREG(0, 8, 14, 0, 5) },
+- { HV_SYS_REG_DBGWVR8_EL1, HVF_SYSREG(0, 8, 14, 0, 6) },
+- { HV_SYS_REG_DBGWCR8_EL1, HVF_SYSREG(0, 8, 14, 0, 7) },
+-
+- { HV_SYS_REG_DBGBVR9_EL1, HVF_SYSREG(0, 9, 14, 0, 4) },
+- { HV_SYS_REG_DBGBCR9_EL1, HVF_SYSREG(0, 9, 14, 0, 5) },
+- { HV_SYS_REG_DBGWVR9_EL1, HVF_SYSREG(0, 9, 14, 0, 6) },
+- { HV_SYS_REG_DBGWCR9_EL1, HVF_SYSREG(0, 9, 14, 0, 7) },
+-
+- { HV_SYS_REG_DBGBVR10_EL1, HVF_SYSREG(0, 10, 14, 0, 4) },
+- { HV_SYS_REG_DBGBCR10_EL1, HVF_SYSREG(0, 10, 14, 0, 5) },
+- { HV_SYS_REG_DBGWVR10_EL1, HVF_SYSREG(0, 10, 14, 0, 6) },
+- { HV_SYS_REG_DBGWCR10_EL1, HVF_SYSREG(0, 10, 14, 0, 7) },
+-
+- { HV_SYS_REG_DBGBVR11_EL1, HVF_SYSREG(0, 11, 14, 0, 4) },
+- { HV_SYS_REG_DBGBCR11_EL1, HVF_SYSREG(0, 11, 14, 0, 5) },
+- { HV_SYS_REG_DBGWVR11_EL1, HVF_SYSREG(0, 11, 14, 0, 6) },
+- { HV_SYS_REG_DBGWCR11_EL1, HVF_SYSREG(0, 11, 14, 0, 7) },
+-
+- { HV_SYS_REG_DBGBVR12_EL1, HVF_SYSREG(0, 12, 14, 0, 4) },
+- { HV_SYS_REG_DBGBCR12_EL1, HVF_SYSREG(0, 12, 14, 0, 5) },
+- { HV_SYS_REG_DBGWVR12_EL1, HVF_SYSREG(0, 12, 14, 0, 6) },
+- { HV_SYS_REG_DBGWCR12_EL1, HVF_SYSREG(0, 12, 14, 0, 7) },
+-
+- { HV_SYS_REG_DBGBVR13_EL1, HVF_SYSREG(0, 13, 14, 0, 4) },
+- { HV_SYS_REG_DBGBCR13_EL1, HVF_SYSREG(0, 13, 14, 0, 5) },
+- { HV_SYS_REG_DBGWVR13_EL1, HVF_SYSREG(0, 13, 14, 0, 6) },
+- { HV_SYS_REG_DBGWCR13_EL1, HVF_SYSREG(0, 13, 14, 0, 7) },
+-
+- { HV_SYS_REG_DBGBVR14_EL1, HVF_SYSREG(0, 14, 14, 0, 4) },
+- { HV_SYS_REG_DBGBCR14_EL1, HVF_SYSREG(0, 14, 14, 0, 5) },
+- { HV_SYS_REG_DBGWVR14_EL1, HVF_SYSREG(0, 14, 14, 0, 6) },
+- { HV_SYS_REG_DBGWCR14_EL1, HVF_SYSREG(0, 14, 14, 0, 7) },
+-
+- { HV_SYS_REG_DBGBVR15_EL1, HVF_SYSREG(0, 15, 14, 0, 4) },
+- { HV_SYS_REG_DBGBCR15_EL1, HVF_SYSREG(0, 15, 14, 0, 5) },
+- { HV_SYS_REG_DBGWVR15_EL1, HVF_SYSREG(0, 15, 14, 0, 6) },
+- { HV_SYS_REG_DBGWCR15_EL1, HVF_SYSREG(0, 15, 14, 0, 7) },
++ { HV_SYS_REG_DBGBVR0_EL1, HVF_SYSREG(0, 0, 2, 0, 4) },
++ { HV_SYS_REG_DBGBCR0_EL1, HVF_SYSREG(0, 0, 2, 0, 5) },
++ { HV_SYS_REG_DBGWVR0_EL1, HVF_SYSREG(0, 0, 2, 0, 6) },
++ { HV_SYS_REG_DBGWCR0_EL1, HVF_SYSREG(0, 0, 2, 0, 7) },
++
++ { HV_SYS_REG_DBGBVR1_EL1, HVF_SYSREG(0, 1, 2, 0, 4) },
++ { HV_SYS_REG_DBGBCR1_EL1, HVF_SYSREG(0, 1, 2, 0, 5) },
++ { HV_SYS_REG_DBGWVR1_EL1, HVF_SYSREG(0, 1, 2, 0, 6) },
++ { HV_SYS_REG_DBGWCR1_EL1, HVF_SYSREG(0, 1, 2, 0, 7) },
++
++ { HV_SYS_REG_DBGBVR2_EL1, HVF_SYSREG(0, 2, 2, 0, 4) },
++ { HV_SYS_REG_DBGBCR2_EL1, HVF_SYSREG(0, 2, 2, 0, 5) },
++ { HV_SYS_REG_DBGWVR2_EL1, HVF_SYSREG(0, 2, 2, 0, 6) },
++ { HV_SYS_REG_DBGWCR2_EL1, HVF_SYSREG(0, 2, 2, 0, 7) },
++
++ { HV_SYS_REG_DBGBVR3_EL1, HVF_SYSREG(0, 3, 2, 0, 4) },
++ { HV_SYS_REG_DBGBCR3_EL1, HVF_SYSREG(0, 3, 2, 0, 5) },
++ { HV_SYS_REG_DBGWVR3_EL1, HVF_SYSREG(0, 3, 2, 0, 6) },
++ { HV_SYS_REG_DBGWCR3_EL1, HVF_SYSREG(0, 3, 2, 0, 7) },
++
++ { HV_SYS_REG_DBGBVR4_EL1, HVF_SYSREG(0, 4, 2, 0, 4) },
++ { HV_SYS_REG_DBGBCR4_EL1, HVF_SYSREG(0, 4, 2, 0, 5) },
++ { HV_SYS_REG_DBGWVR4_EL1, HVF_SYSREG(0, 4, 2, 0, 6) },
++ { HV_SYS_REG_DBGWCR4_EL1, HVF_SYSREG(0, 4, 2, 0, 7) },
++
++ { HV_SYS_REG_DBGBVR5_EL1, HVF_SYSREG(0, 5, 2, 0, 4) },
++ { HV_SYS_REG_DBGBCR5_EL1, HVF_SYSREG(0, 5, 2, 0, 5) },
++ { HV_SYS_REG_DBGWVR5_EL1, HVF_SYSREG(0, 5, 2, 0, 6) },
++ { HV_SYS_REG_DBGWCR5_EL1, HVF_SYSREG(0, 5, 2, 0, 7) },
++
++ { HV_SYS_REG_DBGBVR6_EL1, HVF_SYSREG(0, 6, 2, 0, 4) },
++ { HV_SYS_REG_DBGBCR6_EL1, HVF_SYSREG(0, 6, 2, 0, 5) },
++ { HV_SYS_REG_DBGWVR6_EL1, HVF_SYSREG(0, 6, 2, 0, 6) },
++ { HV_SYS_REG_DBGWCR6_EL1, HVF_SYSREG(0, 6, 2, 0, 7) },
++
++ { HV_SYS_REG_DBGBVR7_EL1, HVF_SYSREG(0, 7, 2, 0, 4) },
++ { HV_SYS_REG_DBGBCR7_EL1, HVF_SYSREG(0, 7, 2, 0, 5) },
++ { HV_SYS_REG_DBGWVR7_EL1, HVF_SYSREG(0, 7, 2, 0, 6) },
++ { HV_SYS_REG_DBGWCR7_EL1, HVF_SYSREG(0, 7, 2, 0, 7) },
++
++ { HV_SYS_REG_DBGBVR8_EL1, HVF_SYSREG(0, 8, 2, 0, 4) },
++ { HV_SYS_REG_DBGBCR8_EL1, HVF_SYSREG(0, 8, 2, 0, 5) },
++ { HV_SYS_REG_DBGWVR8_EL1, HVF_SYSREG(0, 8, 2, 0, 6) },
++ { HV_SYS_REG_DBGWCR8_EL1, HVF_SYSREG(0, 8, 2, 0, 7) },
++
++ { HV_SYS_REG_DBGBVR9_EL1, HVF_SYSREG(0, 9, 2, 0, 4) },
++ { HV_SYS_REG_DBGBCR9_EL1, HVF_SYSREG(0, 9, 2, 0, 5) },
++ { HV_SYS_REG_DBGWVR9_EL1, HVF_SYSREG(0, 9, 2, 0, 6) },
++ { HV_SYS_REG_DBGWCR9_EL1, HVF_SYSREG(0, 9, 2, 0, 7) },
++
++ { HV_SYS_REG_DBGBVR10_EL1, HVF_SYSREG(0, 10, 2, 0, 4) },
++ { HV_SYS_REG_DBGBCR10_EL1, HVF_SYSREG(0, 10, 2, 0, 5) },
++ { HV_SYS_REG_DBGWVR10_EL1, HVF_SYSREG(0, 10, 2, 0, 6) },
++ { HV_SYS_REG_DBGWCR10_EL1, HVF_SYSREG(0, 10, 2, 0, 7) },
++
++ { HV_SYS_REG_DBGBVR11_EL1, HVF_SYSREG(0, 11, 2, 0, 4) },
++ { HV_SYS_REG_DBGBCR11_EL1, HVF_SYSREG(0, 11, 2, 0, 5) },
++ { HV_SYS_REG_DBGWVR11_EL1, HVF_SYSREG(0, 11, 2, 0, 6) },
++ { HV_SYS_REG_DBGWCR11_EL1, HVF_SYSREG(0, 11, 2, 0, 7) },
++
++ { HV_SYS_REG_DBGBVR12_EL1, HVF_SYSREG(0, 12, 2, 0, 4) },
++ { HV_SYS_REG_DBGBCR12_EL1, HVF_SYSREG(0, 12, 2, 0, 5) },
++ { HV_SYS_REG_DBGWVR12_EL1, HVF_SYSREG(0, 12, 2, 0, 6) },
++ { HV_SYS_REG_DBGWCR12_EL1, HVF_SYSREG(0, 12, 2, 0, 7) },
++
++ { HV_SYS_REG_DBGBVR13_EL1, HVF_SYSREG(0, 13, 2, 0, 4) },
++ { HV_SYS_REG_DBGBCR13_EL1, HVF_SYSREG(0, 13, 2, 0, 5) },
++ { HV_SYS_REG_DBGWVR13_EL1, HVF_SYSREG(0, 13, 2, 0, 6) },
++ { HV_SYS_REG_DBGWCR13_EL1, HVF_SYSREG(0, 13, 2, 0, 7) },
++
++ { HV_SYS_REG_DBGBVR14_EL1, HVF_SYSREG(0, 14, 2, 0, 4) },
++ { HV_SYS_REG_DBGBCR14_EL1, HVF_SYSREG(0, 14, 2, 0, 5) },
++ { HV_SYS_REG_DBGWVR14_EL1, HVF_SYSREG(0, 14, 2, 0, 6) },
++ { HV_SYS_REG_DBGWCR14_EL1, HVF_SYSREG(0, 14, 2, 0, 7) },
++
++ { HV_SYS_REG_DBGBVR15_EL1, HVF_SYSREG(0, 15, 2, 0, 4) },
++ { HV_SYS_REG_DBGBCR15_EL1, HVF_SYSREG(0, 15, 2, 0, 5) },
++ { HV_SYS_REG_DBGWVR15_EL1, HVF_SYSREG(0, 15, 2, 0, 6) },
++ { HV_SYS_REG_DBGWCR15_EL1, HVF_SYSREG(0, 15, 2, 0, 7) },
+
+ #ifdef SYNC_NO_RAW_REGS
+ /*
+@@ -277,7 +277,7 @@ static struct hvf_sreg_match hvf_sreg_match[] = {
+ { HV_SYS_REG_MPIDR_EL1, HVF_SYSREG(0, 0, 3, 0, 5) },
+ { HV_SYS_REG_ID_AA64PFR0_EL1, HVF_SYSREG(0, 4, 3, 0, 0) },
+ #endif
+- { HV_SYS_REG_ID_AA64PFR1_EL1, HVF_SYSREG(0, 4, 3, 0, 2) },
++ { HV_SYS_REG_ID_AA64PFR1_EL1, HVF_SYSREG(0, 4, 3, 0, 1) },
+ { HV_SYS_REG_ID_AA64DFR0_EL1, HVF_SYSREG(0, 5, 3, 0, 0) },
+ { HV_SYS_REG_ID_AA64DFR1_EL1, HVF_SYSREG(0, 5, 3, 0, 1) },
+ { HV_SYS_REG_ID_AA64ISAR0_EL1, HVF_SYSREG(0, 6, 3, 0, 0) },
+diff --git a/target/i386/kvm/hyperv.c b/target/i386/kvm/hyperv.c
+index e3ac978648..0a2e2a07e9 100644
+--- a/target/i386/kvm/hyperv.c
++++ b/target/i386/kvm/hyperv.c
+@@ -81,7 +81,7 @@ int kvm_hv_handle_exit(X86CPU *cpu, struct kvm_hyperv_exit *exit)
+ */
+ async_safe_run_on_cpu(CPU(cpu), async_synic_update, RUN_ON_CPU_NULL);
+
+- return 0;
++ return EXCP_INTERRUPT;
+ case KVM_EXIT_HYPERV_HCALL: {
+ uint16_t code = exit->u.hcall.input & 0xffff;
+ bool fast = exit->u.hcall.input & HV_HYPERCALL_FAST;
+diff --git a/target/i386/tcg/decode-new.c.inc b/target/i386/tcg/decode-new.c.inc
+index 528e2fdfbb..1dfc368456 100644
+--- a/target/i386/tcg/decode-new.c.inc
++++ b/target/i386/tcg/decode-new.c.inc
+@@ -1418,9 +1418,9 @@ static bool has_cpuid_feature(DisasContext *s, X86CPUIDFeature cpuid)
+ case X86_FEAT_PCLMULQDQ:
+ return (s->cpuid_ext_features & CPUID_EXT_PCLMULQDQ);
+ case X86_FEAT_SSE:
+- return (s->cpuid_ext_features & CPUID_SSE);
++ return (s->cpuid_features & CPUID_SSE);
+ case X86_FEAT_SSE2:
+- return (s->cpuid_ext_features & CPUID_SSE2);
++ return (s->cpuid_features & CPUID_SSE2);
+ case X86_FEAT_SSE3:
+ return (s->cpuid_ext_features & CPUID_EXT_SSE3);
+ case X86_FEAT_SSSE3:
+diff --git a/target/i386/tcg/fpu_helper.c b/target/i386/tcg/fpu_helper.c
+index 6f3741b635..68c7058628 100644
+--- a/target/i386/tcg/fpu_helper.c
++++ b/target/i386/tcg/fpu_helper.c
+@@ -3011,6 +3011,11 @@ void helper_xsetbv(CPUX86State *env, uint32_t ecx, uint64_t mask)
+ goto do_gpf;
+ }
+
++ /* SSE can be disabled, but only if AVX is disabled too. */
++ if ((mask & (XSTATE_SSE_MASK | XSTATE_YMM_MASK)) == XSTATE_YMM_MASK) {
++ goto do_gpf;
++ }
++
+ /* Disallow enabling unimplemented features. */
+ cpu_x86_cpuid(env, 0x0d, 0, &ena_lo, &dummy, &dummy, &ena_hi);
+ ena = ((uint64_t)ena_hi << 32) | ena_lo;
+diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
+index abacb91ddf..417bc26e8f 100644
+--- a/target/i386/tcg/translate.c
++++ b/target/i386/tcg/translate.c
+@@ -2814,13 +2814,17 @@ static void gen_bnd_jmp(DisasContext *s)
+ static void
+ do_gen_eob_worker(DisasContext *s, bool inhibit, bool recheck_tf, bool jr)
+ {
++ bool inhibit_reset;
++
+ gen_update_cc_op(s);
+
+ /* If several instructions disable interrupts, only the first does it. */
+- if (inhibit && !(s->flags & HF_INHIBIT_IRQ_MASK)) {
+- gen_set_hflag(s, HF_INHIBIT_IRQ_MASK);
+- } else {
++ inhibit_reset = false;
++ if (s->flags & HF_INHIBIT_IRQ_MASK) {
+ gen_reset_hflag(s, HF_INHIBIT_IRQ_MASK);
++ inhibit_reset = true;
++ } else if (inhibit) {
++ gen_set_hflag(s, HF_INHIBIT_IRQ_MASK);
+ }
+
+ if (s->base.tb->flags & HF_RF_MASK) {
+@@ -2829,9 +2833,11 @@ do_gen_eob_worker(DisasContext *s, bool inhibit, bool recheck_tf, bool jr)
+ if (recheck_tf) {
+ gen_helper_rechecking_single_step(cpu_env);
+ tcg_gen_exit_tb(NULL, 0);
+- } else if (s->flags & HF_TF_MASK) {
++ } else if ((s->flags & HF_TF_MASK) && !inhibit) {
+ gen_helper_single_step(cpu_env);
+- } else if (jr) {
++ } else if (jr &&
++ /* give irqs a chance to happen */
++ !inhibit_reset) {
+ tcg_gen_lookup_and_goto_ptr();
+ } else {
+ tcg_gen_exit_tb(NULL, 0);
+@@ -6053,7 +6059,8 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
+ gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
+ break;
+ case 0xee: /* rdpkru */
+- if (prefixes & PREFIX_LOCK) {
++ if (s->prefix & (PREFIX_LOCK | PREFIX_DATA
++ | PREFIX_REPZ | PREFIX_REPNZ)) {
+ goto illegal_op;
+ }
+ tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_ECX]);
+@@ -6061,7 +6068,8 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
+ tcg_gen_extr_i64_tl(cpu_regs[R_EAX], cpu_regs[R_EDX], s->tmp1_i64);
+ break;
+ case 0xef: /* wrpkru */
+- if (prefixes & PREFIX_LOCK) {
++ if (s->prefix & (PREFIX_LOCK | PREFIX_DATA
++ | PREFIX_REPZ | PREFIX_REPNZ)) {
+ goto illegal_op;
+ }
+ tcg_gen_concat_tl_i64(s->tmp1_i64, cpu_regs[R_EAX],
+@@ -6782,12 +6790,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
+ modrm = x86_ldub_code(env, s);
+ reg = ((modrm >> 3) & 7) | REX_R(s);
+
+- if (s->prefix & PREFIX_DATA) {
+- ot = MO_16;
+- } else {
+- ot = mo_64_32(dflag);
+- }
+-
++ ot = dflag;
+ gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
+ gen_extu(ot, s->T0);
+ tcg_gen_mov_tl(cpu_cc_src, s->T0);
+@@ -6953,7 +6956,7 @@ static void i386_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cpu)
+ dc->cpuid_7_0_ecx_features = env->features[FEAT_7_0_ECX];
+ dc->cpuid_xsave_features = env->features[FEAT_XSAVE];
+ dc->jmp_opt = !((cflags & CF_NO_GOTO_TB) ||
+- (flags & (HF_TF_MASK | HF_INHIBIT_IRQ_MASK)));
++ (flags & (HF_RF_MASK | HF_TF_MASK | HF_INHIBIT_IRQ_MASK)));
+ /*
+ * If jmp_opt, we want to handle each string instruction individually.
+ * For icount also disable repz optimization so that each iteration
+diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
+index 92dd50e15e..56e36d81b3 100644
+--- a/target/loongarch/cpu.c
++++ b/target/loongarch/cpu.c
+@@ -653,7 +653,7 @@ void loongarch_cpu_dump_state(CPUState *cs, FILE *f, int flags)
+ qemu_fprintf(f, "EENTRY=%016" PRIx64 "\n", env->CSR_EENTRY);
+ qemu_fprintf(f, "PRCFG1=%016" PRIx64 ", PRCFG2=%016" PRIx64 ","
+ " PRCFG3=%016" PRIx64 "\n",
+- env->CSR_PRCFG1, env->CSR_PRCFG3, env->CSR_PRCFG3);
++ env->CSR_PRCFG1, env->CSR_PRCFG2, env->CSR_PRCFG3);
+ qemu_fprintf(f, "TLBRENTRY=%016" PRIx64 "\n", env->CSR_TLBRENTRY);
+ qemu_fprintf(f, "TLBRBADV=%016" PRIx64 "\n", env->CSR_TLBRBADV);
+ qemu_fprintf(f, "TLBRERA=%016" PRIx64 "\n", env->CSR_TLBRERA);
+diff --git a/tests/avocado/boot_linux_console.py b/tests/avocado/boot_linux_console.py
+index ec07c64291..b54693869b 100644
+--- a/tests/avocado/boot_linux_console.py
++++ b/tests/avocado/boot_linux_console.py
+@@ -542,12 +542,12 @@ def test_arm_cubieboard_initrd(self):
+ :avocado: tags=accel:tcg
+ """
+ deb_url = ('https://apt.armbian.com/pool/main/l/'
+- 'linux-5.10.16-sunxi/linux-image-current-sunxi_21.02.2_armhf.deb')
+- deb_hash = '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0'
++ 'linux-6.6.16/linux-image-current-sunxi_24.2.1_armhf__6.6.16-Seb3e-D6b4a-P2359-Ce96bHfe66-HK01ba-V014b-B067e-R448a.deb')
++ deb_hash = 'f7c3c8c5432f765445dc6e7eab02f3bbe668256b'
+ deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
+ kernel_path = self.extract_from_deb(deb_path,
+- '/boot/vmlinuz-5.10.16-sunxi')
+- dtb_path = '/usr/lib/linux-image-current-sunxi/sun4i-a10-cubieboard.dtb'
++ '/boot/vmlinuz-6.6.16-current-sunxi')
++ dtb_path = '/usr/lib/linux-image-6.6.16-current-sunxi/sun4i-a10-cubieboard.dtb'
+ dtb_path = self.extract_from_deb(deb_path, dtb_path)
+ initrd_url = ('https://github.com/groeck/linux-build-test/raw/'
+ '2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/'
+@@ -583,12 +583,12 @@ def test_arm_cubieboard_sata(self):
+ :avocado: tags=accel:tcg
+ """
+ deb_url = ('https://apt.armbian.com/pool/main/l/'
+- 'linux-5.10.16-sunxi/linux-image-current-sunxi_21.02.2_armhf.deb')
+- deb_hash = '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0'
++ 'linux-6.6.16/linux-image-current-sunxi_24.2.1_armhf__6.6.16-Seb3e-D6b4a-P2359-Ce96bHfe66-HK01ba-V014b-B067e-R448a.deb')
++ deb_hash = 'f7c3c8c5432f765445dc6e7eab02f3bbe668256b'
+ deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
+ kernel_path = self.extract_from_deb(deb_path,
+- '/boot/vmlinuz-5.10.16-sunxi')
+- dtb_path = '/usr/lib/linux-image-current-sunxi/sun4i-a10-cubieboard.dtb'
++ '/boot/vmlinuz-6.6.16-current-sunxi')
++ dtb_path = '/usr/lib/linux-image-6.6.16-current-sunxi/sun4i-a10-cubieboard.dtb'
+ dtb_path = self.extract_from_deb(deb_path, dtb_path)
+ rootfs_url = ('https://github.com/groeck/linux-build-test/raw/'
+ '2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/'
+@@ -713,12 +713,12 @@ def test_arm_orangepi(self):
+ :avocado: tags=accel:tcg
+ """
+ deb_url = ('https://apt.armbian.com/pool/main/l/'
+- 'linux-5.10.16-sunxi/linux-image-current-sunxi_21.02.2_armhf.deb')
+- deb_hash = '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0'
++ 'linux-6.6.16/linux-image-current-sunxi_24.2.1_armhf__6.6.16-Seb3e-D6b4a-P2359-Ce96bHfe66-HK01ba-V014b-B067e-R448a.deb')
++ deb_hash = 'f7c3c8c5432f765445dc6e7eab02f3bbe668256b'
+ deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
+ kernel_path = self.extract_from_deb(deb_path,
+- '/boot/vmlinuz-5.10.16-sunxi')
+- dtb_path = '/usr/lib/linux-image-current-sunxi/sun8i-h3-orangepi-pc.dtb'
++ '/boot/vmlinuz-6.6.16-current-sunxi')
++ dtb_path = '/usr/lib/linux-image-6.6.16-current-sunxi/sun8i-h3-orangepi-pc.dtb'
+ dtb_path = self.extract_from_deb(deb_path, dtb_path)
+
+ self.vm.set_console()
+@@ -739,12 +739,12 @@ def test_arm_orangepi_initrd(self):
+ :avocado: tags=machine:orangepi-pc
+ """
+ deb_url = ('https://apt.armbian.com/pool/main/l/'
+- 'linux-5.10.16-sunxi/linux-image-current-sunxi_21.02.2_armhf.deb')
+- deb_hash = '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0'
++ 'linux-6.6.16/linux-image-current-sunxi_24.2.1_armhf__6.6.16-Seb3e-D6b4a-P2359-Ce96bHfe66-HK01ba-V014b-B067e-R448a.deb')
++ deb_hash = 'f7c3c8c5432f765445dc6e7eab02f3bbe668256b'
+ deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
+ kernel_path = self.extract_from_deb(deb_path,
+- '/boot/vmlinuz-5.10.16-sunxi')
+- dtb_path = '/usr/lib/linux-image-current-sunxi/sun8i-h3-orangepi-pc.dtb'
++ '/boot/vmlinuz-6.6.16-current-sunxi')
++ dtb_path = '/usr/lib/linux-image-6.6.16-current-sunxi/sun8i-h3-orangepi-pc.dtb'
+ dtb_path = self.extract_from_deb(deb_path, dtb_path)
+ initrd_url = ('https://github.com/groeck/linux-build-test/raw/'
+ '2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/'
+@@ -785,12 +785,12 @@ def test_arm_orangepi_sd(self):
+ self.require_netdev('user')
+
+ deb_url = ('https://apt.armbian.com/pool/main/l/'
+- 'linux-5.10.16-sunxi/linux-image-current-sunxi_21.02.2_armhf.deb')
+- deb_hash = '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0'
++ 'linux-6.6.16/linux-image-current-sunxi_24.2.1_armhf__6.6.16-Seb3e-D6b4a-P2359-Ce96bHfe66-HK01ba-V014b-B067e-R448a.deb')
++ deb_hash = 'f7c3c8c5432f765445dc6e7eab02f3bbe668256b'
+ deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
+ kernel_path = self.extract_from_deb(deb_path,
+- '/boot/vmlinuz-5.10.16-sunxi')
+- dtb_path = '/usr/lib/linux-image-current-sunxi/sun8i-h3-orangepi-pc.dtb'
++ '/boot/vmlinuz-6.6.16-current-sunxi')
++ dtb_path = '/usr/lib/linux-image-6.6.16-current-sunxi/sun8i-h3-orangepi-pc.dtb'
+ dtb_path = self.extract_from_deb(deb_path, dtb_path)
+ rootfs_url = ('http://storage.kernelci.org/images/rootfs/buildroot/'
+ 'buildroot-baseline/20221116.0/armel/rootfs.ext2.xz')
+diff --git a/tests/avocado/replay_kernel.py b/tests/avocado/replay_kernel.py
+index 00a26e4a0c..154de3ab5e 100644
+--- a/tests/avocado/replay_kernel.py
++++ b/tests/avocado/replay_kernel.py
+@@ -185,12 +185,12 @@ def test_arm_cubieboard_initrd(self):
+ :avocado: tags=machine:cubieboard
+ """
+ deb_url = ('https://apt.armbian.com/pool/main/l/'
+- 'linux-5.10.16-sunxi/linux-image-current-sunxi_21.02.2_armhf.deb')
+- deb_hash = '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0'
++ 'linux-6.6.16/linux-image-current-sunxi_24.2.1_armhf__6.6.16-Seb3e-D6b4a-P2359-Ce96bHfe66-HK01ba-V014b-B067e-R448a.deb')
++ deb_hash = 'f7c3c8c5432f765445dc6e7eab02f3bbe668256b'
+ deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
+ kernel_path = self.extract_from_deb(deb_path,
+- '/boot/vmlinuz-5.10.16-sunxi')
+- dtb_path = '/usr/lib/linux-image-current-sunxi/sun4i-a10-cubieboard.dtb'
++ '/boot/vmlinuz-6.6.16-current-sunxi')
++ dtb_path = '/usr/lib/linux-image-6.6.16-current-sunxi/sun4i-a10-cubieboard.dtb'
+ dtb_path = self.extract_from_deb(deb_path, dtb_path)
+ initrd_url = ('https://github.com/groeck/linux-build-test/raw/'
+ '2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/'
+diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c
+index 7ff9f1648c..b3d0354845 100644
+--- a/ui/gtk-egl.c
++++ b/ui/gtk-egl.c
+@@ -96,7 +96,7 @@ void gd_egl_draw(VirtualConsole *vc)
+ #ifdef CONFIG_GBM
+ if (dmabuf) {
+ egl_dmabuf_create_fence(dmabuf);
+- if (dmabuf->fence_fd > 0) {
++ if (dmabuf->fence_fd >= 0) {
+ qemu_set_fd_handler(dmabuf->fence_fd, gd_hw_gl_flushed, NULL, vc);
+ return;
+ }
+diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c
+index 1605818bd1..c65e2a0d0c 100644
+--- a/ui/gtk-gl-area.c
++++ b/ui/gtk-gl-area.c
+@@ -85,7 +85,7 @@ void gd_gl_area_draw(VirtualConsole *vc)
+ #ifdef CONFIG_GBM
+ if (dmabuf) {
+ egl_dmabuf_create_fence(dmabuf);
+- if (dmabuf->fence_fd > 0) {
++ if (dmabuf->fence_fd >= 0) {
+ qemu_set_fd_handler(dmabuf->fence_fd, gd_hw_gl_flushed, NULL, vc);
+ return;
+ }
+diff --git a/ui/gtk.c b/ui/gtk.c
+index 283c41a1a1..17a34d37d9 100644
+--- a/ui/gtk.c
++++ b/ui/gtk.c
+@@ -589,10 +589,12 @@ void gd_hw_gl_flushed(void *vcon)
+ VirtualConsole *vc = vcon;
+ QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf;
+
+- qemu_set_fd_handler(dmabuf->fence_fd, NULL, NULL, NULL);
+- close(dmabuf->fence_fd);
+- dmabuf->fence_fd = -1;
+- graphic_hw_gl_block(vc->gfx.dcl.con, false);
++ if (dmabuf->fence_fd >= 0) {
++ qemu_set_fd_handler(dmabuf->fence_fd, NULL, NULL, NULL);
++ close(dmabuf->fence_fd);
++ dmabuf->fence_fd = -1;
++ graphic_hw_gl_block(vc->gfx.dcl.con, false);
++ }
+ }
+
+ /** DisplayState Callbacks (opengl version) **/
+@@ -871,7 +873,7 @@ static gboolean gd_motion_event(GtkWidget *widget, GdkEventMotion *motion,
+ int x, y;
+ int mx, my;
+ int fbh, fbw;
+- int ww, wh, ws;
++ int ww, wh;
+
+ if (!vc->gfx.ds) {
+ return TRUE;
+@@ -879,11 +881,15 @@ static gboolean gd_motion_event(GtkWidget *widget, GdkEventMotion *motion,
+
+ fbw = surface_width(vc->gfx.ds) * vc->gfx.scale_x;
+ fbh = surface_height(vc->gfx.ds) * vc->gfx.scale_y;
+-
+ ww = gtk_widget_get_allocated_width(widget);
+ wh = gtk_widget_get_allocated_height(widget);
+- ws = gtk_widget_get_scale_factor(widget);
+
++ /*
++ * `widget` may not have the same size with the frame buffer.
++ * In such cases, some paddings are needed around the `vc`.
++ * To achieve that, `vc` will be displayed at (mx, my)
++ * so that it is displayed at the center of the widget.
++ */
+ mx = my = 0;
+ if (ww > fbw) {
+ mx = (ww - fbw) / 2;
+@@ -892,8 +898,12 @@ static gboolean gd_motion_event(GtkWidget *widget, GdkEventMotion *motion,
+ my = (wh - fbh) / 2;
+ }
+
+- x = (motion->x - mx) / vc->gfx.scale_x * ws;
+- y = (motion->y - my) / vc->gfx.scale_y * ws;
++ /*
++ * `motion` is reported in `widget` coordinates
++ * so translating it to the coordinates in `vc`.
++ */
++ x = (motion->x - mx) / vc->gfx.scale_x;
++ y = (motion->y - my) / vc->gfx.scale_y;
+
+ if (qemu_input_is_absolute()) {
+ if (x < 0 || y < 0 ||
+diff --git a/ui/sdl2.c b/ui/sdl2.c
+index d630459b78..fc7e8639c2 100644
+--- a/ui/sdl2.c
++++ b/ui/sdl2.c
+@@ -857,6 +857,7 @@ static void sdl2_display_init(DisplayState *ds, DisplayOptions *o)
+ SDL_SetHint(SDL_HINT_ALLOW_ALT_TAB_WHILE_GRABBED, "0");
+ #endif
+ SDL_SetHint(SDL_HINT_WINDOWS_NO_CLOSE_ON_ALT_F4, "1");
++ SDL_EnableScreenSaver();
+ memset(&info, 0, sizeof(info));
+ SDL_VERSION(&info.version);
+
diff --git a/debian/patches/v7.2.13.diff b/debian/patches/v7.2.13.diff
new file mode 100644
index 00000000..26761b80
--- /dev/null
+++ b/debian/patches/v7.2.13.diff
@@ -0,0 +1,3859 @@
+Subject: v7.2.13
+Date: Tue Jul 16 08:40:38 2024 +0300
+From: Michael Tokarev <mjt@tls.msk.ru>
+Forwarded: not-needed
+
+This is a difference between upstream qemu v7.2.12
+and upstream qemu v7.2.13.
+
+ .gitlab-ci.d/buildtest.yml | 34 ++++------
+ .gitlab-ci.d/container-core.yml | 4 +-
+ .gitlab-ci.d/container-cross.yml | 1 +
+ VERSION | 2 +-
+ block.c | 76 ++++++++++++++--------
+ block/qcow2.c | 17 ++++-
+ chardev/char-stdio.c | 4 ++
+ docs/devel/testing.rst | 6 ++
+ hw/display/vga.c | 7 ++
+ hw/net/virtio-net.c | 18 +++--
+ hw/virtio/virtio.c | 1 -
+ linux-user/syscall.c | 10 ++-
+ target/arm/vec_helper.c | 4 +-
+ target/i386/cpu.c | 6 +-
+ target/i386/tcg/translate.c | 2 +-
+ tcg/loongarch64/tcg-target.c.inc | 32 +++++----
+ .../dockerfiles/{centos8.docker => centos9.docker} | 11 ++--
+ tests/docker/dockerfiles/fedora-win32-cross.docker | 4 +-
+ tests/docker/dockerfiles/fedora-win64-cross.docker | 4 +-
+ tests/docker/dockerfiles/fedora.docker | 4 +-
+ tests/docker/dockerfiles/opensuse-leap.docker | 22 +++----
+ tests/docker/dockerfiles/ubuntu2004.docker | 2 +-
+ tests/lcitool/libvirt-ci | 2 +-
+ tests/lcitool/mappings.yml | 60 +++++++++++++++++
+ tests/lcitool/refresh | 8 +--
+ tests/lcitool/targets/centos-stream-8.yml | 3 +
+ tests/lcitool/targets/opensuse-leap-153.yml | 3 +
+ tests/qemu-iotests/061 | 6 +-
+ tests/qemu-iotests/061.out | 8 ++-
+ tests/qemu-iotests/244 | 19 +++++-
+ tests/qemu-iotests/270 | 14 +++-
+ tests/vm/centos | 4 +-
+ 32 files changed, 270 insertions(+), 128 deletions(-)
+
+diff --git a/.gitlab-ci.d/buildtest.yml b/.gitlab-ci.d/buildtest.yml
+index 7243b8079b..9b6da37582 100644
+--- a/.gitlab-ci.d/buildtest.yml
++++ b/.gitlab-ci.d/buildtest.yml
+@@ -162,9 +162,9 @@ crash-test-fedora:
+ build-system-centos:
+ extends: .native_build_job_template
+ needs:
+- job: amd64-centos8-container
++ job: amd64-centos9-container
+ variables:
+- IMAGE: centos8
++ IMAGE: centos9
+ CONFIGURE_ARGS: --disable-nettle --enable-gcrypt --enable-fdt=system
+ --enable-modules --enable-trace-backends=dtrace --enable-docs
+ --enable-vfio-user-server
+@@ -182,7 +182,7 @@ check-system-centos:
+ - job: build-system-centos
+ artifacts: true
+ variables:
+- IMAGE: centos8
++ IMAGE: centos9
+ MAKE_CHECK_ARGS: check
+
+ avocado-system-centos:
+@@ -191,7 +191,7 @@ avocado-system-centos:
+ - job: build-system-centos
+ artifacts: true
+ variables:
+- IMAGE: centos8
++ IMAGE: centos9
+ MAKE_CHECK_ARGS: check-avocado
+
+ build-system-opensuse:
+@@ -237,9 +237,9 @@ avocado-system-opensuse:
+ build-tcg-disabled:
+ extends: .native_build_job_template
+ needs:
+- job: amd64-centos8-container
++ job: amd64-centos9-container
+ variables:
+- IMAGE: centos8
++ IMAGE: centos9
+ script:
+ - mkdir build
+ - cd build
+@@ -469,7 +469,6 @@ tsan-build:
+ CONFIGURE_ARGS: --enable-tsan --cc=clang-10 --cxx=clang++-10
+ --enable-trace-backends=ust --enable-fdt=system --disable-slirp
+ TARGETS: x86_64-softmmu ppc64-softmmu riscv64-softmmu x86_64-linux-user
+- MAKE_CHECK_ARGS: bench V=1
+
+ # gprof/gcov are GCC features
+ build-gprof-gcov:
+@@ -560,29 +559,22 @@ build-coroutine-sigaltstack:
+ MAKE_CHECK_ARGS: check-unit
+
+ # Check our reduced build configurations
+-build-without-default-devices:
++build-without-defaults:
+ extends: .native_build_job_template
+ needs:
+- job: amd64-centos8-container
++ job: amd64-centos9-container
+ variables:
+- IMAGE: centos8
+- CONFIGURE_ARGS: --without-default-devices --disable-user
+-
+-build-without-default-features:
+- extends: .native_build_job_template
+- needs:
+- job: amd64-fedora-container
+- variables:
+- IMAGE: fedora
++ IMAGE: centos9
+ CONFIGURE_ARGS:
++ --without-default-devices
+ --without-default-features
+- --disable-capstone
++ --disable-fdt
+ --disable-pie
+ --disable-qom-cast-debug
+ --disable-strip
+- TARGETS: avr-softmmu i386-softmmu mips64-softmmu s390x-softmmu sh4-softmmu
++ TARGETS: avr-softmmu mips64-softmmu s390x-softmmu sh4-softmmu
+ sparc64-softmmu hexagon-linux-user i386-linux-user s390x-linux-user
+- MAKE_CHECK_ARGS: check-unit check-qtest SPEED=slow
++ MAKE_CHECK_ARGS: check-unit check-qtest-avr check-qtest-mips64
+
+ build-libvhost-user:
+ extends: .base_job_template
+diff --git a/.gitlab-ci.d/container-core.yml b/.gitlab-ci.d/container-core.yml
+index 08f8450fa1..5459447676 100644
+--- a/.gitlab-ci.d/container-core.yml
++++ b/.gitlab-ci.d/container-core.yml
+@@ -1,10 +1,10 @@
+ include:
+ - local: '/.gitlab-ci.d/container-template.yml'
+
+-amd64-centos8-container:
++amd64-centos9-container:
+ extends: .container_job_template
+ variables:
+- NAME: centos8
++ NAME: centos9
+
+ amd64-fedora-container:
+ extends: .container_job_template
+diff --git a/.gitlab-ci.d/container-cross.yml b/.gitlab-ci.d/container-cross.yml
+index 2d560e9764..24343192ac 100644
+--- a/.gitlab-ci.d/container-cross.yml
++++ b/.gitlab-ci.d/container-cross.yml
+@@ -115,6 +115,7 @@ riscv64-debian-cross-container:
+ allow_failure: true
+ variables:
+ NAME: debian-riscv64-cross
++ QEMU_JOB_OPTIONAL: 1
+
+ # we can however build TCG tests using a non-sid base
+ riscv64-debian-test-cross-container:
+diff --git a/VERSION b/VERSION
+index 4625f55e26..c0d5d580b2 100644
+--- a/VERSION
++++ b/VERSION
+@@ -1 +1 @@
+-7.2.12
++7.2.13
+diff --git a/block.c b/block.c
+index a18f052374..ea369a3fe5 100644
+--- a/block.c
++++ b/block.c
+@@ -85,6 +85,7 @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
+ BlockDriverState *parent,
+ const BdrvChildClass *child_class,
+ BdrvChildRole child_role,
++ bool parse_filename,
+ Error **errp);
+
+ static bool bdrv_recurse_has_child(BlockDriverState *bs,
+@@ -2051,7 +2052,8 @@ static void parse_json_protocol(QDict *options, const char **pfilename,
+ * block driver has been specified explicitly.
+ */
+ static int bdrv_fill_options(QDict **options, const char *filename,
+- int *flags, Error **errp)
++ int *flags, bool allow_parse_filename,
++ Error **errp)
+ {
+ const char *drvname;
+ bool protocol = *flags & BDRV_O_PROTOCOL;
+@@ -2093,7 +2095,7 @@ static int bdrv_fill_options(QDict **options, const char *filename,
+ if (protocol && filename) {
+ if (!qdict_haskey(*options, "filename")) {
+ qdict_put_str(*options, "filename", filename);
+- parse_filename = true;
++ parse_filename = allow_parse_filename;
+ } else {
+ error_setg(errp, "Can't specify 'file' and 'filename' options at "
+ "the same time");
+@@ -3516,7 +3518,8 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
+ }
+
+ backing_hd = bdrv_open_inherit(backing_filename, reference, options, 0, bs,
+- &child_of_bds, bdrv_backing_role(bs), errp);
++ &child_of_bds, bdrv_backing_role(bs), true,
++ errp);
+ if (!backing_hd) {
+ bs->open_flags |= BDRV_O_NO_BACKING;
+ error_prepend(errp, "Could not open backing file: ");
+@@ -3549,7 +3552,8 @@ free_exit:
+ static BlockDriverState *
+ bdrv_open_child_bs(const char *filename, QDict *options, const char *bdref_key,
+ BlockDriverState *parent, const BdrvChildClass *child_class,
+- BdrvChildRole child_role, bool allow_none, Error **errp)
++ BdrvChildRole child_role, bool allow_none,
++ bool parse_filename, Error **errp)
+ {
+ BlockDriverState *bs = NULL;
+ QDict *image_options;
+@@ -3580,7 +3584,8 @@ bdrv_open_child_bs(const char *filename, QDict *options, const char *bdref_key,
+ }
+
+ bs = bdrv_open_inherit(filename, reference, image_options, 0,
+- parent, child_class, child_role, errp);
++ parent, child_class, child_role, parse_filename,
++ errp);
+ if (!bs) {
+ goto done;
+ }
+@@ -3590,6 +3595,28 @@ done:
+ return bs;
+ }
+
++static BdrvChild *bdrv_open_child_common(const char *filename,
++ QDict *options, const char *bdref_key,
++ BlockDriverState *parent,
++ const BdrvChildClass *child_class,
++ BdrvChildRole child_role,
++ bool allow_none, bool parse_filename,
++ Error **errp)
++{
++ BlockDriverState *bs;
++
++ GLOBAL_STATE_CODE();
++
++ bs = bdrv_open_child_bs(filename, options, bdref_key, parent, child_class,
++ child_role, allow_none, parse_filename, errp);
++ if (bs == NULL) {
++ return NULL;
++ }
++
++ return bdrv_attach_child(parent, bs, bdref_key, child_class, child_role,
++ errp);
++}
++
+ /*
+ * Opens a disk image whose options are given as BlockdevRef in another block
+ * device's options.
+@@ -3611,18 +3638,9 @@ BdrvChild *bdrv_open_child(const char *filename,
+ BdrvChildRole child_role,
+ bool allow_none, Error **errp)
+ {
+- BlockDriverState *bs;
+-
+- GLOBAL_STATE_CODE();
+-
+- bs = bdrv_open_child_bs(filename, options, bdref_key, parent, child_class,
+- child_role, allow_none, errp);
+- if (bs == NULL) {
+- return NULL;
+- }
+-
+- return bdrv_attach_child(parent, bs, bdref_key, child_class, child_role,
+- errp);
++ return bdrv_open_child_common(filename, options, bdref_key, parent,
++ child_class, child_role, allow_none, false,
++ errp);
+ }
+
+ /*
+@@ -3639,8 +3657,8 @@ int bdrv_open_file_child(const char *filename,
+ role = parent->drv->is_filter ?
+ (BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY) : BDRV_CHILD_IMAGE;
+
+- if (!bdrv_open_child(filename, options, bdref_key, parent,
+- &child_of_bds, role, false, errp))
++ if (!bdrv_open_child_common(filename, options, bdref_key, parent,
++ &child_of_bds, role, false, true, errp))
+ {
+ return -EINVAL;
+ }
+@@ -3685,7 +3703,8 @@ BlockDriverState *bdrv_open_blockdev_ref(BlockdevRef *ref, Error **errp)
+
+ }
+
+- bs = bdrv_open_inherit(NULL, reference, qdict, 0, NULL, NULL, 0, errp);
++ bs = bdrv_open_inherit(NULL, reference, qdict, 0, NULL, NULL, 0, false,
++ errp);
+ obj = NULL;
+ qobject_unref(obj);
+ visit_free(v);
+@@ -3775,7 +3794,7 @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
+ BlockDriverState *parent,
+ const BdrvChildClass *child_class,
+ BdrvChildRole child_role,
+- Error **errp)
++ bool parse_filename, Error **errp)
+ {
+ int ret;
+ BlockBackend *file = NULL;
+@@ -3819,9 +3838,11 @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
+ }
+
+ /* json: syntax counts as explicit options, as if in the QDict */
+- parse_json_protocol(options, &filename, &local_err);
+- if (local_err) {
+- goto fail;
++ if (parse_filename) {
++ parse_json_protocol(options, &filename, &local_err);
++ if (local_err) {
++ goto fail;
++ }
+ }
+
+ bs->explicit_options = qdict_clone_shallow(options);
+@@ -3846,7 +3867,8 @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
+ parent->open_flags, parent->options);
+ }
+
+- ret = bdrv_fill_options(&options, filename, &flags, &local_err);
++ ret = bdrv_fill_options(&options, filename, &flags, parse_filename,
++ &local_err);
+ if (ret < 0) {
+ goto fail;
+ }
+@@ -3915,7 +3937,7 @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
+
+ file_bs = bdrv_open_child_bs(filename, options, "file", bs,
+ &child_of_bds, BDRV_CHILD_IMAGE,
+- true, &local_err);
++ true, true, &local_err);
+ if (local_err) {
+ goto fail;
+ }
+@@ -4062,7 +4084,7 @@ BlockDriverState *bdrv_open(const char *filename, const char *reference,
+ GLOBAL_STATE_CODE();
+
+ return bdrv_open_inherit(filename, reference, options, flags, NULL,
+- NULL, 0, errp);
++ NULL, 0, true, errp);
+ }
+
+ /* Return true if the NULL-terminated @list contains @str */
+diff --git a/block/qcow2.c b/block/qcow2.c
+index 4d6666d3ff..c810424feb 100644
+--- a/block/qcow2.c
++++ b/block/qcow2.c
+@@ -1614,7 +1614,22 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
+ goto fail;
+ }
+
+- if (open_data_file) {
++ if (open_data_file && (flags & BDRV_O_NO_IO)) {
++ /*
++ * Don't open the data file for 'qemu-img info' so that it can be used
++ * to verify that an untrusted qcow2 image doesn't refer to external
++ * files.
++ *
++ * Note: This still makes has_data_file() return true.
++ */
++ if (s->incompatible_features & QCOW2_INCOMPAT_DATA_FILE) {
++ s->data_file = NULL;
++ } else {
++ s->data_file = bs->file;
++ }
++ qdict_extract_subqdict(options, NULL, "data-file.");
++ qdict_del(options, "data-file");
++ } else if (open_data_file) {
+ /* Open external data file */
+ s->data_file = bdrv_open_child(NULL, options, "data-file", bs,
+ &child_of_bds, BDRV_CHILD_DATA,
+diff --git a/chardev/char-stdio.c b/chardev/char-stdio.c
+index 3c648678ab..b960ddd4e4 100644
+--- a/chardev/char-stdio.c
++++ b/chardev/char-stdio.c
+@@ -41,6 +41,7 @@
+ /* init terminal so that we can grab keys */
+ static struct termios oldtty;
+ static int old_fd0_flags;
++static int old_fd1_flags;
+ static bool stdio_in_use;
+ static bool stdio_allow_signal;
+ static bool stdio_echo_state;
+@@ -50,6 +51,8 @@ static void term_exit(void)
+ if (stdio_in_use) {
+ tcsetattr(0, TCSANOW, &oldtty);
+ fcntl(0, F_SETFL, old_fd0_flags);
++ fcntl(1, F_SETFL, old_fd1_flags);
++ stdio_in_use = false;
+ }
+ }
+
+@@ -102,6 +105,7 @@ static void qemu_chr_open_stdio(Chardev *chr,
+
+ stdio_in_use = true;
+ old_fd0_flags = fcntl(0, F_GETFL);
++ old_fd1_flags = fcntl(1, F_GETFL);
+ tcgetattr(0, &oldtty);
+ if (!g_unix_set_fd_nonblocking(0, true, NULL)) {
+ error_setg_errno(errp, errno, "Failed to set FD nonblocking");
+diff --git a/docs/devel/testing.rst b/docs/devel/testing.rst
+index 98c26ecf18..b4c99be195 100644
+--- a/docs/devel/testing.rst
++++ b/docs/devel/testing.rst
+@@ -473,6 +473,12 @@ thus some extra preparation steps will be required first
+ the ``libvirt-ci`` submodule to point to a commit that contains
+ the ``mappings.yml`` update.
+
++For enterprise distros that default to old, end-of-life versions of the
++Python runtime, QEMU uses a separate set of mappings that work with more
++recent versions. These can be found in ``tests/lcitool/mappings.yml``.
++Modifying this file should not be necessary unless the new pre-requisite
++is a Python library or tool.
++
+
+ Adding new OS distros
+ ^^^^^^^^^^^^^^^^^^^^^
+diff --git a/hw/display/vga.c b/hw/display/vga.c
+index 0cb26a791b..8e2d44bea3 100644
+--- a/hw/display/vga.c
++++ b/hw/display/vga.c
+@@ -1746,6 +1746,13 @@ static void vga_draw_blank(VGACommonState *s, int full_update)
+ if (s->last_scr_width <= 0 || s->last_scr_height <= 0)
+ return;
+
++ if (is_buffer_shared(surface)) {
++ /* unshare buffer, otherwise the blanking corrupts vga vram */
++ surface = qemu_create_displaysurface(s->last_scr_width,
++ s->last_scr_height);
++ dpy_gfx_replace_surface(s->con, surface);
++ }
++
+ w = s->last_scr_width * surface_bytes_per_pixel(surface);
+ d = surface_data(surface);
+ for(i = 0; i < s->last_scr_height; i++) {
+diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
+index b6177a6afe..beadea5bf8 100644
+--- a/hw/net/virtio-net.c
++++ b/hw/net/virtio-net.c
+@@ -2646,18 +2646,14 @@ static int32_t virtio_net_flush_tx(VirtIONetQueue *q)
+ out_sg = elem->out_sg;
+ if (out_num < 1) {
+ virtio_error(vdev, "virtio-net header not in first element");
+- virtqueue_detach_element(q->tx_vq, elem, 0);
+- g_free(elem);
+- return -EINVAL;
++ goto detach;
+ }
+
+ if (n->has_vnet_hdr) {
+ if (iov_to_buf(out_sg, out_num, 0, &vhdr, n->guest_hdr_len) <
+ n->guest_hdr_len) {
+ virtio_error(vdev, "virtio-net header incorrect");
+- virtqueue_detach_element(q->tx_vq, elem, 0);
+- g_free(elem);
+- return -EINVAL;
++ goto detach;
+ }
+ if (n->needs_vnet_hdr_swap) {
+ virtio_net_hdr_swap(vdev, (void *) &vhdr);
+@@ -2688,6 +2684,11 @@ static int32_t virtio_net_flush_tx(VirtIONetQueue *q)
+ n->guest_hdr_len, -1);
+ out_num = sg_num;
+ out_sg = sg;
++
++ if (out_num < 1) {
++ virtio_error(vdev, "virtio-net nothing to send");
++ goto detach;
++ }
+ }
+
+ ret = qemu_sendv_packet_async(qemu_get_subqueue(n->nic, queue_index),
+@@ -2708,6 +2709,11 @@ drop:
+ }
+ }
+ return num_packets;
++
++detach:
++ virtqueue_detach_element(q->tx_vq, elem, 0);
++ g_free(elem);
++ return -EINVAL;
+ }
+
+ static void virtio_net_tx_timer(void *opaque);
+diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
+index 4a35d7cb0c..1227e3d692 100644
+--- a/hw/virtio/virtio.c
++++ b/hw/virtio/virtio.c
+@@ -732,7 +732,6 @@ static void vring_packed_event_read(VirtIODevice *vdev,
+ /* Make sure flags is seen before off_wrap */
+ smp_rmb();
+ e->off_wrap = virtio_lduw_phys_cached(vdev, cache, off_off);
+- virtio_tswap16s(vdev, &e->flags);
+ }
+
+ static void vring_packed_off_wrap_write(VirtIODevice *vdev,
+diff --git a/linux-user/syscall.c b/linux-user/syscall.c
+index 74240f99ad..53c46ae951 100644
+--- a/linux-user/syscall.c
++++ b/linux-user/syscall.c
+@@ -7228,11 +7228,17 @@ static inline int tswapid(int id)
+ #else
+ #define __NR_sys_setresgid __NR_setresgid
+ #endif
++#ifdef __NR_setgroups32
++#define __NR_sys_setgroups __NR_setgroups32
++#else
++#define __NR_sys_setgroups __NR_setgroups
++#endif
+
+ _syscall1(int, sys_setuid, uid_t, uid)
+ _syscall1(int, sys_setgid, gid_t, gid)
+ _syscall3(int, sys_setresuid, uid_t, ruid, uid_t, euid, uid_t, suid)
+ _syscall3(int, sys_setresgid, gid_t, rgid, gid_t, egid, gid_t, sgid)
++_syscall2(int, sys_setgroups, int, size, gid_t *, grouplist)
+
+ void syscall_init(void)
+ {
+@@ -11453,7 +11459,7 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
+ unlock_user(target_grouplist, arg2,
+ gidsetsize * sizeof(target_id));
+ }
+- return get_errno(setgroups(gidsetsize, grouplist));
++ return get_errno(sys_setgroups(gidsetsize, grouplist));
+ }
+ case TARGET_NR_fchown:
+ return get_errno(fchown(arg1, low2highuid(arg2), low2highgid(arg3)));
+@@ -11789,7 +11795,7 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
+ }
+ unlock_user(target_grouplist, arg2, 0);
+ }
+- return get_errno(setgroups(gidsetsize, grouplist));
++ return get_errno(sys_setgroups(gidsetsize, grouplist));
+ }
+ #endif
+ #ifdef TARGET_NR_fchown32
+diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
+index f59d3b26ea..859366e264 100644
+--- a/target/arm/vec_helper.c
++++ b/target/arm/vec_helper.c
+@@ -842,7 +842,7 @@ void HELPER(gvec_fcmlah_idx)(void *vd, void *vn, void *vm, void *va,
+ intptr_t index = extract32(desc, SIMD_DATA_SHIFT + 2, 2);
+ uint32_t neg_real = flip ^ neg_imag;
+ intptr_t elements = opr_sz / sizeof(float16);
+- intptr_t eltspersegment = 16 / sizeof(float16);
++ intptr_t eltspersegment = MIN(16 / sizeof(float16), elements);
+ intptr_t i, j;
+
+ /* Shift boolean to the sign bit so we can xor to negate. */
+@@ -904,7 +904,7 @@ void HELPER(gvec_fcmlas_idx)(void *vd, void *vn, void *vm, void *va,
+ intptr_t index = extract32(desc, SIMD_DATA_SHIFT + 2, 2);
+ uint32_t neg_real = flip ^ neg_imag;
+ intptr_t elements = opr_sz / sizeof(float32);
+- intptr_t eltspersegment = 16 / sizeof(float32);
++ intptr_t eltspersegment = MIN(16 / sizeof(float32), elements);
+ intptr_t i, j;
+
+ /* Shift boolean to the sign bit so we can xor to negate. */
+diff --git a/target/i386/cpu.c b/target/i386/cpu.c
+index 52a3020032..9c3e64c54b 100644
+--- a/target/i386/cpu.c
++++ b/target/i386/cpu.c
+@@ -5297,10 +5297,8 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
+ int host_vcpus_per_cache = 1 + ((*eax & 0x3FFC000) >> 14);
+ int vcpus_per_socket = env->nr_dies * cs->nr_cores *
+ cs->nr_threads;
+- if (cs->nr_cores > 1) {
+- *eax &= ~0xFC000000;
+- *eax |= (pow2ceil(cs->nr_cores) - 1) << 26;
+- }
++ *eax &= ~0xFC000000;
++ *eax |= (pow2ceil(cs->nr_cores) - 1) << 26;
+ if (host_vcpus_per_cache > vcpus_per_socket) {
+ *eax &= ~0x3FFC000;
+ *eax |= (pow2ceil(vcpus_per_socket) - 1) << 14;
+diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
+index 417bc26e8f..8eb6a974e5 100644
+--- a/target/i386/tcg/translate.c
++++ b/target/i386/tcg/translate.c
+@@ -2696,7 +2696,7 @@ static void gen_enter(DisasContext *s, int esp_addend, int level)
+ }
+
+ /* Copy the FrameTemp value to EBP. */
+- gen_op_mov_reg_v(s, a_ot, R_EBP, s->T1);
++ gen_op_mov_reg_v(s, d_ot, R_EBP, s->T1);
+
+ /* Compute the final value of ESP. */
+ tcg_gen_subi_tl(s->T1, s->T1, esp_addend + size * level);
+diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
+index d326e28740..f1934b6d7b 100644
+--- a/tcg/loongarch64/tcg-target.c.inc
++++ b/tcg/loongarch64/tcg-target.c.inc
+@@ -332,8 +332,7 @@ static void tcg_out_movi(TCGContext *s, TCGType type, TCGReg rd,
+ * back to the slow path.
+ */
+
+- intptr_t pc_offset;
+- tcg_target_long val_lo, val_hi, pc_hi, offset_hi;
++ intptr_t src_rx, pc_offset;
+ tcg_target_long hi32, hi52;
+ bool rd_high_bits_are_ones;
+
+@@ -344,24 +343,23 @@ static void tcg_out_movi(TCGContext *s, TCGType type, TCGReg rd,
+ }
+
+ /* PC-relative cases. */
+- pc_offset = tcg_pcrel_diff(s, (void *)val);
+- if (pc_offset == sextreg(pc_offset, 0, 22) && (pc_offset & 3) == 0) {
+- /* Single pcaddu2i. */
+- tcg_out_opc_pcaddu2i(s, rd, pc_offset >> 2);
+- return;
++ src_rx = (intptr_t)tcg_splitwx_to_rx(s->code_ptr);
++ if ((val & 3) == 0) {
++ pc_offset = val - src_rx;
++ if (pc_offset == sextreg(pc_offset, 0, 22)) {
++ /* Single pcaddu2i. */
++ tcg_out_opc_pcaddu2i(s, rd, pc_offset >> 2);
++ return;
++ }
+ }
+
+- if (pc_offset == (int32_t)pc_offset) {
+- /* Offset within 32 bits; load with pcalau12i + ori. */
+- val_lo = sextreg(val, 0, 12);
+- val_hi = val >> 12;
+- pc_hi = (val - pc_offset) >> 12;
+- offset_hi = val_hi - pc_hi;
+-
+- tcg_debug_assert(offset_hi == sextreg(offset_hi, 0, 20));
+- tcg_out_opc_pcalau12i(s, rd, offset_hi);
++ pc_offset = (val >> 12) - (src_rx >> 12);
++ if (pc_offset == sextreg(pc_offset, 0, 20)) {
++ /* Load with pcalau12i + ori. */
++ tcg_target_long val_lo = val & 0xfff;
++ tcg_out_opc_pcalau12i(s, rd, pc_offset);
+ if (val_lo != 0) {
+- tcg_out_opc_ori(s, rd, rd, val_lo & 0xfff);
++ tcg_out_opc_ori(s, rd, rd, val_lo);
+ }
+ return;
+ }
+diff --git a/tests/docker/dockerfiles/centos8.docker b/tests/docker/dockerfiles/centos9.docker
+similarity index 91%
+rename from tests/docker/dockerfiles/centos8.docker
+rename to tests/docker/dockerfiles/centos9.docker
+index 1f70d41aeb..62c4896191 100644
+--- a/tests/docker/dockerfiles/centos8.docker
++++ b/tests/docker/dockerfiles/centos9.docker
+@@ -1,15 +1,14 @@
+ # THIS FILE WAS AUTO-GENERATED
+ #
+-# $ lcitool dockerfile --layers all centos-stream-8 qemu
++# $ lcitool dockerfile --layers all centos-stream-9 qemu
+ #
+ # https://gitlab.com/libvirt/libvirt-ci
+
+-FROM quay.io/centos/centos:stream8
++FROM quay.io/centos/centos:stream9
+
+ RUN dnf distro-sync -y && \
+ dnf install 'dnf-command(config-manager)' -y && \
+- dnf config-manager --set-enabled -y powertools && \
+- dnf install -y centos-release-advanced-virtualization && \
++ dnf config-manager --set-enabled -y crb && \
+ dnf install -y epel-release && \
+ dnf install -y epel-next-release && \
+ dnf install -y \
+@@ -43,7 +42,6 @@ RUN dnf distro-sync -y && \
+ glib2-static \
+ glibc-langpack-en \
+ glibc-static \
+- glusterfs-api-devel \
+ gnutls-devel \
+ gtk3-devel \
+ hostname \
+@@ -102,19 +100,18 @@ RUN dnf distro-sync -y && \
+ python3-pip \
+ python3-sphinx \
+ python3-sphinx_rtd_theme \
++ python3-tomli \
+ rdma-core-devel \
+ rpm \
+ sed \
+ snappy-devel \
+ spice-protocol \
+- spice-server-devel \
+ systemd-devel \
+ systemtap-sdt-devel \
+ tar \
+ texinfo \
+ usbredir-devel \
+ util-linux \
+- virglrenderer-devel \
+ vte291-devel \
+ which \
+ xfsprogs-devel \
+diff --git a/tests/docker/dockerfiles/fedora-win32-cross.docker b/tests/docker/dockerfiles/fedora-win32-cross.docker
+index 75383ba185..cc5d1ac4be 100644
+--- a/tests/docker/dockerfiles/fedora-win32-cross.docker
++++ b/tests/docker/dockerfiles/fedora-win32-cross.docker
+@@ -1,10 +1,10 @@
+ # THIS FILE WAS AUTO-GENERATED
+ #
+-# $ lcitool dockerfile --layers all --cross mingw32 fedora-35 qemu
++# $ lcitool dockerfile --layers all --cross mingw32 fedora-37 qemu
+ #
+ # https://gitlab.com/libvirt/libvirt-ci
+
+-FROM registry.fedoraproject.org/fedora:35
++FROM registry.fedoraproject.org/fedora:37
+
+ RUN dnf install -y nosync && \
+ echo -e '#!/bin/sh\n\
+diff --git a/tests/docker/dockerfiles/fedora-win64-cross.docker b/tests/docker/dockerfiles/fedora-win64-cross.docker
+index 98c03dc13b..cabbf4edfc 100644
+--- a/tests/docker/dockerfiles/fedora-win64-cross.docker
++++ b/tests/docker/dockerfiles/fedora-win64-cross.docker
+@@ -1,10 +1,10 @@
+ # THIS FILE WAS AUTO-GENERATED
+ #
+-# $ lcitool dockerfile --layers all --cross mingw64 fedora-35 qemu
++# $ lcitool dockerfile --layers all --cross mingw64 fedora-37 qemu
+ #
+ # https://gitlab.com/libvirt/libvirt-ci
+
+-FROM registry.fedoraproject.org/fedora:35
++FROM registry.fedoraproject.org/fedora:37
+
+ RUN dnf install -y nosync && \
+ echo -e '#!/bin/sh\n\
+diff --git a/tests/docker/dockerfiles/fedora.docker b/tests/docker/dockerfiles/fedora.docker
+index d200c7fc10..f44b005000 100644
+--- a/tests/docker/dockerfiles/fedora.docker
++++ b/tests/docker/dockerfiles/fedora.docker
+@@ -1,10 +1,10 @@
+ # THIS FILE WAS AUTO-GENERATED
+ #
+-# $ lcitool dockerfile --layers all fedora-35 qemu
++# $ lcitool dockerfile --layers all fedora-37 qemu
+ #
+ # https://gitlab.com/libvirt/libvirt-ci
+
+-FROM registry.fedoraproject.org/fedora:35
++FROM registry.fedoraproject.org/fedora:37
+
+ RUN dnf install -y nosync && \
+ echo -e '#!/bin/sh\n\
+diff --git a/tests/docker/dockerfiles/opensuse-leap.docker b/tests/docker/dockerfiles/opensuse-leap.docker
+index 4361b01464..4f1191dc05 100644
+--- a/tests/docker/dockerfiles/opensuse-leap.docker
++++ b/tests/docker/dockerfiles/opensuse-leap.docker
+@@ -90,16 +90,9 @@ RUN zypper update -y && \
+ pcre-devel-static \
+ perl-base \
+ pkgconfig \
+- python3-Pillow \
+- python3-PyYAML \
+- python3-Sphinx \
+- python3-base \
+- python3-numpy \
+- python3-opencv \
+- python3-pip \
+- python3-setuptools \
+- python3-sphinx_rtd_theme \
+- python3-wheel \
++ python39-base \
++ python39-pip \
++ python39-setuptools \
+ rdma-core-devel \
+ rpm \
+ sed \
+@@ -131,10 +124,15 @@ RUN zypper update -y && \
+ ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/g++ && \
+ ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/gcc
+
+-RUN /usr/bin/pip3 install meson==0.56.0
++RUN /usr/bin/pip3.9 install \
++ PyYAML \
++ meson==0.63.2 \
++ pillow \
++ sphinx \
++ sphinx-rtd-theme
+
+ ENV CCACHE_WRAPPERSDIR "/usr/libexec/ccache-wrappers"
+ ENV LANG "en_US.UTF-8"
+ ENV MAKE "/usr/bin/make"
+ ENV NINJA "/usr/bin/ninja"
+-ENV PYTHON "/usr/bin/python3"
++ENV PYTHON "/usr/bin/python3.9"
+diff --git a/tests/docker/dockerfiles/ubuntu2004.docker b/tests/docker/dockerfiles/ubuntu2004.docker
+index 9417bca2fa..39c744eba9 100644
+--- a/tests/docker/dockerfiles/ubuntu2004.docker
++++ b/tests/docker/dockerfiles/ubuntu2004.docker
+@@ -140,7 +140,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
+ ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/g++ && \
+ ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/gcc
+
+-RUN /usr/bin/pip3 install meson==0.56.0
++RUN /usr/bin/pip3 install meson==0.63.2
+
+ ENV CCACHE_WRAPPERSDIR "/usr/libexec/ccache-wrappers"
+ ENV LANG "en_US.UTF-8"
+Submodule tests/lcitool/libvirt-ci e3eb28cf2e..319a534c22:
+diff --git a/tests/lcitool/libvirt-ci/.gitlab-ci.yml b/tests/lcitool/libvirt-ci/.gitlab-ci.yml
+index 21ccc2e6..1c9c8b70 100644
+--- a/tests/lcitool/libvirt-ci/.gitlab-ci.yml
++++ b/tests/lcitool/libvirt-ci/.gitlab-ci.yml
+@@ -148,9 +148,10 @@ unittests:
+ needs: []
+ before_script:
+ - apk update
+- - apk add git
++ - apk add git ansible
+ script:
+- - pip3 install setuptools pytest pyyaml
++ - pip3 install setuptools pytest
++ - pip3 install -r requirements.txt ansible-runner
+ - python3 -m pytest --verbose
+
+ x86_64-check-almalinux-8:
+@@ -201,15 +202,15 @@ x86_64-check-debian-sid:
+ variables:
+ NAME: debian-sid
+
+-x86_64-check-fedora-35:
++x86_64-check-fedora-36:
+ extends: .check_container_template
+ variables:
+- NAME: fedora-35
++ NAME: fedora-36
+
+-x86_64-check-fedora-36:
++x86_64-check-fedora-37:
+ extends: .check_container_template
+ variables:
+- NAME: fedora-36
++ NAME: fedora-37
+
+ x86_64-check-fedora-rawhide:
+ extends: .check_container_template
+diff --git a/tests/lcitool/libvirt-ci/docs/installation.rst b/tests/lcitool/libvirt-ci/docs/installation.rst
+index 7a7f53e8..7134195d 100644
+--- a/tests/lcitool/libvirt-ci/docs/installation.rst
++++ b/tests/lcitool/libvirt-ci/docs/installation.rst
+@@ -58,6 +58,8 @@ in the previous section)
+
+ $ pip3 install --user -r test-requirements.txt
+
++In addition, the ``ansible-inventory`` executable needs to be installed.
++
+ Installing lcitool
+ ------------------
+
+diff --git a/tests/lcitool/libvirt-ci/examples/manifest.yml b/tests/lcitool/libvirt-ci/examples/manifest.yml
+index 7bd9b4b1..2acfbd35 100644
+--- a/tests/lcitool/libvirt-ci/examples/manifest.yml
++++ b/tests/lcitool/libvirt-ci/examples/manifest.yml
+@@ -135,7 +135,7 @@ targets:
+ - arch: ppc64le
+ - arch: s390x
+
+- fedora-35: x86_64
++ fedora-37: x86_64
+
+ fedora-rawhide:
+ jobs:
+diff --git a/tests/lcitool/libvirt-ci/lcitool/ansible/playbooks/build/jobs/defaults.yml b/tests/lcitool/libvirt-ci/lcitool/ansible/playbooks/build/jobs/defaults.yml
+index 25099c74..70691565 100644
+--- a/tests/lcitool/libvirt-ci/lcitool/ansible/playbooks/build/jobs/defaults.yml
++++ b/tests/lcitool/libvirt-ci/lcitool/ansible/playbooks/build/jobs/defaults.yml
+@@ -7,8 +7,8 @@ all_machines:
+ - debian-10
+ - debian-11
+ - debian-sid
+- - fedora-35
+ - fedora-36
++ - fedora-37
+ - fedora-rawhide
+ - freebsd-12
+ - freebsd-13
+@@ -22,8 +22,8 @@ rpm_machines:
+ - almalinux-9
+ - centos-stream-8
+ - centos-stream-9
+- - fedora-35
+ - fedora-36
++ - fedora-37
+ - fedora-rawhide
+ global_env: |
+ . ~/lcitool_build_env
+diff --git a/tests/lcitool/libvirt-ci/lcitool/ansible/playbooks/build/projects/libvirt-dbus.yml b/tests/lcitool/libvirt-ci/lcitool/ansible/playbooks/build/projects/libvirt-dbus.yml
+index 79f81abb..273be6a8 100644
+--- a/tests/lcitool/libvirt-ci/lcitool/ansible/playbooks/build/projects/libvirt-dbus.yml
++++ b/tests/lcitool/libvirt-ci/lcitool/ansible/playbooks/build/projects/libvirt-dbus.yml
+@@ -19,8 +19,8 @@
+ - debian-10
+ - debian-11
+ - debian-sid
+- - fedora-35
+ - fedora-36
++ - fedora-37
+ - fedora-rawhide
+ - opensuse-leap-153
+ - opensuse-tumbleweed
+diff --git a/tests/lcitool/libvirt-ci/lcitool/ansible/playbooks/build/projects/libvirt-sandbox.yml b/tests/lcitool/libvirt-ci/lcitool/ansible/playbooks/build/projects/libvirt-sandbox.yml
+index bcf62b91..231c65bf 100644
+--- a/tests/lcitool/libvirt-ci/lcitool/ansible/playbooks/build/projects/libvirt-sandbox.yml
++++ b/tests/lcitool/libvirt-ci/lcitool/ansible/playbooks/build/projects/libvirt-sandbox.yml
+@@ -6,8 +6,8 @@
+ - debian-10
+ - debian-11
+ - debian-sid
+- - fedora-35
+ - fedora-36
++ - fedora-37
+ - fedora-rawhide
+ - opensuse-leap-153
+ - opensuse-tumbleweed
+@@ -25,6 +25,6 @@
+ - import_tasks: 'jobs/autotools-rpm-job.yml'
+ vars:
+ machines:
+- - fedora-35
+ - fedora-36
++ - fedora-37
+ - fedora-rawhide
+diff --git a/tests/lcitool/libvirt-ci/lcitool/ansible/playbooks/build/projects/libvirt-tck.yml b/tests/lcitool/libvirt-ci/lcitool/ansible/playbooks/build/projects/libvirt-tck.yml
+index e4beddd7..6451b440 100644
+--- a/tests/lcitool/libvirt-ci/lcitool/ansible/playbooks/build/projects/libvirt-tck.yml
++++ b/tests/lcitool/libvirt-ci/lcitool/ansible/playbooks/build/projects/libvirt-tck.yml
+@@ -14,6 +14,6 @@
+ - import_tasks: 'jobs/perl-modulebuild-rpm-job.yml'
+ vars:
+ machines:
+- - fedora-35
+ - fedora-36
++ - fedora-37
+ - fedora-rawhide
+diff --git a/tests/lcitool/libvirt-ci/lcitool/ansible/playbooks/build/projects/libvirt.yml b/tests/lcitool/libvirt-ci/lcitool/ansible/playbooks/build/projects/libvirt.yml
+index 1b120441..7ec9d975 100644
+--- a/tests/lcitool/libvirt-ci/lcitool/ansible/playbooks/build/projects/libvirt.yml
++++ b/tests/lcitool/libvirt-ci/lcitool/ansible/playbooks/build/projects/libvirt.yml
+@@ -19,8 +19,8 @@
+ - debian-10
+ - debian-11
+ - debian-sid
+- - fedora-35
+ - fedora-36
++ - fedora-37
+ - fedora-rawhide
+ - opensuse-leap-153
+ - opensuse-tumbleweed
+diff --git a/tests/lcitool/libvirt-ci/lcitool/ansible/playbooks/build/projects/virt-viewer.yml b/tests/lcitool/libvirt-ci/lcitool/ansible/playbooks/build/projects/virt-viewer.yml
+index 209885a1..eda0c0e6 100644
+--- a/tests/lcitool/libvirt-ci/lcitool/ansible/playbooks/build/projects/virt-viewer.yml
++++ b/tests/lcitool/libvirt-ci/lcitool/ansible/playbooks/build/projects/virt-viewer.yml
+@@ -13,6 +13,6 @@
+ # The spec file for virt-viewer requires a very recent version
+ # of spice-gtk, so we have to skip this job on older distros
+ machines:
+- - fedora-35
+ - fedora-36
++ - fedora-37
+ - fedora-rawhide
+diff --git a/tests/lcitool/libvirt-ci/lcitool/application.py b/tests/lcitool/libvirt-ci/lcitool/application.py
+index 97cb0884..090c1b07 100644
+--- a/tests/lcitool/libvirt-ci/lcitool/application.py
++++ b/tests/lcitool/libvirt-ci/lcitool/application.py
+@@ -13,12 +13,13 @@ from pkg_resources import resource_filename
+ from lcitool import util, LcitoolError
+ from lcitool.config import Config
+ from lcitool.inventory import Inventory
+-from lcitool.package import package_names_by_type
++from lcitool.packages import Packages
+ from lcitool.projects import Projects
++from lcitool.targets import Targets, BuildTarget
+ from lcitool.formatters import DockerfileFormatter, ShellVariablesFormatter, JSONVariablesFormatter, ShellBuildEnvFormatter
+-from lcitool.singleton import Singleton
+ from lcitool.manifest import Manifest
+
++
+ log = logging.getLogger(__name__)
+
+
+@@ -44,7 +45,7 @@ class ApplicationError(LcitoolError):
+ super().__init__(message, "Application")
+
+
+-class Application(metaclass=Singleton):
++class Application:
+ def __init__(self):
+ # make sure the lcitool cache dir exists
+ cache_dir_path = util.get_cache_dir()
+@@ -68,11 +69,13 @@ class Application(metaclass=Singleton):
+
+ base = resource_filename(__name__, "ansible")
+ config = Config()
+- inventory = Inventory()
++ targets = Targets()
++ inventory = Inventory(targets, config)
++ packages = Packages()
+ projects = Projects()
+
+ hosts_expanded = inventory.expand_hosts(hosts_pattern)
+- projects_expanded = Projects().expand_names(projects_pattern)
++ projects_expanded = projects.expand_names(projects_pattern)
+
+ if git_revision is not None:
+ tokens = git_revision.split("/")
+@@ -102,38 +105,16 @@ class Application(metaclass=Singleton):
+ ansible_runner = AnsibleWrapper()
+
+ for host in hosts_expanded:
+- facts = inventory.host_facts[host]
+- target = facts["target"]
+-
+ # packages are evaluated on a target level and since the
+ # host->target mapping is N-1, we can skip hosts belonging to a
+ # target group for which we already evaluated the package list
+- if target in group_vars:
++ target_name = inventory.get_host_target_name(host)
++ if target_name in group_vars:
+ continue
+
+- # resolve the package mappings to actual package names
+- internal_wanted_projects = ["base", "developer", "vm"]
+- if config.values["install"]["cloud_init"]:
+- internal_wanted_projects.append("cloud-init")
+-
+- selected_projects = internal_wanted_projects + projects_expanded
+- pkgs_install = projects.get_packages(selected_projects, facts)
+- pkgs_early_install = projects.get_packages(["early_install"], facts)
+- pkgs_remove = projects.get_packages(["unwanted"], facts)
+- package_names = package_names_by_type(pkgs_install)
+- package_names_remove = package_names_by_type(pkgs_remove)
+- package_names_early_install = package_names_by_type(pkgs_early_install)
+-
+- # merge the package lists to the Ansible group vars
+- packages = {}
+- packages["packages"] = package_names["native"]
+- packages["pypi_packages"] = package_names["pypi"]
+- packages["cpan_packages"] = package_names["cpan"]
+- packages["unwanted_packages"] = package_names_remove["native"]
+- packages["early_install_packages"] = package_names_early_install["native"]
+-
+- group_vars[target] = packages
+- group_vars[target].update(inventory.target_facts[target])
++ target = BuildTarget(targets, packages, target_name)
++ group_vars[target_name] = inventory.get_group_vars(target, projects,
++ projects_expanded)
+
+ ansible_runner.prepare_env(playbookdir=playbook_base,
+ inventories=[inventory.ansible_inventory],
+@@ -149,17 +130,19 @@ class Application(metaclass=Singleton):
+ def _action_hosts(self, args):
+ self._entrypoint_debug(args)
+
+- inventory = Inventory()
++ config = Config()
++ targets = Targets()
++ inventory = Inventory(targets, config)
+ for host in sorted(inventory.hosts):
+ print(host)
+
+ def _action_targets(self, args):
+ self._entrypoint_debug(args)
+
+- inventory = Inventory()
+- for target in sorted(inventory.targets):
++ targets = Targets()
++ for target in sorted(targets.targets):
+ if args.containerized:
+- facts = inventory.target_facts[target]
++ facts = targets.target_facts[target]
+
+ if facts["packaging"]["format"] not in ["apk", "deb", "rpm"]:
+ continue
+@@ -180,7 +163,9 @@ class Application(metaclass=Singleton):
+ self._entrypoint_debug(args)
+
+ facts = {}
+- inventory = Inventory()
++ config = Config()
++ targets = Targets()
++ inventory = Inventory(targets, config)
+ host = args.host
+ target = args.target
+
+@@ -193,10 +178,10 @@ class Application(metaclass=Singleton):
+ "to your inventory or use '--target <target>'"
+ )
+
+- if target not in inventory.targets:
++ if target not in targets.targets:
+ raise ApplicationError(f"Unsupported target OS '{target}'")
+
+- facts = inventory.target_facts[target]
++ facts = targets.target_facts[target]
+ else:
+ if target is not None:
+ raise ApplicationError(
+@@ -236,16 +221,19 @@ class Application(metaclass=Singleton):
+ def _action_variables(self, args):
+ self._entrypoint_debug(args)
+
+- projects_expanded = Projects().expand_names(args.projects)
++ targets = Targets()
++ packages = Packages()
++ projects = Projects()
++ projects_expanded = projects.expand_names(args.projects)
+
+ if args.format == "shell":
+- formatter = ShellVariablesFormatter()
++ formatter = ShellVariablesFormatter(projects)
+ else:
+- formatter = JSONVariablesFormatter()
++ formatter = JSONVariablesFormatter(projects)
+
+- variables = formatter.format(args.target,
+- projects_expanded,
+- args.cross_arch)
++ target = BuildTarget(targets, packages, args.target, args.cross_arch)
++ variables = formatter.format(target,
++ projects_expanded)
+
+ # No comments in json !
+ if args.format != "json":
+@@ -262,12 +250,16 @@ class Application(metaclass=Singleton):
+ def _action_dockerfile(self, args):
+ self._entrypoint_debug(args)
+
+- projects_expanded = Projects().expand_names(args.projects)
++ targets = Targets()
++ packages = Packages()
++ projects = Projects()
++ projects_expanded = projects.expand_names(args.projects)
++ target = BuildTarget(targets, packages, args.target, args.cross_arch)
+
+- dockerfile = DockerfileFormatter(args.base,
+- args.layers).format(args.target,
+- projects_expanded,
+- args.cross_arch)
++ dockerfile = DockerfileFormatter(projects,
++ args.base,
++ args.layers).format(target,
++ projects_expanded)
+
+ cliargv = [args.action]
+ if args.base is not None:
+@@ -283,11 +275,14 @@ class Application(metaclass=Singleton):
+ def _action_buildenvscript(self, args):
+ self._entrypoint_debug(args)
+
+- projects_expanded = Projects().expand_names(args.projects)
++ targets = Targets()
++ packages = Packages()
++ projects = Projects()
++ projects_expanded = projects.expand_names(args.projects)
++ target = BuildTarget(targets, packages, args.target, args.cross_arch)
+
+- buildenvscript = ShellBuildEnvFormatter().format(args.target,
+- projects_expanded,
+- args.cross_arch)
++ buildenvscript = ShellBuildEnvFormatter(projects).format(target,
++ projects_expanded)
+
+ cliargv = [args.action]
+ if args.cross_arch:
+@@ -302,7 +297,10 @@ class Application(metaclass=Singleton):
+ if args.base_dir is not None:
+ base_path = Path(args.base_dir)
+ ci_path = Path(args.ci_dir)
+- manifest = Manifest(args.manifest, args.quiet, ci_path, base_path)
++ targets = Targets()
++ packages = Packages()
++ projects = Projects()
++ manifest = Manifest(targets, packages, projects, args.manifest, args.quiet, ci_path, base_path)
+ manifest.generate(args.dry_run)
+
+ def run(self, args):
+diff --git a/tests/lcitool/libvirt-ci/lcitool/config.py b/tests/lcitool/libvirt-ci/lcitool/config.py
+index b83899b4..d42cda8c 100644
+--- a/tests/lcitool/libvirt-ci/lcitool/config.py
++++ b/tests/lcitool/libvirt-ci/lcitool/config.py
+@@ -12,7 +12,6 @@ from pathlib import Path
+ from pkg_resources import resource_filename
+
+ from lcitool import util, LcitoolError
+-from lcitool.singleton import Singleton
+
+ log = logging.getLogger(__name__)
+
+@@ -47,7 +46,7 @@ class ValidationError(ConfigError):
+ super().__init__(message)
+
+
+-class Config(metaclass=Singleton):
++class Config:
+
+ @property
+ def values(self):
+@@ -60,11 +59,15 @@ class Config(metaclass=Singleton):
+
+ def __init__(self):
+ self._values = None
++ self._config_file_dir = util.get_config_dir()
+ self._config_file_paths = [
+- Path(util.get_config_dir(), fname) for fname in
++ self.get_config_path(fname) for fname in
+ ["config.yml", "config.yaml"]
+ ]
+
++ def get_config_path(self, *args):
++ return Path(self._config_file_dir, *args)
++
+ def _load_config(self):
+ # Load the template config containing the defaults first, this must
+ # always succeed.
+@@ -149,7 +152,7 @@ class Config(metaclass=Singleton):
+
+ def _validate(self):
+ if self._values is None:
+- paths = ", ".join([str(p) for p in self._config_file_paths()])
++ paths = ", ".join([str(p) for p in self._config_file_paths])
+ raise ValidationError(f"Missing or empty configuration file, tried {paths}")
+
+ self._validate_section("install", ["root_password"])
+diff --git a/tests/lcitool/libvirt-ci/lcitool/configs/kickstart.cfg b/tests/lcitool/libvirt-ci/lcitool/configs/kickstart.cfg
+index cc3e103f..51db9963 100644
+--- a/tests/lcitool/libvirt-ci/lcitool/configs/kickstart.cfg
++++ b/tests/lcitool/libvirt-ci/lcitool/configs/kickstart.cfg
+@@ -38,7 +38,7 @@ rootpw --plaintext root
+ # remaining space to the root partition
+ ignoredisk --only-use=vda
+ zerombr
+-clearpart --none
++clearpart --drives=vda --all --disklabel=msdos
+ part / --fstype=ext4 --size=2048 --grow
+ part swap --fstype=swap --size=256
+
+diff --git a/tests/lcitool/libvirt-ci/lcitool/facts/mappings.yml b/tests/lcitool/libvirt-ci/lcitool/facts/mappings.yml
+index 06c8032a..c54241e4 100644
+--- a/tests/lcitool/libvirt-ci/lcitool/facts/mappings.yml
++++ b/tests/lcitool/libvirt-ci/lcitool/facts/mappings.yml
+@@ -1291,7 +1291,6 @@ mappings:
+ CentOSStream8: netcf-devel
+ Debian10: libnetcf-dev
+ Debian11: libnetcf-dev
+- Fedora35: netcf-devel
+ Ubuntu1804: libnetcf-dev
+ Ubuntu2004: libnetcf-dev
+ cross-policy-default: skip
+@@ -1639,7 +1638,6 @@ mappings:
+
+ publican:
+ deb: publican
+- Fedora35: publican
+ Fedora36: publican
+
+ pulseaudio:
+@@ -2203,8 +2201,9 @@ pypi_mappings:
+ python3-dbus:
+ MacOS: dbus-python
+
++ # higher versions are rejected by python3-sphinx-rtd-theme
+ python3-docutils:
+- default: docutils
++ default: docutils<0.18
+
+ python3-gobject:
+ MacOS: PyGObject
+diff --git a/tests/lcitool/libvirt-ci/lcitool/facts/projects/libvirt-php.yml b/tests/lcitool/libvirt-ci/lcitool/facts/projects/libvirt-php.yml
+index f10c6894..4dcfde49 100644
+--- a/tests/lcitool/libvirt-ci/lcitool/facts/projects/libvirt-php.yml
++++ b/tests/lcitool/libvirt-ci/lcitool/facts/projects/libvirt-php.yml
+@@ -10,7 +10,6 @@ packages:
+ - libxml2
+ - make
+ - php
+- - php-imagick
+ - pkg-config
+ - rpmbuild
+ - xmllint
+diff --git a/tests/lcitool/libvirt-ci/lcitool/facts/projects/qemu.yml b/tests/lcitool/libvirt-ci/lcitool/facts/projects/qemu.yml
+index 425459c5..117307ee 100644
+--- a/tests/lcitool/libvirt-ci/lcitool/facts/projects/qemu.yml
++++ b/tests/lcitool/libvirt-ci/lcitool/facts/projects/qemu.yml
+@@ -89,6 +89,7 @@ packages:
+ - pulseaudio
+ - python3
+ - python3-PyYAML
++ - python3-docutils
+ - python3-numpy
+ - python3-opencv
+ - python3-pillow
+diff --git a/tests/lcitool/libvirt-ci/lcitool/facts/targets/fedora-35.yml b/tests/lcitool/libvirt-ci/lcitool/facts/targets/fedora-37.yml
+similarity index 82%
+rename from lcitool/facts/targets/fedora-35.yml
+rename to lcitool/facts/targets/fedora-37.yml
+index 2e8e320c..5513995c 100644
+--- a/tests/lcitool/libvirt-ci/lcitool/facts/targets/fedora-35.yml
++++ b/tests/lcitool/libvirt-ci/lcitool/facts/targets/fedora-37.yml
+@@ -1,7 +1,7 @@
+ ---
+ os:
+ name: 'Fedora'
+- version: '35'
++ version: '37'
+
+ packaging:
+ format: 'rpm'
+@@ -21,7 +21,7 @@ ansible_python_package: python3
+ ansible_python_interpreter: /usr/bin/python3
+
+ install:
+- url: https://download.fedoraproject.org/pub/fedora/linux/releases/35/Everything/x86_64/os
++ url: https://download.fedoraproject.org/pub/fedora/linux/releases/37/Everything/x86_64/os
+
+ containers:
+- base: registry.fedoraproject.org/fedora:35
++ base: registry.fedoraproject.org/fedora:37
+diff --git a/tests/lcitool/libvirt-ci/lcitool/formatters.py b/tests/lcitool/libvirt-ci/lcitool/formatters.py
+index 114499a6..f799b466 100644
+--- a/tests/lcitool/libvirt-ci/lcitool/formatters.py
++++ b/tests/lcitool/libvirt-ci/lcitool/formatters.py
+@@ -7,13 +7,12 @@
+ import abc
+ import json
+ import logging
++import shlex
+
+ from pkg_resources import resource_filename
+
+ from lcitool import util, LcitoolError
+-from lcitool.inventory import Inventory
+-from lcitool.projects import Projects
+-from lcitool.package import package_names_by_type
++from lcitool.packages import package_names_by_type
+
+
+ log = logging.getLogger(__name__)
+@@ -50,6 +49,9 @@ class Formatter(metaclass=abc.ABCMeta):
+ This an abstract base class that each formatter must subclass.
+ """
+
++ def __init__(self, projects):
++ self._projects = projects
++
+ @abc.abstractmethod
+ def format(self):
+ """
+@@ -70,28 +72,27 @@ class Formatter(metaclass=abc.ABCMeta):
+ return c.read().rstrip()
+
+ def _generator_build_varmap(self,
+- facts,
+- selected_projects,
+- cross_arch):
+- projects = Projects()
++ target,
++ selected_projects):
++ projects = self._projects
+
+ # we need the 'base' internal project here, but packages for internal
+ # projects are not resolved via the public API, so it requires special
+ # handling
+ pkgs = {}
+- pkgs.update(projects.internal_projects["base"].get_packages(facts, cross_arch))
++ pkgs.update(projects.internal["base"].get_packages(target))
+
+ # we can now load packages for the rest of the projects
+- pkgs.update(projects.get_packages(selected_projects, facts, cross_arch))
++ pkgs.update(projects.get_packages(selected_projects, target))
+ package_names = package_names_by_type(pkgs)
+
+ varmap = {
+- "packaging_command": facts["packaging"]["command"],
+- "paths_ccache": facts["paths"]["ccache"],
+- "paths_make": facts["paths"]["make"],
+- "paths_ninja": facts["paths"]["ninja"],
+- "paths_python": facts["paths"]["python"],
+- "paths_pip3": facts["paths"]["pip3"],
++ "packaging_command": target.facts["packaging"]["command"],
++ "paths_ccache": target.facts["paths"]["ccache"],
++ "paths_make": target.facts["paths"]["make"],
++ "paths_ninja": target.facts["paths"]["ninja"],
++ "paths_python": target.facts["paths"]["python"],
++ "paths_pip3": target.facts["paths"]["pip3"],
+
+ "cross_arch": None,
+ "cross_abi": None,
+@@ -104,44 +105,22 @@ class Formatter(metaclass=abc.ABCMeta):
+ "cpan_pkgs": package_names["cpan"],
+ }
+
+- if cross_arch:
+- varmap["cross_arch"] = cross_arch
+- varmap["cross_abi"] = util.native_arch_to_abi(cross_arch)
++ if target.cross_arch:
++ varmap["cross_arch"] = target.cross_arch
++ varmap["cross_abi"] = util.native_arch_to_abi(target.cross_arch)
+
+- if facts["packaging"]["format"] == "deb":
+- cross_arch_deb = util.native_arch_to_deb_arch(cross_arch)
++ if target.facts["packaging"]["format"] == "deb":
++ cross_arch_deb = util.native_arch_to_deb_arch(target.cross_arch)
+ varmap["cross_arch_deb"] = cross_arch_deb
+
+ log.debug(f"Generated varmap: {varmap}")
+ return varmap
+
+- def _generator_prepare(self, target, selected_projects, cross_arch):
+- log.debug(f"Generating varmap for "
+- f"target='{target}', "
+- f"projects='{selected_projects}', "
+- f"cross_arch='{cross_arch}'")
+-
+- name = self.__class__.__name__.lower()
+-
+- try:
+- facts = Inventory().target_facts[target]
+- except KeyError:
+- raise FormatterError(f"Invalid target '{target}'")
+-
+- # We can only generate Dockerfiles for Linux
+- if (name == "dockerfileformatter" and
+- facts["packaging"]["format"] not in ["apk", "deb", "rpm"]):
+- raise FormatterError(f"Target {target} doesn't support this generator")
+-
+- varmap = self._generator_build_varmap(facts,
+- selected_projects,
+- cross_arch)
+- return facts, cross_arch, varmap
+-
+
+ class BuildEnvFormatter(Formatter):
+
+- def __init__(self, indent=0, pkgcleanup=False, nosync=False):
++ def __init__(self, inventory, indent=0, pkgcleanup=False, nosync=False):
++ super().__init__(inventory)
+ self._indent = indent
+ self._pkgcleanup = pkgcleanup
+ self._nosync = nosync
+@@ -151,23 +130,22 @@ class BuildEnvFormatter(Formatter):
+ return strings[0]
+
+ align = " \\\n" + (" " * (self._indent + len(command + " ")))
++ strings = [shlex.quote(x) for x in strings]
+ return align[1:] + align.join(strings)
+
+ def _generator_build_varmap(self,
+- facts,
+- selected_projects,
+- cross_arch):
+- varmap = super()._generator_build_varmap(facts,
+- selected_projects,
+- cross_arch)
++ target,
++ selected_projects):
++ varmap = super()._generator_build_varmap(target,
++ selected_projects)
+
+ varmap["nosync"] = ""
+ if self._nosync:
+- if facts["packaging"]["format"] == "deb":
++ if target.facts["packaging"]["format"] == "deb":
+ varmap["nosync"] = "eatmydata "
+- elif facts["packaging"]["format"] == "rpm" and facts["os"]["name"] == "Fedora":
++ elif target.facts["packaging"]["format"] == "rpm" and target.facts["os"]["name"] == "Fedora":
+ varmap["nosync"] = "nosync "
+- elif facts["packaging"]["format"] == "apk":
++ elif target.facts["packaging"]["format"] == "apk":
+ # TODO: 'libeatmydata' package is present in 'testing' repo
+ # for Alpine Edge. Once it graduates to 'main' repo we
+ # should use it here, and see later comment about adding
+@@ -176,14 +154,14 @@ class BuildEnvFormatter(Formatter):
+ pass
+
+ nosync = varmap["nosync"]
+- varmap["pkgs"] = self._align(nosync + facts["packaging"]["command"],
++ varmap["pkgs"] = self._align(nosync + target.facts["packaging"]["command"],
+ varmap["pkgs"])
+
+ if varmap["cross_pkgs"]:
+- varmap["cross_pkgs"] = self._align(nosync + facts["packaging"]["command"],
++ varmap["cross_pkgs"] = self._align(nosync + target.facts["packaging"]["command"],
+ varmap["cross_pkgs"])
+ if varmap["pypi_pkgs"]:
+- varmap["pypi_pkgs"] = self._align(nosync + facts["paths"]["pip3"],
++ varmap["pypi_pkgs"] = self._align(nosync + target.facts["paths"]["pip3"],
+ varmap["pypi_pkgs"])
+ if varmap["cpan_pkgs"]:
+ varmap["cpan_pkgs"] = self._align(nosync + "cpanm",
+@@ -191,7 +169,7 @@ class BuildEnvFormatter(Formatter):
+
+ return varmap
+
+- def _format_commands_ccache(self, cross_arch, varmap):
++ def _format_commands_ccache(self, target, varmap):
+ commands = []
+ compilers = set()
+
+@@ -213,14 +191,15 @@ class BuildEnvFormatter(Formatter):
+ ])
+
+ for compiler in sorted(compilers):
+- if cross_arch:
++ if target.cross_arch:
+ compiler = "{cross_abi}-" + compiler
+ commands.extend([
+ "ln -s {paths_ccache} /usr/libexec/ccache-wrappers/" + compiler,
+ ])
+ return commands
+
+- def _format_commands_pkglist(self, facts):
++ def _format_commands_pkglist(self, target):
++ facts = target.facts
+ commands = []
+ if facts["packaging"]["format"] == "apk":
+ commands.extend(["apk list | sort > /packages.txt"])
+@@ -232,7 +211,8 @@ class BuildEnvFormatter(Formatter):
+ commands.extend(["rpm -qa | sort > /packages.txt"])
+ return commands
+
+- def _format_commands_native(self, facts, cross_arch, varmap):
++ def _format_commands_native(self, target, varmap):
++ facts = target.facts
+ commands = []
+ osname = facts["os"]["name"]
+ osversion = facts["os"]["version"]
+@@ -356,9 +336,9 @@ class BuildEnvFormatter(Formatter):
+ "{nosync}{packaging_command} clean all -y",
+ ])
+
+- if not cross_arch:
+- commands.extend(self._format_commands_pkglist(facts))
+- commands.extend(self._format_commands_ccache(None, varmap))
++ if not target.cross_arch:
++ commands.extend(self._format_commands_pkglist(target))
++ commands.extend(self._format_commands_ccache(target, varmap))
+
+ commands = [c.format(**varmap) for c in commands]
+
+@@ -386,7 +366,8 @@ class BuildEnvFormatter(Formatter):
+
+ return env
+
+- def _format_commands_foreign(self, facts, cross_arch, varmap):
++ def _format_commands_foreign(self, target, varmap):
++ facts = target.facts
+ cross_commands = []
+
+ if facts["packaging"]["format"] == "deb":
+@@ -394,7 +375,7 @@ class BuildEnvFormatter(Formatter):
+ "export DEBIAN_FRONTEND=noninteractive",
+ "dpkg --add-architecture {cross_arch_deb}",
+ ])
+- if cross_arch == "riscv64":
++ if target.cross_arch == "riscv64":
+ cross_commands.extend([
+ "{nosync}{packaging_command} install debian-ports-archive-keyring",
+ "{nosync}echo 'deb http://ftp.ports.debian.org/debian-ports/ sid main' > /etc/apt/sources.list.d/ports.list",
+@@ -420,7 +401,7 @@ class BuildEnvFormatter(Formatter):
+ "{nosync}{packaging_command} clean all -y",
+ ])
+
+- if not cross_arch.startswith("mingw"):
++ if not target.cross_arch.startswith("mingw"):
+ cross_commands.extend([
+ "mkdir -p /usr/local/share/meson/cross",
+ "echo \"{cross_meson}\" > /usr/local/share/meson/cross/{cross_abi}",
+@@ -429,14 +410,14 @@ class BuildEnvFormatter(Formatter):
+ cross_meson = self._get_meson_cross(varmap["cross_abi"])
+ varmap["cross_meson"] = cross_meson.replace("\n", "\\n\\\n")
+
+- cross_commands.extend(self._format_commands_pkglist(facts))
+- cross_commands.extend(self._format_commands_ccache(cross_arch, varmap))
++ cross_commands.extend(self._format_commands_pkglist(target))
++ cross_commands.extend(self._format_commands_ccache(target, varmap))
+
+ cross_commands = [c.format(**varmap) for c in cross_commands]
+
+ return cross_commands
+
+- def _format_env_foreign(self, cross_arch, varmap):
++ def _format_env_foreign(self, target, varmap):
+ env = {}
+ env["ABI"] = varmap["cross_abi"]
+
+@@ -444,7 +425,7 @@ class BuildEnvFormatter(Formatter):
+ env["CONFIGURE_OPTS"] = "--host=" + varmap["cross_abi"]
+
+ if "meson" in varmap["mappings"]:
+- if cross_arch.startswith("mingw"):
++ if target.cross_arch.startswith("mingw"):
+ env["MESON_OPTS"] = "--cross-file=/usr/share/mingw/toolchain-" + varmap["cross_arch"] + ".meson"
+ else:
+ env["MESON_OPTS"] = "--cross-file=" + varmap["cross_abi"]
+@@ -454,8 +435,9 @@ class BuildEnvFormatter(Formatter):
+
+ class DockerfileFormatter(BuildEnvFormatter):
+
+- def __init__(self, base=None, layers="all"):
+- super().__init__(indent=len("RUN "),
++ def __init__(self, inventory, base=None, layers="all"):
++ super().__init__(inventory,
++ indent=len("RUN "),
+ pkgcleanup=True,
+ nosync=True)
+ self._base = base
+@@ -469,17 +451,17 @@ class DockerfileFormatter(BuildEnvFormatter):
+ lines.append(f"\nENV {key} \"{val}\"")
+ return "".join(lines)
+
+- def _format_section_base(self, facts):
++ def _format_section_base(self, target):
+ strings = []
+ if self._base:
+ base = self._base
+ else:
+- base = facts["containers"]["base"]
++ base = target.facts["containers"]["base"]
+ strings.append(f"FROM {base}")
+ return strings
+
+- def _format_section_native(self, facts, cross_arch, varmap):
+- groups = self._format_commands_native(facts, cross_arch, varmap)
++ def _format_section_native(self, target, varmap):
++ groups = self._format_commands_native(target, varmap)
+
+ strings = []
+ for commands in groups:
+@@ -489,25 +471,25 @@ class DockerfileFormatter(BuildEnvFormatter):
+ strings.append(self._format_env(env))
+ return strings
+
+- def _format_section_foreign(self, facts, cross_arch, varmap):
+- commands = self._format_commands_foreign(facts, cross_arch, varmap)
++ def _format_section_foreign(self, target, varmap):
++ commands = self._format_commands_foreign(target, varmap)
+
+ strings = ["\nRUN " + " && \\\n ".join(commands)]
+
+- env = self._format_env_foreign(cross_arch, varmap)
++ env = self._format_env_foreign(target, varmap)
+ strings.append(self._format_env(env))
+ return strings
+
+- def _format_dockerfile(self, target, project, facts, cross_arch, varmap):
++ def _format_dockerfile(self, target, project, varmap):
+ strings = []
+- strings.extend(self._format_section_base(facts))
++ strings.extend(self._format_section_base(target))
+ if self._layers in ["all", "native"]:
+- strings.extend(self._format_section_native(facts, cross_arch, varmap))
+- if cross_arch and self._layers in ["all", "foreign"]:
+- strings.extend(self._format_section_foreign(facts, cross_arch, varmap))
++ strings.extend(self._format_section_native(target, varmap))
++ if target.cross_arch and self._layers in ["all", "foreign"]:
++ strings.extend(self._format_section_foreign(target, varmap))
+ return strings
+
+- def format(self, target, selected_projects, cross_arch):
++ def format(self, target, selected_projects):
+ """
+ Generates and formats a Dockerfile.
+
+@@ -521,17 +503,18 @@ class DockerfileFormatter(BuildEnvFormatter):
+ """
+
+ log.debug(f"Generating Dockerfile for projects '{selected_projects}' "
+- f"on target '{target}' (cross_arch={cross_arch})")
++ f"on target {target}")
++
++ # We can only generate Dockerfiles for Linux
++ if (target.facts["packaging"]["format"] not in ["apk", "deb", "rpm"]):
++ raise DockerfileError(f"Target {target} doesn't support this generator")
+
+ try:
+- facts, cross_arch, varmap = self._generator_prepare(target,
+- selected_projects,
+- cross_arch)
++ varmap = self._generator_build_varmap(target, selected_projects)
+ except FormatterError as ex:
+ raise DockerfileError(str(ex))
+
+- return '\n'.join(self._format_dockerfile(target, selected_projects,
+- facts, cross_arch, varmap))
++ return '\n'.join(self._format_dockerfile(target, selected_projects, varmap))
+
+
+ class VariablesFormatter(Formatter):
+@@ -559,7 +542,7 @@ class VariablesFormatter(Formatter):
+ def _format_variables(varmap):
+ pass
+
+- def format(self, target, selected_projects, cross_arch):
++ def format(self, target, selected_projects):
+ """
+ Generates and formats environment variables as KEY=VAL pairs.
+
+@@ -572,12 +555,10 @@ class VariablesFormatter(Formatter):
+ """
+
+ log.debug(f"Generating variables for projects '{selected_projects} on "
+- f"target '{target}' (cross_arch={cross_arch})")
++ f"target {target}")
+
+ try:
+- _, _, varmap = self._generator_prepare(target,
+- selected_projects,
+- cross_arch)
++ varmap = self._generator_build_varmap(target, selected_projects)
+ except FormatterError as ex:
+ raise VariablesError(str(ex))
+
+@@ -608,8 +589,9 @@ class JSONVariablesFormatter(VariablesFormatter):
+
+ class ShellBuildEnvFormatter(BuildEnvFormatter):
+
+- def __init__(self, base=None, layers="all"):
+- super().__init__(indent=len(" "),
++ def __init__(self, inventory, base=None, layers="all"):
++ super().__init__(inventory,
++ indent=len(" "),
+ pkgcleanup=False,
+ nosync=False)
+
+@@ -621,25 +603,25 @@ class ShellBuildEnvFormatter(BuildEnvFormatter):
+ exp.append(f"export {key}=\"{val}\"")
+ return "\n" + "\n".join(exp)
+
+- def _format_buildenv(self, target, project, facts, cross_arch, varmap):
++ def _format_buildenv(self, target, project, varmap):
+ strings = [
+ "function install_buildenv() {",
+ ]
+- groups = self._format_commands_native(facts, cross_arch, varmap)
++ groups = self._format_commands_native(target, varmap)
+ for commands in groups:
+ strings.extend([" " + c for c in commands])
+- if cross_arch:
+- for command in self._format_commands_foreign(facts, cross_arch, varmap):
++ if target.cross_arch:
++ for command in self._format_commands_foreign(target, varmap):
+ strings.append(" " + command)
+ strings.append("}")
+
+ strings.append(self._format_env(self._format_env_native(varmap)))
+- if cross_arch:
++ if target.cross_arch:
+ strings.append(self._format_env(
+- self._format_env_foreign(cross_arch, varmap)))
++ self._format_env_foreign(target, varmap)))
+ return strings
+
+- def format(self, target, selected_projects, cross_arch):
++ def format(self, target, selected_projects):
+ """
+ Generates and formats a Shell script for preparing a build env.
+
+@@ -653,14 +635,11 @@ class ShellBuildEnvFormatter(BuildEnvFormatter):
+ """
+
+ log.debug(f"Generating Shell Build Env for projects '{selected_projects}' "
+- f"on target '{target}' (cross_arch={cross_arch})")
++ f"on target {target}")
+
+ try:
+- facts, cross_arch, varmap = self._generator_prepare(target,
+- selected_projects,
+- cross_arch)
++ varmap = self._generator_build_varmap(target, selected_projects)
+ except FormatterError as ex:
+ raise ShellBuildEnvError(str(ex))
+
+- return '\n'.join(self._format_buildenv(target, selected_projects,
+- facts, cross_arch, varmap))
++ return '\n'.join(self._format_buildenv(target, selected_projects, varmap))
+diff --git a/tests/lcitool/libvirt-ci/lcitool/inventory.py b/tests/lcitool/libvirt-ci/lcitool/inventory.py
+index 9752ca60..fe2b929b 100644
+--- a/tests/lcitool/libvirt-ci/lcitool/inventory.py
++++ b/tests/lcitool/libvirt-ci/lcitool/inventory.py
+@@ -4,15 +4,10 @@
+ #
+ # SPDX-License-Identifier: GPL-2.0-or-later
+
+-import copy
+ import logging
+-import yaml
+-
+-from pathlib import Path
+-from pkg_resources import resource_filename
+
+ from lcitool import util, LcitoolError
+-from lcitool.singleton import Singleton
++from lcitool.packages import package_names_by_type
+
+ log = logging.getLogger(__name__)
+
+@@ -24,7 +19,7 @@ class InventoryError(LcitoolError):
+ super().__init__(message, "Inventory")
+
+
+-class Inventory(metaclass=Singleton):
++class Inventory():
+
+ @property
+ def ansible_inventory(self):
+@@ -32,16 +27,6 @@ class Inventory(metaclass=Singleton):
+ self._ansible_inventory = self._get_ansible_inventory()
+ return self._ansible_inventory
+
+- @property
+- def target_facts(self):
+- if self._target_facts is None:
+- self._target_facts = self._load_target_facts()
+- return self._target_facts
+-
+- @property
+- def targets(self):
+- return list(self.target_facts.keys())
+-
+ @property
+ def host_facts(self):
+ if self._host_facts is None:
+@@ -52,22 +37,18 @@ class Inventory(metaclass=Singleton):
+ def hosts(self):
+ return list(self.host_facts.keys())
+
+- def __init__(self):
+- self._target_facts = None
++ def __init__(self, targets, config):
++ self._targets = targets
++ self._config = config
+ self._host_facts = None
+ self._ansible_inventory = None
+
+- @staticmethod
+- def _read_facts_from_file(yaml_path):
+- log.debug(f"Loading facts from '{yaml_path}'")
+- with open(yaml_path, "r") as infile:
+- return yaml.safe_load(infile)
+-
+ def _get_ansible_inventory(self):
+ from lcitool.ansible_wrapper import AnsibleWrapper, AnsibleWrapperError
+
+ inventory_sources = []
+- inventory_path = Path(util.get_config_dir(), "inventory")
++ inventory_path = self._config.get_config_path("inventory")
++ log.debug(f"Using '{inventory_path}' for lcitool inventory")
+ if inventory_path.exists():
+ inventory_sources.append(inventory_path)
+
+@@ -76,7 +57,7 @@ class Inventory(metaclass=Singleton):
+
+ ansible_runner = AnsibleWrapper()
+ ansible_runner.prepare_env(inventories=inventory_sources,
+- group_vars=self.target_facts)
++ group_vars=self._targets.target_facts)
+
+ log.debug(f"Running ansible-inventory on '{inventory_sources}'")
+ try:
+@@ -100,56 +81,6 @@ class Inventory(metaclass=Singleton):
+
+ return inventory
+
+- @staticmethod
+- def _validate_target_facts(target_facts, target):
+- fname = target + ".yml"
+-
+- actual_osname = target_facts["os"]["name"].lower()
+- if not target.startswith(actual_osname + "-"):
+- raise InventoryError(f'OS name "{target_facts["os"]["name"]}" does not match file name {fname}')
+- target = target[len(actual_osname) + 1:]
+-
+- actual_version = target_facts["os"]["version"].lower()
+- expected_version = target.replace("-", "")
+- if expected_version != actual_version:
+- raise InventoryError(f'OS version "{target_facts["os"]["version"]}" does not match version in file name {fname} ({expected_version})')
+-
+- def _load_target_facts(self):
+- def merge_dict(source, dest):
+- for key in source.keys():
+- if key not in dest:
+- dest[key] = copy.deepcopy(source[key])
+- continue
+-
+- if isinstance(source[key], list) or isinstance(dest[key], list):
+- raise InventoryError("cannot merge lists")
+- if isinstance(source[key], dict) != isinstance(dest[key], dict):
+- raise InventoryError("cannot merge dictionaries with non-dictionaries")
+- if isinstance(source[key], dict):
+- merge_dict(source[key], dest[key])
+-
+- facts = {}
+- targets_path = Path(resource_filename(__name__, "facts/targets/"))
+- targets_all_path = Path(targets_path, "all.yml")
+-
+- # first load the shared facts from targets/all.yml
+- shared_facts = self._read_facts_from_file(targets_all_path)
+-
+- # then load the rest of the facts
+- for entry in targets_path.iterdir():
+- if not entry.is_file() or entry.suffix != ".yml" or entry.name == "all.yml":
+- continue
+-
+- target = entry.stem
+- facts[target] = self._read_facts_from_file(entry)
+- self._validate_target_facts(facts[target], target)
+- facts[target]["target"] = target
+-
+- # missing per-distro facts fall back to shared facts
+- merge_dict(shared_facts, facts[target])
+-
+- return facts
+-
+ def _load_host_facts(self):
+ facts = {}
+ groups = {}
+@@ -184,7 +115,7 @@ class Inventory(metaclass=Singleton):
+
+ _rec(self.ansible_inventory["all"], "all")
+
+- targets = set(self.targets)
++ targets = set(self._targets.targets)
+ for host_name, host_groups in groups.items():
+ host_targets = host_groups.intersection(targets)
+
+@@ -209,3 +140,29 @@ class Inventory(metaclass=Singleton):
+ except Exception as ex:
+ log.debug(f"Failed to load expand '{pattern}'")
+ raise InventoryError(f"Failed to expand '{pattern}': {ex}")
++
++ def get_host_target_name(self, host):
++ return self.host_facts[host]["target"]
++
++ def get_group_vars(self, target, projects, projects_expanded):
++ # resolve the package mappings to actual package names
++ internal_wanted_projects = ["base", "developer", "vm"]
++ if self._config.values["install"]["cloud_init"]:
++ internal_wanted_projects.append("cloud-init")
++
++ selected_projects = internal_wanted_projects + projects_expanded
++ pkgs_install = projects.get_packages(selected_projects, target)
++ pkgs_early_install = projects.get_packages(["early_install"], target)
++ pkgs_remove = projects.get_packages(["unwanted"], target)
++ package_names = package_names_by_type(pkgs_install)
++ package_names_remove = package_names_by_type(pkgs_remove)
++ package_names_early_install = package_names_by_type(pkgs_early_install)
++
++ # merge the package lists to the Ansible group vars
++ group_vars = dict(target.facts)
++ group_vars["packages"] = package_names["native"]
++ group_vars["pypi_packages"] = package_names["pypi"]
++ group_vars["cpan_packages"] = package_names["cpan"]
++ group_vars["unwanted_packages"] = package_names_remove["native"]
++ group_vars["early_install_packages"] = package_names_early_install["native"]
++ return group_vars
+diff --git a/tests/lcitool/libvirt-ci/lcitool/manifest.py b/tests/lcitool/libvirt-ci/lcitool/manifest.py
+index c4cb8c0a..2ad53582 100644
+--- a/tests/lcitool/libvirt-ci/lcitool/manifest.py
++++ b/tests/lcitool/libvirt-ci/lcitool/manifest.py
+@@ -9,8 +9,8 @@ import yaml
+ from pathlib import Path
+
+ from lcitool.formatters import DockerfileFormatter, ShellVariablesFormatter, ShellBuildEnvFormatter
+-from lcitool.inventory import Inventory
+ from lcitool import gitlab, util, LcitoolError
++from lcitool.targets import BuildTarget
+
+ log = logging.getLogger(__name__)
+
+@@ -24,7 +24,10 @@ class ManifestError(LcitoolError):
+
+ class Manifest:
+
+- def __init__(self, configfp, quiet=False, cidir=Path("ci"), basedir=None):
++ def __init__(self, targets, packages, projects, configfp, quiet=False, cidir=Path("ci"), basedir=None):
++ self._targets = targets
++ self._packages = packages
++ self._projects = projects
+ self.configpath = configfp.name
+ self.values = yaml.safe_load(configfp)
+ self.quiet = quiet
+@@ -88,7 +91,6 @@ class Manifest:
+ targets = self.values["targets"] = {}
+ have_containers = False
+ have_cirrus = False
+- inventory = Inventory()
+ for target, targetinfo in targets.items():
+ if type(targetinfo) == str:
+ targets[target] = {"jobs": [{"arch": targetinfo}]}
+@@ -99,7 +101,7 @@ class Manifest:
+ jobsinfo = targetinfo["jobs"]
+
+ try:
+- facts = inventory.target_facts[target]
++ facts = self._targets.target_facts[target]
+ except KeyError:
+ raise ValueError(f"Invalid target '{target}'")
+
+@@ -205,27 +207,26 @@ class Manifest:
+ if not dryrun:
+ header = util.generate_file_header(["manifest",
+ self.configpath])
+- payload = formatter.format(target,
+- wantprojects,
+- arch)
++ payload = formatter.format(BuildTarget(self._targets, self._packages, target, arch),
++ wantprojects)
+ util.atomic_write(filename, header + payload + "\n")
+
+ return generated
+
+ def _generate_containers(self, dryrun):
+- formatter = DockerfileFormatter()
++ formatter = DockerfileFormatter(self._projects)
+ return self._generate_formatter(dryrun,
+ "containers", "Dockerfile",
+ formatter, "containers")
+
+ def _generate_cirrus(self, dryrun):
+- formatter = ShellVariablesFormatter()
++ formatter = ShellVariablesFormatter(self._projects)
+ return self._generate_formatter(dryrun,
+ "cirrus", "vars",
+ formatter, "cirrus")
+
+ def _generate_buildenv(self, dryrun):
+- formatter = ShellBuildEnvFormatter()
++ formatter = ShellBuildEnvFormatter(self._projects)
+ return self._generate_formatter(dryrun,
+ "buildenv", "sh",
+ formatter, "containers")
+@@ -416,7 +417,6 @@ class Manifest:
+
+ def _generate_build_jobs(self, targettype, cross, jobfunc):
+ jobs = []
+- inventory = Inventory()
+ for target, targetinfo in self.values["targets"].items():
+ if not targetinfo["enabled"]:
+ continue
+@@ -424,7 +424,7 @@ class Manifest:
+ continue
+
+ try:
+- facts = inventory.target_facts[target]
++ facts = self._targets.target_facts[target]
+ except KeyError:
+ raise ManifestError(f"Invalid target '{target}'")
+
+diff --git a/tests/lcitool/libvirt-ci/lcitool/package.py b/tests/lcitool/libvirt-ci/lcitool/packages.py
+similarity index 61%
+rename from lcitool/package.py
+rename to lcitool/packages.py
+index d267e2f2..6f3c3139 100644
+--- a/tests/lcitool/libvirt-ci/lcitool/package.py
++++ b/tests/lcitool/libvirt-ci/lcitool/packages.py
+@@ -30,7 +30,7 @@ Exported classes:
+ - CrossPackage
+ - PyPIPackage
+ - CPANPackage
+- - PackageFactory
++ - Packages
+
+ Exported functions:
+ - package_names_by_type
+@@ -39,6 +39,9 @@ Exported functions:
+
+ import abc
+ import logging
++import yaml
++
++from pkg_resources import resource_filename
+
+ from lcitool import util, LcitoolError
+
+@@ -90,8 +93,8 @@ class Package(metaclass=abc.ABCMeta):
+ - PyPIPackage
+ - CPANPackage
+
+- Do not instantiate any of the specific package subclasses, instead, use an
+- instance of the PackageFactory class which does that for you transparently.
++ Do not instantiate any of the specific package subclasses, instead, use
++ the Packages class which does that for you transparently.
+ Then use this public interface to interact with the instance itself.
+
+ Attributes:
+@@ -99,7 +102,7 @@ class Package(metaclass=abc.ABCMeta):
+ :ivar mapping: the generic package name that will resolve to @name
+ """
+
+- def __init__(self, pkg_mapping):
++ def __init__(self, mappings, pkg_mapping, keys, target):
+ """
+ Initialize the package with a generic package name
+
+@@ -107,9 +110,11 @@ class Package(metaclass=abc.ABCMeta):
+ """
+
+ self.mapping = pkg_mapping
+- self.name = None
++ self.name = self._eval(mappings, target, keys)
++ if self.name is None:
++ raise PackageEval(f"No mapping for '{pkg_mapping}'")
+
+- def _eval(self, mappings, keys=["default"]):
++ def _eval(self, mappings, target, keys):
+ """
+ Resolves package mapping to the actual name of the package.
+
+@@ -138,32 +143,26 @@ class CrossPackage(Package):
+ def __init__(self,
+ mappings,
+ pkg_mapping,
+- pkg_format,
+ base_keys,
+- cross_arch):
+-
+- super().__init__(pkg_mapping)
+-
+- self.name = self._eval(mappings, pkg_format, base_keys, cross_arch)
+- if self.name is None:
+- raise PackageEval(f"No mapping for '{pkg_mapping}'")
+-
+- def _eval(self, mappings, pkg_format, base_keys, cross_arch):
+- cross_keys = ["cross-" + cross_arch + "-" + k for k in base_keys]
++ target):
++ cross_keys = ["cross-" + target.cross_arch + "-" + k for k in base_keys]
+
+- if pkg_format == "deb":
++ if target.facts["packaging"]["format"] == "deb":
+ # For Debian-based distros, the name of the foreign package
+ # is usually the same as the native package, but there might
+ # be architecture-specific overrides, so we have to look both
+ # at the neutral keys and at the specific ones
+- arch_keys = [cross_arch + "-" + k for k in base_keys]
++ arch_keys = [target.cross_arch + "-" + k for k in base_keys]
+ cross_keys.extend(arch_keys + base_keys)
+
+- pkg_name = super()._eval(mappings, keys=cross_keys)
++ super().__init__(mappings, pkg_mapping, cross_keys, target)
++
++ def _eval(self, mappings, target, keys):
++ pkg_name = super()._eval(mappings, target, keys)
+ if pkg_name is None:
+ return None
+
+- if pkg_format == "deb":
++ if target.facts["packaging"]["format"] == "deb":
+ # For Debian-based distros, the name of the foreign package
+ # is obtained by appending the foreign architecture (in
+ # Debian format) to the name of the native package.
+@@ -171,7 +170,7 @@ class CrossPackage(Package):
+ # The exception to this is cross-compilers, where we have
+ # to install the package for the native architecture in
+ # order to be able to build for the foreign architecture
+- cross_arch_deb = util.native_arch_to_deb_arch(cross_arch)
++ cross_arch_deb = util.native_arch_to_deb_arch(target.cross_arch)
+ if self.mapping not in ["gcc", "g++"]:
+ pkg_name = pkg_name + ":" + cross_arch_deb
+ return pkg_name
+@@ -182,154 +181,150 @@ class NativePackage(Package):
+ def __init__(self,
+ mappings,
+ pkg_mapping,
+- base_keys):
+-
+- super().__init__(pkg_mapping)
+-
+- self.name = self._eval(mappings, base_keys)
+- if self.name is None:
+- raise PackageEval(f"No mapping for '{pkg_mapping}'")
+-
+- def _eval(self, mappings, base_keys):
++ base_keys,
++ target):
+ native_arch = util.get_native_arch()
+ native_keys = [native_arch + "-" + k for k in base_keys] + base_keys
+-
+- return super()._eval(mappings, keys=native_keys)
++ super().__init__(mappings, pkg_mapping, native_keys, target)
+
+
+ class PyPIPackage(Package):
+-
+- def __init__(self,
+- mappings,
+- pkg_mapping,
+- base_keys):
+-
+- super().__init__(pkg_mapping)
+-
+- self.name = self._eval(mappings, keys=base_keys)
+- if self.name is None:
+- raise PackageEval(f"No mapping for '{pkg_mapping}'")
++ pass
+
+
+ class CPANPackage(Package):
+-
+- def __init__(self,
+- mappings,
+- pkg_mapping,
+- base_keys):
+-
+- super().__init__(pkg_mapping)
+-
+- self.name = self._eval(mappings, keys=base_keys)
+- if self.name is None:
+- raise PackageEval(f"No mapping for '{pkg_mapping}'")
++ pass
+
+
+-class PackageFactory:
++class Packages:
+ """
+- Factory producing Package instances.
+-
+- Creates Package class instances based on the generic package mapping name
+- which will be resolved to the actual package name the moment a Package
+- instance is created by this factory.
++ Database of package mappings. Package class representing the actual
++ package name are created based on the generic package mapping.
+
+ """
+
+- def __init__(self, mappings, facts):
+- """
+- Initialize package factory model.
+-
+- :param mappings: dictionary of ALL existing package mappings, i.e.
+- including Python and CPAN ones
+- :param facts: dictionary of target OS facts
+- """
+-
+- def _generate_base_keys(facts):
+- base_keys = [
+- # keys are ordered by priority
+- facts["os"]["name"] + facts["os"]["version"],
+- facts["os"]["name"],
+- facts["packaging"]["format"],
+- "default"
+- ]
+- return base_keys
+-
+- self._mappings = mappings["mappings"]
+- self._pypi_mappings = mappings["pypi_mappings"]
+- self._cpan_mappings = mappings["cpan_mappings"]
+- self._facts = facts
+- self._base_keys = _generate_base_keys(facts)
+-
+- def _get_cross_policy(self, pkg_mapping):
+- for k in ["cross-policy-" + k for k in self._base_keys]:
+- if k in self._mappings[pkg_mapping]:
+- cross_policy = self._mappings[pkg_mapping][k]
++ def __init__(self):
++ self._mappings = None
++ self._pypi_mappings = None
++ self._cpan_mappings = None
++
++ @staticmethod
++ def _base_keys(target):
++ return [
++ target.facts["os"]["name"] + target.facts["os"]["version"],
++ target.facts["os"]["name"],
++ target.facts["packaging"]["format"],
++ "default"
++ ]
++
++ def _get_cross_policy(self, pkg_mapping, target):
++ base_keys = self._base_keys(target)
++ for k in ["cross-policy-" + k for k in base_keys]:
++ if k in self.mappings[pkg_mapping]:
++ cross_policy = self.mappings[pkg_mapping][k]
+ if cross_policy not in ["native", "foreign", "skip"]:
+ raise Exception(
+ f"Unexpected cross arch policy {cross_policy} for "
+ f"{pkg_mapping}"
+ )
+ return cross_policy
+- return None
++ return "native"
+
+- def _get_native_package(self, pkg_mapping):
+- return NativePackage(self._mappings, pkg_mapping, self._base_keys)
++ def _get_native_package(self, pkg_mapping, target):
++ base_keys = self._base_keys(target)
++ return NativePackage(self.mappings, pkg_mapping, base_keys, target)
+
+- def _get_pypi_package(self, pkg_mapping):
+- return PyPIPackage(self._pypi_mappings, pkg_mapping, self._base_keys)
++ def _get_pypi_package(self, pkg_mapping, target):
++ base_keys = self._base_keys(target)
++ return PyPIPackage(self.pypi_mappings, pkg_mapping, base_keys, target)
+
+- def _get_cpan_package(self, pkg_mapping):
+- return CPANPackage(self._cpan_mappings, pkg_mapping, self._base_keys)
++ def _get_cpan_package(self, pkg_mapping, target):
++ base_keys = self._base_keys(target)
++ return CPANPackage(self.cpan_mappings, pkg_mapping, base_keys, target)
+
+- def _get_noncross_package(self, pkg_mapping):
++ def _get_noncross_package(self, pkg_mapping, target):
+ package_resolvers = [self._get_native_package,
+ self._get_pypi_package,
+ self._get_cpan_package]
+
+ for resolver in package_resolvers:
+ try:
+- return resolver(pkg_mapping)
++ return resolver(pkg_mapping, target)
+ except PackageEval:
+ continue
+
+ # This package doesn't exist on the given platform
+ return None
+
+- def _get_cross_package(self, pkg_mapping, cross_arch):
++ def _get_cross_package(self, pkg_mapping, target):
+
+ # query the cross policy for the mapping to see whether we need
+ # a cross- or non-cross version of a package
+- cross_policy = self._get_cross_policy(pkg_mapping)
++ cross_policy = self._get_cross_policy(pkg_mapping, target)
+ if cross_policy == "skip":
+ return None
+
+- elif cross_policy == "native" or cross_policy is None:
+- return self._get_noncross_package(pkg_mapping)
++ elif cross_policy == "native":
++ return self._get_noncross_package(pkg_mapping, target)
+
+ try:
+- return CrossPackage(self._mappings, pkg_mapping,
+- self._facts["packaging"]["format"],
+- self._base_keys, cross_arch)
++ base_keys = self._base_keys(target)
++ return CrossPackage(self.mappings, pkg_mapping, base_keys, target)
+ except PackageEval:
+ pass
+
+ # This package doesn't exist on the given platform
+ return None
+
+- def get_package(self, pkg_mapping, cross_arch=None):
++ @property
++ def mappings(self):
++ if self._mappings is None:
++ self._load_mappings()
++
++ return self._mappings
++
++ @property
++ def pypi_mappings(self):
++ if self._mappings is None:
++ self._load_mappings()
++
++ return self._pypi_mappings
++
++ @property
++ def cpan_mappings(self):
++ if self._mappings is None:
++ self._load_mappings()
++
++ return self._cpan_mappings
++
++ def get_package(self, pkg_mapping, target):
+ """
+ Resolves the generic mapping name and returns a Package instance.
+
+ :param pkg_mapping: generic package mapping name
+- :param cross_arch: cross architecture string (if needed)
++ :param target: target to resolve the package for
+ :return: instance of Package subclass or None if package mapping could
+ not be resolved
+ """
+
+- if pkg_mapping not in self._mappings:
++ if pkg_mapping not in self.mappings:
+ raise PackageMissing(f"Package {pkg_mapping} not present in mappings")
+
+- if cross_arch is None:
+- return self._get_noncross_package(pkg_mapping)
++ if target.cross_arch is None:
++ return self._get_noncross_package(pkg_mapping, target)
+ else:
+- return self._get_cross_package(pkg_mapping, cross_arch)
++ return self._get_cross_package(pkg_mapping, target)
++
++ def _load_mappings(self):
++ mappings_path = resource_filename(__name__,
++ "facts/mappings.yml")
++
++ try:
++ with open(mappings_path, "r") as infile:
++ mappings = yaml.safe_load(infile)
++ self._mappings = mappings["mappings"]
++ self._pypi_mappings = mappings["pypi_mappings"]
++ self._cpan_mappings = mappings["cpan_mappings"]
++ except Exception as ex:
++ log.debug("Can't load mappings")
++ raise PackageError(f"Can't load mappings: {ex}")
+diff --git a/tests/lcitool/libvirt-ci/lcitool/projects.py b/tests/lcitool/libvirt-ci/lcitool/projects.py
+index 06d34803..28e83a27 100644
+--- a/tests/lcitool/libvirt-ci/lcitool/projects.py
++++ b/tests/lcitool/libvirt-ci/lcitool/projects.py
+@@ -11,8 +11,7 @@ from pathlib import Path
+ from pkg_resources import resource_filename
+
+ from lcitool import util, LcitoolError
+-from lcitool.package import PackageFactory, PyPIPackage, CPANPackage
+-from lcitool.singleton import Singleton
++from lcitool.packages import PyPIPackage, CPANPackage
+
+ log = logging.getLogger(__name__)
+
+@@ -29,79 +28,58 @@ class ProjectError(LcitoolError):
+ super().__init__(message, "Project")
+
+
+-class Projects(metaclass=Singleton):
++class Projects:
+ """
+ Attributes:
+ :ivar names: list of all project names
++ :ivar public: dictionary from project names to ``Project`` objects for public projects
++ :ivar internal: dictionary from project names to ``Project`` objects for internal projects
+ """
+
+ @property
+- def projects(self):
+- if self._projects is None:
+- self._projects = self._load_projects()
+- return self._projects
++ def public(self):
++ if self._public is None:
++ self._load_public()
++ return self._public
+
+ @property
+ def names(self):
+- return list(self.projects.keys())
++ return list(self.public.keys())
+
+ @property
+- def internal_projects(self):
+- if self._internal_projects is None:
+- self._internal_projects = self._load_internal_projects()
+- return self._internal_projects
+-
+- @property
+- def mappings(self):
+-
+- # lazy load mappings
+- if self._mappings is None:
+- self._mappings = self._load_mappings()
+- return self._mappings
++ def internal(self):
++ if self._internal is None:
++ self._load_internal()
++ return self._internal
+
+ def __init__(self):
+- self._projects = None
+- self._internal_projects = None
+- self._mappings = None
++ self._public = None
++ self._internal = None
+
+- @staticmethod
+- def _load_projects_from_path(path):
++ def _load_projects_from_path(self, path):
+ projects = {}
+
+ for item in path.iterdir():
+ if not item.is_file() or item.suffix != ".yml":
+ continue
+
+- projects[item.stem] = Project(item.stem, item)
++ projects[item.stem] = Project(self, item.stem, item)
+
+ return projects
+
+- @staticmethod
+- def _load_projects():
++ def _load_public(self):
+ source = Path(resource_filename(__name__, "facts/projects"))
+- projects = Projects._load_projects_from_path(source)
++ projects = self._load_projects_from_path(source)
+
+ if util.get_extra_data_dir() is not None:
+ source = Path(util.get_extra_data_dir()).joinpath("projects")
+- projects.update(Projects._load_projects_from_path(source))
++ projects.update(self._load_projects_from_path(source))
+
+- return projects
++ self._public = projects
+
+- @staticmethod
+- def _load_internal_projects():
++ def _load_internal(self):
+ source = Path(resource_filename(__name__, "facts/projects/internal"))
+- return Projects._load_projects_from_path(source)
+-
+- def _load_mappings(self):
+- mappings_path = resource_filename(__name__,
+- "facts/mappings.yml")
+-
+- try:
+- with open(mappings_path, "r") as infile:
+- return yaml.safe_load(infile)
+- except Exception as ex:
+- log.debug("Can't load mappings")
+- raise ProjectError(f"Can't load mappings: {ex}")
++ self._internal = self._load_projects_from_path(source)
+
+ def expand_names(self, pattern):
+ try:
+@@ -110,18 +88,46 @@ class Projects(metaclass=Singleton):
+ log.debug(f"Failed to expand '{pattern}'")
+ raise ProjectError(f"Failed to expand '{pattern}': {ex}")
+
+- def get_packages(self, projects, facts, cross_arch=None):
++ def get_packages(self, projects, target):
+ packages = {}
+
+ for proj in projects:
+ try:
+- obj = self.projects[proj]
++ obj = self.public[proj]
+ except KeyError:
+- obj = self.internal_projects[proj]
+- packages.update(obj.get_packages(facts, cross_arch))
++ obj = self.internal[proj]
++ packages.update(obj.get_packages(target))
+
+ return packages
+
++ def eval_generic_packages(self, target, generic_packages):
++ pkgs = {}
++ needs_pypi = False
++ needs_cpan = False
++
++ for mapping in generic_packages:
++ pkg = target.get_package(mapping)
++ if pkg is None:
++ continue
++ pkgs[pkg.mapping] = pkg
++
++ if isinstance(pkg, PyPIPackage):
++ needs_pypi = True
++ elif isinstance(pkg, CPANPackage):
++ needs_cpan = True
++
++ # The get_packages eval_generic_packages cycle is deliberate and
++ # harmless since we'll only ever hit it with the following internal
++ # projects
++ if needs_pypi:
++ proj = self.internal["python-pip"]
++ pkgs.update(proj.get_packages(target))
++ if needs_cpan:
++ proj = self.internal["perl-cpan"]
++ pkgs.update(proj.get_packages(target))
++
++ return pkgs
++
+
+ class Project:
+ """
+@@ -129,6 +135,7 @@ class Project:
+ :ivar name: project name
+ :ivar generic_packages: list of generic packages needed by the project
+ to build successfully
++ :ivar projects: parent ``Projects`` instance
+ """
+
+ @property
+@@ -139,7 +146,8 @@ class Project:
+ self._generic_packages = self._load_generic_packages()
+ return self._generic_packages
+
+- def __init__(self, name, path):
++ def __init__(self, projects, name, path):
++ self.projects = projects
+ self.name = name
+ self.path = path
+ self._generic_packages = None
+@@ -156,49 +164,21 @@ class Project:
+ log.debug(f"Can't load pacakges for '{self.name}'")
+ raise ProjectError(f"Can't load packages for '{self.name}': {ex}")
+
+- def _eval_generic_packages(self, facts, cross_arch=None):
+- pkgs = {}
+- factory = PackageFactory(Projects().mappings, facts)
+- needs_pypi = False
+- needs_cpan = False
+-
+- for mapping in self.generic_packages:
+- pkg = factory.get_package(mapping, cross_arch)
+- if pkg is None:
+- continue
+- pkgs[pkg.mapping] = pkg
+-
+- if isinstance(pkg, PyPIPackage):
+- needs_pypi = True
+- elif isinstance(pkg, CPANPackage):
+- needs_cpan = True
+-
+- # The get_packages _eval_generic_packages cycle is deliberate and
+- # harmless since we'll only ever hit it with the following internal
+- # projects
+- if needs_pypi:
+- proj = Projects().internal_projects["python-pip"]
+- pkgs.update(proj.get_packages(facts, cross_arch))
+- if needs_cpan:
+- proj = Projects().internal_projects["perl-cpan"]
+- pkgs.update(proj.get_packages(facts, cross_arch))
+-
+- return pkgs
+-
+- def get_packages(self, facts, cross_arch=None):
+- osname = facts["os"]["name"]
+- osversion = facts["os"]["version"]
++ def get_packages(self, target):
++ osname = target.facts["os"]["name"]
++ osversion = target.facts["os"]["version"]
+ target_name = f"{osname.lower()}-{osversion.lower()}"
+- if cross_arch is None:
++ if target.cross_arch is None:
+ target_name = f"{target_name}-x86_64"
+ else:
+ try:
+- util.validate_cross_platform(cross_arch, osname)
++ util.validate_cross_platform(target.cross_arch, osname)
+ except ValueError as ex:
+ raise ProjectError(ex)
+- target_name = f"{target_name}-{cross_arch}"
++ target_name = f"{target_name}-{target.cross_arch}"
+
+ # lazy evaluation + caching of package names for a given distro
+ if self._target_packages.get(target_name) is None:
+- self._target_packages[target_name] = self._eval_generic_packages(facts, cross_arch)
++ self._target_packages[target_name] = self.projects.eval_generic_packages(target,
++ self.generic_packages)
+ return self._target_packages[target_name]
+diff --git a/tests/lcitool/libvirt-ci/lcitool/singleton.py b/tests/lcitool/libvirt-ci/lcitool/singleton.py
+deleted file mode 100644
+index 46d1379f..00000000
+--- a/tests/lcitool/libvirt-ci/lcitool/singleton.py
++++ /dev/null
+@@ -1,14 +0,0 @@
+-# singleton.py - module singleton class definition
+-#
+-# Copyright (C) 2021 Red Hat, Inc.
+-#
+-# SPDX-License-Identifier: GPL-2.0-or-later
+-
+-class Singleton(type):
+- _instances = {}
+-
+- def __call__(cls, *args, **kwargs):
+- if cls not in cls._instances:
+- instance = super(Singleton, cls).__call__(*args, **kwargs)
+- cls._instances[cls] = instance
+- return cls._instances[cls]
+diff --git a/tests/lcitool/libvirt-ci/lcitool/targets.py b/tests/lcitool/libvirt-ci/lcitool/targets.py
+new file mode 100644
+index 00000000..ef6deab1
+--- /dev/null
++++ b/tests/lcitool/libvirt-ci/lcitool/targets.py
+@@ -0,0 +1,108 @@
++# targets.py - module containing accessors to per-target information
++#
++# Copyright (C) 2022 Red Hat, Inc.
++#
++# SPDX-License-Identifier: GPL-2.0-or-later
++
++import logging
++import yaml
++
++from pathlib import Path
++from pkg_resources import resource_filename
++
++from lcitool import util, LcitoolError
++
++
++log = logging.getLogger(__name__)
++
++
++class TargetsError(LcitoolError):
++ """Global exception type for the targets module."""
++
++ def __init__(self, message):
++ super().__init__(message, "Targets")
++
++
++class Targets():
++
++ @property
++ def target_facts(self):
++ if self._target_facts is None:
++ self._target_facts = self._load_target_facts()
++ return self._target_facts
++
++ @property
++ def targets(self):
++ return list(self.target_facts.keys())
++
++ def __init__(self):
++ self._target_facts = None
++
++ @staticmethod
++ def _read_facts_from_file(yaml_path):
++ log.debug(f"Loading facts from '{yaml_path}'")
++ with open(yaml_path, "r") as infile:
++ return yaml.safe_load(infile)
++
++ @staticmethod
++ def _validate_target_facts(target_facts, target):
++ fname = target + ".yml"
++
++ actual_osname = target_facts["os"]["name"].lower()
++ if not target.startswith(actual_osname + "-"):
++ raise TargetsError(f'OS name "{target_facts["os"]["name"]}" does not match file name {fname}')
++ target = target[len(actual_osname) + 1:]
++
++ actual_version = target_facts["os"]["version"].lower()
++ expected_version = target.replace("-", "")
++ if expected_version != actual_version:
++ raise TargetsError(f'OS version "{target_facts["os"]["version"]}" does not match version in file name {fname} ({expected_version})')
++
++ def _load_target_facts(self):
++ facts = {}
++ targets_path = Path(resource_filename(__name__, "facts/targets/"))
++ targets_all_path = Path(targets_path, "all.yml")
++
++ # first load the shared facts from targets/all.yml
++ shared_facts = self._read_facts_from_file(targets_all_path)
++
++ # then load the rest of the facts
++ for entry in targets_path.iterdir():
++ if not entry.is_file() or entry.suffix != ".yml" or entry.name == "all.yml":
++ continue
++
++ target = entry.stem
++ facts[target] = self._read_facts_from_file(entry)
++ self._validate_target_facts(facts[target], target)
++ facts[target]["target"] = target
++
++ # missing per-distro facts fall back to shared facts
++ util.merge_dict(shared_facts, facts[target])
++
++ return facts
++
++
++class BuildTarget:
++ """
++ Attributes:
++ :ivar _targets: object to retrieve the target facts
++ :ivar name: target name
++ :ivar cross_arch: cross compilation architecture
++ """
++
++ def __init__(self, targets, packages, name, cross_arch=None):
++ if name not in targets.target_facts:
++ raise TargetsError(f"Target not found: {name}")
++ self._packages = packages
++ self.name = name
++ self.cross_arch = cross_arch
++ self.facts = targets.target_facts[self.name]
++
++ def __str__(self):
++ if self.cross_arch:
++ return f"{self.name} (cross_arch={self.cross_arch}"
++ else:
++ return self.name
++
++ def get_package(self, name):
++ return self._packages.get_package(name, self)
+diff --git a/tests/lcitool/libvirt-ci/lcitool/util.py b/tests/lcitool/libvirt-ci/lcitool/util.py
+index d2577917..c231df00 100644
+--- a/tests/lcitool/libvirt-ci/lcitool/util.py
++++ b/tests/lcitool/libvirt-ci/lcitool/util.py
+@@ -4,6 +4,7 @@
+ #
+ # SPDX-License-Identifier: GPL-2.0-or-later
+
++import copy
+ import fnmatch
+ import logging
+ import os
+@@ -202,6 +203,20 @@ def get_config_dir():
+ return Path(config_dir, "lcitool")
+
+
++def merge_dict(source, dest):
++ for key in source.keys():
++ if key not in dest:
++ dest[key] = copy.deepcopy(source[key])
++ continue
++
++ if isinstance(source[key], list) or isinstance(dest[key], list):
++ raise ValueError("cannot merge lists")
++ if isinstance(source[key], dict) != isinstance(dest[key], dict):
++ raise ValueError("cannot merge dictionaries with non-dictionaries")
++ if isinstance(source[key], dict):
++ merge_dict(source[key], dest[key])
++
++
+ extra_data_dir = None
+
+
+diff --git a/tests/lcitool/libvirt-ci/test-requirements.txt b/tests/lcitool/libvirt-ci/test-requirements.txt
+index 8e3fd1fd..b816c69f 100644
+--- a/tests/lcitool/libvirt-ci/test-requirements.txt
++++ b/tests/lcitool/libvirt-ci/test-requirements.txt
+@@ -1,5 +1,7 @@
+ -r requirements.txt
+--r vm-requirements.txt
++
++ansible
++ansible-runner
+
+ flake8
+ pytest
+diff --git a/tests/lcitool/libvirt-ci/tests/conftest.py b/tests/lcitool/libvirt-ci/tests/conftest.py
+index 751eb405..61a7b436 100644
+--- a/tests/lcitool/libvirt-ci/tests/conftest.py
++++ b/tests/lcitool/libvirt-ci/tests/conftest.py
+@@ -1,5 +1,16 @@
+ import pytest
+
++from pathlib import Path
++
++from lcitool.config import Config
++from lcitool.inventory import Inventory
++from lcitool.packages import Packages
++from lcitool.projects import Projects
++from lcitool.targets import Targets
++from lcitool import util
++
++import test_utils.utils as test_utils
++
+
+ def pytest_addoption(parser):
+ parser.addoption(
+@@ -13,3 +24,54 @@ def pytest_addoption(parser):
+ def pytest_configure(config):
+ opts = ["regenerate_output"]
+ pytest.custom_args = {opt: config.getoption(opt) for opt in opts}
++
++
++# These needs to be a global in order to compute ALL_PROJECTS and ALL_TARGETS
++# at collection time. Tests do not access it and use the fixtures below.
++_PROJECTS = Projects()
++_TARGETS = Targets()
++
++ALL_PROJECTS = sorted(_PROJECTS.names + list(_PROJECTS.internal.keys()))
++ALL_TARGETS = sorted(_TARGETS.targets)
++
++
++@pytest.fixture
++def config(monkeypatch, request):
++ if 'config_filename' in request.fixturenames:
++ config_filename = request.getfixturevalue('config_filename')
++ actual_path = Path(test_utils.test_data_indir(request.module.__file__), config_filename)
++
++ # we have to monkeypatch the '_config_file_paths' attribute, since we don't
++ # support custom inventory paths
++ config = Config()
++ monkeypatch.setattr(config, "_config_file_paths", [actual_path])
++ else:
++ actual_dir = Path(test_utils.test_data_indir(request.module.__file__))
++ monkeypatch.setattr(util, "get_config_dir", lambda: actual_dir)
++ config = Config()
++
++ return config
++
++
++@pytest.fixture
++def inventory(monkeypatch, targets, config):
++ inventory = Inventory(targets, config)
++
++ monkeypatch.setattr(inventory, "_get_libvirt_inventory",
++ lambda: {"all": {"children": {}}})
++ return inventory
++
++
++@pytest.fixture(scope="module")
++def packages():
++ return Packages()
++
++
++@pytest.fixture
++def projects():
++ return _PROJECTS
++
++
++@pytest.fixture
++def targets():
++ return _TARGETS
+diff --git a/tests/lcitool/libvirt-ci/tests/data/formatters/out/alpine-315-all-projects.Dockerfile b/tests/lcitool/libvirt-ci/tests/data/formatters/out/alpine-315-all-projects.Dockerfile
+index 13e1a542..5fabdb95 100644
+--- a/tests/lcitool/libvirt-ci/tests/data/formatters/out/alpine-315-all-projects.Dockerfile
++++ b/tests/lcitool/libvirt-ci/tests/data/formatters/out/alpine-315-all-projects.Dockerfile
+@@ -156,7 +156,6 @@ RUN apk update && \
+ perl-xml-xpath \
+ perl-yaml \
+ php8-dev \
+- php8-pecl-imagick \
+ pixman-dev \
+ pkgconf \
+ polkit \
+diff --git a/tests/lcitool/libvirt-ci/tests/data/formatters/out/alpine-316-all-projects.Dockerfile b/tests/lcitool/libvirt-ci/tests/data/formatters/out/alpine-316-all-projects.Dockerfile
+index 7eef4d51..077eacee 100644
+--- a/tests/lcitool/libvirt-ci/tests/data/formatters/out/alpine-316-all-projects.Dockerfile
++++ b/tests/lcitool/libvirt-ci/tests/data/formatters/out/alpine-316-all-projects.Dockerfile
+@@ -156,7 +156,6 @@ RUN apk update && \
+ perl-xml-xpath \
+ perl-yaml \
+ php8-dev \
+- php8-pecl-imagick \
+ pixman-dev \
+ pkgconf \
+ polkit \
+diff --git a/tests/lcitool/libvirt-ci/tests/data/formatters/out/alpine-edge-all-projects.Dockerfile b/tests/lcitool/libvirt-ci/tests/data/formatters/out/alpine-edge-all-projects.Dockerfile
+index 67b591ea..0d0f7527 100644
+--- a/tests/lcitool/libvirt-ci/tests/data/formatters/out/alpine-edge-all-projects.Dockerfile
++++ b/tests/lcitool/libvirt-ci/tests/data/formatters/out/alpine-edge-all-projects.Dockerfile
+@@ -156,7 +156,6 @@ RUN apk update && \
+ perl-xml-xpath \
+ perl-yaml \
+ php8-dev \
+- php8-pecl-imagick \
+ pixman-dev \
+ pkgconf \
+ polkit \
+diff --git a/tests/lcitool/libvirt-ci/tests/data/formatters/out/debian-10-all-projects.Dockerfile b/tests/lcitool/libvirt-ci/tests/data/formatters/out/debian-10-all-projects.Dockerfile
+index 0d0b3e57..9d784d24 100644
+--- a/tests/lcitool/libvirt-ci/tests/data/formatters/out/debian-10-all-projects.Dockerfile
++++ b/tests/lcitool/libvirt-ci/tests/data/formatters/out/debian-10-all-projects.Dockerfile
+@@ -221,7 +221,6 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
+ perl \
+ perl-base \
+ php-dev \
+- php-imagick \
+ pkgconf \
+ policykit-1 \
+ publican \
+diff --git a/tests/lcitool/libvirt-ci/tests/data/formatters/out/debian-11-all-projects.Dockerfile b/tests/lcitool/libvirt-ci/tests/data/formatters/out/debian-11-all-projects.Dockerfile
+index 7ab4c2ca..ee5166c6 100644
+--- a/tests/lcitool/libvirt-ci/tests/data/formatters/out/debian-11-all-projects.Dockerfile
++++ b/tests/lcitool/libvirt-ci/tests/data/formatters/out/debian-11-all-projects.Dockerfile
+@@ -224,7 +224,6 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
+ perl \
+ perl-base \
+ php-dev \
+- php-imagick \
+ pkgconf \
+ policykit-1 \
+ publican \
+diff --git a/tests/lcitool/libvirt-ci/tests/data/formatters/out/debian-sid-all-projects.Dockerfile b/tests/lcitool/libvirt-ci/tests/data/formatters/out/debian-sid-all-projects.Dockerfile
+index 8ca21e51..09dac3eb 100644
+--- a/tests/lcitool/libvirt-ci/tests/data/formatters/out/debian-sid-all-projects.Dockerfile
++++ b/tests/lcitool/libvirt-ci/tests/data/formatters/out/debian-sid-all-projects.Dockerfile
+@@ -224,7 +224,6 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
+ perl \
+ perl-base \
+ php-dev \
+- php-imagick \
+ pkgconf \
+ policykit-1 \
+ publican \
+diff --git a/tests/lcitool/libvirt-ci/tests/data/formatters/out/fedora-36-all-projects.Dockerfile b/tests/lcitool/libvirt-ci/tests/data/formatters/out/fedora-36-all-projects.Dockerfile
+index 51b2b96b..cb416150 100644
+--- a/tests/lcitool/libvirt-ci/tests/data/formatters/out/fedora-36-all-projects.Dockerfile
++++ b/tests/lcitool/libvirt-ci/tests/data/formatters/out/fedora-36-all-projects.Dockerfile
+@@ -214,7 +214,6 @@ exec "$@"' > /usr/bin/nosync && \
+ perl-generators \
+ perl-podlators \
+ php-devel \
+- php-pecl-imagick \
+ pixman-devel \
+ pkgconfig \
+ polkit \
+diff --git a/tests/lcitool/libvirt-ci/tests/data/formatters/out/fedora-35-all-projects.Dockerfile b/tests/lcitool/libvirt-ci/tests/data/formatters/out/fedora-37-all-projects.Dockerfile
+similarity index 98%
+rename from tests/data/formatters/out/fedora-35-all-projects.Dockerfile
+rename to tests/data/formatters/out/fedora-37-all-projects.Dockerfile
+index 35789b6d..e477d3f3 100644
+--- a/tests/lcitool/libvirt-ci/tests/data/formatters/out/fedora-35-all-projects.Dockerfile
++++ b/tests/lcitool/libvirt-ci/tests/data/formatters/out/fedora-37-all-projects.Dockerfile
+@@ -1,4 +1,4 @@
+-FROM registry.fedoraproject.org/fedora:35
++FROM registry.fedoraproject.org/fedora:37
+
+ RUN dnf install -y nosync && \
+ echo -e '#!/bin/sh\n\
+@@ -163,7 +163,6 @@ exec "$@"' > /usr/bin/nosync && \
+ nbdkit \
+ ncurses-devel \
+ net-snmp-devel \
+- netcf-devel \
+ nettle-devel \
+ nfs-utils \
+ ninja-build \
+@@ -215,11 +214,9 @@ exec "$@"' > /usr/bin/nosync && \
+ perl-generators \
+ perl-podlators \
+ php-devel \
+- php-pecl-imagick \
+ pixman-devel \
+ pkgconfig \
+ polkit \
+- publican \
+ pulseaudio-libs-devel \
+ python3 \
+ python3-PyYAML \
+diff --git a/tests/lcitool/libvirt-ci/tests/data/formatters/out/fedora-rawhide-all-projects.Dockerfile b/tests/lcitool/libvirt-ci/tests/data/formatters/out/fedora-rawhide-all-projects.Dockerfile
+index bc47cf9f..35852443 100644
+--- a/tests/lcitool/libvirt-ci/tests/data/formatters/out/fedora-rawhide-all-projects.Dockerfile
++++ b/tests/lcitool/libvirt-ci/tests/data/formatters/out/fedora-rawhide-all-projects.Dockerfile
+@@ -215,7 +215,6 @@ exec "$@"' > /usr/bin/nosync && \
+ perl-generators \
+ perl-podlators \
+ php-devel \
+- php-pecl-imagick \
+ pixman-devel \
+ pkgconfig \
+ polkit \
+diff --git a/tests/lcitool/libvirt-ci/tests/data/formatters/out/opensuse-leap-153-all-projects.Dockerfile b/tests/lcitool/libvirt-ci/tests/data/formatters/out/opensuse-leap-153-all-projects.Dockerfile
+index 16bb069b..c6f116cc 100644
+--- a/tests/lcitool/libvirt-ci/tests/data/formatters/out/opensuse-leap-153-all-projects.Dockerfile
++++ b/tests/lcitool/libvirt-ci/tests/data/formatters/out/opensuse-leap-153-all-projects.Dockerfile
+@@ -193,7 +193,6 @@ RUN zypper update -y && \
+ perl-YAML \
+ perl-base \
+ php-devel \
+- php-imagick \
+ pkgconfig \
+ polkit \
+ python3-Pillow \
+diff --git a/tests/lcitool/libvirt-ci/tests/data/formatters/out/opensuse-leap-154-all-projects.Dockerfile b/tests/lcitool/libvirt-ci/tests/data/formatters/out/opensuse-leap-154-all-projects.Dockerfile
+index 499ec816..23749f23 100644
+--- a/tests/lcitool/libvirt-ci/tests/data/formatters/out/opensuse-leap-154-all-projects.Dockerfile
++++ b/tests/lcitool/libvirt-ci/tests/data/formatters/out/opensuse-leap-154-all-projects.Dockerfile
+@@ -194,7 +194,6 @@ RUN zypper update -y && \
+ perl-YAML \
+ perl-base \
+ php-devel \
+- php-imagick \
+ pkgconfig \
+ polkit \
+ python3-Pillow \
+diff --git a/tests/lcitool/libvirt-ci/tests/data/formatters/out/opensuse-tumbleweed-all-projects.Dockerfile b/tests/lcitool/libvirt-ci/tests/data/formatters/out/opensuse-tumbleweed-all-projects.Dockerfile
+index 84e898ae..1e357bfe 100644
+--- a/tests/lcitool/libvirt-ci/tests/data/formatters/out/opensuse-tumbleweed-all-projects.Dockerfile
++++ b/tests/lcitool/libvirt-ci/tests/data/formatters/out/opensuse-tumbleweed-all-projects.Dockerfile
+@@ -194,7 +194,6 @@ RUN zypper dist-upgrade -y && \
+ perl-YAML \
+ perl-base \
+ php-devel \
+- php-imagick \
+ pkgconfig \
+ polkit \
+ python3-Pillow \
+diff --git a/tests/lcitool/libvirt-ci/tests/data/formatters/out/ubuntu-1804-all-projects.Dockerfile b/tests/lcitool/libvirt-ci/tests/data/formatters/out/ubuntu-1804-all-projects.Dockerfile
+index 9adad777..2b8715e8 100644
+--- a/tests/lcitool/libvirt-ci/tests/data/formatters/out/ubuntu-1804-all-projects.Dockerfile
++++ b/tests/lcitool/libvirt-ci/tests/data/formatters/out/ubuntu-1804-all-projects.Dockerfile
+@@ -217,7 +217,6 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
+ perl \
+ perl-base \
+ php-dev \
+- php-imagick \
+ pkgconf \
+ policykit-1 \
+ publican \
+diff --git a/tests/lcitool/libvirt-ci/tests/data/formatters/out/ubuntu-2004-all-projects.Dockerfile b/tests/lcitool/libvirt-ci/tests/data/formatters/out/ubuntu-2004-all-projects.Dockerfile
+index 2e26434d..ab976b62 100644
+--- a/tests/lcitool/libvirt-ci/tests/data/formatters/out/ubuntu-2004-all-projects.Dockerfile
++++ b/tests/lcitool/libvirt-ci/tests/data/formatters/out/ubuntu-2004-all-projects.Dockerfile
+@@ -221,7 +221,6 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
+ perl \
+ perl-base \
+ php-dev \
+- php-imagick \
+ pkgconf \
+ policykit-1 \
+ publican \
+diff --git a/tests/lcitool/libvirt-ci/tests/data/formatters/out/ubuntu-2204-all-projects.Dockerfile b/tests/lcitool/libvirt-ci/tests/data/formatters/out/ubuntu-2204-all-projects.Dockerfile
+index 560b45b9..b9c457b1 100644
+--- a/tests/lcitool/libvirt-ci/tests/data/formatters/out/ubuntu-2204-all-projects.Dockerfile
++++ b/tests/lcitool/libvirt-ci/tests/data/formatters/out/ubuntu-2204-all-projects.Dockerfile
+@@ -224,7 +224,6 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
+ perl \
+ perl-base \
+ php-dev \
+- php-imagick \
+ pkgconf \
+ policykit-1 \
+ publican \
+diff --git a/tests/lcitool/libvirt-ci/tests/data/inventory/in/config.yml b/tests/lcitool/libvirt-ci/tests/data/inventory/in/config.yml
+new file mode 100644
+index 00000000..0eafdbee
+--- /dev/null
++++ b/tests/lcitool/libvirt-ci/tests/data/inventory/in/config.yml
+@@ -0,0 +1,3 @@
++install:
++ cloud_init: true
++ root_password: foo
+diff --git a/tests/lcitool/libvirt-ci/tests/data/inventory/in/inventory/sample b/tests/lcitool/libvirt-ci/tests/data/inventory/in/inventory/sample
+new file mode 100644
+index 00000000..83b103cd
+--- /dev/null
++++ b/tests/lcitool/libvirt-ci/tests/data/inventory/in/inventory/sample
+@@ -0,0 +1,12 @@
++[centos-stream-8]
++centos-stream-8-1
++centos-stream-8-2
++some-other-centos-stream-8
++
++[fedora-37]
++fedora-test-1
++fedora-test-2 fully_managed=True
++
++[debian-10]
++192.168.1.30
++
+diff --git a/tests/lcitool/libvirt-ci/tests/data/packages/out/fedora-35.yml b/tests/lcitool/libvirt-ci/tests/data/packages/out/fedora-37.yml
+similarity index 99%
+rename from tests/data/packages/out/fedora-35.yml
+rename to tests/data/packages/out/fedora-37.yml
+index 2ad108ae..465fbe19 100644
+--- a/tests/lcitool/libvirt-ci/tests/data/packages/out/fedora-35.yml
++++ b/tests/lcitool/libvirt-ci/tests/data/packages/out/fedora-37.yml
+@@ -159,7 +159,6 @@ native:
+ - ncurses-devel
+ - net-snmp-devel
+ - net-tools
+-- netcf-devel
+ - nettle-devel
+ - nfs-utils
+ - ninja-build
+@@ -216,7 +215,6 @@ native:
+ - pixman-devel
+ - pkgconfig
+ - polkit
+-- publican
+ - pulseaudio-libs-devel
+ - python3
+ - python3-PyYAML
+diff --git a/tests/lcitool/libvirt-ci/tests/test_config.py b/tests/lcitool/libvirt-ci/tests/test_config.py
+index 049340f1..9a2fa7fc 100644
+--- a/tests/lcitool/libvirt-ci/tests/test_config.py
++++ b/tests/lcitool/libvirt-ci/tests/test_config.py
+@@ -9,20 +9,11 @@ import pytest
+ import test_utils.utils as test_utils
+
+ from pathlib import Path
+-from lcitool.config import Config, ValidationError
+-from lcitool.singleton import Singleton
+-
+-
+-@pytest.fixture(autouse=True)
+-def destroy_config():
+- # The following makes sure the Config singleton is deleted after each test
+- # See https://docs.pytest.org/en/6.2.x/fixture.html#teardown-cleanup-aka-fixture-finalization
+- yield
+- del Singleton._instances[Config]
++from lcitool.config import ValidationError
+
+
+ @pytest.mark.parametrize(
+- "filename",
++ "config_filename",
+ [
+ "full.yml",
+ "minimal.yml",
+@@ -30,21 +21,15 @@ def destroy_config():
+ "unknown_key.yml",
+ ],
+ )
+-def test_config(monkeypatch, filename):
+- actual_path = Path(test_utils.test_data_indir(__file__), filename)
+- expected_path = Path(test_utils.test_data_outdir(__file__), filename)
+-
+- config = Config()
++def test_config(config, config_filename):
++ expected_path = Path(test_utils.test_data_outdir(__file__), config_filename)
+
+- # we have to monkeypatch the '_config_file_paths' attribute, since we don't
+- # support custom inventory paths
+- monkeypatch.setattr(config, "_config_file_paths", [actual_path])
+ actual = config.values
+ test_utils.assert_yaml_matches_file(actual, expected_path)
+
+
+ @pytest.mark.parametrize(
+- "filename",
++ "config_filename",
+ [
+ "empty.yml",
+ "missing_mandatory_section.yml",
+@@ -52,11 +37,6 @@ def test_config(monkeypatch, filename):
+ "missing_gitlab_section_with_gitlab_flavor.yml",
+ ],
+ )
+-def test_config_invalid(monkeypatch, filename):
+- actual_path = Path(test_utils.test_data_indir(__file__), filename)
+-
+- config = Config()
+- monkeypatch.setattr(config, "_config_file_paths", [actual_path])
+-
++def test_config_invalid(config, config_filename):
+ with pytest.raises(ValidationError):
+ config.values
+diff --git a/tests/lcitool/libvirt-ci/tests/test_formatters.py b/tests/lcitool/libvirt-ci/tests/test_formatters.py
+index 8abb4b3c..49b4a3c0 100644
+--- a/tests/lcitool/libvirt-ci/tests/test_formatters.py
++++ b/tests/lcitool/libvirt-ci/tests/test_formatters.py
+@@ -9,8 +9,7 @@ import pytest
+ import test_utils.utils as test_utils
+ from pathlib import Path
+
+-from lcitool.inventory import Inventory
+-from lcitool.projects import Projects
++from lcitool.targets import BuildTarget
+ from lcitool.formatters import ShellVariablesFormatter, JSONVariablesFormatter, DockerfileFormatter, ShellBuildEnvFormatter
+
+
+@@ -41,56 +40,62 @@ layer_scenarios = [
+
+
+ @pytest.mark.parametrize("project,target,arch", scenarios)
+-def test_dockerfiles(project, target, arch, request):
+- gen = DockerfileFormatter()
+- actual = gen.format(target, [project], arch)
++def test_dockerfiles(packages, projects, targets, project, target, arch, request):
++ gen = DockerfileFormatter(projects)
++ target_obj = BuildTarget(targets, packages, target, arch)
++ actual = gen.format(target_obj, [project])
+ expected_path = Path(test_utils.test_data_outdir(__file__), request.node.callspec.id + ".Dockerfile")
+ test_utils.assert_matches_file(actual, expected_path)
+
+
+ @pytest.mark.parametrize("project,target,arch,base,layers", layer_scenarios)
+-def test_dockerfile_layers(project, target, arch, base, layers, request):
+- gen = DockerfileFormatter(base, layers)
+- actual = gen.format(target, [project], arch)
++def test_dockerfile_layers(packages, projects, targets, project, target, arch, base, layers, request):
++ gen = DockerfileFormatter(projects, base, layers)
++ target_obj = BuildTarget(targets, packages, target, arch)
++ actual = gen.format(target_obj, [project])
+ expected_path = Path(test_utils.test_data_outdir(__file__), request.node.callspec.id + ".Dockerfile")
+ test_utils.assert_matches_file(actual, expected_path)
+
+
+ @pytest.mark.parametrize("project,target,arch", scenarios)
+-def test_variables_shell(project, target, arch, request):
+- gen = ShellVariablesFormatter()
+- actual = gen.format(target, [project], arch)
++def test_variables_shell(packages, projects, targets, project, target, arch, request):
++ gen = ShellVariablesFormatter(projects)
++ target_obj = BuildTarget(targets, packages, target, arch)
++ actual = gen.format(target_obj, [project])
+ expected_path = Path(test_utils.test_data_outdir(__file__), request.node.callspec.id + ".vars")
+ test_utils.assert_matches_file(actual, expected_path)
+
+
+ @pytest.mark.parametrize("project,target,arch", scenarios)
+-def test_variables_json(project, target, arch, request):
+- gen = JSONVariablesFormatter()
+- actual = gen.format(target, [project], arch)
++def test_variables_json(packages, projects, targets, project, target, arch, request):
++ gen = JSONVariablesFormatter(projects)
++ target_obj = BuildTarget(targets, packages, target, arch)
++ actual = gen.format(target_obj, [project])
+ expected_path = Path(test_utils.test_data_outdir(__file__), request.node.callspec.id + ".json")
+ test_utils.assert_matches_file(actual, expected_path)
+
+
+ @pytest.mark.parametrize("project,target,arch", scenarios)
+-def test_prepbuildenv(project, target, arch, request):
+- gen = ShellBuildEnvFormatter()
+- actual = gen.format(target, [project], arch)
++def test_prepbuildenv(packages, projects, targets, project, target, arch, request):
++ gen = ShellBuildEnvFormatter(projects)
++ target_obj = BuildTarget(targets, packages, target, arch)
++ actual = gen.format(target_obj, [project])
+ expected_path = Path(test_utils.test_data_outdir(__file__), request.node.callspec.id + ".sh")
+ test_utils.assert_matches_file(actual, expected_path)
+
+
+-def test_all_projects_dockerfiles():
+- inventory = Inventory()
+- all_projects = Projects().names
++def test_all_projects_dockerfiles(packages, projects, targets):
++ all_projects = projects.names
+
+- for target in sorted(inventory.targets):
+- facts = inventory.target_facts[target]
++ for target in sorted(targets.targets):
++ target_obj = BuildTarget(targets, packages, target)
++
++ facts = target_obj.facts
+
+ if facts["packaging"]["format"] not in ["apk", "deb", "rpm"]:
+ continue
+
+- gen = DockerfileFormatter()
+- actual = gen.format(target, all_projects, None)
++ gen = DockerfileFormatter(projects)
++ actual = gen.format(target_obj, all_projects)
+ expected_path = Path(test_utils.test_data_outdir(__file__), f"{target}-all-projects.Dockerfile")
+ test_utils.assert_matches_file(actual, expected_path)
+diff --git a/tests/lcitool/libvirt-ci/tests/test_inventory.py b/tests/lcitool/libvirt-ci/tests/test_inventory.py
+new file mode 100644
+index 00000000..f8e6e21f
+--- /dev/null
++++ b/tests/lcitool/libvirt-ci/tests/test_inventory.py
+@@ -0,0 +1,50 @@
++# test_inventory: test lcitool Ansible inventory
++#
++# Copyright (C) 2022 Red Hat, Inc.
++#
++# SPDX-License-Identifier: GPL-2.0-or-later
++
++import pytest
++
++from lcitool.inventory import InventoryError
++from lcitool.targets import BuildTarget
++
++
++pytestmark = pytest.mark.filterwarnings("ignore:'pipes' is deprecated:DeprecationWarning")
++
++
++@pytest.mark.parametrize("host,target,fully_managed", [
++ pytest.param("centos-stream-8-1", "centos-stream-8", False, id="centos-stream-8-1"),
++ pytest.param("192.168.1.30", "debian-10", False, id="debian-10"),
++ pytest.param("fedora-test-2", "fedora-37", True, id="fedora-test-2"),
++])
++def test_host_facts(inventory, targets, host, target, fully_managed):
++ host_facts = inventory.host_facts[host]
++ assert host_facts["target"] == target
++ for key, value in targets.target_facts[target].items():
++ assert host_facts[key] == value
++ assert host_facts.get("fully_managed", False) == fully_managed
++
++
++def test_expand_hosts(inventory):
++ assert sorted(inventory.expand_hosts("*centos*")) == [
++ "centos-stream-8-1",
++ "centos-stream-8-2",
++ "some-other-centos-stream-8"
++ ]
++ with pytest.raises(InventoryError):
++ inventory.expand_hosts("debian-10")
++
++
++def test_host_target_name(inventory):
++ assert inventory.get_host_target_name("fedora-test-1") == "fedora-37"
++
++
++def test_group_vars(inventory, targets, packages, projects):
++ target = BuildTarget(targets, packages, "fedora-37")
++ group_vars = inventory.get_group_vars(target, projects, ["nbdkit"])
++ assert "nano" in group_vars["unwanted_packages"]
++ assert "python3-libselinux" in group_vars["early_install_packages"]
++
++ for key, value in target.facts.items():
++ assert group_vars[key] == value
+diff --git a/tests/lcitool/libvirt-ci/tests/test_manifest.py b/tests/lcitool/libvirt-ci/tests/test_manifest.py
+index 7c923e0b..33ef4e3e 100644
+--- a/tests/lcitool/libvirt-ci/tests/test_manifest.py
++++ b/tests/lcitool/libvirt-ci/tests/test_manifest.py
+@@ -14,7 +14,7 @@ from lcitool import util
+ from lcitool.manifest import Manifest
+
+
+-def test_generate(monkeypatch):
++def test_generate(targets, packages, projects, monkeypatch):
+ manifest_path = Path(test_utils.test_data_indir(__file__), "manifest.yml")
+
+ # Squish the header that contains argv with paths we don't
+@@ -67,7 +67,7 @@ def test_generate(monkeypatch):
+ m.setattr(Path, 'glob', fake_glob)
+
+ with open(manifest_path, "r") as fp:
+- manifest = Manifest(fp, quiet=True)
++ manifest = Manifest(targets, packages, projects, fp, quiet=True)
+
+ manifest.generate()
+
+@@ -134,7 +134,7 @@ def test_generate(monkeypatch):
+ finally:
+ if pytest.custom_args["regenerate_output"]:
+ with open(manifest_path, "r") as fp:
+- manifest = Manifest(fp, quiet=True,
++ manifest = Manifest(targets, packages, projects, fp, quiet=True,
+ basedir=Path(test_utils.test_data_outdir(__file__)))
+
+ manifest.generate()
+diff --git a/tests/lcitool/libvirt-ci/tests/test_packages.py b/tests/lcitool/libvirt-ci/tests/test_packages.py
+index dad37611..ec4492e3 100644
+--- a/tests/lcitool/libvirt-ci/tests/test_packages.py
++++ b/tests/lcitool/libvirt-ci/tests/test_packages.py
+@@ -13,12 +13,11 @@ from functools import total_ordering
+
+ from pathlib import Path
+ from lcitool import util
+-from lcitool.inventory import Inventory
+-from lcitool.projects import Project, Projects, ProjectError
+-from lcitool.package import NativePackage, CrossPackage, PyPIPackage, CPANPackage
++from lcitool.projects import Project, ProjectError
++from lcitool.packages import NativePackage, CrossPackage, PyPIPackage, CPANPackage
++from lcitool.targets import BuildTarget
+
+-
+-ALL_TARGETS = sorted(Inventory().targets)
++from conftest import ALL_TARGETS
+
+
+ def get_non_cross_targets():
+@@ -43,14 +42,14 @@ def packages_as_dict(raw_pkgs):
+
+
+ @pytest.fixture
+-def test_project():
+- return Project("packages",
++def test_project(projects):
++ return Project(projects, "packages",
+ Path(test_utils.test_data_indir(__file__), "packages.yml"))
+
+
+-def test_verify_all_mappings_and_packages():
++def test_verify_all_mappings_and_packages(packages):
+ expected_path = Path(test_utils.test_data_indir(__file__), "packages.yml")
+- actual = {"packages": sorted(Projects().mappings["mappings"].keys())}
++ actual = {"packages": sorted(packages.mappings.keys())}
+
+ test_utils.assert_yaml_matches_file(actual, expected_path)
+
+@@ -66,14 +65,14 @@ cross_params = [
+
+
+ @pytest.mark.parametrize("target,arch", native_params + cross_params)
+-def test_package_resolution(test_project, target, arch):
++def test_package_resolution(targets, packages, test_project, target, arch):
+ if arch is None:
+ outfile = f"{target}.yml"
+ else:
+ outfile = f"{target}-cross-{arch}.yml"
+ expected_path = Path(test_utils.test_data_outdir(__file__), outfile)
+- pkgs = test_project.get_packages(Inventory().target_facts[target],
+- cross_arch=arch)
++ target_obj = BuildTarget(targets, packages, target, arch)
++ pkgs = test_project.get_packages(target_obj)
+ actual = packages_as_dict(pkgs)
+
+ test_utils.assert_yaml_matches_file(actual, expected_path)
+@@ -83,10 +82,10 @@ def test_package_resolution(test_project, target, arch):
+ "target",
+ [pytest.param(target, id=target) for target in get_non_cross_targets()],
+ )
+-def test_unsupported_cross_platform(test_project, target):
++def test_unsupported_cross_platform(targets, packages, test_project, target):
+ with pytest.raises(ProjectError):
+- test_project.get_packages(Inventory().target_facts[target],
+- cross_arch="s390x")
++ target_obj = BuildTarget(targets, packages, target, "s390x")
++ test_project.get_packages(target_obj)
+
+
+ @pytest.mark.parametrize(
+@@ -96,10 +95,10 @@ def test_unsupported_cross_platform(test_project, target):
+ pytest.param("fedora-rawhide", "s390x", id="fedora-rawhide-cross-s390x"),
+ ],
+ )
+-def test_cross_platform_arch_mismatch(test_project, target, arch):
++def test_cross_platform_arch_mismatch(targets, packages, test_project, target, arch):
+ with pytest.raises(ProjectError):
+- test_project.get_packages(Inventory().target_facts[target],
+- cross_arch=arch)
++ target_obj = BuildTarget(targets, packages, target, arch)
++ test_project.get_packages(target_obj)
+
+
+ @total_ordering
+@@ -124,11 +123,11 @@ class MappingKey(namedtuple('MappingKey', ['components', 'priority'])):
+ return self.components < other.components
+
+
+-def mapping_keys_product():
++def mapping_keys_product(targets):
+ basekeys = set()
+
+ basekeys.add(MappingKey(("default", ), 0))
+- for target, facts in Inventory().target_facts.items():
++ for target, facts in targets.target_facts.items():
+ fmt = facts["packaging"]["format"]
+ name = facts["os"]["name"]
+ ver = facts["os"]["version"]
+@@ -148,10 +147,11 @@ def mapping_keys_product():
+ return basekeys + archkeys + crossarchkeys + crosspolicykeys
+
+
+-def test_project_mappings_sorting():
+- mappings = Projects().mappings["mappings"]
++@pytest.mark.parametrize("key", ["mappings", "pypi_mappings", "cpan_mappings"])
++def test_project_mappings_sorting(targets, packages, key):
++ mappings = getattr(packages, key)
+
+- all_expect_keys = mapping_keys_product()
++ all_expect_keys = mapping_keys_product(targets)
+ for package, entries in mappings.items():
+ got_keys = list(entries.keys())
+ expect_keys = list(filter(lambda k: k in got_keys, all_expect_keys))
+diff --git a/tests/lcitool/libvirt-ci/tests/test_projects.py b/tests/lcitool/libvirt-ci/tests/test_projects.py
+index 760d331c..84493834 100644
+--- a/tests/lcitool/libvirt-ci/tests/test_projects.py
++++ b/tests/lcitool/libvirt-ci/tests/test_projects.py
+@@ -6,37 +6,25 @@
+
+ import pytest
+
+-from lcitool.projects import Projects
+-from lcitool.inventory import Inventory
++from lcitool.targets import BuildTarget
+
++from conftest import ALL_PROJECTS
+
+-projects = Projects()
+-ALL_PROJECTS = sorted(projects.names + list(projects.internal_projects.keys()))
+
+-
+-@pytest.mark.parametrize(
+- "name",
+- ALL_PROJECTS
+-)
+-def test_project_packages(name):
++@pytest.fixture(params=ALL_PROJECTS)
++def project(request, projects):
+ try:
+- project = projects.projects[name]
++ return projects.public[request.param]
+ except KeyError:
+- project = projects.internal_projects[name]
+- target = Inventory().targets[0]
+- facts = Inventory().target_facts[target]
+- project.get_packages(facts)
++ return projects.internal[request.param]
+
+
+-@pytest.mark.parametrize(
+- "name",
+- ALL_PROJECTS
+-)
+-def test_project_package_sorting(name):
+- try:
+- project = projects.projects[name]
+- except KeyError:
+- project = projects.internal_projects[name]
++def test_project_packages(targets, packages, project):
++ target = BuildTarget(targets, packages, targets.targets[0])
++ project.get_packages(target)
++
++
++def test_project_package_sorting(project):
+ pkgs = project._load_generic_packages()
+
+ otherpkgs = sorted(pkgs)
+diff --git a/tests/lcitool/libvirt-ci/tests/test_misc.py b/tests/lcitool/libvirt-ci/tests/test_targets.py
+similarity index 77%
+rename from tests/test_misc.py
+rename to tests/test_targets.py
+index 5f1af1e9..61985f7f 100644
+--- a/tests/lcitool/libvirt-ci/tests/test_misc.py
++++ b/tests/lcitool/libvirt-ci/tests/test_targets.py
+@@ -1,4 +1,4 @@
+-# test_misc: test uncategorized aspects of lcitool
++# test_targets: test lcitool target facts
+ #
+ # Copyright (C) 2022 Red Hat, Inc.
+ #
+@@ -6,17 +6,14 @@
+
+ import pytest
+
+-from lcitool.inventory import Inventory
+-
+-inventory = Inventory()
+-ALL_TARGETS = sorted(inventory.targets)
++from conftest import ALL_TARGETS
+
+
+ @pytest.mark.parametrize("target", ALL_TARGETS)
+-def test_group_vars(target):
++def test_group_vars(targets, target):
+ """Check selected group_vars fields for correctness."""
+
+- facts = inventory.target_facts[target]
++ facts = targets.target_facts[target]
+ split = target.split('-', maxsplit=1)
+ target_os = split[0]
+ target_version = split[1].replace("-", "")
+diff --git a/tests/lcitool/mappings.yml b/tests/lcitool/mappings.yml
+new file mode 100644
+index 0000000000..4b4b44adf1
+--- /dev/null
++++ b/tests/lcitool/mappings.yml
+@@ -0,0 +1,60 @@
++mappings:
++ flake8:
++ OpenSUSELeap153:
++
++ meson:
++ OpenSUSELeap153:
++
++ python3:
++ OpenSUSELeap153: python39-base
++
++ python3-PyYAML:
++ OpenSUSELeap153:
++
++ python3-devel:
++ OpenSUSELeap153: python39-devel
++
++ python3-docutils:
++ OpenSUSELeap153:
++
++ python3-numpy:
++ OpenSUSELeap153:
++
++ python3-opencv:
++ OpenSUSELeap153:
++
++ python3-pillow:
++ OpenSUSELeap153:
++
++ python3-pip:
++ OpenSUSELeap153: python39-pip
++
++ python3-pillow:
++ OpenSUSELeap153:
++
++ python3-selinux:
++ OpenSUSELeap153:
++
++ python3-setuptools:
++ OpenSUSELeap153: python39-setuptools
++
++ python3-sphinx:
++ OpenSUSELeap153:
++
++ python3-sphinx-rtd-theme:
++ OpenSUSELeap153:
++
++ python3-venv:
++ OpenSUSELeap153: python39-base
++
++ python3-wheel:
++ OpenSUSELeap153: python39-pip
++
++pypi_mappings:
++ # Request more recent version
++ meson:
++ default: meson==0.63.2
++
++ # Drop packages that need devel headers
++ python3-numpy:
++ OpenSUSELeap153:
+diff --git a/tests/lcitool/refresh b/tests/lcitool/refresh
+index fa966e4009..7a4cd6fd32 100755
+--- a/tests/lcitool/refresh
++++ b/tests/lcitool/refresh
+@@ -108,10 +108,10 @@ try:
+ # Standard native builds
+ #
+ generate_dockerfile("alpine", "alpine-316")
+- generate_dockerfile("centos8", "centos-stream-8")
++ generate_dockerfile("centos9", "centos-stream-9")
+ generate_dockerfile("debian-amd64", "debian-11",
+ trailer="".join(debian11_extras))
+- generate_dockerfile("fedora", "fedora-35")
++ generate_dockerfile("fedora", "fedora-37")
+ generate_dockerfile("opensuse-leap", "opensuse-leap-153")
+ generate_dockerfile("ubuntu2004", "ubuntu-2004",
+ trailer="".join(ubuntu2004_tsanhack))
+@@ -161,12 +161,12 @@ try:
+ trailer=cross_build("s390x-linux-gnu-",
+ "s390x-softmmu,s390x-linux-user"))
+
+- generate_dockerfile("fedora-win32-cross", "fedora-35",
++ generate_dockerfile("fedora-win32-cross", "fedora-37",
+ cross="mingw32",
+ trailer=cross_build("i686-w64-mingw32-",
+ "i386-softmmu"))
+
+- generate_dockerfile("fedora-win64-cross", "fedora-35",
++ generate_dockerfile("fedora-win64-cross", "fedora-37",
+ cross="mingw64",
+ trailer=cross_build("x86_64-w64-mingw32-",
+ "x86_64-softmmu"))
+diff --git a/tests/lcitool/targets/centos-stream-8.yml b/tests/lcitool/targets/centos-stream-8.yml
+new file mode 100644
+index 0000000000..6b11160fd1
+--- /dev/null
++++ b/tests/lcitool/targets/centos-stream-8.yml
+@@ -0,0 +1,3 @@
++paths:
++ pip3: /usr/bin/pip3.8
++ python: /usr/bin/python3.8
+diff --git a/tests/lcitool/targets/opensuse-leap-153.yml b/tests/lcitool/targets/opensuse-leap-153.yml
+new file mode 100644
+index 0000000000..683016e007
+--- /dev/null
++++ b/tests/lcitool/targets/opensuse-leap-153.yml
+@@ -0,0 +1,3 @@
++paths:
++ pip3: /usr/bin/pip3.9
++ python: /usr/bin/python3.9
+diff --git a/tests/qemu-iotests/061 b/tests/qemu-iotests/061
+index 509ad247cd..168a5831dd 100755
+--- a/tests/qemu-iotests/061
++++ b/tests/qemu-iotests/061
+@@ -326,12 +326,14 @@ $QEMU_IMG amend -o "data_file=foo" "$TEST_IMG"
+ echo
+ _make_test_img -o "compat=1.1,data_file=$TEST_IMG.data" 64M
+ $QEMU_IMG amend -o "data_file=foo" "$TEST_IMG"
+-_img_info --format-specific
++$QEMU_IO -c "read 0 4k" "$TEST_IMG" 2>&1 | _filter_testdir | _filter_imgfmt
++$QEMU_IO -c "open -o data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG" -c "read 0 4k" | _filter_qemu_io
+ TEST_IMG="data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG" _img_info --format-specific --image-opts
+
+ echo
+ $QEMU_IMG amend -o "data_file=" --image-opts "data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG"
+-_img_info --format-specific
++$QEMU_IO -c "read 0 4k" "$TEST_IMG" 2>&1 | _filter_testdir | _filter_imgfmt
++$QEMU_IO -c "open -o data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG" -c "read 0 4k" | _filter_qemu_io
+ TEST_IMG="data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG" _img_info --format-specific --image-opts
+
+ echo
+diff --git a/tests/qemu-iotests/061.out b/tests/qemu-iotests/061.out
+index 139fc68177..24c33add7c 100644
+--- a/tests/qemu-iotests/061.out
++++ b/tests/qemu-iotests/061.out
+@@ -545,7 +545,9 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
+ qemu-img: data-file can only be set for images that use an external data file
+
+ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 data_file=TEST_DIR/t.IMGFMT.data
+-qemu-img: Could not open 'TEST_DIR/t.IMGFMT': Could not open 'foo': No such file or directory
++qemu-io: can't open device TEST_DIR/t.IMGFMT: Could not open 'foo': No such file or directory
++read 4096/4096 bytes at offset 0
++4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+ image: TEST_DIR/t.IMGFMT
+ file format: IMGFMT
+ virtual size: 64 MiB (67108864 bytes)
+@@ -560,7 +562,9 @@ Format specific information:
+ corrupt: false
+ extended l2: false
+
+-qemu-img: Could not open 'TEST_DIR/t.IMGFMT': 'data-file' is required for this image
++qemu-io: can't open device TEST_DIR/t.IMGFMT: 'data-file' is required for this image
++read 4096/4096 bytes at offset 0
++4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+ image: TEST_DIR/t.IMGFMT
+ file format: IMGFMT
+ virtual size: 64 MiB (67108864 bytes)
+diff --git a/tests/qemu-iotests/244 b/tests/qemu-iotests/244
+index 3e61fa25bb..bb9cc6512f 100755
+--- a/tests/qemu-iotests/244
++++ b/tests/qemu-iotests/244
+@@ -215,9 +215,22 @@ $QEMU_IMG convert -f $IMGFMT -O $IMGFMT -n -C "$TEST_IMG.src" "$TEST_IMG"
+ $QEMU_IMG compare -f $IMGFMT -F $IMGFMT "$TEST_IMG.src" "$TEST_IMG"
+
+ # blkdebug doesn't support copy offloading, so this tests the error path
+-$QEMU_IMG amend -f $IMGFMT -o "data_file=blkdebug::$TEST_IMG.data" "$TEST_IMG"
+-$QEMU_IMG convert -f $IMGFMT -O $IMGFMT -n -C "$TEST_IMG.src" "$TEST_IMG"
+-$QEMU_IMG compare -f $IMGFMT -F $IMGFMT "$TEST_IMG.src" "$TEST_IMG"
++test_img_with_blkdebug="json:{
++ 'driver': 'qcow2',
++ 'file': {
++ 'driver': 'file',
++ 'filename': '$TEST_IMG'
++ },
++ 'data-file': {
++ 'driver': 'blkdebug',
++ 'image': {
++ 'driver': 'file',
++ 'filename': '$TEST_IMG.data'
++ }
++ }
++}"
++$QEMU_IMG convert -f $IMGFMT -O $IMGFMT -n -C "$TEST_IMG.src" "$test_img_with_blkdebug"
++$QEMU_IMG compare -f $IMGFMT -F $IMGFMT "$TEST_IMG.src" "$test_img_with_blkdebug"
+
+ echo
+ echo "=== Flushing should flush the data file ==="
+diff --git a/tests/qemu-iotests/270 b/tests/qemu-iotests/270
+index 74352342db..c37b674aa2 100755
+--- a/tests/qemu-iotests/270
++++ b/tests/qemu-iotests/270
+@@ -60,8 +60,16 @@ _make_test_img -o cluster_size=2M,data_file="$TEST_IMG.orig" \
+ # "write" 2G of data without using any space.
+ # (qemu-img create does not like it, though, because null-co does not
+ # support image creation.)
+-$QEMU_IMG amend -o data_file="json:{'driver':'null-co',,'size':'4294967296'}" \
+- "$TEST_IMG"
++test_img_with_null_data="json:{
++ 'driver': '$IMGFMT',
++ 'file': {
++ 'filename': '$TEST_IMG'
++ },
++ 'data-file': {
++ 'driver': 'null-co',
++ 'size':'4294967296'
++ }
++}"
+
+ # This gives us a range of:
+ # 2^31 - 512 + 768 - 1 = 2^31 + 255 > 2^31
+@@ -74,7 +82,7 @@ $QEMU_IMG amend -o data_file="json:{'driver':'null-co',,'size':'4294967296'}" \
+ # on L2 boundaries, we need large L2 tables; hence the cluster size of
+ # 2 MB. (Anything from 256 kB should work, though, because then one L2
+ # table covers 8 GB.)
+-$QEMU_IO -c "write 768 $((2 ** 31 - 512))" "$TEST_IMG" | _filter_qemu_io
++$QEMU_IO -c "write 768 $((2 ** 31 - 512))" "$test_img_with_null_data" | _filter_qemu_io
+
+ _check_test_img
+
+diff --git a/tests/vm/centos b/tests/vm/centos
+index 097a9ca14d..d25c8f8b5b 100755
+--- a/tests/vm/centos
++++ b/tests/vm/centos
+@@ -26,8 +26,8 @@ class CentosVM(basevm.BaseVM):
+ export SRC_ARCHIVE=/dev/vdb;
+ sudo chmod a+r $SRC_ARCHIVE;
+ tar -xf $SRC_ARCHIVE;
+- make docker-test-block@centos8 {verbose} J={jobs} NETWORK=1;
+- make docker-test-quick@centos8 {verbose} J={jobs} NETWORK=1;
++ make docker-test-block@centos9 {verbose} J={jobs} NETWORK=1;
++ make docker-test-quick@centos9 {verbose} J={jobs} NETWORK=1;
+ """
+
+ def build_image(self, img):
diff --git a/debian/patches/v7.2.14.diff b/debian/patches/v7.2.14.diff
new file mode 100644
index 00000000..d8ad312d
--- /dev/null
+++ b/debian/patches/v7.2.14.diff
@@ -0,0 +1,3173 @@
+Subject: v7.2.14
+Date: Wed Sep 18 19:14:56 2024 +0300
+From: Michael Tokarev <mjt@tls.msk.ru>
+Forwarded: not-needed
+
+This is a difference between upstream qemu v7.2.13
+and upstream qemu v7.2.14.
+
+ .gitlab-ci.d/container-cross.yml | 6 -
+ .gitlab-ci.d/crossbuilds.yml | 14 -
+ .gitlab-ci.d/custom-runners.yml | 2 +-
+ ...untu-20.04-s390x.yml => ubuntu-22.04-s390x.yml} | 28 +-
+ VERSION | 2 +-
+ block/blkio.c | 6 +-
+ block/monitor/block-hmp-cmds.c | 3 +-
+ block/vvfat.c | 27 +-
+ blockdev-nbd.c | 59 +-
+ chardev/char-win-stdio.c | 5 +
+ crypto/pbkdf-gcrypt.c | 2 +-
+ crypto/pbkdf-gnutls.c | 2 +-
+ crypto/pbkdf.c | 53 +-
+ crypto/tlscredspsk.c | 1 +
+ docs/sphinx/depfile.py | 2 +-
+ hw/arm/mps2-tz.c | 6 +-
+ hw/char/bcm2835_aux.c | 2 +-
+ hw/core/ptimer.c | 4 +-
+ hw/cxl/cxl-host.c | 3 +-
+ hw/display/vhost-user-gpu.c | 2 +-
+ hw/i386/amd_iommu.c | 8 +-
+ hw/i386/intel_iommu_internal.h | 2 +-
+ hw/i386/sgx.c | 6 +-
+ hw/intc/arm_gic.c | 11 +-
+ hw/intc/loongarch_ipi.c | 9 +-
+ hw/misc/bcm2835_property.c | 27 +-
+ hw/net/virtio-net.c | 31 +-
+ hw/nvme/ctrl.c | 1 +
+ hw/sd/sdhci.c | 1 +
+ hw/virtio/virtio.c | 64 +-
+ include/block/nbd.h | 18 +-
+ include/exec/ramlist.h | 1 +
+ include/hw/virtio/virtio.h | 27 +-
+ meson.build | 4 +
+ nbd/server.c | 46 +-
+ nbd/trace-events | 1 +
+ qapi/block-export.json | 4 +-
+ qapi/qom.json | 3 +-
+ qemu-nbd.c | 4 +-
+ softmmu/physmem.c | 35 +-
+ target/arm/helper-sme.h | 2 +-
+ target/arm/helper.c | 2 +-
+ target/arm/sme_helper.c | 49 +-
+ target/arm/translate-sme.c | 43 +-
+ target/arm/translate-sve.c | 18 +-
+ target/i386/tcg/decode-new.c.inc | 5 +-
+ target/rx/translate.c | 3 +-
+ tests/docker/dockerfiles/debian-armel-cross.docker | 170 -----
+ tests/lcitool/refresh | 5 -
+ tests/qemu-iotests/check | 2 +-
+ tests/qemu-iotests/fat16.py | 690 +++++++++++++++++++++
+ tests/qemu-iotests/testenv.py | 2 +-
+ tests/qemu-iotests/tests/vvfat | 485 +++++++++++++++
+ tests/qemu-iotests/tests/vvfat.out | 5 +
+ tests/unit/ptimer-test.c | 33 +
+ util/async.c | 2 +-
+ util/module.c | 2 +-
+ 57 files changed, 1683 insertions(+), 367 deletions(-)
+
+diff --git a/.gitlab-ci.d/container-cross.yml b/.gitlab-ci.d/container-cross.yml
+index 24343192ac..f4c8642f5a 100644
+--- a/.gitlab-ci.d/container-cross.yml
++++ b/.gitlab-ci.d/container-cross.yml
+@@ -22,12 +22,6 @@ arm64-debian-cross-container:
+ variables:
+ NAME: debian-arm64-cross
+
+-armel-debian-cross-container:
+- extends: .container_job_template
+- stage: containers
+- variables:
+- NAME: debian-armel-cross
+-
+ armhf-debian-cross-container:
+ extends: .container_job_template
+ stage: containers
+diff --git a/.gitlab-ci.d/crossbuilds.yml b/.gitlab-ci.d/crossbuilds.yml
+index c4cd96433d..ba2971ec96 100644
+--- a/.gitlab-ci.d/crossbuilds.yml
++++ b/.gitlab-ci.d/crossbuilds.yml
+@@ -1,20 +1,6 @@
+ include:
+ - local: '/.gitlab-ci.d/crossbuild-template.yml'
+
+-cross-armel-system:
+- extends: .cross_system_build_job
+- needs:
+- job: armel-debian-cross-container
+- variables:
+- IMAGE: debian-armel-cross
+-
+-cross-armel-user:
+- extends: .cross_user_build_job
+- needs:
+- job: armel-debian-cross-container
+- variables:
+- IMAGE: debian-armel-cross
+-
+ cross-armhf-system:
+ extends: .cross_system_build_job
+ needs:
+diff --git a/.gitlab-ci.d/custom-runners.yml b/.gitlab-ci.d/custom-runners.yml
+index 97f99e29c2..94414457f1 100644
+--- a/.gitlab-ci.d/custom-runners.yml
++++ b/.gitlab-ci.d/custom-runners.yml
+@@ -14,7 +14,7 @@ variables:
+ GIT_STRATEGY: clone
+
+ include:
+- - local: '/.gitlab-ci.d/custom-runners/ubuntu-20.04-s390x.yml'
++ - local: '/.gitlab-ci.d/custom-runners/ubuntu-22.04-s390x.yml'
+ - local: '/.gitlab-ci.d/custom-runners/ubuntu-22.04-aarch64.yml'
+ - local: '/.gitlab-ci.d/custom-runners/ubuntu-22.04-aarch32.yml'
+ - local: '/.gitlab-ci.d/custom-runners/centos-stream-8-x86_64.yml'
+diff --git a/.gitlab-ci.d/custom-runners/ubuntu-20.04-s390x.yml b/.gitlab-ci.d/custom-runners/ubuntu-22.04-s390x.yml
+similarity index 89%
+rename from .gitlab-ci.d/custom-runners/ubuntu-20.04-s390x.yml
+rename to .gitlab-ci.d/custom-runners/ubuntu-22.04-s390x.yml
+index 0c835939db..12c6e21119 100644
+--- a/.gitlab-ci.d/custom-runners/ubuntu-20.04-s390x.yml
++++ b/.gitlab-ci.d/custom-runners/ubuntu-22.04-s390x.yml
+@@ -1,12 +1,12 @@
+-# All ubuntu-20.04 jobs should run successfully in an environment
++# All ubuntu-22.04 jobs should run successfully in an environment
+ # setup by the scripts/ci/setup/build-environment.yml task
+-# "Install basic packages to build QEMU on Ubuntu 20.04/20.04"
++# "Install basic packages to build QEMU on Ubuntu 22.04"
+
+-ubuntu-20.04-s390x-all-linux-static:
++ubuntu-22.04-s390x-all-linux-static:
+ needs: []
+ stage: build
+ tags:
+- - ubuntu_20.04
++ - ubuntu_22.04
+ - s390x
+ rules:
+ - if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
+@@ -24,11 +24,11 @@ ubuntu-20.04-s390x-all-linux-static:
+ - make --output-sync -j`nproc` check-tcg V=1
+ || { cat meson-logs/testlog.txt; exit 1; } ;
+
+-ubuntu-20.04-s390x-all:
++ubuntu-22.04-s390x-all:
+ needs: []
+ stage: build
+ tags:
+- - ubuntu_20.04
++ - ubuntu_22.04
+ - s390x
+ timeout: 75m
+ rules:
+@@ -43,11 +43,11 @@ ubuntu-20.04-s390x-all:
+ - make --output-sync -j`nproc` check V=1
+ || { cat meson-logs/testlog.txt; exit 1; } ;
+
+-ubuntu-20.04-s390x-alldbg:
++ubuntu-22.04-s390x-alldbg:
+ needs: []
+ stage: build
+ tags:
+- - ubuntu_20.04
++ - ubuntu_22.04
+ - s390x
+ rules:
+ - if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
+@@ -66,11 +66,11 @@ ubuntu-20.04-s390x-alldbg:
+ - make --output-sync -j`nproc` check V=1
+ || { cat meson-logs/testlog.txt; exit 1; } ;
+
+-ubuntu-20.04-s390x-clang:
++ubuntu-22.04-s390x-clang:
+ needs: []
+ stage: build
+ tags:
+- - ubuntu_20.04
++ - ubuntu_22.04
+ - s390x
+ rules:
+ - if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
+@@ -88,11 +88,11 @@ ubuntu-20.04-s390x-clang:
+ - make --output-sync -j`nproc` check V=1
+ || { cat meson-logs/testlog.txt; exit 1; } ;
+
+-ubuntu-20.04-s390x-tci:
++ubuntu-22.04-s390x-tci:
+ needs: []
+ stage: build
+ tags:
+- - ubuntu_20.04
++ - ubuntu_22.04
+ - s390x
+ rules:
+ - if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
+@@ -108,11 +108,11 @@ ubuntu-20.04-s390x-tci:
+ || { cat config.log meson-logs/meson-log.txt; exit 1; }
+ - make --output-sync -j`nproc`
+
+-ubuntu-20.04-s390x-notcg:
++ubuntu-22.04-s390x-notcg:
+ needs: []
+ stage: build
+ tags:
+- - ubuntu_20.04
++ - ubuntu_22.04
+ - s390x
+ rules:
+ - if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
+diff --git a/VERSION b/VERSION
+index c0d5d580b2..0755f425a1 100644
+--- a/VERSION
++++ b/VERSION
+@@ -1 +1 @@
+-7.2.13
++7.2.14
+diff --git a/block/blkio.c b/block/blkio.c
+index cb66160268..1fd47c434c 100644
+--- a/block/blkio.c
++++ b/block/blkio.c
+@@ -808,8 +808,10 @@ static int blkio_file_open(BlockDriverState *bs, QDict *options, int flags,
+ }
+
+ bs->supported_write_flags = BDRV_REQ_FUA | BDRV_REQ_REGISTERED_BUF;
+- bs->supported_zero_flags = BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP |
+- BDRV_REQ_NO_FALLBACK;
++ bs->supported_zero_flags = BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK;
++#ifdef CONFIG_BLKIO_WRITE_ZEROS_FUA
++ bs->supported_zero_flags |= BDRV_REQ_FUA;
++#endif
+
+ qemu_mutex_init(&s->blkio_lock);
+ qemu_co_mutex_init(&s->bounce_lock);
+diff --git a/block/monitor/block-hmp-cmds.c b/block/monitor/block-hmp-cmds.c
+index cf21b5e40a..d564d8d234 100644
+--- a/block/monitor/block-hmp-cmds.c
++++ b/block/monitor/block-hmp-cmds.c
+@@ -413,7 +413,8 @@ void hmp_nbd_server_start(Monitor *mon, const QDict *qdict)
+ goto exit;
+ }
+
+- nbd_server_start(addr, NULL, NULL, 0, &local_err);
++ nbd_server_start(addr, NULL, NULL, NBD_DEFAULT_MAX_CONNECTIONS,
++ &local_err);
+ qapi_free_SocketAddress(addr);
+ if (local_err != NULL) {
+ goto exit;
+diff --git a/block/vvfat.c b/block/vvfat.c
+index 723c91216e..eb844c3134 100644
+--- a/block/vvfat.c
++++ b/block/vvfat.c
+@@ -1368,8 +1368,9 @@ static int open_file(BDRVVVFATState* s,mapping_t* mapping)
+ return -1;
+ vvfat_close_current_file(s);
+ s->current_fd = fd;
+- s->current_mapping = mapping;
+ }
++
++ s->current_mapping = mapping;
+ return 0;
+ }
+
+@@ -1407,7 +1408,9 @@ read_cluster_directory:
+
+ assert(s->current_fd);
+
+- offset=s->cluster_size*(cluster_num-s->current_mapping->begin)+s->current_mapping->info.file.offset;
++ offset = s->cluster_size *
++ ((cluster_num - s->current_mapping->begin)
++ + s->current_mapping->info.file.offset);
+ if(lseek(s->current_fd, offset, SEEK_SET)!=offset)
+ return -3;
+ s->cluster=s->cluster_buffer;
+@@ -1877,7 +1880,6 @@ static uint32_t get_cluster_count_for_direntry(BDRVVVFATState* s,
+
+ uint32_t cluster_num = begin_of_direntry(direntry);
+ uint32_t offset = 0;
+- int first_mapping_index = -1;
+ mapping_t* mapping = NULL;
+ const char* basename2 = NULL;
+
+@@ -1928,8 +1930,9 @@ static uint32_t get_cluster_count_for_direntry(BDRVVVFATState* s,
+ (mapping->mode & MODE_DIRECTORY) == 0) {
+
+ /* was modified in qcow */
+- if (offset != mapping->info.file.offset + s->cluster_size
+- * (cluster_num - mapping->begin)) {
++ if (offset != s->cluster_size
++ * ((cluster_num - mapping->begin)
++ + mapping->info.file.offset)) {
+ /* offset of this cluster in file chain has changed */
+ abort();
+ copy_it = 1;
+@@ -1938,14 +1941,9 @@ static uint32_t get_cluster_count_for_direntry(BDRVVVFATState* s,
+
+ if (strcmp(basename, basename2))
+ copy_it = 1;
+- first_mapping_index = array_index(&(s->mapping), mapping);
+- }
+-
+- if (mapping->first_mapping_index != first_mapping_index
+- && mapping->info.file.offset > 0) {
+- abort();
+- copy_it = 1;
+ }
++ assert(mapping->first_mapping_index == -1
++ || mapping->info.file.offset > 0);
+
+ /* need to write out? */
+ if (!was_modified && is_file(direntry)) {
+@@ -2402,7 +2400,7 @@ static int commit_mappings(BDRVVVFATState* s,
+ (mapping->end - mapping->begin);
+ } else
+ next_mapping->info.file.offset = mapping->info.file.offset +
+- mapping->end - mapping->begin;
++ (mapping->end - mapping->begin);
+
+ mapping = next_mapping;
+ }
+@@ -2522,8 +2520,9 @@ static int commit_one_file(BDRVVVFATState* s,
+ return -1;
+ }
+
+- for (i = s->cluster_size; i < offset; i += s->cluster_size)
++ for (i = 0; i < offset; i += s->cluster_size) {
+ c = modified_fat_get(s, c);
++ }
+
+ fd = qemu_open_old(mapping->path, O_RDWR | O_CREAT | O_BINARY, 0666);
+ if (fd < 0) {
+diff --git a/blockdev-nbd.c b/blockdev-nbd.c
+index 012256bb02..e06c26b0af 100644
+--- a/blockdev-nbd.c
++++ b/blockdev-nbd.c
+@@ -21,12 +21,18 @@
+ #include "io/channel-socket.h"
+ #include "io/net-listener.h"
+
++typedef struct NBDConn {
++ QIOChannelSocket *cioc;
++ QLIST_ENTRY(NBDConn) next;
++} NBDConn;
++
+ typedef struct NBDServerData {
+ QIONetListener *listener;
+ QCryptoTLSCreds *tlscreds;
+ char *tlsauthz;
+ uint32_t max_connections;
+ uint32_t connections;
++ QLIST_HEAD(, NBDConn) conns;
+ } NBDServerData;
+
+ static NBDServerData *nbd_server;
+@@ -51,6 +57,14 @@ int nbd_server_max_connections(void)
+
+ static void nbd_blockdev_client_closed(NBDClient *client, bool ignored)
+ {
++ NBDConn *conn = nbd_client_owner(client);
++
++ assert(qemu_in_main_thread() && nbd_server);
++
++ object_unref(OBJECT(conn->cioc));
++ QLIST_REMOVE(conn, next);
++ g_free(conn);
++
+ nbd_client_put(client);
+ assert(nbd_server->connections > 0);
+ nbd_server->connections--;
+@@ -60,31 +74,56 @@ static void nbd_blockdev_client_closed(NBDClient *client, bool ignored)
+ static void nbd_accept(QIONetListener *listener, QIOChannelSocket *cioc,
+ gpointer opaque)
+ {
++ NBDConn *conn = g_new0(NBDConn, 1);
++
++ assert(qemu_in_main_thread() && nbd_server);
+ nbd_server->connections++;
++ object_ref(OBJECT(cioc));
++ conn->cioc = cioc;
++ QLIST_INSERT_HEAD(&nbd_server->conns, conn, next);
+ nbd_update_server_watch(nbd_server);
+
+ qio_channel_set_name(QIO_CHANNEL(cioc), "nbd-server");
+- nbd_client_new(cioc, nbd_server->tlscreds, nbd_server->tlsauthz,
+- nbd_blockdev_client_closed);
++ /* TODO - expose handshake timeout as QMP option */
++ nbd_client_new(cioc, NBD_DEFAULT_HANDSHAKE_MAX_SECS,
++ nbd_server->tlscreds, nbd_server->tlsauthz,
++ nbd_blockdev_client_closed, conn);
+ }
+
+ static void nbd_update_server_watch(NBDServerData *s)
+ {
+- if (!s->max_connections || s->connections < s->max_connections) {
+- qio_net_listener_set_client_func(s->listener, nbd_accept, NULL, NULL);
+- } else {
+- qio_net_listener_set_client_func(s->listener, NULL, NULL, NULL);
++ if (s->listener) {
++ if (!s->max_connections || s->connections < s->max_connections) {
++ qio_net_listener_set_client_func(s->listener, nbd_accept, NULL,
++ NULL);
++ } else {
++ qio_net_listener_set_client_func(s->listener, NULL, NULL, NULL);
++ }
+ }
+ }
+
+ static void nbd_server_free(NBDServerData *server)
+ {
++ NBDConn *conn, *tmp;
++
+ if (!server) {
+ return;
+ }
+
++ /*
++ * Forcefully close the listener socket, and any clients that have
++ * not yet disconnected on their own.
++ */
+ qio_net_listener_disconnect(server->listener);
+ object_unref(OBJECT(server->listener));
++ server->listener = NULL;
++ QLIST_FOREACH_SAFE(conn, &server->conns, next, tmp) {
++ qio_channel_shutdown(QIO_CHANNEL(conn->cioc), QIO_CHANNEL_SHUTDOWN_BOTH,
++ NULL);
++ }
++
++ AIO_WAIT_WHILE_UNLOCKED(NULL, server->connections > 0);
++
+ if (server->tlscreds) {
+ object_unref(OBJECT(server->tlscreds));
+ }
+@@ -168,6 +207,10 @@ void nbd_server_start(SocketAddress *addr, const char *tls_creds,
+
+ void nbd_server_start_options(NbdServerOptions *arg, Error **errp)
+ {
++ if (!arg->has_max_connections) {
++ arg->max_connections = NBD_DEFAULT_MAX_CONNECTIONS;
++ }
++
+ nbd_server_start(arg->addr, arg->tls_creds, arg->tls_authz,
+ arg->max_connections, errp);
+ }
+@@ -180,6 +223,10 @@ void qmp_nbd_server_start(SocketAddressLegacy *addr,
+ {
+ SocketAddress *addr_flat = socket_address_flatten(addr);
+
++ if (!has_max_connections) {
++ max_connections = NBD_DEFAULT_MAX_CONNECTIONS;
++ }
++
+ nbd_server_start(addr_flat, tls_creds, tls_authz, max_connections, errp);
+ qapi_free_SocketAddress(addr_flat);
+ }
+diff --git a/chardev/char-win-stdio.c b/chardev/char-win-stdio.c
+index eb830eabd9..6e59db84dd 100644
+--- a/chardev/char-win-stdio.c
++++ b/chardev/char-win-stdio.c
+@@ -33,6 +33,7 @@
+ struct WinStdioChardev {
+ Chardev parent;
+ HANDLE hStdIn;
++ DWORD dwOldMode;
+ HANDLE hInputReadyEvent;
+ HANDLE hInputDoneEvent;
+ HANDLE hInputThread;
+@@ -159,6 +160,7 @@ static void qemu_chr_open_stdio(Chardev *chr,
+ }
+
+ is_console = GetConsoleMode(stdio->hStdIn, &dwMode) != 0;
++ stdio->dwOldMode = dwMode;
+
+ if (is_console) {
+ if (qemu_add_wait_object(stdio->hStdIn,
+@@ -221,6 +223,9 @@ static void char_win_stdio_finalize(Object *obj)
+ {
+ WinStdioChardev *stdio = WIN_STDIO_CHARDEV(obj);
+
++ if (stdio->hStdIn != INVALID_HANDLE_VALUE) {
++ SetConsoleMode(stdio->hStdIn, stdio->dwOldMode);
++ }
+ if (stdio->hInputReadyEvent != INVALID_HANDLE_VALUE) {
+ CloseHandle(stdio->hInputReadyEvent);
+ }
+diff --git a/crypto/pbkdf-gcrypt.c b/crypto/pbkdf-gcrypt.c
+index a8d8e64f4d..bc0719c831 100644
+--- a/crypto/pbkdf-gcrypt.c
++++ b/crypto/pbkdf-gcrypt.c
+@@ -33,7 +33,7 @@ bool qcrypto_pbkdf2_supports(QCryptoHashAlgorithm hash)
+ case QCRYPTO_HASH_ALG_SHA384:
+ case QCRYPTO_HASH_ALG_SHA512:
+ case QCRYPTO_HASH_ALG_RIPEMD160:
+- return true;
++ return qcrypto_hash_supports(hash);
+ default:
+ return false;
+ }
+diff --git a/crypto/pbkdf-gnutls.c b/crypto/pbkdf-gnutls.c
+index 2dfbbd382c..911b565bea 100644
+--- a/crypto/pbkdf-gnutls.c
++++ b/crypto/pbkdf-gnutls.c
+@@ -33,7 +33,7 @@ bool qcrypto_pbkdf2_supports(QCryptoHashAlgorithm hash)
+ case QCRYPTO_HASH_ALG_SHA384:
+ case QCRYPTO_HASH_ALG_SHA512:
+ case QCRYPTO_HASH_ALG_RIPEMD160:
+- return true;
++ return qcrypto_hash_supports(hash);
+ default:
+ return false;
+ }
+diff --git a/crypto/pbkdf.c b/crypto/pbkdf.c
+index 8d198c152c..d1c06ef3ed 100644
+--- a/crypto/pbkdf.c
++++ b/crypto/pbkdf.c
+@@ -19,6 +19,7 @@
+ */
+
+ #include "qemu/osdep.h"
++#include "qemu/thread.h"
+ #include "qapi/error.h"
+ #include "crypto/pbkdf.h"
+ #ifndef _WIN32
+@@ -85,12 +86,28 @@ static int qcrypto_pbkdf2_get_thread_cpu(unsigned long long *val_ms,
+ #endif
+ }
+
+-uint64_t qcrypto_pbkdf2_count_iters(QCryptoHashAlgorithm hash,
+- const uint8_t *key, size_t nkey,
+- const uint8_t *salt, size_t nsalt,
+- size_t nout,
+- Error **errp)
++typedef struct CountItersData {
++ QCryptoHashAlgorithm hash;
++ const uint8_t *key;
++ size_t nkey;
++ const uint8_t *salt;
++ size_t nsalt;
++ size_t nout;
++ uint64_t iterations;
++ Error **errp;
++} CountItersData;
++
++static void *threaded_qcrypto_pbkdf2_count_iters(void *data)
+ {
++ CountItersData *iters_data = (CountItersData *) data;
++ QCryptoHashAlgorithm hash = iters_data->hash;
++ const uint8_t *key = iters_data->key;
++ size_t nkey = iters_data->nkey;
++ const uint8_t *salt = iters_data->salt;
++ size_t nsalt = iters_data->nsalt;
++ size_t nout = iters_data->nout;
++ Error **errp = iters_data->errp;
++
+ uint64_t ret = -1;
+ g_autofree uint8_t *out = g_new(uint8_t, nout);
+ uint64_t iterations = (1 << 15);
+@@ -114,7 +131,10 @@ uint64_t qcrypto_pbkdf2_count_iters(QCryptoHashAlgorithm hash,
+
+ delta_ms = end_ms - start_ms;
+
+- if (delta_ms > 500) {
++ if (delta_ms == 0) { /* sanity check */
++ error_setg(errp, "Unable to get accurate CPU usage");
++ goto cleanup;
++ } else if (delta_ms > 500) {
+ break;
+ } else if (delta_ms < 100) {
+ iterations = iterations * 10;
+@@ -129,5 +149,24 @@ uint64_t qcrypto_pbkdf2_count_iters(QCryptoHashAlgorithm hash,
+
+ cleanup:
+ memset(out, 0, nout);
+- return ret;
++ iters_data->iterations = ret;
++ return NULL;
++}
++
++uint64_t qcrypto_pbkdf2_count_iters(QCryptoHashAlgorithm hash,
++ const uint8_t *key, size_t nkey,
++ const uint8_t *salt, size_t nsalt,
++ size_t nout,
++ Error **errp)
++{
++ CountItersData data = {
++ hash, key, nkey, salt, nsalt, nout, 0, errp
++ };
++ QemuThread thread;
++
++ qemu_thread_create(&thread, "pbkdf2", threaded_qcrypto_pbkdf2_count_iters,
++ &data, QEMU_THREAD_JOINABLE);
++ qemu_thread_join(&thread);
++
++ return data.iterations;
+ }
+diff --git a/crypto/tlscredspsk.c b/crypto/tlscredspsk.c
+index 546cad1c5a..0d6b71a37c 100644
+--- a/crypto/tlscredspsk.c
++++ b/crypto/tlscredspsk.c
+@@ -243,6 +243,7 @@ qcrypto_tls_creds_psk_finalize(Object *obj)
+ QCryptoTLSCredsPSK *creds = QCRYPTO_TLS_CREDS_PSK(obj);
+
+ qcrypto_tls_creds_psk_unload(creds);
++ g_free(creds->username);
+ }
+
+ static void
+diff --git a/docs/sphinx/depfile.py b/docs/sphinx/depfile.py
+index afdcbcec6e..e74be6af98 100644
+--- a/docs/sphinx/depfile.py
++++ b/docs/sphinx/depfile.py
+@@ -19,7 +19,7 @@
+
+ def get_infiles(env):
+ for x in env.found_docs:
+- yield env.doc2path(x)
++ yield str(env.doc2path(x))
+ yield from ((os.path.join(env.srcdir, dep)
+ for dep in env.dependencies[x]))
+ for mod in sys.modules.values():
+diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
+index 284c09c91d..334cd836c3 100644
+--- a/hw/arm/mps2-tz.c
++++ b/hw/arm/mps2-tz.c
+@@ -427,7 +427,7 @@ static MemoryRegion *make_uart(MPS2TZMachineState *mms, void *opaque,
+ const char *name, hwaddr size,
+ const int *irqs, const PPCExtraData *extradata)
+ {
+- /* The irq[] array is tx, rx, combined, in that order */
++ /* The irq[] array is rx, tx, combined, in that order */
+ MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
+ CMSDKAPBUART *uart = opaque;
+ int i = uart - &mms->uart[0];
+@@ -439,8 +439,8 @@ static MemoryRegion *make_uart(MPS2TZMachineState *mms, void *opaque,
+ qdev_prop_set_uint32(DEVICE(uart), "pclk-frq", mmc->apb_periph_frq);
+ sysbus_realize(SYS_BUS_DEVICE(uart), &error_fatal);
+ s = SYS_BUS_DEVICE(uart);
+- sysbus_connect_irq(s, 0, get_sse_irq_in(mms, irqs[0]));
+- sysbus_connect_irq(s, 1, get_sse_irq_in(mms, irqs[1]));
++ sysbus_connect_irq(s, 0, get_sse_irq_in(mms, irqs[1]));
++ sysbus_connect_irq(s, 1, get_sse_irq_in(mms, irqs[0]));
+ sysbus_connect_irq(s, 2, qdev_get_gpio_in(orgate_dev, i * 2));
+ sysbus_connect_irq(s, 3, qdev_get_gpio_in(orgate_dev, i * 2 + 1));
+ sysbus_connect_irq(s, 4, get_sse_irq_in(mms, irqs[2]));
+diff --git a/hw/char/bcm2835_aux.c b/hw/char/bcm2835_aux.c
+index 96410b1ff8..0f1b28547e 100644
+--- a/hw/char/bcm2835_aux.c
++++ b/hw/char/bcm2835_aux.c
+@@ -138,7 +138,7 @@ static uint64_t bcm2835_aux_read(void *opaque, hwaddr offset, unsigned size)
+ res = 0x30e; /* space in the output buffer, empty tx fifo, idle tx/rx */
+ if (s->read_count > 0) {
+ res |= 0x1; /* data in input buffer */
+- assert(s->read_count < BCM2835_AUX_RX_FIFO_LEN);
++ assert(s->read_count <= BCM2835_AUX_RX_FIFO_LEN);
+ res |= ((uint32_t)s->read_count) << 16; /* rx fifo fill level */
+ }
+ return res;
+diff --git a/hw/core/ptimer.c b/hw/core/ptimer.c
+index eb5ba1aff7..f1f8109385 100644
+--- a/hw/core/ptimer.c
++++ b/hw/core/ptimer.c
+@@ -83,7 +83,7 @@ static void ptimer_reload(ptimer_state *s, int delta_adjust)
+ delta = s->delta = s->limit;
+ }
+
+- if (s->period == 0) {
++ if (s->period == 0 && s->period_frac == 0) {
+ if (!qtest_enabled()) {
+ fprintf(stderr, "Timer with period zero, disabling\n");
+ }
+@@ -309,7 +309,7 @@ void ptimer_run(ptimer_state *s, int oneshot)
+
+ assert(s->in_transaction);
+
+- if (was_disabled && s->period == 0) {
++ if (was_disabled && s->period == 0 && s->period_frac == 0) {
+ if (!qtest_enabled()) {
+ fprintf(stderr, "Timer with period zero, disabling\n");
+ }
+diff --git a/hw/cxl/cxl-host.c b/hw/cxl/cxl-host.c
+index 0fc3e57138..3253874322 100644
+--- a/hw/cxl/cxl-host.c
++++ b/hw/cxl/cxl-host.c
+@@ -282,7 +282,8 @@ static void machine_set_cxl(Object *obj, Visitor *v, const char *name,
+ static void machine_get_cfmw(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
+ {
+- CXLFixedMemoryWindowOptionsList **list = opaque;
++ CXLState *state = opaque;
++ CXLFixedMemoryWindowOptionsList **list = &state->cfmw_list;
+
+ visit_type_CXLFixedMemoryWindowOptionsList(v, name, list, errp);
+ }
+diff --git a/hw/display/vhost-user-gpu.c b/hw/display/vhost-user-gpu.c
+index 19c0e20103..7dee566cfe 100644
+--- a/hw/display/vhost-user-gpu.c
++++ b/hw/display/vhost-user-gpu.c
+@@ -335,7 +335,7 @@ vhost_user_gpu_chr_read(void *opaque)
+ }
+
+ msg->request = request;
+- msg->flags = size;
++ msg->flags = flags;
+ msg->size = size;
+
+ if (request == VHOST_USER_GPU_CURSOR_UPDATE ||
+diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c
+index a20f3e1d50..02597db1e1 100644
+--- a/hw/i386/amd_iommu.c
++++ b/hw/i386/amd_iommu.c
+@@ -346,12 +346,12 @@ static void amdvi_update_iotlb(AMDVIState *s, uint16_t devid,
+ uint64_t gpa, IOMMUTLBEntry to_cache,
+ uint16_t domid)
+ {
+- AMDVIIOTLBEntry *entry = g_new(AMDVIIOTLBEntry, 1);
+- uint64_t *key = g_new(uint64_t, 1);
+- uint64_t gfn = gpa >> AMDVI_PAGE_SHIFT_4K;
+-
+ /* don't cache erroneous translations */
+ if (to_cache.perm != IOMMU_NONE) {
++ AMDVIIOTLBEntry *entry = g_new(AMDVIIOTLBEntry, 1);
++ uint64_t *key = g_new(uint64_t, 1);
++ uint64_t gfn = gpa >> AMDVI_PAGE_SHIFT_4K;
++
+ trace_amdvi_cache_update(domid, PCI_BUS_NUM(devid), PCI_SLOT(devid),
+ PCI_FUNC(devid), gpa, to_cache.translated_addr);
+
+diff --git a/hw/i386/intel_iommu_internal.h b/hw/i386/intel_iommu_internal.h
+index e4d43ce48c..830e319e34 100644
+--- a/hw/i386/intel_iommu_internal.h
++++ b/hw/i386/intel_iommu_internal.h
+@@ -267,7 +267,7 @@
+ /* For the low 64-bit of 128-bit */
+ #define VTD_FRCD_FI(val) ((val) & ~0xfffULL)
+ #define VTD_FRCD_PV(val) (((val) & 0xffffULL) << 40)
+-#define VTD_FRCD_PP(val) (((val) & 0x1) << 31)
++#define VTD_FRCD_PP(val) (((val) & 0x1ULL) << 31)
+
+ /* DMA Remapping Fault Conditions */
+ typedef enum VTDFaultReason {
+diff --git a/hw/i386/sgx.c b/hw/i386/sgx.c
+index 09d9c7c73d..f64987c6dd 100644
+--- a/hw/i386/sgx.c
++++ b/hw/i386/sgx.c
+@@ -268,10 +268,12 @@ void hmp_info_sgx(Monitor *mon, const QDict *qdict)
+
+ bool sgx_epc_get_section(int section_nr, uint64_t *addr, uint64_t *size)
+ {
+- PCMachineState *pcms = PC_MACHINE(qdev_get_machine());
++ PCMachineState *pcms =
++ (PCMachineState *)object_dynamic_cast(qdev_get_machine(),
++ TYPE_PC_MACHINE);
+ SGXEPCDevice *epc;
+
+- if (pcms->sgx_epc.size == 0 || pcms->sgx_epc.nr_sections <= section_nr) {
++ if (!pcms || pcms->sgx_epc.size == 0 || pcms->sgx_epc.nr_sections <= section_nr) {
+ return true;
+ }
+
+diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c
+index 47f01e45e3..b8a4364b7f 100644
+--- a/hw/intc/arm_gic.c
++++ b/hw/intc/arm_gic.c
+@@ -1263,9 +1263,14 @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
+ trace_gic_enable_irq(irq + i);
+ }
+ GIC_DIST_SET_ENABLED(irq + i, cm);
+- /* If a raised level triggered IRQ enabled then mark
+- is as pending. */
+- if (GIC_DIST_TEST_LEVEL(irq + i, mask)
++ /*
++ * If a raised level triggered IRQ enabled then mark
++ * it as pending on 11MPCore. For other GIC revisions we
++ * handle the "level triggered and line asserted" check
++ * at the other end in gic_test_pending().
++ */
++ if (s->revision == REV_11MPCORE
++ && GIC_DIST_TEST_LEVEL(irq + i, mask)
+ && !GIC_DIST_TEST_EDGE_TRIGGER(irq + i)) {
+ DPRINTF("Set %d pending mask %x\n", irq + i, mask);
+ GIC_DIST_SET_PENDING(irq + i, mask);
+diff --git a/hw/intc/loongarch_ipi.c b/hw/intc/loongarch_ipi.c
+index 40e98af2ce..a4079e3732 100644
+--- a/hw/intc/loongarch_ipi.c
++++ b/hw/intc/loongarch_ipi.c
+@@ -12,6 +12,7 @@
+ #include "qapi/error.h"
+ #include "qemu/log.h"
+ #include "exec/address-spaces.h"
++#include "exec/memory.h"
+ #include "hw/loongarch/virt.h"
+ #include "migration/vmstate.h"
+ #include "target/loongarch/internals.h"
+@@ -59,8 +60,8 @@ static void send_ipi_data(CPULoongArchState *env, target_ulong val, target_ulong
+ * if the mask is 0, we need not to do anything.
+ */
+ if ((val >> 27) & 0xf) {
+- data = address_space_ldl(&env->address_space_iocsr, addr,
+- MEMTXATTRS_UNSPECIFIED, NULL);
++ data = address_space_ldl_le(&env->address_space_iocsr, addr,
++ MEMTXATTRS_UNSPECIFIED, NULL);
+ for (i = 0; i < 4; i++) {
+ /* get mask for byte writing */
+ if (val & (0x1 << (27 + i))) {
+@@ -71,8 +72,8 @@ static void send_ipi_data(CPULoongArchState *env, target_ulong val, target_ulong
+
+ data &= mask;
+ data |= (val >> 32) & ~mask;
+- address_space_stl(&env->address_space_iocsr, addr,
+- data, MEMTXATTRS_UNSPECIFIED, NULL);
++ address_space_stl_le(&env->address_space_iocsr, addr,
++ data, MEMTXATTRS_UNSPECIFIED, NULL);
+ }
+
+ static void ipi_send(uint64_t val)
+diff --git a/hw/misc/bcm2835_property.c b/hw/misc/bcm2835_property.c
+index de056ea2df..c7834d3fc7 100644
+--- a/hw/misc/bcm2835_property.c
++++ b/hw/misc/bcm2835_property.c
+@@ -26,8 +26,6 @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
+ uint32_t tot_len;
+ size_t resplen;
+ uint32_t tmp;
+- int n;
+- uint32_t offset, length, color;
+
+ /*
+ * Copy the current state of the framebuffer config; we will update
+@@ -258,18 +256,25 @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
+ resplen = 16;
+ break;
+ case 0x0004800b: /* Set palette */
+- offset = ldl_le_phys(&s->dma_as, value + 12);
+- length = ldl_le_phys(&s->dma_as, value + 16);
+- n = 0;
+- while (n < length - offset) {
+- color = ldl_le_phys(&s->dma_as, value + 20 + (n << 2));
+- stl_le_phys(&s->dma_as,
+- s->fbdev->vcram_base + ((offset + n) << 2), color);
+- n++;
++ {
++ uint32_t offset = ldl_le_phys(&s->dma_as, value + 12);
++ uint32_t length = ldl_le_phys(&s->dma_as, value + 16);
++ int resp;
++
++ if (offset > 255 || length < 1 || length > 256) {
++ resp = 1; /* invalid request */
++ } else {
++ for (uint32_t e = 0; e < length; e++) {
++ uint32_t color = ldl_le_phys(&s->dma_as, value + 20 + (e << 2));
++ stl_le_phys(&s->dma_as,
++ s->fbdev->vcram_base + ((offset + e) << 2), color);
++ }
++ resp = 0;
+ }
+- stl_le_phys(&s->dma_as, value + 12, 0);
++ stl_le_phys(&s->dma_as, value + 12, resp);
+ resplen = 4;
+ break;
++ }
+ case 0x00040013: /* Get number of displays */
+ stl_le_phys(&s->dma_as, value + 12, 1);
+ resplen = 4;
+diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
+index beadea5bf8..925a5c319e 100644
+--- a/hw/net/virtio-net.c
++++ b/hw/net/virtio-net.c
+@@ -1597,24 +1597,28 @@ static bool virtio_net_can_receive(NetClientState *nc)
+
+ static int virtio_net_has_buffers(VirtIONetQueue *q, int bufsize)
+ {
++ int opaque;
++ unsigned int in_bytes;
+ VirtIONet *n = q->n;
+- if (virtio_queue_empty(q->rx_vq) ||
+- (n->mergeable_rx_bufs &&
+- !virtqueue_avail_bytes(q->rx_vq, bufsize, 0))) {
+- virtio_queue_set_notification(q->rx_vq, 1);
+-
+- /* To avoid a race condition where the guest has made some buffers
+- * available after the above check but before notification was
+- * enabled, check for available buffers again.
+- */
+- if (virtio_queue_empty(q->rx_vq) ||
+- (n->mergeable_rx_bufs &&
+- !virtqueue_avail_bytes(q->rx_vq, bufsize, 0))) {
++
++ while (virtio_queue_empty(q->rx_vq) || n->mergeable_rx_bufs) {
++ opaque = virtqueue_get_avail_bytes(q->rx_vq, &in_bytes, NULL,
++ bufsize, 0);
++ /* Buffer is enough, disable notifiaction */
++ if (bufsize <= in_bytes) {
++ break;
++ }
++
++ if (virtio_queue_enable_notification_and_check(q->rx_vq, opaque)) {
++ /* Guest has added some buffers, try again */
++ continue;
++ } else {
+ return 0;
+ }
+ }
+
+ virtio_queue_set_notification(q->rx_vq, 0);
++
+ return 1;
+ }
+
+@@ -1846,7 +1850,8 @@ static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf,
+ if (!no_rss && n->rss_data.enabled && n->rss_data.enabled_software_rss) {
+ int index = virtio_net_process_rss(nc, buf, size);
+ if (index >= 0) {
+- NetClientState *nc2 = qemu_get_subqueue(n->nic, index);
++ NetClientState *nc2 =
++ qemu_get_subqueue(n->nic, index % n->curr_queue_pairs);
+ return virtio_net_receive_rcu(nc2, buf, size, true);
+ }
+ }
+diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c
+index 027d67f10b..ed56ad40b3 100644
+--- a/hw/nvme/ctrl.c
++++ b/hw/nvme/ctrl.c
+@@ -2465,6 +2465,7 @@ next:
+ done:
+ iocb->aiocb = NULL;
+ iocb->common.cb(iocb->common.opaque, iocb->ret);
++ g_free(iocb->range);
+ qemu_aio_unref(iocb);
+ }
+
+diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
+index abd503d168..c4a9b5956d 100644
+--- a/hw/sd/sdhci.c
++++ b/hw/sd/sdhci.c
+@@ -846,6 +846,7 @@ static void sdhci_do_adma(SDHCIState *s)
+ }
+ }
+ if (res != MEMTX_OK) {
++ s->data_count = 0;
+ if (s->errintstsen & SDHC_EISEN_ADMAERR) {
+ trace_sdhci_error("Set ADMA error flag");
+ s->errintsts |= SDHC_EIS_ADMAERR;
+diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
+index 1227e3d692..d0d13f4766 100644
+--- a/hw/virtio/virtio.c
++++ b/hw/virtio/virtio.c
+@@ -1153,6 +1153,60 @@ int virtio_queue_empty(VirtQueue *vq)
+ }
+ }
+
++static bool virtio_queue_split_poll(VirtQueue *vq, unsigned shadow_idx)
++{
++ if (unlikely(!vq->vring.avail)) {
++ return false;
++ }
++
++ return (uint16_t)shadow_idx != vring_avail_idx(vq);
++}
++
++static bool virtio_queue_packed_poll(VirtQueue *vq, unsigned shadow_idx)
++{
++ VRingPackedDesc desc;
++ VRingMemoryRegionCaches *caches;
++
++ if (unlikely(!vq->vring.desc)) {
++ return false;
++ }
++
++ caches = vring_get_region_caches(vq);
++ if (!caches) {
++ return false;
++ }
++
++ vring_packed_desc_read(vq->vdev, &desc, &caches->desc,
++ shadow_idx, true);
++
++ return is_desc_avail(desc.flags, vq->shadow_avail_wrap_counter);
++}
++
++static bool virtio_queue_poll(VirtQueue *vq, unsigned shadow_idx)
++{
++ if (virtio_device_disabled(vq->vdev)) {
++ return false;
++ }
++
++ if (virtio_vdev_has_feature(vq->vdev, VIRTIO_F_RING_PACKED)) {
++ return virtio_queue_packed_poll(vq, shadow_idx);
++ } else {
++ return virtio_queue_split_poll(vq, shadow_idx);
++ }
++}
++
++bool virtio_queue_enable_notification_and_check(VirtQueue *vq,
++ int opaque)
++{
++ virtio_queue_set_notification(vq, 1);
++
++ if (opaque >= 0) {
++ return virtio_queue_poll(vq, (unsigned)opaque);
++ } else {
++ return false;
++ }
++}
++
+ static void virtqueue_unmap_sg(VirtQueue *vq, const VirtQueueElement *elem,
+ unsigned int len)
+ {
+@@ -1727,9 +1781,9 @@ err:
+ goto done;
+ }
+
+-void virtqueue_get_avail_bytes(VirtQueue *vq, unsigned int *in_bytes,
+- unsigned int *out_bytes,
+- unsigned max_in_bytes, unsigned max_out_bytes)
++int virtqueue_get_avail_bytes(VirtQueue *vq, unsigned int *in_bytes,
++ unsigned int *out_bytes, unsigned max_in_bytes,
++ unsigned max_out_bytes)
+ {
+ uint16_t desc_size;
+ VRingMemoryRegionCaches *caches;
+@@ -1762,7 +1816,7 @@ void virtqueue_get_avail_bytes(VirtQueue *vq, unsigned int *in_bytes,
+ caches);
+ }
+
+- return;
++ return (int)vq->shadow_avail_idx;
+ err:
+ if (in_bytes) {
+ *in_bytes = 0;
+@@ -1770,6 +1824,8 @@ err:
+ if (out_bytes) {
+ *out_bytes = 0;
+ }
++
++ return -1;
+ }
+
+ int virtqueue_avail_bytes(VirtQueue *vq, unsigned int in_bytes,
+diff --git a/include/block/nbd.h b/include/block/nbd.h
+index 4ede3b2bd0..88be104e31 100644
+--- a/include/block/nbd.h
++++ b/include/block/nbd.h
+@@ -27,6 +27,19 @@
+
+ extern const BlockExportDriver blk_exp_nbd;
+
++/*
++ * NBD_DEFAULT_HANDSHAKE_MAX_SECS: Number of seconds in which client must
++ * succeed at NBD_OPT_GO before being forcefully dropped as too slow.
++ */
++#define NBD_DEFAULT_HANDSHAKE_MAX_SECS 10
++
++/*
++ * NBD_DEFAULT_MAX_CONNECTIONS: Number of client sockets to allow at
++ * once; must be large enough to allow a MULTI_CONN-aware client like
++ * nbdcopy to create its typical number of 8-16 sockets.
++ */
++#define NBD_DEFAULT_MAX_CONNECTIONS 100
++
+ /* Handshake phase structs - this struct is passed on the wire */
+
+ struct NBDOption {
+@@ -338,9 +351,12 @@ AioContext *nbd_export_aio_context(NBDExport *exp);
+ NBDExport *nbd_export_find(const char *name);
+
+ void nbd_client_new(QIOChannelSocket *sioc,
++ uint32_t handshake_max_secs,
+ QCryptoTLSCreds *tlscreds,
+ const char *tlsauthz,
+- void (*close_fn)(NBDClient *, bool));
++ void (*close_fn)(NBDClient *, bool),
++ void *owner);
++void *nbd_client_owner(NBDClient *client);
+ void nbd_client_get(NBDClient *client);
+ void nbd_client_put(NBDClient *client);
+
+diff --git a/include/exec/ramlist.h b/include/exec/ramlist.h
+index 2ad2a81acc..d9cfe530be 100644
+--- a/include/exec/ramlist.h
++++ b/include/exec/ramlist.h
+@@ -50,6 +50,7 @@ typedef struct RAMList {
+ /* RCU-enabled, writes protected by the ramlist lock. */
+ QLIST_HEAD(, RAMBlock) blocks;
+ DirtyMemoryBlocks *dirty_memory[DIRTY_MEMORY_NUM];
++ unsigned int num_dirty_blocks;
+ uint32_t version;
+ QLIST_HEAD(, RAMBlockNotifier) ramblock_notifiers;
+ } RAMList;
+diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
+index c1a7c9bd3b..ab3eb182f4 100644
+--- a/include/hw/virtio/virtio.h
++++ b/include/hw/virtio/virtio.h
+@@ -237,9 +237,13 @@ void qemu_put_virtqueue_element(VirtIODevice *vdev, QEMUFile *f,
+ VirtQueueElement *elem);
+ int virtqueue_avail_bytes(VirtQueue *vq, unsigned int in_bytes,
+ unsigned int out_bytes);
+-void virtqueue_get_avail_bytes(VirtQueue *vq, unsigned int *in_bytes,
+- unsigned int *out_bytes,
+- unsigned max_in_bytes, unsigned max_out_bytes);
++/**
++ * Return <0 on error or an opaque >=0 to pass to
++ * virtio_queue_enable_notification_and_check on success.
++ */
++int virtqueue_get_avail_bytes(VirtQueue *vq, unsigned int *in_bytes,
++ unsigned int *out_bytes, unsigned max_in_bytes,
++ unsigned max_out_bytes);
+
+ void virtio_notify_irqfd(VirtIODevice *vdev, VirtQueue *vq);
+ void virtio_notify(VirtIODevice *vdev, VirtQueue *vq);
+@@ -266,6 +270,15 @@ int virtio_queue_ready(VirtQueue *vq);
+
+ int virtio_queue_empty(VirtQueue *vq);
+
++/**
++ * Enable notification and check whether guest has added some
++ * buffers since last call to virtqueue_get_avail_bytes.
++ *
++ * @opaque: value returned from virtqueue_get_avail_bytes
++ */
++bool virtio_queue_enable_notification_and_check(VirtQueue *vq,
++ int opaque);
++
+ /* Host binding interface. */
+
+ uint32_t virtio_config_readb(VirtIODevice *vdev, uint32_t addr);
+@@ -425,9 +438,9 @@ static inline bool virtio_device_started(VirtIODevice *vdev, uint8_t status)
+ * @vdev - the VirtIO device
+ * @status - the devices status bits
+ *
+- * This is similar to virtio_device_started() but also encapsulates a
+- * check on the VM status which would prevent a device starting
+- * anyway.
++ * This is similar to virtio_device_started() but ignores vdev->started
++ * and also encapsulates a check on the VM status which would prevent a
++ * device from starting anyway.
+ */
+ static inline bool virtio_device_should_start(VirtIODevice *vdev, uint8_t status)
+ {
+@@ -435,7 +448,7 @@ static inline bool virtio_device_should_start(VirtIODevice *vdev, uint8_t status
+ return false;
+ }
+
+- return virtio_device_started(vdev, status);
++ return status & VIRTIO_CONFIG_S_DRIVER_OK;
+ }
+
+ static inline void virtio_set_started(VirtIODevice *vdev, bool started)
+diff --git a/meson.build b/meson.build
+index 787f91855e..16dc9627e0 100644
+--- a/meson.build
++++ b/meson.build
+@@ -1831,6 +1831,10 @@ config_host_data.set('CONFIG_LZO', lzo.found())
+ config_host_data.set('CONFIG_MPATH', mpathpersist.found())
+ config_host_data.set('CONFIG_MPATH_NEW_API', mpathpersist_new_api)
+ config_host_data.set('CONFIG_BLKIO', blkio.found())
++if blkio.found()
++ config_host_data.set('CONFIG_BLKIO_WRITE_ZEROS_FUA',
++ blkio.version().version_compare('>=1.4.0'))
++endif
+ config_host_data.set('CONFIG_CURL', curl.found())
+ config_host_data.set('CONFIG_CURSES', curses.found())
+ config_host_data.set('CONFIG_GBM', gbm.found())
+diff --git a/nbd/server.c b/nbd/server.c
+index 74edb2815b..bfa8d47dad 100644
+--- a/nbd/server.c
++++ b/nbd/server.c
+@@ -120,10 +120,12 @@ typedef struct NBDExportMetaContexts {
+ struct NBDClient {
+ int refcount;
+ void (*close_fn)(NBDClient *client, bool negotiated);
++ void *owner;
+
+ NBDExport *exp;
+ QCryptoTLSCreds *tlscreds;
+ char *tlsauthz;
++ uint32_t handshake_max_secs;
+ QIOChannelSocket *sioc; /* The underlying data channel */
+ QIOChannel *ioc; /* The current I/O channel which may differ (eg TLS) */
+
+@@ -2748,33 +2750,63 @@ static void nbd_client_receive_next_request(NBDClient *client)
+ }
+ }
+
++static void nbd_handshake_timer_cb(void *opaque)
++{
++ QIOChannel *ioc = opaque;
++
++ trace_nbd_handshake_timer_cb();
++ qio_channel_shutdown(ioc, QIO_CHANNEL_SHUTDOWN_BOTH, NULL);
++}
++
+ static coroutine_fn void nbd_co_client_start(void *opaque)
+ {
+ NBDClient *client = opaque;
+ Error *local_err = NULL;
++ QEMUTimer *handshake_timer = NULL;
+
+ qemu_co_mutex_init(&client->send_lock);
+
++ /*
++ * Create a timer to bound the time spent in negotiation. If the
++ * timer expires, it is likely nbd_negotiate will fail because the
++ * socket was shutdown.
++ */
++ if (client->handshake_max_secs > 0) {
++ handshake_timer = aio_timer_new(qemu_get_aio_context(),
++ QEMU_CLOCK_REALTIME,
++ SCALE_NS,
++ nbd_handshake_timer_cb,
++ client->sioc);
++ timer_mod(handshake_timer,
++ qemu_clock_get_ns(QEMU_CLOCK_REALTIME) +
++ client->handshake_max_secs * NANOSECONDS_PER_SECOND);
++ }
++
+ if (nbd_negotiate(client, &local_err)) {
+ if (local_err) {
+ error_report_err(local_err);
+ }
++ timer_free(handshake_timer);
+ client_close(client, false);
+ return;
+ }
+
++ timer_free(handshake_timer);
+ nbd_client_receive_next_request(client);
+ }
+
+ /*
+- * Create a new client listener using the given channel @sioc.
++ * Create a new client listener using the given channel @sioc and @owner.
+ * Begin servicing it in a coroutine. When the connection closes, call
+- * @close_fn with an indication of whether the client completed negotiation.
++ * @close_fn with an indication of whether the client completed negotiation
++ * within @handshake_max_secs seconds (0 for unbounded).
+ */
+ void nbd_client_new(QIOChannelSocket *sioc,
++ uint32_t handshake_max_secs,
+ QCryptoTLSCreds *tlscreds,
+ const char *tlsauthz,
+- void (*close_fn)(NBDClient *, bool))
++ void (*close_fn)(NBDClient *, bool),
++ void *owner)
+ {
+ NBDClient *client;
+ Coroutine *co;
+@@ -2786,12 +2818,20 @@ void nbd_client_new(QIOChannelSocket *sioc,
+ object_ref(OBJECT(client->tlscreds));
+ }
+ client->tlsauthz = g_strdup(tlsauthz);
++ client->handshake_max_secs = handshake_max_secs;
+ client->sioc = sioc;
+ object_ref(OBJECT(client->sioc));
+ client->ioc = QIO_CHANNEL(sioc);
+ object_ref(OBJECT(client->ioc));
+ client->close_fn = close_fn;
++ client->owner = owner;
+
+ co = qemu_coroutine_create(nbd_co_client_start, client);
+ qemu_coroutine_enter(co);
+ }
++
++void *
++nbd_client_owner(NBDClient *client)
++{
++ return client->owner;
++}
+diff --git a/nbd/trace-events b/nbd/trace-events
+index b7032ca277..675f880fa1 100644
+--- a/nbd/trace-events
++++ b/nbd/trace-events
+@@ -73,6 +73,7 @@ nbd_co_receive_request_decode_type(uint64_t handle, uint16_t type, const char *n
+ nbd_co_receive_request_payload_received(uint64_t handle, uint32_t len) "Payload received: handle = %" PRIu64 ", len = %" PRIu32
+ nbd_co_receive_align_compliance(const char *op, uint64_t from, uint32_t len, uint32_t align) "client sent non-compliant unaligned %s request: from=0x%" PRIx64 ", len=0x%" PRIx32 ", align=0x%" PRIx32
+ nbd_trip(void) "Reading request"
++nbd_handshake_timer_cb(void) "client took too long to negotiate"
+
+ # client-connection.c
+ nbd_connect_thread_sleep(uint64_t timeout) "timeout %" PRIu64
+diff --git a/qapi/block-export.json b/qapi/block-export.json
+index 4627bbc4e6..67d2337f91 100644
+--- a/qapi/block-export.json
++++ b/qapi/block-export.json
+@@ -24,7 +24,7 @@
+ # @max-connections: The maximum number of connections to allow at the same
+ # time, 0 for unlimited. Setting this to 1 also stops
+ # the server from advertising multiple client support
+-# (since 5.2; default: 0)
++# (since 5.2; default: 100)
+ #
+ # Since: 4.2
+ ##
+@@ -55,7 +55,7 @@
+ # @max-connections: The maximum number of connections to allow at the same
+ # time, 0 for unlimited. Setting this to 1 also stops
+ # the server from advertising multiple client support
+-# (since 5.2; default: 0).
++# (since 5.2; default: 100).
+ #
+ # Returns: error if the server is already running.
+ #
+diff --git a/qapi/qom.json b/qapi/qom.json
+index 30e76653ad..694bb81948 100644
+--- a/qapi/qom.json
++++ b/qapi/qom.json
+@@ -860,7 +860,8 @@
+ # @ObjectType:
+ #
+ # Features:
+-# @unstable: Member @x-remote-object is experimental.
++# @unstable: Members @x-remote-object and @x-vfio-user-server are
++# experimental.
+ #
+ # Since: 6.0
+ ##
+diff --git a/qemu-nbd.c b/qemu-nbd.c
+index f71f5125d8..16b220bdad 100644
+--- a/qemu-nbd.c
++++ b/qemu-nbd.c
+@@ -369,7 +369,9 @@ static void nbd_accept(QIONetListener *listener, QIOChannelSocket *cioc,
+
+ nb_fds++;
+ nbd_update_server_watch();
+- nbd_client_new(cioc, tlscreds, tlsauthz, nbd_client_closed);
++ /* TODO - expose handshake timeout as command line option */
++ nbd_client_new(cioc, NBD_DEFAULT_HANDSHAKE_MAX_SECS,
++ tlscreds, tlsauthz, nbd_client_closed, NULL);
+ }
+
+ static void nbd_update_server_watch(void)
+diff --git a/softmmu/physmem.c b/softmmu/physmem.c
+index 1b606a3002..5b176581f6 100644
+--- a/softmmu/physmem.c
++++ b/softmmu/physmem.c
+@@ -1660,18 +1660,6 @@ static ram_addr_t find_ram_offset(ram_addr_t size)
+ return offset;
+ }
+
+-static unsigned long last_ram_page(void)
+-{
+- RAMBlock *block;
+- ram_addr_t last = 0;
+-
+- RCU_READ_LOCK_GUARD();
+- RAMBLOCK_FOREACH(block) {
+- last = MAX(last, block->offset + block->max_length);
+- }
+- return last >> TARGET_PAGE_BITS;
+-}
+-
+ static void qemu_ram_setup_dump(void *addr, ram_addr_t size)
+ {
+ int ret;
+@@ -1919,13 +1907,11 @@ void qemu_ram_msync(RAMBlock *block, ram_addr_t start, ram_addr_t length)
+ }
+
+ /* Called with ram_list.mutex held */
+-static void dirty_memory_extend(ram_addr_t old_ram_size,
+- ram_addr_t new_ram_size)
++static void dirty_memory_extend(ram_addr_t new_ram_size)
+ {
+- ram_addr_t old_num_blocks = DIV_ROUND_UP(old_ram_size,
+- DIRTY_MEMORY_BLOCK_SIZE);
+- ram_addr_t new_num_blocks = DIV_ROUND_UP(new_ram_size,
+- DIRTY_MEMORY_BLOCK_SIZE);
++ unsigned int old_num_blocks = ram_list.num_dirty_blocks;
++ unsigned int new_num_blocks = DIV_ROUND_UP(new_ram_size,
++ DIRTY_MEMORY_BLOCK_SIZE);
+ int i;
+
+ /* Only need to extend if block count increased */
+@@ -1957,6 +1943,8 @@ static void dirty_memory_extend(ram_addr_t old_ram_size,
+ g_free_rcu(old_blocks, rcu);
+ }
+ }
++
++ ram_list.num_dirty_blocks = new_num_blocks;
+ }
+
+ static void ram_block_add(RAMBlock *new_block, Error **errp)
+@@ -1965,11 +1953,9 @@ static void ram_block_add(RAMBlock *new_block, Error **errp)
+ const bool shared = qemu_ram_is_shared(new_block);
+ RAMBlock *block;
+ RAMBlock *last_block = NULL;
+- ram_addr_t old_ram_size, new_ram_size;
++ ram_addr_t ram_size;
+ Error *err = NULL;
+
+- old_ram_size = last_ram_page();
+-
+ qemu_mutex_lock_ramlist();
+ new_block->offset = find_ram_offset(new_block->max_length);
+
+@@ -1997,11 +1983,8 @@ static void ram_block_add(RAMBlock *new_block, Error **errp)
+ }
+ }
+
+- new_ram_size = MAX(old_ram_size,
+- (new_block->offset + new_block->max_length) >> TARGET_PAGE_BITS);
+- if (new_ram_size > old_ram_size) {
+- dirty_memory_extend(old_ram_size, new_ram_size);
+- }
++ ram_size = (new_block->offset + new_block->max_length) >> TARGET_PAGE_BITS;
++ dirty_memory_extend(ram_size);
+ /* Keep the list sorted from biggest to smallest block. Unlike QTAILQ,
+ * QLIST (which has an RCU-friendly variant) does not have insertion at
+ * tail, so save the last element in last_block.
+diff --git a/target/arm/helper-sme.h b/target/arm/helper-sme.h
+index d2d544a696..d33fbcd8fd 100644
+--- a/target/arm/helper-sme.h
++++ b/target/arm/helper-sme.h
+@@ -122,7 +122,7 @@ DEF_HELPER_FLAGS_5(sme_addha_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
+ DEF_HELPER_FLAGS_5(sme_addva_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
+
+ DEF_HELPER_FLAGS_7(sme_fmopa_h, TCG_CALL_NO_RWG,
+- void, ptr, ptr, ptr, ptr, ptr, ptr, i32)
++ void, ptr, ptr, ptr, ptr, ptr, env, i32)
+ DEF_HELPER_FLAGS_7(sme_fmopa_s, TCG_CALL_NO_RWG,
+ void, ptr, ptr, ptr, ptr, ptr, ptr, i32)
+ DEF_HELPER_FLAGS_7(sme_fmopa_d, TCG_CALL_NO_RWG,
+diff --git a/target/arm/helper.c b/target/arm/helper.c
+index acc0470e86..5c22626b80 100644
+--- a/target/arm/helper.c
++++ b/target/arm/helper.c
+@@ -6335,7 +6335,7 @@ uint32_t sve_vqm1_for_el_sm(CPUARMState *env, int el, bool sm)
+ if (el <= 1 && !el_is_in_host(env, el)) {
+ len = MIN(len, 0xf & (uint32_t)cr[1]);
+ }
+- if (el <= 2 && arm_feature(env, ARM_FEATURE_EL2)) {
++ if (el <= 2 && arm_is_el2_enabled(env)) {
+ len = MIN(len, 0xf & (uint32_t)cr[2]);
+ }
+ if (arm_feature(env, ARM_FEATURE_EL3)) {
+diff --git a/target/arm/sme_helper.c b/target/arm/sme_helper.c
+index d592c78ec9..98a4840970 100644
+--- a/target/arm/sme_helper.c
++++ b/target/arm/sme_helper.c
+@@ -949,7 +949,7 @@ void HELPER(sme_fmopa_s)(void *vza, void *vzn, void *vzm, void *vpn,
+ if (pb & 1) {
+ uint32_t *a = vza_row + H1_4(col);
+ uint32_t *m = vzm + H1_4(col);
+- *a = float32_muladd(n, *m, *a, 0, vst);
++ *a = float32_muladd(n, *m, *a, 0, &fpst);
+ }
+ col += 4;
+ pb >>= 4;
+@@ -1009,12 +1009,23 @@ static inline uint32_t f16mop_adj_pair(uint32_t pair, uint32_t pg, uint32_t neg)
+ }
+
+ static float32 f16_dotadd(float32 sum, uint32_t e1, uint32_t e2,
+- float_status *s_std, float_status *s_odd)
++ float_status *s_f16, float_status *s_std,
++ float_status *s_odd)
+ {
+- float64 e1r = float16_to_float64(e1 & 0xffff, true, s_std);
+- float64 e1c = float16_to_float64(e1 >> 16, true, s_std);
+- float64 e2r = float16_to_float64(e2 & 0xffff, true, s_std);
+- float64 e2c = float16_to_float64(e2 >> 16, true, s_std);
++ /*
++ * We need three different float_status for different parts of this
++ * operation:
++ * - the input conversion of the float16 values must use the
++ * f16-specific float_status, so that the FPCR.FZ16 control is applied
++ * - operations on float32 including the final accumulation must use
++ * the normal float_status, so that FPCR.FZ is applied
++ * - we have pre-set-up copy of s_std which is set to round-to-odd,
++ * for the multiply (see below)
++ */
++ float64 e1r = float16_to_float64(e1 & 0xffff, true, s_f16);
++ float64 e1c = float16_to_float64(e1 >> 16, true, s_f16);
++ float64 e2r = float16_to_float64(e2 & 0xffff, true, s_f16);
++ float64 e2c = float16_to_float64(e2 >> 16, true, s_f16);
+ float64 t64;
+ float32 t32;
+
+@@ -1036,20 +1047,23 @@ static float32 f16_dotadd(float32 sum, uint32_t e1, uint32_t e2,
+ }
+
+ void HELPER(sme_fmopa_h)(void *vza, void *vzn, void *vzm, void *vpn,
+- void *vpm, void *vst, uint32_t desc)
++ void *vpm, CPUARMState *env, uint32_t desc)
+ {
+ intptr_t row, col, oprsz = simd_maxsz(desc);
+ uint32_t neg = simd_data(desc) * 0x80008000u;
+ uint16_t *pn = vpn, *pm = vpm;
+- float_status fpst_odd, fpst_std;
++ float_status fpst_odd, fpst_std, fpst_f16;
+
+ /*
+- * Make a copy of float_status because this operation does not
+- * update the cumulative fp exception status. It also produces
+- * default nans. Make a second copy with round-to-odd -- see above.
++ * Make copies of fp_status and fp_status_f16, because this operation
++ * does not update the cumulative fp exception status. It also
++ * produces default NaNs. We also need a second copy of fp_status with
++ * round-to-odd -- see above.
+ */
+- fpst_std = *(float_status *)vst;
++ fpst_f16 = env->vfp.fp_status_f16;
++ fpst_std = env->vfp.fp_status;
+ set_default_nan_mode(true, &fpst_std);
++ set_default_nan_mode(true, &fpst_f16);
+ fpst_odd = fpst_std;
+ set_float_rounding_mode(float_round_to_odd, &fpst_odd);
+
+@@ -1069,7 +1083,8 @@ void HELPER(sme_fmopa_h)(void *vza, void *vzn, void *vzm, void *vpn,
+ uint32_t m = *(uint32_t *)(vzm + H1_4(col));
+
+ m = f16mop_adj_pair(m, pcol, 0);
+- *a = f16_dotadd(*a, n, m, &fpst_std, &fpst_odd);
++ *a = f16_dotadd(*a, n, m,
++ &fpst_f16, &fpst_std, &fpst_odd);
+ }
+ col += 4;
+ pcol >>= 4;
+@@ -1167,10 +1182,10 @@ static uint64_t NAME(uint64_t n, uint64_t m, uint64_t a, uint8_t p, bool neg) \
+ uint64_t sum = 0; \
+ /* Apply P to N as a mask, making the inactive elements 0. */ \
+ n &= expand_pred_h(p); \
+- sum += (NTYPE)(n >> 0) * (MTYPE)(m >> 0); \
+- sum += (NTYPE)(n >> 16) * (MTYPE)(m >> 16); \
+- sum += (NTYPE)(n >> 32) * (MTYPE)(m >> 32); \
+- sum += (NTYPE)(n >> 48) * (MTYPE)(m >> 48); \
++ sum += (int64_t)(NTYPE)(n >> 0) * (MTYPE)(m >> 0); \
++ sum += (int64_t)(NTYPE)(n >> 16) * (MTYPE)(m >> 16); \
++ sum += (int64_t)(NTYPE)(n >> 32) * (MTYPE)(m >> 32); \
++ sum += (int64_t)(NTYPE)(n >> 48) * (MTYPE)(m >> 48); \
+ return neg ? a - sum : a + sum; \
+ }
+
+diff --git a/target/arm/translate-sme.c b/target/arm/translate-sme.c
+index 65f8495bdd..c864bd016c 100644
+--- a/target/arm/translate-sme.c
++++ b/target/arm/translate-sme.c
+@@ -56,7 +56,15 @@ static TCGv_ptr get_tile_rowcol(DisasContext *s, int esz, int rs,
+ /* Prepare a power-of-two modulo via extraction of @len bits. */
+ len = ctz32(streaming_vec_reg_size(s)) - esz;
+
+- if (vertical) {
++ if (!len) {
++ /*
++ * SVL is 128 and the element size is 128. There is exactly
++ * one 128x128 tile in the ZA storage, and so we calculate
++ * (Rs + imm) MOD 1, which is always 0. We need to special case
++ * this because TCG doesn't allow deposit ops with len 0.
++ */
++ tcg_gen_movi_i32(tmp, 0);
++ } else if (vertical) {
+ /*
+ * Compute the byte offset of the index within the tile:
+ * (index % (svl / size)) * size
+@@ -340,6 +348,7 @@ static bool do_outprod(DisasContext *s, arg_op *a, MemOp esz,
+ }
+
+ static bool do_outprod_fpst(DisasContext *s, arg_op *a, MemOp esz,
++ ARMFPStatusFlavour e_fpst,
+ gen_helper_gvec_5_ptr *fn)
+ {
+ int svl = streaming_vec_reg_size(s);
+@@ -355,7 +364,7 @@ static bool do_outprod_fpst(DisasContext *s, arg_op *a, MemOp esz,
+ zm = vec_full_reg_ptr(s, a->zm);
+ pn = pred_full_reg_ptr(s, a->pn);
+ pm = pred_full_reg_ptr(s, a->pm);
+- fpst = fpstatus_ptr(FPST_FPCR);
++ fpst = fpstatus_ptr(e_fpst);
+
+ fn(za, zn, zm, pn, pm, fpst, tcg_constant_i32(desc));
+
+@@ -367,9 +376,33 @@ static bool do_outprod_fpst(DisasContext *s, arg_op *a, MemOp esz,
+ return true;
+ }
+
+-TRANS_FEAT(FMOPA_h, aa64_sme, do_outprod_fpst, a, MO_32, gen_helper_sme_fmopa_h)
+-TRANS_FEAT(FMOPA_s, aa64_sme, do_outprod_fpst, a, MO_32, gen_helper_sme_fmopa_s)
+-TRANS_FEAT(FMOPA_d, aa64_sme_f64f64, do_outprod_fpst, a, MO_64, gen_helper_sme_fmopa_d)
++static bool do_outprod_env(DisasContext *s, arg_op *a, MemOp esz,
++ gen_helper_gvec_5_ptr *fn)
++{
++ int svl = streaming_vec_reg_size(s);
++ uint32_t desc = simd_desc(svl, svl, a->sub);
++ TCGv_ptr za, zn, zm, pn, pm;
++
++ if (!sme_smza_enabled_check(s)) {
++ return true;
++ }
++
++ za = get_tile(s, esz, a->zad);
++ zn = vec_full_reg_ptr(s, a->zn);
++ zm = vec_full_reg_ptr(s, a->zm);
++ pn = pred_full_reg_ptr(s, a->pn);
++ pm = pred_full_reg_ptr(s, a->pm);
++
++ fn(za, zn, zm, pn, pm, cpu_env, tcg_constant_i32(desc));
++ return true;
++}
++
++TRANS_FEAT(FMOPA_h, aa64_sme, do_outprod_env, a,
++ MO_32, gen_helper_sme_fmopa_h)
++TRANS_FEAT(FMOPA_s, aa64_sme, do_outprod_fpst, a,
++ MO_32, FPST_FPCR, gen_helper_sme_fmopa_s)
++TRANS_FEAT(FMOPA_d, aa64_sme_f64f64, do_outprod_fpst, a,
++ MO_64, FPST_FPCR, gen_helper_sme_fmopa_d)
+
+ /* TODO: FEAT_EBF16 */
+ TRANS_FEAT(BFMOPA, aa64_sme, do_outprod, a, MO_32, gen_helper_sme_bfmopa)
+diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
+index 7388e1dbc7..034e816491 100644
+--- a/target/arm/translate-sve.c
++++ b/target/arm/translate-sve.c
+@@ -61,13 +61,27 @@ static int tszimm_esz(DisasContext *s, int x)
+
+ static int tszimm_shr(DisasContext *s, int x)
+ {
+- return (16 << tszimm_esz(s, x)) - x;
++ /*
++ * We won't use the tszimm_shr() value if tszimm_esz() returns -1 (the
++ * trans function will check for esz < 0), so we can return any
++ * value we like from here in that case as long as we avoid UB.
++ */
++ int esz = tszimm_esz(s, x);
++ if (esz < 0) {
++ return esz;
++ }
++ return (16 << esz) - x;
+ }
+
+ /* See e.g. LSL (immediate, predicated). */
+ static int tszimm_shl(DisasContext *s, int x)
+ {
+- return x - (8 << tszimm_esz(s, x));
++ /* As with tszimm_shr(), value will be unused if esz < 0 */
++ int esz = tszimm_esz(s, x);
++ if (esz < 0) {
++ return esz;
++ }
++ return x - (8 << esz);
+ }
+
+ /* The SH bit is in bit 8. Extract the low 8 and shift. */
+diff --git a/target/i386/tcg/decode-new.c.inc b/target/i386/tcg/decode-new.c.inc
+index 1dfc368456..88de92ed16 100644
+--- a/target/i386/tcg/decode-new.c.inc
++++ b/target/i386/tcg/decode-new.c.inc
+@@ -1176,7 +1176,10 @@ static bool decode_op(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode,
+ op->unit = X86_OP_SSE;
+ }
+ get_reg:
+- op->n = ((get_modrm(s, env) >> 3) & 7) | REX_R(s);
++ op->n = ((get_modrm(s, env) >> 3) & 7);
++ if (op->unit != X86_OP_MMX) {
++ op->n |= REX_R(s);
++ }
+ break;
+
+ case X86_TYPE_E: /* ALU modrm operand */
+diff --git a/target/rx/translate.c b/target/rx/translate.c
+index 87a3f54adb..4233622c4e 100644
+--- a/target/rx/translate.c
++++ b/target/rx/translate.c
+@@ -83,7 +83,8 @@ static uint32_t decode_load_bytes(DisasContext *ctx, uint32_t insn,
+
+ static uint32_t li(DisasContext *ctx, int sz)
+ {
+- int32_t tmp, addr;
++ target_ulong addr;
++ uint32_t tmp;
+ CPURXState *env = ctx->env;
+ addr = ctx->base.pc_next;
+
+diff --git a/tests/docker/dockerfiles/debian-armel-cross.docker b/tests/docker/dockerfiles/debian-armel-cross.docker
+deleted file mode 100644
+index d5c08714e4..0000000000
+--- a/tests/docker/dockerfiles/debian-armel-cross.docker
++++ /dev/null
+@@ -1,170 +0,0 @@
+-# THIS FILE WAS AUTO-GENERATED
+-#
+-# $ lcitool dockerfile --layers all --cross armv6l debian-11 qemu
+-#
+-# https://gitlab.com/libvirt/libvirt-ci
+-
+-FROM docker.io/library/debian:11-slim
+-
+-RUN export DEBIAN_FRONTEND=noninteractive && \
+- apt-get update && \
+- apt-get install -y eatmydata && \
+- eatmydata apt-get dist-upgrade -y && \
+- eatmydata apt-get install --no-install-recommends -y \
+- bash \
+- bc \
+- bison \
+- bsdextrautils \
+- bzip2 \
+- ca-certificates \
+- ccache \
+- dbus \
+- debianutils \
+- diffutils \
+- exuberant-ctags \
+- findutils \
+- flex \
+- gcovr \
+- genisoimage \
+- gettext \
+- git \
+- hostname \
+- libglib2.0-dev \
+- libpcre2-dev \
+- libsndio-dev \
+- libspice-protocol-dev \
+- llvm \
+- locales \
+- make \
+- meson \
+- ncat \
+- ninja-build \
+- openssh-client \
+- perl-base \
+- pkgconf \
+- python3 \
+- python3-numpy \
+- python3-opencv \
+- python3-pillow \
+- python3-pip \
+- python3-sphinx \
+- python3-sphinx-rtd-theme \
+- python3-venv \
+- python3-yaml \
+- rpm2cpio \
+- sed \
+- sparse \
+- tar \
+- tesseract-ocr \
+- tesseract-ocr-eng \
+- texinfo && \
+- eatmydata apt-get autoremove -y && \
+- eatmydata apt-get autoclean -y && \
+- sed -Ei 's,^# (en_US\.UTF-8 .*)$,\1,' /etc/locale.gen && \
+- dpkg-reconfigure locales
+-
+-ENV CCACHE_WRAPPERSDIR "/usr/libexec/ccache-wrappers"
+-ENV LANG "en_US.UTF-8"
+-ENV MAKE "/usr/bin/make"
+-ENV NINJA "/usr/bin/ninja"
+-ENV PYTHON "/usr/bin/python3"
+-
+-RUN export DEBIAN_FRONTEND=noninteractive && \
+- dpkg --add-architecture armel && \
+- eatmydata apt-get update && \
+- eatmydata apt-get dist-upgrade -y && \
+- eatmydata apt-get install --no-install-recommends -y dpkg-dev && \
+- eatmydata apt-get install --no-install-recommends -y \
+- g++-arm-linux-gnueabi \
+- gcc-arm-linux-gnueabi \
+- libaio-dev:armel \
+- libasan5:armel \
+- libasound2-dev:armel \
+- libattr1-dev:armel \
+- libbpf-dev:armel \
+- libbrlapi-dev:armel \
+- libbz2-dev:armel \
+- libc6-dev:armel \
+- libcacard-dev:armel \
+- libcap-ng-dev:armel \
+- libcapstone-dev:armel \
+- libcmocka-dev:armel \
+- libcurl4-gnutls-dev:armel \
+- libdaxctl-dev:armel \
+- libdrm-dev:armel \
+- libepoxy-dev:armel \
+- libfdt-dev:armel \
+- libffi-dev:armel \
+- libfuse3-dev:armel \
+- libgbm-dev:armel \
+- libgcrypt20-dev:armel \
+- libglib2.0-dev:armel \
+- libglusterfs-dev:armel \
+- libgnutls28-dev:armel \
+- libgtk-3-dev:armel \
+- libibumad-dev:armel \
+- libibverbs-dev:armel \
+- libiscsi-dev:armel \
+- libjemalloc-dev:armel \
+- libjpeg62-turbo-dev:armel \
+- libjson-c-dev:armel \
+- liblttng-ust-dev:armel \
+- liblzo2-dev:armel \
+- libncursesw5-dev:armel \
+- libnfs-dev:armel \
+- libnuma-dev:armel \
+- libpam0g-dev:armel \
+- libpixman-1-dev:armel \
+- libpng-dev:armel \
+- libpulse-dev:armel \
+- librbd-dev:armel \
+- librdmacm-dev:armel \
+- libsasl2-dev:armel \
+- libsdl2-dev:armel \
+- libsdl2-image-dev:armel \
+- libseccomp-dev:armel \
+- libselinux1-dev:armel \
+- libslirp-dev:armel \
+- libsnappy-dev:armel \
+- libspice-server-dev:armel \
+- libssh-gcrypt-dev:armel \
+- libsystemd-dev:armel \
+- libtasn1-6-dev:armel \
+- libubsan1:armel \
+- libudev-dev:armel \
+- liburing-dev:armel \
+- libusb-1.0-0-dev:armel \
+- libusbredirhost-dev:armel \
+- libvdeplug-dev:armel \
+- libvirglrenderer-dev:armel \
+- libvte-2.91-dev:armel \
+- libzstd-dev:armel \
+- nettle-dev:armel \
+- systemtap-sdt-dev:armel \
+- xfslibs-dev:armel \
+- zlib1g-dev:armel && \
+- eatmydata apt-get autoremove -y && \
+- eatmydata apt-get autoclean -y && \
+- mkdir -p /usr/local/share/meson/cross && \
+- echo "[binaries]\n\
+-c = '/usr/bin/arm-linux-gnueabi-gcc'\n\
+-ar = '/usr/bin/arm-linux-gnueabi-gcc-ar'\n\
+-strip = '/usr/bin/arm-linux-gnueabi-strip'\n\
+-pkgconfig = '/usr/bin/arm-linux-gnueabi-pkg-config'\n\
+-\n\
+-[host_machine]\n\
+-system = 'linux'\n\
+-cpu_family = 'arm'\n\
+-cpu = 'arm'\n\
+-endian = 'little'" > /usr/local/share/meson/cross/arm-linux-gnueabi && \
+- dpkg-query --showformat '${Package}_${Version}_${Architecture}\n' --show > /packages.txt && \
+- mkdir -p /usr/libexec/ccache-wrappers && \
+- ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/arm-linux-gnueabi-c++ && \
+- ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/arm-linux-gnueabi-cc && \
+- ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/arm-linux-gnueabi-g++ && \
+- ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/arm-linux-gnueabi-gcc
+-
+-ENV ABI "arm-linux-gnueabi"
+-ENV MESON_OPTS "--cross-file=arm-linux-gnueabi"
+-ENV QEMU_CONFIGURE_OPTS --cross-prefix=arm-linux-gnueabi-
+-ENV DEF_TARGET_LIST arm-softmmu,arm-linux-user,armeb-linux-user
+diff --git a/tests/lcitool/refresh b/tests/lcitool/refresh
+index 7a4cd6fd32..6ef732521d 100755
+--- a/tests/lcitool/refresh
++++ b/tests/lcitool/refresh
+@@ -131,11 +131,6 @@ try:
+ trailer=cross_build("aarch64-linux-gnu-",
+ "aarch64-softmmu,aarch64-linux-user"))
+
+- generate_dockerfile("debian-armel-cross", "debian-11",
+- cross="armv6l",
+- trailer=cross_build("arm-linux-gnueabi-",
+- "arm-softmmu,arm-linux-user,armeb-linux-user"))
+-
+ generate_dockerfile("debian-armhf-cross", "debian-11",
+ cross="armv7l",
+ trailer=cross_build("arm-linux-gnueabihf-",
+diff --git a/tests/qemu-iotests/check b/tests/qemu-iotests/check
+index 75de1b4691..4da95cff2a 100755
+--- a/tests/qemu-iotests/check
++++ b/tests/qemu-iotests/check
+@@ -70,7 +70,7 @@ def make_argparser() -> argparse.ArgumentParser:
+ p.set_defaults(imgfmt='raw', imgproto='file')
+
+ format_list = ['raw', 'bochs', 'cloop', 'parallels', 'qcow', 'qcow2',
+- 'qed', 'vdi', 'vpc', 'vhdx', 'vmdk', 'luks', 'dmg']
++ 'qed', 'vdi', 'vpc', 'vhdx', 'vmdk', 'luks', 'dmg', 'vvfat']
+ g_fmt = p.add_argument_group(
+ ' image format options',
+ 'The following options set the IMGFMT environment variable. '
+diff --git a/tests/qemu-iotests/fat16.py b/tests/qemu-iotests/fat16.py
+new file mode 100644
+index 0000000000..7d2d052413
+--- /dev/null
++++ b/tests/qemu-iotests/fat16.py
+@@ -0,0 +1,690 @@
++# A simple FAT16 driver that is used to test the `vvfat` driver in QEMU.
++#
++# Copyright (C) 2024 Amjad Alsharafi <amjadsharafi10@gmail.com>
++#
++# This program is free software; you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation; either version 2 of the License, or
++# (at your option) any later version.
++#
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++# GNU General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program. If not, see <http://www.gnu.org/licenses/>.
++
++from typing import Callable, List, Optional, Protocol, Set
++import string
++
++SECTOR_SIZE = 512
++DIRENTRY_SIZE = 32
++ALLOWED_FILE_CHARS = set(
++ "!#$%&'()-@^_`{}~" + string.digits + string.ascii_uppercase
++)
++
++
++class MBR:
++ def __init__(self, data: bytes):
++ assert len(data) == 512
++ self.partition_table = []
++ for i in range(4):
++ partition = data[446 + i * 16 : 446 + (i + 1) * 16]
++ self.partition_table.append(
++ {
++ "status": partition[0],
++ "start_head": partition[1],
++ "start_sector": partition[2] & 0x3F,
++ "start_cylinder": ((partition[2] & 0xC0) << 2)
++ | partition[3],
++ "type": partition[4],
++ "end_head": partition[5],
++ "end_sector": partition[6] & 0x3F,
++ "end_cylinder": ((partition[6] & 0xC0) << 2)
++ | partition[7],
++ "start_lba": int.from_bytes(partition[8:12], "little"),
++ "size": int.from_bytes(partition[12:16], "little"),
++ }
++ )
++
++ def __str__(self):
++ return "\n".join(
++ [
++ f"{i}: {partition}"
++ for i, partition in enumerate(self.partition_table)
++ ]
++ )
++
++
++class FatBootSector:
++ # pylint: disable=too-many-instance-attributes
++ def __init__(self, data: bytes):
++ assert len(data) == 512
++ self.bytes_per_sector = int.from_bytes(data[11:13], "little")
++ self.sectors_per_cluster = data[13]
++ self.reserved_sectors = int.from_bytes(data[14:16], "little")
++ self.fat_count = data[16]
++ self.root_entries = int.from_bytes(data[17:19], "little")
++ total_sectors_16 = int.from_bytes(data[19:21], "little")
++ self.media_descriptor = data[21]
++ self.sectors_per_fat = int.from_bytes(data[22:24], "little")
++ self.sectors_per_track = int.from_bytes(data[24:26], "little")
++ self.heads = int.from_bytes(data[26:28], "little")
++ self.hidden_sectors = int.from_bytes(data[28:32], "little")
++ total_sectors_32 = int.from_bytes(data[32:36], "little")
++ assert (
++ total_sectors_16 == 0 or total_sectors_32 == 0
++ ), "Both total sectors (16 and 32) fields are non-zero"
++ self.total_sectors = total_sectors_16 or total_sectors_32
++ self.drive_number = data[36]
++ self.volume_id = int.from_bytes(data[39:43], "little")
++ self.volume_label = data[43:54].decode("ascii").strip()
++ self.fs_type = data[54:62].decode("ascii").strip()
++
++ def root_dir_start(self):
++ """
++ Calculate the start sector of the root directory.
++ """
++ return self.reserved_sectors + self.fat_count * self.sectors_per_fat
++
++ def root_dir_size(self):
++ """
++ Calculate the size of the root directory in sectors.
++ """
++ return (
++ self.root_entries * DIRENTRY_SIZE + self.bytes_per_sector - 1
++ ) // self.bytes_per_sector
++
++ def data_sector_start(self):
++ """
++ Calculate the start sector of the data region.
++ """
++ return self.root_dir_start() + self.root_dir_size()
++
++ def first_sector_of_cluster(self, cluster: int) -> int:
++ """
++ Calculate the first sector of the given cluster.
++ """
++ return (
++ self.data_sector_start() + (cluster - 2) * self.sectors_per_cluster
++ )
++
++ def cluster_bytes(self):
++ """
++ Calculate the number of bytes in a cluster.
++ """
++ return self.bytes_per_sector * self.sectors_per_cluster
++
++ def __str__(self):
++ return (
++ f"Bytes per sector: {self.bytes_per_sector}\n"
++ f"Sectors per cluster: {self.sectors_per_cluster}\n"
++ f"Reserved sectors: {self.reserved_sectors}\n"
++ f"FAT count: {self.fat_count}\n"
++ f"Root entries: {self.root_entries}\n"
++ f"Total sectors: {self.total_sectors}\n"
++ f"Media descriptor: {self.media_descriptor}\n"
++ f"Sectors per FAT: {self.sectors_per_fat}\n"
++ f"Sectors per track: {self.sectors_per_track}\n"
++ f"Heads: {self.heads}\n"
++ f"Hidden sectors: {self.hidden_sectors}\n"
++ f"Drive number: {self.drive_number}\n"
++ f"Volume ID: {self.volume_id}\n"
++ f"Volume label: {self.volume_label}\n"
++ f"FS type: {self.fs_type}\n"
++ )
++
++
++class FatDirectoryEntry:
++ # pylint: disable=too-many-instance-attributes
++ def __init__(self, data: bytes, sector: int, offset: int):
++ self.name = data[0:8].decode("ascii").strip()
++ self.ext = data[8:11].decode("ascii").strip()
++ self.attributes = data[11]
++ self.reserved = data[12]
++ self.create_time_tenth = data[13]
++ self.create_time = int.from_bytes(data[14:16], "little")
++ self.create_date = int.from_bytes(data[16:18], "little")
++ self.last_access_date = int.from_bytes(data[18:20], "little")
++ high_cluster = int.from_bytes(data[20:22], "little")
++ self.last_mod_time = int.from_bytes(data[22:24], "little")
++ self.last_mod_date = int.from_bytes(data[24:26], "little")
++ low_cluster = int.from_bytes(data[26:28], "little")
++ self.cluster = (high_cluster << 16) | low_cluster
++ self.size_bytes = int.from_bytes(data[28:32], "little")
++
++ # extra (to help write back to disk)
++ self.sector = sector
++ self.offset = offset
++
++ def as_bytes(self) -> bytes:
++ return (
++ self.name.ljust(8, " ").encode("ascii")
++ + self.ext.ljust(3, " ").encode("ascii")
++ + self.attributes.to_bytes(1, "little")
++ + self.reserved.to_bytes(1, "little")
++ + self.create_time_tenth.to_bytes(1, "little")
++ + self.create_time.to_bytes(2, "little")
++ + self.create_date.to_bytes(2, "little")
++ + self.last_access_date.to_bytes(2, "little")
++ + (self.cluster >> 16).to_bytes(2, "little")
++ + self.last_mod_time.to_bytes(2, "little")
++ + self.last_mod_date.to_bytes(2, "little")
++ + (self.cluster & 0xFFFF).to_bytes(2, "little")
++ + self.size_bytes.to_bytes(4, "little")
++ )
++
++ def whole_name(self):
++ if self.ext:
++ return f"{self.name}.{self.ext}"
++ else:
++ return self.name
++
++ def __str__(self):
++ return (
++ f"Name: {self.name}\n"
++ f"Ext: {self.ext}\n"
++ f"Attributes: {self.attributes}\n"
++ f"Reserved: {self.reserved}\n"
++ f"Create time tenth: {self.create_time_tenth}\n"
++ f"Create time: {self.create_time}\n"
++ f"Create date: {self.create_date}\n"
++ f"Last access date: {self.last_access_date}\n"
++ f"Last mod time: {self.last_mod_time}\n"
++ f"Last mod date: {self.last_mod_date}\n"
++ f"Cluster: {self.cluster}\n"
++ f"Size: {self.size_bytes}\n"
++ )
++
++ def __repr__(self):
++ # convert to dict
++ return str(vars(self))
++
++
++class SectorReader(Protocol):
++ def __call__(self, start_sector: int, num_sectors: int = 1) -> bytes: ...
++
++# pylint: disable=broad-exception-raised
++class Fat16:
++ def __init__(
++ self,
++ start_sector: int,
++ size: int,
++ sector_reader: SectorReader,
++ sector_writer: Callable[[int, bytes], None]
++ ):
++ self.start_sector = start_sector
++ self.size_in_sectors = size
++ self.sector_reader = sector_reader
++ self.sector_writer = sector_writer
++
++ self.boot_sector = FatBootSector(self.sector_reader(start_sector, 1))
++
++ fat_size_in_sectors = (
++ self.boot_sector.sectors_per_fat * self.boot_sector.fat_count
++ )
++ self.fats = self.read_sectors(
++ self.boot_sector.reserved_sectors, fat_size_in_sectors
++ )
++ self.fats_dirty_sectors: Set[int] = set()
++
++ def read_sectors(self, start_sector: int, num_sectors: int) -> bytes:
++ return self.sector_reader(start_sector + self.start_sector,
++ num_sectors)
++
++ def write_sectors(self, start_sector: int, data: bytes) -> None:
++ return self.sector_writer(start_sector + self.start_sector, data)
++
++ def directory_from_bytes(
++ self, data: bytes, start_sector: int
++ ) -> List[FatDirectoryEntry]:
++ """
++ Convert `bytes` into a list of `FatDirectoryEntry` objects.
++ Will ignore long file names.
++ Will stop when it encounters a 0x00 byte.
++ """
++
++ entries = []
++ for i in range(0, len(data), DIRENTRY_SIZE):
++ entry = data[i : i + DIRENTRY_SIZE]
++
++ current_sector = start_sector + (i // SECTOR_SIZE)
++ current_offset = i % SECTOR_SIZE
++
++ if entry[0] == 0:
++ break
++
++ if entry[0] == 0xE5:
++ # Deleted file
++ continue
++
++ if entry[11] & 0xF == 0xF:
++ # Long file name
++ continue
++
++ entries.append(
++ FatDirectoryEntry(entry, current_sector, current_offset)
++ )
++ return entries
++
++ def read_root_directory(self) -> List[FatDirectoryEntry]:
++ root_dir = self.read_sectors(
++ self.boot_sector.root_dir_start(), self.boot_sector.root_dir_size()
++ )
++ return self.directory_from_bytes(
++ root_dir, self.boot_sector.root_dir_start()
++ )
++
++ def read_fat_entry(self, cluster: int) -> int:
++ """
++ Read the FAT entry for the given cluster.
++ """
++ fat_offset = cluster * 2 # FAT16
++ return int.from_bytes(self.fats[fat_offset : fat_offset + 2], "little")
++
++ def write_fat_entry(self, cluster: int, value: int) -> None:
++ """
++ Write the FAT entry for the given cluster.
++ """
++ fat_offset = cluster * 2
++ self.fats = (
++ self.fats[:fat_offset]
++ + value.to_bytes(2, "little")
++ + self.fats[fat_offset + 2 :]
++ )
++ self.fats_dirty_sectors.add(fat_offset // SECTOR_SIZE)
++
++ def flush_fats(self) -> None:
++ """
++ Write the FATs back to the disk.
++ """
++ for sector in self.fats_dirty_sectors:
++ data = self.fats[sector * SECTOR_SIZE : (sector + 1) * SECTOR_SIZE]
++ sector = self.boot_sector.reserved_sectors + sector
++ self.write_sectors(sector, data)
++ self.fats_dirty_sectors = set()
++
++ def next_cluster(self, cluster: int) -> Optional[int]:
++ """
++ Get the next cluster in the chain.
++ If its `None`, then its the last cluster.
++ The function will crash if the next cluster
++ is `FREE` (unexpected) or invalid entry.
++ """
++ fat_entry = self.read_fat_entry(cluster)
++ if fat_entry == 0:
++ raise Exception("Unexpected: FREE cluster")
++ if fat_entry == 1:
++ raise Exception("Unexpected: RESERVED cluster")
++ if fat_entry >= 0xFFF8:
++ return None
++ if fat_entry >= 0xFFF7:
++ raise Exception("Invalid FAT entry")
++
++ return fat_entry
++
++ def next_free_cluster(self) -> int:
++ """
++ Find the next free cluster.
++ """
++ # simple linear search
++ for i in range(2, 0xFFFF):
++ if self.read_fat_entry(i) == 0:
++ return i
++ raise Exception("No free clusters")
++
++ def next_free_cluster_non_continuous(self) -> int:
++ """
++ Find the next free cluster, but makes sure
++ that the cluster before and after it are not allocated.
++ """
++ # simple linear search
++ before = False
++ for i in range(2, 0xFFFF):
++ if self.read_fat_entry(i) == 0:
++ if before and self.read_fat_entry(i + 1) == 0:
++ return i
++ else:
++ before = True
++ else:
++ before = False
++
++ raise Exception("No free clusters")
++
++ def read_cluster(self, cluster: int) -> bytes:
++ """
++ Read the cluster at the given cluster.
++ """
++ return self.read_sectors(
++ self.boot_sector.first_sector_of_cluster(cluster),
++ self.boot_sector.sectors_per_cluster,
++ )
++
++ def write_cluster(self, cluster: int, data: bytes) -> None:
++ """
++ Write the cluster at the given cluster.
++ """
++ assert len(data) == self.boot_sector.cluster_bytes()
++ self.write_sectors(
++ self.boot_sector.first_sector_of_cluster(cluster),
++ data,
++ )
++
++ def read_directory(
++ self, cluster: Optional[int]
++ ) -> List[FatDirectoryEntry]:
++ """
++ Read the directory at the given cluster.
++ """
++ entries = []
++ while cluster is not None:
++ data = self.read_cluster(cluster)
++ entries.extend(
++ self.directory_from_bytes(
++ data, self.boot_sector.first_sector_of_cluster(cluster)
++ )
++ )
++ cluster = self.next_cluster(cluster)
++ return entries
++
++ def add_direntry(
++ self, cluster: Optional[int], name: str, ext: str, attributes: int
++ ) -> FatDirectoryEntry:
++ """
++ Add a new directory entry to the given cluster.
++ If the cluster is `None`, then it will be added to the root directory.
++ """
++
++ def find_free_entry(data: bytes) -> Optional[int]:
++ for i in range(0, len(data), DIRENTRY_SIZE):
++ entry = data[i : i + DIRENTRY_SIZE]
++ if entry[0] == 0 or entry[0] == 0xE5:
++ return i
++ return None
++
++ assert len(name) <= 8, "Name must be 8 characters or less"
++ assert len(ext) <= 3, "Ext must be 3 characters or less"
++ assert attributes % 0x15 != 0x15, "Invalid attributes"
++
++ # initial dummy data
++ new_entry = FatDirectoryEntry(b"\0" * 32, 0, 0)
++ new_entry.name = name.ljust(8, " ")
++ new_entry.ext = ext.ljust(3, " ")
++ new_entry.attributes = attributes
++ new_entry.reserved = 0
++ new_entry.create_time_tenth = 0
++ new_entry.create_time = 0
++ new_entry.create_date = 0
++ new_entry.last_access_date = 0
++ new_entry.last_mod_time = 0
++ new_entry.last_mod_date = 0
++ new_entry.cluster = self.next_free_cluster()
++ new_entry.size_bytes = 0
++
++ # mark as EOF
++ self.write_fat_entry(new_entry.cluster, 0xFFFF)
++
++ if cluster is None:
++ for i in range(self.boot_sector.root_dir_size()):
++ sector_data = self.read_sectors(
++ self.boot_sector.root_dir_start() + i, 1
++ )
++ offset = find_free_entry(sector_data)
++ if offset is not None:
++ new_entry.sector = self.boot_sector.root_dir_start() + i
++ new_entry.offset = offset
++ self.update_direntry(new_entry)
++ return new_entry
++ else:
++ while cluster is not None:
++ data = self.read_cluster(cluster)
++ offset = find_free_entry(data)
++ if offset is not None:
++ new_entry.sector = (
++ self.boot_sector.first_sector_of_cluster(cluster)
++ + (offset // SECTOR_SIZE))
++ new_entry.offset = offset % SECTOR_SIZE
++ self.update_direntry(new_entry)
++ return new_entry
++ cluster = self.next_cluster(cluster)
++
++ raise Exception("No free directory entries")
++
++ def update_direntry(self, entry: FatDirectoryEntry) -> None:
++ """
++ Write the directory entry back to the disk.
++ """
++ sector = self.read_sectors(entry.sector, 1)
++ sector = (
++ sector[: entry.offset]
++ + entry.as_bytes()
++ + sector[entry.offset + DIRENTRY_SIZE :]
++ )
++ self.write_sectors(entry.sector, sector)
++
++ def find_direntry(self, path: str) -> Optional[FatDirectoryEntry]:
++ """
++ Find the directory entry for the given path.
++ """
++ assert path[0] == "/", "Path must start with /"
++
++ path = path[1:] # remove the leading /
++ parts = path.split("/")
++ directory = self.read_root_directory()
++
++ current_entry = None
++
++ for i, part in enumerate(parts):
++ is_last = i == len(parts) - 1
++
++ for entry in directory:
++ if entry.whole_name() == part:
++ current_entry = entry
++ break
++ if current_entry is None:
++ return None
++
++ if is_last:
++ return current_entry
++
++ if current_entry.attributes & 0x10 == 0:
++ raise Exception(
++ f"{current_entry.whole_name()} is not a directory"
++ )
++
++ directory = self.read_directory(current_entry.cluster)
++
++ assert False, "Exited loop with is_last == False"
++
++ def read_file(self, entry: Optional[FatDirectoryEntry]) -> Optional[bytes]:
++ """
++ Read the content of the file at the given path.
++ """
++ if entry is None:
++ return None
++ if entry.attributes & 0x10 != 0:
++ raise Exception(f"{entry.whole_name()} is a directory")
++
++ data = b""
++ cluster: Optional[int] = entry.cluster
++ while cluster is not None and len(data) <= entry.size_bytes:
++ data += self.read_cluster(cluster)
++ cluster = self.next_cluster(cluster)
++ return data[: entry.size_bytes]
++
++ def truncate_file(
++ self,
++ entry: FatDirectoryEntry,
++ new_size: int,
++ allocate_non_continuous: bool = False,
++ ) -> None:
++ """
++ Truncate the file at the given path to the new size.
++ """
++ if entry is None:
++ raise Exception("entry is None")
++ if entry.attributes & 0x10 != 0:
++ raise Exception(f"{entry.whole_name()} is a directory")
++
++ def clusters_from_size(size: int) -> int:
++ return (
++ size + self.boot_sector.cluster_bytes() - 1
++ ) // self.boot_sector.cluster_bytes()
++
++ # First, allocate new FATs if we need to
++ required_clusters = clusters_from_size(new_size)
++ current_clusters = clusters_from_size(entry.size_bytes)
++
++ affected_clusters = set()
++
++ # Keep at least one cluster, easier to manage this way
++ if required_clusters == 0:
++ required_clusters = 1
++ if current_clusters == 0:
++ current_clusters = 1
++
++ cluster: Optional[int]
++
++ if required_clusters > current_clusters:
++ # Allocate new clusters
++ cluster = entry.cluster
++ to_add = required_clusters
++ for _ in range(current_clusters - 1):
++ to_add -= 1
++ assert cluster is not None, "Cluster is None"
++ affected_clusters.add(cluster)
++ cluster = self.next_cluster(cluster)
++ assert required_clusters > 0, "No new clusters to allocate"
++ assert cluster is not None, "Cluster is None"
++ assert (
++ self.next_cluster(cluster) is None
++ ), "Cluster is not the last cluster"
++
++ # Allocate new clusters
++ for _ in range(to_add - 1):
++ if allocate_non_continuous:
++ new_cluster = self.next_free_cluster_non_continuous()
++ else:
++ new_cluster = self.next_free_cluster()
++ self.write_fat_entry(cluster, new_cluster)
++ self.write_fat_entry(new_cluster, 0xFFFF)
++ cluster = new_cluster
++
++ elif required_clusters < current_clusters:
++ # Truncate the file
++ cluster = entry.cluster
++ for _ in range(required_clusters - 1):
++ assert cluster is not None, "Cluster is None"
++ cluster = self.next_cluster(cluster)
++ assert cluster is not None, "Cluster is None"
++
++ next_cluster = self.next_cluster(cluster)
++ # mark last as EOF
++ self.write_fat_entry(cluster, 0xFFFF)
++ # free the rest
++ while next_cluster is not None:
++ cluster = next_cluster
++ next_cluster = self.next_cluster(next_cluster)
++ self.write_fat_entry(cluster, 0)
++
++ self.flush_fats()
++
++ # verify number of clusters
++ cluster = entry.cluster
++ count = 0
++ while cluster is not None:
++ count += 1
++ affected_clusters.add(cluster)
++ cluster = self.next_cluster(cluster)
++ assert (
++ count == required_clusters
++ ), f"Expected {required_clusters} clusters, got {count}"
++
++ # update the size
++ entry.size_bytes = new_size
++ self.update_direntry(entry)
++
++ # trigger every affected cluster
++ for cluster in affected_clusters:
++ first_sector = self.boot_sector.first_sector_of_cluster(cluster)
++ first_sector_data = self.read_sectors(first_sector, 1)
++ self.write_sectors(first_sector, first_sector_data)
++
++ def write_file(self, entry: FatDirectoryEntry, data: bytes) -> None:
++ """
++ Write the content of the file at the given path.
++ """
++ if entry is None:
++ raise Exception("entry is None")
++ if entry.attributes & 0x10 != 0:
++ raise Exception(f"{entry.whole_name()} is a directory")
++
++ data_len = len(data)
++
++ self.truncate_file(entry, data_len)
++
++ cluster: Optional[int] = entry.cluster
++ while cluster is not None:
++ data_to_write = data[: self.boot_sector.cluster_bytes()]
++ if len(data_to_write) < self.boot_sector.cluster_bytes():
++ old_data = self.read_cluster(cluster)
++ data_to_write += old_data[len(data_to_write) :]
++
++ self.write_cluster(cluster, data_to_write)
++ data = data[self.boot_sector.cluster_bytes() :]
++ if len(data) == 0:
++ break
++ cluster = self.next_cluster(cluster)
++
++ assert (
++ len(data) == 0
++ ), "Data was not written completely, clusters missing"
++
++ def create_file(self, path: str) -> Optional[FatDirectoryEntry]:
++ """
++ Create a new file at the given path.
++ """
++ assert path[0] == "/", "Path must start with /"
++
++ path = path[1:] # remove the leading /
++
++ parts = path.split("/")
++
++ directory_cluster = None
++ directory = self.read_root_directory()
++
++ parts, filename = parts[:-1], parts[-1]
++
++ for _, part in enumerate(parts):
++ current_entry = None
++ for entry in directory:
++ if entry.whole_name() == part:
++ current_entry = entry
++ break
++ if current_entry is None:
++ return None
++
++ if current_entry.attributes & 0x10 == 0:
++ raise Exception(
++ f"{current_entry.whole_name()} is not a directory"
++ )
++
++ directory = self.read_directory(current_entry.cluster)
++ directory_cluster = current_entry.cluster
++
++ # add new entry to the directory
++
++ filename, ext = filename.split(".")
++
++ if len(ext) > 3:
++ raise Exception("Ext must be 3 characters or less")
++ if len(filename) > 8:
++ raise Exception("Name must be 8 characters or less")
++
++ for c in filename + ext:
++
++ if c not in ALLOWED_FILE_CHARS:
++ raise Exception("Invalid character in filename")
++
++ return self.add_direntry(directory_cluster, filename, ext, 0)
+diff --git a/tests/qemu-iotests/testenv.py b/tests/qemu-iotests/testenv.py
+index a864c74b12..23307fa2f4 100644
+--- a/tests/qemu-iotests/testenv.py
++++ b/tests/qemu-iotests/testenv.py
+@@ -250,7 +250,7 @@ def __init__(self, imgfmt: str, imgproto: str, aiomode: str,
+ self.qemu_img_options = os.getenv('QEMU_IMG_OPTIONS')
+ self.qemu_nbd_options = os.getenv('QEMU_NBD_OPTIONS')
+
+- is_generic = self.imgfmt not in ['bochs', 'cloop', 'dmg']
++ is_generic = self.imgfmt not in ['bochs', 'cloop', 'dmg', 'vvfat']
+ self.imgfmt_generic = 'true' if is_generic else 'false'
+
+ self.qemu_io_options = f'--cache {self.cachemode} --aio {self.aiomode}'
+diff --git a/tests/qemu-iotests/tests/vvfat b/tests/qemu-iotests/tests/vvfat
+new file mode 100755
+index 0000000000..acdc6ce8ff
+--- /dev/null
++++ b/tests/qemu-iotests/tests/vvfat
+@@ -0,0 +1,485 @@
++#!/usr/bin/env python3
++# group: rw vvfat
++#
++# Test vvfat driver implementation
++# Here, we use a simple FAT16 implementation and check the behavior of
++# the vvfat driver.
++#
++# Copyright (C) 2024 Amjad Alsharafi <amjadsharafi10@gmail.com>
++#
++# This program is free software; you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation; either version 2 of the License, or
++# (at your option) any later version.
++#
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++# GNU General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program. If not, see <http://www.gnu.org/licenses/>.
++
++import os
++import shutil
++import iotests
++from iotests import imgfmt, QMPTestCase
++from fat16 import MBR, Fat16, DIRENTRY_SIZE
++
++filesystem = os.path.join(iotests.test_dir, "filesystem")
++
++nbd_sock = iotests.file_path("nbd.sock", base_dir=iotests.sock_dir)
++nbd_uri = "nbd+unix:///disk?socket=" + nbd_sock
++
++SECTOR_SIZE = 512
++
++
++class TestVVFatDriver(QMPTestCase):
++ # pylint: disable=broad-exception-raised
++ def setUp(self) -> None:
++ if os.path.exists(filesystem):
++ if os.path.isdir(filesystem):
++ shutil.rmtree(filesystem)
++ else:
++ raise Exception(f"{filesystem} exists and is not a directory")
++
++ os.mkdir(filesystem)
++
++ # Add some text files to the filesystem
++ for i in range(10):
++ with open(os.path.join(filesystem, f"file{i}.txt"),
++ "w", encoding="ascii") as f:
++ f.write(f"Hello, world! {i}\n")
++
++ # Add 2 large files, above the cluster size (8KB)
++ with open(os.path.join(filesystem, "large1.txt"), "wb") as f:
++ # write 'A' * 1KB, 'B' * 1KB, 'C' * 1KB, ...
++ for i in range(8 * 2): # two clusters
++ f.write(bytes([0x41 + i] * 1024))
++
++ with open(os.path.join(filesystem, "large2.txt"), "wb") as f:
++ # write 'A' * 1KB, 'B' * 1KB, 'C' * 1KB, ...
++ for i in range(8 * 3): # 3 clusters
++ f.write(bytes([0x41 + i] * 1024))
++
++ self.vm = iotests.VM()
++
++ self.vm.add_blockdev(
++ self.vm.qmp_to_opts(
++ {
++ "driver": imgfmt,
++ "node-name": "disk",
++ "rw": "true",
++ "fat-type": "16",
++ "dir": filesystem,
++ }
++ )
++ )
++
++ self.vm.launch()
++
++ self.vm.qmp_log("block-dirty-bitmap-add", **{
++ "node": "disk",
++ "name": "bitmap0",
++ })
++
++ # attach nbd server
++ self.vm.qmp_log(
++ "nbd-server-start",
++ **{"addr": {"type": "unix", "data": {"path": nbd_sock}}},
++ filters=[],
++ )
++
++ self.vm.qmp_log(
++ "nbd-server-add",
++ **{"device": "disk", "writable": True, "bitmap": "bitmap0"},
++ )
++
++ self.qio = iotests.QemuIoInteractive("-f", "raw", nbd_uri)
++
++ def tearDown(self) -> None:
++ self.qio.close()
++ self.vm.shutdown()
++ # print(self.vm.get_log())
++ shutil.rmtree(filesystem)
++
++ def read_sectors(self, sector: int, num: int = 1) -> bytes:
++ """
++ Read `num` sectors starting from `sector` from the `disk`.
++ This uses `QemuIoInteractive` to read the sectors into `stdout` and
++ then parse the output.
++ """
++ self.assertGreater(num, 0)
++
++ # The output contains the content of the sector in hex dump format
++ # We need to extract the content from it
++ output = self.qio.cmd(
++ f"read -v {sector * SECTOR_SIZE} {num * SECTOR_SIZE}")
++
++ # Each row is 16 bytes long, and we are writing `num` sectors
++ rows = num * SECTOR_SIZE // 16
++ output_rows = output.split("\n")[:rows]
++
++ hex_content = "".join(
++ [(row.split(": ")[1]).split(" ")[0] for row in output_rows]
++ )
++ bytes_content = bytes.fromhex(hex_content)
++
++ self.assertEqual(len(bytes_content), num * SECTOR_SIZE)
++
++ return bytes_content
++
++ def write_sectors(self, sector: int, data: bytes) -> None:
++ """
++ Write `data` to the `disk` starting from `sector`.
++ This uses `QemuIoInteractive` to write the data into the disk.
++ """
++
++ self.assertGreater(len(data), 0)
++ self.assertEqual(len(data) % SECTOR_SIZE, 0)
++
++ temp_file = os.path.join(iotests.test_dir, "temp.bin")
++ with open(temp_file, "wb") as f:
++ f.write(data)
++
++ self.qio.cmd(
++ f"write -s {temp_file} {sector * SECTOR_SIZE} {len(data)}"
++ )
++
++ os.remove(temp_file)
++
++ def init_fat16(self):
++ mbr = MBR(self.read_sectors(0))
++ return Fat16(
++ mbr.partition_table[0]["start_lba"],
++ mbr.partition_table[0]["size"],
++ self.read_sectors,
++ self.write_sectors,
++ )
++
++ # Tests
++
++ def test_fat_filesystem(self):
++ """
++ Test that vvfat produce a valid FAT16 and MBR sectors
++ """
++ mbr = MBR(self.read_sectors(0))
++
++ self.assertEqual(mbr.partition_table[0]["status"], 0x80)
++ self.assertEqual(mbr.partition_table[0]["type"], 6)
++
++ fat16 = Fat16(
++ mbr.partition_table[0]["start_lba"],
++ mbr.partition_table[0]["size"],
++ self.read_sectors,
++ self.write_sectors,
++ )
++ self.assertEqual(fat16.boot_sector.bytes_per_sector, 512)
++ self.assertEqual(fat16.boot_sector.volume_label, "QEMU VVFAT")
++
++ def test_read_root_directory(self):
++ """
++ Test the content of the root directory
++ """
++ fat16 = self.init_fat16()
++
++ root_dir = fat16.read_root_directory()
++
++ self.assertEqual(len(root_dir), 13) # 12 + 1 special file
++
++ files = {
++ "QEMU VVF.AT": 0, # special empty file
++ "FILE0.TXT": 16,
++ "FILE1.TXT": 16,
++ "FILE2.TXT": 16,
++ "FILE3.TXT": 16,
++ "FILE4.TXT": 16,
++ "FILE5.TXT": 16,
++ "FILE6.TXT": 16,
++ "FILE7.TXT": 16,
++ "FILE8.TXT": 16,
++ "FILE9.TXT": 16,
++ "LARGE1.TXT": 0x2000 * 2,
++ "LARGE2.TXT": 0x2000 * 3,
++ }
++
++ for entry in root_dir:
++ self.assertIn(entry.whole_name(), files)
++ self.assertEqual(entry.size_bytes, files[entry.whole_name()])
++
++ def test_direntry_as_bytes(self):
++ """
++ Test if we can convert Direntry back to bytes, so that we can write it
++ back to the disk safely.
++ """
++ fat16 = self.init_fat16()
++
++ root_dir = fat16.read_root_directory()
++ first_entry_bytes = fat16.read_sectors(
++ fat16.boot_sector.root_dir_start(), 1)
++
++ # The first entry won't be deleted, so we can compare it with the first
++ # entry in the root directory
++ self.assertEqual(root_dir[0].as_bytes(),
++ first_entry_bytes[:DIRENTRY_SIZE])
++
++ def test_read_files(self):
++ """
++ Test reading the content of the files
++ """
++ fat16 = self.init_fat16()
++
++ for i in range(10):
++ file = fat16.find_direntry(f"/FILE{i}.TXT")
++ self.assertIsNotNone(file)
++ self.assertEqual(
++ fat16.read_file(file), f"Hello, world! {i}\n".encode("ascii")
++ )
++
++ # test large files
++ large1 = fat16.find_direntry("/LARGE1.TXT")
++ with open(os.path.join(filesystem, "large1.txt"), "rb") as f:
++ self.assertEqual(fat16.read_file(large1), f.read())
++
++ large2 = fat16.find_direntry("/LARGE2.TXT")
++ self.assertIsNotNone(large2)
++ with open(os.path.join(filesystem, "large2.txt"), "rb") as f:
++ self.assertEqual(fat16.read_file(large2), f.read())
++
++ def test_write_file_same_content_direct(self):
++ """
++ Similar to `test_write_file_in_same_content`, but we write the file
++ directly clusters and thus we don't go through the modification of
++ direntry.
++ """
++ fat16 = self.init_fat16()
++
++ file = fat16.find_direntry("/FILE0.TXT")
++ self.assertIsNotNone(file)
++
++ data = fat16.read_cluster(file.cluster)
++ fat16.write_cluster(file.cluster, data)
++
++ with open(os.path.join(filesystem, "file0.txt"), "rb") as f:
++ self.assertEqual(fat16.read_file(file), f.read())
++
++ def test_write_file_in_same_content(self):
++ """
++ Test writing the same content to the file back to it
++ """
++ fat16 = self.init_fat16()
++
++ file = fat16.find_direntry("/FILE0.TXT")
++ self.assertIsNotNone(file)
++
++ self.assertEqual(fat16.read_file(file), b"Hello, world! 0\n")
++
++ fat16.write_file(file, b"Hello, world! 0\n")
++ self.assertEqual(fat16.read_file(file), b"Hello, world! 0\n")
++
++ with open(os.path.join(filesystem, "file0.txt"), "rb") as f:
++ self.assertEqual(f.read(), b"Hello, world! 0\n")
++
++ def test_modify_content_same_clusters(self):
++ """
++ Test modifying the content of the file without changing the number of
++ clusters
++ """
++ fat16 = self.init_fat16()
++
++ file = fat16.find_direntry("/FILE0.TXT")
++ self.assertIsNotNone(file)
++
++ new_content = b"Hello, world! Modified\n"
++ self.assertEqual(fat16.read_file(file), b"Hello, world! 0\n")
++
++ fat16.write_file(file, new_content)
++ self.assertEqual(fat16.read_file(file), new_content)
++
++ with open(os.path.join(filesystem, "file0.txt"), "rb") as f:
++ self.assertEqual(f.read(), new_content)
++
++ def test_truncate_file_same_clusters_less(self):
++ """
++ Test truncating the file without changing number of clusters
++ Test decreasing the file size
++ """
++ fat16 = self.init_fat16()
++
++ file = fat16.find_direntry("/FILE0.TXT")
++ self.assertIsNotNone(file)
++
++ self.assertEqual(fat16.read_file(file), b"Hello, world! 0\n")
++
++ fat16.truncate_file(file, 5)
++ new_content = fat16.read_file(file)
++ self.assertEqual(new_content, b"Hello")
++
++ with open(os.path.join(filesystem, "file0.txt"), "rb") as f:
++ self.assertEqual(f.read(), new_content)
++
++ def test_truncate_file_same_clusters_more(self):
++ """
++ Test truncating the file without changing number of clusters
++ Test increase the file size
++ """
++ fat16 = self.init_fat16()
++
++ file = fat16.find_direntry("/FILE0.TXT")
++ self.assertIsNotNone(file)
++
++ self.assertEqual(fat16.read_file(file), b"Hello, world! 0\n")
++
++ fat16.truncate_file(file, 20)
++ new_content = fat16.read_file(file)
++ self.assertIsNotNone(new_content)
++
++ # random pattern will be appended to the file, and its not always the
++ # same
++ self.assertEqual(new_content[:16], b"Hello, world! 0\n")
++ self.assertEqual(len(new_content), 20)
++
++ with open(os.path.join(filesystem, "file0.txt"), "rb") as f:
++ self.assertEqual(f.read(), new_content)
++
++ def test_write_large_file(self):
++ """
++ Test writing a large file
++ """
++ fat16 = self.init_fat16()
++
++ file = fat16.find_direntry("/LARGE1.TXT")
++ self.assertIsNotNone(file)
++
++ # The content of LARGE1 is A * 1KB, B * 1KB, C * 1KB, ..., P * 1KB
++ # Lets change it to be Z * 1KB, Y * 1KB, X * 1KB, ..., K * 1KB
++ # without changing the number of clusters or filesize
++ new_content = b"".join([bytes([0x5A - i] * 1024) for i in range(16)])
++ fat16.write_file(file, new_content)
++ self.assertEqual(fat16.read_file(file), new_content)
++
++ with open(os.path.join(filesystem, "large1.txt"), "rb") as f:
++ self.assertEqual(f.read(), new_content)
++
++ def test_truncate_file_change_clusters_less(self):
++ """
++ Test truncating a file by reducing the number of clusters
++ """
++ fat16 = self.init_fat16()
++
++ file = fat16.find_direntry("/LARGE1.TXT")
++ self.assertIsNotNone(file)
++
++ fat16.truncate_file(file, 1)
++ self.assertEqual(fat16.read_file(file), b"A")
++
++ with open(os.path.join(filesystem, "large1.txt"), "rb") as f:
++ self.assertEqual(f.read(), b"A")
++
++ def test_write_file_change_clusters_less(self):
++ """
++ Test truncating a file by reducing the number of clusters
++ """
++ fat16 = self.init_fat16()
++
++ file = fat16.find_direntry("/LARGE2.TXT")
++ self.assertIsNotNone(file)
++
++ new_content = b"X" * 8 * 1024 + b"Y" * 8 * 1024
++ fat16.write_file(file, new_content)
++ self.assertEqual(fat16.read_file(file), new_content)
++
++ with open(os.path.join(filesystem, "large2.txt"), "rb") as f:
++ self.assertEqual(f.read(), new_content)
++
++ def test_write_file_change_clusters_more(self):
++ """
++ Test truncating a file by increasing the number of clusters
++ """
++ fat16 = self.init_fat16()
++
++ file = fat16.find_direntry("/LARGE2.TXT")
++ self.assertIsNotNone(file)
++
++ # from 3 clusters to 4 clusters
++ new_content = (
++ b"W" * 8 * 1024 +
++ b"X" * 8 * 1024 +
++ b"Y" * 8 * 1024 +
++ b"Z" * 8 * 1024
++ )
++ fat16.write_file(file, new_content)
++ self.assertEqual(fat16.read_file(file), new_content)
++
++ with open(os.path.join(filesystem, "large2.txt"), "rb") as f:
++ self.assertEqual(f.read(), new_content)
++
++ def test_write_file_change_clusters_more_non_contiguous_2_mappings(self):
++ """
++ Test truncating a file by increasing the number of clusters Here we
++ allocate the new clusters in a way that makes them non-contiguous so
++ that we will get 2 cluster mappings for the file
++ """
++ fat16 = self.init_fat16()
++
++ file = fat16.find_direntry("/LARGE1.TXT")
++ self.assertIsNotNone(file)
++
++ # from 2 clusters to 3 clusters with non-contiguous allocation
++ fat16.truncate_file(file, 3 * 0x2000, allocate_non_continuous=True)
++ new_content = b"X" * 8 * 1024 + b"Y" * 8 * 1024 + b"Z" * 8 * 1024
++ fat16.write_file(file, new_content)
++ self.assertEqual(fat16.read_file(file), new_content)
++
++ with open(os.path.join(filesystem, "large1.txt"), "rb") as f:
++ self.assertEqual(f.read(), new_content)
++
++ def test_write_file_change_clusters_more_non_contiguous_3_mappings(self):
++ """
++ Test truncating a file by increasing the number of clusters Here we
++ allocate the new clusters in a way that makes them non-contiguous so
++ that we will get 3 cluster mappings for the file
++ """
++ fat16 = self.init_fat16()
++
++ file = fat16.find_direntry("/LARGE1.TXT")
++ self.assertIsNotNone(file)
++
++ # from 2 clusters to 4 clusters with non-contiguous allocation
++ fat16.truncate_file(file, 4 * 0x2000, allocate_non_continuous=True)
++ new_content = (
++ b"W" * 8 * 1024 +
++ b"X" * 8 * 1024 +
++ b"Y" * 8 * 1024 +
++ b"Z" * 8 * 1024
++ )
++ fat16.write_file(file, new_content)
++ self.assertEqual(fat16.read_file(file), new_content)
++
++ with open(os.path.join(filesystem, "large1.txt"), "rb") as f:
++ self.assertEqual(f.read(), new_content)
++
++ def test_create_file(self):
++ """
++ Test creating a new file
++ """
++ fat16 = self.init_fat16()
++
++ new_file = fat16.create_file("/NEWFILE.TXT")
++
++ self.assertIsNotNone(new_file)
++ self.assertEqual(new_file.size_bytes, 0)
++
++ new_content = b"Hello, world! New file\n"
++ fat16.write_file(new_file, new_content)
++ self.assertEqual(fat16.read_file(new_file), new_content)
++
++ with open(os.path.join(filesystem, "newfile.txt"), "rb") as f:
++ self.assertEqual(f.read(), new_content)
++
++ # TODO: support deleting files
++
++
++if __name__ == "__main__":
++ # This is a specific test for vvfat driver
++ iotests.main(supported_fmts=["vvfat"], supported_protocols=["file"])
+diff --git a/tests/qemu-iotests/tests/vvfat.out b/tests/qemu-iotests/tests/vvfat.out
+new file mode 100755
+index 0000000000..b6f257674e
+--- /dev/null
++++ b/tests/qemu-iotests/tests/vvfat.out
+@@ -0,0 +1,5 @@
++................
++----------------------------------------------------------------------
++Ran 16 tests
++
++OK
+diff --git a/tests/unit/ptimer-test.c b/tests/unit/ptimer-test.c
+index 04b5f4e3d0..08240594bb 100644
+--- a/tests/unit/ptimer-test.c
++++ b/tests/unit/ptimer-test.c
+@@ -763,6 +763,33 @@ static void check_oneshot_with_load_0(gconstpointer arg)
+ ptimer_free(ptimer);
+ }
+
++static void check_freq_more_than_1000M(gconstpointer arg)
++{
++ const uint8_t *policy = arg;
++ ptimer_state *ptimer = ptimer_init(ptimer_trigger, NULL, *policy);
++ bool no_round_down = (*policy & PTIMER_POLICY_NO_COUNTER_ROUND_DOWN);
++
++ triggered = false;
++
++ ptimer_transaction_begin(ptimer);
++ ptimer_set_freq(ptimer, 2000000000);
++ ptimer_set_limit(ptimer, 8, 1);
++ ptimer_run(ptimer, 1);
++ ptimer_transaction_commit(ptimer);
++
++ qemu_clock_step(3);
++
++ g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 3 : 2);
++ g_assert_false(triggered);
++
++ qemu_clock_step(1);
++
++ g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
++ g_assert_true(triggered);
++
++ ptimer_free(ptimer);
++}
++
+ static void add_ptimer_tests(uint8_t policy)
+ {
+ char policy_name[256] = "";
+@@ -857,6 +884,12 @@ static void add_ptimer_tests(uint8_t policy)
+ policy_name),
+ g_memdup2(&policy, 1), check_oneshot_with_load_0, g_free);
+ g_free(tmp);
++
++ g_test_add_data_func_full(
++ tmp = g_strdup_printf("/ptimer/freq_more_than_1000M policy=%s",
++ policy_name),
++ g_memdup2(&policy, 1), check_freq_more_than_1000M, g_free);
++ g_free(tmp);
+ }
+
+ static void add_all_ptimer_policies_comb_tests(void)
+diff --git a/util/async.c b/util/async.c
+index a1f07fc5a7..0cc3037e0c 100644
+--- a/util/async.c
++++ b/util/async.c
+@@ -744,7 +744,7 @@ void aio_context_set_thread_pool_params(AioContext *ctx, int64_t min,
+ int64_t max, Error **errp)
+ {
+
+- if (min > max || !max || min > INT_MAX || max > INT_MAX) {
++ if (min > max || max <= 0 || min < 0 || min > INT_MAX || max > INT_MAX) {
+ error_setg(errp, "bad thread-pool-min/thread-pool-max values");
+ return;
+ }
+diff --git a/util/module.c b/util/module.c
+index 32e263163c..3eb0f06df1 100644
+--- a/util/module.c
++++ b/util/module.c
+@@ -354,13 +354,13 @@ int module_load_qom(const char *type, Error **errp)
+ void module_load_qom_all(void)
+ {
+ const QemuModinfo *modinfo;
+- Error *local_err = NULL;
+
+ if (module_loaded_qom_all) {
+ return;
+ }
+
+ for (modinfo = module_info; modinfo->name != NULL; modinfo++) {
++ Error *local_err = NULL;
+ if (!modinfo->objs) {
+ continue;
+ }
diff --git a/debian/patches/v7.2.15.diff b/debian/patches/v7.2.15.diff
new file mode 100644
index 00000000..bdebfb92
--- /dev/null
+++ b/debian/patches/v7.2.15.diff
@@ -0,0 +1,1245 @@
+Subject: v7.2.15
+Date: Thu Nov 21 00:11:28 2024 +0300
+From: Michael Tokarev <mjt@tls.msk.ru>
+Forwarded: not-needed
+
+This is a difference between upstream qemu v7.2.14
+and upstream qemu v7.2.15.
+
+ .gitlab-ci.d/check-dco.py | 5 +-
+ .gitlab-ci.d/check-patch.py | 5 +-
+ VERSION | 2 +-
+ accel/kvm/kvm-all.c | 88 +++++++++++++++++++++++++++++-------
+ accel/kvm/trace-events | 1 +
+ block/copy-before-write.c | 3 +-
+ block/raw-format.c | 4 +-
+ block/reqlist.c | 2 -
+ hw/9pfs/9p.c | 5 ++
+ hw/audio/hda-codec.c | 14 +++---
+ hw/intc/arm_gicv3_cpuif.c | 2 +-
+ hw/intc/riscv_aplic.c | 38 ++++++++++++++--
+ hw/intc/sifive_plic.c | 6 ++-
+ hw/nvme/ctrl.c | 21 +++++----
+ hw/scsi/scsi-bus.c | 36 +++++++++++++--
+ hw/usb/dev-hub.c | 1 +
+ include/hw/misc/mos6522.h | 2 +-
+ include/hw/scsi/scsi.h | 1 +
+ include/sysemu/kvm_int.h | 1 +
+ linux-user/elfload.c | 12 ++---
+ linux-user/flatload.c | 3 ++
+ linux-user/ppc/signal.c | 2 +-
+ linux-user/syscall.c | 20 ++++++--
+ net/colo-compare.c | 3 +-
+ net/tap-win32.c | 15 +++---
+ scripts/oss-fuzz/build.sh | 1 +
+ scripts/tracetool/__init__.py | 14 +++---
+ scripts/tracetool/format/log_stap.py | 2 +-
+ softmmu/physmem.c | 2 +-
+ target/arm/internals.h | 5 +-
+ target/arm/sve_helper.c | 4 --
+ target/arm/vec_helper.c | 9 +++-
+ target/i386/cpu.h | 1 +
+ target/i386/tcg/seg_helper.c | 2 +-
+ target/i386/tcg/sysemu/excp_helper.c | 19 ++++++--
+ target/ppc/translate.c | 3 +-
+ target/ppc/translate/vsx-impl.c.inc | 2 +-
+ target/riscv/cpu.c | 1 +
+ target/riscv/cpu.h | 5 +-
+ target/riscv/csr.c | 4 +-
+ target/riscv/vector_helper.c | 2 +-
+ tcg/tcg-op-gvec.c | 15 +++++-
+ tcg/tcg.c | 2 +-
+ tests/qtest/tpm-tests.c | 2 +-
+ 44 files changed, 276 insertions(+), 111 deletions(-)
+
+diff --git a/.gitlab-ci.d/check-dco.py b/.gitlab-ci.d/check-dco.py
+index b929571eed..8780d73e31 100755
+--- a/.gitlab-ci.d/check-dco.py
++++ b/.gitlab-ci.d/check-dco.py
+@@ -19,10 +19,9 @@
+ reponame = os.path.basename(cwd)
+ repourl = "https://gitlab.com/%s/%s.git" % (namespace, reponame)
+
++print(f"adding upstream git repo @ {repourl}")
+ subprocess.check_call(["git", "remote", "add", "check-dco", repourl])
+-subprocess.check_call(["git", "fetch", "check-dco", "stable-7.2"],
+- stdout=subprocess.DEVNULL,
+- stderr=subprocess.DEVNULL)
++subprocess.check_call(["git", "fetch", "check-dco", "stable-7.2"])
+
+ ancestor = subprocess.check_output(["git", "merge-base",
+ "check-dco/stable-7.2", "HEAD"],
+diff --git a/.gitlab-ci.d/check-patch.py b/.gitlab-ci.d/check-patch.py
+index 39e2b403c9..68c549a146 100755
+--- a/.gitlab-ci.d/check-patch.py
++++ b/.gitlab-ci.d/check-patch.py
+@@ -19,13 +19,12 @@
+ reponame = os.path.basename(cwd)
+ repourl = "https://gitlab.com/%s/%s.git" % (namespace, reponame)
+
++print(f"adding upstream git repo @ {repourl}")
+ # GitLab CI environment does not give us any direct info about the
+ # base for the user's branch. We thus need to figure out a common
+ # ancestor between the user's branch and current git master.
+ subprocess.check_call(["git", "remote", "add", "check-patch", repourl])
+-subprocess.check_call(["git", "fetch", "check-patch", "master"],
+- stdout=subprocess.DEVNULL,
+- stderr=subprocess.DEVNULL)
++subprocess.check_call(["git", "fetch", "check-patch", "master"])
+
+ ancestor = subprocess.check_output(["git", "merge-base",
+ "check-patch/master", "HEAD"],
+diff --git a/VERSION b/VERSION
+index 0755f425a1..cc53d22108 100644
+--- a/VERSION
++++ b/VERSION
+@@ -1 +1 @@
+-7.2.14
++7.2.15
+diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
+index 0a127ece11..370ecab785 100644
+--- a/accel/kvm/kvm-all.c
++++ b/accel/kvm/kvm-all.c
+@@ -77,6 +77,9 @@
+ do { } while (0)
+ #endif
+
++/* Default num of memslots to be allocated when VM starts */
++#define KVM_MEMSLOTS_NR_ALLOC_DEFAULT 16
++
+ struct KVMParkedVcpu {
+ unsigned long vcpu_id;
+ int kvm_fd;
+@@ -172,6 +175,57 @@ void kvm_resample_fd_notify(int gsi)
+ }
+ }
+
++/**
++ * kvm_slots_grow(): Grow the slots[] array in the KVMMemoryListener
++ *
++ * @kml: The KVMMemoryListener* to grow the slots[] array
++ * @nr_slots_new: The new size of slots[] array
++ *
++ * Returns: True if the array grows larger, false otherwise.
++ */
++static bool kvm_slots_grow(KVMMemoryListener *kml, unsigned int nr_slots_new)
++{
++ unsigned int i, cur = kml->nr_slots_allocated;
++ KVMSlot *slots;
++
++ if (nr_slots_new > kvm_state->nr_slots) {
++ nr_slots_new = kvm_state->nr_slots;
++ }
++
++ if (cur >= nr_slots_new) {
++ /* Big enough, no need to grow, or we reached max */
++ return false;
++ }
++
++ if (cur == 0) {
++ slots = g_new0(KVMSlot, nr_slots_new);
++ } else {
++ assert(kml->slots);
++ slots = g_renew(KVMSlot, kml->slots, nr_slots_new);
++ /*
++ * g_renew() doesn't initialize extended buffers, however kvm
++ * memslots require fields to be zero-initialized. E.g. pointers,
++ * memory_size field, etc.
++ */
++ memset(&slots[cur], 0x0, sizeof(slots[0]) * (nr_slots_new - cur));
++ }
++
++ for (i = cur; i < nr_slots_new; i++) {
++ slots[i].slot = i;
++ }
++
++ kml->slots = slots;
++ kml->nr_slots_allocated = nr_slots_new;
++ trace_kvm_slots_grow(cur, nr_slots_new);
++
++ return true;
++}
++
++static bool kvm_slots_double(KVMMemoryListener *kml)
++{
++ return kvm_slots_grow(kml, kml->nr_slots_allocated * 2);
++}
++
+ int kvm_get_max_memslots(void)
+ {
+ KVMState *s = KVM_STATE(current_accel());
+@@ -182,15 +236,26 @@ int kvm_get_max_memslots(void)
+ /* Called with KVMMemoryListener.slots_lock held */
+ static KVMSlot *kvm_get_free_slot(KVMMemoryListener *kml)
+ {
+- KVMState *s = kvm_state;
++ unsigned int n;
+ int i;
+
+- for (i = 0; i < s->nr_slots; i++) {
++ for (i = 0; i < kml->nr_slots_allocated; i++) {
+ if (kml->slots[i].memory_size == 0) {
+ return &kml->slots[i];
+ }
+ }
+
++ /*
++ * If no free slots, try to grow first by doubling. Cache the old size
++ * here to avoid another round of search: if the grow succeeded, it
++ * means slots[] now must have the existing "n" slots occupied,
++ * followed by one or more free slots starting from slots[n].
++ */
++ n = kml->nr_slots_allocated;
++ if (kvm_slots_double(kml)) {
++ return &kml->slots[n];
++ }
++
+ return NULL;
+ }
+
+@@ -224,10 +289,9 @@ static KVMSlot *kvm_lookup_matching_slot(KVMMemoryListener *kml,
+ hwaddr start_addr,
+ hwaddr size)
+ {
+- KVMState *s = kvm_state;
+ int i;
+
+- for (i = 0; i < s->nr_slots; i++) {
++ for (i = 0; i < kml->nr_slots_allocated; i++) {
+ KVMSlot *mem = &kml->slots[i];
+
+ if (start_addr == mem->start_addr && size == mem->memory_size) {
+@@ -269,7 +333,7 @@ int kvm_physical_memory_addr_from_host(KVMState *s, void *ram,
+ int i, ret = 0;
+
+ kvm_slots_lock();
+- for (i = 0; i < s->nr_slots; i++) {
++ for (i = 0; i < kml->nr_slots_allocated; i++) {
+ KVMSlot *mem = &kml->slots[i];
+
+ if (ram >= mem->ram && ram < mem->ram + mem->memory_size) {
+@@ -991,7 +1055,7 @@ static int kvm_physical_log_clear(KVMMemoryListener *kml,
+
+ kvm_slots_lock();
+
+- for (i = 0; i < s->nr_slots; i++) {
++ for (i = 0; i < kml->nr_slots_allocated; i++) {
+ mem = &kml->slots[i];
+ /* Discard slots that are empty or do not overlap the section */
+ if (!mem->memory_size ||
+@@ -1482,19 +1546,14 @@ static void kvm_log_sync(MemoryListener *listener,
+ static void kvm_log_sync_global(MemoryListener *l)
+ {
+ KVMMemoryListener *kml = container_of(l, KVMMemoryListener, listener);
+- KVMState *s = kvm_state;
+ KVMSlot *mem;
+ int i;
+
+ /* Flush all kernel dirty addresses into KVMSlot dirty bitmap */
+ kvm_dirty_ring_flush();
+
+- /*
+- * TODO: make this faster when nr_slots is big while there are
+- * only a few used slots (small VMs).
+- */
+ kvm_slots_lock();
+- for (i = 0; i < s->nr_slots; i++) {
++ for (i = 0; i < kml->nr_slots_allocated; i++) {
+ mem = &kml->slots[i];
+ if (mem->memory_size && mem->flags & KVM_MEM_LOG_DIRTY_PAGES) {
+ kvm_slot_sync_dirty_pages(mem);
+@@ -1603,12 +1662,9 @@ void kvm_memory_listener_register(KVMState *s, KVMMemoryListener *kml,
+ {
+ int i;
+
+- kml->slots = g_new0(KVMSlot, s->nr_slots);
+ kml->as_id = as_id;
+
+- for (i = 0; i < s->nr_slots; i++) {
+- kml->slots[i].slot = i;
+- }
++ kvm_slots_grow(kml, KVM_MEMSLOTS_NR_ALLOC_DEFAULT);
+
+ kml->listener.region_add = kvm_region_add;
+ kml->listener.region_del = kvm_region_del;
+diff --git a/accel/kvm/trace-events b/accel/kvm/trace-events
+index 399aaeb0ec..a1965a50c5 100644
+--- a/accel/kvm/trace-events
++++ b/accel/kvm/trace-events
+@@ -26,3 +26,4 @@ kvm_dirty_ring_reap(uint64_t count, int64_t t) "reaped %"PRIu64" pages (took %"P
+ kvm_dirty_ring_reaper_kick(const char *reason) "%s"
+ kvm_dirty_ring_flush(int finished) "%d"
+
++kvm_slots_grow(unsigned int old, unsigned int new) "%u -> %u"
+diff --git a/block/copy-before-write.c b/block/copy-before-write.c
+index 4abaa7339e..8748aad5a4 100644
+--- a/block/copy-before-write.c
++++ b/block/copy-before-write.c
+@@ -64,7 +64,8 @@ typedef struct BDRVCopyBeforeWriteState {
+
+ /*
+ * @frozen_read_reqs: current read requests for fleecing user in bs->file
+- * node. These areas must not be rewritten by guest.
++ * node. These areas must not be rewritten by guest. There can be multiple
++ * overlapping read requests.
+ */
+ BlockReqList frozen_read_reqs;
+
+diff --git a/block/raw-format.c b/block/raw-format.c
+index a68014ef0b..f3fc604f92 100644
+--- a/block/raw-format.c
++++ b/block/raw-format.c
+@@ -110,7 +110,7 @@ static int raw_apply_options(BlockDriverState *bs, BDRVRawState *s,
+ if (offset > real_size) {
+ error_setg(errp, "Offset (%" PRIu64 ") cannot be greater than "
+ "size of the containing file (%" PRId64 ")",
+- s->offset, real_size);
++ offset, real_size);
+ return -EINVAL;
+ }
+
+@@ -118,7 +118,7 @@ static int raw_apply_options(BlockDriverState *bs, BDRVRawState *s,
+ error_setg(errp, "The sum of offset (%" PRIu64 ") and size "
+ "(%" PRIu64 ") has to be smaller or equal to the "
+ " actual size of the containing file (%" PRId64 ")",
+- s->offset, s->size, real_size);
++ offset, size, real_size);
+ return -EINVAL;
+ }
+
+diff --git a/block/reqlist.c b/block/reqlist.c
+index 08cb57cfa4..098e807378 100644
+--- a/block/reqlist.c
++++ b/block/reqlist.c
+@@ -20,8 +20,6 @@
+ void reqlist_init_req(BlockReqList *reqs, BlockReq *req, int64_t offset,
+ int64_t bytes)
+ {
+- assert(!reqlist_find_conflict(reqs, offset, bytes));
+-
+ *req = (BlockReq) {
+ .offset = offset,
+ .bytes = bytes,
+diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c
+index 072cf67956..51ad5bfb11 100644
+--- a/hw/9pfs/9p.c
++++ b/hw/9pfs/9p.c
+@@ -2596,6 +2596,11 @@ static void coroutine_fn v9fs_readdir(void *opaque)
+ retval = -EINVAL;
+ goto out_nofid;
+ }
++ if (fidp->fid_type != P9_FID_DIR) {
++ warn_report_once("9p: bad client: T_readdir on non-directory stream");
++ retval = -ENOTDIR;
++ goto out;
++ }
+ if (!fidp->fs.dir.stream) {
+ retval = -EINVAL;
+ goto out;
+diff --git a/hw/audio/hda-codec.c b/hw/audio/hda-codec.c
+index 0f66754b6a..5c75a3a59a 100644
+--- a/hw/audio/hda-codec.c
++++ b/hw/audio/hda-codec.c
+@@ -488,8 +488,7 @@ static void hda_audio_setup(HDAAudioStream *st)
+ if (st->output) {
+ if (use_timer) {
+ cb = hda_audio_output_cb;
+- st->buft = timer_new_ns(QEMU_CLOCK_VIRTUAL,
+- hda_audio_output_timer, st);
++ timer_del(st->buft);
+ } else {
+ cb = hda_audio_compat_output_cb;
+ }
+@@ -498,8 +497,7 @@ static void hda_audio_setup(HDAAudioStream *st)
+ } else {
+ if (use_timer) {
+ cb = hda_audio_input_cb;
+- st->buft = timer_new_ns(QEMU_CLOCK_VIRTUAL,
+- hda_audio_input_timer, st);
++ timer_del(st->buft);
+ } else {
+ cb = hda_audio_compat_input_cb;
+ }
+@@ -722,8 +720,12 @@ static int hda_audio_init(HDACodecDevice *hda, const struct desc_codec *desc)
+ st->gain_right = QEMU_HDA_AMP_STEPS;
+ st->compat_bpos = sizeof(st->compat_buf);
+ st->output = true;
++ st->buft = timer_new_ns(QEMU_CLOCK_VIRTUAL,
++ hda_audio_output_timer, st);
+ } else {
+ st->output = false;
++ st->buft = timer_new_ns(QEMU_CLOCK_VIRTUAL,
++ hda_audio_input_timer, st);
+ }
+ st->format = AC_FMT_TYPE_PCM | AC_FMT_BITS_16 |
+ (1 << AC_FMT_CHAN_SHIFT);
+@@ -747,9 +749,7 @@ static void hda_audio_exit(HDACodecDevice *hda)
+ if (st->node == NULL) {
+ continue;
+ }
+- if (a->use_timer) {
+- timer_del(st->buft);
+- }
++ timer_free(st->buft);
+ if (st->output) {
+ AUD_close_out(&a->card, st->voice.out);
+ } else {
+diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
+index ddfbc69d65..9811fb3fb4 100644
+--- a/hw/intc/arm_gicv3_cpuif.c
++++ b/hw/intc/arm_gicv3_cpuif.c
+@@ -751,7 +751,7 @@ static void icv_activate_vlpi(GICv3CPUState *cs)
+ int regno = aprbit / 32;
+ int regbit = aprbit % 32;
+
+- cs->ich_apr[cs->hppvlpi.grp][regno] |= (1 << regbit);
++ cs->ich_apr[cs->hppvlpi.grp][regno] |= (1U << regbit);
+ gicv3_redist_vlpi_pending(cs, cs->hppvlpi.irq, 0);
+ }
+
+diff --git a/hw/intc/riscv_aplic.c b/hw/intc/riscv_aplic.c
+index 961caff7b6..153827a056 100644
+--- a/hw/intc/riscv_aplic.c
++++ b/hw/intc/riscv_aplic.c
+@@ -148,18 +148,42 @@
+
+ #define APLIC_IDC_CLAIMI 0x1c
+
++static bool riscv_aplic_irq_rectified_val(RISCVAPLICState *aplic,
++ uint32_t irq)
++{
++ uint32_t sourcecfg, sm, raw_input, irq_inverted;
++
++ if (!irq || aplic->num_irqs <= irq) {
++ return false;
++ }
++
++ sourcecfg = aplic->sourcecfg[irq];
++ if (sourcecfg & APLIC_SOURCECFG_D) {
++ return false;
++ }
++
++ sm = sourcecfg & APLIC_SOURCECFG_SM_MASK;
++ if (sm == APLIC_SOURCECFG_SM_INACTIVE) {
++ return false;
++ }
++
++ raw_input = (aplic->state[irq] & APLIC_ISTATE_INPUT) ? 1 : 0;
++ irq_inverted = (sm == APLIC_SOURCECFG_SM_LEVEL_LOW ||
++ sm == APLIC_SOURCECFG_SM_EDGE_FALL) ? 1 : 0;
++
++ return !!(raw_input ^ irq_inverted);
++}
++
+ static uint32_t riscv_aplic_read_input_word(RISCVAPLICState *aplic,
+ uint32_t word)
+ {
+- uint32_t i, irq, ret = 0;
++ uint32_t i, irq, rectified_val, ret = 0;
+
+ for (i = 0; i < 32; i++) {
+ irq = word * 32 + i;
+- if (!irq || aplic->num_irqs <= irq) {
+- continue;
+- }
+
+- ret |= ((aplic->state[irq] & APLIC_ISTATE_INPUT) ? 1 : 0) << i;
++ rectified_val = riscv_aplic_irq_rectified_val(aplic, irq);
++ ret |= rectified_val << i;
+ }
+
+ return ret;
+@@ -665,6 +689,10 @@ static void riscv_aplic_write(void *opaque, hwaddr addr, uint64_t value,
+ (aplic->sourcecfg[irq] == 0)) {
+ riscv_aplic_set_pending_raw(aplic, irq, false);
+ riscv_aplic_set_enabled_raw(aplic, irq, false);
++ } else {
++ if (riscv_aplic_irq_rectified_val(aplic, irq)) {
++ riscv_aplic_set_pending_raw(aplic, irq, true);
++ }
+ }
+ } else if (aplic->mmode && aplic->msimode &&
+ (addr == APLIC_MMSICFGADDR)) {
+diff --git a/hw/intc/sifive_plic.c b/hw/intc/sifive_plic.c
+index c2dfacf028..7a42c4b792 100644
+--- a/hw/intc/sifive_plic.c
++++ b/hw/intc/sifive_plic.c
+@@ -331,8 +331,10 @@ static void sifive_plic_irq_request(void *opaque, int irq, int level)
+ {
+ SiFivePLICState *s = opaque;
+
+- sifive_plic_set_pending(s, irq, level > 0);
+- sifive_plic_update(s);
++ if (level > 0) {
++ sifive_plic_set_pending(s, irq, true);
++ sifive_plic_update(s);
++ }
+ }
+
+ static void sifive_plic_realize(DeviceState *dev, Error **errp)
+diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c
+index ed56ad40b3..5710392e30 100644
+--- a/hw/nvme/ctrl.c
++++ b/hw/nvme/ctrl.c
+@@ -1385,9 +1385,16 @@ static void nvme_post_cqes(void *opaque)
+ stl_le_p(&n->bar.csts, NVME_CSTS_FAILED);
+ break;
+ }
++
+ QTAILQ_REMOVE(&cq->req_list, req, entry);
++
+ nvme_inc_cq_tail(cq);
+ nvme_sg_unmap(&req->sg);
++
++ if (QTAILQ_EMPTY(&sq->req_list) && !nvme_sq_empty(sq)) {
++ qemu_bh_schedule(sq->bh);
++ }
++
+ QTAILQ_INSERT_TAIL(&sq->req_list, req, entry);
+ }
+ if (cq->tail != cq->head) {
+@@ -6792,7 +6799,6 @@ static void nvme_process_db(NvmeCtrl *n, hwaddr addr, int val)
+ /* Completion queue doorbell write */
+
+ uint16_t new_head = val & 0xffff;
+- int start_sqs;
+ NvmeCQueue *cq;
+
+ qid = (addr - (0x1000 + (1 << 2))) >> 3;
+@@ -6843,19 +6849,16 @@ static void nvme_process_db(NvmeCtrl *n, hwaddr addr, int val)
+
+ trace_pci_nvme_mmio_doorbell_cq(cq->cqid, new_head);
+
+- start_sqs = nvme_cq_full(cq) ? 1 : 0;
++ /* scheduled deferred cqe posting if queue was previously full */
++ if (nvme_cq_full(cq)) {
++ qemu_bh_schedule(cq->bh);
++ }
++
+ cq->head = new_head;
+ if (!qid && n->dbbuf_enabled) {
+ pci_dma_write(&n->parent_obj, cq->db_addr, &cq->head,
+ sizeof(cq->head));
+ }
+- if (start_sqs) {
+- NvmeSQueue *sq;
+- QTAILQ_FOREACH(sq, &cq->sq_list, entry) {
+- qemu_bh_schedule(sq->bh);
+- }
+- qemu_bh_schedule(cq->bh);
+- }
+
+ if (cq->tail == cq->head) {
+ if (cq->irq_enabled) {
+diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c
+index e5c9f7a53d..e76bfbd47b 100644
+--- a/hw/scsi/scsi-bus.c
++++ b/hw/scsi/scsi-bus.c
+@@ -413,19 +413,35 @@ static const struct SCSIReqOps reqops_invalid_opcode = {
+
+ /* SCSIReqOps implementation for unit attention conditions. */
+
+-static int32_t scsi_unit_attention(SCSIRequest *req, uint8_t *buf)
++static void scsi_fetch_unit_attention_sense(SCSIRequest *req)
+ {
++ SCSISense *ua = NULL;
++
+ if (req->dev->unit_attention.key == UNIT_ATTENTION) {
+- scsi_req_build_sense(req, req->dev->unit_attention);
++ ua = &req->dev->unit_attention;
+ } else if (req->bus->unit_attention.key == UNIT_ATTENTION) {
+- scsi_req_build_sense(req, req->bus->unit_attention);
++ ua = &req->bus->unit_attention;
+ }
++
++ /*
++ * Fetch the unit attention sense immediately so that another
++ * scsi_req_new does not use reqops_unit_attention.
++ */
++ if (ua) {
++ scsi_req_build_sense(req, *ua);
++ *ua = SENSE_CODE(NO_SENSE);
++ }
++}
++
++static int32_t scsi_unit_attention(SCSIRequest *req, uint8_t *buf)
++{
+ scsi_req_complete(req, CHECK_CONDITION);
+ return 0;
+ }
+
+ static const struct SCSIReqOps reqops_unit_attention = {
+ .size = sizeof(SCSIRequest),
++ .init_req = scsi_fetch_unit_attention_sense,
+ .send_command = scsi_unit_attention
+ };
+
+@@ -699,6 +715,11 @@ SCSIRequest *scsi_req_alloc(const SCSIReqOps *reqops, SCSIDevice *d,
+ object_ref(OBJECT(d));
+ object_ref(OBJECT(qbus->parent));
+ notifier_list_init(&req->cancel_notifiers);
++
++ if (reqops->init_req) {
++ reqops->init_req(req);
++ }
++
+ trace_scsi_req_alloc(req->dev->id, req->lun, req->tag);
+ return req;
+ }
+@@ -798,6 +819,15 @@ uint8_t *scsi_req_get_buf(SCSIRequest *req)
+ static void scsi_clear_unit_attention(SCSIRequest *req)
+ {
+ SCSISense *ua;
++
++ /*
++ * scsi_fetch_unit_attention_sense() already cleaned the unit attention
++ * in this case.
++ */
++ if (req->ops == &reqops_unit_attention) {
++ return;
++ }
++
+ if (req->dev->unit_attention.key != UNIT_ATTENTION &&
+ req->bus->unit_attention.key != UNIT_ATTENTION) {
+ return;
+diff --git a/hw/usb/dev-hub.c b/hw/usb/dev-hub.c
+index a6b50dbc8d..ccedd2bcd2 100644
+--- a/hw/usb/dev-hub.c
++++ b/hw/usb/dev-hub.c
+@@ -479,6 +479,7 @@ static void usb_hub_handle_control(USBDevice *dev, USBPacket *p,
+ usb_hub_port_clear(port, PORT_STAT_SUSPEND);
+ port->wPortChange = 0;
+ }
++ break;
+ default:
+ goto fail;
+ }
+diff --git a/include/hw/misc/mos6522.h b/include/hw/misc/mos6522.h
+index 0bc22a8395..1183d404e9 100644
+--- a/include/hw/misc/mos6522.h
++++ b/include/hw/misc/mos6522.h
+@@ -155,7 +155,7 @@ struct MOS6522State {
+ OBJECT_DECLARE_TYPE(MOS6522State, MOS6522DeviceClass, MOS6522)
+
+ struct MOS6522DeviceClass {
+- DeviceClass parent_class;
++ SysBusDeviceClass parent_class;
+
+ DeviceReset parent_reset;
+ void (*portB_write)(MOS6522State *dev);
+diff --git a/include/hw/scsi/scsi.h b/include/hw/scsi/scsi.h
+index 6ea4b64fe7..60bc32da32 100644
+--- a/include/hw/scsi/scsi.h
++++ b/include/hw/scsi/scsi.h
+@@ -108,6 +108,7 @@ int cdrom_read_toc_raw(int nb_sectors, uint8_t *buf, int msf, int session_num);
+ /* scsi-bus.c */
+ struct SCSIReqOps {
+ size_t size;
++ void (*init_req)(SCSIRequest *req);
+ void (*free_req)(SCSIRequest *req);
+ int32_t (*send_command)(SCSIRequest *req, uint8_t *buf);
+ void (*read_data)(SCSIRequest *req);
+diff --git a/include/sysemu/kvm_int.h b/include/sysemu/kvm_int.h
+index 3b4adcdc10..269c925cb1 100644
+--- a/include/sysemu/kvm_int.h
++++ b/include/sysemu/kvm_int.h
+@@ -34,6 +34,7 @@ typedef struct KVMSlot
+ typedef struct KVMMemoryListener {
+ MemoryListener listener;
+ KVMSlot *slots;
++ unsigned int nr_slots_allocated;
+ int as_id;
+ } KVMMemoryListener;
+
+diff --git a/linux-user/elfload.c b/linux-user/elfload.c
+index 87895847ec..97528a13ed 100644
+--- a/linux-user/elfload.c
++++ b/linux-user/elfload.c
+@@ -2899,11 +2899,11 @@ static bool parse_elf_properties(int image_fd,
+ }
+
+ /*
+- * The contents of a valid PT_GNU_PROPERTY is a sequence
+- * of uint32_t -- swap them all now.
++ * The contents of a valid PT_GNU_PROPERTY is a sequence of uint32_t.
++ * Swap most of them now, beyond the header and namesz.
+ */
+ #ifdef BSWAP_NEEDED
+- for (int i = 0; i < n / 4; i++) {
++ for (int i = 4; i < n / 4; i++) {
+ bswap32s(note.data + i);
+ }
+ #endif
+@@ -2913,15 +2913,15 @@ static bool parse_elf_properties(int image_fd,
+ * immediately follows nhdr and is thus at the 4th word. Further, all
+ * of the inputs to the kernel's round_up are multiples of 4.
+ */
+- if (note.nhdr.n_type != NT_GNU_PROPERTY_TYPE_0 ||
+- note.nhdr.n_namesz != NOTE_NAME_SZ ||
++ if (tswap32(note.nhdr.n_type) != NT_GNU_PROPERTY_TYPE_0 ||
++ tswap32(note.nhdr.n_namesz) != NOTE_NAME_SZ ||
+ note.data[3] != GNU0_MAGIC) {
+ error_setg(errp, "Invalid note in PT_GNU_PROPERTY");
+ return false;
+ }
+ off = sizeof(note.nhdr) + NOTE_NAME_SZ;
+
+- datasz = note.nhdr.n_descsz + off;
++ datasz = tswap32(note.nhdr.n_descsz) + off;
+ if (datasz > n) {
+ error_setg(errp, "Invalid note size in PT_GNU_PROPERTY");
+ return false;
+diff --git a/linux-user/flatload.c b/linux-user/flatload.c
+index e99570ca18..7f243500b3 100644
+--- a/linux-user/flatload.c
++++ b/linux-user/flatload.c
+@@ -747,7 +747,10 @@ int load_flt_binary(struct linux_binprm *bprm, struct image_info *info)
+ stack_len += (bprm->envc + 1) * 4; /* the envp array */
+
+
++ mmap_lock();
+ res = load_flat_file(bprm, libinfo, 0, &stack_len);
++ mmap_unlock();
++
+ if (is_error(res)) {
+ return res;
+ }
+diff --git a/linux-user/ppc/signal.c b/linux-user/ppc/signal.c
+index 07729c1653..6968c817dc 100644
+--- a/linux-user/ppc/signal.c
++++ b/linux-user/ppc/signal.c
+@@ -617,7 +617,7 @@ static int do_setcontext(struct target_ucontext *ucp, CPUPPCState *env, int sig)
+ if (!lock_user_struct(VERIFY_READ, mcp, mcp_addr, 1))
+ return 1;
+
+- target_to_host_sigset_internal(&blocked, &set);
++ target_to_host_sigset(&blocked, &set);
+ set_sigmask(&blocked);
+ restore_user_regs(env, mcp, sig);
+
+diff --git a/linux-user/syscall.c b/linux-user/syscall.c
+index 53c46ae951..236076e647 100644
+--- a/linux-user/syscall.c
++++ b/linux-user/syscall.c
+@@ -7233,12 +7233,24 @@ static inline int tswapid(int id)
+ #else
+ #define __NR_sys_setgroups __NR_setgroups
+ #endif
++#ifdef __NR_sys_setreuid32
++#define __NR_sys_setreuid __NR_setreuid32
++#else
++#define __NR_sys_setreuid __NR_setreuid
++#endif
++#ifdef __NR_sys_setregid32
++#define __NR_sys_setregid __NR_setregid32
++#else
++#define __NR_sys_setregid __NR_setregid
++#endif
+
+ _syscall1(int, sys_setuid, uid_t, uid)
+ _syscall1(int, sys_setgid, gid_t, gid)
+ _syscall3(int, sys_setresuid, uid_t, ruid, uid_t, euid, uid_t, suid)
+ _syscall3(int, sys_setresgid, gid_t, rgid, gid_t, egid, gid_t, sgid)
+ _syscall2(int, sys_setgroups, int, size, gid_t *, grouplist)
++_syscall2(int, sys_setreuid, uid_t, ruid, uid_t, euid);
++_syscall2(int, sys_setregid, gid_t, rgid, gid_t, egid);
+
+ void syscall_init(void)
+ {
+@@ -11399,9 +11411,9 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
+ return get_errno(high2lowgid(getegid()));
+ #endif
+ case TARGET_NR_setreuid:
+- return get_errno(setreuid(low2highuid(arg1), low2highuid(arg2)));
++ return get_errno(sys_setreuid(low2highuid(arg1), low2highuid(arg2)));
+ case TARGET_NR_setregid:
+- return get_errno(setregid(low2highgid(arg1), low2highgid(arg2)));
++ return get_errno(sys_setregid(low2highgid(arg1), low2highgid(arg2)));
+ case TARGET_NR_getgroups:
+ {
+ int gidsetsize = arg1;
+@@ -11731,11 +11743,11 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
+ #endif
+ #ifdef TARGET_NR_setreuid32
+ case TARGET_NR_setreuid32:
+- return get_errno(setreuid(arg1, arg2));
++ return get_errno(sys_setreuid(arg1, arg2));
+ #endif
+ #ifdef TARGET_NR_setregid32
+ case TARGET_NR_setregid32:
+- return get_errno(setregid(arg1, arg2));
++ return get_errno(sys_setregid(arg1, arg2));
+ #endif
+ #ifdef TARGET_NR_getgroups32
+ case TARGET_NR_getgroups32:
+diff --git a/net/colo-compare.c b/net/colo-compare.c
+index 787c740f14..ccc5206084 100644
+--- a/net/colo-compare.c
++++ b/net/colo-compare.c
+@@ -413,8 +413,7 @@ static void colo_compare_tcp(CompareState *s, Connection *conn)
+ * can ensure that the packet's payload is acknowledged by
+ * primary and secondary.
+ */
+- uint32_t min_ack = conn->pack - conn->sack > 0 ?
+- conn->sack : conn->pack;
++ uint32_t min_ack = MIN(conn->pack, conn->sack);
+
+ pri:
+ if (g_queue_is_empty(&conn->primary_list)) {
+diff --git a/net/tap-win32.c b/net/tap-win32.c
+index a49c28ba5d..16c21d971a 100644
+--- a/net/tap-win32.c
++++ b/net/tap-win32.c
+@@ -214,7 +214,7 @@ static int is_tap_win32_dev(const char *guid)
+
+ for (;;) {
+ char enum_name[256];
+- char unit_string[256];
++ g_autofree char *unit_string = NULL;
+ HKEY unit_key;
+ char component_id_string[] = "ComponentId";
+ char component_id[256];
+@@ -239,8 +239,7 @@ static int is_tap_win32_dev(const char *guid)
+ return FALSE;
+ }
+
+- snprintf (unit_string, sizeof(unit_string), "%s\\%s",
+- ADAPTER_KEY, enum_name);
++ unit_string = g_strdup_printf("%s\\%s", ADAPTER_KEY, enum_name);
+
+ status = RegOpenKeyEx(
+ HKEY_LOCAL_MACHINE,
+@@ -315,7 +314,7 @@ static int get_device_guid(
+ while (!stop)
+ {
+ char enum_name[256];
+- char connection_string[256];
++ g_autofree char *connection_string = NULL;
+ HKEY connection_key;
+ char name_data[256];
+ DWORD name_type;
+@@ -338,9 +337,7 @@ static int get_device_guid(
+ return -1;
+ }
+
+- snprintf(connection_string,
+- sizeof(connection_string),
+- "%s\\%s\\Connection",
++ connection_string = g_strdup_printf("%s\\%s\\Connection",
+ NETWORK_CONNECTIONS_KEY, enum_name);
+
+ status = RegOpenKeyEx(
+@@ -595,7 +592,7 @@ static void tap_win32_free_buffer(tap_win32_overlapped_t *overlapped,
+ static int tap_win32_open(tap_win32_overlapped_t **phandle,
+ const char *preferred_name)
+ {
+- char device_path[256];
++ g_autofree char *device_path = NULL;
+ char device_guid[0x100];
+ int rc;
+ HANDLE handle;
+@@ -617,7 +614,7 @@ static int tap_win32_open(tap_win32_overlapped_t **phandle,
+ if (rc)
+ return -1;
+
+- snprintf (device_path, sizeof(device_path), "%s%s%s",
++ device_path = g_strdup_printf("%s%s%s",
+ USERMODEDEVICEDIR,
+ device_guid,
+ TAPSUFFIX);
+diff --git a/scripts/oss-fuzz/build.sh b/scripts/oss-fuzz/build.sh
+index 3bda0d72c7..6c2a546994 100755
+--- a/scripts/oss-fuzz/build.sh
++++ b/scripts/oss-fuzz/build.sh
+@@ -92,6 +92,7 @@ make install DESTDIR=$DEST_DIR/qemu-bundle
+ rm -rf $DEST_DIR/qemu-bundle/opt/qemu-oss-fuzz/bin
+ rm -rf $DEST_DIR/qemu-bundle/opt/qemu-oss-fuzz/libexec
+
++export ASAN_OPTIONS=detect_leaks=0
+ targets=$(./qemu-fuzz-i386 | grep generic-fuzz | awk '$1 ~ /\*/ {print $2}')
+ base_copy="$DEST_DIR/qemu-fuzz-i386-target-$(echo "$targets" | head -n 1)"
+
+diff --git a/scripts/tracetool/__init__.py b/scripts/tracetool/__init__.py
+index cd46e7597c..e31aaedcbb 100644
+--- a/scripts/tracetool/__init__.py
++++ b/scripts/tracetool/__init__.py
+@@ -223,12 +223,12 @@ class Event(object):
+
+ """
+
+- _CRE = re.compile("((?P<props>[\w\s]+)\s+)?"
+- "(?P<name>\w+)"
+- "\((?P<args>[^)]*)\)"
+- "\s*"
+- "(?:(?:(?P<fmt_trans>\".+),)?\s*(?P<fmt>\".+))?"
+- "\s*")
++ _CRE = re.compile(r"((?P<props>[\w\s]+)\s+)?"
++ r"(?P<name>\w+)"
++ r"\((?P<args>[^)]*)\)"
++ r"\s*"
++ r"(?:(?:(?P<fmt_trans>\".+),)?\s*(?P<fmt>\".+))?"
++ r"\s*")
+
+ _VALID_PROPS = set(["disable", "vcpu"])
+
+@@ -339,7 +339,7 @@ def __repr__(self):
+ fmt)
+ # Star matching on PRI is dangerous as one might have multiple
+ # arguments with that format, hence the non-greedy version of it.
+- _FMT = re.compile("(%[\d\.]*\w+|%.*?PRI\S+)")
++ _FMT = re.compile(r"(%[\d\.]*\w+|%.*?PRI\S+)")
+
+ def formats(self):
+ """List conversion specifiers in the argument print format string."""
+diff --git a/scripts/tracetool/format/log_stap.py b/scripts/tracetool/format/log_stap.py
+index 0b6549d534..b49afababd 100644
+--- a/scripts/tracetool/format/log_stap.py
++++ b/scripts/tracetool/format/log_stap.py
+@@ -83,7 +83,7 @@ def c_fmt_to_stap(fmt):
+ # and "%ll" is not valid at all. Similarly the size_t
+ # based "%z" size qualifier is not valid. We just
+ # strip all size qualifiers for sanity.
+- fmt = re.sub("%(\d*)(l+|z)(x|u|d)", "%\\1\\3", "".join(bits))
++ fmt = re.sub(r"%(\d*)(l+|z)(x|u|d)", r"%\1\3", "".join(bits))
+ return fmt
+
+ def generate(events, backend, group):
+diff --git a/softmmu/physmem.c b/softmmu/physmem.c
+index 5b176581f6..b96534ea16 100644
+--- a/softmmu/physmem.c
++++ b/softmmu/physmem.c
+@@ -3245,7 +3245,7 @@ void *address_space_map(AddressSpace *as,
+ memory_region_ref(mr);
+ bounce.mr = mr;
+ if (!is_write) {
+- flatview_read(fv, addr, MEMTXATTRS_UNSPECIFIED,
++ flatview_read(fv, addr, attrs,
+ bounce.buffer, l);
+ }
+
+diff --git a/target/arm/internals.h b/target/arm/internals.h
+index 3c7ff51c99..bdd89ae21e 100644
+--- a/target/arm/internals.h
++++ b/target/arm/internals.h
+@@ -723,6 +723,7 @@ static inline uint32_t regime_el(CPUARMState *env, ARMMMUIdx mmu_idx)
+ static inline bool regime_is_user(CPUARMState *env, ARMMMUIdx mmu_idx)
+ {
+ switch (mmu_idx) {
++ case ARMMMUIdx_E10_0:
+ case ARMMMUIdx_E20_0:
+ case ARMMMUIdx_Stage1_E0:
+ case ARMMMUIdx_MUser:
+@@ -732,10 +733,6 @@ static inline bool regime_is_user(CPUARMState *env, ARMMMUIdx mmu_idx)
+ return true;
+ default:
+ return false;
+- case ARMMMUIdx_E10_0:
+- case ARMMMUIdx_E10_1:
+- case ARMMMUIdx_E10_1_PAN:
+- g_assert_not_reached();
+ }
+ }
+
+diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
+index 45a93755fe..989257416e 100644
+--- a/target/arm/sve_helper.c
++++ b/target/arm/sve_helper.c
+@@ -6309,9 +6309,6 @@ void sve_stN_r(CPUARMState *env, uint64_t *vg, target_ulong addr,
+
+ flags = info.page[0].flags | info.page[1].flags;
+ if (unlikely(flags != 0)) {
+-#ifdef CONFIG_USER_ONLY
+- g_assert_not_reached();
+-#else
+ /*
+ * At least one page includes MMIO.
+ * Any bus operation can fail with cpu_transaction_failed,
+@@ -6342,7 +6339,6 @@ void sve_stN_r(CPUARMState *env, uint64_t *vg, target_ulong addr,
+ } while (reg_off & 63);
+ } while (reg_off <= reg_last);
+ return;
+-#endif
+ }
+
+ mem_off = info.mem_off_first[0];
+diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
+index 859366e264..77678aca78 100644
+--- a/target/arm/vec_helper.c
++++ b/target/arm/vec_helper.c
+@@ -691,6 +691,13 @@ void HELPER(NAME)(void *vd, void *vn, void *vm, void *va, uint32_t desc) \
+ { \
+ intptr_t i = 0, opr_sz = simd_oprsz(desc); \
+ intptr_t opr_sz_n = opr_sz / sizeof(TYPED); \
++ /* \
++ * Special case: opr_sz == 8 from AA64/AA32 advsimd means the \
++ * first iteration might not be a full 16 byte segment. But \
++ * for vector lengths beyond that this must be SVE and we know \
++ * opr_sz is a multiple of 16, so we need not clamp segend \
++ * to opr_sz_n when we advance it at the end of the loop. \
++ */ \
+ intptr_t segend = MIN(16 / sizeof(TYPED), opr_sz_n); \
+ intptr_t index = simd_data(desc); \
+ TYPED *d = vd, *a = va; \
+@@ -708,7 +715,7 @@ void HELPER(NAME)(void *vd, void *vn, void *vm, void *va, uint32_t desc) \
+ n[i * 4 + 2] * m2 + \
+ n[i * 4 + 3] * m3); \
+ } while (++i < segend); \
+- segend = i + 4; \
++ segend = i + (16 / sizeof(TYPED)); \
+ } while (i < opr_sz_n); \
+ clear_tail(d, opr_sz, simd_maxsz(desc)); \
+ }
+diff --git a/target/i386/cpu.h b/target/i386/cpu.h
+index 326649ca99..59c39fe527 100644
+--- a/target/i386/cpu.h
++++ b/target/i386/cpu.h
+@@ -336,6 +336,7 @@ typedef enum X86Seg {
+ #define PG_MODE_PKE (1 << 17)
+ #define PG_MODE_PKS (1 << 18)
+ #define PG_MODE_SMEP (1 << 19)
++#define PG_MODE_PG (1 << 20)
+
+ #define MCG_CTL_P (1ULL<<8) /* MCG_CAP register available */
+ #define MCG_SER_P (1ULL<<24) /* MCA recovery/new status bits */
+diff --git a/target/i386/tcg/seg_helper.c b/target/i386/tcg/seg_helper.c
+index 539189b4d1..1fa334a743 100644
+--- a/target/i386/tcg/seg_helper.c
++++ b/target/i386/tcg/seg_helper.c
+@@ -30,7 +30,7 @@
+
+ int get_pg_mode(CPUX86State *env)
+ {
+- int pg_mode = 0;
++ int pg_mode = PG_MODE_PG;
+ if (!(env->cr[0] & CR0_PG_MASK)) {
+ return 0;
+ }
+diff --git a/target/i386/tcg/sysemu/excp_helper.c b/target/i386/tcg/sysemu/excp_helper.c
+index 5f13252d68..9e9e02e1ad 100644
+--- a/target/i386/tcg/sysemu/excp_helper.c
++++ b/target/i386/tcg/sysemu/excp_helper.c
+@@ -146,6 +146,8 @@ static bool mmu_translate(CPUX86State *env, const TranslateParams *in,
+ hwaddr pte_addr, paddr;
+ uint32_t pkr;
+ int page_size;
++ int error_code;
++ int prot;
+
+ restart_all:
+ rsvd_mask = ~MAKE_64BIT_MASK(0, env_archcpu(env)->phys_bits);
+@@ -294,7 +296,7 @@ static bool mmu_translate(CPUX86State *env, const TranslateParams *in,
+ /* combine pde and pte nx, user and rw protections */
+ ptep &= pte ^ PG_NX_MASK;
+ page_size = 4096;
+- } else {
++ } else if (pg_mode & PG_MODE_PG) {
+ /*
+ * Page table level 2
+ */
+@@ -339,6 +341,15 @@ static bool mmu_translate(CPUX86State *env, const TranslateParams *in,
+ ptep &= pte | PG_NX_MASK;
+ page_size = 4096;
+ rsvd_mask = 0;
++ } else {
++ /*
++ * No paging (real mode), let's tentatively resolve the address as 1:1
++ * here, but conditionally still perform an NPT walk on it later.
++ */
++ page_size = 0x40000000;
++ paddr = in->addr;
++ prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
++ goto stage2;
+ }
+
+ do_check_protect:
+@@ -354,7 +365,7 @@ do_check_protect_pse36:
+ goto do_fault_protect;
+ }
+
+- int prot = 0;
++ prot = 0;
+ if (!is_mmu_index_smap(in->mmu_idx) || !(ptep & PG_USER_MASK)) {
+ prot |= PAGE_READ;
+ if ((ptep & PG_RW_MASK) || !(is_user || (pg_mode & PG_MODE_WP))) {
+@@ -416,6 +427,7 @@ do_check_protect_pse36:
+
+ /* merge offset within page */
+ paddr = (pte & PG_ADDRESS_MASK & ~(page_size - 1)) | (addr & (page_size - 1));
++ stage2:
+
+ /*
+ * Note that NPT is walked (for both paging structures and final guest
+@@ -464,7 +476,6 @@ do_check_protect_pse36:
+ out->page_size = page_size;
+ return true;
+
+- int error_code;
+ do_fault_rsvd:
+ error_code = PG_ERROR_RSVD_MASK;
+ goto do_fault_cont;
+@@ -558,7 +569,7 @@ static bool get_physical_address(CPUX86State *env, vaddr addr,
+ addr = (uint32_t)addr;
+ }
+
+- if (likely(env->cr[0] & CR0_PG_MASK)) {
++ if (likely(env->cr[0] & CR0_PG_MASK || use_stage2)) {
+ in.cr3 = env->cr[3];
+ in.mmu_idx = mmu_idx;
+ in.ptw_idx = use_stage2 ? MMU_NESTED_IDX : MMU_PHYS_IDX;
+diff --git a/target/ppc/translate.c b/target/ppc/translate.c
+index 90f749a728..5ab6c5c861 100644
+--- a/target/ppc/translate.c
++++ b/target/ppc/translate.c
+@@ -7455,8 +7455,6 @@ static bool decode_legacy(PowerPCCPU *cpu, DisasContext *ctx, uint32_t insn)
+ opc_handler_t **table, *handler;
+ uint32_t inval;
+
+- ctx->opcode = insn;
+-
+ LOG_DISAS("translate opcode %08x (%02x %02x %02x %02x) (%s)\n",
+ insn, opc1(insn), opc2(insn), opc3(insn), opc4(insn),
+ ctx->le_mode ? "little" : "big");
+@@ -7587,6 +7585,7 @@ static void ppc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
+ ctx->base.pc_next = pc += 4;
+
+ if (!is_prefix_insn(ctx, insn)) {
++ ctx->opcode = insn;
+ ok = (decode_insn32(ctx, insn) ||
+ decode_legacy(cpu, ctx, insn));
+ } else if ((pc & 63) == 0) {
+diff --git a/target/ppc/translate/vsx-impl.c.inc b/target/ppc/translate/vsx-impl.c.inc
+index de1709809d..9e10291010 100644
+--- a/target/ppc/translate/vsx-impl.c.inc
++++ b/target/ppc/translate/vsx-impl.c.inc
+@@ -2542,7 +2542,7 @@ static bool do_lstxv_PLS_D(DisasContext *ctx, arg_PLS_D *a,
+
+ static bool do_lstxv_X(DisasContext *ctx, arg_X *a, bool store, bool paired)
+ {
+- if (paired || a->rt >= 32) {
++ if (paired || a->rt < 32) {
+ REQUIRE_VSX(ctx);
+ } else {
+ REQUIRE_VECTOR(ctx);
+diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
+index d14e95c9dc..0808cbdb19 100644
+--- a/target/riscv/cpu.c
++++ b/target/riscv/cpu.c
+@@ -581,6 +581,7 @@ static void riscv_cpu_reset(DeviceState *dev)
+ cs->exception_index = RISCV_EXCP_NONE;
+ env->load_res = -1;
+ set_default_nan_mode(1, &env->fp_status);
++ env->vill = true;
+
+ #ifndef CONFIG_USER_ONLY
+ if (riscv_feature(env, RISCV_FEATURE_DEBUG)) {
+diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
+index 3a9e25053f..039f25dc6e 100644
+--- a/target/riscv/cpu.h
++++ b/target/riscv/cpu.h
+@@ -675,8 +675,11 @@ static inline RISCVMXL riscv_cpu_sxl(CPURISCVState *env)
+ #ifdef CONFIG_USER_ONLY
+ return env->misa_mxl;
+ #else
+- return get_field(env->mstatus, MSTATUS64_SXL);
++ if (env->misa_mxl != MXL_RV32) {
++ return get_field(env->mstatus, MSTATUS64_SXL);
++ }
+ #endif
++ return MXL_RV32;
+ }
+ #endif
+
+diff --git a/target/riscv/csr.c b/target/riscv/csr.c
+index 15dba5f653..7a3bc7bea6 100644
+--- a/target/riscv/csr.c
++++ b/target/riscv/csr.c
+@@ -494,7 +494,7 @@ static RISCVException write_vxrm(CPURISCVState *env, int csrno,
+ static RISCVException read_vxsat(CPURISCVState *env, int csrno,
+ target_ulong *val)
+ {
+- *val = env->vxsat;
++ *val = env->vxsat & BIT(0);
+ return RISCV_EXCP_NONE;
+ }
+
+@@ -504,7 +504,7 @@ static RISCVException write_vxsat(CPURISCVState *env, int csrno,
+ #if !defined(CONFIG_USER_ONLY)
+ env->mstatus |= MSTATUS_VS;
+ #endif
+- env->vxsat = val;
++ env->vxsat = val & BIT(0);
+ return RISCV_EXCP_NONE;
+ }
+
+diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c
+index 0020b9a95d..a6ac61c724 100644
+--- a/target/riscv/vector_helper.c
++++ b/target/riscv/vector_helper.c
+@@ -5273,7 +5273,7 @@ void HELPER(NAME)(void *vd, void *v0, void *vs1, void *vs2, \
+ } \
+ env->vstart = 0; \
+ /* set tail elements to 1s */ \
+- vext_set_elems_1s(vd, vta, vl * esz, total_elems * esz); \
++ vext_set_elems_1s(vd, vta, num * esz, total_elems * esz); \
+ }
+
+ /* Compress into vd elements of vs2 where vs1 is enabled */
+diff --git a/tcg/tcg-op-gvec.c b/tcg/tcg-op-gvec.c
+index 079a761b04..63bcfcb1eb 100644
+--- a/tcg/tcg-op-gvec.c
++++ b/tcg/tcg-op-gvec.c
+@@ -88,7 +88,20 @@ uint32_t simd_desc(uint32_t oprsz, uint32_t maxsz, int32_t data)
+ uint32_t desc = 0;
+
+ check_size_align(oprsz, maxsz, 0);
+- tcg_debug_assert(data == sextract32(data, 0, SIMD_DATA_BITS));
++
++ /*
++ * We want to check that 'data' will fit into SIMD_DATA_BITS.
++ * However, some callers want to treat the data as a signed
++ * value (which they can later get back with simd_data())
++ * and some want to treat it as an unsigned value.
++ * So here we assert only that the data will fit into the
++ * field in at least one way. This means that some invalid
++ * values from the caller will not be detected, e.g. if the
++ * caller wants to handle the value as a signed integer but
++ * incorrectly passes us 1 << (SIMD_DATA_BITS - 1).
++ */
++ tcg_debug_assert(data == sextract32(data, 0, SIMD_DATA_BITS) ||
++ data == extract32(data, 0, SIMD_DATA_BITS));
+
+ oprsz = (oprsz / 8) - 1;
+ maxsz = (maxsz / 8) - 1;
+diff --git a/tcg/tcg.c b/tcg/tcg.c
+index 436fcf6ebd..e7aa02c447 100644
+--- a/tcg/tcg.c
++++ b/tcg/tcg.c
+@@ -716,7 +716,6 @@ TranslationBlock *tcg_tb_alloc(TCGContext *s)
+ goto retry;
+ }
+ qatomic_set(&s->code_gen_ptr, next);
+- s->data_gen_ptr = NULL;
+ return tb;
+ }
+
+@@ -4249,6 +4248,7 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb, target_ulong pc_start)
+ */
+ s->code_buf = tcg_splitwx_to_rw(tb->tc.ptr);
+ s->code_ptr = s->code_buf;
++ s->data_gen_ptr = NULL;
+
+ #ifdef TCG_TARGET_NEED_LDST_LABELS
+ QSIMPLEQ_INIT(&s->ldst_labels);
+diff --git a/tests/qtest/tpm-tests.c b/tests/qtest/tpm-tests.c
+index 25073d1f9e..7ea9038f60 100644
+--- a/tests/qtest/tpm-tests.c
++++ b/tests/qtest/tpm-tests.c
+@@ -114,7 +114,7 @@ void tpm_test_swtpm_migration_test(const char *src_tpm_path,
+ sizeof(tpm_pcrread_resp));
+
+ tpm_util_migrate(src_qemu, uri);
+- tpm_util_wait_for_migration_complete(src_qemu);
++ tpm_util_wait_for_migration_complete(dst_qemu);
+
+ tpm_util_pcrread(dst_qemu, tx, tpm_pcrread_resp,
+ sizeof(tpm_pcrread_resp));
diff --git a/debian/patches/v7.2.16.diff b/debian/patches/v7.2.16.diff
new file mode 100644
index 00000000..e1aaf390
--- /dev/null
+++ b/debian/patches/v7.2.16.diff
@@ -0,0 +1,1368 @@
+Subject: v7.2.16
+Date: Sat Feb 8 14:26:26 2025 +0300
+From: Michael Tokarev <mjt@tls.msk.ru>
+Forwarded: not-needed
+
+This is a difference between upstream qemu v7.2.15
+and upstream qemu v7.2.16.
+
+ .cirrus.yml | 109 ----------------
+ MAINTAINERS | 3 +-
+ VERSION | 2 +-
+ backends/cryptodev-vhost-user.c | 3 +-
+ block/ssh.c | 3 -
+ docs/about/removed-features.rst | 4 +-
+ hw/9pfs/9p.c | 12 +-
+ hw/core/qdev-properties-system.c | 54 +++++---
+ hw/i386/acpi-build.c | 33 +++--
+ hw/i386/x86.c | 2 +-
+ hw/intc/arm_gicv3_its.c | 44 +++----
+ hw/intc/loongarch_extioi.c | 9 +-
+ hw/intc/openpic.c | 15 +--
+ hw/net/virtio-net.c | 5 +-
+ hw/openrisc/openrisc_sim.c | 26 +++-
+ hw/pci/msix.c | 2 +-
+ hw/pci/pcie.c | 12 +-
+ hw/s390x/s390-virtio-ccw.c | 11 ++
+ hw/scsi/megasas.c | 14 +--
+ hw/usb/canokey.c | 6 +-
+ hw/usb/canokey.h | 4 -
+ hw/usb/hcd-xhci-pci.c | 1 +
+ include/qemu/bitmap.h | 8 ++
+ include/qemu/bitops.h | 172 +++++++++++++++++++++++++-
+ meson.build | 2 +-
+ target/arm/sme_helper.c | 2 +-
+ target/i386/cpu.c | 3 +-
+ target/ppc/excp_helper.c | 7 ++
+ tcg/riscv/tcg-target.c.inc | 2 +-
+ tests/data/acpi/pc/DSDT | Bin 6458 -> 6476 bytes
+ tests/data/acpi/pc/DSDT.acpierst | Bin 6418 -> 6436 bytes
+ tests/data/acpi/pc/DSDT.acpihmat | Bin 7783 -> 7801 bytes
+ tests/data/acpi/pc/DSDT.bridge | Bin 9532 -> 9550 bytes
+ tests/data/acpi/pc/DSDT.cphp | Bin 6922 -> 6940 bytes
+ tests/data/acpi/pc/DSDT.dimmpxm | Bin 8112 -> 8130 bytes
+ tests/data/acpi/pc/DSDT.hpbridge | Bin 6418 -> 6436 bytes
+ tests/data/acpi/pc/DSDT.ipmikcs | Bin 6530 -> 6548 bytes
+ tests/data/acpi/pc/DSDT.memhp | Bin 7817 -> 7835 bytes
+ tests/data/acpi/pc/DSDT.nohpet | Bin 6316 -> 6334 bytes
+ tests/data/acpi/pc/DSDT.numamem | Bin 6464 -> 6482 bytes
+ tests/data/acpi/pc/DSDT.roothp | Bin 6656 -> 6674 bytes
+ tests/data/acpi/q35/DSDT | Bin 8310 -> 8328 bytes
+ tests/data/acpi/q35/DSDT.acpierst | Bin 8327 -> 8345 bytes
+ tests/data/acpi/q35/DSDT.acpihmat | Bin 9635 -> 9653 bytes
+ tests/data/acpi/q35/DSDT.acpihmat-noinitiator | Bin 8589 -> 8607 bytes
+ tests/data/acpi/q35/DSDT.applesmc | Bin 8356 -> 8374 bytes
+ tests/data/acpi/q35/DSDT.bridge | Bin 11439 -> 11457 bytes
+ tests/data/acpi/q35/DSDT.core-count2 | Bin 32450 -> 32468 bytes
+ tests/data/acpi/q35/DSDT.cphp | Bin 8774 -> 8792 bytes
+ tests/data/acpi/q35/DSDT.cxl | Bin 9637 -> 9655 bytes
+ tests/data/acpi/q35/DSDT.dimmpxm | Bin 9964 -> 9982 bytes
+ tests/data/acpi/q35/DSDT.ipmibt | Bin 8385 -> 8403 bytes
+ tests/data/acpi/q35/DSDT.ipmismbus | Bin 8398 -> 8416 bytes
+ tests/data/acpi/q35/DSDT.ivrs | Bin 8327 -> 8345 bytes
+ tests/data/acpi/q35/DSDT.memhp | Bin 9669 -> 9687 bytes
+ tests/data/acpi/q35/DSDT.mmio64 | Bin 9440 -> 9458 bytes
+ tests/data/acpi/q35/DSDT.multi-bridge | Bin 8630 -> 8648 bytes
+ tests/data/acpi/q35/DSDT.nohpet | Bin 8168 -> 8186 bytes
+ tests/data/acpi/q35/DSDT.numamem | Bin 8316 -> 8334 bytes
+ tests/data/acpi/q35/DSDT.pvpanic-isa | Bin 8411 -> 8429 bytes
+ tests/data/acpi/q35/DSDT.tis.tpm12 | Bin 8916 -> 8934 bytes
+ tests/data/acpi/q35/DSDT.tis.tpm2 | Bin 8942 -> 8960 bytes
+ tests/data/acpi/q35/DSDT.viot | Bin 9419 -> 9437 bytes
+ tests/data/acpi/q35/DSDT.xapic | Bin 35673 -> 35691 bytes
+ tests/qtest/fuzz/generic_fuzz_configs.h | 3 +-
+ tests/qtest/libqos/virtio-9p-client.c | 3 +-
+ tests/qtest/virtio-9p-test.c | 46 +++++++
+ 67 files changed, 393 insertions(+), 229 deletions(-)
+
+diff --git a/.cirrus.yml b/.cirrus.yml
+deleted file mode 100644
+index 4895987da4..0000000000
+--- a/.cirrus.yml
++++ /dev/null
+@@ -1,109 +0,0 @@
+-env:
+- CIRRUS_CLONE_DEPTH: 1
+-
+-windows_msys2_task:
+- timeout_in: 90m
+- windows_container:
+- image: cirrusci/windowsservercore:2019
+- os_version: 2019
+- cpu: 8
+- memory: 8G
+- env:
+- CIRRUS_SHELL: powershell
+- MSYS: winsymlinks:native
+- MSYSTEM: MINGW64
+- MSYS2_URL: https://github.com/msys2/msys2-installer/releases/download/2022-06-03/msys2-base-x86_64-20220603.sfx.exe
+- MSYS2_FINGERPRINT: 0
+- MSYS2_PACKAGES: "
+- diffutils git grep make pkg-config sed
+- mingw-w64-x86_64-python
+- mingw-w64-x86_64-python-sphinx
+- mingw-w64-x86_64-toolchain
+- mingw-w64-x86_64-SDL2
+- mingw-w64-x86_64-SDL2_image
+- mingw-w64-x86_64-gtk3
+- mingw-w64-x86_64-glib2
+- mingw-w64-x86_64-ninja
+- mingw-w64-x86_64-jemalloc
+- mingw-w64-x86_64-lzo2
+- mingw-w64-x86_64-zstd
+- mingw-w64-x86_64-libjpeg-turbo
+- mingw-w64-x86_64-pixman
+- mingw-w64-x86_64-libgcrypt
+- mingw-w64-x86_64-libpng
+- mingw-w64-x86_64-libssh
+- mingw-w64-x86_64-snappy
+- mingw-w64-x86_64-libusb
+- mingw-w64-x86_64-usbredir
+- mingw-w64-x86_64-libtasn1
+- mingw-w64-x86_64-nettle
+- mingw-w64-x86_64-cyrus-sasl
+- mingw-w64-x86_64-curl
+- mingw-w64-x86_64-gnutls
+- mingw-w64-x86_64-libnfs
+- "
+- CHERE_INVOKING: 1
+- msys2_cache:
+- folder: C:\tools\archive
+- reupload_on_changes: false
+- # These env variables are used to generate fingerprint to trigger the cache procedure
+- # If wanna to force re-populate msys2, increase MSYS2_FINGERPRINT
+- fingerprint_script:
+- - |
+- echo $env:CIRRUS_TASK_NAME
+- echo $env:MSYS2_URL
+- echo $env:MSYS2_FINGERPRINT
+- echo $env:MSYS2_PACKAGES
+- populate_script:
+- - |
+- md -Force C:\tools\archive\pkg
+- $start_time = Get-Date
+- bitsadmin /transfer msys_download /dynamic /download /priority FOREGROUND $env:MSYS2_URL C:\tools\archive\base.exe
+- Write-Output "Download time taken: $((Get-Date).Subtract($start_time))"
+- cd C:\tools
+- C:\tools\archive\base.exe -y
+- del -Force C:\tools\archive\base.exe
+- Write-Output "Base install time taken: $((Get-Date).Subtract($start_time))"
+- $start_time = Get-Date
+-
+- ((Get-Content -path C:\tools\msys64\etc\\post-install\\07-pacman-key.post -Raw) -replace '--refresh-keys', '--version') | Set-Content -Path C:\tools\msys64\etc\\post-install\\07-pacman-key.post
+- C:\tools\msys64\usr\bin\bash.exe -lc "sed -i 's/^CheckSpace/#CheckSpace/g' /etc/pacman.conf"
+- C:\tools\msys64\usr\bin\bash.exe -lc "export"
+- C:\tools\msys64\usr\bin\pacman.exe --noconfirm -Sy
+- echo Y | C:\tools\msys64\usr\bin\pacman.exe --noconfirm -Suu --overwrite=*
+- taskkill /F /FI "MODULES eq msys-2.0.dll"
+- tasklist
+- C:\tools\msys64\usr\bin\bash.exe -lc "mv -f /etc/pacman.conf.pacnew /etc/pacman.conf || true"
+- C:\tools\msys64\usr\bin\bash.exe -lc "pacman --noconfirm -Syuu --overwrite=*"
+- Write-Output "Core install time taken: $((Get-Date).Subtract($start_time))"
+- $start_time = Get-Date
+-
+- C:\tools\msys64\usr\bin\bash.exe -lc "pacman --noconfirm -S --needed $env:MSYS2_PACKAGES"
+- Write-Output "Package install time taken: $((Get-Date).Subtract($start_time))"
+- $start_time = Get-Date
+-
+- del -Force -ErrorAction SilentlyContinue C:\tools\msys64\etc\mtab
+- del -Force -ErrorAction SilentlyContinue C:\tools\msys64\dev\fd
+- del -Force -ErrorAction SilentlyContinue C:\tools\msys64\dev\stderr
+- del -Force -ErrorAction SilentlyContinue C:\tools\msys64\dev\stdin
+- del -Force -ErrorAction SilentlyContinue C:\tools\msys64\dev\stdout
+- del -Force -Recurse -ErrorAction SilentlyContinue C:\tools\msys64\var\cache\pacman\pkg
+- tar cf C:\tools\archive\msys64.tar -C C:\tools\ msys64
+-
+- Write-Output "Package archive time taken: $((Get-Date).Subtract($start_time))"
+- del -Force -Recurse -ErrorAction SilentlyContinue c:\tools\msys64
+- install_script:
+- - |
+- $start_time = Get-Date
+- cd C:\tools
+- ls C:\tools\archive\msys64.tar
+- tar xf C:\tools\archive\msys64.tar
+- Write-Output "Extract msys2 time taken: $((Get-Date).Subtract($start_time))"
+- script:
+- - C:\tools\msys64\usr\bin\bash.exe -lc "mkdir build"
+- - C:\tools\msys64\usr\bin\bash.exe -lc "cd build && ../configure --python=python3"
+- - C:\tools\msys64\usr\bin\bash.exe -lc "cd build && make -j8"
+- - exit $LastExitCode
+- test_script:
+- - C:\tools\msys64\usr\bin\bash.exe -lc "cd build && make V=1 check"
+- - exit $LastExitCode
+diff --git a/MAINTAINERS b/MAINTAINERS
+index e688db1f55..83c4eacc66 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -3731,8 +3731,7 @@ W: https://cirrus-ci.com/github/qemu/qemu
+ Windows Hosted Continuous Integration
+ M: Yonggang Luo <luoyonggang@gmail.com>
+ S: Maintained
+-F: .cirrus.yml
+-W: https://cirrus-ci.com/github/qemu/qemu
++F: .gitlab-ci.d/windows.yml
+
+ Guest Test Compilation Support
+ M: Alex Bennée <alex.bennee@linaro.org>
+diff --git a/VERSION b/VERSION
+index cc53d22108..a1f5232276 100644
+--- a/VERSION
++++ b/VERSION
+@@ -1 +1 @@
+-7.2.15
++7.2.16
+diff --git a/backends/cryptodev-vhost-user.c b/backends/cryptodev-vhost-user.c
+index ab3028e045..518f18b838 100644
+--- a/backends/cryptodev-vhost-user.c
++++ b/backends/cryptodev-vhost-user.c
+@@ -283,8 +283,7 @@ static int cryptodev_vhost_user_create_session(
+ break;
+
+ default:
+- error_setg(&local_error, "Unsupported opcode :%" PRIu32 "",
+- sess_info->op_code);
++ error_report("Unsupported opcode :%" PRIu32 "", sess_info->op_code);
+ return -VIRTIO_CRYPTO_NOTSUPP;
+ }
+
+diff --git a/block/ssh.c b/block/ssh.c
+index 04726d4ecb..c90d705453 100644
+--- a/block/ssh.c
++++ b/block/ssh.c
+@@ -859,9 +859,6 @@ static int ssh_file_open(BlockDriverState *bs, QDict *options, int bdrv_flags,
+ goto err;
+ }
+
+- /* Go non-blocking. */
+- ssh_set_blocking(s->session, 0);
+-
+ if (s->attrs->type == SSH_FILEXFER_TYPE_REGULAR) {
+ bs->supported_truncate_flags = BDRV_REQ_ZERO_WRITE;
+ }
+diff --git a/docs/about/removed-features.rst b/docs/about/removed-features.rst
+index 63df9848fd..93cc6e47b6 100644
+--- a/docs/about/removed-features.rst
++++ b/docs/about/removed-features.rst
+@@ -702,8 +702,8 @@ reason the maintainers strongly suspected no one actually used it.
+ TCG introspection features
+ --------------------------
+
+-TCG trace-events (since 6.2)
+-''''''''''''''''''''''''''''
++TCG trace-events (removed in 7.0)
++'''''''''''''''''''''''''''''''''
+
+ The ability to add new TCG trace points had bit rotted and as the
+ feature can be replicated with TCG plugins it was removed. If
+diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c
+index 51ad5bfb11..d950ad6de6 100644
+--- a/hw/9pfs/9p.c
++++ b/hw/9pfs/9p.c
+@@ -1605,11 +1605,13 @@ static void coroutine_fn v9fs_getattr(void *opaque)
+ retval = -ENOENT;
+ goto out_nofid;
+ }
+- /*
+- * Currently we only support BASIC fields in stat, so there is no
+- * need to look at request_mask.
+- */
+- retval = v9fs_co_lstat(pdu, &fidp->path, &stbuf);
++ if ((fidp->fid_type == P9_FID_FILE && fidp->fs.fd != -1) ||
++ (fidp->fid_type == P9_FID_DIR && fidp->fs.dir.stream))
++ {
++ retval = v9fs_co_fstat(pdu, fidp, &stbuf);
++ } else {
++ retval = v9fs_co_lstat(pdu, &fidp->path, &stbuf);
++ }
+ if (retval < 0) {
+ goto out;
+ }
+diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c
+index a91f60567a..d350789e76 100644
+--- a/hw/core/qdev-properties-system.c
++++ b/hw/core/qdev-properties-system.c
+@@ -740,39 +740,57 @@ static void set_pci_devfn(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
+ {
+ Property *prop = opaque;
++ g_autofree GenericAlternate *alt;
+ int32_t value, *ptr = object_field_prop_ptr(obj, prop);
+ unsigned int slot, fn, n;
+- char *str;
++ g_autofree char *str = NULL;
++
++ if (!visit_start_alternate(v, name, &alt, sizeof(*alt), errp)) {
++ return;
++ }
++
++ switch (alt->type) {
++ case QTYPE_QSTRING:
++ if (!visit_type_str(v, name, &str, errp)) {
++ goto out;
++ }
++
++ if (sscanf(str, "%x.%x%n", &slot, &fn, &n) != 2) {
++ fn = 0;
++ if (sscanf(str, "%x%n", &slot, &n) != 1) {
++ goto invalid;
++ }
++ }
++ if (str[n] != '\0' || fn > 7 || slot > 31) {
++ goto invalid;
++ }
++ *ptr = slot << 3 | fn;
++ break;
+
+- if (!visit_type_str(v, name, &str, NULL)) {
++ case QTYPE_QNUM:
+ if (!visit_type_int32(v, name, &value, errp)) {
+- return;
++ goto out;
+ }
+ if (value < -1 || value > 255) {
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
+ name ? name : "null", "a value between -1 and 255");
+- return;
++ goto out;
+ }
+ *ptr = value;
+- return;
+- }
++ break;
+
+- if (sscanf(str, "%x.%x%n", &slot, &fn, &n) != 2) {
+- fn = 0;
+- if (sscanf(str, "%x%n", &slot, &n) != 1) {
+- goto invalid;
+- }
+- }
+- if (str[n] != '\0' || fn > 7 || slot > 31) {
+- goto invalid;
++ default:
++ error_setg(errp, "Invalid parameter type for '%s', expected int or str",
++ name ? name : "null");
++ goto out;
+ }
+- *ptr = slot << 3 | fn;
+- g_free(str);
+- return;
++
++ goto out;
+
+ invalid:
+ error_set_from_qdev_prop_error(errp, EINVAL, obj, name, str);
+- g_free(str);
++out:
++ visit_end_alternate(v, (void **) &alt);
+ }
+
+ static int print_pci_devfn(Object *obj, Property *prop, char *dest,
+diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
+index f9cdacadb1..79b68f2218 100644
+--- a/hw/i386/acpi-build.c
++++ b/hw/i386/acpi-build.c
+@@ -541,6 +541,7 @@ static Aml *aml_pci_pdsm(void)
+ Aml *acpi_index = aml_local(2);
+ Aml *zero = aml_int(0);
+ Aml *one = aml_int(1);
++ Aml *not_supp = aml_int(0xFFFFFFFF);
+ Aml *func = aml_arg(2);
+ Aml *rev = aml_arg(1);
+ Aml *params = aml_arg(4);
+@@ -586,7 +587,7 @@ static Aml *aml_pci_pdsm(void)
+ */
+ ifctx1 = aml_if(aml_lnot(
+ aml_or(aml_equal(acpi_index, zero),
+- aml_equal(acpi_index, aml_int(0xFFFFFFFF)), NULL)
++ aml_equal(acpi_index, not_supp), NULL)
+ ));
+ {
+ /* have supported functions */
+@@ -612,18 +613,30 @@ static Aml *aml_pci_pdsm(void)
+ {
+ Aml *pkg = aml_package(2);
+
+- aml_append(pkg, zero);
+- /*
+- * optional, if not impl. should return null string
+- */
+- aml_append(pkg, aml_string("%s", ""));
+- aml_append(ifctx, aml_store(pkg, ret));
+-
+ aml_append(ifctx, aml_store(aml_call2("AIDX", bnum, sunum), acpi_index));
++ aml_append(ifctx, aml_store(pkg, ret));
+ /*
+- * update acpi-index to actual value
++ * Windows calls func=7 without checking if it's available,
++ * as workaround Microsoft has suggested to return invalid for func7
++ * Package, so return 2 elements package but only initialize elements
++ * when acpi_index is supported and leave them uninitialized, which
++ * leads elements to being Uninitialized ObjectType and should trip
++ * Windows into discarding result as an unexpected and prevent setting
++ * bogus 'PCI Label' on the device.
+ */
+- aml_append(ifctx, aml_store(acpi_index, aml_index(ret, zero)));
++ ifctx1 = aml_if(aml_lnot(aml_lor(
++ aml_equal(acpi_index, zero), aml_equal(acpi_index, not_supp)
++ )));
++ {
++ aml_append(ifctx1, aml_store(acpi_index, aml_index(ret, zero)));
++ /*
++ * optional, if not impl. should return null string
++ */
++ aml_append(ifctx1, aml_store(aml_string("%s", ""),
++ aml_index(ret, one)));
++ }
++ aml_append(ifctx, ifctx1);
++
+ aml_append(ifctx, aml_return(ret));
+ }
+
+diff --git a/hw/i386/x86.c b/hw/i386/x86.c
+index 80be3032cc..a2925821c5 100644
+--- a/hw/i386/x86.c
++++ b/hw/i386/x86.c
+@@ -1084,7 +1084,7 @@ void x86_load_linux(X86MachineState *x86ms,
+ * kernel on the other side of the fw_cfg interface matches the hash of the
+ * file the user passed in.
+ */
+- if (!sev_enabled()) {
++ if (!sev_enabled() && protocol > 0) {
+ memcpy(setup, header, MIN(sizeof(header), setup_size));
+ }
+
+diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
+index 2ff21ed6bb..05b63a0848 100644
+--- a/hw/intc/arm_gicv3_its.c
++++ b/hw/intc/arm_gicv3_its.c
+@@ -468,7 +468,7 @@ static ItsCmdResult lookup_vte(GICv3ITSState *s, const char *who,
+ static ItsCmdResult process_its_cmd_phys(GICv3ITSState *s, const ITEntry *ite,
+ int irqlevel)
+ {
+- CTEntry cte;
++ CTEntry cte = {};
+ ItsCmdResult cmdres;
+
+ cmdres = lookup_cte(s, __func__, ite->icid, &cte);
+@@ -482,7 +482,7 @@ static ItsCmdResult process_its_cmd_phys(GICv3ITSState *s, const ITEntry *ite,
+ static ItsCmdResult process_its_cmd_virt(GICv3ITSState *s, const ITEntry *ite,
+ int irqlevel)
+ {
+- VTEntry vte;
++ VTEntry vte = {};
+ ItsCmdResult cmdres;
+
+ cmdres = lookup_vte(s, __func__, ite->vpeid, &vte);
+@@ -517,8 +517,8 @@ static ItsCmdResult process_its_cmd_virt(GICv3ITSState *s, const ITEntry *ite,
+ static ItsCmdResult do_process_its_cmd(GICv3ITSState *s, uint32_t devid,
+ uint32_t eventid, ItsCmdType cmd)
+ {
+- DTEntry dte;
+- ITEntry ite;
++ DTEntry dte = {};
++ ITEntry ite = {};
+ ItsCmdResult cmdres;
+ int irqlevel;
+
+@@ -586,8 +586,8 @@ static ItsCmdResult process_mapti(GICv3ITSState *s, const uint64_t *cmdpkt,
+ uint32_t pIntid = 0;
+ uint64_t num_eventids;
+ uint16_t icid = 0;
+- DTEntry dte;
+- ITEntry ite;
++ DTEntry dte = {};
++ ITEntry ite = {};
+
+ devid = (cmdpkt[0] & DEVID_MASK) >> DEVID_SHIFT;
+ eventid = cmdpkt[1] & EVENTID_MASK;
+@@ -654,8 +654,8 @@ static ItsCmdResult process_vmapti(GICv3ITSState *s, const uint64_t *cmdpkt,
+ {
+ uint32_t devid, eventid, vintid, doorbell, vpeid;
+ uint32_t num_eventids;
+- DTEntry dte;
+- ITEntry ite;
++ DTEntry dte = {};
++ ITEntry ite = {};
+
+ if (!its_feature_virtual(s)) {
+ return CMD_CONTINUE;
+@@ -764,7 +764,7 @@ static bool update_cte(GICv3ITSState *s, uint16_t icid, const CTEntry *cte)
+ static ItsCmdResult process_mapc(GICv3ITSState *s, const uint64_t *cmdpkt)
+ {
+ uint16_t icid;
+- CTEntry cte;
++ CTEntry cte = {};
+
+ icid = cmdpkt[2] & ICID_MASK;
+ cte.valid = cmdpkt[2] & CMD_FIELD_VALID_MASK;
+@@ -825,7 +825,7 @@ static bool update_dte(GICv3ITSState *s, uint32_t devid, const DTEntry *dte)
+ static ItsCmdResult process_mapd(GICv3ITSState *s, const uint64_t *cmdpkt)
+ {
+ uint32_t devid;
+- DTEntry dte;
++ DTEntry dte = {};
+
+ devid = (cmdpkt[0] & DEVID_MASK) >> DEVID_SHIFT;
+ dte.size = cmdpkt[1] & SIZE_MASK;
+@@ -889,9 +889,9 @@ static ItsCmdResult process_movi(GICv3ITSState *s, const uint64_t *cmdpkt)
+ {
+ uint32_t devid, eventid;
+ uint16_t new_icid;
+- DTEntry dte;
+- CTEntry old_cte, new_cte;
+- ITEntry old_ite;
++ DTEntry dte = {};
++ CTEntry old_cte = {}, new_cte = {};
++ ITEntry old_ite = {};
+ ItsCmdResult cmdres;
+
+ devid = FIELD_EX64(cmdpkt[0], MOVI_0, DEVICEID);
+@@ -968,7 +968,7 @@ static bool update_vte(GICv3ITSState *s, uint32_t vpeid, const VTEntry *vte)
+
+ static ItsCmdResult process_vmapp(GICv3ITSState *s, const uint64_t *cmdpkt)
+ {
+- VTEntry vte;
++ VTEntry vte = {};
+ uint32_t vpeid;
+
+ if (!its_feature_virtual(s)) {
+@@ -1033,7 +1033,7 @@ static void vmovp_callback(gpointer data, gpointer opaque)
+ */
+ GICv3ITSState *s = data;
+ VmovpCallbackData *cbdata = opaque;
+- VTEntry vte;
++ VTEntry vte = {};
+ ItsCmdResult cmdres;
+
+ cmdres = lookup_vte(s, __func__, cbdata->vpeid, &vte);
+@@ -1088,9 +1088,9 @@ static ItsCmdResult process_vmovi(GICv3ITSState *s, const uint64_t *cmdpkt)
+ {
+ uint32_t devid, eventid, vpeid, doorbell;
+ bool doorbell_valid;
+- DTEntry dte;
+- ITEntry ite;
+- VTEntry old_vte, new_vte;
++ DTEntry dte = {};
++ ITEntry ite = {};
++ VTEntry old_vte = {}, new_vte = {};
+ ItsCmdResult cmdres;
+
+ if (!its_feature_virtual(s)) {
+@@ -1189,10 +1189,10 @@ static ItsCmdResult process_vinvall(GICv3ITSState *s, const uint64_t *cmdpkt)
+ static ItsCmdResult process_inv(GICv3ITSState *s, const uint64_t *cmdpkt)
+ {
+ uint32_t devid, eventid;
+- ITEntry ite;
+- DTEntry dte;
+- CTEntry cte;
+- VTEntry vte;
++ ITEntry ite = {};
++ DTEntry dte = {};
++ CTEntry cte = {};
++ VTEntry vte = {};
+ ItsCmdResult cmdres;
+
+ devid = FIELD_EX64(cmdpkt[0], INV_0, DEVICEID);
+diff --git a/hw/intc/loongarch_extioi.c b/hw/intc/loongarch_extioi.c
+index 4b8ec3f28a..fe17c7e0b1 100644
+--- a/hw/intc/loongarch_extioi.c
++++ b/hw/intc/loongarch_extioi.c
+@@ -56,14 +56,9 @@ static void extioi_setirq(void *opaque, int irq, int level)
+ LoongArchExtIOI *s = LOONGARCH_EXTIOI(opaque);
+ trace_loongarch_extioi_setirq(irq, level);
+ if (level) {
+- /*
+- * s->isr should be used in vmstate structure,
+- * but it not support 'unsigned long',
+- * so we have to switch it.
+- */
+- set_bit(irq, (unsigned long *)s->isr);
++ set_bit32(irq, s->isr);
+ } else {
+- clear_bit(irq, (unsigned long *)s->isr);
++ clear_bit32(irq, s->isr);
+ }
+ extioi_update_irq(s, irq, level);
+ }
+diff --git a/hw/intc/openpic.c b/hw/intc/openpic.c
+index c757adbe53..adc79abbe5 100644
+--- a/hw/intc/openpic.c
++++ b/hw/intc/openpic.c
+@@ -1035,13 +1035,14 @@ static void openpic_cpu_write_internal(void *opaque, hwaddr addr,
+ s_IRQ = IRQ_get_next(opp, &dst->servicing);
+ /* Check queued interrupts. */
+ n_IRQ = IRQ_get_next(opp, &dst->raised);
+- src = &opp->src[n_IRQ];
+- if (n_IRQ != -1 &&
+- (s_IRQ == -1 ||
+- IVPR_PRIORITY(src->ivpr) > dst->servicing.priority)) {
+- DPRINTF("Raise OpenPIC INT output cpu %d irq %d",
+- idx, n_IRQ);
+- qemu_irq_raise(opp->dst[idx].irqs[OPENPIC_OUTPUT_INT]);
++ if (n_IRQ != -1) {
++ src = &opp->src[n_IRQ];
++ if (s_IRQ == -1 ||
++ IVPR_PRIORITY(src->ivpr) > dst->servicing.priority) {
++ DPRINTF("Raise OpenPIC INT output cpu %d irq %d",
++ idx, n_IRQ);
++ qemu_irq_raise(opp->dst[idx].irqs[OPENPIC_OUTPUT_INT]);
++ }
+ }
+ break;
+ default:
+diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
+index 925a5c319e..204a80ec71 100644
+--- a/hw/net/virtio-net.c
++++ b/hw/net/virtio-net.c
+@@ -1647,8 +1647,11 @@ static void virtio_net_hdr_swap(VirtIODevice *vdev, struct virtio_net_hdr *hdr)
+ static void work_around_broken_dhclient(struct virtio_net_hdr *hdr,
+ uint8_t *buf, size_t size)
+ {
++ size_t csum_size = ETH_HLEN + sizeof(struct ip_header) +
++ sizeof(struct udp_header);
++
+ if ((hdr->flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) && /* missing csum */
+- (size > 27 && size < 1500) && /* normal sized MTU */
++ (size >= csum_size && size < 1500) && /* normal sized MTU */
+ (buf[12] == 0x08 && buf[13] == 0x00) && /* ethertype == IPv4 */
+ (buf[23] == 17) && /* ip.protocol == UDP */
+ (buf[34] == 0 && buf[35] == 67)) { /* udp.srcport == bootps */
+diff --git a/hw/openrisc/openrisc_sim.c b/hw/openrisc/openrisc_sim.c
+index 35da123aef..dc1fea8cd8 100644
+--- a/hw/openrisc/openrisc_sim.c
++++ b/hw/openrisc/openrisc_sim.c
+@@ -248,7 +248,7 @@ static void openrisc_sim_serial_init(Or1ksimState *state, hwaddr base,
+ void *fdt = state->fdt;
+ char *nodename;
+ qemu_irq serial_irq;
+- char alias[sizeof("uart0")];
++ char alias[sizeof("serial0")];
+ int i;
+
+ if (num_cpus > 1) {
+@@ -263,7 +263,7 @@ static void openrisc_sim_serial_init(Or1ksimState *state, hwaddr base,
+ serial_irq = get_cpu_irq(cpus, 0, irq_pin);
+ }
+ serial_mm_init(get_system_memory(), base, 0, serial_irq, 115200,
+- serial_hd(OR1KSIM_UART_COUNT - uart_idx - 1),
++ serial_hd(uart_idx),
+ DEVICE_NATIVE_ENDIAN);
+
+ /* Add device tree node for serial. */
+@@ -275,10 +275,13 @@ static void openrisc_sim_serial_init(Or1ksimState *state, hwaddr base,
+ qemu_fdt_setprop_cell(fdt, nodename, "clock-frequency", OR1KSIM_CLK_MHZ);
+ qemu_fdt_setprop(fdt, nodename, "big-endian", NULL, 0);
+
+- /* The /chosen node is created during fdt creation. */
+- qemu_fdt_setprop_string(fdt, "/chosen", "stdout-path", nodename);
+- snprintf(alias, sizeof(alias), "uart%d", uart_idx);
++ if (uart_idx == 0) {
++ /* The /chosen node is created during fdt creation. */
++ qemu_fdt_setprop_string(fdt, "/chosen", "stdout-path", nodename);
++ }
++ snprintf(alias, sizeof(alias), "serial%d", uart_idx);
+ qemu_fdt_setprop_string(fdt, "/aliases", alias, nodename);
++
+ g_free(nodename);
+ }
+
+@@ -326,11 +329,22 @@ static void openrisc_sim_init(MachineState *machine)
+ smp_cpus, cpus, OR1KSIM_OMPIC_IRQ);
+ }
+
+- for (n = 0; n < OR1KSIM_UART_COUNT; ++n)
++ /*
++ * We create the UART nodes starting with the highest address and
++ * working downwards, because in QEMU the DTB nodes end up in the
++ * DTB in reverse order of creation. Correctly-written guest software
++ * will not care about the node order (it will look at stdout-path
++ * or the alias nodes), but for the benefit of guest software which
++ * just looks for the first UART node in the DTB, make sure the
++ * lowest-address UART (which is QEMU's first serial port) appears
++ * first in the DTB.
++ */
++ for (n = OR1KSIM_UART_COUNT - 1; n >= 0; n--) {
+ openrisc_sim_serial_init(state, or1ksim_memmap[OR1KSIM_UART].base +
+ or1ksim_memmap[OR1KSIM_UART].size * n,
+ or1ksim_memmap[OR1KSIM_UART].size,
+ smp_cpus, cpus, OR1KSIM_UART_IRQ, n);
++ }
+
+ load_addr = openrisc_load_kernel(ram_size, kernel_filename,
+ &boot_info.bootstrap_pc);
+diff --git a/hw/pci/msix.c b/hw/pci/msix.c
+index 4b258566d4..20e39e51b4 100644
+--- a/hw/pci/msix.c
++++ b/hw/pci/msix.c
+@@ -241,7 +241,7 @@ static uint64_t msix_pba_mmio_read(void *opaque, hwaddr addr,
+ PCIDevice *dev = opaque;
+ if (dev->msix_vector_poll_notifier) {
+ unsigned vector_start = addr * 8;
+- unsigned vector_end = MIN(addr + size * 8, dev->msix_entries_nr);
++ unsigned vector_end = MIN((addr + size) * 8, dev->msix_entries_nr);
+ dev->msix_vector_poll_notifier(dev, vector_start, vector_end);
+ }
+
+diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c
+index 68a62da0b5..9ffc625cc2 100644
+--- a/hw/pci/pcie.c
++++ b/hw/pci/pcie.c
+@@ -999,18 +999,22 @@ void pcie_sync_bridge_lnk(PCIDevice *bridge_dev)
+ if ((lnksta & PCI_EXP_LNKSTA_NLW) > (lnkcap & PCI_EXP_LNKCAP_MLW)) {
+ lnksta &= ~PCI_EXP_LNKSTA_NLW;
+ lnksta |= lnkcap & PCI_EXP_LNKCAP_MLW;
+- } else if (!(lnksta & PCI_EXP_LNKSTA_NLW)) {
+- lnksta |= QEMU_PCI_EXP_LNKSTA_NLW(QEMU_PCI_EXP_LNK_X1);
+ }
+
+ if ((lnksta & PCI_EXP_LNKSTA_CLS) > (lnkcap & PCI_EXP_LNKCAP_SLS)) {
+ lnksta &= ~PCI_EXP_LNKSTA_CLS;
+ lnksta |= lnkcap & PCI_EXP_LNKCAP_SLS;
+- } else if (!(lnksta & PCI_EXP_LNKSTA_CLS)) {
+- lnksta |= QEMU_PCI_EXP_LNKSTA_CLS(QEMU_PCI_EXP_LNK_2_5GT);
+ }
+ }
+
++ if (!(lnksta & PCI_EXP_LNKSTA_NLW)) {
++ lnksta |= QEMU_PCI_EXP_LNKSTA_NLW(QEMU_PCI_EXP_LNK_X1);
++ }
++
++ if (!(lnksta & PCI_EXP_LNKSTA_CLS)) {
++ lnksta |= QEMU_PCI_EXP_LNKSTA_CLS(QEMU_PCI_EXP_LNK_2_5GT);
++ }
++
+ pci_word_test_and_clear_mask(exp_cap + PCI_EXP_LNKSTA,
+ PCI_EXP_LNKSTA_CLS | PCI_EXP_LNKSTA_NLW);
+ pci_word_test_and_set_mask(exp_cap + PCI_EXP_LNKSTA, lnksta &
+diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
+index 16899a1814..e163ff7d05 100644
+--- a/hw/s390x/s390-virtio-ccw.c
++++ b/hw/s390x/s390-virtio-ccw.c
+@@ -171,6 +171,17 @@ static void s390_memory_init(MemoryRegion *ram)
+ {
+ MemoryRegion *sysmem = get_system_memory();
+
++ if (!QEMU_IS_ALIGNED(memory_region_size(ram), 1 * MiB)) {
++ /*
++ * SCLP cannot possibly expose smaller granularity right now and KVM
++ * cannot handle smaller granularity. As we don't support NUMA, the
++ * region size directly corresponds to machine->ram_size, and the region
++ * is a single RAM memory region.
++ */
++ error_report("ram size must be multiples of 1 MiB");
++ exit(EXIT_FAILURE);
++ }
++
+ /* allocate RAM for core */
+ memory_region_add_subregion(sysmem, 0, ram);
+
+diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c
+index 9cbbb16121..d624866bb6 100644
+--- a/hw/scsi/megasas.c
++++ b/hw/scsi/megasas.c
+@@ -1780,7 +1780,7 @@ static int megasas_handle_io(MegasasState *s, MegasasCmd *cmd, int frame_cmd)
+ uint8_t cdb[16];
+ int len;
+ struct SCSIDevice *sdev = NULL;
+- int target_id, lun_id, cdb_len;
++ int target_id, lun_id;
+
+ lba_count = le32_to_cpu(cmd->frame->io.header.data_len);
+ lba_start_lo = le32_to_cpu(cmd->frame->io.lba_lo);
+@@ -1789,7 +1789,6 @@ static int megasas_handle_io(MegasasState *s, MegasasCmd *cmd, int frame_cmd)
+
+ target_id = cmd->frame->header.target_id;
+ lun_id = cmd->frame->header.lun_id;
+- cdb_len = cmd->frame->header.cdb_len;
+
+ if (target_id < MFI_MAX_LD && lun_id == 0) {
+ sdev = scsi_device_find(&s->bus, 0, target_id, lun_id);
+@@ -1804,15 +1803,6 @@ static int megasas_handle_io(MegasasState *s, MegasasCmd *cmd, int frame_cmd)
+ return MFI_STAT_DEVICE_NOT_FOUND;
+ }
+
+- if (cdb_len > 16) {
+- trace_megasas_scsi_invalid_cdb_len(
+- mfi_frame_desc(frame_cmd), 1, target_id, lun_id, cdb_len);
+- megasas_write_sense(cmd, SENSE_CODE(INVALID_OPCODE));
+- cmd->frame->header.scsi_status = CHECK_CONDITION;
+- s->event_count++;
+- return MFI_STAT_SCSI_DONE_WITH_ERROR;
+- }
+-
+ cmd->iov_size = lba_count * sdev->blocksize;
+ if (megasas_map_sgl(s, cmd, &cmd->frame->io.sgl)) {
+ megasas_write_sense(cmd, SENSE_CODE(TARGET_FAILURE));
+@@ -1823,7 +1813,7 @@ static int megasas_handle_io(MegasasState *s, MegasasCmd *cmd, int frame_cmd)
+
+ megasas_encode_lba(cdb, lba_start, lba_count, is_write);
+ cmd->req = scsi_req_new(sdev, cmd->index,
+- lun_id, cdb, cdb_len, cmd);
++ lun_id, cdb, sizeof(cdb), cmd);
+ if (!cmd->req) {
+ trace_megasas_scsi_req_alloc_failed(
+ mfi_frame_desc(frame_cmd), target_id, lun_id);
+diff --git a/hw/usb/canokey.c b/hw/usb/canokey.c
+index bbc5da07b5..5abb8db771 100644
+--- a/hw/usb/canokey.c
++++ b/hw/usb/canokey.c
+@@ -197,8 +197,8 @@ static void canokey_handle_data(USBDevice *dev, USBPacket *p)
+ switch (p->pid) {
+ case USB_TOKEN_OUT:
+ trace_canokey_handle_data_out(ep_out, p->iov.size);
+- usb_packet_copy(p, key->ep_out_buffer[ep_out], p->iov.size);
+ out_pos = 0;
++ /* segment packet into (possibly multiple) ep_out */
+ while (out_pos != p->iov.size) {
+ /*
+ * key->ep_out[ep_out] set by prepare_receive
+@@ -207,8 +207,8 @@ static void canokey_handle_data(USBDevice *dev, USBPacket *p)
+ * to be the buffer length
+ */
+ out_len = MIN(p->iov.size - out_pos, key->ep_out_size[ep_out]);
+- memcpy(key->ep_out[ep_out],
+- key->ep_out_buffer[ep_out] + out_pos, out_len);
++ /* usb_packet_copy would update the pos offset internally */
++ usb_packet_copy(p, key->ep_out[ep_out], out_len);
+ out_pos += out_len;
+ /* update ep_out_size to actual len */
+ key->ep_out_size[ep_out] = out_len;
+diff --git a/hw/usb/canokey.h b/hw/usb/canokey.h
+index 24cf304203..fdcad10f80 100644
+--- a/hw/usb/canokey.h
++++ b/hw/usb/canokey.h
+@@ -24,8 +24,6 @@
+ #define CANOKEY_EP_NUM 3
+ /* BULK/INTR IN can be up to 1352 bytes, e.g. get key info */
+ #define CANOKEY_EP_IN_BUFFER_SIZE 2048
+-/* BULK OUT can be up to 270 bytes, e.g. PIV import cert */
+-#define CANOKEY_EP_OUT_BUFFER_SIZE 512
+
+ typedef enum {
+ CANOKEY_EP_IN_WAIT,
+@@ -59,8 +57,6 @@ typedef struct CanoKeyState {
+ /* OUT pointer to canokey recv buffer */
+ uint8_t *ep_out[CANOKEY_EP_NUM];
+ uint32_t ep_out_size[CANOKEY_EP_NUM];
+- /* For large BULK OUT, multiple write to ep_out is needed */
+- uint8_t ep_out_buffer[CANOKEY_EP_NUM][CANOKEY_EP_OUT_BUFFER_SIZE];
+
+ /* Properties */
+ char *file; /* canokey-file */
+diff --git a/hw/usb/hcd-xhci-pci.c b/hw/usb/hcd-xhci-pci.c
+index 643d4643e4..560ce582b2 100644
+--- a/hw/usb/hcd-xhci-pci.c
++++ b/hw/usb/hcd-xhci-pci.c
+@@ -74,6 +74,7 @@ static bool xhci_pci_intr_raise(XHCIState *xhci, int n, bool level)
+ }
+
+ if (msi_enabled(pci_dev) && level) {
++ n %= msi_nr_vectors_allocated(pci_dev);
+ msi_notify(pci_dev, n);
+ return true;
+ }
+diff --git a/include/qemu/bitmap.h b/include/qemu/bitmap.h
+index 3ccb00865f..1f35e0193f 100644
+--- a/include/qemu/bitmap.h
++++ b/include/qemu/bitmap.h
+@@ -69,6 +69,14 @@
+ #define DECLARE_BITMAP(name,bits) \
+ unsigned long name[BITS_TO_LONGS(bits)]
+
++/*
++ * This is for use with the bit32 versions of set_bit() etc;
++ * we don't currently support the full range of bitmap operations
++ * on bitmaps backed by an array of uint32_t.
++ */
++#define DECLARE_BITMAP32(name, bits) \
++ uint32_t name[BITS_TO_U32S(bits)]
++
+ #define small_nbits(nbits) \
+ ((nbits) <= BITS_PER_LONG)
+
+diff --git a/include/qemu/bitops.h b/include/qemu/bitops.h
+index 03213ce952..888ac7f0e6 100644
+--- a/include/qemu/bitops.h
++++ b/include/qemu/bitops.h
+@@ -18,16 +18,47 @@
+
+ #define BITS_PER_BYTE CHAR_BIT
+ #define BITS_PER_LONG (sizeof (unsigned long) * BITS_PER_BYTE)
++#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
++#define BITS_TO_U32S(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(uint32_t))
+
+ #define BIT(nr) (1UL << (nr))
+ #define BIT_ULL(nr) (1ULL << (nr))
+-#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
+-#define BIT_WORD(nr) ((nr) / BITS_PER_LONG)
+-#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
+
+ #define MAKE_64BIT_MASK(shift, length) \
+ (((~0ULL) >> (64 - (length))) << (shift))
+
++/**
++ * DOC: Functions operating on arrays of bits
++ *
++ * We provide a set of functions which work on arbitrary-length arrays of
++ * bits. These come in several flavours which vary in what the type of the
++ * underlying storage for the bits is:
++ *
++ * - Bits stored in an array of 'unsigned long': set_bit(), clear_bit(), etc
++ * - Bits stored in an array of 'uint32_t': set_bit32(), clear_bit32(), etc
++ *
++ * Because the 'unsigned long' type has a size which varies between
++ * host systems, the versions using 'uint32_t' are often preferable.
++ * This is particularly the case in a device model where there may
++ * be some guest-visible register view of the bit array.
++ *
++ * We do not currently implement uint32_t versions of find_last_bit(),
++ * find_next_bit(), find_next_zero_bit(), find_first_bit() or
++ * find_first_zero_bit(), because we haven't yet needed them. If you
++ * need them you should implement them similarly to the 'unsigned long'
++ * versions.
++ *
++ * You can declare a bitmap to be used with these functions via the
++ * DECLARE_BITMAP and DECLARE_BITMAP32 macros in bitmap.h.
++ */
++
++/**
++ * DOC: 'unsigned long' bit array APIs
++ */
++
++#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
++#define BIT_WORD(nr) ((nr) / BITS_PER_LONG)
++
+ /**
+ * set_bit - Set a bit in memory
+ * @nr: the bit to set
+@@ -211,6 +242,141 @@ static inline unsigned long find_first_zero_bit(const unsigned long *addr,
+ return find_next_zero_bit(addr, size, 0);
+ }
+
++/**
++ * DOC: 'uint32_t' bit array APIs
++ */
++
++#define BIT32_MASK(nr) (1UL << ((nr) % 32))
++#define BIT32_WORD(nr) ((nr) / 32)
++
++/**
++ * set_bit32 - Set a bit in memory
++ * @nr: the bit to set
++ * @addr: the address to start counting from
++ */
++static inline void set_bit32(long nr, uint32_t *addr)
++{
++ uint32_t mask = BIT32_MASK(nr);
++ uint32_t *p = addr + BIT32_WORD(nr);
++
++ *p |= mask;
++}
++
++/**
++ * set_bit32_atomic - Set a bit in memory atomically
++ * @nr: the bit to set
++ * @addr: the address to start counting from
++ */
++static inline void set_bit32_atomic(long nr, uint32_t *addr)
++{
++ uint32_t mask = BIT32_MASK(nr);
++ uint32_t *p = addr + BIT32_WORD(nr);
++
++ qatomic_or(p, mask);
++}
++
++/**
++ * clear_bit32 - Clears a bit in memory
++ * @nr: Bit to clear
++ * @addr: Address to start counting from
++ */
++static inline void clear_bit32(long nr, uint32_t *addr)
++{
++ uint32_t mask = BIT32_MASK(nr);
++ uint32_t *p = addr + BIT32_WORD(nr);
++
++ *p &= ~mask;
++}
++
++/**
++ * clear_bit32_atomic - Clears a bit in memory atomically
++ * @nr: Bit to clear
++ * @addr: Address to start counting from
++ */
++static inline void clear_bit32_atomic(long nr, uint32_t *addr)
++{
++ uint32_t mask = BIT32_MASK(nr);
++ uint32_t *p = addr + BIT32_WORD(nr);
++
++ return qatomic_and(p, ~mask);
++}
++
++/**
++ * change_bit32 - Toggle a bit in memory
++ * @nr: Bit to change
++ * @addr: Address to start counting from
++ */
++static inline void change_bit32(long nr, uint32_t *addr)
++{
++ uint32_t mask = BIT32_MASK(nr);
++ uint32_t *p = addr + BIT32_WORD(nr);
++
++ *p ^= mask;
++}
++
++/**
++ * test_and_set_bit32 - Set a bit and return its old value
++ * @nr: Bit to set
++ * @addr: Address to count from
++ */
++static inline int test_and_set_bit32(long nr, uint32_t *addr)
++{
++ uint32_t mask = BIT32_MASK(nr);
++ uint32_t *p = addr + BIT32_WORD(nr);
++ uint32_t old = *p;
++
++ *p = old | mask;
++ return (old & mask) != 0;
++}
++
++/**
++ * test_and_clear_bit32 - Clear a bit and return its old value
++ * @nr: Bit to clear
++ * @addr: Address to count from
++ */
++static inline int test_and_clear_bit32(long nr, uint32_t *addr)
++{
++ uint32_t mask = BIT32_MASK(nr);
++ uint32_t *p = addr + BIT32_WORD(nr);
++ uint32_t old = *p;
++
++ *p = old & ~mask;
++ return (old & mask) != 0;
++}
++
++/**
++ * test_and_change_bit32 - Change a bit and return its old value
++ * @nr: Bit to change
++ * @addr: Address to count from
++ */
++static inline int test_and_change_bit32(long nr, uint32_t *addr)
++{
++ uint32_t mask = BIT32_MASK(nr);
++ uint32_t *p = addr + BIT32_WORD(nr);
++ uint32_t old = *p;
++
++ *p = old ^ mask;
++ return (old & mask) != 0;
++}
++
++/**
++ * test_bit32 - Determine whether a bit is set
++ * @nr: bit number to test
++ * @addr: Address to start counting from
++ */
++static inline int test_bit32(long nr, const uint32_t *addr)
++{
++ return 1U & (addr[BIT32_WORD(nr)] >> (nr & 31));
++}
++
++/**
++ * DOC: Miscellaneous bit operations on single values
++ *
++ * These functions are a collection of useful operations
++ * (rotations, bit extract, bit deposit, etc) on single
++ * integer values.
++ */
++
+ /**
+ * rol8 - rotate an 8-bit value left
+ * @word: value to rotate
+diff --git a/meson.build b/meson.build
+index 16dc9627e0..c0608332cd 100644
+--- a/meson.build
++++ b/meson.build
+@@ -580,7 +580,7 @@ endif
+
+ libnfs = not_found
+ if not get_option('libnfs').auto() or have_block
+- libnfs = dependency('libnfs', version: '>=1.9.3',
++ libnfs = dependency('libnfs', version: ['>=1.9.3', '<6.0.0'],
+ required: get_option('libnfs'),
+ method: 'pkg-config', kwargs: static_kwargs)
+ endif
+diff --git a/target/arm/sme_helper.c b/target/arm/sme_helper.c
+index 98a4840970..fd5625c87e 100644
+--- a/target/arm/sme_helper.c
++++ b/target/arm/sme_helper.c
+@@ -35,7 +35,7 @@ void arm_reset_sve_state(CPUARMState *env)
+ memset(env->vfp.zregs, 0, sizeof(env->vfp.zregs));
+ /* Recall that FFR is stored as pregs[16]. */
+ memset(env->vfp.pregs, 0, sizeof(env->vfp.pregs));
+- vfp_set_fpcr(env, 0x0800009f);
++ vfp_set_fpsr(env, 0x0800009f);
+ }
+
+ void helper_set_pstate_sm(CPUARMState *env, uint32_t i)
+diff --git a/target/i386/cpu.c b/target/i386/cpu.c
+index 9c3e64c54b..489ab9cd41 100644
+--- a/target/i386/cpu.c
++++ b/target/i386/cpu.c
+@@ -3044,6 +3044,7 @@ static const X86CPUDefinition builtin_x86_defs[] = {
+ },
+ {
+ .version = 4,
++ .note = "IBRS, EPT switching, no TSX",
+ .props = (PropValue[]) {
+ { "vmx-eptp-switching", "on" },
+ { /* end of list */ }
+@@ -3178,7 +3179,7 @@ static const X86CPUDefinition builtin_x86_defs[] = {
+ },
+ },
+ { .version = 4,
+- .note = "ARCH_CAPABILITIES, no TSX",
++ .note = "ARCH_CAPABILITIES, EPT switching, no TSX",
+ .props = (PropValue[]) {
+ { "vmx-eptp-switching", "on" },
+ { /* end of list */ }
+diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
+index 839d95c1eb..037efc04af 100644
+--- a/target/ppc/excp_helper.c
++++ b/target/ppc/excp_helper.c
+@@ -2511,10 +2511,16 @@ static void ppc_deliver_interrupt(CPUPPCState *env, int interrupt)
+ }
+ }
+
++/*
++ * system reset is not delivered via normal irq method, so have to set
++ * halted = 0 to resume CPU running if it was halted. Possibly we should
++ * move it over to using PPC_INTERRUPT_RESET rather than async_run_on_cpu.
++ */
+ void ppc_cpu_do_system_reset(CPUState *cs)
+ {
+ PowerPCCPU *cpu = POWERPC_CPU(cs);
+
++ cs->halted = 0;
+ powerpc_excp(cpu, POWERPC_EXCP_RESET);
+ }
+
+@@ -2536,6 +2542,7 @@ void ppc_cpu_do_fwnmi_machine_check(CPUState *cs, target_ulong vector)
+
+ /* Anything for nested required here? MSR[HV] bit? */
+
++ cs->halted = 0;
+ powerpc_set_excp_state(cpu, vector, msr);
+ }
+
+diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc
+index 81a83e45b1..e91a7aaf0e 100644
+--- a/tcg/riscv/tcg-target.c.inc
++++ b/tcg/riscv/tcg-target.c.inc
+@@ -838,7 +838,7 @@ static void tcg_out_mb(TCGContext *s, TCGArg a0)
+ insn |= 0x02100000;
+ }
+ if (a0 & TCG_MO_ST_ST) {
+- insn |= 0x02200000;
++ insn |= 0x01100000;
+ }
+ tcg_out32(s, insn);
+ }
+diff --git a/tests/data/acpi/pc/DSDT b/tests/data/acpi/pc/DSDT
+index b688686dc3..246bcadaa7 100644
+Binary files a/tests/data/acpi/pc/DSDT and b/tests/data/acpi/pc/DSDT differ
+diff --git a/tests/data/acpi/pc/DSDT.acpierst b/tests/data/acpi/pc/DSDT.acpierst
+index 86259be9d1..3074cecb6c 100644
+Binary files a/tests/data/acpi/pc/DSDT.acpierst and b/tests/data/acpi/pc/DSDT.acpierst differ
+diff --git a/tests/data/acpi/pc/DSDT.acpihmat b/tests/data/acpi/pc/DSDT.acpihmat
+index e2cc2a6fc9..0a32881d58 100644
+Binary files a/tests/data/acpi/pc/DSDT.acpihmat and b/tests/data/acpi/pc/DSDT.acpihmat differ
+diff --git a/tests/data/acpi/pc/DSDT.bridge b/tests/data/acpi/pc/DSDT.bridge
+index 75016fd4b7..95c12aa316 100644
+Binary files a/tests/data/acpi/pc/DSDT.bridge and b/tests/data/acpi/pc/DSDT.bridge differ
+diff --git a/tests/data/acpi/pc/DSDT.cphp b/tests/data/acpi/pc/DSDT.cphp
+index 53eb0dd7d4..ac40cbc595 100644
+Binary files a/tests/data/acpi/pc/DSDT.cphp and b/tests/data/acpi/pc/DSDT.cphp differ
+diff --git a/tests/data/acpi/pc/DSDT.dimmpxm b/tests/data/acpi/pc/DSDT.dimmpxm
+index 9089d994e0..b8b62cf9e9 100644
+Binary files a/tests/data/acpi/pc/DSDT.dimmpxm and b/tests/data/acpi/pc/DSDT.dimmpxm differ
+diff --git a/tests/data/acpi/pc/DSDT.hpbridge b/tests/data/acpi/pc/DSDT.hpbridge
+index 86259be9d1..3074cecb6c 100644
+Binary files a/tests/data/acpi/pc/DSDT.hpbridge and b/tests/data/acpi/pc/DSDT.hpbridge differ
+diff --git a/tests/data/acpi/pc/DSDT.ipmikcs b/tests/data/acpi/pc/DSDT.ipmikcs
+index 39427103aa..40edcc0f94 100644
+Binary files a/tests/data/acpi/pc/DSDT.ipmikcs and b/tests/data/acpi/pc/DSDT.ipmikcs differ
+diff --git a/tests/data/acpi/pc/DSDT.memhp b/tests/data/acpi/pc/DSDT.memhp
+index 987a263339..b2a7fd0dbd 100644
+Binary files a/tests/data/acpi/pc/DSDT.memhp and b/tests/data/acpi/pc/DSDT.memhp differ
+diff --git a/tests/data/acpi/pc/DSDT.nohpet b/tests/data/acpi/pc/DSDT.nohpet
+index fc7598b762..713aae4d8a 100644
+Binary files a/tests/data/acpi/pc/DSDT.nohpet and b/tests/data/acpi/pc/DSDT.nohpet differ
+diff --git a/tests/data/acpi/pc/DSDT.numamem b/tests/data/acpi/pc/DSDT.numamem
+index 85af400cdb..70b44ec476 100644
+Binary files a/tests/data/acpi/pc/DSDT.numamem and b/tests/data/acpi/pc/DSDT.numamem differ
+diff --git a/tests/data/acpi/pc/DSDT.roothp b/tests/data/acpi/pc/DSDT.roothp
+index 545512adfa..1030c94cc5 100644
+Binary files a/tests/data/acpi/pc/DSDT.roothp and b/tests/data/acpi/pc/DSDT.roothp differ
+diff --git a/tests/data/acpi/q35/DSDT b/tests/data/acpi/q35/DSDT
+index 2771bcea89..5c2b505163 100644
+Binary files a/tests/data/acpi/q35/DSDT and b/tests/data/acpi/q35/DSDT differ
+diff --git a/tests/data/acpi/q35/DSDT.acpierst b/tests/data/acpi/q35/DSDT.acpierst
+index b45abca7c2..1fd50e1c8b 100644
+Binary files a/tests/data/acpi/q35/DSDT.acpierst and b/tests/data/acpi/q35/DSDT.acpierst differ
+diff --git a/tests/data/acpi/q35/DSDT.acpihmat b/tests/data/acpi/q35/DSDT.acpihmat
+index d90fd4723a..c224736325 100644
+Binary files a/tests/data/acpi/q35/DSDT.acpihmat and b/tests/data/acpi/q35/DSDT.acpihmat differ
+diff --git a/tests/data/acpi/q35/DSDT.acpihmat-noinitiator b/tests/data/acpi/q35/DSDT.acpihmat-noinitiator
+index 279fafa821..ecdb94cc67 100644
+Binary files a/tests/data/acpi/q35/DSDT.acpihmat-noinitiator and b/tests/data/acpi/q35/DSDT.acpihmat-noinitiator differ
+diff --git a/tests/data/acpi/q35/DSDT.applesmc b/tests/data/acpi/q35/DSDT.applesmc
+index fdf6d14428..241a02dcf4 100644
+Binary files a/tests/data/acpi/q35/DSDT.applesmc and b/tests/data/acpi/q35/DSDT.applesmc differ
+diff --git a/tests/data/acpi/q35/DSDT.bridge b/tests/data/acpi/q35/DSDT.bridge
+index b41a4dddc0..bb41a3c218 100644
+Binary files a/tests/data/acpi/q35/DSDT.bridge and b/tests/data/acpi/q35/DSDT.bridge differ
+diff --git a/tests/data/acpi/q35/DSDT.core-count2 b/tests/data/acpi/q35/DSDT.core-count2
+index 375aceed6b..5e0da94644 100644
+Binary files a/tests/data/acpi/q35/DSDT.core-count2 and b/tests/data/acpi/q35/DSDT.core-count2 differ
+diff --git a/tests/data/acpi/q35/DSDT.cphp b/tests/data/acpi/q35/DSDT.cphp
+index a0ecafc36c..6d64cd51f6 100644
+Binary files a/tests/data/acpi/q35/DSDT.cphp and b/tests/data/acpi/q35/DSDT.cphp differ
+diff --git a/tests/data/acpi/q35/DSDT.cxl b/tests/data/acpi/q35/DSDT.cxl
+index 267709e4e4..737e5a2447 100644
+Binary files a/tests/data/acpi/q35/DSDT.cxl and b/tests/data/acpi/q35/DSDT.cxl differ
+diff --git a/tests/data/acpi/q35/DSDT.dimmpxm b/tests/data/acpi/q35/DSDT.dimmpxm
+index f0659716e3..665a0c88ff 100644
+Binary files a/tests/data/acpi/q35/DSDT.dimmpxm and b/tests/data/acpi/q35/DSDT.dimmpxm differ
+diff --git a/tests/data/acpi/q35/DSDT.ipmibt b/tests/data/acpi/q35/DSDT.ipmibt
+index 9c52529919..25ddd90f8e 100644
+Binary files a/tests/data/acpi/q35/DSDT.ipmibt and b/tests/data/acpi/q35/DSDT.ipmibt differ
+diff --git a/tests/data/acpi/q35/DSDT.ipmismbus b/tests/data/acpi/q35/DSDT.ipmismbus
+index 3f32dffdbf..3367016d9a 100644
+Binary files a/tests/data/acpi/q35/DSDT.ipmismbus and b/tests/data/acpi/q35/DSDT.ipmismbus differ
+diff --git a/tests/data/acpi/q35/DSDT.ivrs b/tests/data/acpi/q35/DSDT.ivrs
+index b45abca7c2..1fd50e1c8b 100644
+Binary files a/tests/data/acpi/q35/DSDT.ivrs and b/tests/data/acpi/q35/DSDT.ivrs differ
+diff --git a/tests/data/acpi/q35/DSDT.memhp b/tests/data/acpi/q35/DSDT.memhp
+index 28a192c69a..bfd2278260 100644
+Binary files a/tests/data/acpi/q35/DSDT.memhp and b/tests/data/acpi/q35/DSDT.memhp differ
+diff --git a/tests/data/acpi/q35/DSDT.mmio64 b/tests/data/acpi/q35/DSDT.mmio64
+index 8fda921296..5b50f66a1e 100644
+Binary files a/tests/data/acpi/q35/DSDT.mmio64 and b/tests/data/acpi/q35/DSDT.mmio64 differ
+diff --git a/tests/data/acpi/q35/DSDT.multi-bridge b/tests/data/acpi/q35/DSDT.multi-bridge
+index 3dba4d8436..2f37a6f8b6 100644
+Binary files a/tests/data/acpi/q35/DSDT.multi-bridge and b/tests/data/acpi/q35/DSDT.multi-bridge differ
+diff --git a/tests/data/acpi/q35/DSDT.nohpet b/tests/data/acpi/q35/DSDT.nohpet
+index b116947dac..5c17ed809d 100644
+Binary files a/tests/data/acpi/q35/DSDT.nohpet and b/tests/data/acpi/q35/DSDT.nohpet differ
+diff --git a/tests/data/acpi/q35/DSDT.numamem b/tests/data/acpi/q35/DSDT.numamem
+index 5eb6159d5f..e92f2a0c7a 100644
+Binary files a/tests/data/acpi/q35/DSDT.numamem and b/tests/data/acpi/q35/DSDT.numamem differ
+diff --git a/tests/data/acpi/q35/DSDT.pvpanic-isa b/tests/data/acpi/q35/DSDT.pvpanic-isa
+index 908e7b6606..308ed32bf0 100644
+Binary files a/tests/data/acpi/q35/DSDT.pvpanic-isa and b/tests/data/acpi/q35/DSDT.pvpanic-isa differ
+diff --git a/tests/data/acpi/q35/DSDT.tis.tpm12 b/tests/data/acpi/q35/DSDT.tis.tpm12
+index ce2c2c29c2..a7ec593951 100644
+Binary files a/tests/data/acpi/q35/DSDT.tis.tpm12 and b/tests/data/acpi/q35/DSDT.tis.tpm12 differ
+diff --git a/tests/data/acpi/q35/DSDT.tis.tpm2 b/tests/data/acpi/q35/DSDT.tis.tpm2
+index e9e4b7f6ed..ee242eceba 100644
+Binary files a/tests/data/acpi/q35/DSDT.tis.tpm2 and b/tests/data/acpi/q35/DSDT.tis.tpm2 differ
+diff --git a/tests/data/acpi/q35/DSDT.viot b/tests/data/acpi/q35/DSDT.viot
+index 6b436f9cd9..60451836ff 100644
+Binary files a/tests/data/acpi/q35/DSDT.viot and b/tests/data/acpi/q35/DSDT.viot differ
+diff --git a/tests/data/acpi/q35/DSDT.xapic b/tests/data/acpi/q35/DSDT.xapic
+index f47f091222..9f96175d93 100644
+Binary files a/tests/data/acpi/q35/DSDT.xapic and b/tests/data/acpi/q35/DSDT.xapic differ
+diff --git a/tests/qtest/fuzz/generic_fuzz_configs.h b/tests/qtest/fuzz/generic_fuzz_configs.h
+index a825b78c14..4c3235311b 100644
+--- a/tests/qtest/fuzz/generic_fuzz_configs.h
++++ b/tests/qtest/fuzz/generic_fuzz_configs.h
+@@ -143,7 +143,8 @@ const generic_fuzz_config predefined_configs[] = {
+ "-chardev null,id=cd0 -chardev null,id=cd1 "
+ "-device usb-braille,chardev=cd0 -device usb-ccid -device usb-ccid "
+ "-device usb-kbd -device usb-mouse -device usb-serial,chardev=cd1 "
+- "-device usb-tablet -device usb-wacom-tablet -device usb-audio",
++ "-device usb-tablet -device usb-wacom-tablet "
++ "-device usb-audio,audiodev=snd0 -audiodev none,id=snd0",
+ .objects = "*usb* *uhci* *xhci*",
+ },{
+ .name = "pc-i440fx",
+diff --git a/tests/qtest/libqos/virtio-9p-client.c b/tests/qtest/libqos/virtio-9p-client.c
+index e4a368e036..340e704d24 100644
+--- a/tests/qtest/libqos/virtio-9p-client.c
++++ b/tests/qtest/libqos/virtio-9p-client.c
+@@ -235,10 +235,11 @@ static const char *rmessage_name(uint8_t id)
+ id == P9_RMKDIR ? "RMKDIR" :
+ id == P9_RLCREATE ? "RLCREATE" :
+ id == P9_RSYMLINK ? "RSYMLINK" :
++ id == P9_RGETATTR ? "RGETATTR" :
+ id == P9_RLINK ? "RLINK" :
+ id == P9_RUNLINKAT ? "RUNLINKAT" :
+ id == P9_RFLUSH ? "RFLUSH" :
+- id == P9_RREADDIR ? "READDIR" :
++ id == P9_RREADDIR ? "RREADDIR" :
+ "<unknown>";
+ }
+
+diff --git a/tests/qtest/virtio-9p-test.c b/tests/qtest/virtio-9p-test.c
+index 65e69491e5..86ff86409c 100644
+--- a/tests/qtest/virtio-9p-test.c
++++ b/tests/qtest/virtio-9p-test.c
+@@ -693,6 +693,50 @@ static void fs_unlinkat_hardlink(void *obj, void *data,
+ g_assert(stat(real_file, &st_real) == 0);
+ }
+
++static void fs_use_after_unlink(void *obj, void *data,
++ QGuestAllocator *t_alloc)
++{
++ QVirtio9P *v9p = obj;
++ v9fs_set_allocator(t_alloc);
++ static const uint32_t write_count = P9_MAX_SIZE / 2;
++ g_autofree char *real_file = virtio_9p_test_path("09/doa_file");
++ g_autofree char *buf = g_malloc0(write_count);
++ struct stat st_file;
++ struct v9fs_attr attr;
++ uint32_t fid_file;
++ uint32_t count;
++
++ tattach({ .client = v9p });
++
++ /* create a file "09/doa_file" and make sure it exists and is regular */
++ tmkdir({ .client = v9p, .atPath = "/", .name = "09" });
++ tlcreate({ .client = v9p, .atPath = "09", .name = "doa_file" });
++ g_assert(stat(real_file, &st_file) == 0);
++ g_assert((st_file.st_mode & S_IFMT) == S_IFREG);
++
++ /* request a FID for that regular file that we can work with next */
++ fid_file = twalk({
++ .client = v9p, .fid = 0, .path = "09/doa_file"
++ }).newfid;
++ g_assert(fid_file != 0);
++
++ /* now first open the file in write mode before ... */
++ tlopen({ .client = v9p, .fid = fid_file, .flags = O_WRONLY });
++ /* ... removing the file from file system */
++ tunlinkat({ .client = v9p, .atPath = "09", .name = "doa_file" });
++
++ /* file is removed, but we still have it open, so this should succeed */
++ tgetattr({
++ .client = v9p, .fid = fid_file, .request_mask = P9_GETATTR_BASIC,
++ .rgetattr.attr = &attr
++ });
++ count = twrite({
++ .client = v9p, .fid = fid_file, .offset = 0, .count = write_count,
++ .data = buf
++ }).count;
++ g_assert_cmpint(count, ==, write_count);
++}
++
+ static void *assign_9p_local_driver(GString *cmd_line, void *arg)
+ {
+ virtio_9p_assign_local_driver(cmd_line, "security_model=mapped-xattr");
+@@ -756,6 +800,8 @@ static void register_virtio_9p_test(void)
+ qos_add_test("local/hardlink_file", "virtio-9p", fs_hardlink_file, &opts);
+ qos_add_test("local/unlinkat_hardlink", "virtio-9p", fs_unlinkat_hardlink,
+ &opts);
++ qos_add_test("local/use_after_unlink", "virtio-9p", fs_use_after_unlink,
++ &opts);
+ }
+
+ libqos_init(register_virtio_9p_test);
diff --git a/debian/patches/v7.2.17.diff b/debian/patches/v7.2.17.diff
new file mode 100644
index 00000000..fe0c18f0
--- /dev/null
+++ b/debian/patches/v7.2.17.diff
@@ -0,0 +1,1397 @@
+Subject: v7.2.17
+Date: Wed Mar 26 12:13:29 2025 +0300
+From: Michael Tokarev <mjt@tls.msk.ru>
+Forwarded: not-needed
+
+This is a difference between upstream qemu v7.2.16
+and upstream qemu v7.2.17.
+
+ VERSION | 2 +-
+ backends/cryptodev-vhost.c | 2 +-
+ block/qed.c | 1 +
+ block/snapshot.c | 1 +
+ docs/devel/build-system.rst | 10 +--
+ docs/devel/kconfig.rst | 16 ++--
+ hw/arm/Kconfig | 6 +-
+ hw/gpio/npcm7xx_gpio.c | 3 +-
+ hw/i386/amd_iommu.c | 10 +--
+ hw/i386/amd_iommu.h | 2 +-
+ hw/intc/arm_gicv3_cpuif.c | 9 ---
+ hw/misc/aspeed_hace.c | 5 ++
+ hw/net/smc91c111.c | 149 +++++++++++++++++++++++++++++++++----
+ hw/ppc/pnv_occ.c | 33 ++++----
+ hw/rtc/goldfish_rtc.c | 43 ++++-------
+ hw/usb/Kconfig | 4 +
+ hw/usb/meson.build | 2 +-
+ hw/virtio/vhost-shadow-virtqueue.c | 18 +++--
+ linux-user/syscall.c | 4 +-
+ net/vhost-vdpa.c | 13 ++++
+ target/arm/cpu.h | 1 +
+ target/arm/helper.c | 21 ++++--
+ target/arm/op_helper.c | 13 +++-
+ target/arm/translate-a64.c | 37 ++++-----
+ target/arm/translate-a64.h | 2 +-
+ target/arm/translate.h | 10 ++-
+ target/ppc/cpu_init.c | 8 --
+ target/riscv/cpu_helper.c | 18 +++++
+ target/riscv/debug.c | 6 +-
+ target/riscv/vector_helper.c | 8 +-
+ target/sparc/gdbstub.c | 18 ++++-
+ ui/cocoa.m | 5 ++
+ ui/meson.build | 2 -
+ ui/sdl2.c | 26 -------
+ util/cacheflush.c | 4 +-
+ 35 files changed, 333 insertions(+), 179 deletions(-)
+
+diff --git a/VERSION b/VERSION
+index a1f5232276..a961ff94f2 100644
+--- a/VERSION
++++ b/VERSION
+@@ -1 +1 @@
+-7.2.16
++7.2.17
+diff --git a/backends/cryptodev-vhost.c b/backends/cryptodev-vhost.c
+index 572f87b3be..af1d232a9e 100644
+--- a/backends/cryptodev-vhost.c
++++ b/backends/cryptodev-vhost.c
+@@ -54,7 +54,7 @@ cryptodev_vhost_init(
+ CryptoDevBackendVhost *crypto;
+ Error *local_err = NULL;
+
+- crypto = g_new(CryptoDevBackendVhost, 1);
++ crypto = g_new0(CryptoDevBackendVhost, 1);
+ crypto->dev.max_queues = 1;
+ crypto->dev.nvqs = 1;
+ crypto->dev.vqs = crypto->vqs;
+diff --git a/block/qed.c b/block/qed.c
+index 2f36ad342c..1ebb00fe04 100644
+--- a/block/qed.c
++++ b/block/qed.c
+@@ -340,6 +340,7 @@ static void bdrv_qed_detach_aio_context(BlockDriverState *bs)
+
+ qed_cancel_need_check_timer(s);
+ timer_free(s->need_check_timer);
++ s->need_check_timer = NULL;
+ }
+
+ static void bdrv_qed_attach_aio_context(BlockDriverState *bs,
+diff --git a/block/snapshot.c b/block/snapshot.c
+index 86e29ca59f..2f6c35f7eb 100644
+--- a/block/snapshot.c
++++ b/block/snapshot.c
+@@ -286,6 +286,7 @@ int bdrv_snapshot_goto(BlockDriverState *bs,
+ bdrv_unref_child(bs, fallback);
+
+ ret = bdrv_snapshot_goto(fallback_bs, snapshot_id, errp);
++ memset(bs->opaque, 0, drv->instance_size);
+ open_ret = drv->bdrv_open(bs, options, bs->open_flags, &local_err);
+ qobject_unref(options);
+ if (open_ret < 0) {
+diff --git a/docs/devel/build-system.rst b/docs/devel/build-system.rst
+index 1894721743..21fff65d28 100644
+--- a/docs/devel/build-system.rst
++++ b/docs/devel/build-system.rst
+@@ -193,7 +193,7 @@ Target-dependent emulator sourcesets:
+ Each emulator also includes sources for files in the ``hw/`` and ``target/``
+ subdirectories. The subdirectory used for each emulator comes
+ from the target's definition of ``TARGET_BASE_ARCH`` or (if missing)
+- ``TARGET_ARCH``, as found in ``default-configs/targets/*.mak``.
++ ``TARGET_ARCH``, as found in ``configs/targets/*.mak``.
+
+ Each subdirectory in ``hw/`` adds one sourceset to the ``hw_arch`` dictionary,
+ for example::
+@@ -250,8 +250,8 @@ Utility sourcesets:
+ The following files concur in the definition of which files are linked
+ into each emulator:
+
+-``default-configs/devices/*.mak``
+- The files under ``default-configs/devices/`` control the boards and devices
++``configs/devices/*.mak``
++ The files under ``configs/devices/`` control the boards and devices
+ that are built into each QEMU system emulation targets. They merely contain
+ a list of config variable definitions such as::
+
+@@ -260,11 +260,11 @@ into each emulator:
+ CONFIG_XLNX_VERSAL=y
+
+ ``*/Kconfig``
+- These files are processed together with ``default-configs/devices/*.mak`` and
++ These files are processed together with ``configs/devices/*.mak`` and
+ describe the dependencies between various features, subsystems and
+ device models. They are described in :ref:`kconfig`
+
+-``default-configs/targets/*.mak``
++``configs/targets/*.mak``
+ These files mostly define symbols that appear in the ``*-config-target.h``
+ file for each emulator [#cfgtarget]_. However, the ``TARGET_ARCH``
+ and ``TARGET_BASE_ARCH`` will also be used to select the ``hw/`` and
+diff --git a/docs/devel/kconfig.rst b/docs/devel/kconfig.rst
+index 69674d008a..ba5e1f399a 100644
+--- a/docs/devel/kconfig.rst
++++ b/docs/devel/kconfig.rst
+@@ -38,7 +38,7 @@ originated in the Linux kernel, though it was heavily simplified and
+ the handling of dependencies is stricter in QEMU.
+
+ Unlike Linux, there is no user interface to edit the configuration, which
+-is instead specified in per-target files under the ``default-configs/``
++is instead specified in per-target files under the ``configs/``
+ directory of the QEMU source tree. This is because, unlike Linux,
+ configuration and dependencies can be treated as a black box when building
+ QEMU; the default configuration that QEMU ships with should be okay in
+@@ -103,7 +103,7 @@ directives can be included:
+ **default value**: ``default <value> [if <expr>]``
+
+ Default values are assigned to the config symbol if no other value was
+- set by the user via ``default-configs/*.mak`` files, and only if
++ set by the user via ``configs/*.mak`` files, and only if
+ ``select`` or ``depends on`` directives do not force the value to true
+ or false respectively. ``<value>`` can be ``y`` or ``n``; it cannot
+ be an arbitrary Boolean expression. However, a condition for applying
+@@ -119,7 +119,7 @@ directives can be included:
+ This is similar to ``select`` as it applies a lower limit of ``y``
+ to another symbol. However, the lower limit is only a default
+ and the "implied" symbol's value may still be set to ``n`` from a
+- ``default-configs/*.mak`` files. The following two examples are
++ ``configs/*.mak`` files. The following two examples are
+ equivalent::
+
+ config FOO
+@@ -146,7 +146,7 @@ declares its dependencies in different ways:
+ bool
+
+ Subsystems always default to false (they have no ``default`` directive)
+- and are never visible in ``default-configs/*.mak`` files. It's
++ and are never visible in ``configs/*.mak`` files. It's
+ up to other symbols to ``select`` whatever subsystems they require.
+
+ They sometimes have ``select`` directives to bring in other required
+@@ -229,7 +229,7 @@ declares its dependencies in different ways:
+ cannot be started at all without it. It should be listed under
+ ``imply`` if (depending on the QEMU command line) the board may or
+ may not be started without it. Boards also default to false; they are
+- enabled by the ``default-configs/*.mak`` for the target they apply to.
++ enabled by the ``configs/*.mak`` for the target they apply to.
+
+ **internal elements**
+
+@@ -241,18 +241,18 @@ declares its dependencies in different ways:
+
+ Internal elements group code that is useful in several boards or
+ devices. They are usually enabled with ``select`` and in turn select
+- other elements; they are never visible in ``default-configs/*.mak``
++ other elements; they are never visible in ``configs/*.mak``
+ files, and often not even in the Makefile.
+
+ Writing and modifying default configurations
+ --------------------------------------------
+
+ In addition to the Kconfig files under hw/, each target also includes
+-a file called ``default-configs/TARGETNAME-softmmu.mak``. These files
++a file called ``configs/TARGETNAME-softmmu.mak``. These files
+ initialize some Kconfig variables to non-default values and provide the
+ starting point to turn on devices and subsystems.
+
+-A file in ``default-configs/`` looks like the following example::
++A file in ``configs/`` looks like the following example::
+
+ # Default configuration for alpha-softmmu
+
+diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
+index 17fcde8e1c..837d0c5d41 100644
+--- a/hw/arm/Kconfig
++++ b/hw/arm/Kconfig
+@@ -300,7 +300,7 @@ config ZYNQ
+ select PL330
+ select SDHCI
+ select SSI_M25P80
+- select USB_EHCI_SYSBUS
++ select USB_CHIPIDEA
+ select XILINX # UART
+ select XILINX_AXI
+ select XILINX_SPI
+@@ -416,6 +416,7 @@ config FSL_IMX25
+ select IMX
+ select IMX_FEC
+ select IMX_I2C
++ select USB_CHIPIDEA
+ select WDT_IMX2
+ select SDHCI
+
+@@ -438,6 +439,7 @@ config FSL_IMX6
+ select IMX_USBPHY
+ select WDT_IMX2
+ select SDHCI
++ select USB_CHIPIDEA
+
+ config ASPEED_SOC
+ bool
+@@ -488,6 +490,7 @@ config FSL_IMX7
+ select PCI_EXPRESS_DESIGNWARE
+ select SDHCI
+ select UNIMP
++ select USB_CHIPIDEA
+
+ config ARM_SMMUV3
+ bool
+@@ -501,6 +504,7 @@ config FSL_IMX6UL
+ select IMX_I2C
+ select WDT_IMX2
+ select SDHCI
++ select USB_CHIPIDEA
+ select UNIMP
+
+ config MICROBIT
+diff --git a/hw/gpio/npcm7xx_gpio.c b/hw/gpio/npcm7xx_gpio.c
+index 3376901ab1..c75f9e073d 100644
+--- a/hw/gpio/npcm7xx_gpio.c
++++ b/hw/gpio/npcm7xx_gpio.c
+@@ -220,8 +220,6 @@ static void npcm7xx_gpio_regs_write(void *opaque, hwaddr addr, uint64_t v,
+ return;
+ }
+
+- diff = s->regs[reg] ^ value;
+-
+ switch (reg) {
+ case NPCM7XX_GPIO_TLOCK1:
+ case NPCM7XX_GPIO_TLOCK2:
+@@ -242,6 +240,7 @@ static void npcm7xx_gpio_regs_write(void *opaque, hwaddr addr, uint64_t v,
+ case NPCM7XX_GPIO_PU:
+ case NPCM7XX_GPIO_PD:
+ case NPCM7XX_GPIO_IEM:
++ diff = s->regs[reg] ^ value;
+ s->regs[reg] = value;
+ npcm7xx_gpio_update_pins(s, diff);
+ break;
+diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c
+index 02597db1e1..d68e85b606 100644
+--- a/hw/i386/amd_iommu.c
++++ b/hw/i386/amd_iommu.c
+@@ -1279,15 +1279,15 @@ static int amdvi_int_remap_msi(AMDVIState *iommu,
+ ret = -AMDVI_IR_ERR;
+ break;
+ case AMDVI_IOAPIC_INT_TYPE_NMI:
+- pass = dte[3] & AMDVI_DEV_NMI_PASS_MASK;
++ pass = dte[2] & AMDVI_DEV_NMI_PASS_MASK;
+ trace_amdvi_ir_delivery_mode("nmi");
+ break;
+ case AMDVI_IOAPIC_INT_TYPE_INIT:
+- pass = dte[3] & AMDVI_DEV_INT_PASS_MASK;
++ pass = dte[2] & AMDVI_DEV_INT_PASS_MASK;
+ trace_amdvi_ir_delivery_mode("init");
+ break;
+ case AMDVI_IOAPIC_INT_TYPE_EINT:
+- pass = dte[3] & AMDVI_DEV_EINT_PASS_MASK;
++ pass = dte[2] & AMDVI_DEV_EINT_PASS_MASK;
+ trace_amdvi_ir_delivery_mode("eint");
+ break;
+ default:
+@@ -1514,9 +1514,9 @@ static void amdvi_init(AMDVIState *s)
+ /* reset AMDVI specific capabilities, all r/o */
+ pci_set_long(s->pci.dev.config + s->capab_offset, AMDVI_CAPAB_FEATURES);
+ pci_set_long(s->pci.dev.config + s->capab_offset + AMDVI_CAPAB_BAR_LOW,
+- s->mmio.addr & ~(0xffff0000));
++ AMDVI_BASE_ADDR & MAKE_64BIT_MASK(14, 18));
+ pci_set_long(s->pci.dev.config + s->capab_offset + AMDVI_CAPAB_BAR_HIGH,
+- (s->mmio.addr & ~(0xffff)) >> 16);
++ AMDVI_BASE_ADDR >> 32);
+ pci_set_long(s->pci.dev.config + s->capab_offset + AMDVI_CAPAB_RANGE,
+ 0xff000000);
+ pci_set_long(s->pci.dev.config + s->capab_offset + AMDVI_CAPAB_MISC, 0);
+diff --git a/hw/i386/amd_iommu.h b/hw/i386/amd_iommu.h
+index 210a37dfb1..1899e9aee1 100644
+--- a/hw/i386/amd_iommu.h
++++ b/hw/i386/amd_iommu.h
+@@ -185,7 +185,7 @@
+ AMDVI_CAPAB_FLAG_HTTUNNEL | AMDVI_CAPAB_EFR_SUP)
+
+ /* AMDVI default address */
+-#define AMDVI_BASE_ADDR 0xfed80000
++#define AMDVI_BASE_ADDR 0xfed80000ULL
+
+ /* page management constants */
+ #define AMDVI_PAGE_SHIFT 12
+diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
+index 9811fb3fb4..8d36f57f3d 100644
+--- a/hw/intc/arm_gicv3_cpuif.c
++++ b/hw/intc/arm_gicv3_cpuif.c
+@@ -2097,9 +2097,6 @@ static CPAccessResult gicv3_irqfiq_access(CPUARMState *env,
+ }
+ }
+
+- if (r == CP_ACCESS_TRAP_EL3 && !arm_el_is_aa64(env, 3)) {
+- r = CP_ACCESS_TRAP;
+- }
+ return r;
+ }
+
+@@ -2162,9 +2159,6 @@ static CPAccessResult gicv3_fiq_access(CPUARMState *env,
+ }
+ }
+
+- if (r == CP_ACCESS_TRAP_EL3 && !arm_el_is_aa64(env, 3)) {
+- r = CP_ACCESS_TRAP;
+- }
+ return r;
+ }
+
+@@ -2201,9 +2195,6 @@ static CPAccessResult gicv3_irq_access(CPUARMState *env,
+ }
+ }
+
+- if (r == CP_ACCESS_TRAP_EL3 && !arm_el_is_aa64(env, 3)) {
+- r = CP_ACCESS_TRAP;
+- }
+ return r;
+ }
+
+diff --git a/hw/misc/aspeed_hace.c b/hw/misc/aspeed_hace.c
+index 69175e972d..11bd25708e 100644
+--- a/hw/misc/aspeed_hace.c
++++ b/hw/misc/aspeed_hace.c
+@@ -123,6 +123,11 @@ static bool has_padding(AspeedHACEState *s, struct iovec *iov,
+ if (*total_msg_len <= s->total_req_len) {
+ uint32_t padding_size = s->total_req_len - *total_msg_len;
+ uint8_t *padding = iov->iov_base;
++
++ if (padding_size > req_len) {
++ return false;
++ }
++
+ *pad_offset = req_len - padding_size;
+ if (padding[*pad_offset] == 0x80) {
+ return true;
+diff --git a/hw/net/smc91c111.c b/hw/net/smc91c111.c
+index 4eda971ef3..81e5c823d1 100644
+--- a/hw/net/smc91c111.c
++++ b/hw/net/smc91c111.c
+@@ -13,6 +13,7 @@
+ #include "net/net.h"
+ #include "hw/irq.h"
+ #include "hw/net/smc91c111.h"
++#include "hw/registerfields.h"
+ #include "hw/qdev-properties.h"
+ #include "qapi/error.h"
+ #include "qemu/log.h"
+@@ -23,6 +24,13 @@
+
+ /* Number of 2k memory pages available. */
+ #define NUM_PACKETS 4
++/*
++ * Maximum size of a data frame, including the leading status word
++ * and byte count fields and the trailing CRC, last data byte
++ * and control byte (per figure 8-1 in the Microchip Technology
++ * LAN91C111 datasheet).
++ */
++#define MAX_PACKET_SIZE 2048
+
+ #define TYPE_SMC91C111 "smc91c111"
+ OBJECT_DECLARE_SIMPLE_TYPE(smc91c111_state, SMC91C111)
+@@ -119,6 +127,18 @@ static const VMStateDescription vmstate_smc91c111 = {
+ #define RS_TOOSHORT 0x0400
+ #define RS_MULTICAST 0x0001
+
++FIELD(PTR, PTR, 0, 11)
++FIELD(PTR, NOT_EMPTY, 11, 1)
++FIELD(PTR, RESERVED, 12, 1)
++FIELD(PTR, READ, 13, 1)
++FIELD(PTR, AUTOINCR, 14, 1)
++FIELD(PTR, RCV, 15, 1)
++
++static inline bool packetnum_valid(int packet_num)
++{
++ return packet_num >= 0 && packet_num < NUM_PACKETS;
++}
++
+ /* Update interrupt status. */
+ static void smc91c111_update(smc91c111_state *s)
+ {
+@@ -183,6 +203,15 @@ static void smc91c111_pop_rx_fifo(smc91c111_state *s)
+ {
+ int i;
+
++ if (s->rx_fifo_len == 0) {
++ /*
++ * The datasheet doesn't document what the behaviour is if the
++ * guest tries to pop an empty RX FIFO, and there's no obvious
++ * error status register to report it. Just ignore the attempt.
++ */
++ return;
++ }
++
+ s->rx_fifo_len--;
+ if (s->rx_fifo_len) {
+ for (i = 0; i < s->rx_fifo_len; i++)
+@@ -210,12 +239,33 @@ static void smc91c111_pop_tx_fifo_done(smc91c111_state *s)
+ /* Release the memory allocated to a packet. */
+ static void smc91c111_release_packet(smc91c111_state *s, int packet)
+ {
++ if (!packetnum_valid(packet)) {
++ /*
++ * Data sheet doesn't document behaviour in this guest error
++ * case, and there is no error status register to report it.
++ * Log and ignore the attempt.
++ */
++ qemu_log_mask(LOG_GUEST_ERROR,
++ "smc91c111: attempt to release invalid packet %d\n",
++ packet);
++ return;
++ }
+ s->allocated &= ~(1 << packet);
+ if (s->tx_alloc == 0x80)
+ smc91c111_tx_alloc(s);
+ smc91c111_flush_queued_packets(s);
+ }
+
++static void smc91c111_complete_tx_packet(smc91c111_state *s, int packetnum)
++{
++ if (s->ctr & CTR_AUTO_RELEASE) {
++ /* Race? */
++ smc91c111_release_packet(s, packetnum);
++ } else if (s->tx_fifo_done_len < NUM_PACKETS) {
++ s->tx_fifo_done[s->tx_fifo_done_len++] = packetnum;
++ }
++}
++
+ /* Flush the TX FIFO. */
+ static void smc91c111_do_tx(smc91c111_state *s)
+ {
+@@ -231,12 +281,25 @@ static void smc91c111_do_tx(smc91c111_state *s)
+ return;
+ for (i = 0; i < s->tx_fifo_len; i++) {
+ packetnum = s->tx_fifo[i];
++ /* queue_tx checked the packet number was valid */
++ assert(packetnum_valid(packetnum));
+ p = &s->data[packetnum][0];
+ /* Set status word. */
+ *(p++) = 0x01;
+ *(p++) = 0x40;
+ len = *(p++);
+ len |= ((int)*(p++)) << 8;
++ if (len > MAX_PACKET_SIZE) {
++ /*
++ * Datasheet doesn't say what to do here, and there is no
++ * relevant tx error condition listed. Log, and drop the packet.
++ */
++ qemu_log_mask(LOG_GUEST_ERROR,
++ "smc91c111: tx packet with bad length %d, dropping\n",
++ len);
++ smc91c111_complete_tx_packet(s, packetnum);
++ continue;
++ }
+ len -= 6;
+ control = p[len + 1];
+ if (control & 0x20)
+@@ -265,11 +328,7 @@ static void smc91c111_do_tx(smc91c111_state *s)
+ }
+ }
+ #endif
+- if (s->ctr & CTR_AUTO_RELEASE)
+- /* Race? */
+- smc91c111_release_packet(s, packetnum);
+- else if (s->tx_fifo_done_len < NUM_PACKETS)
+- s->tx_fifo_done[s->tx_fifo_done_len++] = packetnum;
++ smc91c111_complete_tx_packet(s, packetnum);
+ qemu_send_packet(qemu_get_queue(s->nic), p, len);
+ }
+ s->tx_fifo_len = 0;
+@@ -279,6 +338,17 @@ static void smc91c111_do_tx(smc91c111_state *s)
+ /* Add a packet to the TX FIFO. */
+ static void smc91c111_queue_tx(smc91c111_state *s, int packet)
+ {
++ if (!packetnum_valid(packet)) {
++ /*
++ * Datasheet doesn't document behaviour in this error case, and
++ * there's no error status register we could report it in.
++ * Log and ignore.
++ */
++ qemu_log_mask(LOG_GUEST_ERROR,
++ "smc91c111: attempt to queue invalid packet %d\n",
++ packet);
++ return;
++ }
+ if (s->tx_fifo_len == NUM_PACKETS)
+ return;
+ s->tx_fifo[s->tx_fifo_len++] = packet;
+@@ -310,6 +380,49 @@ static void smc91c111_reset(DeviceState *dev)
+ #define SET_LOW(name, val) s->name = (s->name & 0xff00) | val
+ #define SET_HIGH(name, val) s->name = (s->name & 0xff) | (val << 8)
+
++/*
++ * The pointer register's pointer is an 11 bit value (so it exactly
++ * indexes a 2048-byte data frame). Add the specified offset to it,
++ * wrapping around at the 2048 byte mark, and return the resulting
++ * wrapped value. There are flag bits in the top part of the register,
++ * but we can ignore them here as the mask will mask them out.
++ */
++static int ptr_reg_add(smc91c111_state *s, int offset)
++{
++ return (s->ptr + offset) & R_PTR_PTR_MASK;
++}
++
++/*
++ * For an access to the Data Register at @offset, return the
++ * required offset into the packet's data frame. This will
++ * perform the pointer register autoincrement if required, and
++ * guarantees to return an in-bounds offset.
++ */
++static int data_reg_ptr(smc91c111_state *s, int offset)
++{
++ int p;
++
++ if (s->ptr & R_PTR_AUTOINCR_MASK) {
++ /*
++ * Autoincrement: use the current pointer value, and
++ * increment the pointer register's pointer field.
++ */
++ p = FIELD_EX32(s->ptr, PTR, PTR);
++ s->ptr = FIELD_DP32(s->ptr, PTR, PTR, ptr_reg_add(s, 1));
++ } else {
++ /*
++ * No autoincrement: register offset determines which
++ * byte we're addressing. Setting the pointer to the top
++ * of the data buffer and then using the pointer wrapping
++ * to read the bottom byte of the buffer is not something
++ * sensible guest software will do, but the datasheet
++ * doesn't say what the behaviour is, so we don't forbid it.
++ */
++ p = ptr_reg_add(s, offset & 3);
++ }
++ return p;
++}
++
+ static void smc91c111_writeb(void *opaque, hwaddr offset,
+ uint32_t value)
+ {
+@@ -449,12 +562,14 @@ static void smc91c111_writeb(void *opaque, hwaddr offset,
+ n = s->rx_fifo[0];
+ else
+ n = s->packet_num;
+- p = s->ptr & 0x07ff;
+- if (s->ptr & 0x4000) {
+- s->ptr = (s->ptr & 0xf800) | ((s->ptr + 1) & 0x7ff);
+- } else {
+- p += (offset & 3);
++ if (!packetnum_valid(n)) {
++ /* Datasheet doesn't document what to do here */
++ qemu_log_mask(LOG_GUEST_ERROR,
++ "smc91c111: attempt to write data to invalid packet %d\n",
++ n);
++ return;
+ }
++ p = data_reg_ptr(s, offset);
+ s->data[n][p] = value;
+ }
+ return;
+@@ -597,12 +712,14 @@ static uint32_t smc91c111_readb(void *opaque, hwaddr offset)
+ n = s->rx_fifo[0];
+ else
+ n = s->packet_num;
+- p = s->ptr & 0x07ff;
+- if (s->ptr & 0x4000) {
+- s->ptr = (s->ptr & 0xf800) | ((s->ptr + 1) & 0x07ff);
+- } else {
+- p += (offset & 3);
++ if (!packetnum_valid(n)) {
++ /* Datasheet doesn't document what to do here */
++ qemu_log_mask(LOG_GUEST_ERROR,
++ "smc91c111: attempt to read data from invalid packet %d\n",
++ n);
++ return 0;
+ }
++ p = data_reg_ptr(s, offset);
+ return s->data[n][p];
+ }
+ case 12: /* Interrupt status. */
+@@ -705,6 +822,8 @@ static ssize_t smc91c111_receive(NetClientState *nc, const uint8_t *buf, size_t
+ return -1;
+ s->rx_fifo[s->rx_fifo_len++] = packetnum;
+
++ /* allocate_packet() will not hand us back an invalid packet number */
++ assert(packetnum_valid(packetnum));
+ p = &s->data[packetnum][0];
+ /* ??? Multicast packets? */
+ status = 0;
+diff --git a/hw/ppc/pnv_occ.c b/hw/ppc/pnv_occ.c
+index 9fa6d91d31..fe00a62b94 100644
+--- a/hw/ppc/pnv_occ.c
++++ b/hw/ppc/pnv_occ.c
+@@ -32,22 +32,21 @@
+ #define OCB_OCI_OCCMISC_OR 0x4022
+
+ /* OCC sensors */
+-#define OCC_SENSOR_DATA_BLOCK_OFFSET 0x580000
+-#define OCC_SENSOR_DATA_VALID 0x580001
+-#define OCC_SENSOR_DATA_VERSION 0x580002
+-#define OCC_SENSOR_DATA_READING_VERSION 0x580004
+-#define OCC_SENSOR_DATA_NR_SENSORS 0x580008
+-#define OCC_SENSOR_DATA_NAMES_OFFSET 0x580010
+-#define OCC_SENSOR_DATA_READING_PING_OFFSET 0x580014
+-#define OCC_SENSOR_DATA_READING_PONG_OFFSET 0x58000c
+-#define OCC_SENSOR_DATA_NAME_LENGTH 0x58000d
+-#define OCC_SENSOR_NAME_STRUCTURE_TYPE 0x580023
+-#define OCC_SENSOR_LOC_CORE 0x580022
+-#define OCC_SENSOR_LOC_GPU 0x580020
+-#define OCC_SENSOR_TYPE_POWER 0x580003
+-#define OCC_SENSOR_NAME 0x580005
+-#define HWMON_SENSORS_MASK 0x58001e
+-#define SLW_IMAGE_BASE 0x0
++#define OCC_SENSOR_DATA_BLOCK_OFFSET 0x0000
++#define OCC_SENSOR_DATA_VALID 0x0001
++#define OCC_SENSOR_DATA_VERSION 0x0002
++#define OCC_SENSOR_DATA_READING_VERSION 0x0004
++#define OCC_SENSOR_DATA_NR_SENSORS 0x0008
++#define OCC_SENSOR_DATA_NAMES_OFFSET 0x0010
++#define OCC_SENSOR_DATA_READING_PING_OFFSET 0x0014
++#define OCC_SENSOR_DATA_READING_PONG_OFFSET 0x000c
++#define OCC_SENSOR_DATA_NAME_LENGTH 0x000d
++#define OCC_SENSOR_NAME_STRUCTURE_TYPE 0x0023
++#define OCC_SENSOR_LOC_CORE 0x0022
++#define OCC_SENSOR_LOC_GPU 0x0020
++#define OCC_SENSOR_TYPE_POWER 0x0003
++#define OCC_SENSOR_NAME 0x0005
++#define HWMON_SENSORS_MASK 0x001e
+
+ static void pnv_occ_set_misc(PnvOCC *occ, uint64_t val)
+ {
+@@ -129,8 +128,6 @@ static uint64_t pnv_occ_common_area_read(void *opaque, hwaddr addr,
+ case HWMON_SENSORS_MASK:
+ case OCC_SENSOR_LOC_GPU:
+ return 0x8e00;
+- case SLW_IMAGE_BASE:
+- return 0x1000000000000000;
+ }
+ return 0;
+ }
+diff --git a/hw/rtc/goldfish_rtc.c b/hw/rtc/goldfish_rtc.c
+index 19a56402a0..81cc942b46 100644
+--- a/hw/rtc/goldfish_rtc.c
++++ b/hw/rtc/goldfish_rtc.c
+@@ -178,38 +178,21 @@ static void goldfish_rtc_write(void *opaque, hwaddr offset,
+ trace_goldfish_rtc_write(offset, value);
+ }
+
+-static int goldfish_rtc_pre_save(void *opaque)
+-{
+- uint64_t delta;
+- GoldfishRTCState *s = opaque;
+-
+- /*
+- * We want to migrate this offset, which sounds straightforward.
+- * Unfortunately, we cannot directly pass tick_offset because
+- * rtc_clock on destination Host might not be same source Host.
+- *
+- * To tackle, this we pass tick_offset relative to vm_clock from
+- * source Host and make it relative to rtc_clock at destination Host.
+- */
+- delta = qemu_clock_get_ns(rtc_clock) -
+- qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+- s->tick_offset_vmstate = s->tick_offset + delta;
+-
+- return 0;
+-}
+-
+ static int goldfish_rtc_post_load(void *opaque, int version_id)
+ {
+- uint64_t delta;
+ GoldfishRTCState *s = opaque;
+
+- /*
+- * We extract tick_offset from tick_offset_vmstate by doing
+- * reverse math compared to pre_save() function.
+- */
+- delta = qemu_clock_get_ns(rtc_clock) -
+- qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+- s->tick_offset = s->tick_offset_vmstate - delta;
++ if (version_id < 3) {
++ /*
++ * Previous versions didn't migrate tick_offset directly. Instead, they
++ * migrated tick_offset_vmstate, which is a recalculation based on
++ * QEMU_CLOCK_VIRTUAL. We use tick_offset_vmstate when migrating from
++ * older versions.
++ */
++ uint64_t delta = qemu_clock_get_ns(rtc_clock) -
++ qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
++ s->tick_offset = s->tick_offset_vmstate - delta;
++ }
+
+ goldfish_rtc_set_alarm(s);
+
+@@ -239,8 +222,7 @@ static const MemoryRegionOps goldfish_rtc_ops[2] = {
+
+ static const VMStateDescription goldfish_rtc_vmstate = {
+ .name = TYPE_GOLDFISH_RTC,
+- .version_id = 2,
+- .pre_save = goldfish_rtc_pre_save,
++ .version_id = 3,
+ .post_load = goldfish_rtc_post_load,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT64(tick_offset_vmstate, GoldfishRTCState),
+@@ -249,6 +231,7 @@ static const VMStateDescription goldfish_rtc_vmstate = {
+ VMSTATE_UINT32(irq_pending, GoldfishRTCState),
+ VMSTATE_UINT32(irq_enabled, GoldfishRTCState),
+ VMSTATE_UINT32(time_high, GoldfishRTCState),
++ VMSTATE_UINT64_V(tick_offset, GoldfishRTCState, 3),
+ VMSTATE_END_OF_LIST()
+ }
+ };
+diff --git a/hw/usb/Kconfig b/hw/usb/Kconfig
+index ce4f433976..db17750a64 100644
+--- a/hw/usb/Kconfig
++++ b/hw/usb/Kconfig
+@@ -138,3 +138,7 @@ config XLNX_USB_SUBSYS
+ bool
+ default y if XLNX_VERSAL
+ select USB_DWC3
++
++config USB_CHIPIDEA
++ bool
++ select USB_EHCI_SYSBUS
+diff --git a/hw/usb/meson.build b/hw/usb/meson.build
+index 793df42e21..ed5d0ad7e5 100644
+--- a/hw/usb/meson.build
++++ b/hw/usb/meson.build
+@@ -25,9 +25,9 @@ softmmu_ss.add(when: 'CONFIG_USB_XHCI_NEC', if_true: files('hcd-xhci-nec.c'))
+ softmmu_ss.add(when: 'CONFIG_USB_MUSB', if_true: files('hcd-musb.c'))
+ softmmu_ss.add(when: 'CONFIG_USB_DWC2', if_true: files('hcd-dwc2.c'))
+ softmmu_ss.add(when: 'CONFIG_USB_DWC3', if_true: files('hcd-dwc3.c'))
++softmmu_ss.add(when: 'CONFIG_USB_CHIPIDEA', if_true: files('chipidea.c'))
+
+ softmmu_ss.add(when: 'CONFIG_TUSB6010', if_true: files('tusb6010.c'))
+-softmmu_ss.add(when: 'CONFIG_IMX', if_true: files('chipidea.c'))
+ softmmu_ss.add(when: 'CONFIG_IMX_USBPHY', if_true: files('imx-usb-phy.c'))
+ softmmu_ss.add(when: 'CONFIG_VT82C686', if_true: files('vt82c686-uhci-pci.c'))
+ specific_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files('xlnx-versal-usb2-ctrl-regs.c'))
+diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c
+index d422418f2d..20dcc7d2a0 100644
+--- a/hw/virtio/vhost-shadow-virtqueue.c
++++ b/hw/virtio/vhost-shadow-virtqueue.c
+@@ -165,10 +165,10 @@ static bool vhost_svq_vring_write_descs(VhostShadowVirtqueue *svq, hwaddr *sg,
+ descs[i].len = cpu_to_le32(iovec[n].iov_len);
+
+ last = i;
+- i = cpu_to_le16(svq->desc_next[i]);
++ i = svq->desc_next[i];
+ }
+
+- svq->free_head = le16_to_cpu(svq->desc_next[last]);
++ svq->free_head = svq->desc_next[last];
+ return true;
+ }
+
+@@ -228,10 +228,12 @@ static void vhost_svq_kick(VhostShadowVirtqueue *svq)
+ smp_mb();
+
+ if (virtio_vdev_has_feature(svq->vdev, VIRTIO_RING_F_EVENT_IDX)) {
+- uint16_t avail_event = *(uint16_t *)(&svq->vring.used->ring[svq->vring.num]);
++ uint16_t avail_event = le16_to_cpu(
++ *(uint16_t *)(&svq->vring.used->ring[svq->vring.num]));
+ needs_kick = vring_need_event(avail_event, svq->shadow_avail_idx, svq->shadow_avail_idx - 1);
+ } else {
+- needs_kick = !(svq->vring.used->flags & VRING_USED_F_NO_NOTIFY);
++ needs_kick =
++ !(svq->vring.used->flags & cpu_to_le16(VRING_USED_F_NO_NOTIFY));
+ }
+
+ if (!needs_kick) {
+@@ -365,7 +367,7 @@ static bool vhost_svq_more_used(VhostShadowVirtqueue *svq)
+ return true;
+ }
+
+- svq->shadow_used_idx = cpu_to_le16(*(volatile uint16_t *)used_idx);
++ svq->shadow_used_idx = le16_to_cpu(*(volatile uint16_t *)used_idx);
+
+ return svq->last_used_idx != svq->shadow_used_idx;
+ }
+@@ -383,7 +385,7 @@ static bool vhost_svq_enable_notification(VhostShadowVirtqueue *svq)
+ {
+ if (virtio_vdev_has_feature(svq->vdev, VIRTIO_RING_F_EVENT_IDX)) {
+ uint16_t *used_event = (uint16_t *)&svq->vring.avail->ring[svq->vring.num];
+- *used_event = svq->shadow_used_idx;
++ *used_event = cpu_to_le16(svq->shadow_used_idx);
+ } else {
+ svq->vring.avail->flags &= ~cpu_to_le16(VRING_AVAIL_F_NO_INTERRUPT);
+ }
+@@ -408,7 +410,7 @@ static uint16_t vhost_svq_last_desc_of_chain(const VhostShadowVirtqueue *svq,
+ uint16_t num, uint16_t i)
+ {
+ for (uint16_t j = 0; j < (num - 1); ++j) {
+- i = le16_to_cpu(svq->desc_next[i]);
++ i = svq->desc_next[i];
+ }
+
+ return i;
+@@ -670,7 +672,7 @@ void vhost_svq_start(VhostShadowVirtqueue *svq, VirtIODevice *vdev,
+ svq->desc_state = g_new0(SVQDescState, svq->vring.num);
+ svq->desc_next = g_new0(uint16_t, svq->vring.num);
+ for (unsigned i = 0; i < svq->vring.num - 1; i++) {
+- svq->desc_next[i] = cpu_to_le16(i + 1);
++ svq->desc_next[i] = i + 1;
+ }
+ }
+
+diff --git a/linux-user/syscall.c b/linux-user/syscall.c
+index 236076e647..737065c28c 100644
+--- a/linux-user/syscall.c
++++ b/linux-user/syscall.c
+@@ -352,7 +352,8 @@ _syscall3(int, sys_sched_getaffinity, pid_t, pid, unsigned int, len,
+ #define __NR_sys_sched_setaffinity __NR_sched_setaffinity
+ _syscall3(int, sys_sched_setaffinity, pid_t, pid, unsigned int, len,
+ unsigned long *, user_mask_ptr);
+-/* sched_attr is not defined in glibc */
++/* sched_attr is not defined in glibc < 2.41 */
++#ifndef SCHED_ATTR_SIZE_VER0
+ struct sched_attr {
+ uint32_t size;
+ uint32_t sched_policy;
+@@ -365,6 +366,7 @@ struct sched_attr {
+ uint32_t sched_util_min;
+ uint32_t sched_util_max;
+ };
++#endif
+ #define __NR_sys_sched_getattr __NR_sched_getattr
+ _syscall4(int, sys_sched_getattr, pid_t, pid, struct sched_attr *, attr,
+ unsigned int, size, unsigned int, flags);
+diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c
+index 1b1a27de02..fcc9406a20 100644
+--- a/net/vhost-vdpa.c
++++ b/net/vhost-vdpa.c
+@@ -203,6 +203,18 @@ static bool vhost_vdpa_has_ufo(NetClientState *nc)
+
+ }
+
++/*
++ * FIXME: vhost_vdpa doesn't have an API to "set h/w endianness". But it's
++ * reasonable to assume that h/w is LE by default, because LE is what
++ * virtio 1.0 and later ask for. So, this function just says "yes, the h/w is
++ * LE". Otherwise, on a BE machine, higher-level code would mistakely think
++ * the h/w is BE and can't support VDPA for a virtio 1.0 client.
++ */
++static int vhost_vdpa_set_vnet_le(NetClientState *nc, bool enable)
++{
++ return 0;
++}
++
+ static bool vhost_vdpa_check_peer_type(NetClientState *nc, ObjectClass *oc,
+ Error **errp)
+ {
+@@ -230,6 +242,7 @@ static NetClientInfo net_vhost_vdpa_info = {
+ .cleanup = vhost_vdpa_cleanup,
+ .has_vnet_hdr = vhost_vdpa_has_vnet_hdr,
+ .has_ufo = vhost_vdpa_has_ufo,
++ .set_vnet_le = vhost_vdpa_set_vnet_le,
+ .check_peer_type = vhost_vdpa_check_peer_type,
+ };
+
+diff --git a/target/arm/cpu.h b/target/arm/cpu.h
+index a9cd7178f8..32b0bf8e2d 100644
+--- a/target/arm/cpu.h
++++ b/target/arm/cpu.h
+@@ -57,6 +57,7 @@
+ #define EXCP_UNALIGNED 22 /* v7M UNALIGNED UsageFault */
+ #define EXCP_DIVBYZERO 23 /* v7M DIVBYZERO UsageFault */
+ #define EXCP_VSERR 24
++#define EXCP_MON_TRAP 29 /* AArch32 trap to Monitor mode */
+ /* NB: add new EXCP_ defines to the array in arm_log_exception() too */
+
+ #define ARMV7M_EXCP_RESET 1
+diff --git a/target/arm/helper.c b/target/arm/helper.c
+index 5c22626b80..6cffbcb276 100644
+--- a/target/arm/helper.c
++++ b/target/arm/helper.c
+@@ -2505,7 +2505,7 @@ static CPAccessResult gt_stimer_access(CPUARMState *env,
+ switch (arm_current_el(env)) {
+ case 1:
+ if (!arm_is_secure(env)) {
+- return CP_ACCESS_TRAP;
++ return CP_ACCESS_TRAP_UNCATEGORIZED;
+ }
+ if (!(env->cp15.scr_el3 & SCR_ST)) {
+ return CP_ACCESS_TRAP_EL3;
+@@ -2513,7 +2513,7 @@ static CPAccessResult gt_stimer_access(CPUARMState *env,
+ return CP_ACCESS_OK;
+ case 0:
+ case 2:
+- return CP_ACCESS_TRAP;
++ return CP_ACCESS_TRAP_UNCATEGORIZED;
+ case 3:
+ return CP_ACCESS_OK;
+ default:
+@@ -3516,7 +3516,7 @@ static CPAccessResult at_s1e2_access(CPUARMState *env, const ARMCPRegInfo *ri,
+ {
+ if (arm_current_el(env) == 3 &&
+ !(env->cp15.scr_el3 & (SCR_NS | SCR_EEL2))) {
+- return CP_ACCESS_TRAP;
++ return CP_ACCESS_TRAP_UNCATEGORIZED;
+ }
+ return CP_ACCESS_OK;
+ }
+@@ -6650,8 +6650,8 @@ 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;
++ /* UNDEF if SCR_EL3.NS == 0 */
++ return CP_ACCESS_TRAP_UNCATEGORIZED;
+ }
+ return access_lor_ns(env, ri, isread);
+ }
+@@ -9475,6 +9475,7 @@ void arm_log_exception(CPUState *cs)
+ [EXCP_UNALIGNED] = "v7M UNALIGNED UsageFault",
+ [EXCP_DIVBYZERO] = "v7M DIVBYZERO UsageFault",
+ [EXCP_VSERR] = "Virtual SERR",
++ [EXCP_MON_TRAP] = "Monitor Trap",
+ };
+
+ if (idx >= 0 && idx < ARRAY_SIZE(excnames)) {
+@@ -10036,6 +10037,16 @@ static void arm_cpu_do_interrupt_aarch32(CPUState *cs)
+ mask = CPSR_A | CPSR_I | CPSR_F;
+ offset = 0;
+ break;
++ case EXCP_MON_TRAP:
++ new_mode = ARM_CPU_MODE_MON;
++ addr = 0x04;
++ mask = CPSR_A | CPSR_I | CPSR_F;
++ if (env->thumb) {
++ offset = 2;
++ } else {
++ offset = 4;
++ }
++ break;
+ default:
+ cpu_abort(cs, "Unhandled exception 0x%x\n", cs->exception_index);
+ return; /* Never happens. Keep compiler happy. */
+diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
+index 70672bcd9f..9b07c79392 100644
+--- a/target/arm/op_helper.c
++++ b/target/arm/op_helper.c
+@@ -631,6 +631,7 @@ void HELPER(access_check_cp_reg)(CPUARMState *env, void *rip, uint32_t syndrome,
+ const ARMCPRegInfo *ri = rip;
+ CPAccessResult res = CP_ACCESS_OK;
+ int target_el;
++ uint32_t excp;
+
+ if (arm_feature(env, ARM_FEATURE_XSCALE) && ri->cp < 14
+ && extract32(env->cp15.c15_cpar, ri->cp, 1) == 0) {
+@@ -667,8 +668,18 @@ void HELPER(access_check_cp_reg)(CPUARMState *env, void *rip, uint32_t syndrome,
+ }
+
+ fail:
++ excp = EXCP_UDEF;
+ switch (res & ~CP_ACCESS_EL_MASK) {
+ case CP_ACCESS_TRAP:
++ /*
++ * If EL3 is AArch32 then there's no syndrome register; the cases
++ * where we would raise a SystemAccessTrap to AArch64 EL3 all become
++ * raising a Monitor trap exception. (Because there's no visible
++ * syndrome it doesn't matter what we pass to raise_exception().)
++ */
++ if ((res & CP_ACCESS_EL_MASK) == 3 && !arm_el_is_aa64(env, 3)) {
++ excp = EXCP_MON_TRAP;
++ }
+ break;
+ case CP_ACCESS_TRAP_UNCATEGORIZED:
+ if (cpu_isar_feature(aa64_ids, cpu) && isread &&
+@@ -702,7 +713,7 @@ void HELPER(access_check_cp_reg)(CPUARMState *env, void *rip, uint32_t syndrome,
+ g_assert_not_reached();
+ }
+
+- raise_exception(env, EXCP_UDEF, syndrome, target_el);
++ raise_exception(env, excp, syndrome, target_el);
+ }
+
+ void HELPER(set_cp_reg)(CPUARMState *env, void *rip, uint32_t value)
+diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
+index f0b8db7ce5..190574cb29 100644
+--- a/target/arm/translate-a64.c
++++ b/target/arm/translate-a64.c
+@@ -1176,14 +1176,14 @@ static bool fp_access_check_only(DisasContext *s)
+ {
+ if (s->fp_excp_el) {
+ assert(!s->fp_access_checked);
+- s->fp_access_checked = true;
++ s->fp_access_checked = -1;
+
+ gen_exception_insn_el(s, 0, EXCP_UDEF,
+ syn_fp_access_trap(1, 0xe, false, 0),
+ s->fp_excp_el);
+ return false;
+ }
+- s->fp_access_checked = true;
++ s->fp_access_checked = 1;
+ return true;
+ }
+
+@@ -1208,23 +1208,23 @@ static bool fp_access_check(DisasContext *s)
+ bool sve_access_check(DisasContext *s)
+ {
+ if (s->pstate_sm || !dc_isar_feature(aa64_sve, s)) {
++ bool ret;
++
+ assert(dc_isar_feature(aa64_sme, s));
+- if (!sme_sm_enabled_check(s)) {
+- goto fail_exit;
+- }
+- } else if (s->sve_excp_el) {
++ ret = sme_sm_enabled_check(s);
++ s->sve_access_checked = (ret ? 1 : -1);
++ return ret;
++ }
++ if (s->sve_excp_el) {
++ /* Assert that we only raise one exception per instruction. */
++ assert(!s->sve_access_checked);
+ gen_exception_insn_el(s, 0, EXCP_UDEF,
+ syn_sve_access_trap(), s->sve_excp_el);
+- goto fail_exit;
++ s->sve_access_checked = -1;
++ return false;
+ }
+- s->sve_access_checked = true;
++ s->sve_access_checked = 1;
+ return fp_access_check(s);
+-
+- fail_exit:
+- /* Assert that we only raise one exception per instruction. */
+- assert(!s->sve_access_checked);
+- s->sve_access_checked = true;
+- return false;
+ }
+
+ /*
+@@ -1252,8 +1252,9 @@ bool sme_enabled_check(DisasContext *s)
+ * sme_excp_el by itself for cpregs access checks.
+ */
+ if (!s->fp_excp_el || s->sme_excp_el < s->fp_excp_el) {
+- s->fp_access_checked = true;
+- return sme_access_check(s);
++ bool ret = sme_access_check(s);
++ s->fp_access_checked = (ret ? 1 : -1);
++ return ret;
+ }
+ return fp_access_check_only(s);
+ }
+@@ -14870,8 +14871,8 @@ static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
+ s->insn = insn;
+ s->base.pc_next = pc + 4;
+
+- s->fp_access_checked = false;
+- s->sve_access_checked = false;
++ s->fp_access_checked = 0;
++ s->sve_access_checked = 0;
+
+ if (s->pstate_il) {
+ /*
+diff --git a/target/arm/translate-a64.h b/target/arm/translate-a64.h
+index ad3762d1ac..f01d2d973c 100644
+--- a/target/arm/translate-a64.h
++++ b/target/arm/translate-a64.h
+@@ -66,7 +66,7 @@ TCGv_i64 gen_mte_checkN(DisasContext *s, TCGv_i64 addr, bool is_write,
+ static inline void assert_fp_access_checked(DisasContext *s)
+ {
+ #ifdef CONFIG_DEBUG_TCG
+- if (unlikely(!s->fp_access_checked || s->fp_excp_el)) {
++ if (unlikely(s->fp_access_checked <= 0)) {
+ fprintf(stderr, "target-arm: FP access check missing for "
+ "instruction 0x%08x\n", s->insn);
+ abort();
+diff --git a/target/arm/translate.h b/target/arm/translate.h
+index 3cdc7dbc2f..3856df8060 100644
+--- a/target/arm/translate.h
++++ b/target/arm/translate.h
+@@ -85,15 +85,19 @@ typedef struct DisasContext {
+ uint64_t features; /* CPU features bits */
+ bool aarch64;
+ bool thumb;
+- /* Because unallocated encodings generate different exception syndrome
++ /*
++ * Because unallocated encodings generate different exception syndrome
+ * information from traps due to FP being disabled, we can't do a single
+ * "is fp access disabled" check at a high level in the decode tree.
+ * To help in catching bugs where the access check was forgotten in some
+ * code path, we set this flag when the access check is done, and assert
+ * that it is set at the point where we actually touch the FP regs.
++ * 0: not checked,
++ * 1: checked, access ok
++ * -1: checked, access denied
+ */
+- bool fp_access_checked;
+- bool sve_access_checked;
++ int8_t fp_access_checked;
++ int8_t sve_access_checked;
+ /* ARMv8 single-step state (this is distinct from the QEMU gdbstub
+ * single-step support).
+ */
+diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
+index 294a18a5b7..3f22e0b02e 100644
+--- a/target/ppc/cpu_init.c
++++ b/target/ppc/cpu_init.c
+@@ -2712,14 +2712,6 @@ static void init_proc_e200(CPUPPCState *env)
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_generic,
+ 0x00000000); /* TOFIX */
+- spr_register(env, SPR_BOOKE_DSRR0, "DSRR0",
+- SPR_NOACCESS, SPR_NOACCESS,
+- &spr_read_generic, &spr_write_generic,
+- 0x00000000);
+- spr_register(env, SPR_BOOKE_DSRR1, "DSRR1",
+- SPR_NOACCESS, SPR_NOACCESS,
+- &spr_read_generic, &spr_write_generic,
+- 0x00000000);
+ #if !defined(CONFIG_USER_ONLY)
+ env->nb_tlb = 64;
+ env->nb_ways = 1;
+diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
+index 278d163803..b68327e13f 100644
+--- a/target/riscv/cpu_helper.c
++++ b/target/riscv/cpu_helper.c
+@@ -25,6 +25,7 @@
+ #include "exec/exec-all.h"
+ #include "instmap.h"
+ #include "tcg/tcg-op.h"
++#include "hw/core/tcg-cpu-ops.h"
+ #include "trace.h"
+ #include "semihosting/common-semi.h"
+ #include "cpu_bits.h"
+@@ -1345,6 +1346,23 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
+ } else if (probe) {
+ return false;
+ } else {
++ int wp_access = 0;
++
++ if (access_type == MMU_DATA_LOAD) {
++ wp_access |= BP_MEM_READ;
++ } else if (access_type == MMU_DATA_STORE) {
++ wp_access |= BP_MEM_WRITE;
++ }
++
++ /*
++ * If a watchpoint isn't found for 'addr' this will
++ * be a no-op and we'll resume the mmu_exception path.
++ * Otherwise we'll throw a debug exception and execution
++ * will continue elsewhere.
++ */
++ cpu_check_watchpoint(cs, address, size, MEMTXATTRS_UNSPECIFIED,
++ wp_access, retaddr);
++
+ raise_mmu_exception(env, address, access_type, pmp_violation,
+ first_stage_error,
+ riscv_cpu_virt_enabled(env) ||
+diff --git a/target/riscv/debug.c b/target/riscv/debug.c
+index 26ea764407..cf71b52899 100644
+--- a/target/riscv/debug.c
++++ b/target/riscv/debug.c
+@@ -305,7 +305,7 @@ static void type2_breakpoint_insert(CPURISCVState *env, target_ulong index)
+ bool enabled = type2_breakpoint_enabled(ctrl);
+ CPUState *cs = env_cpu(env);
+ int flags = BP_CPU | BP_STOP_BEFORE_ACCESS;
+- uint32_t size;
++ uint32_t size, def_size;
+
+ if (!enabled) {
+ return;
+@@ -328,7 +328,9 @@ static void type2_breakpoint_insert(CPURISCVState *env, target_ulong index)
+ cpu_watchpoint_insert(cs, addr, size, flags,
+ &env->cpu_watchpoint[index]);
+ } else {
+- cpu_watchpoint_insert(cs, addr, 8, flags,
++ def_size = riscv_cpu_mxl(env) == MXL_RV64 ? 8 : 4;
++
++ cpu_watchpoint_insert(cs, addr, def_size, flags,
+ &env->cpu_watchpoint[index]);
+ }
+ }
+diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c
+index a6ac61c724..d2fe96e5c8 100644
+--- a/target/riscv/vector_helper.c
++++ b/target/riscv/vector_helper.c
+@@ -4621,7 +4621,9 @@ void HELPER(NAME)(void *vd, void *v0, void *vs1, \
+ } \
+ s1 = OP(s1, (TD)s2); \
+ } \
+- *((TD *)vd + HD(0)) = s1; \
++ if (vl > 0) { \
++ *((TD *)vd + HD(0)) = s1; \
++ } \
+ env->vstart = 0; \
+ /* set tail elements to 1s */ \
+ vext_set_elems_1s(vd, vta, esz, vlenb); \
+@@ -4707,7 +4709,9 @@ void HELPER(NAME)(void *vd, void *v0, void *vs1, \
+ } \
+ s1 = OP(s1, (TD)s2, &env->fp_status); \
+ } \
+- *((TD *)vd + HD(0)) = s1; \
++ if (vl > 0) { \
++ *((TD *)vd + HD(0)) = s1; \
++ } \
+ env->vstart = 0; \
+ /* set tail elements to 1s */ \
+ vext_set_elems_1s(vd, vta, esz, vlenb); \
+diff --git a/target/sparc/gdbstub.c b/target/sparc/gdbstub.c
+index 5d1e808e8c..2bbc494d81 100644
+--- a/target/sparc/gdbstub.c
++++ b/target/sparc/gdbstub.c
+@@ -80,8 +80,13 @@ int sparc_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
+ }
+ }
+ if (n < 80) {
+- /* f32-f62 (double width, even numbers only) */
+- return gdb_get_reg64(mem_buf, env->fpr[(n - 32) / 2].ll);
++ /* f32-f62 (16 double width registers, even register numbers only)
++ * n == 64: f32 : env->fpr[16]
++ * n == 65: f34 : env->fpr[17]
++ * etc...
++ * n == 79: f62 : env->fpr[31]
++ */
++ return gdb_get_reg64(mem_buf, env->fpr[(n - 64) + 16].ll);
+ }
+ switch (n) {
+ case 80:
+@@ -174,8 +179,13 @@ int sparc_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
+ }
+ return 4;
+ } else if (n < 80) {
+- /* f32-f62 (double width, even numbers only) */
+- env->fpr[(n - 32) / 2].ll = tmp;
++ /* f32-f62 (16 double width registers, even register numbers only)
++ * n == 64: f32 : env->fpr[16]
++ * n == 65: f34 : env->fpr[17]
++ * etc...
++ * n == 79: f62 : env->fpr[31]
++ */
++ env->fpr[(n - 64) + 16].ll = tmp;
+ } else {
+ switch (n) {
+ case 80:
+diff --git a/ui/cocoa.m b/ui/cocoa.m
+index c41689e951..54acf14794 100644
+--- a/ui/cocoa.m
++++ b/ui/cocoa.m
+@@ -549,6 +549,9 @@ - (void) setContentDimensions
+ }
+ }
+
++#pragma clang diagnostic push
++#pragma clang diagnostic ignored "-Wdeprecated-declarations"
++
+ - (void) updateUIInfoLocked
+ {
+ /* Must be called with the iothread lock, i.e. via updateUIInfo */
+@@ -594,6 +597,8 @@ - (void) updateUIInfoLocked
+ dpy_set_ui_info(dcl.con, &info, TRUE);
+ }
+
++#pragma clang diagnostic pop
++
+ - (void) updateUIInfo
+ {
+ if (!allow_events) {
+diff --git a/ui/meson.build b/ui/meson.build
+index 76c6644b3f..7756760789 100644
+--- a/ui/meson.build
++++ b/ui/meson.build
+@@ -110,8 +110,6 @@ if gtk.found()
+ endif
+
+ if sdl.found()
+- softmmu_ss.add(when: 'CONFIG_WIN32', if_true: files('win32-kbd-hook.c'))
+-
+ sdl_ss = ss.source_set()
+ sdl_ss.add(sdl, sdl_image, pixman, glib, files(
+ 'sdl2-2d.c',
+diff --git a/ui/sdl2.c b/ui/sdl2.c
+index fc7e8639c2..f9e7402151 100644
+--- a/ui/sdl2.c
++++ b/ui/sdl2.c
+@@ -32,7 +32,6 @@
+ #include "sysemu/runstate.h"
+ #include "sysemu/runstate-action.h"
+ #include "sysemu/sysemu.h"
+-#include "ui/win32-kbd-hook.h"
+ #include "qemu/log.h"
+
+ static int sdl2_num_outputs;
+@@ -231,7 +230,6 @@ static void sdl_grab_start(struct sdl2_console *scon)
+ }
+ SDL_SetWindowGrab(scon->real_window, SDL_TRUE);
+ gui_grab = 1;
+- win32_kbd_set_grab(true);
+ sdl_update_caption(scon);
+ }
+
+@@ -239,7 +237,6 @@ static void sdl_grab_end(struct sdl2_console *scon)
+ {
+ SDL_SetWindowGrab(scon->real_window, SDL_FALSE);
+ gui_grab = 0;
+- win32_kbd_set_grab(false);
+ sdl_show_cursor(scon);
+ sdl_update_caption(scon);
+ }
+@@ -340,19 +337,6 @@ static int get_mod_state(void)
+ }
+ }
+
+-static void *sdl2_win32_get_hwnd(struct sdl2_console *scon)
+-{
+-#ifdef CONFIG_WIN32
+- SDL_SysWMinfo info;
+-
+- SDL_VERSION(&info.version);
+- if (SDL_GetWindowWMInfo(scon->real_window, &info)) {
+- return info.info.win.window;
+- }
+-#endif
+- return NULL;
+-}
+-
+ static void handle_keydown(SDL_Event *ev)
+ {
+ int win;
+@@ -576,10 +560,6 @@ static void handle_windowevent(SDL_Event *ev)
+ sdl2_redraw(scon);
+ break;
+ case SDL_WINDOWEVENT_FOCUS_GAINED:
+- win32_kbd_set_grab(gui_grab);
+- if (qemu_console_is_graphic(scon->dcl.con)) {
+- win32_kbd_set_window(sdl2_win32_get_hwnd(scon));
+- }
+ /* fall through */
+ case SDL_WINDOWEVENT_ENTER:
+ if (!gui_grab && (qemu_input_is_absolute() || absolute_enabled)) {
+@@ -595,9 +575,6 @@ static void handle_windowevent(SDL_Event *ev)
+ scon->ignore_hotkeys = get_mod_state();
+ break;
+ case SDL_WINDOWEVENT_FOCUS_LOST:
+- if (qemu_console_is_graphic(scon->dcl.con)) {
+- win32_kbd_set_window(NULL);
+- }
+ if (gui_grab && !gui_fullscreen) {
+ sdl_grab_end(scon);
+ }
+@@ -849,10 +826,7 @@ static void sdl2_display_init(DisplayState *ds, DisplayOptions *o)
+ #ifdef SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR /* only available since SDL 2.0.8 */
+ SDL_SetHint(SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR, "0");
+ #endif
+-#ifndef CONFIG_WIN32
+- /* QEMU uses its own low level keyboard hook procecure on Windows */
+ SDL_SetHint(SDL_HINT_GRAB_KEYBOARD, "1");
+-#endif
+ #ifdef SDL_HINT_ALLOW_ALT_TAB_WHILE_GRABBED
+ SDL_SetHint(SDL_HINT_ALLOW_ALT_TAB_WHILE_GRABBED, "0");
+ #endif
+diff --git a/util/cacheflush.c b/util/cacheflush.c
+index 2c2c73e085..9b1debd1c1 100644
+--- a/util/cacheflush.c
++++ b/util/cacheflush.c
+@@ -264,9 +264,11 @@ void flush_idcache_range(uintptr_t rx, uintptr_t rw, size_t len)
+ for (p = rw & -dcache_lsize; p < rw + len; p += dcache_lsize) {
+ asm volatile("dc\tcvau, %0" : : "r" (p) : "memory");
+ }
+- asm volatile("dsb\tish" : : : "memory");
+ }
+
++ /* DSB unconditionally to ensure any outstanding writes are committed. */
++ asm volatile("dsb\tish" : : : "memory");
++
+ /*
+ * If CTR_EL0.DIC is enabled, Instruction cache cleaning to the Point
+ * of Unification is not required for instruction to data coherence.
diff --git a/debian/patches/v7.2.2.diff b/debian/patches/v7.2.2.diff
new file mode 100644
index 00000000..719617f6
--- /dev/null
+++ b/debian/patches/v7.2.2.diff
@@ -0,0 +1,514 @@
+Subject: v7.2.2
+Date: Sat, 29 Apr 2023 12:09:18 +0300
+From: Michael Tokarev <mjt@tls.msk.ru>
+Forwarded: not-needed
+
+This is a difference between upstream qemu v7.2.1
+and upstream qemu v7.2.2.
+
+ VERSION | 2 +-
+ block/vhdx-log.c | 2 +-
+ hw/arm/boot.c | 5 ++++-
+ hw/net/vmxnet3.c | 2 +-
+ hw/nvme/ctrl.c | 3 +++
+ hw/rdma/vmw/pvrdma_cmd.c | 6 ++++++
+ include/qemu/osdep.h | 2 +-
+ io/channel-tls.c | 3 +++
+ linux-user/fd-trans.c | 10 ++++++---
+ linux-user/fd-trans.h | 1 +
+ linux-user/generic/target_resource.h | 4 ++--
+ linux-user/syscall.c | 21 ++++++++++++------
+ qga/commands.c | 5 ++---
+ qga/installer/qemu-ga.wxs | 1 +
+ qga/vss-win32/install.cpp | 2 +-
+ target/arm/cpu.h | 3 +++
+ target/s390x/arch_dump.c | 2 +-
+ target/s390x/cpu.h | 1 +
+ target/s390x/s390x-internal.h | 3 ++-
+ target/s390x/tcg/insn-data.h.inc | 4 ++--
+ target/s390x/tcg/mem_helper.c | 1 +
+ target/s390x/tcg/translate.c | 41 ++++++++++++++++++++++++++++--------
+ ui/gtk.c | 4 +++-
+ util/fdmon-epoll.c | 25 ++++++++++++++++------
+ 24 files changed, 112 insertions(+), 41 deletions(-)
+
+diff --git a/VERSION b/VERSION
+index b26a34e470..77f5bec5b2 100644
+--- a/VERSION
++++ b/VERSION
+@@ -1 +1 @@
+-7.2.1
++7.2.2
+diff --git a/block/vhdx-log.c b/block/vhdx-log.c
+index 572582b87b..0866897a85 100644
+--- a/block/vhdx-log.c
++++ b/block/vhdx-log.c
+@@ -980,7 +980,7 @@ static int vhdx_log_write(BlockDriverState *bs, BDRVVHDXState *s,
+ sector_write = merged_sector;
+ } else if (i == sectors - 1 && trailing_length) {
+ /* partial sector at the end of the buffer */
+- ret = bdrv_pread(bs->file, file_offset,
++ ret = bdrv_pread(bs->file, file_offset + trailing_length,
+ VHDX_LOG_SECTOR_SIZE - trailing_length,
+ merged_sector + trailing_length, 0);
+ if (ret < 0) {
+diff --git a/hw/arm/boot.c b/hw/arm/boot.c
+index 15c2bf1867..725bab8adc 100644
+--- a/hw/arm/boot.c
++++ b/hw/arm/boot.c
+@@ -686,7 +686,10 @@ int arm_load_dtb(hwaddr addr, const struct arm_boot_info *binfo,
+ qemu_register_reset_nosnapshotload(qemu_fdt_randomize_seeds,
+ rom_ptr_for_as(as, addr, size));
+
+- g_free(fdt);
++ if (fdt != ms->fdt) {
++ g_free(ms->fdt);
++ ms->fdt = fdt;
++ }
+
+ return size;
+
+diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c
+index d2ab527ef4..56559cda24 100644
+--- a/hw/net/vmxnet3.c
++++ b/hw/net/vmxnet3.c
+@@ -1441,7 +1441,7 @@ static void vmxnet3_activate_device(VMXNET3State *s)
+ vmxnet3_setup_rx_filtering(s);
+ /* Cache fields from shared memory */
+ s->mtu = VMXNET3_READ_DRV_SHARED32(d, s->drv_shmem, devRead.misc.mtu);
+- assert(VMXNET3_MIN_MTU <= s->mtu && s->mtu < VMXNET3_MAX_MTU);
++ assert(VMXNET3_MIN_MTU <= s->mtu && s->mtu <= VMXNET3_MAX_MTU);
+ VMW_CFPRN("MTU is %u", s->mtu);
+
+ s->max_rx_frags =
+diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c
+index 1d3e058452..749a6938dd 100644
+--- a/hw/nvme/ctrl.c
++++ b/hw/nvme/ctrl.c
+@@ -2491,6 +2491,9 @@ static uint16_t nvme_dsm(NvmeCtrl *n, NvmeRequest *req)
+ status = nvme_h2c(n, (uint8_t *)iocb->range, sizeof(NvmeDsmRange) * nr,
+ req);
+ if (status) {
++ g_free(iocb->range);
++ qemu_aio_unref(iocb);
++
+ return status;
+ }
+
+diff --git a/hw/rdma/vmw/pvrdma_cmd.c b/hw/rdma/vmw/pvrdma_cmd.c
+index da7ddfa548..89db963c46 100644
+--- a/hw/rdma/vmw/pvrdma_cmd.c
++++ b/hw/rdma/vmw/pvrdma_cmd.c
+@@ -796,6 +796,12 @@ int pvrdma_exec_cmd(PVRDMADev *dev)
+
+ dsr_info = &dev->dsr_info;
+
++ if (!dsr_info->dsr) {
++ /* Buggy or malicious guest driver */
++ rdma_error_report("Exec command without dsr, req or rsp buffers");
++ goto out;
++ }
++
+ if (dsr_info->req->hdr.cmd >= sizeof(cmd_handlers) /
+ sizeof(struct cmd_handler)) {
+ rdma_error_report("Unsupported command");
+diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h
+index b9c4307779..3d6cb431ad 100644
+--- a/include/qemu/osdep.h
++++ b/include/qemu/osdep.h
+@@ -177,7 +177,7 @@ extern "C" {
+ * supports QEMU_ERROR, this will be reported at compile time; otherwise
+ * this will be reported at link time due to the missing symbol.
+ */
+-extern G_NORETURN
++G_NORETURN extern
+ void QEMU_ERROR("code path is reachable")
+ qemu_build_not_reached_always(void);
+ #if defined(__OPTIMIZE__) && !defined(__NO_INLINE__)
+diff --git a/io/channel-tls.c b/io/channel-tls.c
+index 4ce890a538..4ce08ccc28 100644
+--- a/io/channel-tls.c
++++ b/io/channel-tls.c
+@@ -74,6 +74,9 @@ qio_channel_tls_new_server(QIOChannel *master,
+ ioc = QIO_CHANNEL_TLS(object_new(TYPE_QIO_CHANNEL_TLS));
+
+ ioc->master = master;
++ if (qio_channel_has_feature(master, QIO_CHANNEL_FEATURE_SHUTDOWN)) {
++ qio_channel_set_feature(QIO_CHANNEL(ioc), QIO_CHANNEL_FEATURE_SHUTDOWN);
++ }
+ object_ref(OBJECT(master));
+
+ ioc->session = qcrypto_tls_session_new(
+diff --git a/linux-user/fd-trans.c b/linux-user/fd-trans.c
+index 7b25468d02..146aaaafaa 100644
+--- a/linux-user/fd-trans.c
++++ b/linux-user/fd-trans.c
+@@ -1622,7 +1622,7 @@ TargetFdTrans target_signalfd_trans = {
+ .host_to_target_data = host_to_target_data_signalfd,
+ };
+
+-static abi_long swap_data_eventfd(void *buf, size_t len)
++static abi_long swap_data_u64(void *buf, size_t len)
+ {
+ uint64_t *counter = buf;
+ int i;
+@@ -1640,8 +1640,12 @@ static abi_long swap_data_eventfd(void *buf, size_t len)
+ }
+
+ TargetFdTrans target_eventfd_trans = {
+- .host_to_target_data = swap_data_eventfd,
+- .target_to_host_data = swap_data_eventfd,
++ .host_to_target_data = swap_data_u64,
++ .target_to_host_data = swap_data_u64,
++};
++
++TargetFdTrans target_timerfd_trans = {
++ .host_to_target_data = swap_data_u64,
+ };
+
+ #if defined(CONFIG_INOTIFY) && (defined(TARGET_NR_inotify_init) || \
+diff --git a/linux-user/fd-trans.h b/linux-user/fd-trans.h
+index 1b9fa2041c..910faaf237 100644
+--- a/linux-user/fd-trans.h
++++ b/linux-user/fd-trans.h
+@@ -130,6 +130,7 @@ extern TargetFdTrans target_netlink_route_trans;
+ extern TargetFdTrans target_netlink_audit_trans;
+ extern TargetFdTrans target_signalfd_trans;
+ extern TargetFdTrans target_eventfd_trans;
++extern TargetFdTrans target_timerfd_trans;
+ #if (defined(TARGET_NR_inotify_init) && defined(__NR_inotify_init)) || \
+ (defined(CONFIG_INOTIFY1) && defined(TARGET_NR_inotify_init1) && \
+ defined(__NR_inotify_init1))
+diff --git a/linux-user/generic/target_resource.h b/linux-user/generic/target_resource.h
+index 539d8c4677..37d3eb09b3 100644
+--- a/linux-user/generic/target_resource.h
++++ b/linux-user/generic/target_resource.h
+@@ -12,8 +12,8 @@ struct target_rlimit {
+ };
+
+ struct target_rlimit64 {
+- uint64_t rlim_cur;
+- uint64_t rlim_max;
++ abi_ullong rlim_cur;
++ abi_ullong rlim_max;
+ };
+
+ #define TARGET_RLIM_INFINITY ((abi_ulong)-1)
+diff --git a/linux-user/syscall.c b/linux-user/syscall.c
+index 24b25759be..9ca30149d4 100644
+--- a/linux-user/syscall.c
++++ b/linux-user/syscall.c
+@@ -1755,6 +1755,11 @@ static inline abi_long target_to_host_sockaddr(int fd, struct sockaddr *addr,
+ lladdr = (struct target_sockaddr_ll *)addr;
+ lladdr->sll_ifindex = tswap32(lladdr->sll_ifindex);
+ lladdr->sll_hatype = tswap16(lladdr->sll_hatype);
++ } else if (sa_family == AF_INET6) {
++ struct sockaddr_in6 *in6addr;
++
++ in6addr = (struct sockaddr_in6 *)addr;
++ in6addr->sin6_scope_id = tswap32(in6addr->sin6_scope_id);
+ }
+ unlock_user(target_saddr, target_addr, 0);
+
+@@ -12883,8 +12888,8 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
+ if (!lock_user_struct(VERIFY_READ, target_rnew, arg3, 1)) {
+ return -TARGET_EFAULT;
+ }
+- rnew.rlim_cur = tswap64(target_rnew->rlim_cur);
+- rnew.rlim_max = tswap64(target_rnew->rlim_max);
++ __get_user(rnew.rlim_cur, &target_rnew->rlim_cur);
++ __get_user(rnew.rlim_max, &target_rnew->rlim_max);
+ unlock_user_struct(target_rnew, arg3, 0);
+ rnewp = &rnew;
+ }
+@@ -12894,8 +12899,8 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
+ if (!lock_user_struct(VERIFY_WRITE, target_rold, arg4, 1)) {
+ return -TARGET_EFAULT;
+ }
+- target_rold->rlim_cur = tswap64(rold.rlim_cur);
+- target_rold->rlim_max = tswap64(rold.rlim_max);
++ __put_user(rold.rlim_cur, &target_rold->rlim_cur);
++ __put_user(rold.rlim_max, &target_rold->rlim_max);
+ unlock_user_struct(target_rold, arg4, 1);
+ }
+ return ret;
+@@ -13115,8 +13120,12 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
+
+ #if defined(TARGET_NR_timerfd_create) && defined(CONFIG_TIMERFD)
+ case TARGET_NR_timerfd_create:
+- return get_errno(timerfd_create(arg1,
+- target_to_host_bitmask(arg2, fcntl_flags_tbl)));
++ ret = get_errno(timerfd_create(arg1,
++ target_to_host_bitmask(arg2, fcntl_flags_tbl)));
++ if (ret >= 0) {
++ fd_trans_register(ret, &target_timerfd_trans);
++ }
++ return ret;
+ #endif
+
+ #if defined(TARGET_NR_timerfd_gettime) && defined(CONFIG_TIMERFD)
+diff --git a/qga/commands.c b/qga/commands.c
+index 7ff551d092..6cf978322e 100644
+--- a/qga/commands.c
++++ b/qga/commands.c
+@@ -32,9 +32,8 @@
+ #define GUEST_FILE_READ_COUNT_MAX (48 * MiB)
+
+ /* Note: in some situations, like with the fsfreeze, logging may be
+- * temporarilly disabled. if it is necessary that a command be able
+- * to log for accounting purposes, check ga_logging_enabled() beforehand,
+- * and use the QERR_QGA_LOGGING_DISABLED to generate an error
++ * temporarily disabled. if it is necessary that a command be able
++ * to log for accounting purposes, check ga_logging_enabled() beforehand.
+ */
+ void slog(const gchar *fmt, ...)
+ {
+diff --git a/qga/installer/qemu-ga.wxs b/qga/installer/qemu-ga.wxs
+index 813d1c6ca6..3442383627 100644
+--- a/qga/installer/qemu-ga.wxs
++++ b/qga/installer/qemu-ga.wxs
+@@ -31,6 +31,7 @@
+ />
+ <Media Id="1" Cabinet="qemu_ga.$(var.QEMU_GA_VERSION).cab" EmbedCab="yes" />
+ <Property Id="WHSLogo">1</Property>
++ <Property Id="ARPNOMODIFY" Value="yes" Secure="yes" />
+ <MajorUpgrade
+ DowngradeErrorMessage="Error: A newer version of QEMU guest agent is already installed."
+ />
+diff --git a/qga/vss-win32/install.cpp b/qga/vss-win32/install.cpp
+index b57508fbe0..b8087e5baa 100644
+--- a/qga/vss-win32/install.cpp
++++ b/qga/vss-win32/install.cpp
+@@ -518,7 +518,7 @@ namespace _com_util
+ /* Stop QGA VSS provider service using Winsvc API */
+ STDAPI StopService(void)
+ {
+- HRESULT hr;
++ HRESULT hr = S_OK;
+ SC_HANDLE manager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
+ SC_HANDLE service = NULL;
+
+diff --git a/target/arm/cpu.h b/target/arm/cpu.h
+index 9aeed3c848..a9cd7178f8 100644
+--- a/target/arm/cpu.h
++++ b/target/arm/cpu.h
+@@ -2407,6 +2407,9 @@ static inline bool arm_is_el3_or_mon(CPUARMState *env)
+ /* Return true if the processor is in secure state */
+ static inline bool arm_is_secure(CPUARMState *env)
+ {
++ if (arm_feature(env, ARM_FEATURE_M)) {
++ return env->v7m.secure;
++ }
+ if (arm_is_el3_or_mon(env)) {
+ return true;
+ }
+diff --git a/target/s390x/arch_dump.c b/target/s390x/arch_dump.c
+index a2329141e8..a7c44ba49d 100644
+--- a/target/s390x/arch_dump.c
++++ b/target/s390x/arch_dump.c
+@@ -248,7 +248,7 @@ static int s390x_write_elf64_notes(const char *note_name,
+ notep = g_malloc(note_size);
+ }
+
+- memset(notep, 0, sizeof(note));
++ memset(notep, 0, note_size);
+
+ /* Setup note header data */
+ notep->hdr.n_descsz = cpu_to_be32(content_size);
+diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h
+index 7d6d01325b..8aaf8dd5a3 100644
+--- a/target/s390x/cpu.h
++++ b/target/s390x/cpu.h
+@@ -87,6 +87,7 @@ struct CPUArchState {
+ uint64_t cc_vr;
+
+ uint64_t ex_value;
++ uint64_t ex_target;
+
+ uint64_t __excp_addr;
+ uint64_t psa;
+diff --git a/target/s390x/s390x-internal.h b/target/s390x/s390x-internal.h
+index 5d4361d35b..825252d728 100644
+--- a/target/s390x/s390x-internal.h
++++ b/target/s390x/s390x-internal.h
+@@ -11,6 +11,7 @@
+ #define S390X_INTERNAL_H
+
+ #include "cpu.h"
++#include "fpu/softfloat.h"
+
+ #ifndef CONFIG_USER_ONLY
+ typedef struct LowCore {
+@@ -299,7 +300,7 @@ uint32_t set_cc_nz_f128(float128 v);
+ uint8_t s390_softfloat_exc_to_ieee(unsigned int exc);
+ int s390_swap_bfp_rounding_mode(CPUS390XState *env, int m3);
+ void s390_restore_bfp_rounding_mode(CPUS390XState *env, int old_mode);
+-int float_comp_to_cc(CPUS390XState *env, int float_compare);
++int float_comp_to_cc(CPUS390XState *env, FloatRelation float_compare);
+
+ #define DCMASK_ZERO 0x0c00
+ #define DCMASK_NORMAL 0x0300
+diff --git a/target/s390x/tcg/insn-data.h.inc b/target/s390x/tcg/insn-data.h.inc
+index 54d4250c9f..2a5fc99818 100644
+--- a/target/s390x/tcg/insn-data.h.inc
++++ b/target/s390x/tcg/insn-data.h.inc
+@@ -199,8 +199,8 @@
+ C(0xe55c, CHSI, SIL, GIE, m1_32s, i2, 0, 0, 0, cmps64)
+ C(0xe558, CGHSI, SIL, GIE, m1_64, i2, 0, 0, 0, cmps64)
+ /* COMPARE HALFWORD RELATIVE LONG */
+- C(0xc605, CHRL, RIL_b, GIE, r1_o, mri2_32s, 0, 0, 0, cmps32)
+- C(0xc604, CGHRL, RIL_b, GIE, r1_o, mri2_64, 0, 0, 0, cmps64)
++ C(0xc605, CHRL, RIL_b, GIE, r1_o, mri2_16s, 0, 0, 0, cmps32)
++ C(0xc604, CGHRL, RIL_b, GIE, r1_o, mri2_16s, 0, 0, 0, cmps64)
+ /* COMPARE HIGH */
+ C(0xb9cd, CHHR, RRE, HW, r1_sr32, r2_sr32, 0, 0, 0, cmps32)
+ C(0xb9dd, CHLR, RRE, HW, r1_sr32, r2_o, 0, 0, 0, cmps32)
+diff --git a/target/s390x/tcg/mem_helper.c b/target/s390x/tcg/mem_helper.c
+index 3758b9e688..7e7de5e2f1 100644
+--- a/target/s390x/tcg/mem_helper.c
++++ b/target/s390x/tcg/mem_helper.c
+@@ -2618,6 +2618,7 @@ void HELPER(ex)(CPUS390XState *env, uint32_t ilen, uint64_t r1, uint64_t addr)
+ that ex_value is non-zero, which flags that we are in a state
+ that requires such execution. */
+ env->ex_value = insn | ilen;
++ env->ex_target = addr;
+ }
+
+ uint32_t HELPER(mvcos)(CPUS390XState *env, uint64_t dest, uint64_t src,
+diff --git a/target/s390x/tcg/translate.c b/target/s390x/tcg/translate.c
+index 1e599ac259..e328aa5b97 100644
+--- a/target/s390x/tcg/translate.c
++++ b/target/s390x/tcg/translate.c
+@@ -5962,9 +5962,25 @@ static void in2_a2(DisasContext *s, DisasOps *o)
+ }
+ #define SPEC_in2_a2 0
+
++static TCGv gen_ri2(DisasContext *s)
++{
++ int64_t delta = (int64_t)get_field(s, i2) * 2;
++ TCGv ri2;
++
++ if (unlikely(s->ex_value)) {
++ ri2 = tcg_temp_new_i64();
++ tcg_gen_ld_i64(ri2, cpu_env, offsetof(CPUS390XState, ex_target));
++ tcg_gen_addi_i64(ri2, ri2, delta);
++ } else {
++ ri2 = tcg_constant_i64(s->base.pc_next + delta);
++ }
++
++ return ri2;
++}
++
+ static void in2_ri2(DisasContext *s, DisasOps *o)
+ {
+- o->in2 = tcg_const_i64(s->base.pc_next + (int64_t)get_field(s, i2) * 2);
++ o->in2 = gen_ri2(s);
+ }
+ #define SPEC_in2_ri2 0
+
+@@ -6050,31 +6066,38 @@ static void in2_m2_64a(DisasContext *s, DisasOps *o)
+ #define SPEC_in2_m2_64a 0
+ #endif
+
++static void in2_mri2_16s(DisasContext *s, DisasOps *o)
++{
++ o->in2 = tcg_temp_new_i64();
++ tcg_gen_qemu_ld16s(o->in2, gen_ri2(s), get_mem_index(s));
++}
++#define SPEC_in2_mri2_16s 0
++
+ static void in2_mri2_16u(DisasContext *s, DisasOps *o)
+ {
+- in2_ri2(s, o);
+- tcg_gen_qemu_ld16u(o->in2, o->in2, get_mem_index(s));
++ o->in2 = tcg_temp_new_i64();
++ tcg_gen_qemu_ld16u(o->in2, gen_ri2(s), get_mem_index(s));
+ }
+ #define SPEC_in2_mri2_16u 0
+
+ static void in2_mri2_32s(DisasContext *s, DisasOps *o)
+ {
+- in2_ri2(s, o);
+- tcg_gen_qemu_ld32s(o->in2, o->in2, get_mem_index(s));
++ o->in2 = tcg_temp_new_i64();
++ tcg_gen_qemu_ld32s(o->in2, gen_ri2(s), get_mem_index(s));
+ }
+ #define SPEC_in2_mri2_32s 0
+
+ static void in2_mri2_32u(DisasContext *s, DisasOps *o)
+ {
+- in2_ri2(s, o);
+- tcg_gen_qemu_ld32u(o->in2, o->in2, get_mem_index(s));
++ o->in2 = tcg_temp_new_i64();
++ tcg_gen_qemu_ld32u(o->in2, gen_ri2(s), get_mem_index(s));
+ }
+ #define SPEC_in2_mri2_32u 0
+
+ static void in2_mri2_64(DisasContext *s, DisasOps *o)
+ {
+- in2_ri2(s, o);
+- tcg_gen_qemu_ld64(o->in2, o->in2, get_mem_index(s));
++ o->in2 = tcg_temp_new_i64();
++ tcg_gen_qemu_ld64(o->in2, gen_ri2(s), get_mem_index(s));
+ }
+ #define SPEC_in2_mri2_64 0
+
+diff --git a/ui/gtk.c b/ui/gtk.c
+index 4817623c8f..dfaf6d33c3 100644
+--- a/ui/gtk.c
++++ b/ui/gtk.c
+@@ -1783,7 +1783,9 @@ static void gd_vc_chr_accept_input(Chardev *chr)
+ VCChardev *vcd = VC_CHARDEV(chr);
+ VirtualConsole *vc = vcd->console;
+
+- gd_vc_send_chars(vc);
++ if (vc) {
++ gd_vc_send_chars(vc);
++ }
+ }
+
+ static void gd_vc_chr_set_echo(Chardev *chr, bool echo)
+diff --git a/util/fdmon-epoll.c b/util/fdmon-epoll.c
+index e11a8a022e..1683aa1105 100644
+--- a/util/fdmon-epoll.c
++++ b/util/fdmon-epoll.c
+@@ -127,6 +127,8 @@ static bool fdmon_epoll_try_enable(AioContext *ctx)
+
+ bool fdmon_epoll_try_upgrade(AioContext *ctx, unsigned npfd)
+ {
++ bool ok;
++
+ if (ctx->epollfd < 0) {
+ return false;
+ }
+@@ -136,14 +138,23 @@ bool fdmon_epoll_try_upgrade(AioContext *ctx, unsigned npfd)
+ return false;
+ }
+
+- if (npfd >= EPOLL_ENABLE_THRESHOLD) {
+- if (fdmon_epoll_try_enable(ctx)) {
+- return true;
+- } else {
+- fdmon_epoll_disable(ctx);
+- }
++ if (npfd < EPOLL_ENABLE_THRESHOLD) {
++ return false;
++ }
++
++ /* The list must not change while we add fds to epoll */
++ if (!qemu_lockcnt_dec_if_lock(&ctx->list_lock)) {
++ return false;
++ }
++
++ ok = fdmon_epoll_try_enable(ctx);
++
++ qemu_lockcnt_inc_and_unlock(&ctx->list_lock);
++
++ if (!ok) {
++ fdmon_epoll_disable(ctx);
+ }
+- return false;
++ return ok;
+ }
+
+ void fdmon_epoll_setup(AioContext *ctx)
diff --git a/debian/patches/v7.2.3.diff b/debian/patches/v7.2.3.diff
new file mode 100644
index 00000000..d6d3da44
--- /dev/null
+++ b/debian/patches/v7.2.3.diff
@@ -0,0 +1,2258 @@
+diff --git a/VERSION b/VERSION
+index 77f5bec5b2..429dc57af3 100644
+--- a/VERSION
++++ b/VERSION
+@@ -1 +1 @@
+-7.2.2
++7.2.3
+diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
+index 6f1c00682b..1160aec626 100644
+--- a/accel/tcg/cputlb.c
++++ b/accel/tcg/cputlb.c
+@@ -1817,7 +1817,7 @@ static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
+ } else /* if (prot & PAGE_READ) */ {
+ tlb_addr = tlbe->addr_read;
+ if (!tlb_hit(tlb_addr, addr)) {
+- if (!VICTIM_TLB_HIT(addr_write, addr)) {
++ if (!VICTIM_TLB_HIT(addr_read, addr)) {
+ tlb_fill(env_cpu(env), addr, size,
+ MMU_DATA_LOAD, mmu_idx, retaddr);
+ index = tlb_index(env, mmu_idx, addr);
+diff --git a/block/monitor/block-hmp-cmds.c b/block/monitor/block-hmp-cmds.c
+index b6135e9bfe..cf21b5e40a 100644
+--- a/block/monitor/block-hmp-cmds.c
++++ b/block/monitor/block-hmp-cmds.c
+@@ -213,15 +213,17 @@ void hmp_commit(Monitor *mon, const QDict *qdict)
+ error_report("Device '%s' not found", device);
+ return;
+ }
+- if (!blk_is_available(blk)) {
+- error_report("Device '%s' has no medium", device);
+- return;
+- }
+
+ bs = bdrv_skip_implicit_filters(blk_bs(blk));
+ aio_context = bdrv_get_aio_context(bs);
+ aio_context_acquire(aio_context);
+
++ if (!blk_is_available(blk)) {
++ error_report("Device '%s' has no medium", device);
++ aio_context_release(aio_context);
++ return;
++ }
++
+ ret = bdrv_commit(bs);
+
+ aio_context_release(aio_context);
+diff --git a/blockdev.c b/blockdev.c
+index 3f1dec6242..ae27a41efa 100644
+--- a/blockdev.c
++++ b/blockdev.c
+@@ -152,12 +152,22 @@ void blockdev_mark_auto_del(BlockBackend *blk)
+
+ JOB_LOCK_GUARD();
+
+- for (job = block_job_next_locked(NULL); job;
+- job = block_job_next_locked(job)) {
+- if (block_job_has_bdrv(job, blk_bs(blk))) {
++ do {
++ job = block_job_next_locked(NULL);
++ while (job && (job->job.cancelled ||
++ job->job.deferred_to_main_loop ||
++ !block_job_has_bdrv(job, blk_bs(blk))))
++ {
++ job = block_job_next_locked(job);
++ }
++ if (job) {
++ /*
++ * This drops the job lock temporarily and polls, so we need to
++ * restart processing the list from the start after this.
++ */
+ job_cancel_locked(&job->job, false);
+ }
+- }
++ } while (job);
+
+ dinfo->auto_del = 1;
+ }
+diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst
+index 93affe3669..0b26c01da0 100644
+--- a/docs/about/deprecated.rst
++++ b/docs/about/deprecated.rst
+@@ -233,8 +233,8 @@ Use the more generic event ``DEVICE_UNPLUG_GUEST_ERROR`` instead.
+ System emulator machines
+ ------------------------
+
+-Arm ``virt`` machine ``dtb-kaslr-seed`` property
+-''''''''''''''''''''''''''''''''''''''''''''''''
++Arm ``virt`` machine ``dtb-kaslr-seed`` property (since 7.1)
++''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
+
+ The ``dtb-kaslr-seed`` property on the ``virt`` board has been
+ deprecated; use the new name ``dtb-randomness`` instead. The new name
+diff --git a/fpu/softfloat.c b/fpu/softfloat.c
+index c7454c3eb1..108f9cb224 100644
+--- a/fpu/softfloat.c
++++ b/fpu/softfloat.c
+@@ -5135,7 +5135,7 @@ float32 float32_exp2(float32 a, float_status *status)
+ float64_unpack_canonical(&rp, float64_one, status);
+ for (i = 0 ; i < 15 ; i++) {
+ float64_unpack_canonical(&tp, float32_exp2_coefficients[i], status);
+- rp = *parts_muladd(&tp, &xp, &rp, 0, status);
++ rp = *parts_muladd(&tp, &xnp, &rp, 0, status);
+ xnp = *parts_mul(&xnp, &xp, status);
+ }
+
+diff --git a/hw/9pfs/trace-events b/hw/9pfs/trace-events
+index 6c77966c0b..a12e55c165 100644
+--- a/hw/9pfs/trace-events
++++ b/hw/9pfs/trace-events
+@@ -48,3 +48,9 @@ v9fs_readlink(uint16_t tag, uint8_t id, int32_t fid) "tag %d id %d fid %d"
+ v9fs_readlink_return(uint16_t tag, uint8_t id, char* target) "tag %d id %d name %s"
+ v9fs_setattr(uint16_t tag, uint8_t id, int32_t fid, int32_t valid, int32_t mode, int32_t uid, int32_t gid, int64_t size, int64_t atime_sec, int64_t mtime_sec) "tag %u id %u fid %d iattr={valid %d mode %d uid %d gid %d size %"PRId64" atime=%"PRId64" mtime=%"PRId64" }"
+ v9fs_setattr_return(uint16_t tag, uint8_t id) "tag %u id %u"
++
++# xen-9p-backend.c
++xen_9pfs_alloc(char *name) "name %s"
++xen_9pfs_connect(char *name) "name %s"
++xen_9pfs_disconnect(char *name) "name %s"
++xen_9pfs_free(char *name) "name %s"
+diff --git a/hw/9pfs/xen-9p-backend.c b/hw/9pfs/xen-9p-backend.c
+index 65c4979c3c..ab1df8dd2f 100644
+--- a/hw/9pfs/xen-9p-backend.c
++++ b/hw/9pfs/xen-9p-backend.c
+@@ -24,6 +24,8 @@
+ #include "qemu/option.h"
+ #include "fsdev/qemu-fsdev.h"
+
++#include "trace.h"
++
+ #define VERSIONS "1"
+ #define MAX_RINGS 8
+ #define MAX_RING_ORDER 9
+@@ -335,6 +337,8 @@ static void xen_9pfs_disconnect(struct XenLegacyDevice *xendev)
+ Xen9pfsDev *xen_9pdev = container_of(xendev, Xen9pfsDev, xendev);
+ int i;
+
++ trace_xen_9pfs_disconnect(xendev->name);
++
+ for (i = 0; i < xen_9pdev->num_rings; i++) {
+ if (xen_9pdev->rings[i].evtchndev != NULL) {
+ qemu_set_fd_handler(xenevtchn_fd(xen_9pdev->rings[i].evtchndev),
+@@ -343,39 +347,40 @@ static void xen_9pfs_disconnect(struct XenLegacyDevice *xendev)
+ xen_9pdev->rings[i].local_port);
+ xen_9pdev->rings[i].evtchndev = NULL;
+ }
+- }
+-}
+-
+-static int xen_9pfs_free(struct XenLegacyDevice *xendev)
+-{
+- Xen9pfsDev *xen_9pdev = container_of(xendev, Xen9pfsDev, xendev);
+- int i;
+-
+- if (xen_9pdev->rings[0].evtchndev != NULL) {
+- xen_9pfs_disconnect(xendev);
+- }
+-
+- for (i = 0; i < xen_9pdev->num_rings; i++) {
+ if (xen_9pdev->rings[i].data != NULL) {
+ xen_be_unmap_grant_refs(&xen_9pdev->xendev,
+ xen_9pdev->rings[i].data,
+ (1 << xen_9pdev->rings[i].ring_order));
++ xen_9pdev->rings[i].data = NULL;
+ }
+ if (xen_9pdev->rings[i].intf != NULL) {
+ xen_be_unmap_grant_refs(&xen_9pdev->xendev,
+ xen_9pdev->rings[i].intf,
+ 1);
++ xen_9pdev->rings[i].intf = NULL;
+ }
+ if (xen_9pdev->rings[i].bh != NULL) {
+ qemu_bh_delete(xen_9pdev->rings[i].bh);
++ xen_9pdev->rings[i].bh = NULL;
+ }
+ }
+
+ g_free(xen_9pdev->id);
++ xen_9pdev->id = NULL;
+ g_free(xen_9pdev->tag);
++ xen_9pdev->tag = NULL;
+ g_free(xen_9pdev->path);
++ xen_9pdev->path = NULL;
+ g_free(xen_9pdev->security_model);
++ xen_9pdev->security_model = NULL;
+ g_free(xen_9pdev->rings);
++ xen_9pdev->rings = NULL;
++}
++
++static int xen_9pfs_free(struct XenLegacyDevice *xendev)
++{
++ trace_xen_9pfs_free(xendev->name);
++
+ return 0;
+ }
+
+@@ -387,6 +392,8 @@ static int xen_9pfs_connect(struct XenLegacyDevice *xendev)
+ V9fsState *s = &xen_9pdev->state;
+ QemuOpts *fsdev;
+
++ trace_xen_9pfs_connect(xendev->name);
++
+ if (xenstore_read_fe_int(&xen_9pdev->xendev, "num-rings",
+ &xen_9pdev->num_rings) == -1 ||
+ xen_9pdev->num_rings > MAX_RINGS || xen_9pdev->num_rings < 1) {
+@@ -494,6 +501,8 @@ out:
+
+ static void xen_9pfs_alloc(struct XenLegacyDevice *xendev)
+ {
++ trace_xen_9pfs_alloc(xendev->name);
++
+ xenstore_write_be_str(xendev, "versions", VERSIONS);
+ xenstore_write_be_int(xendev, "max-rings", MAX_RINGS);
+ xenstore_write_be_int(xendev, "max-ring-page-order", MAX_RING_ORDER);
+diff --git a/hw/acpi/pcihp.c b/hw/acpi/pcihp.c
+index 84d75e6b84..a2a3738b46 100644
+--- a/hw/acpi/pcihp.c
++++ b/hw/acpi/pcihp.c
+@@ -429,6 +429,16 @@ void acpi_pcihp_device_unplug_request_cb(HotplugHandler *hotplug_dev,
+ * acpi_pcihp_eject_slot() when the operation is completed.
+ */
+ pdev->qdev.pending_deleted_event = true;
++ /* if unplug was requested before OSPM is initialized,
++ * linux kernel will clear GPE0.sts[] bits during boot, which effectively
++ * hides unplug event. And than followup qmp_device_del() calls remain
++ * blocked by above flag permanently.
++ * Unblock qmp_device_del() by setting expire limit, so user can
++ * repeat unplug request later when OSPM has been booted.
++ */
++ pdev->qdev.pending_deleted_expires_ms =
++ qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL); /* 1 msec */
++
+ s->acpi_pcihp_pci_status[bsel].down |= (1U << slot);
+ acpi_send_event(DEVICE(hotplug_dev), ACPI_PCI_HOTPLUG_STATUS);
+ }
+diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
+index 55f114ef72..97fb1916ec 100644
+--- a/hw/arm/aspeed.c
++++ b/hw/arm/aspeed.c
+@@ -188,33 +188,35 @@ struct AspeedMachineState {
+ static void aspeed_write_smpboot(ARMCPU *cpu,
+ const struct arm_boot_info *info)
+ {
+- static const uint32_t poll_mailbox_ready[] = {
++ AddressSpace *as = arm_boot_address_space(cpu, info);
++ static const ARMInsnFixup poll_mailbox_ready[] = {
+ /*
+ * r2 = per-cpu go sign value
+ * r1 = AST_SMP_MBOX_FIELD_ENTRY
+ * r0 = AST_SMP_MBOX_FIELD_GOSIGN
+ */
+- 0xee100fb0, /* mrc p15, 0, r0, c0, c0, 5 */
+- 0xe21000ff, /* ands r0, r0, #255 */
+- 0xe59f201c, /* ldr r2, [pc, #28] */
+- 0xe1822000, /* orr r2, r2, r0 */
+-
+- 0xe59f1018, /* ldr r1, [pc, #24] */
+- 0xe59f0018, /* ldr r0, [pc, #24] */
+-
+- 0xe320f002, /* wfe */
+- 0xe5904000, /* ldr r4, [r0] */
+- 0xe1520004, /* cmp r2, r4 */
+- 0x1afffffb, /* bne <wfe> */
+- 0xe591f000, /* ldr pc, [r1] */
+- AST_SMP_MBOX_GOSIGN,
+- AST_SMP_MBOX_FIELD_ENTRY,
+- AST_SMP_MBOX_FIELD_GOSIGN,
++ { 0xee100fb0 }, /* mrc p15, 0, r0, c0, c0, 5 */
++ { 0xe21000ff }, /* ands r0, r0, #255 */
++ { 0xe59f201c }, /* ldr r2, [pc, #28] */
++ { 0xe1822000 }, /* orr r2, r2, r0 */
++
++ { 0xe59f1018 }, /* ldr r1, [pc, #24] */
++ { 0xe59f0018 }, /* ldr r0, [pc, #24] */
++
++ { 0xe320f002 }, /* wfe */
++ { 0xe5904000 }, /* ldr r4, [r0] */
++ { 0xe1520004 }, /* cmp r2, r4 */
++ { 0x1afffffb }, /* bne <wfe> */
++ { 0xe591f000 }, /* ldr pc, [r1] */
++ { AST_SMP_MBOX_GOSIGN },
++ { AST_SMP_MBOX_FIELD_ENTRY },
++ { AST_SMP_MBOX_FIELD_GOSIGN },
++ { 0, FIXUP_TERMINATOR }
+ };
++ static const uint32_t fixupcontext[FIXUP_MAX] = { 0 };
+
+- rom_add_blob_fixed("aspeed.smpboot", poll_mailbox_ready,
+- sizeof(poll_mailbox_ready),
+- info->smp_loader_start);
++ arm_write_bootloader("aspeed.smpboot", as, info->smp_loader_start,
++ poll_mailbox_ready, fixupcontext);
+ }
+
+ static void aspeed_reset_secondary(ARMCPU *cpu,
+diff --git a/hw/arm/boot.c b/hw/arm/boot.c
+index 725bab8adc..8ff315f431 100644
+--- a/hw/arm/boot.c
++++ b/hw/arm/boot.c
+@@ -59,26 +59,6 @@ AddressSpace *arm_boot_address_space(ARMCPU *cpu,
+ return cpu_get_address_space(cs, asidx);
+ }
+
+-typedef enum {
+- FIXUP_NONE = 0, /* do nothing */
+- FIXUP_TERMINATOR, /* end of insns */
+- FIXUP_BOARDID, /* overwrite with board ID number */
+- FIXUP_BOARD_SETUP, /* overwrite with board specific setup code address */
+- FIXUP_ARGPTR_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 */
+- FIXUP_MAX,
+-} FixupType;
+-
+-typedef struct ARMInsnFixup {
+- uint32_t insn;
+- FixupType fixup;
+-} ARMInsnFixup;
+-
+ static const ARMInsnFixup bootloader_aarch64[] = {
+ { 0x580000c0 }, /* ldr x0, arg ; Load the lower 32-bits of DTB */
+ { 0xaa1f03e1 }, /* mov x1, xzr */
+@@ -149,9 +129,10 @@ static const ARMInsnFixup smpboot[] = {
+ { 0, FIXUP_TERMINATOR }
+ };
+
+-static void write_bootloader(const char *name, hwaddr addr,
+- const ARMInsnFixup *insns, uint32_t *fixupcontext,
+- AddressSpace *as)
++void arm_write_bootloader(const char *name,
++ AddressSpace *as, hwaddr addr,
++ const ARMInsnFixup *insns,
++ const uint32_t *fixupcontext)
+ {
+ /* Fix up the specified bootloader fragment and write it into
+ * guest memory using rom_add_blob_fixed(). fixupcontext is
+@@ -213,8 +194,8 @@ static void default_write_secondary(ARMCPU *cpu,
+ fixupcontext[FIXUP_DSB] = CP15_DSB_INSN;
+ }
+
+- write_bootloader("smpboot", info->smp_loader_start,
+- smpboot, fixupcontext, as);
++ arm_write_bootloader("smpboot", as, info->smp_loader_start,
++ smpboot, fixupcontext);
+ }
+
+ void arm_write_secure_board_setup_dummy_smc(ARMCPU *cpu,
+@@ -1174,8 +1155,8 @@ static void arm_setup_direct_kernel_boot(ARMCPU *cpu,
+ fixupcontext[FIXUP_ENTRYPOINT_LO] = entry;
+ fixupcontext[FIXUP_ENTRYPOINT_HI] = entry >> 32;
+
+- write_bootloader("bootloader", info->loader_start,
+- primary_loader, fixupcontext, as);
++ arm_write_bootloader("bootloader", as, info->loader_start,
++ primary_loader, fixupcontext);
+
+ if (info->write_board_setup) {
+ info->write_board_setup(cpu, info);
+diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
+index 92d068d1f9..a7d287b1a8 100644
+--- a/hw/arm/raspi.c
++++ b/hw/arm/raspi.c
+@@ -16,6 +16,7 @@
+ #include "qemu/units.h"
+ #include "qemu/cutils.h"
+ #include "qapi/error.h"
++#include "hw/arm/boot.h"
+ #include "hw/arm/bcm2836.h"
+ #include "hw/registerfields.h"
+ #include "qemu/error-report.h"
+@@ -124,20 +125,22 @@ static const char *board_type(uint32_t board_rev)
+
+ static void write_smpboot(ARMCPU *cpu, const struct arm_boot_info *info)
+ {
+- static const uint32_t smpboot[] = {
+- 0xe1a0e00f, /* mov lr, pc */
+- 0xe3a0fe00 + (BOARDSETUP_ADDR >> 4), /* mov pc, BOARDSETUP_ADDR */
+- 0xee100fb0, /* mrc p15, 0, r0, c0, c0, 5;get core ID */
+- 0xe7e10050, /* ubfx r0, r0, #0, #2 ;extract LSB */
+- 0xe59f5014, /* ldr r5, =0x400000CC ;load mbox base */
+- 0xe320f001, /* 1: yield */
+- 0xe7953200, /* ldr r3, [r5, r0, lsl #4] ;read mbox for our core*/
+- 0xe3530000, /* cmp r3, #0 ;spin while zero */
+- 0x0afffffb, /* beq 1b */
+- 0xe7853200, /* str r3, [r5, r0, lsl #4] ;clear mbox */
+- 0xe12fff13, /* bx r3 ;jump to target */
+- 0x400000cc, /* (constant: mailbox 3 read/clear base) */
++ static const ARMInsnFixup smpboot[] = {
++ { 0xe1a0e00f }, /* mov lr, pc */
++ { 0xe3a0fe00 + (BOARDSETUP_ADDR >> 4) }, /* mov pc, BOARDSETUP_ADDR */
++ { 0xee100fb0 }, /* mrc p15, 0, r0, c0, c0, 5;get core ID */
++ { 0xe7e10050 }, /* ubfx r0, r0, #0, #2 ;extract LSB */
++ { 0xe59f5014 }, /* ldr r5, =0x400000CC ;load mbox base */
++ { 0xe320f001 }, /* 1: yield */
++ { 0xe7953200 }, /* ldr r3, [r5, r0, lsl #4] ;read mbox for our core */
++ { 0xe3530000 }, /* cmp r3, #0 ;spin while zero */
++ { 0x0afffffb }, /* beq 1b */
++ { 0xe7853200 }, /* str r3, [r5, r0, lsl #4] ;clear mbox */
++ { 0xe12fff13 }, /* bx r3 ;jump to target */
++ { 0x400000cc }, /* (constant: mailbox 3 read/clear base) */
++ { 0, FIXUP_TERMINATOR }
+ };
++ static const uint32_t fixupcontext[FIXUP_MAX] = { 0 };
+
+ /* check that we don't overrun board setup vectors */
+ QEMU_BUILD_BUG_ON(SMPBOOT_ADDR + sizeof(smpboot) > MVBAR_ADDR);
+@@ -145,9 +148,8 @@ static void write_smpboot(ARMCPU *cpu, const struct arm_boot_info *info)
+ QEMU_BUILD_BUG_ON((BOARDSETUP_ADDR & 0xf) != 0
+ || (BOARDSETUP_ADDR >> 4) >= 0x100);
+
+- rom_add_blob_fixed_as("raspi_smpboot", smpboot, sizeof(smpboot),
+- info->smp_loader_start,
+- arm_boot_address_space(cpu, info));
++ arm_write_bootloader("raspi_smpboot", arm_boot_address_space(cpu, info),
++ info->smp_loader_start, smpboot, fixupcontext);
+ }
+
+ static void write_smpboot64(ARMCPU *cpu, const struct arm_boot_info *info)
+@@ -161,26 +163,28 @@ static void write_smpboot64(ARMCPU *cpu, const struct arm_boot_info *info)
+ * the primary CPU goes into the kernel. We put these variables inside
+ * a rom blob, so that the reset for ROM contents zeroes them for us.
+ */
+- static const uint32_t smpboot[] = {
+- 0xd2801b05, /* mov x5, 0xd8 */
+- 0xd53800a6, /* mrs x6, mpidr_el1 */
+- 0x924004c6, /* and x6, x6, #0x3 */
+- 0xd503205f, /* spin: wfe */
+- 0xf86678a4, /* ldr x4, [x5,x6,lsl #3] */
+- 0xb4ffffc4, /* cbz x4, spin */
+- 0xd2800000, /* mov x0, #0x0 */
+- 0xd2800001, /* mov x1, #0x0 */
+- 0xd2800002, /* mov x2, #0x0 */
+- 0xd2800003, /* mov x3, #0x0 */
+- 0xd61f0080, /* br x4 */
++ static const ARMInsnFixup smpboot[] = {
++ { 0xd2801b05 }, /* mov x5, 0xd8 */
++ { 0xd53800a6 }, /* mrs x6, mpidr_el1 */
++ { 0x924004c6 }, /* and x6, x6, #0x3 */
++ { 0xd503205f }, /* spin: wfe */
++ { 0xf86678a4 }, /* ldr x4, [x5,x6,lsl #3] */
++ { 0xb4ffffc4 }, /* cbz x4, spin */
++ { 0xd2800000 }, /* mov x0, #0x0 */
++ { 0xd2800001 }, /* mov x1, #0x0 */
++ { 0xd2800002 }, /* mov x2, #0x0 */
++ { 0xd2800003 }, /* mov x3, #0x0 */
++ { 0xd61f0080 }, /* br x4 */
++ { 0, FIXUP_TERMINATOR }
+ };
++ static const uint32_t fixupcontext[FIXUP_MAX] = { 0 };
+
+ static const uint64_t spintables[] = {
+ 0, 0, 0, 0
+ };
+
+- rom_add_blob_fixed_as("raspi_smpboot", smpboot, sizeof(smpboot),
+- info->smp_loader_start, as);
++ arm_write_bootloader("raspi_smpboot", as, info->smp_loader_start,
++ smpboot, fixupcontext);
+ rom_add_blob_fixed_as("raspi_spintables", spintables, sizeof(spintables),
+ SPINTABLE_ADDR, as);
+ }
+diff --git a/hw/core/machine.c b/hw/core/machine.c
+index 035d078a74..19f42450f5 100644
+--- a/hw/core/machine.c
++++ b/hw/core/machine.c
+@@ -1329,6 +1329,14 @@ void machine_run_board_init(MachineState *machine, const char *mem_path, Error *
+ }
+ } else if (machine_class->default_ram_id && machine->ram_size &&
+ numa_uses_legacy_mem()) {
++ if (object_property_find(object_get_objects_root(),
++ machine_class->default_ram_id)) {
++ error_setg(errp, "object name '%s' is reserved for the default"
++ " RAM backend, it can't be used for any other purposes."
++ " Change the object's 'id' to something else",
++ machine_class->default_ram_id);
++ return;
++ }
+ if (!create_default_memdev(current_machine, mem_path, errp)) {
+ return;
+ }
+diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
+index 24616bf924..04f793cca1 100644
+--- a/hw/i386/pc_piix.c
++++ b/hw/i386/pc_piix.c
+@@ -405,6 +405,7 @@ static void pc_xen_hvm_init(MachineState *machine)
+ }
+
+ pc_xen_hvm_init_pci(machine);
++ xen_igd_reserve_slot(pcms->bus);
+ pci_create_simple(pcms->bus, -1, "xen-platform");
+ }
+ #endif
+diff --git a/hw/intc/allwinner-a10-pic.c b/hw/intc/allwinner-a10-pic.c
+index 8cca124807..4875e68ba6 100644
+--- a/hw/intc/allwinner-a10-pic.c
++++ b/hw/intc/allwinner-a10-pic.c
+@@ -49,12 +49,9 @@ static void aw_a10_pic_update(AwA10PICState *s)
+ static void aw_a10_pic_set_irq(void *opaque, int irq, int level)
+ {
+ AwA10PICState *s = opaque;
++ uint32_t *pending_reg = &s->irq_pending[irq / 32];
+
+- if (level) {
+- set_bit(irq % 32, (void *)&s->irq_pending[irq / 32]);
+- } else {
+- clear_bit(irq % 32, (void *)&s->irq_pending[irq / 32]);
+- }
++ *pending_reg = deposit32(*pending_reg, irq % 32, 1, level);
+ aw_a10_pic_update(s);
+ }
+
+diff --git a/hw/net/allwinner-sun8i-emac.c b/hw/net/allwinner-sun8i-emac.c
+index ecc0245fe8..c3fed5fcbe 100644
+--- a/hw/net/allwinner-sun8i-emac.c
++++ b/hw/net/allwinner-sun8i-emac.c
+@@ -350,8 +350,13 @@ static void allwinner_sun8i_emac_get_desc(AwSun8iEmacState *s,
+ FrameDescriptor *desc,
+ uint32_t phys_addr)
+ {
+- dma_memory_read(&s->dma_as, phys_addr, desc, sizeof(*desc),
++ uint32_t desc_words[4];
++ dma_memory_read(&s->dma_as, phys_addr, &desc_words, sizeof(desc_words),
+ MEMTXATTRS_UNSPECIFIED);
++ desc->status = le32_to_cpu(desc_words[0]);
++ desc->status2 = le32_to_cpu(desc_words[1]);
++ desc->addr = le32_to_cpu(desc_words[2]);
++ desc->next = le32_to_cpu(desc_words[3]);
+ }
+
+ static uint32_t allwinner_sun8i_emac_next_desc(AwSun8iEmacState *s,
+@@ -400,10 +405,15 @@ static uint32_t allwinner_sun8i_emac_tx_desc(AwSun8iEmacState *s,
+ }
+
+ static void allwinner_sun8i_emac_flush_desc(AwSun8iEmacState *s,
+- FrameDescriptor *desc,
++ const FrameDescriptor *desc,
+ uint32_t phys_addr)
+ {
+- dma_memory_write(&s->dma_as, phys_addr, desc, sizeof(*desc),
++ uint32_t desc_words[4];
++ desc_words[0] = cpu_to_le32(desc->status);
++ desc_words[1] = cpu_to_le32(desc->status2);
++ desc_words[2] = cpu_to_le32(desc->addr);
++ desc_words[3] = cpu_to_le32(desc->next);
++ dma_memory_write(&s->dma_as, phys_addr, &desc_words, sizeof(desc_words),
+ MEMTXATTRS_UNSPECIFIED);
+ }
+
+@@ -638,8 +648,7 @@ static uint64_t allwinner_sun8i_emac_read(void *opaque, hwaddr offset,
+ break;
+ case REG_TX_CUR_BUF: /* Transmit Current Buffer */
+ if (s->tx_desc_curr != 0) {
+- dma_memory_read(&s->dma_as, s->tx_desc_curr, &desc, sizeof(desc),
+- MEMTXATTRS_UNSPECIFIED);
++ allwinner_sun8i_emac_get_desc(s, &desc, s->tx_desc_curr);
+ value = desc.addr;
+ } else {
+ value = 0;
+@@ -652,8 +661,7 @@ static uint64_t allwinner_sun8i_emac_read(void *opaque, hwaddr offset,
+ break;
+ case REG_RX_CUR_BUF: /* Receive Current Buffer */
+ if (s->rx_desc_curr != 0) {
+- dma_memory_read(&s->dma_as, s->rx_desc_curr, &desc, sizeof(desc),
+- MEMTXATTRS_UNSPECIFIED);
++ allwinner_sun8i_emac_get_desc(s, &desc, s->rx_desc_curr);
+ value = desc.addr;
+ } else {
+ value = 0;
+diff --git a/hw/net/e1000.c b/hw/net/e1000.c
+index e26e0a64c1..0dfdf47313 100644
+--- a/hw/net/e1000.c
++++ b/hw/net/e1000.c
+@@ -567,7 +567,7 @@ e1000_send_packet(E1000State *s, const uint8_t *buf, int size)
+ qemu_send_packet(nc, buf, size);
+ }
+ inc_tx_bcast_or_mcast_count(s, buf);
+- e1000x_increase_size_stats(s->mac_reg, PTCregs, size);
++ e1000x_increase_size_stats(s->mac_reg, PTCregs, size + 4);
+ }
+
+ static void
+@@ -631,10 +631,9 @@ xmit_seg(E1000State *s)
+ }
+
+ e1000x_inc_reg_if_not_full(s->mac_reg, TPT);
+- e1000x_grow_8reg_if_not_full(s->mac_reg, TOTL, s->tx.size);
+- s->mac_reg[GPTC] = s->mac_reg[TPT];
+- s->mac_reg[GOTCL] = s->mac_reg[TOTL];
+- s->mac_reg[GOTCH] = s->mac_reg[TOTH];
++ e1000x_grow_8reg_if_not_full(s->mac_reg, TOTL, s->tx.size + 4);
++ e1000x_inc_reg_if_not_full(s->mac_reg, GPTC);
++ e1000x_grow_8reg_if_not_full(s->mac_reg, GOTCL, s->tx.size + 4);
+ }
+
+ static void
+diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c
+index fc9cdb4528..c71d82ce1d 100644
+--- a/hw/net/e1000e_core.c
++++ b/hw/net/e1000e_core.c
+@@ -687,9 +687,8 @@ e1000e_on_tx_done_update_stats(E1000ECore *core, struct NetTxPkt *tx_pkt)
+ g_assert_not_reached();
+ }
+
+- core->mac[GPTC] = core->mac[TPT];
+- core->mac[GOTCL] = core->mac[TOTL];
+- core->mac[GOTCH] = core->mac[TOTH];
++ e1000x_inc_reg_if_not_full(core->mac, GPTC);
++ e1000x_grow_8reg_if_not_full(core->mac, GOTCL, tot_len);
+ }
+
+ static void
+diff --git a/hw/net/e1000x_common.c b/hw/net/e1000x_common.c
+index a8d93870b5..3fdc34f753 100644
+--- a/hw/net/e1000x_common.c
++++ b/hw/net/e1000x_common.c
+@@ -217,15 +217,14 @@ e1000x_update_rx_total_stats(uint32_t *mac,
+
+ e1000x_increase_size_stats(mac, PRCregs, data_fcs_size);
+ e1000x_inc_reg_if_not_full(mac, TPR);
+- mac[GPRC] = mac[TPR];
++ e1000x_inc_reg_if_not_full(mac, GPRC);
+ /* TOR - Total Octets Received:
+ * This register includes bytes received in a packet from the <Destination
+ * Address> field through the <CRC> field, inclusively.
+ * Always include FCS length (4) in size.
+ */
+ e1000x_grow_8reg_if_not_full(mac, TORL, data_size + 4);
+- mac[GORCL] = mac[TORL];
+- mac[GORCH] = mac[TORH];
++ e1000x_grow_8reg_if_not_full(mac, GORCL, data_size + 4);
+ }
+
+ void
+diff --git a/hw/net/msf2-emac.c b/hw/net/msf2-emac.c
+index 7ccd3e5142..db3a04deb1 100644
+--- a/hw/net/msf2-emac.c
++++ b/hw/net/msf2-emac.c
+@@ -118,14 +118,18 @@ static void emac_load_desc(MSF2EmacState *s, EmacDesc *d, hwaddr desc)
+ d->next = le32_to_cpu(d->next);
+ }
+
+-static void emac_store_desc(MSF2EmacState *s, EmacDesc *d, hwaddr desc)
++static void emac_store_desc(MSF2EmacState *s, const EmacDesc *d, hwaddr desc)
+ {
+- /* Convert from host endianness into LE. */
+- d->pktaddr = cpu_to_le32(d->pktaddr);
+- d->pktsize = cpu_to_le32(d->pktsize);
+- d->next = cpu_to_le32(d->next);
+-
+- address_space_write(&s->dma_as, desc, MEMTXATTRS_UNSPECIFIED, d, sizeof *d);
++ EmacDesc outd;
++ /*
++ * Convert from host endianness into LE. We use a local struct because
++ * calling code may still want to look at the fields afterwards.
++ */
++ outd.pktaddr = cpu_to_le32(d->pktaddr);
++ outd.pktsize = cpu_to_le32(d->pktsize);
++ outd.next = cpu_to_le32(d->next);
++
++ address_space_write(&s->dma_as, desc, MEMTXATTRS_UNSPECIFIED, &outd, sizeof outd);
+ }
+
+ static void msf2_dma_tx(MSF2EmacState *s)
+diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c
+index 700b1b66b6..eb679d7c40 100644
+--- a/hw/net/rtl8139.c
++++ b/hw/net/rtl8139.c
+@@ -2154,6 +2154,9 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
+
+ int large_send_mss = (txdw0 >> CP_TC_LGSEN_MSS_SHIFT) &
+ CP_TC_LGSEN_MSS_MASK;
++ if (large_send_mss == 0) {
++ goto skip_offload;
++ }
+
+ DPRINTF("+++ C+ mode offloaded task TSO IP data %d "
+ "frame data %d specified MSS=%d\n",
+diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
+index aba12759d5..4abd49e298 100644
+--- a/hw/net/virtio-net.c
++++ b/hw/net/virtio-net.c
+@@ -802,7 +802,6 @@ static uint64_t virtio_net_get_features(VirtIODevice *vdev, uint64_t features,
+ }
+
+ if (!get_vhost_net(nc->peer)) {
+- virtio_add_feature(&features, VIRTIO_F_RING_RESET);
+ return features;
+ }
+
+diff --git a/hw/scsi/lsi53c895a.c b/hw/scsi/lsi53c895a.c
+index 50979640c3..42532c4744 100644
+--- a/hw/scsi/lsi53c895a.c
++++ b/hw/scsi/lsi53c895a.c
+@@ -1134,15 +1134,24 @@ static void lsi_execute_script(LSIState *s)
+ uint32_t addr, addr_high;
+ int opcode;
+ int insn_processed = 0;
++ static int reentrancy_level;
++
++ reentrancy_level++;
+
+ s->istat1 |= LSI_ISTAT1_SRUN;
+ again:
+- if (++insn_processed > LSI_MAX_INSN) {
+- /* Some windows drivers make the device spin waiting for a memory
+- location to change. If we have been executed a lot of code then
+- assume this is the case and force an unexpected device disconnect.
+- This is apparently sufficient to beat the drivers into submission.
+- */
++ /*
++ * Some windows drivers make the device spin waiting for a memory location
++ * to change. If we have executed more than LSI_MAX_INSN instructions then
++ * assume this is the case and force an unexpected device disconnect. This
++ * is apparently sufficient to beat the drivers into submission.
++ *
++ * Another issue (CVE-2023-0330) can occur if the script is programmed to
++ * trigger itself again and again. Avoid this problem by stopping after
++ * being called multiple times in a reentrant way (8 is an arbitrary value
++ * which should be enough for all valid use cases).
++ */
++ if (++insn_processed > LSI_MAX_INSN || reentrancy_level > 8) {
+ if (!(s->sien0 & LSI_SIST0_UDC)) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "lsi_scsi: inf. loop with UDC masked");
+@@ -1596,6 +1605,8 @@ again:
+ }
+ }
+ trace_lsi_execute_script_stop();
++
++ reentrancy_level--;
+ }
+
+ static uint8_t lsi_reg_readb(LSIState *s, int offset)
+diff --git a/hw/scsi/scsi-generic.c b/hw/scsi/scsi-generic.c
+index 92cce20a4d..d513870181 100644
+--- a/hw/scsi/scsi-generic.c
++++ b/hw/scsi/scsi-generic.c
+@@ -190,12 +190,16 @@ static int scsi_handle_inquiry_reply(SCSIGenericReq *r, SCSIDevice *s, int len)
+ if ((s->type == TYPE_DISK || s->type == TYPE_ZBC) &&
+ (r->req.cmd.buf[1] & 0x01)) {
+ page = r->req.cmd.buf[2];
+- if (page == 0xb0) {
++ if (page == 0xb0 && r->buflen >= 8) {
++ uint8_t buf[16] = {};
++ uint8_t buf_used = MIN(r->buflen, 16);
+ uint64_t max_transfer = calculate_max_transfer(s);
+- stl_be_p(&r->buf[8], max_transfer);
+- /* Also take care of the opt xfer len. */
+- stl_be_p(&r->buf[12],
+- MIN_NON_ZERO(max_transfer, ldl_be_p(&r->buf[12])));
++
++ memcpy(buf, r->buf, buf_used);
++ stl_be_p(&buf[8], max_transfer);
++ stl_be_p(&buf[12], MIN_NON_ZERO(max_transfer, ldl_be_p(&buf[12])));
++ memcpy(r->buf + 8, buf + 8, buf_used - 8);
++
+ } else if (s->needs_vpd_bl_emulation && page == 0x00 && r->buflen >= 4) {
+ /*
+ * Now we're capable of supplying the VPD Block Limits
+diff --git a/hw/sd/allwinner-sdhost.c b/hw/sd/allwinner-sdhost.c
+index 51e5e90830..92a0f42708 100644
+--- a/hw/sd/allwinner-sdhost.c
++++ b/hw/sd/allwinner-sdhost.c
+@@ -302,6 +302,30 @@ static void allwinner_sdhost_auto_stop(AwSdHostState *s)
+ }
+ }
+
++static void read_descriptor(AwSdHostState *s, hwaddr desc_addr,
++ TransferDescriptor *desc)
++{
++ uint32_t desc_words[4];
++ dma_memory_read(&s->dma_as, desc_addr, &desc_words, sizeof(desc_words),
++ MEMTXATTRS_UNSPECIFIED);
++ desc->status = le32_to_cpu(desc_words[0]);
++ desc->size = le32_to_cpu(desc_words[1]);
++ desc->addr = le32_to_cpu(desc_words[2]);
++ desc->next = le32_to_cpu(desc_words[3]);
++}
++
++static void write_descriptor(AwSdHostState *s, hwaddr desc_addr,
++ const TransferDescriptor *desc)
++{
++ uint32_t desc_words[4];
++ desc_words[0] = cpu_to_le32(desc->status);
++ desc_words[1] = cpu_to_le32(desc->size);
++ desc_words[2] = cpu_to_le32(desc->addr);
++ desc_words[3] = cpu_to_le32(desc->next);
++ dma_memory_write(&s->dma_as, desc_addr, &desc_words, sizeof(desc_words),
++ MEMTXATTRS_UNSPECIFIED);
++}
++
+ static uint32_t allwinner_sdhost_process_desc(AwSdHostState *s,
+ hwaddr desc_addr,
+ TransferDescriptor *desc,
+@@ -312,9 +336,7 @@ static uint32_t allwinner_sdhost_process_desc(AwSdHostState *s,
+ uint32_t num_bytes = max_bytes;
+ uint8_t buf[1024];
+
+- /* Read descriptor */
+- dma_memory_read(&s->dma_as, desc_addr, desc, sizeof(*desc),
+- MEMTXATTRS_UNSPECIFIED);
++ read_descriptor(s, desc_addr, desc);
+ if (desc->size == 0) {
+ desc->size = klass->max_desc_size;
+ } else if (desc->size > klass->max_desc_size) {
+@@ -356,8 +378,7 @@ static uint32_t allwinner_sdhost_process_desc(AwSdHostState *s,
+
+ /* Clear hold flag and flush descriptor */
+ desc->status &= ~DESC_STATUS_HOLD;
+- dma_memory_write(&s->dma_as, desc_addr, desc, sizeof(*desc),
+- MEMTXATTRS_UNSPECIFIED);
++ write_descriptor(s, desc_addr, desc);
+
+ return num_done;
+ }
+diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c
+index 9d68036d23..c3ab762f54 100644
+--- a/hw/usb/hcd-ohci.c
++++ b/hw/usb/hcd-ohci.c
+@@ -1210,6 +1210,8 @@ static void ohci_frame_boundary(void *opaque)
+ /* Increment frame number and take care of endianness. */
+ ohci->frame_number = (ohci->frame_number + 1) & 0xffff;
+ hcca.frame = cpu_to_le16(ohci->frame_number);
++ /* When the HC updates frame number, set pad to 0. Ref OHCI Spec 4.4.1*/
++ hcca.pad = 0;
+
+ if (ohci->done_count == 0 && !(ohci->intr_status & OHCI_INTR_WD)) {
+ if (!ohci->done)
+diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c
+index a723073747..d422418f2d 100644
+--- a/hw/virtio/vhost-shadow-virtqueue.c
++++ b/hw/virtio/vhost-shadow-virtqueue.c
+@@ -68,7 +68,7 @@ bool vhost_svq_valid_features(uint64_t features, Error **errp)
+ */
+ static uint16_t vhost_svq_available_slots(const VhostShadowVirtqueue *svq)
+ {
+- return svq->vring.num - (svq->shadow_avail_idx - svq->shadow_used_idx);
++ return svq->num_free;
+ }
+
+ /**
+@@ -263,6 +263,7 @@ int vhost_svq_add(VhostShadowVirtqueue *svq, const struct iovec *out_sg,
+ return -EINVAL;
+ }
+
++ svq->num_free -= ndescs;
+ svq->desc_state[qemu_head].elem = elem;
+ svq->desc_state[qemu_head].ndescs = ndescs;
+ vhost_svq_kick(svq);
+@@ -449,6 +450,7 @@ static VirtQueueElement *vhost_svq_get_buf(VhostShadowVirtqueue *svq,
+ last_used_chain = vhost_svq_last_desc_of_chain(svq, num, used_elem.id);
+ svq->desc_next[last_used_chain] = svq->free_head;
+ svq->free_head = used_elem.id;
++ svq->num_free += num;
+
+ *len = used_elem.len;
+ return g_steal_pointer(&svq->desc_state[used_elem.id].elem);
+@@ -656,6 +658,7 @@ void vhost_svq_start(VhostShadowVirtqueue *svq, VirtIODevice *vdev,
+ svq->vq = vq;
+
+ svq->vring.num = virtio_queue_get_num(vdev, virtio_get_queue_index(vq));
++ svq->num_free = svq->vring.num;
+ driver_size = vhost_svq_driver_area_size(svq);
+ device_size = vhost_svq_device_area_size(svq);
+ svq->vring.desc = qemu_memalign(qemu_real_host_page_size(), driver_size);
+diff --git a/hw/virtio/vhost-shadow-virtqueue.h b/hw/virtio/vhost-shadow-virtqueue.h
+index d04c34a589..328a7fc075 100644
+--- a/hw/virtio/vhost-shadow-virtqueue.h
++++ b/hw/virtio/vhost-shadow-virtqueue.h
+@@ -107,6 +107,9 @@ typedef struct VhostShadowVirtqueue {
+
+ /* Next head to consume from the device */
+ uint16_t last_used_idx;
++
++ /* Size of SVQ vring free descriptors */
++ uint16_t num_free;
+ } VhostShadowVirtqueue;
+
+ bool vhost_svq_valid_features(uint64_t features, Error **errp);
+diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
+index 8f635844af..d92b026e1c 100644
+--- a/hw/virtio/vhost-user.c
++++ b/hw/virtio/vhost-user.c
+@@ -305,19 +305,8 @@ static int vhost_user_read_header(struct vhost_dev *dev, VhostUserMsg *msg)
+ return 0;
+ }
+
+-struct vhost_user_read_cb_data {
+- struct vhost_dev *dev;
+- VhostUserMsg *msg;
+- GMainLoop *loop;
+- int ret;
+-};
+-
+-static gboolean vhost_user_read_cb(void *do_not_use, GIOCondition condition,
+- gpointer opaque)
++static int vhost_user_read(struct vhost_dev *dev, VhostUserMsg *msg)
+ {
+- struct vhost_user_read_cb_data *data = opaque;
+- struct vhost_dev *dev = data->dev;
+- VhostUserMsg *msg = data->msg;
+ struct vhost_user *u = dev->opaque;
+ CharBackend *chr = u->user->chr;
+ uint8_t *p = (uint8_t *) msg;
+@@ -325,8 +314,7 @@ static gboolean vhost_user_read_cb(void *do_not_use, GIOCondition condition,
+
+ r = vhost_user_read_header(dev, msg);
+ if (r < 0) {
+- data->ret = r;
+- goto end;
++ return r;
+ }
+
+ /* validate message size is sane */
+@@ -334,8 +322,7 @@ static gboolean vhost_user_read_cb(void *do_not_use, GIOCondition condition,
+ error_report("Failed to read msg header."
+ " Size %d exceeds the maximum %zu.", msg->hdr.size,
+ VHOST_USER_PAYLOAD_SIZE);
+- data->ret = -EPROTO;
+- goto end;
++ return -EPROTO;
+ }
+
+ if (msg->hdr.size) {
+@@ -346,84 +333,11 @@ static gboolean vhost_user_read_cb(void *do_not_use, GIOCondition condition,
+ int saved_errno = errno;
+ error_report("Failed to read msg payload."
+ " Read %d instead of %d.", r, msg->hdr.size);
+- data->ret = r < 0 ? -saved_errno : -EIO;
+- goto end;
++ return r < 0 ? -saved_errno : -EIO;
+ }
+ }
+
+-end:
+- g_main_loop_quit(data->loop);
+- return G_SOURCE_REMOVE;
+-}
+-
+-static gboolean slave_read(QIOChannel *ioc, GIOCondition condition,
+- gpointer opaque);
+-
+-/*
+- * This updates the read handler to use a new event loop context.
+- * Event sources are removed from the previous context : this ensures
+- * that events detected in the previous context are purged. They will
+- * be re-detected and processed in the new context.
+- */
+-static void slave_update_read_handler(struct vhost_dev *dev,
+- GMainContext *ctxt)
+-{
+- struct vhost_user *u = dev->opaque;
+-
+- if (!u->slave_ioc) {
+- return;
+- }
+-
+- if (u->slave_src) {
+- g_source_destroy(u->slave_src);
+- g_source_unref(u->slave_src);
+- }
+-
+- u->slave_src = qio_channel_add_watch_source(u->slave_ioc,
+- G_IO_IN | G_IO_HUP,
+- slave_read, dev, NULL,
+- ctxt);
+-}
+-
+-static int vhost_user_read(struct vhost_dev *dev, VhostUserMsg *msg)
+-{
+- struct vhost_user *u = dev->opaque;
+- CharBackend *chr = u->user->chr;
+- GMainContext *prev_ctxt = chr->chr->gcontext;
+- GMainContext *ctxt = g_main_context_new();
+- GMainLoop *loop = g_main_loop_new(ctxt, FALSE);
+- struct vhost_user_read_cb_data data = {
+- .dev = dev,
+- .loop = loop,
+- .msg = msg,
+- .ret = 0
+- };
+-
+- /*
+- * We want to be able to monitor the slave channel fd while waiting
+- * for chr I/O. This requires an event loop, but we can't nest the
+- * one to which chr is currently attached : its fd handlers might not
+- * be prepared for re-entrancy. So we create a new one and switch chr
+- * to use it.
+- */
+- slave_update_read_handler(dev, ctxt);
+- qemu_chr_be_update_read_handlers(chr->chr, ctxt);
+- qemu_chr_fe_add_watch(chr, G_IO_IN | G_IO_HUP, vhost_user_read_cb, &data);
+-
+- g_main_loop_run(loop);
+-
+- /*
+- * Restore the previous event loop context. This also destroys/recreates
+- * event sources : this guarantees that all pending events in the original
+- * context that have been processed by the nested loop are purged.
+- */
+- qemu_chr_be_update_read_handlers(chr->chr, prev_ctxt);
+- slave_update_read_handler(dev, NULL);
+-
+- g_main_loop_unref(loop);
+- g_main_context_unref(ctxt);
+-
+- return data.ret;
++ return 0;
+ }
+
+ static int process_message_reply(struct vhost_dev *dev,
+@@ -1802,7 +1716,9 @@ static int vhost_setup_slave_channel(struct vhost_dev *dev)
+ return -ECONNREFUSED;
+ }
+ u->slave_ioc = ioc;
+- slave_update_read_handler(dev, NULL);
++ u->slave_src = qio_channel_add_watch_source(u->slave_ioc,
++ G_IO_IN | G_IO_HUP,
++ slave_read, dev, NULL, NULL);
+
+ if (reply_supported) {
+ msg.hdr.flags |= VHOST_USER_NEED_REPLY_MASK;
+@@ -2108,8 +2024,8 @@ static int vhost_user_backend_init(struct vhost_dev *dev, void *opaque,
+ } else {
+ if (virtio_has_feature(protocol_features,
+ VHOST_USER_PROTOCOL_F_CONFIG)) {
+- warn_reportf_err(*errp, "vhost-user backend supports "
+- "VHOST_USER_PROTOCOL_F_CONFIG but QEMU does not.");
++ warn_report("vhost-user backend supports "
++ "VHOST_USER_PROTOCOL_F_CONFIG but QEMU does not.");
+ protocol_features &= ~(1ULL << VHOST_USER_PROTOCOL_F_CONFIG);
+ }
+ }
+diff --git a/hw/virtio/virtio-crypto.c b/hw/virtio/virtio-crypto.c
+index 97da74e719..a6dbdd32da 100644
+--- a/hw/virtio/virtio-crypto.c
++++ b/hw/virtio/virtio-crypto.c
+@@ -476,15 +476,17 @@ static void virtio_crypto_free_request(VirtIOCryptoReq *req)
+ size_t max_len;
+ CryptoDevBackendSymOpInfo *op_info = req->op_info.u.sym_op_info;
+
+- max_len = op_info->iv_len +
+- op_info->aad_len +
+- op_info->src_len +
+- op_info->dst_len +
+- op_info->digest_result_len;
+-
+- /* Zeroize and free request data structure */
+- memset(op_info, 0, sizeof(*op_info) + max_len);
+- g_free(op_info);
++ if (op_info) {
++ max_len = op_info->iv_len +
++ op_info->aad_len +
++ op_info->src_len +
++ op_info->dst_len +
++ op_info->digest_result_len;
++
++ /* Zeroize and free request data structure */
++ memset(op_info, 0, sizeof(*op_info) + max_len);
++ g_free(op_info);
++ }
+ } else if (req->flags == CRYPTODEV_BACKEND_ALG_ASYM) {
+ CryptoDevBackendAsymOpInfo *op_info = req->op_info.u.asym_op_info;
+ if (op_info) {
+diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
+index eb6347ab5d..384c8f0f08 100644
+--- a/hw/virtio/virtio.c
++++ b/hw/virtio/virtio.c
+@@ -1478,7 +1478,7 @@ static void virtqueue_split_get_avail_bytes(VirtQueue *vq,
+ VRingMemoryRegionCaches *caches)
+ {
+ VirtIODevice *vdev = vq->vdev;
+- unsigned int max, idx;
++ unsigned int idx;
+ unsigned int total_bufs, in_total, out_total;
+ MemoryRegionCache indirect_desc_cache = MEMORY_REGION_CACHE_INVALID;
+ int64_t len = 0;
+@@ -1487,13 +1487,12 @@ static void virtqueue_split_get_avail_bytes(VirtQueue *vq,
+ idx = vq->last_avail_idx;
+ total_bufs = in_total = out_total = 0;
+
+- max = vq->vring.num;
+-
+ while ((rc = virtqueue_num_heads(vq, idx)) > 0) {
+ MemoryRegionCache *desc_cache = &caches->desc;
+ unsigned int num_bufs;
+ VRingDesc desc;
+ unsigned int i;
++ unsigned int max = vq->vring.num;
+
+ num_bufs = total_bufs;
+
+@@ -1615,7 +1614,7 @@ static void virtqueue_packed_get_avail_bytes(VirtQueue *vq,
+ VRingMemoryRegionCaches *caches)
+ {
+ VirtIODevice *vdev = vq->vdev;
+- unsigned int max, idx;
++ unsigned int idx;
+ unsigned int total_bufs, in_total, out_total;
+ MemoryRegionCache *desc_cache;
+ MemoryRegionCache indirect_desc_cache = MEMORY_REGION_CACHE_INVALID;
+@@ -1627,14 +1626,14 @@ static void virtqueue_packed_get_avail_bytes(VirtQueue *vq,
+ wrap_counter = vq->last_avail_wrap_counter;
+ total_bufs = in_total = out_total = 0;
+
+- max = vq->vring.num;
+-
+ for (;;) {
+ unsigned int num_bufs = total_bufs;
+ unsigned int i = idx;
+ int rc;
++ unsigned int max = vq->vring.num;
+
+ desc_cache = &caches->desc;
++
+ vring_packed_desc_read(vdev, &desc, desc_cache, idx, true);
+ if (!is_desc_avail(desc.flags, wrap_counter)) {
+ break;
+diff --git a/hw/xen/xen_pt.c b/hw/xen/xen_pt.c
+index 0ec7e52183..5dd706efbf 100644
+--- a/hw/xen/xen_pt.c
++++ b/hw/xen/xen_pt.c
+@@ -57,6 +57,7 @@
+ #include <sys/ioctl.h>
+
+ #include "hw/pci/pci.h"
++#include "hw/pci/pci_bus.h"
+ #include "hw/qdev-properties.h"
+ #include "hw/qdev-properties-system.h"
+ #include "hw/xen/xen.h"
+@@ -780,15 +781,6 @@ static void xen_pt_realize(PCIDevice *d, Error **errp)
+ s->hostaddr.bus, s->hostaddr.slot, s->hostaddr.function,
+ s->dev.devfn);
+
+- xen_host_pci_device_get(&s->real_device,
+- s->hostaddr.domain, s->hostaddr.bus,
+- s->hostaddr.slot, s->hostaddr.function,
+- errp);
+- if (*errp) {
+- error_append_hint(errp, "Failed to \"open\" the real pci device");
+- return;
+- }
+-
+ s->is_virtfn = s->real_device.is_virtfn;
+ if (s->is_virtfn) {
+ XEN_PT_LOG(d, "%04x:%02x:%02x.%d is a SR-IOV Virtual Function\n",
+@@ -803,8 +795,10 @@ static void xen_pt_realize(PCIDevice *d, Error **errp)
+ s->io_listener = xen_pt_io_listener;
+
+ /* Setup VGA bios for passthrough GFX */
+- if ((s->real_device.domain == 0) && (s->real_device.bus == 0) &&
+- (s->real_device.dev == 2) && (s->real_device.func == 0)) {
++ if ((s->real_device.domain == XEN_PCI_IGD_DOMAIN) &&
++ (s->real_device.bus == XEN_PCI_IGD_BUS) &&
++ (s->real_device.dev == XEN_PCI_IGD_DEV) &&
++ (s->real_device.func == XEN_PCI_IGD_FN)) {
+ if (!is_igd_vga_passthrough(&s->real_device)) {
+ error_setg(errp, "Need to enable igd-passthru if you're trying"
+ " to passthrough IGD GFX");
+@@ -950,11 +944,58 @@ static void xen_pci_passthrough_instance_init(Object *obj)
+ PCI_DEVICE(obj)->cap_present |= QEMU_PCI_CAP_EXPRESS;
+ }
+
++void xen_igd_reserve_slot(PCIBus *pci_bus)
++{
++ if (!xen_igd_gfx_pt_enabled()) {
++ return;
++ }
++
++ XEN_PT_LOG(0, "Reserving PCI slot 2 for IGD\n");
++ pci_bus->slot_reserved_mask |= XEN_PCI_IGD_SLOT_MASK;
++}
++
++static void xen_igd_clear_slot(DeviceState *qdev, Error **errp)
++{
++ ERRP_GUARD();
++ PCIDevice *pci_dev = (PCIDevice *)qdev;
++ XenPCIPassthroughState *s = XEN_PT_DEVICE(pci_dev);
++ XenPTDeviceClass *xpdc = XEN_PT_DEVICE_GET_CLASS(s);
++ PCIBus *pci_bus = pci_get_bus(pci_dev);
++
++ xen_host_pci_device_get(&s->real_device,
++ s->hostaddr.domain, s->hostaddr.bus,
++ s->hostaddr.slot, s->hostaddr.function,
++ errp);
++ if (*errp) {
++ error_append_hint(errp, "Failed to \"open\" the real pci device");
++ return;
++ }
++
++ if (!(pci_bus->slot_reserved_mask & XEN_PCI_IGD_SLOT_MASK)) {
++ xpdc->pci_qdev_realize(qdev, errp);
++ return;
++ }
++
++ if (is_igd_vga_passthrough(&s->real_device) &&
++ s->real_device.domain == XEN_PCI_IGD_DOMAIN &&
++ s->real_device.bus == XEN_PCI_IGD_BUS &&
++ s->real_device.dev == XEN_PCI_IGD_DEV &&
++ s->real_device.func == XEN_PCI_IGD_FN &&
++ s->real_device.vendor_id == PCI_VENDOR_ID_INTEL) {
++ pci_bus->slot_reserved_mask &= ~XEN_PCI_IGD_SLOT_MASK;
++ XEN_PT_LOG(pci_dev, "Intel IGD found, using slot 2\n");
++ }
++ xpdc->pci_qdev_realize(qdev, errp);
++}
++
+ static void xen_pci_passthrough_class_init(ObjectClass *klass, void *data)
+ {
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
++ XenPTDeviceClass *xpdc = XEN_PT_DEVICE_CLASS(klass);
++ xpdc->pci_qdev_realize = dc->realize;
++ dc->realize = xen_igd_clear_slot;
+ k->realize = xen_pt_realize;
+ k->exit = xen_pt_unregister_device;
+ k->config_read = xen_pt_pci_read_config;
+@@ -977,6 +1018,7 @@ static const TypeInfo xen_pci_passthrough_info = {
+ .instance_size = sizeof(XenPCIPassthroughState),
+ .instance_finalize = xen_pci_passthrough_finalize,
+ .class_init = xen_pci_passthrough_class_init,
++ .class_size = sizeof(XenPTDeviceClass),
+ .instance_init = xen_pci_passthrough_instance_init,
+ .interfaces = (InterfaceInfo[]) {
+ { INTERFACE_CONVENTIONAL_PCI_DEVICE },
+diff --git a/hw/xen/xen_pt.h b/hw/xen/xen_pt.h
+index e7c4316a7d..292bdf7499 100644
+--- a/hw/xen/xen_pt.h
++++ b/hw/xen/xen_pt.h
+@@ -41,7 +41,20 @@ typedef struct XenPTReg XenPTReg;
+ #define TYPE_XEN_PT_DEVICE "xen-pci-passthrough"
+ OBJECT_DECLARE_SIMPLE_TYPE(XenPCIPassthroughState, XEN_PT_DEVICE)
+
++#define XEN_PT_DEVICE_CLASS(klass) \
++ OBJECT_CLASS_CHECK(XenPTDeviceClass, klass, TYPE_XEN_PT_DEVICE)
++#define XEN_PT_DEVICE_GET_CLASS(obj) \
++ OBJECT_GET_CLASS(XenPTDeviceClass, obj, TYPE_XEN_PT_DEVICE)
++
++typedef void (*XenPTQdevRealize)(DeviceState *qdev, Error **errp);
++
++typedef struct XenPTDeviceClass {
++ PCIDeviceClass parent_class;
++ XenPTQdevRealize pci_qdev_realize;
++} XenPTDeviceClass;
++
+ uint32_t igd_read_opregion(XenPCIPassthroughState *s);
++void xen_igd_reserve_slot(PCIBus *pci_bus);
+ void igd_write_opregion(XenPCIPassthroughState *s, uint32_t val);
+ void xen_igd_passthrough_isa_bridge_create(XenPCIPassthroughState *s,
+ XenHostPCIDevice *dev);
+@@ -76,6 +89,13 @@ typedef int (*xen_pt_conf_byte_read)
+
+ #define XEN_PCI_INTEL_OPREGION 0xfc
+
++#define XEN_PCI_IGD_DOMAIN 0
++#define XEN_PCI_IGD_BUS 0
++#define XEN_PCI_IGD_DEV 2
++#define XEN_PCI_IGD_FN 0
++#define XEN_PCI_IGD_SLOT_MASK \
++ (1UL << PCI_SLOT(PCI_DEVFN(XEN_PCI_IGD_DEV, XEN_PCI_IGD_FN)))
++
+ typedef enum {
+ XEN_PT_GRP_TYPE_HARDWIRED = 0, /* 0 Hardwired reg group */
+ XEN_PT_GRP_TYPE_EMU, /* emul reg group */
+diff --git a/hw/xen/xen_pt_stub.c b/hw/xen/xen_pt_stub.c
+index 2d8cac8d54..5c108446a8 100644
+--- a/hw/xen/xen_pt_stub.c
++++ b/hw/xen/xen_pt_stub.c
+@@ -20,3 +20,7 @@ void xen_igd_gfx_pt_set(bool value, Error **errp)
+ error_setg(errp, "Xen PCI passthrough support not built in");
+ }
+ }
++
++void xen_igd_reserve_slot(PCIBus *pci_bus)
++{
++}
+diff --git a/include/hw/arm/boot.h b/include/hw/arm/boot.h
+index f18cc3064f..80c492d742 100644
+--- a/include/hw/arm/boot.h
++++ b/include/hw/arm/boot.h
+@@ -183,4 +183,53 @@ void arm_write_secure_board_setup_dummy_smc(ARMCPU *cpu,
+ const struct arm_boot_info *info,
+ hwaddr mvbar_addr);
+
++typedef enum {
++ FIXUP_NONE = 0, /* do nothing */
++ FIXUP_TERMINATOR, /* end of insns */
++ FIXUP_BOARDID, /* overwrite with board ID number */
++ FIXUP_BOARD_SETUP, /* overwrite with board specific setup code address */
++ FIXUP_ARGPTR_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 */
++ FIXUP_MAX,
++} FixupType;
++
++typedef struct ARMInsnFixup {
++ uint32_t insn;
++ FixupType fixup;
++} ARMInsnFixup;
++
++/**
++ * arm_write_bootloader - write a bootloader to guest memory
++ * @name: name of the bootloader blob
++ * @as: AddressSpace to write the bootloader
++ * @addr: guest address to write it
++ * @insns: the blob to be loaded
++ * @fixupcontext: context to be used for any fixups in @insns
++ *
++ * Write a bootloader to guest memory at address @addr in the address
++ * space @as. @name is the name to use for the resulting ROM blob, so
++ * it should be unique in the system and reasonably identifiable for debugging.
++ *
++ * @insns must be an array of ARMInsnFixup structs, each of which has
++ * one 32-bit value to be written to the guest memory, and a fixup to be
++ * applied to the value. FIXUP_NONE (do nothing) is value 0, so effectively
++ * the fixup is optional when writing a struct initializer.
++ * The final entry in the array must be { 0, FIXUP_TERMINATOR }.
++ *
++ * All other supported fixup types have the semantics "ignore insn
++ * and instead use the value from the array element @fixupcontext[fixup]".
++ * The caller should therefore provide @fixupcontext as an array of
++ * size FIXUP_MAX whose elements have been initialized for at least
++ * the entries that @insns refers to.
++ */
++void arm_write_bootloader(const char *name,
++ AddressSpace *as, hwaddr addr,
++ const ARMInsnFixup *insns,
++ const uint32_t *fixupcontext);
++
+ #endif /* HW_ARM_BOOT_H */
+diff --git a/linux-user/mips/cpu_loop.c b/linux-user/mips/cpu_loop.c
+index d5c1c7941d..8735e58bad 100644
+--- a/linux-user/mips/cpu_loop.c
++++ b/linux-user/mips/cpu_loop.c
+@@ -290,7 +290,10 @@ void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs)
+ env->CP0_Status |= (1 << CP0St_FR);
+ env->hflags |= MIPS_HFLAG_F64;
+ }
+- } else if (!prog_req.fre && !prog_req.frdefault &&
++ } else if (prog_req.fr1) {
++ env->CP0_Status |= (1 << CP0St_FR);
++ env->hflags |= MIPS_HFLAG_F64;
++ } else if (!prog_req.fre && !prog_req.frdefault &&
+ !prog_req.fr1 && !prog_req.single && !prog_req.soft) {
+ fprintf(stderr, "qemu: Can't find a matching FPU mode\n");
+ exit(1);
+diff --git a/linux-user/syscall.c b/linux-user/syscall.c
+index 9ca30149d4..cedf22c5b5 100644
+--- a/linux-user/syscall.c
++++ b/linux-user/syscall.c
+@@ -11438,39 +11438,58 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
+ {
+ int gidsetsize = arg1;
+ target_id *target_grouplist;
+- gid_t *grouplist;
++ g_autofree gid_t *grouplist = NULL;
+ int i;
+
+- grouplist = alloca(gidsetsize * sizeof(gid_t));
++ if (gidsetsize > NGROUPS_MAX) {
++ return -TARGET_EINVAL;
++ }
++ if (gidsetsize > 0) {
++ grouplist = g_try_new(gid_t, gidsetsize);
++ if (!grouplist) {
++ return -TARGET_ENOMEM;
++ }
++ }
+ ret = get_errno(getgroups(gidsetsize, grouplist));
+- if (gidsetsize == 0)
+- return ret;
+- if (!is_error(ret)) {
+- target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * sizeof(target_id), 0);
+- if (!target_grouplist)
++ if (!is_error(ret) && gidsetsize > 0) {
++ target_grouplist = lock_user(VERIFY_WRITE, arg2,
++ gidsetsize * sizeof(target_id), 0);
++ if (!target_grouplist) {
+ return -TARGET_EFAULT;
+- for(i = 0;i < ret; i++)
++ }
++ for (i = 0; i < ret; i++) {
+ target_grouplist[i] = tswapid(high2lowgid(grouplist[i]));
+- unlock_user(target_grouplist, arg2, gidsetsize * sizeof(target_id));
++ }
++ unlock_user(target_grouplist, arg2,
++ gidsetsize * sizeof(target_id));
+ }
++ return ret;
+ }
+- return ret;
+ case TARGET_NR_setgroups:
+ {
+ int gidsetsize = arg1;
+ target_id *target_grouplist;
+- gid_t *grouplist = NULL;
++ g_autofree gid_t *grouplist = NULL;
+ int i;
+- if (gidsetsize) {
+- grouplist = alloca(gidsetsize * sizeof(gid_t));
+- target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * sizeof(target_id), 1);
++
++ if (gidsetsize > NGROUPS_MAX || gidsetsize < 0) {
++ return -TARGET_EINVAL;
++ }
++ if (gidsetsize > 0) {
++ grouplist = g_try_new(gid_t, gidsetsize);
++ if (!grouplist) {
++ return -TARGET_ENOMEM;
++ }
++ target_grouplist = lock_user(VERIFY_READ, arg2,
++ gidsetsize * sizeof(target_id), 1);
+ if (!target_grouplist) {
+ return -TARGET_EFAULT;
+ }
+ for (i = 0; i < gidsetsize; i++) {
+ grouplist[i] = low2highgid(tswapid(target_grouplist[i]));
+ }
+- unlock_user(target_grouplist, arg2, 0);
++ unlock_user(target_grouplist, arg2,
++ gidsetsize * sizeof(target_id));
+ }
+ return get_errno(setgroups(gidsetsize, grouplist));
+ }
+@@ -11755,41 +11774,59 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
+ {
+ int gidsetsize = arg1;
+ uint32_t *target_grouplist;
+- gid_t *grouplist;
++ g_autofree gid_t *grouplist = NULL;
+ int i;
+
+- grouplist = alloca(gidsetsize * sizeof(gid_t));
++ if (gidsetsize > NGROUPS_MAX) {
++ return -TARGET_EINVAL;
++ }
++ if (gidsetsize > 0) {
++ grouplist = g_try_new(gid_t, gidsetsize);
++ if (!grouplist) {
++ return -TARGET_ENOMEM;
++ }
++ }
+ ret = get_errno(getgroups(gidsetsize, grouplist));
+- if (gidsetsize == 0)
+- return ret;
+- if (!is_error(ret)) {
+- target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 4, 0);
++ if (!is_error(ret) && gidsetsize > 0) {
++ target_grouplist = lock_user(VERIFY_WRITE, arg2,
++ gidsetsize * 4, 0);
+ if (!target_grouplist) {
+ return -TARGET_EFAULT;
+ }
+- for(i = 0;i < ret; i++)
++ for (i = 0; i < ret; i++) {
+ target_grouplist[i] = tswap32(grouplist[i]);
++ }
+ unlock_user(target_grouplist, arg2, gidsetsize * 4);
+ }
++ return ret;
+ }
+- return ret;
+ #endif
+ #ifdef TARGET_NR_setgroups32
+ case TARGET_NR_setgroups32:
+ {
+ int gidsetsize = arg1;
+ uint32_t *target_grouplist;
+- gid_t *grouplist;
++ g_autofree gid_t *grouplist = NULL;
+ int i;
+
+- grouplist = alloca(gidsetsize * sizeof(gid_t));
+- target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 4, 1);
+- if (!target_grouplist) {
+- return -TARGET_EFAULT;
++ if (gidsetsize > NGROUPS_MAX || gidsetsize < 0) {
++ return -TARGET_EINVAL;
++ }
++ if (gidsetsize > 0) {
++ grouplist = g_try_new(gid_t, gidsetsize);
++ if (!grouplist) {
++ return -TARGET_ENOMEM;
++ }
++ target_grouplist = lock_user(VERIFY_READ, arg2,
++ gidsetsize * 4, 1);
++ if (!target_grouplist) {
++ return -TARGET_EFAULT;
++ }
++ for (i = 0; i < gidsetsize; i++) {
++ grouplist[i] = tswap32(target_grouplist[i]);
++ }
++ unlock_user(target_grouplist, arg2, 0);
+ }
+- for(i = 0;i < gidsetsize; i++)
+- grouplist[i] = tswap32(target_grouplist[i]);
+- unlock_user(target_grouplist, arg2, 0);
+ return get_errno(setgroups(gidsetsize, grouplist));
+ }
+ #endif
+diff --git a/meson.build b/meson.build
+index b88867ca9d..450c48a9f0 100644
+--- a/meson.build
++++ b/meson.build
+@@ -3164,6 +3164,10 @@ modinfo_files = []
+ block_mods = []
+ softmmu_mods = []
+ foreach d, list : modules
++ if not (d == 'block' ? have_block : have_system)
++ continue
++ endif
++
+ foreach m, module_ss : list
+ if enable_modules and targetos != 'windows'
+ module_ss = module_ss.apply(config_all, strict: false)
+diff --git a/migration/migration.c b/migration/migration.c
+index f485eea5fb..c19fb5cb3e 100644
+--- a/migration/migration.c
++++ b/migration/migration.c
+@@ -3320,7 +3320,6 @@ static void migration_completion(MigrationState *s)
+ ret = global_state_store();
+
+ if (!ret) {
+- bool inactivate = !migrate_colo_enabled();
+ ret = vm_stop_force_state(RUN_STATE_FINISH_MIGRATE);
+ trace_migration_completion_vm_stop(ret);
+ if (ret >= 0) {
+@@ -3328,12 +3327,15 @@ static void migration_completion(MigrationState *s)
+ MIGRATION_STATUS_DEVICE);
+ }
+ if (ret >= 0) {
++ /*
++ * Inactivate disks except in COLO, and track that we
++ * have done so in order to remember to reactivate
++ * them if migration fails or is cancelled.
++ */
++ s->block_inactive = !migrate_colo_enabled();
+ qemu_file_set_rate_limit(s->to_dst_file, INT64_MAX);
+ ret = qemu_savevm_state_complete_precopy(s->to_dst_file, false,
+- inactivate);
+- }
+- if (inactivate && ret >= 0) {
+- s->block_inactive = true;
++ s->block_inactive);
+ }
+ }
+ qemu_mutex_unlock_iothread();
+@@ -3370,13 +3372,13 @@ static void migration_completion(MigrationState *s)
+ rp_error = await_return_path_close_on_source(s);
+ trace_migration_return_path_end_after(rp_error);
+ if (rp_error) {
+- goto fail_invalidate;
++ goto fail;
+ }
+ }
+
+ if (qemu_file_get_error(s->to_dst_file)) {
+ trace_migration_completion_file_err();
+- goto fail_invalidate;
++ goto fail;
+ }
+
+ if (migrate_colo_enabled() && s->state == MIGRATION_STATUS_ACTIVE) {
+@@ -3390,12 +3392,13 @@ static void migration_completion(MigrationState *s)
+
+ return;
+
+-fail_invalidate:
+- /* If not doing postcopy, vm_start() will be called: let's regain
+- * control on images.
+- */
+- if (s->state == MIGRATION_STATUS_ACTIVE ||
+- s->state == MIGRATION_STATUS_DEVICE) {
++fail:
++ if (s->block_inactive && (s->state == MIGRATION_STATUS_ACTIVE ||
++ s->state == MIGRATION_STATUS_DEVICE)) {
++ /*
++ * If not doing postcopy, vm_start() will be called: let's
++ * regain control on images.
++ */
+ Error *local_err = NULL;
+
+ qemu_mutex_lock_iothread();
+@@ -3408,7 +3411,6 @@ fail_invalidate:
+ qemu_mutex_unlock_iothread();
+ }
+
+-fail:
+ migrate_set_state(&s->state, current_active_state,
+ MIGRATION_STATUS_FAILED);
+ }
+diff --git a/qemu-options.hx b/qemu-options.hx
+index 7f99d15b23..e52289479b 100644
+--- a/qemu-options.hx
++++ b/qemu-options.hx
+@@ -1140,10 +1140,22 @@ have gone through several iterations as the feature set and complexity
+ of the block layer have grown. Many online guides to QEMU often
+ reference older and deprecated options, which can lead to confusion.
+
+-The recommended modern way to describe disks is to use a combination of
++The most explicit way to describe disks is to use a combination of
+ ``-device`` to specify the hardware device and ``-blockdev`` to
+ describe the backend. The device defines what the guest sees and the
+-backend describes how QEMU handles the data.
++backend describes how QEMU handles the data. It is the only guaranteed
++stable interface for describing block devices and as such is
++recommended for management tools and scripting.
++
++The ``-drive`` option combines the device and backend into a single
++command line option which is a more human friendly. There is however no
++interface stability guarantee although some older board models still
++need updating to work with the modern blockdev forms.
++
++Older options like ``-hda`` are essentially macros which expand into
++``-drive`` options for various drive interfaces. The original forms
++bake in a lot of assumptions from the days when QEMU was emulating a
++legacy PC, they are not recommended for modern configurations.
+
+ ERST
+
+@@ -1636,6 +1648,14 @@ SRST
+ the raw disk image you use is not written back. You can however
+ force the write back by pressing C-a s (see the :ref:`disk images`
+ chapter in the System Emulation Users Guide).
++
++ .. warning::
++ snapshot is incompatible with ``-blockdev`` (instead use qemu-img
++ to manually create snapshot images to attach to your blockdev).
++ If you have mixed ``-blockdev`` and ``-drive`` declarations you
++ can use the 'snapshot' property on your drive declarations
++ instead of this global option.
++
+ ERST
+
+ DEF("fsdev", HAS_ARG, QEMU_OPTION_fsdev,
+diff --git a/target/arm/kvm.c b/target/arm/kvm.c
+index f022c644d2..84da49332c 100644
+--- a/target/arm/kvm.c
++++ b/target/arm/kvm.c
+@@ -280,6 +280,8 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
+ }
+ }
+
++ kvm_arm_init_debug(s);
++
+ return ret;
+ }
+
+diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
+index 1197253d12..810db33ccb 100644
+--- a/target/arm/kvm64.c
++++ b/target/arm/kvm64.c
+@@ -74,24 +74,16 @@ GArray *hw_breakpoints, *hw_watchpoints;
+ #define get_hw_bp(i) (&g_array_index(hw_breakpoints, HWBreakpoint, i))
+ #define get_hw_wp(i) (&g_array_index(hw_watchpoints, HWWatchpoint, i))
+
+-/**
+- * kvm_arm_init_debug() - check for guest debug capabilities
+- * @cs: CPUState
+- *
+- * kvm_check_extension returns the number of debug registers we have
+- * or 0 if we have none.
+- *
+- */
+-static void kvm_arm_init_debug(CPUState *cs)
++void kvm_arm_init_debug(KVMState *s)
+ {
+- have_guest_debug = kvm_check_extension(cs->kvm_state,
++ have_guest_debug = kvm_check_extension(s,
+ KVM_CAP_SET_GUEST_DEBUG);
+
+- max_hw_wps = kvm_check_extension(cs->kvm_state, KVM_CAP_GUEST_DEBUG_HW_WPS);
++ max_hw_wps = kvm_check_extension(s, KVM_CAP_GUEST_DEBUG_HW_WPS);
+ hw_watchpoints = g_array_sized_new(true, true,
+ sizeof(HWWatchpoint), max_hw_wps);
+
+- max_hw_bps = kvm_check_extension(cs->kvm_state, KVM_CAP_GUEST_DEBUG_HW_BPS);
++ max_hw_bps = kvm_check_extension(s, KVM_CAP_GUEST_DEBUG_HW_BPS);
+ hw_breakpoints = g_array_sized_new(true, true,
+ sizeof(HWBreakpoint), max_hw_bps);
+ return;
+@@ -920,8 +912,6 @@ int kvm_arch_init_vcpu(CPUState *cs)
+ }
+ cpu->mp_affinity = mpidr & ARM64_AFFINITY_MASK;
+
+- kvm_arm_init_debug(cs);
+-
+ /* Check whether user space can specify guest syndrome value */
+ kvm_arm_init_serror_injection(cs);
+
+diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
+index 99017b635c..330fbe5c72 100644
+--- a/target/arm/kvm_arm.h
++++ b/target/arm/kvm_arm.h
+@@ -18,6 +18,14 @@
+ #define KVM_ARM_VGIC_V2 (1 << 0)
+ #define KVM_ARM_VGIC_V3 (1 << 1)
+
++/**
++ * kvm_arm_init_debug() - initialize guest debug capabilities
++ * @s: KVMState
++ *
++ * Should be called only once before using guest debug capabilities.
++ */
++void kvm_arm_init_debug(KVMState *s);
++
+ /**
+ * kvm_arm_vcpu_init:
+ * @cs: CPUState
+diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
+index 521fc9b969..27838fb6e2 100644
+--- a/target/arm/sve_helper.c
++++ b/target/arm/sve_helper.c
+@@ -6726,6 +6726,7 @@ void sve_ldff1_z(CPUARMState *env, void *vd, uint64_t *vg, void *vm,
+ intptr_t reg_off;
+ SVEHostPage info;
+ target_ulong addr, in_page;
++ ARMVectorReg scratch;
+
+ /* Skip to the first true predicate. */
+ reg_off = find_next_active(vg, 0, reg_max, esz);
+@@ -6735,6 +6736,11 @@ void sve_ldff1_z(CPUARMState *env, void *vd, uint64_t *vg, void *vm,
+ return;
+ }
+
++ /* Protect against overlap between vd and vm. */
++ if (unlikely(vd == vm)) {
++ vm = memcpy(&scratch, vm, reg_max);
++ }
++
+ /*
+ * Probe the first element, allowing faults.
+ */
+diff --git a/target/arm/translate-a32.h b/target/arm/translate-a32.h
+index 5339c22f1e..99eea85fa8 100644
+--- a/target/arm/translate-a32.h
++++ b/target/arm/translate-a32.h
+@@ -61,6 +61,13 @@ static inline TCGv_i32 load_cpu_offset(int offset)
+
+ #define load_cpu_field(name) load_cpu_offset(offsetof(CPUARMState, name))
+
++/* Load from the low half of a 64-bit field to a TCGv_i32 */
++#define load_cpu_field_low32(name) \
++ ({ \
++ QEMU_BUILD_BUG_ON(sizeof_field(CPUARMState, name) != 8); \
++ load_cpu_offset(offsetoflow32(CPUARMState, name)); \
++ })
++
+ void store_cpu_offset(TCGv_i32 var, int offset, int size);
+
+ #define store_cpu_field(var, name) \
+diff --git a/target/arm/translate.c b/target/arm/translate.c
+index 1dcaefb8e7..a06da05640 100644
+--- a/target/arm/translate.c
++++ b/target/arm/translate.c
+@@ -2886,7 +2886,7 @@ static bool msr_banked_access_decode(DisasContext *s, int r, int sysm, int rn,
+ if (arm_dc_feature(s, ARM_FEATURE_AARCH64) &&
+ dc_isar_feature(aa64_sel2, s)) {
+ /* Target EL is EL<3 minus SCR_EL3.EEL2> */
+- tcg_el = load_cpu_field(cp15.scr_el3);
++ tcg_el = load_cpu_field_low32(cp15.scr_el3);
+ tcg_gen_sextract_i32(tcg_el, tcg_el, ctz32(SCR_EEL2), 1);
+ tcg_gen_addi_i32(tcg_el, tcg_el, 3);
+ } else {
+@@ -6558,7 +6558,7 @@ static bool trans_ERET(DisasContext *s, arg_ERET *a)
+ }
+ if (s->current_el == 2) {
+ /* ERET from Hyp uses ELR_Hyp, not LR */
+- tmp = load_cpu_field(elr_el[2]);
++ tmp = load_cpu_field_low32(elr_el[2]);
+ } else {
+ tmp = load_reg(s, 14);
+ }
+diff --git a/target/i386/cpu.c b/target/i386/cpu.c
+index 22b681ca37..0f71ff9fea 100644
+--- a/target/i386/cpu.c
++++ b/target/i386/cpu.c
+@@ -5584,8 +5584,8 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
+ } else {
+ *eax &= env->features[FEAT_SGX_12_1_EAX];
+ *ebx &= 0; /* ebx reserve */
+- *ecx &= env->features[FEAT_XSAVE_XSS_LO];
+- *edx &= env->features[FEAT_XSAVE_XSS_HI];
++ *ecx &= env->features[FEAT_XSAVE_XCR0_LO];
++ *edx &= env->features[FEAT_XSAVE_XCR0_HI];
+
+ /* FP and SSE are always allowed regardless of XSAVE/XCR0. */
+ *ecx |= XSTATE_FP_MASK | XSTATE_SSE_MASK;
+diff --git a/target/i386/ops_sse.h b/target/i386/ops_sse.h
+index 3cbc36a59d..44c1e70093 100644
+--- a/target/i386/ops_sse.h
++++ b/target/i386/ops_sse.h
+@@ -2493,6 +2493,14 @@ void helper_vpermdq_ymm(Reg *d, Reg *v, Reg *s, uint32_t order)
+ d->Q(1) = r1;
+ d->Q(2) = r2;
+ d->Q(3) = r3;
++ if (order & 0x8) {
++ d->Q(0) = 0;
++ d->Q(1) = 0;
++ }
++ if (order & 0x80) {
++ d->Q(2) = 0;
++ d->Q(3) = 0;
++ }
+ }
+
+ void helper_vpermq_ymm(Reg *d, Reg *s, uint32_t order)
+diff --git a/target/i386/tcg/decode-new.c.inc b/target/i386/tcg/decode-new.c.inc
+index 80c579164f..c2ee712561 100644
+--- a/target/i386/tcg/decode-new.c.inc
++++ b/target/i386/tcg/decode-new.c.inc
+@@ -782,6 +782,17 @@ static void decode_0F2D(DisasContext *s, CPUX86State *env, X86OpEntry *entry, ui
+ *entry = *decode_by_prefix(s, opcodes_0F2D);
+ }
+
++static void decode_VxCOMISx(DisasContext *s, CPUX86State *env, X86OpEntry *entry, uint8_t *b)
++{
++ /*
++ * VUCOMISx and VCOMISx are different and use no-prefix and 0x66 for SS and SD
++ * respectively. Scalar values usually are associated with 0xF2 and 0xF3, for
++ * which X86_VEX_REPScalar exists, but here it has to be decoded by hand.
++ */
++ entry->s1 = entry->s2 = (s->prefix & PREFIX_DATA ? X86_SIZE_sd : X86_SIZE_ss);
++ entry->gen = (*b == 0x2E ? gen_VUCOMI : gen_VCOMI);
++}
++
+ static void decode_sse_unary(DisasContext *s, CPUX86State *env, X86OpEntry *entry, uint8_t *b)
+ {
+ if (!(s->prefix & (PREFIX_REPZ | PREFIX_REPNZ))) {
+@@ -870,8 +881,8 @@ static const X86OpEntry opcodes_0F[256] = {
+ [0x2B] = X86_OP_GROUP0(0F2B),
+ [0x2C] = X86_OP_GROUP0(0F2C),
+ [0x2D] = X86_OP_GROUP0(0F2D),
+- [0x2E] = X86_OP_ENTRY3(VUCOMI, None,None, V,x, W,x, vex4 p_00_66),
+- [0x2F] = X86_OP_ENTRY3(VCOMI, None,None, V,x, W,x, vex4 p_00_66),
++ [0x2E] = X86_OP_GROUP3(VxCOMISx, None,None, V,x, W,x, vex3 p_00_66), /* VUCOMISS/SD */
++ [0x2F] = X86_OP_GROUP3(VxCOMISx, None,None, V,x, W,x, vex3 p_00_66), /* VCOMISS/SD */
+
+ [0x38] = X86_OP_GROUP0(0F38),
+ [0x3a] = X86_OP_GROUP0(0F3A),
+diff --git a/target/i386/tcg/emit.c.inc b/target/i386/tcg/emit.c.inc
+index 7296f3952c..5d31fce65d 100644
+--- a/target/i386/tcg/emit.c.inc
++++ b/target/i386/tcg/emit.c.inc
+@@ -2288,7 +2288,7 @@ static void gen_VZEROALL(DisasContext *s, CPUX86State *env, X86DecodedInsn *deco
+ {
+ TCGv_ptr ptr = tcg_temp_new_ptr();
+
+- tcg_gen_addi_ptr(ptr, cpu_env, offsetof(CPUX86State, xmm_t0));
++ tcg_gen_addi_ptr(ptr, cpu_env, offsetof(CPUX86State, xmm_regs));
+ gen_helper_memset(ptr, ptr, tcg_constant_i32(0),
+ tcg_constant_ptr(CPU_NB_REGS * sizeof(ZMMReg)));
+ tcg_temp_free_ptr(ptr);
+diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
+index 94adcb766b..30bc2e6adf 100644
+--- a/target/ppc/excp_helper.c
++++ b/target/ppc/excp_helper.c
+@@ -2631,7 +2631,7 @@ void helper_scv(CPUPPCState *env, uint32_t lev)
+ }
+ }
+
+-void helper_pminsn(CPUPPCState *env, powerpc_pm_insn_t insn)
++void helper_pminsn(CPUPPCState *env, uint32_t insn)
+ {
+ CPUState *cs;
+
+diff --git a/target/ppc/translate/vmx-impl.c.inc b/target/ppc/translate/vmx-impl.c.inc
+index 7741f2eb49..764b76dcc6 100644
+--- a/target/ppc/translate/vmx-impl.c.inc
++++ b/target/ppc/translate/vmx-impl.c.inc
+@@ -2231,7 +2231,7 @@ static bool trans_VEXPANDQM(DisasContext *ctx, arg_VX_tb *a)
+ static bool do_vextractm(DisasContext *ctx, arg_VX_tb *a, unsigned vece)
+ {
+ const uint64_t elem_width = 8 << vece, elem_count_half = 8 >> vece,
+- mask = dup_const(vece, 1 << (elem_width - 1));
++ mask = dup_const(vece, 1ULL << (elem_width - 1));
+ uint64_t i, j;
+ TCGv_i64 lo, hi, t0, t1;
+
+diff --git a/target/riscv/insn_trans/trans_privileged.c.inc b/target/riscv/insn_trans/trans_privileged.c.inc
+index 3281408a87..74e2894462 100644
+--- a/target/riscv/insn_trans/trans_privileged.c.inc
++++ b/target/riscv/insn_trans/trans_privileged.c.inc
+@@ -77,6 +77,9 @@ static bool trans_sret(DisasContext *ctx, arg_sret *a)
+ #ifndef CONFIG_USER_ONLY
+ if (has_ext(ctx, RVS)) {
+ decode_save_opc(ctx);
++ if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
++ gen_io_start();
++ }
+ gen_helper_sret(cpu_pc, cpu_env);
+ tcg_gen_exit_tb(NULL, 0); /* no chaining */
+ ctx->base.is_jmp = DISAS_NORETURN;
+@@ -93,6 +96,9 @@ static bool trans_mret(DisasContext *ctx, arg_mret *a)
+ {
+ #ifndef CONFIG_USER_ONLY
+ decode_save_opc(ctx);
++ if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
++ gen_io_start();
++ }
+ gen_helper_mret(cpu_pc, cpu_env);
+ tcg_gen_exit_tb(NULL, 0); /* no chaining */
+ ctx->base.is_jmp = DISAS_NORETURN;
+diff --git a/target/s390x/tcg/insn-data.h.inc b/target/s390x/tcg/insn-data.h.inc
+index 2a5fc99818..13ffdda4da 100644
+--- a/target/s390x/tcg/insn-data.h.inc
++++ b/target/s390x/tcg/insn-data.h.inc
+@@ -606,7 +606,7 @@
+ F(0xed04, LDEB, RXE, Z, 0, m2_32u, new, f1, ldeb, 0, IF_BFP)
+ F(0xed05, LXDB, RXE, Z, 0, m2_64, new_P, x1, lxdb, 0, IF_BFP)
+ F(0xed06, LXEB, RXE, Z, 0, m2_32u, new_P, x1, lxeb, 0, IF_BFP)
+- F(0xb324, LDER, RXE, Z, 0, e2, new, f1, lde, 0, IF_AFP1)
++ F(0xb324, LDER, RRE, Z, 0, e2, new, f1, lde, 0, IF_AFP1)
+ F(0xed24, LDE, RXE, Z, 0, m2_32u, new, f1, lde, 0, IF_AFP1)
+ /* LOAD ROUNDED */
+ F(0xb344, LEDBR, RRF_e, Z, 0, f2, new, e1, ledb, 0, IF_BFP)
+diff --git a/target/s390x/tcg/translate.c b/target/s390x/tcg/translate.c
+index e328aa5b97..0885bf2641 100644
+--- a/target/s390x/tcg/translate.c
++++ b/target/s390x/tcg/translate.c
+@@ -1585,18 +1585,51 @@ static DisasJumpType op_bal(DisasContext *s, DisasOps *o)
+ }
+ }
+
++/*
++ * Disassemble the target of a branch. The results are returned in a form
++ * suitable for passing into help_branch():
++ *
++ * - bool IS_IMM reflects whether the target is fixed or computed. Non-EXECUTEd
++ * branches, whose DisasContext *S contains the relative immediate field RI,
++ * are considered fixed. All the other branches are considered computed.
++ * - int IMM is the value of RI.
++ * - TCGv_i64 CDEST is the address of the computed target.
++ */
++#define disas_jdest(s, ri, is_imm, imm, cdest) do { \
++ if (have_field(s, ri)) { \
++ if (unlikely(s->ex_value)) { \
++ cdest = tcg_temp_new_i64(); \
++ tcg_gen_ld_i64(cdest, cpu_env, offsetof(CPUS390XState, ex_target));\
++ tcg_gen_addi_i64(cdest, cdest, (int64_t)get_field(s, ri) * 2); \
++ is_imm = false; \
++ } else { \
++ is_imm = true; \
++ } \
++ } else { \
++ is_imm = false; \
++ } \
++ imm = is_imm ? get_field(s, ri) : 0; \
++} while (false)
++
+ static DisasJumpType op_basi(DisasContext *s, DisasOps *o)
+ {
++ DisasCompare c;
++ bool is_imm;
++ int imm;
++
+ pc_to_link_info(o->out, s, s->pc_tmp);
+- return help_goto_direct(s, s->base.pc_next + (int64_t)get_field(s, i2) * 2);
++
++ disas_jdest(s, i2, is_imm, imm, o->in2);
++ disas_jcc(s, &c, 0xf);
++ return help_branch(s, &c, is_imm, imm, o->in2);
+ }
+
+ static DisasJumpType op_bc(DisasContext *s, DisasOps *o)
+ {
+ int m1 = get_field(s, m1);
+- bool is_imm = have_field(s, i2);
+- int imm = is_imm ? get_field(s, i2) : 0;
+ DisasCompare c;
++ bool is_imm;
++ int imm;
+
+ /* BCR with R2 = 0 causes no branching */
+ if (have_field(s, r2) && get_field(s, r2) == 0) {
+@@ -1613,6 +1646,7 @@ static DisasJumpType op_bc(DisasContext *s, DisasOps *o)
+ return DISAS_NEXT;
+ }
+
++ disas_jdest(s, i2, is_imm, imm, o->in2);
+ disas_jcc(s, &c, m1);
+ return help_branch(s, &c, is_imm, imm, o->in2);
+ }
+@@ -1620,10 +1654,10 @@ static DisasJumpType op_bc(DisasContext *s, DisasOps *o)
+ static DisasJumpType op_bct32(DisasContext *s, DisasOps *o)
+ {
+ int r1 = get_field(s, r1);
+- bool is_imm = have_field(s, i2);
+- int imm = is_imm ? get_field(s, i2) : 0;
+ DisasCompare c;
++ bool is_imm;
+ TCGv_i64 t;
++ int imm;
+
+ c.cond = TCG_COND_NE;
+ c.is_64 = false;
+@@ -1638,6 +1672,7 @@ static DisasJumpType op_bct32(DisasContext *s, DisasOps *o)
+ tcg_gen_extrl_i64_i32(c.u.s32.a, t);
+ tcg_temp_free_i64(t);
+
++ disas_jdest(s, i2, is_imm, imm, o->in2);
+ return help_branch(s, &c, is_imm, imm, o->in2);
+ }
+
+@@ -1668,9 +1703,9 @@ static DisasJumpType op_bcth(DisasContext *s, DisasOps *o)
+ static DisasJumpType op_bct64(DisasContext *s, DisasOps *o)
+ {
+ int r1 = get_field(s, r1);
+- bool is_imm = have_field(s, i2);
+- int imm = is_imm ? get_field(s, i2) : 0;
+ DisasCompare c;
++ bool is_imm;
++ int imm;
+
+ c.cond = TCG_COND_NE;
+ c.is_64 = true;
+@@ -1681,6 +1716,7 @@ static DisasJumpType op_bct64(DisasContext *s, DisasOps *o)
+ c.u.s64.a = regs[r1];
+ c.u.s64.b = tcg_const_i64(0);
+
++ disas_jdest(s, i2, is_imm, imm, o->in2);
+ return help_branch(s, &c, is_imm, imm, o->in2);
+ }
+
+@@ -1688,10 +1724,10 @@ static DisasJumpType op_bx32(DisasContext *s, DisasOps *o)
+ {
+ int r1 = get_field(s, r1);
+ int r3 = get_field(s, r3);
+- bool is_imm = have_field(s, i2);
+- int imm = is_imm ? get_field(s, i2) : 0;
+ DisasCompare c;
++ bool is_imm;
+ TCGv_i64 t;
++ int imm;
+
+ c.cond = (s->insn->data ? TCG_COND_LE : TCG_COND_GT);
+ c.is_64 = false;
+@@ -1707,6 +1743,7 @@ static DisasJumpType op_bx32(DisasContext *s, DisasOps *o)
+ store_reg32_i64(r1, t);
+ tcg_temp_free_i64(t);
+
++ disas_jdest(s, i2, is_imm, imm, o->in2);
+ return help_branch(s, &c, is_imm, imm, o->in2);
+ }
+
+@@ -1714,9 +1751,9 @@ static DisasJumpType op_bx64(DisasContext *s, DisasOps *o)
+ {
+ int r1 = get_field(s, r1);
+ int r3 = get_field(s, r3);
+- bool is_imm = have_field(s, i2);
+- int imm = is_imm ? get_field(s, i2) : 0;
+ DisasCompare c;
++ bool is_imm;
++ int imm;
+
+ c.cond = (s->insn->data ? TCG_COND_LE : TCG_COND_GT);
+ c.is_64 = true;
+@@ -1733,6 +1770,7 @@ static DisasJumpType op_bx64(DisasContext *s, DisasOps *o)
+ c.u.s64.a = regs[r1];
+ c.g1 = true;
+
++ disas_jdest(s, i2, is_imm, imm, o->in2);
+ return help_branch(s, &c, is_imm, imm, o->in2);
+ }
+
+@@ -1750,10 +1788,9 @@ static DisasJumpType op_cj(DisasContext *s, DisasOps *o)
+ c.u.s64.a = o->in1;
+ c.u.s64.b = o->in2;
+
+- is_imm = have_field(s, i4);
+- if (is_imm) {
+- imm = get_field(s, i4);
+- } else {
++ o->out = NULL;
++ disas_jdest(s, i4, is_imm, imm, o->out);
++ if (!is_imm && !o->out) {
+ imm = 0;
+ o->out = get_address(s, 0, get_field(s, b4),
+ get_field(s, d4));
+@@ -5964,15 +6001,13 @@ static void in2_a2(DisasContext *s, DisasOps *o)
+
+ static TCGv gen_ri2(DisasContext *s)
+ {
+- int64_t delta = (int64_t)get_field(s, i2) * 2;
+- TCGv ri2;
++ TCGv ri2 = NULL;
++ bool is_imm;
++ int imm;
+
+- if (unlikely(s->ex_value)) {
+- ri2 = tcg_temp_new_i64();
+- tcg_gen_ld_i64(ri2, cpu_env, offsetof(CPUS390XState, ex_target));
+- tcg_gen_addi_i64(ri2, ri2, delta);
+- } else {
+- ri2 = tcg_constant_i64(s->base.pc_next + delta);
++ disas_jdest(s, i2, is_imm, imm, ri2);
++ if (is_imm) {
++ ri2 = tcg_constant_i64(s->base.pc_next + imm * 2);
+ }
+
+ return ri2;
+diff --git a/tests/docker/dockerfiles/debian-xtensa-cross.docker b/tests/docker/dockerfiles/debian-xtensa-cross.docker
+index 2f11b3b7bc..aebfabdd6e 100644
+--- a/tests/docker/dockerfiles/debian-xtensa-cross.docker
++++ b/tests/docker/dockerfiles/debian-xtensa-cross.docker
+@@ -5,7 +5,7 @@
+ # using a prebuilt toolchains for Xtensa cores from:
+ # https://github.com/foss-xtensa/toolchain/releases
+ #
+-FROM docker.io/library/debian:stretch-slim
++FROM docker.io/library/debian:11-slim
+
+ RUN apt-get update && \
+ DEBIAN_FRONTEND=noninteractive apt install -yy eatmydata && \
+diff --git a/tests/qtest/fuzz-lsi53c895a-test.c b/tests/qtest/fuzz-lsi53c895a-test.c
+index 392a7ae7ed..9b007def26 100644
+--- a/tests/qtest/fuzz-lsi53c895a-test.c
++++ b/tests/qtest/fuzz-lsi53c895a-test.c
+@@ -8,6 +8,36 @@
+ #include "qemu/osdep.h"
+ #include "libqtest.h"
+
++/*
++ * This used to trigger a DMA reentrancy issue
++ * leading to memory corruption bugs like stack
++ * overflow or use-after-free
++ * https://gitlab.com/qemu-project/qemu/-/issues/1563
++ */
++static void test_lsi_dma_reentrancy(void)
++{
++ QTestState *s;
++
++ s = qtest_init("-M q35 -m 512M -nodefaults "
++ "-blockdev driver=null-co,node-name=null0 "
++ "-device lsi53c810 -device scsi-cd,drive=null0");
++
++ qtest_outl(s, 0xcf8, 0x80000804); /* PCI Command Register */
++ qtest_outw(s, 0xcfc, 0x7); /* Enables accesses */
++ qtest_outl(s, 0xcf8, 0x80000814); /* Memory Bar 1 */
++ qtest_outl(s, 0xcfc, 0xff100000); /* Set MMIO Address*/
++ qtest_outl(s, 0xcf8, 0x80000818); /* Memory Bar 2 */
++ qtest_outl(s, 0xcfc, 0xff000000); /* Set RAM Address*/
++ qtest_writel(s, 0xff000000, 0xc0000024);
++ qtest_writel(s, 0xff000114, 0x00000080);
++ qtest_writel(s, 0xff00012c, 0xff000000);
++ qtest_writel(s, 0xff000004, 0xff000114);
++ qtest_writel(s, 0xff000008, 0xff100014);
++ qtest_writel(s, 0xff10002f, 0x000000ff);
++
++ qtest_quit(s);
++}
++
+ /*
+ * This used to trigger a UAF in lsi_do_msgout()
+ * https://gitlab.com/qemu-project/qemu/-/issues/972
+@@ -120,5 +150,8 @@ int main(int argc, char **argv)
+ qtest_add_func("fuzz/lsi53c895a/lsi_do_msgout_cancel_req",
+ test_lsi_do_msgout_cancel_req);
+
++ qtest_add_func("fuzz/lsi53c895a/lsi_dma_reentrancy",
++ test_lsi_dma_reentrancy);
++
+ return g_test_run();
+ }
+diff --git a/ui/console.c b/ui/console.c
+index 3c0d9b061a..646202214a 100644
+--- a/ui/console.c
++++ b/ui/console.c
+@@ -307,7 +307,7 @@ static bool png_save(int fd, pixman_image_t *image, Error **errp)
+ png_struct *png_ptr;
+ png_info *info_ptr;
+ g_autoptr(pixman_image_t) linebuf =
+- qemu_pixman_linebuf_create(PIXMAN_a8r8g8b8, width);
++ qemu_pixman_linebuf_create(PIXMAN_BE_r8g8b8, width);
+ uint8_t *buf = (uint8_t *)pixman_image_get_data(linebuf);
+ FILE *f = fdopen(fd, "wb");
+ int y;
+@@ -337,7 +337,7 @@ static bool png_save(int fd, pixman_image_t *image, Error **errp)
+ png_init_io(png_ptr, f);
+
+ png_set_IHDR(png_ptr, info_ptr, width, height, 8,
+- PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE,
++ PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
+ PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
+
+ png_write_info(png_ptr, info_ptr);
+diff --git a/ui/vnc.c b/ui/vnc.c
+index 88f55cbf3c..1856d57380 100644
+--- a/ui/vnc.c
++++ b/ui/vnc.c
+@@ -3765,7 +3765,7 @@ static int vnc_display_get_address(const char *addrstr,
+
+ addr->type = SOCKET_ADDRESS_TYPE_INET;
+ inet = &addr->u.inet;
+- if (addrstr[0] == '[' && addrstr[hostlen - 1] == ']') {
++ if (hostlen && addrstr[0] == '[' && addrstr[hostlen - 1] == ']') {
+ inet->host = g_strndup(addrstr + 1, hostlen - 2);
+ } else {
+ inet->host = g_strndup(addrstr, hostlen);
+diff --git a/util/async.c b/util/async.c
+index 63434ddae4..f449c3444e 100644
+--- a/util/async.c
++++ b/util/async.c
+@@ -158,7 +158,21 @@ int aio_bh_poll(AioContext *ctx)
+ int ret = 0;
+
+ QSLIST_MOVE_ATOMIC(&slice.bh_list, &ctx->bh_list);
++
++ /*
++ * GCC13 [-Werror=dangling-pointer=] complains that the local variable
++ * 'slice' is being stored in the global 'ctx->bh_slice_list' but the
++ * list is emptied before this function returns.
++ */
++#if !defined(__clang__)
++#pragma GCC diagnostic push
++#pragma GCC diagnostic ignored "-Wpragmas"
++#pragma GCC diagnostic ignored "-Wdangling-pointer="
++#endif
+ QSIMPLEQ_INSERT_TAIL(&ctx->bh_slice_list, &slice, next);
++#if !defined(__clang__)
++#pragma GCC diagnostic pop
++#endif
+
+ while ((s = QSIMPLEQ_FIRST(&ctx->bh_slice_list))) {
+ QEMUBH *bh;
+diff --git a/util/vfio-helpers.c b/util/vfio-helpers.c
+index 0d1520caac..4670867e1f 100644
+--- a/util/vfio-helpers.c
++++ b/util/vfio-helpers.c
+@@ -106,15 +106,17 @@ struct QEMUVFIOState {
+ */
+ static char *sysfs_find_group_file(const char *device, Error **errp)
+ {
++ g_autoptr(GError) gerr = NULL;
+ char *sysfs_link;
+ char *sysfs_group;
+ char *p;
+ char *path = NULL;
+
+ sysfs_link = g_strdup_printf("/sys/bus/pci/devices/%s/iommu_group", device);
+- sysfs_group = g_malloc0(PATH_MAX);
+- if (readlink(sysfs_link, sysfs_group, PATH_MAX - 1) == -1) {
+- error_setg_errno(errp, errno, "Failed to find iommu group sysfs path");
++ sysfs_group = g_file_read_link(sysfs_link, &gerr);
++ if (gerr) {
++ error_setg(errp, "Failed to find iommu group sysfs path: %s",
++ gerr->message);
+ goto out;
+ }
+ p = strrchr(sysfs_group, '/');
diff --git a/debian/patches/v7.2.4.diff b/debian/patches/v7.2.4.diff
new file mode 100644
index 00000000..e2eeed5f
--- /dev/null
+++ b/debian/patches/v7.2.4.diff
@@ -0,0 +1,1420 @@
+diff --git a/.gitlab-ci.d/buildtest.yml b/.gitlab-ci.d/buildtest.yml
+index d21b4a1fd4..10886bb414 100644
+--- a/.gitlab-ci.d/buildtest.yml
++++ b/.gitlab-ci.d/buildtest.yml
+@@ -109,8 +109,8 @@ crash-test-debian:
+ IMAGE: debian-amd64
+ script:
+ - cd build
+- - make check-venv
+- - tests/venv/bin/python3 scripts/device-crash-test -q ./qemu-system-i386
++ - make NINJA=":" check-venv
++ - tests/venv/bin/python3 scripts/device-crash-test -q --tcg-only ./qemu-system-i386
+
+ build-system-fedora:
+ extends: .native_build_job_template
+@@ -155,7 +155,7 @@ crash-test-fedora:
+ IMAGE: fedora
+ script:
+ - cd build
+- - make check-venv
++ - make NINJA=":" check-venv
+ - tests/venv/bin/python3 scripts/device-crash-test -q ./qemu-system-ppc
+ - tests/venv/bin/python3 scripts/device-crash-test -q ./qemu-system-riscv32
+
+diff --git a/VERSION b/VERSION
+index 429dc57af3..2bbaead448 100644
+--- a/VERSION
++++ b/VERSION
+@@ -1 +1 @@
+-7.2.3
++7.2.4
+diff --git a/docs/system/multi-process.rst b/docs/system/multi-process.rst
+index 210531ee17..1b8852c27c 100644
+--- a/docs/system/multi-process.rst
++++ b/docs/system/multi-process.rst
+@@ -2,7 +2,7 @@ Multi-process QEMU
+ ==================
+
+ This document describes how to configure and use multi-process qemu.
+-For the design document refer to docs/devel/qemu-multiprocess.
++For the design document refer to docs/devel/multi-process.rst.
+
+ 1) Configuration
+ ----------------
+diff --git a/fsdev/virtfs-proxy-helper.c b/fsdev/virtfs-proxy-helper.c
+index 5cafcd7703..d9511f429c 100644
+--- a/fsdev/virtfs-proxy-helper.c
++++ b/fsdev/virtfs-proxy-helper.c
+@@ -26,6 +26,7 @@
+ #include "qemu/xattr.h"
+ #include "9p-iov-marshal.h"
+ #include "hw/9pfs/9p-proxy.h"
++#include "hw/9pfs/9p-util.h"
+ #include "fsdev/9p-iov-marshal.h"
+
+ #define PROGNAME "virtfs-proxy-helper"
+@@ -338,6 +339,28 @@ static void resetugid(int suid, int sgid)
+ }
+ }
+
++/*
++ * Open regular file or directory. Attempts to open any special file are
++ * rejected.
++ *
++ * returns file descriptor or -1 on error
++ */
++static int open_regular(const char *pathname, int flags, mode_t mode)
++{
++ int fd;
++
++ fd = open(pathname, flags, mode);
++ if (fd < 0) {
++ return fd;
++ }
++
++ if (close_if_special_file(fd) < 0) {
++ return -1;
++ }
++
++ return fd;
++}
++
+ /*
+ * send response in two parts
+ * 1) ProxyHeader
+@@ -682,7 +705,7 @@ static int do_create(struct iovec *iovec)
+ if (ret < 0) {
+ goto unmarshal_err_out;
+ }
+- ret = open(path.data, flags, mode);
++ ret = open_regular(path.data, flags, mode);
+ if (ret < 0) {
+ ret = -errno;
+ }
+@@ -707,7 +730,7 @@ static int do_open(struct iovec *iovec)
+ if (ret < 0) {
+ goto err_out;
+ }
+- ret = open(path.data, flags);
++ ret = open_regular(path.data, flags, 0);
+ if (ret < 0) {
+ ret = -errno;
+ }
+diff --git a/hw/9pfs/9p-util.h b/hw/9pfs/9p-util.h
+index c3526144c9..6b44e5f7a4 100644
+--- a/hw/9pfs/9p-util.h
++++ b/hw/9pfs/9p-util.h
+@@ -13,6 +13,8 @@
+ #ifndef QEMU_9P_UTIL_H
+ #define QEMU_9P_UTIL_H
+
++#include "qemu/error-report.h"
++
+ #ifdef O_PATH
+ #define O_PATH_9P_UTIL O_PATH
+ #else
+@@ -112,6 +114,38 @@ static inline void close_preserve_errno(int fd)
+ errno = serrno;
+ }
+
++/**
++ * close_if_special_file() - Close @fd if neither regular file nor directory.
++ *
++ * @fd: file descriptor of open file
++ * Return: 0 on regular file or directory, -1 otherwise
++ *
++ * CVE-2023-2861: Prohibit opening any special file directly on host
++ * (especially device files), as a compromised client could potentially gain
++ * access outside exported tree under certain, unsafe setups. We expect
++ * client to handle I/O on special files exclusively on guest side.
++ */
++static inline int close_if_special_file(int fd)
++{
++ struct stat stbuf;
++
++ if (fstat(fd, &stbuf) < 0) {
++ close_preserve_errno(fd);
++ return -1;
++ }
++ if (!S_ISREG(stbuf.st_mode) && !S_ISDIR(stbuf.st_mode)) {
++ error_report_once(
++ "9p: broken or compromised client detected; attempt to open "
++ "special file (i.e. neither regular file, nor directory)"
++ );
++ close(fd);
++ errno = ENXIO;
++ return -1;
++ }
++
++ return 0;
++}
++
+ static inline int openat_dir(int dirfd, const char *name)
+ {
+ return openat(dirfd, name,
+@@ -146,6 +180,10 @@ again:
+ return -1;
+ }
+
++ if (close_if_special_file(fd) < 0) {
++ return -1;
++ }
++
+ serrno = errno;
+ /* O_NONBLOCK was only needed to open the file. Let's drop it. We don't
+ * do that with O_PATH since fcntl(F_SETFL) isn't supported, and openat()
+diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
+index 335cfc417d..5905a33015 100644
+--- a/hw/arm/xlnx-zynqmp.c
++++ b/hw/arm/xlnx-zynqmp.c
+@@ -213,7 +213,7 @@ static void xlnx_zynqmp_create_rpu(MachineState *ms, XlnxZynqMPState *s,
+ const char *boot_cpu, Error **errp)
+ {
+ int i;
+- int num_rpus = MIN(ms->smp.cpus - XLNX_ZYNQMP_NUM_APU_CPUS,
++ int num_rpus = MIN((int)(ms->smp.cpus - XLNX_ZYNQMP_NUM_APU_CPUS),
+ XLNX_ZYNQMP_NUM_RPU_CPUS);
+
+ if (num_rpus <= 0) {
+diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
+index 5e15c79b94..4e2e0dd53a 100644
+--- a/hw/display/virtio-gpu.c
++++ b/hw/display/virtio-gpu.c
+@@ -498,6 +498,8 @@ static void virtio_gpu_resource_flush(VirtIOGPU *g,
+ struct virtio_gpu_resource_flush rf;
+ struct virtio_gpu_scanout *scanout;
+ pixman_region16_t flush_region;
++ bool within_bounds = false;
++ bool update_submitted = false;
+ int i;
+
+ VIRTIO_GPU_FILL_CMD(rf);
+@@ -518,13 +520,28 @@ static void virtio_gpu_resource_flush(VirtIOGPU *g,
+ rf.r.x < scanout->x + scanout->width &&
+ rf.r.x + rf.r.width >= scanout->x &&
+ rf.r.y < scanout->y + scanout->height &&
+- rf.r.y + rf.r.height >= scanout->y &&
+- console_has_gl(scanout->con)) {
+- dpy_gl_update(scanout->con, 0, 0, scanout->width,
+- scanout->height);
++ rf.r.y + rf.r.height >= scanout->y) {
++ within_bounds = true;
++
++ if (console_has_gl(scanout->con)) {
++ dpy_gl_update(scanout->con, 0, 0, scanout->width,
++ scanout->height);
++ update_submitted = true;
++ }
+ }
+ }
+- return;
++
++ if (update_submitted) {
++ return;
++ }
++ if (!within_bounds) {
++ qemu_log_mask(LOG_GUEST_ERROR, "%s: flush bounds outside scanouts"
++ " bounds for flush %d: %d %d %d %d\n",
++ __func__, rf.resource_id, rf.r.x, rf.r.y,
++ rf.r.width, rf.r.height);
++ cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
++ return;
++ }
+ }
+
+ if (!res->blob &&
+diff --git a/hw/dma/xilinx_axidma.c b/hw/dma/xilinx_axidma.c
+index cbb8f0f169..99e50f65e2 100644
+--- a/hw/dma/xilinx_axidma.c
++++ b/hw/dma/xilinx_axidma.c
+@@ -168,6 +168,11 @@ static inline int stream_idle(struct Stream *s)
+ return !!(s->regs[R_DMASR] & DMASR_IDLE);
+ }
+
++static inline int stream_halted(struct Stream *s)
++{
++ return !!(s->regs[R_DMASR] & DMASR_HALTED);
++}
++
+ static void stream_reset(struct Stream *s)
+ {
+ s->regs[R_DMASR] = DMASR_HALTED; /* starts up halted. */
+@@ -269,7 +274,7 @@ static void stream_process_mem2s(struct Stream *s, StreamSink *tx_data_dev,
+ uint64_t addr;
+ bool eop;
+
+- if (!stream_running(s) || stream_idle(s)) {
++ if (!stream_running(s) || stream_idle(s) || stream_halted(s)) {
+ return;
+ }
+
+@@ -326,7 +331,7 @@ static size_t stream_process_s2mem(struct Stream *s, unsigned char *buf,
+ unsigned int rxlen;
+ size_t pos = 0;
+
+- if (!stream_running(s) || stream_idle(s)) {
++ if (!stream_running(s) || stream_idle(s) || stream_halted(s)) {
+ return 0;
+ }
+
+@@ -407,7 +412,7 @@ xilinx_axidma_data_stream_can_push(StreamSink *obj,
+ XilinxAXIDMAStreamSink *ds = XILINX_AXI_DMA_DATA_STREAM(obj);
+ struct Stream *s = &ds->dma->streams[1];
+
+- if (!stream_running(s) || stream_idle(s)) {
++ if (!stream_running(s) || stream_idle(s) || stream_halted(s)) {
+ ds->dma->notify = notify;
+ ds->dma->notify_opaque = notify_opaque;
+ return false;
+diff --git a/hw/hppa/machine.c b/hw/hppa/machine.c
+index de1cc7ab71..98a78b84b4 100644
+--- a/hw/hppa/machine.c
++++ b/hw/hppa/machine.c
+@@ -123,6 +123,7 @@ static FWCfgState *create_fw_cfg(MachineState *ms)
+ {
+ FWCfgState *fw_cfg;
+ uint64_t val;
++ const char qemu_version[] = QEMU_VERSION;
+
+ fw_cfg = fw_cfg_init_mem(FW_CFG_IO_BASE, FW_CFG_IO_BASE + 4);
+ fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, ms->smp.cpus);
+@@ -148,6 +149,10 @@ static FWCfgState *create_fw_cfg(MachineState *ms)
+ fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, ms->boot_config.order[0]);
+ qemu_register_boot_set(fw_cfg_boot_set, fw_cfg);
+
++ fw_cfg_add_file(fw_cfg, "/etc/qemu-version",
++ g_memdup(qemu_version, sizeof(qemu_version)),
++ sizeof(qemu_version));
++
+ return fw_cfg;
+ }
+
+@@ -418,10 +423,16 @@ static void hppa_machine_reset(MachineState *ms, ShutdownCause reason)
+
+ /* Start all CPUs at the firmware entry point.
+ * Monarch CPU will initialize firmware, secondary CPUs
+- * will enter a small idle look and wait for rendevouz. */
++ * will enter a small idle loop and wait for rendevouz. */
+ for (i = 0; i < smp_cpus; i++) {
+- cpu_set_pc(CPU(cpu[i]), firmware_entry);
++ CPUState *cs = CPU(cpu[i]);
++
++ cpu_set_pc(cs, firmware_entry);
++ cpu[i]->env.psw = PSW_Q;
+ cpu[i]->env.gr[5] = CPU_HPA + i * 0x1000;
++
++ cs->exception_index = -1;
++ cs->halted = 0;
+ }
+
+ /* already initialized by machine_hppa_init()? */
+diff --git a/hw/intc/allwinner-a10-pic.c b/hw/intc/allwinner-a10-pic.c
+index 4875e68ba6..d0bf8d545b 100644
+--- a/hw/intc/allwinner-a10-pic.c
++++ b/hw/intc/allwinner-a10-pic.c
+@@ -51,7 +51,7 @@ static void aw_a10_pic_set_irq(void *opaque, int irq, int level)
+ AwA10PICState *s = opaque;
+ uint32_t *pending_reg = &s->irq_pending[irq / 32];
+
+- *pending_reg = deposit32(*pending_reg, irq % 32, 1, level);
++ *pending_reg = deposit32(*pending_reg, irq % 32, 1, !!level);
+ aw_a10_pic_update(s);
+ }
+
+diff --git a/hw/misc/aspeed_hace.c b/hw/misc/aspeed_hace.c
+index ac21be306c..69175e972d 100644
+--- a/hw/misc/aspeed_hace.c
++++ b/hw/misc/aspeed_hace.c
+@@ -189,7 +189,7 @@ static void do_hash_operation(AspeedHACEState *s, int algo, bool sg_mode,
+ bool acc_mode)
+ {
+ struct iovec iov[ASPEED_HACE_MAX_SG];
+- g_autofree uint8_t *digest_buf;
++ g_autofree uint8_t *digest_buf = NULL;
+ size_t digest_len = 0;
+ int niov = 0;
+ int i;
+diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c
+index dc86c1c7db..fbdc48911e 100644
+--- a/hw/ppc/ppc.c
++++ b/hw/ppc/ppc.c
+@@ -806,6 +806,8 @@ static void __cpu_ppc_store_decr(PowerPCCPU *cpu, uint64_t *nextp,
+ int64_t signed_decr;
+
+ /* Truncate value to decr_width and sign extend for simplicity */
++ value = extract64(value, 0, nr_bits);
++ decr = extract64(decr, 0, nr_bits);
+ signed_value = sextract64(value, 0, nr_bits);
+ signed_decr = sextract64(decr, 0, nr_bits);
+
+diff --git a/hw/ppc/prep.c b/hw/ppc/prep.c
+index fcbe4c5837..ec8d9584fb 100644
+--- a/hw/ppc/prep.c
++++ b/hw/ppc/prep.c
+@@ -271,9 +271,11 @@ static void ibm_40p_init(MachineState *machine)
+ }
+
+ /* PCI -> ISA bridge */
+- i82378_dev = DEVICE(pci_create_simple(pci_bus, PCI_DEVFN(11, 0), "i82378"));
++ i82378_dev = DEVICE(pci_new(PCI_DEVFN(11, 0), "i82378"));
+ qdev_connect_gpio_out(i82378_dev, 0,
+ qdev_get_gpio_in(DEVICE(cpu), PPC6xx_INPUT_INT));
++ qdev_realize_and_unref(i82378_dev, BUS(pci_bus), &error_fatal);
++
+ sysbus_connect_irq(pcihost, 0, qdev_get_gpio_in(i82378_dev, 15));
+ isa_bus = ISA_BUS(qdev_get_child_bus(i82378_dev, "isa.0"));
+
+diff --git a/hw/remote/trace-events b/hw/remote/trace-events
+index c167b3c7a5..0d1b7d56a5 100644
+--- a/hw/remote/trace-events
++++ b/hw/remote/trace-events
+@@ -5,8 +5,8 @@ mpqemu_recv_io_error(int cmd, int size, int nfds) "failed to receive %d size %d,
+
+ # vfio-user-obj.c
+ vfu_prop(const char *prop, const char *val) "vfu: setting %s as %s"
+-vfu_cfg_read(uint32_t offset, uint32_t val) "vfu: cfg: 0x%u -> 0x%x"
+-vfu_cfg_write(uint32_t offset, uint32_t val) "vfu: cfg: 0x%u <- 0x%x"
++vfu_cfg_read(uint32_t offset, uint32_t val) "vfu: cfg: 0x%x -> 0x%x"
++vfu_cfg_write(uint32_t offset, uint32_t val) "vfu: cfg: 0x%x <- 0x%x"
+ vfu_dma_register(uint64_t gpa, size_t len) "vfu: registering GPA 0x%"PRIx64", %zu bytes"
+ vfu_dma_unregister(uint64_t gpa) "vfu: unregistering GPA 0x%"PRIx64""
+ vfu_bar_register(int i, uint64_t addr, uint64_t size) "vfu: BAR %d: addr 0x%"PRIx64" size 0x%"PRIx64""
+diff --git a/hw/riscv/numa.c b/hw/riscv/numa.c
+index 7fe92d402f..edf6750f54 100644
+--- a/hw/riscv/numa.c
++++ b/hw/riscv/numa.c
+@@ -207,6 +207,12 @@ int64_t riscv_numa_get_default_cpu_node_id(const MachineState *ms, int idx)
+ {
+ int64_t nidx = 0;
+
++ if (ms->numa_state->num_nodes > ms->smp.cpus) {
++ error_report("Number of NUMA nodes (%d)"
++ " cannot exceed the number of available CPUs (%d).",
++ ms->numa_state->num_nodes, ms->smp.max_cpus);
++ exit(EXIT_FAILURE);
++ }
+ if (ms->numa_state->num_nodes) {
+ nidx = idx / (ms->smp.cpus / ms->numa_state->num_nodes);
+ if (ms->numa_state->num_nodes <= nidx) {
+diff --git a/hw/timer/nrf51_timer.c b/hw/timer/nrf51_timer.c
+index 42be79c736..50c6772383 100644
+--- a/hw/timer/nrf51_timer.c
++++ b/hw/timer/nrf51_timer.c
+@@ -45,7 +45,12 @@ static uint32_t update_counter(NRF51TimerState *s, int64_t now)
+ uint32_t ticks = ns_to_ticks(s, now - s->update_counter_ns);
+
+ s->counter = (s->counter + ticks) % BIT(bitwidths[s->bitmode]);
+- s->update_counter_ns = now;
++ /*
++ * Only advance the sync time to the timestamp of the last tick,
++ * not all the way to 'now', so we don't lose time if we do
++ * multiple resyncs in a single tick.
++ */
++ s->update_counter_ns += ticks_to_ns(s, ticks);
+ return ticks;
+ }
+
+diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
+index 939dcc3d4a..92a45de4c3 100644
+--- a/hw/vfio/pci.c
++++ b/hw/vfio/pci.c
+@@ -663,6 +663,8 @@ static void vfio_msi_enable(VFIOPCIDevice *vdev)
+
+ vfio_disable_interrupts(vdev);
+
++ vdev->nr_vectors = msi_nr_vectors_allocated(&vdev->pdev);
++retry:
+ /*
+ * Setting vector notifiers needs to enable route for each vector.
+ * Deferring to commit the KVM routes once rather than per vector
+@@ -670,8 +672,6 @@ static void vfio_msi_enable(VFIOPCIDevice *vdev)
+ */
+ vfio_prepare_kvm_msi_virq_batch(vdev);
+
+- vdev->nr_vectors = msi_nr_vectors_allocated(&vdev->pdev);
+-retry:
+ vdev->msi_vectors = g_new0(VFIOMSIVector, vdev->nr_vectors);
+
+ for (i = 0; i < vdev->nr_vectors; i++) {
+@@ -3159,7 +3159,9 @@ static void vfio_realize(PCIDevice *pdev, Error **errp)
+
+ out_deregister:
+ pci_device_set_intx_routing_notifier(&vdev->pdev, NULL);
+- kvm_irqchip_remove_change_notifier(&vdev->irqchip_change_notifier);
++ if (vdev->irqchip_change_notifier.notify) {
++ kvm_irqchip_remove_change_notifier(&vdev->irqchip_change_notifier);
++ }
+ out_teardown:
+ vfio_teardown_msi(vdev);
+ vfio_bars_exit(vdev);
+diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
+index fdcd1a8fdf..f38997b3f6 100644
+--- a/hw/virtio/vhost.c
++++ b/hw/virtio/vhost.c
+@@ -1934,6 +1934,9 @@ fail_vq:
+ }
+
+ fail_mem:
++ if (vhost_dev_has_iommu(hdev)) {
++ memory_listener_unregister(&hdev->iommu_listener);
++ }
+ fail_features:
+ vdev->vhost_started = false;
+ hdev->started = false;
+diff --git a/include/qemu/compiler.h b/include/qemu/compiler.h
+index f20a76e4a2..c7ffcaba43 100644
+--- a/include/qemu/compiler.h
++++ b/include/qemu/compiler.h
+@@ -184,4 +184,17 @@
+ #define QEMU_DISABLE_CFI
+ #endif
+
++/*
++ * Apple clang version 14 has a bug in its __builtin_subcll(); define
++ * BUILTIN_SUBCLL_BROKEN for the offending versions so we can avoid it.
++ * When a version of Apple clang which has this bug fixed is released
++ * we can add an upper bound to this check.
++ * See https://gitlab.com/qemu-project/qemu/-/issues/1631
++ * and https://gitlab.com/qemu-project/qemu/-/issues/1659 for details.
++ * The bug never made it into any upstream LLVM releases, only Apple ones.
++ */
++#if defined(__apple_build_version__) && __clang_major__ >= 14
++#define BUILTIN_SUBCLL_BROKEN
++#endif
++
+ #endif /* COMPILER_H */
+diff --git a/include/qemu/host-utils.h b/include/qemu/host-utils.h
+index 88d476161c..b3434ec0bc 100644
+--- a/include/qemu/host-utils.h
++++ b/include/qemu/host-utils.h
+@@ -596,7 +596,7 @@ static inline uint64_t uadd64_carry(uint64_t x, uint64_t y, bool *pcarry)
+ */
+ static inline uint64_t usub64_borrow(uint64_t x, uint64_t y, bool *pborrow)
+ {
+-#if __has_builtin(__builtin_subcll)
++#if __has_builtin(__builtin_subcll) && !defined(BUILTIN_SUBCLL_BROKEN)
+ unsigned long long b = *pborrow;
+ x = __builtin_subcll(x, y, b, &b);
+ *pborrow = b & 1;
+diff --git a/linux-user/s390x/cpu_loop.c b/linux-user/s390x/cpu_loop.c
+index 285bc60071..8b7ac2879e 100644
+--- a/linux-user/s390x/cpu_loop.c
++++ b/linux-user/s390x/cpu_loop.c
+@@ -86,6 +86,15 @@ void cpu_loop(CPUS390XState *env)
+ } else if (ret != -QEMU_ESIGRETURN) {
+ env->regs[2] = ret;
+ }
++
++ if (unlikely(cs->singlestep_enabled)) {
++ /*
++ * cpu_tb_exec() did not raise EXCP_DEBUG, because it has seen
++ * that EXCP_SVC was already pending.
++ */
++ cs->exception_index = EXCP_DEBUG;
++ }
++
+ break;
+
+ case EXCP_DEBUG:
+diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c
+index 2b4b85d8f8..e533f8a348 100644
+--- a/net/vhost-vdpa.c
++++ b/net/vhost-vdpa.c
+@@ -49,6 +49,7 @@ const int vdpa_feature_bits[] = {
+ VIRTIO_F_VERSION_1,
+ VIRTIO_NET_F_CSUM,
+ VIRTIO_NET_F_GUEST_CSUM,
++ VIRTIO_NET_F_CTRL_GUEST_OFFLOADS,
+ VIRTIO_NET_F_GSO,
+ VIRTIO_NET_F_GUEST_TSO4,
+ VIRTIO_NET_F_GUEST_TSO6,
+@@ -160,6 +161,14 @@ static void vhost_vdpa_cleanup(NetClientState *nc)
+ VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc);
+ struct vhost_dev *dev = &s->vhost_net->dev;
+
++ /*
++ * If a peer NIC is attached, do not cleanup anything.
++ * Cleanup will happen as a part of qemu_cleanup() -> net_cleanup()
++ * when the guest is shutting down.
++ */
++ if (nc->peer && nc->peer->info->type == NET_CLIENT_DRIVER_NIC) {
++ return;
++ }
+ qemu_vfree(s->cvq_cmd_out_buffer);
+ qemu_vfree(s->status);
+ if (dev->vq_index + dev->nvqs == dev->vq_index_end) {
+@@ -500,7 +509,7 @@ static int vhost_vdpa_net_handle_ctrl_avail(VhostShadowVirtqueue *svq,
+ }
+
+ if (*s->status != VIRTIO_NET_OK) {
+- return VIRTIO_NET_ERR;
++ goto out;
+ }
+
+ status = VIRTIO_NET_ERR;
+diff --git a/pc-bios/keymaps/meson.build b/pc-bios/keymaps/meson.build
+index 06c75e646b..452395b962 100644
+--- a/pc-bios/keymaps/meson.build
++++ b/pc-bios/keymaps/meson.build
+@@ -1,5 +1,5 @@
+ keymaps = {
+- 'ar': '-l ar',
++ 'ar': '-l ara',
+ 'bepo': '-l fr -v dvorak',
+ 'cz': '-l cz',
+ 'da': '-l dk',
+diff --git a/qga/commands-posix.c b/qga/commands-posix.c
+index 32493d6383..182eba4a38 100644
+--- a/qga/commands-posix.c
++++ b/qga/commands-posix.c
+@@ -1925,10 +1925,10 @@ static void guest_suspend(SuspendMode mode, Error **errp)
+ if (systemd_supports_mode(mode, &local_err)) {
+ mode_supported = true;
+ systemd_suspend(mode, &local_err);
+- }
+
+- if (!local_err) {
+- return;
++ if (!local_err) {
++ return;
++ }
+ }
+
+ error_free(local_err);
+@@ -1937,10 +1937,10 @@ static void guest_suspend(SuspendMode mode, Error **errp)
+ if (pmutils_supports_mode(mode, &local_err)) {
+ mode_supported = true;
+ pmutils_suspend(mode, &local_err);
+- }
+
+- if (!local_err) {
+- return;
++ if (!local_err) {
++ return;
++ }
+ }
+
+ error_free(local_err);
+diff --git a/scripts/device-crash-test b/scripts/device-crash-test
+index 73bcb98693..b74d887331 100755
+--- a/scripts/device-crash-test
++++ b/scripts/device-crash-test
+@@ -397,7 +397,7 @@ def binariesToTest(args, testcase):
+
+
+ def accelsToTest(args, testcase):
+- if getBinaryInfo(args, testcase['binary']).kvm_available:
++ if getBinaryInfo(args, testcase['binary']).kvm_available and not args.tcg_only:
+ yield 'kvm'
+ yield 'tcg'
+
+@@ -510,6 +510,8 @@ def main():
+ help="Full mode: test cases that are expected to fail")
+ parser.add_argument('--strict', action='store_true', dest='strict',
+ help="Treat all warnings as fatal")
++ parser.add_argument('--tcg-only', action='store_true', dest='tcg_only',
++ help="Only test with TCG accelerator")
+ parser.add_argument('qemu', nargs='*', metavar='QEMU',
+ help='QEMU binary to run')
+ args = parser.parse_args()
+diff --git a/softmmu/icount.c b/softmmu/icount.c
+index 4504433e16..a5cef9c60a 100644
+--- a/softmmu/icount.c
++++ b/softmmu/icount.c
+@@ -259,11 +259,16 @@ static void icount_warp_rt(void)
+ warp_delta = clock - timers_state.vm_clock_warp_start;
+ if (icount_enabled() == 2) {
+ /*
+- * In adaptive mode, do not let QEMU_CLOCK_VIRTUAL run too
+- * far ahead of real time.
++ * In adaptive mode, do not let QEMU_CLOCK_VIRTUAL run too far
++ * ahead of real time (it might already be ahead so careful not
++ * to go backwards).
+ */
+ int64_t cur_icount = icount_get_locked();
+ int64_t delta = clock - cur_icount;
++
++ if (delta < 0) {
++ delta = 0;
++ }
+ warp_delta = MIN(warp_delta, delta);
+ }
+ qatomic_set_i64(&timers_state.qemu_icount_bias,
+diff --git a/target/arm/tlb_helper.c b/target/arm/tlb_helper.c
+index 0f4f4fc809..1384fe6f98 100644
+--- a/target/arm/tlb_helper.c
++++ b/target/arm/tlb_helper.c
+@@ -82,8 +82,17 @@ static uint32_t compute_fsr_fsc(CPUARMState *env, ARMMMUFaultInfo *fi,
+ ARMMMUIdx arm_mmu_idx = core_to_arm_mmu_idx(env, mmu_idx);
+ uint32_t fsr, fsc;
+
+- if (target_el == 2 || arm_el_is_aa64(env, target_el) ||
+- arm_s1_regime_using_lpae_format(env, arm_mmu_idx)) {
++ /*
++ * For M-profile there is no guest-facing FSR. We compute a
++ * short-form value for env->exception.fsr which we will then
++ * examine in arm_v7m_cpu_do_interrupt(). In theory we could
++ * use the LPAE format instead as long as both bits of code agree
++ * (and arm_fi_to_lfsc() handled the M-profile specific
++ * ARMFault_QEMU_NSCExec and ARMFault_QEMU_SFault cases).
++ */
++ if (!arm_feature(env, ARM_FEATURE_M) &&
++ (target_el == 2 || arm_el_is_aa64(env, target_el) ||
++ arm_s1_regime_using_lpae_format(env, arm_mmu_idx))) {
+ /*
+ * LPAE format fault status register : bottom 6 bits are
+ * status code in the same form as needed for syndrome
+diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
+index 2ee171f249..f0b8db7ce5 100644
+--- a/target/arm/translate-a64.c
++++ b/target/arm/translate-a64.c
+@@ -3536,8 +3536,22 @@ static void disas_ldst_atomic(DisasContext *s, uint32_t insn,
+ */
+ fn(tcg_rt, clean_addr, tcg_rs, get_mem_index(s), mop);
+
+- if ((mop & MO_SIGN) && size != MO_64) {
+- tcg_gen_ext32u_i64(tcg_rt, tcg_rt);
++ if (mop & MO_SIGN) {
++ switch (size) {
++ case MO_8:
++ tcg_gen_ext8u_i64(tcg_rt, tcg_rt);
++ break;
++ case MO_16:
++ tcg_gen_ext16u_i64(tcg_rt, tcg_rt);
++ break;
++ case MO_32:
++ tcg_gen_ext32u_i64(tcg_rt, tcg_rt);
++ break;
++ case MO_64:
++ break;
++ default:
++ g_assert_not_reached();
++ }
+ }
+ }
+
+@@ -4176,9 +4190,13 @@ static void disas_ldst_tag(DisasContext *s, uint32_t insn)
+ if (s->ata) {
+ gen_helper_ldg(tcg_rt, cpu_env, addr, tcg_rt);
+ } else {
++ /*
++ * Tag access disabled: we must check for aborts on the load
++ * load from [rn+offset], and then insert a 0 tag into rt.
++ */
+ clean_addr = clean_data_tbi(s, addr);
+ gen_probe_access(s, clean_addr, MMU_DATA_LOAD, MO_8);
+- gen_address_with_allocation_tag0(tcg_rt, addr);
++ gen_address_with_allocation_tag0(tcg_rt, tcg_rt);
+ }
+ } else {
+ tcg_rt = cpu_reg_sp(s, rt);
+diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
+index cbf0081374..294a18a5b7 100644
+--- a/target/ppc/cpu_init.c
++++ b/target/ppc/cpu_init.c
+@@ -7085,7 +7085,7 @@ static void ppc_cpu_reset(DeviceState *dev)
+ if (env->mmu_model != POWERPC_MMU_REAL) {
+ ppc_tlb_invalidate_all(env);
+ }
+- pmu_update_summaries(env);
++ pmu_mmcr01_updated(env);
+ }
+
+ /* clean any pending stop state */
+diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
+index 30bc2e6adf..6cf88f635a 100644
+--- a/target/ppc/excp_helper.c
++++ b/target/ppc/excp_helper.c
+@@ -1358,9 +1358,12 @@ static void powerpc_excp_books(PowerPCCPU *cpu, int excp)
+
+ /*
+ * We don't want to generate a Hypervisor Emulation Assistance
+- * Interrupt if we don't have HVB in msr_mask (PAPR mode).
++ * Interrupt if we don't have HVB in msr_mask (PAPR mode),
++ * unless running a nested-hv guest, in which case the L1
++ * kernel wants the interrupt.
+ */
+- if (excp == POWERPC_EXCP_HV_EMU && !(env->msr_mask & MSR_HVB)) {
++ if (excp == POWERPC_EXCP_HV_EMU && !(env->msr_mask & MSR_HVB) &&
++ !books_vhyp_handles_hv_excp(cpu)) {
+ excp = POWERPC_EXCP_PROGRAM;
+ }
+
+diff --git a/target/ppc/helper_regs.c b/target/ppc/helper_regs.c
+index c0aee5855b..e200091a23 100644
+--- a/target/ppc/helper_regs.c
++++ b/target/ppc/helper_regs.c
+@@ -46,6 +46,48 @@ void hreg_swap_gpr_tgpr(CPUPPCState *env)
+ env->tgpr[3] = tmp;
+ }
+
++static uint32_t hreg_compute_pmu_hflags_value(CPUPPCState *env)
++{
++ uint32_t hflags = 0;
++
++#if defined(TARGET_PPC64)
++ if (env->spr[SPR_POWER_MMCR0] & MMCR0_PMCC0) {
++ hflags |= 1 << HFLAGS_PMCC0;
++ }
++ if (env->spr[SPR_POWER_MMCR0] & MMCR0_PMCC1) {
++ hflags |= 1 << HFLAGS_PMCC1;
++ }
++ if (env->spr[SPR_POWER_MMCR0] & MMCR0_PMCjCE) {
++ hflags |= 1 << HFLAGS_PMCJCE;
++ }
++
++#ifndef CONFIG_USER_ONLY
++ if (env->pmc_ins_cnt) {
++ hflags |= 1 << HFLAGS_INSN_CNT;
++ }
++ if (env->pmc_ins_cnt & 0x1e) {
++ hflags |= 1 << HFLAGS_PMC_OTHER;
++ }
++#endif
++#endif
++
++ return hflags;
++}
++
++/* Mask of all PMU hflags */
++static uint32_t hreg_compute_pmu_hflags_mask(CPUPPCState *env)
++{
++ uint32_t hflags_mask = 0;
++#if defined(TARGET_PPC64)
++ hflags_mask |= 1 << HFLAGS_PMCC0;
++ hflags_mask |= 1 << HFLAGS_PMCC1;
++ hflags_mask |= 1 << HFLAGS_PMCJCE;
++ hflags_mask |= 1 << HFLAGS_INSN_CNT;
++ hflags_mask |= 1 << HFLAGS_PMC_OTHER;
++#endif
++ return hflags_mask;
++}
++
+ static uint32_t hreg_compute_hflags_value(CPUPPCState *env)
+ {
+ target_ulong msr = env->msr;
+@@ -103,30 +145,12 @@ static uint32_t hreg_compute_hflags_value(CPUPPCState *env)
+ if (env->spr[SPR_LPCR] & LPCR_HR) {
+ hflags |= 1 << HFLAGS_HR;
+ }
+- if (env->spr[SPR_POWER_MMCR0] & MMCR0_PMCC0) {
+- hflags |= 1 << HFLAGS_PMCC0;
+- }
+- if (env->spr[SPR_POWER_MMCR0] & MMCR0_PMCC1) {
+- hflags |= 1 << HFLAGS_PMCC1;
+- }
+- if (env->spr[SPR_POWER_MMCR0] & MMCR0_PMCjCE) {
+- hflags |= 1 << HFLAGS_PMCJCE;
+- }
+
+ #ifndef CONFIG_USER_ONLY
+ if (!env->has_hv_mode || (msr & (1ull << MSR_HV))) {
+ hflags |= 1 << HFLAGS_HV;
+ }
+
+-#if defined(TARGET_PPC64)
+- if (env->pmc_ins_cnt) {
+- hflags |= 1 << HFLAGS_INSN_CNT;
+- }
+- if (env->pmc_ins_cnt & 0x1e) {
+- hflags |= 1 << HFLAGS_PMC_OTHER;
+- }
+-#endif
+-
+ /*
+ * This is our encoding for server processors. The architecture
+ * specifies that there is no such thing as userspace with
+@@ -171,6 +195,8 @@ static uint32_t hreg_compute_hflags_value(CPUPPCState *env)
+ hflags |= dmmu_idx << HFLAGS_DMMU_IDX;
+ #endif
+
++ hflags |= hreg_compute_pmu_hflags_value(env);
++
+ return hflags | (msr & msr_mask);
+ }
+
+@@ -179,6 +205,17 @@ void hreg_compute_hflags(CPUPPCState *env)
+ env->hflags = hreg_compute_hflags_value(env);
+ }
+
++/*
++ * This can be used as a lighter-weight alternative to hreg_compute_hflags
++ * when PMU MMCR0 or pmc_ins_cnt changes. pmc_ins_cnt is changed by
++ * pmu_update_summaries.
++ */
++void hreg_update_pmu_hflags(CPUPPCState *env)
++{
++ env->hflags &= ~hreg_compute_pmu_hflags_mask(env);
++ env->hflags |= hreg_compute_pmu_hflags_value(env);
++}
++
+ #ifdef CONFIG_DEBUG_TCG
+ void cpu_get_tb_cpu_state(CPUPPCState *env, target_ulong *pc,
+ target_ulong *cs_base, uint32_t *flags)
+diff --git a/target/ppc/helper_regs.h b/target/ppc/helper_regs.h
+index 42f26870b9..8196c1346d 100644
+--- a/target/ppc/helper_regs.h
++++ b/target/ppc/helper_regs.h
+@@ -22,6 +22,7 @@
+
+ void hreg_swap_gpr_tgpr(CPUPPCState *env);
+ void hreg_compute_hflags(CPUPPCState *env);
++void hreg_update_pmu_hflags(CPUPPCState *env);
+ void cpu_interrupt_exittb(CPUState *cs);
+ int hreg_store_msr(CPUPPCState *env, target_ulong value, int alter_hv);
+
+diff --git a/target/ppc/machine.c b/target/ppc/machine.c
+index be6eb3d968..134b16c625 100644
+--- a/target/ppc/machine.c
++++ b/target/ppc/machine.c
+@@ -21,10 +21,6 @@ static void post_load_update_msr(CPUPPCState *env)
+ */
+ env->msr ^= env->msr_mask & ~((1ULL << MSR_TGPR) | MSR_HVB);
+ ppc_store_msr(env, msr);
+-
+- if (tcg_enabled()) {
+- pmu_update_summaries(env);
+- }
+ }
+
+ static int get_avr(QEMUFile *f, void *pv, size_t size,
+@@ -317,6 +313,10 @@ static int cpu_post_load(void *opaque, int version_id)
+
+ post_load_update_msr(env);
+
++ if (tcg_enabled()) {
++ pmu_mmcr01_updated(env);
++ }
++
+ return 0;
+ }
+
+diff --git a/target/ppc/power8-pmu.c b/target/ppc/power8-pmu.c
+index 1381072b9e..fccd011088 100644
+--- a/target/ppc/power8-pmu.c
++++ b/target/ppc/power8-pmu.c
+@@ -31,7 +31,11 @@ static bool pmc_has_overflow_enabled(CPUPPCState *env, int sprn)
+ return env->spr[SPR_POWER_MMCR0] & MMCR0_PMCjCE;
+ }
+
+-void pmu_update_summaries(CPUPPCState *env)
++/*
++ * Called after MMCR0 or MMCR1 changes to update pmc_ins_cnt and pmc_cyc_cnt.
++ * hflags must subsequently be updated.
++ */
++static void pmu_update_summaries(CPUPPCState *env)
+ {
+ target_ulong mmcr0 = env->spr[SPR_POWER_MMCR0];
+ target_ulong mmcr1 = env->spr[SPR_POWER_MMCR1];
+@@ -39,7 +43,7 @@ void pmu_update_summaries(CPUPPCState *env)
+ int cyc_cnt = 0;
+
+ if (mmcr0 & MMCR0_FC) {
+- goto hflags_calc;
++ goto out;
+ }
+
+ if (!(mmcr0 & MMCR0_FC14) && mmcr1 != 0) {
+@@ -73,10 +77,19 @@ void pmu_update_summaries(CPUPPCState *env)
+ ins_cnt |= !(mmcr0 & MMCR0_FC56) << 5;
+ cyc_cnt |= !(mmcr0 & MMCR0_FC56) << 6;
+
+- hflags_calc:
++ out:
+ env->pmc_ins_cnt = ins_cnt;
+ env->pmc_cyc_cnt = cyc_cnt;
+- env->hflags = deposit32(env->hflags, HFLAGS_INSN_CNT, 1, ins_cnt != 0);
++}
++
++void pmu_mmcr01_updated(CPUPPCState *env)
++{
++ pmu_update_summaries(env);
++ hreg_update_pmu_hflags(env);
++ /*
++ * Should this update overflow timers (if mmcr0 is updated) so they
++ * get set in cpu_post_load?
++ */
+ }
+
+ static bool pmu_increment_insns(CPUPPCState *env, uint32_t num_insns)
+@@ -234,18 +247,11 @@ static void pmu_delete_timers(CPUPPCState *env)
+
+ void helper_store_mmcr0(CPUPPCState *env, target_ulong value)
+ {
+- bool hflags_pmcc0 = (value & MMCR0_PMCC0) != 0;
+- bool hflags_pmcc1 = (value & MMCR0_PMCC1) != 0;
+-
+ pmu_update_cycles(env);
+
+ env->spr[SPR_POWER_MMCR0] = value;
+
+- /* MMCR0 writes can change HFLAGS_PMCC[01] and HFLAGS_INSN_CNT */
+- env->hflags = deposit32(env->hflags, HFLAGS_PMCC0, 1, hflags_pmcc0);
+- env->hflags = deposit32(env->hflags, HFLAGS_PMCC1, 1, hflags_pmcc1);
+-
+- pmu_update_summaries(env);
++ pmu_mmcr01_updated(env);
+
+ /* Update cycle overflow timers with the current MMCR0 state */
+ pmu_update_overflow_timers(env);
+@@ -257,8 +263,7 @@ void helper_store_mmcr1(CPUPPCState *env, uint64_t value)
+
+ env->spr[SPR_POWER_MMCR1] = value;
+
+- /* MMCR1 writes can change HFLAGS_INSN_CNT */
+- pmu_update_summaries(env);
++ pmu_mmcr01_updated(env);
+ }
+
+ target_ulong helper_read_pmc(CPUPPCState *env, uint32_t sprn)
+@@ -287,8 +292,8 @@ static void fire_PMC_interrupt(PowerPCCPU *cpu)
+ env->spr[SPR_POWER_MMCR0] &= ~MMCR0_FCECE;
+ env->spr[SPR_POWER_MMCR0] |= MMCR0_FC;
+
+- /* Changing MMCR0_FC requires a new HFLAGS_INSN_CNT calc */
+- pmu_update_summaries(env);
++ /* Changing MMCR0_FC requires summaries and hflags update */
++ pmu_mmcr01_updated(env);
+
+ /*
+ * Delete all pending timers if we need to freeze
+@@ -299,6 +304,7 @@ static void fire_PMC_interrupt(PowerPCCPU *cpu)
+ }
+
+ if (env->spr[SPR_POWER_MMCR0] & MMCR0_PMAE) {
++ /* These MMCR0 bits do not require summaries or hflags update. */
+ env->spr[SPR_POWER_MMCR0] &= ~MMCR0_PMAE;
+ env->spr[SPR_POWER_MMCR0] |= MMCR0_PMAO;
+ }
+diff --git a/target/ppc/power8-pmu.h b/target/ppc/power8-pmu.h
+index c0093e2219..775e640053 100644
+--- a/target/ppc/power8-pmu.h
++++ b/target/ppc/power8-pmu.h
+@@ -18,10 +18,10 @@
+ #define PMC_COUNTER_NEGATIVE_VAL 0x80000000UL
+
+ void cpu_ppc_pmu_init(CPUPPCState *env);
+-void pmu_update_summaries(CPUPPCState *env);
++void pmu_mmcr01_updated(CPUPPCState *env);
+ #else
+ static inline void cpu_ppc_pmu_init(CPUPPCState *env) { }
+-static inline void pmu_update_summaries(CPUPPCState *env) { }
++static inline void pmu_mmcr01_updated(CPUPPCState *env) { }
+ #endif
+
+ #endif
+diff --git a/target/ppc/translate.c b/target/ppc/translate.c
+index 19c1d17cb0..1de7eca9c4 100644
+--- a/target/ppc/translate.c
++++ b/target/ppc/translate.c
+@@ -3972,6 +3972,7 @@ static void gen_lqarx(DisasContext *ctx)
+ }
+ tcg_temp_free(EA);
+
++ tcg_gen_mov_tl(cpu_reserve, EA);
+ tcg_gen_st_tl(hi, cpu_env, offsetof(CPUPPCState, reserve_val));
+ tcg_gen_st_tl(lo, cpu_env, offsetof(CPUPPCState, reserve_val2));
+ }
+diff --git a/target/s390x/cpu_models.c b/target/s390x/cpu_models.c
+index c3a4f80633..a85c56b4ee 100644
+--- a/target/s390x/cpu_models.c
++++ b/target/s390x/cpu_models.c
+@@ -604,8 +604,8 @@ void s390_realize_cpu_model(CPUState *cs, Error **errp)
+ #if !defined(CONFIG_USER_ONLY)
+ cpu->env.cpuid = s390_cpuid_from_cpu_model(cpu->model);
+ if (tcg_enabled()) {
+- /* basic mode, write the cpu address into the first 4 bit of the ID */
+- cpu->env.cpuid = deposit64(cpu->env.cpuid, 54, 4, cpu->env.core_id);
++ cpu->env.cpuid = deposit64(cpu->env.cpuid, CPU_PHYS_ADDR_SHIFT,
++ CPU_PHYS_ADDR_BITS, cpu->env.core_id);
+ }
+ #endif
+ }
+diff --git a/target/s390x/cpu_models.h b/target/s390x/cpu_models.h
+index fb1adc8b21..cc7305ec21 100644
+--- a/target/s390x/cpu_models.h
++++ b/target/s390x/cpu_models.h
+@@ -96,10 +96,18 @@ static inline bool s390_known_cpu_type(uint16_t type)
+ {
+ return s390_get_gen_for_cpu_type(type) != 0;
+ }
++#define CPU_ID_SHIFT 32
++#define CPU_ID_BITS 24
++/*
++ * When cpu_id_format is 0 (basic mode), the leftmost 4 bits of cpu_id contain
++ * the rightmost 4 bits of the physical CPU address.
++ */
++#define CPU_PHYS_ADDR_BITS 4
++#define CPU_PHYS_ADDR_SHIFT (CPU_ID_SHIFT + CPU_ID_BITS - CPU_PHYS_ADDR_BITS)
+ static inline uint64_t s390_cpuid_from_cpu_model(const S390CPUModel *model)
+ {
+ return ((uint64_t)model->cpu_ver << 56) |
+- ((uint64_t)model->cpu_id << 32) |
++ ((uint64_t)model->cpu_id << CPU_ID_SHIFT) |
+ ((uint64_t)model->def->type << 16) |
+ (model->def->gen == 7 ? 0 : (uint64_t)model->cpu_id_format << 15);
+ }
+diff --git a/target/s390x/tcg/insn-data.h.inc b/target/s390x/tcg/insn-data.h.inc
+index 13ffdda4da..4249632af3 100644
+--- a/target/s390x/tcg/insn-data.h.inc
++++ b/target/s390x/tcg/insn-data.h.inc
+@@ -486,7 +486,7 @@
+ F(0xb343, LCXBR, RRE, Z, x2h, x2l, new_P, x1, negf128, f128, IF_BFP)
+ F(0xb373, LCDFR, RRE, FPSSH, 0, f2, new, f1, negf64, 0, IF_AFP1 | IF_AFP2)
+ /* LOAD COUNT TO BLOCK BOUNDARY */
+- C(0xe727, LCBB, RXE, V, la2, 0, r1, 0, lcbb, 0)
++ C(0xe727, LCBB, RXE, V, la2, 0, new, r1_32, lcbb, 0)
+ /* LOAD HALFWORD */
+ C(0xb927, LHR, RRE, EI, 0, r2_16s, 0, r1_32, mov2, 0)
+ C(0xb907, LGHR, RRE, EI, 0, r2_16s, 0, r1, mov2, 0)
+@@ -564,7 +564,7 @@
+ C(0xec46, LOCGHI, RIE_g, LOC2, r1, i2, r1, 0, loc, 0)
+ C(0xec4e, LOCHHI, RIE_g, LOC2, r1_sr32, i2, new, r1_32h, loc, 0)
+ /* LOAD HIGH ON CONDITION */
+- C(0xb9e0, LOCFHR, RRF_c, LOC2, r1_sr32, r2, new, r1_32h, loc, 0)
++ C(0xb9e0, LOCFHR, RRF_c, LOC2, r1_sr32, r2_sr32, new, r1_32h, loc, 0)
+ C(0xebe0, LOCFH, RSY_b, LOC2, r1_sr32, m2_32u, new, r1_32h, loc, 0)
+ /* LOAD PAIR DISJOINT */
+ D(0xc804, LPD, SSF, ILA, 0, 0, new_P, r3_P32, lpd, 0, MO_TEUL)
+diff --git a/tests/tcg/s390x/Makefile.target b/tests/tcg/s390x/Makefile.target
+index 07fcc6d0ce..cb90d4183d 100644
+--- a/tests/tcg/s390x/Makefile.target
++++ b/tests/tcg/s390x/Makefile.target
+@@ -26,6 +26,8 @@ TESTS+=branch-relative-long
+ TESTS+=noexec
+
+ Z13_TESTS=vistr
++Z13_TESTS+=lcbb
++Z13_TESTS+=locfhr
+ $(Z13_TESTS): CFLAGS+=-march=z13 -O2
+ TESTS+=$(Z13_TESTS)
+
+@@ -54,7 +56,16 @@ run-gdbstub-signals-s390x: signals-s390x
+ --bin $< --test $(S390X_SRC)/gdbstub/test-signals-s390x.py, \
+ mixing signals and debugging)
+
+-EXTRA_RUNS += run-gdbstub-signals-s390x
++hello-s390x-asm: CFLAGS+=-nostdlib
++
++run-gdbstub-svc: hello-s390x-asm
++ $(call run-test, $@, $(GDB_SCRIPT) \
++ --gdb $(HAVE_GDB_BIN) \
++ --qemu $(QEMU) --qargs "$(QEMU_OPTS)" \
++ --bin $< --test $(S390X_SRC)/gdbstub/test-svc.py, \
++ single-stepping svc)
++
++EXTRA_RUNS += run-gdbstub-signals-s390x run-gdbstub-svc
+ endif
+
+ # MVX versions of sha512
+diff --git a/tests/tcg/s390x/gdbstub/test-svc.py b/tests/tcg/s390x/gdbstub/test-svc.py
+new file mode 100644
+index 0000000000..7851ca7284
+--- /dev/null
++++ b/tests/tcg/s390x/gdbstub/test-svc.py
+@@ -0,0 +1,64 @@
++"""Test single-stepping SVC.
++
++This runs as a sourced script (via -x, via run-test.py)."""
++from __future__ import print_function
++import gdb
++import sys
++
++
++n_failures = 0
++
++
++def report(cond, msg):
++ """Report success/fail of a test"""
++ if cond:
++ print("PASS: {}".format(msg))
++ else:
++ print("FAIL: {}".format(msg))
++ global n_failures
++ n_failures += 1
++
++
++def run_test():
++ """Run through the tests one by one"""
++ report("lghi\t" in gdb.execute("x/i $pc", False, True), "insn #1")
++ gdb.execute("si")
++ report("larl\t" in gdb.execute("x/i $pc", False, True), "insn #2")
++ gdb.execute("si")
++ report("lghi\t" in gdb.execute("x/i $pc", False, True), "insn #3")
++ gdb.execute("si")
++ report("svc\t" in gdb.execute("x/i $pc", False, True), "insn #4")
++ gdb.execute("si")
++ report("xgr\t" in gdb.execute("x/i $pc", False, True), "insn #5")
++ gdb.execute("si")
++ report("svc\t" in gdb.execute("x/i $pc", False, True), "insn #6")
++ gdb.execute("si")
++
++
++def main():
++ """Prepare the environment and run through the tests"""
++ try:
++ inferior = gdb.selected_inferior()
++ print("ATTACHED: {}".format(inferior.architecture().name()))
++ except (gdb.error, AttributeError):
++ print("SKIPPING (not connected)")
++ exit(0)
++
++ if gdb.parse_and_eval('$pc') == 0:
++ print("SKIP: PC not set")
++ exit(0)
++
++ try:
++ # These are not very useful in scripts
++ gdb.execute("set pagination off")
++ gdb.execute("set confirm off")
++
++ # Run the actual tests
++ run_test()
++ except gdb.error:
++ report(False, "GDB Exception: {}".format(sys.exc_info()[0]))
++ print("All tests complete: %d failures" % n_failures)
++ exit(n_failures)
++
++
++main()
+diff --git a/tests/tcg/s390x/hello-s390x-asm.S b/tests/tcg/s390x/hello-s390x-asm.S
+new file mode 100644
+index 0000000000..2e9faa1604
+--- /dev/null
++++ b/tests/tcg/s390x/hello-s390x-asm.S
+@@ -0,0 +1,20 @@
++/*
++ * Hello, World! in assembly.
++ */
++
++.globl _start
++_start:
++
++/* puts("Hello, World!"); */
++lghi %r2,1
++larl %r3,foo
++lghi %r4,foo_end-foo
++svc 4
++
++/* exit(0); */
++xgr %r2,%r2
++svc 1
++
++.align 2
++foo: .asciz "Hello, World!\n"
++foo_end:
+diff --git a/tests/tcg/s390x/lcbb.c b/tests/tcg/s390x/lcbb.c
+new file mode 100644
+index 0000000000..8d368e0998
+--- /dev/null
++++ b/tests/tcg/s390x/lcbb.c
+@@ -0,0 +1,51 @@
++/*
++ * Test the LCBB instruction.
++ *
++ * SPDX-License-Identifier: GPL-2.0-or-later
++ */
++#include <assert.h>
++#include <stdlib.h>
++
++static inline __attribute__((__always_inline__)) void
++lcbb(long *r1, void *dxb2, int m3, int *cc)
++{
++ asm("lcbb %[r1],%[dxb2],%[m3]\n"
++ "ipm %[cc]"
++ : [r1] "+r" (*r1), [cc] "=r" (*cc)
++ : [dxb2] "R" (*(char *)dxb2), [m3] "i" (m3)
++ : "cc");
++ *cc = (*cc >> 28) & 3;
++}
++
++static char buf[0x1000] __attribute__((aligned(0x1000)));
++
++static inline __attribute__((__always_inline__)) void
++test_lcbb(void *p, int m3, int exp_r1, int exp_cc)
++{
++ long r1 = 0xfedcba9876543210;
++ int cc;
++
++ lcbb(&r1, p, m3, &cc);
++ assert(r1 == (0xfedcba9800000000 | exp_r1));
++ assert(cc == exp_cc);
++}
++
++int main(void)
++{
++ test_lcbb(&buf[0], 0, 16, 0);
++ test_lcbb(&buf[63], 0, 1, 3);
++ test_lcbb(&buf[0], 1, 16, 0);
++ test_lcbb(&buf[127], 1, 1, 3);
++ test_lcbb(&buf[0], 2, 16, 0);
++ test_lcbb(&buf[255], 2, 1, 3);
++ test_lcbb(&buf[0], 3, 16, 0);
++ test_lcbb(&buf[511], 3, 1, 3);
++ test_lcbb(&buf[0], 4, 16, 0);
++ test_lcbb(&buf[1023], 4, 1, 3);
++ test_lcbb(&buf[0], 5, 16, 0);
++ test_lcbb(&buf[2047], 5, 1, 3);
++ test_lcbb(&buf[0], 6, 16, 0);
++ test_lcbb(&buf[4095], 6, 1, 3);
++
++ return EXIT_SUCCESS;
++}
+diff --git a/tests/tcg/s390x/locfhr.c b/tests/tcg/s390x/locfhr.c
+new file mode 100644
+index 0000000000..ab9ff6e449
+--- /dev/null
++++ b/tests/tcg/s390x/locfhr.c
+@@ -0,0 +1,29 @@
++/*
++ * Test the LOCFHR instruction.
++ *
++ * SPDX-License-Identifier: GPL-2.0-or-later
++ */
++#include <assert.h>
++#include <stdlib.h>
++
++static inline __attribute__((__always_inline__)) long
++locfhr(long r1, long r2, int m3, int cc)
++{
++ cc <<= 28;
++ asm("spm %[cc]\n"
++ "locfhr %[r1],%[r2],%[m3]\n"
++ : [r1] "+r" (r1)
++ : [cc] "r" (cc), [r2] "r" (r2), [m3] "i" (m3)
++ : "cc");
++ return r1;
++}
++
++int main(void)
++{
++ assert(locfhr(0x1111111122222222, 0x3333333344444444, 8, 0) ==
++ 0x3333333322222222);
++ assert(locfhr(0x5555555566666666, 0x7777777788888888, 11, 1) ==
++ 0x5555555566666666);
++
++ return EXIT_SUCCESS;
++}
+diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c
+index e84431790c..e99e3b0d8c 100644
+--- a/ui/gtk-egl.c
++++ b/ui/gtk-egl.c
+@@ -88,8 +88,8 @@ void gd_egl_draw(VirtualConsole *vc)
+ #endif
+ gd_egl_scanout_flush(&vc->gfx.dcl, 0, 0, vc->gfx.w, vc->gfx.h);
+
+- vc->gfx.scale_x = (double)ww / vc->gfx.w;
+- vc->gfx.scale_y = (double)wh / vc->gfx.h;
++ vc->gfx.scale_x = (double)ww / surface_width(vc->gfx.ds);
++ vc->gfx.scale_y = (double)wh / surface_height(vc->gfx.ds);
+
+ glFlush();
+ #ifdef CONFIG_GBM
+@@ -256,8 +256,9 @@ void gd_egl_scanout_dmabuf(DisplayChangeListener *dcl,
+ }
+
+ gd_egl_scanout_texture(dcl, dmabuf->texture,
+- false, dmabuf->width, dmabuf->height,
+- 0, 0, dmabuf->width, dmabuf->height);
++ dmabuf->y0_top, dmabuf->width, dmabuf->height,
++ dmabuf->x, dmabuf->y, dmabuf->scanout_width,
++ dmabuf->scanout_height);
+
+ if (dmabuf->allow_fences) {
+ vc->gfx.guest_fb.dmabuf = dmabuf;
+diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c
+index 7696df1f6b..1605818bd1 100644
+--- a/ui/gtk-gl-area.c
++++ b/ui/gtk-gl-area.c
+@@ -298,8 +298,9 @@ void gd_gl_area_scanout_dmabuf(DisplayChangeListener *dcl,
+ }
+
+ gd_gl_area_scanout_texture(dcl, dmabuf->texture,
+- false, dmabuf->width, dmabuf->height,
+- 0, 0, dmabuf->width, dmabuf->height);
++ dmabuf->y0_top, dmabuf->width, dmabuf->height,
++ dmabuf->x, dmabuf->y, dmabuf->scanout_width,
++ dmabuf->scanout_height);
+
+ if (dmabuf->allow_fences) {
+ vc->gfx.guest_fb.dmabuf = dmabuf;
+diff --git a/ui/gtk.c b/ui/gtk.c
+index dfaf6d33c3..e681e8c319 100644
+--- a/ui/gtk.c
++++ b/ui/gtk.c
+@@ -868,7 +868,6 @@ static gboolean gd_motion_event(GtkWidget *widget, GdkEventMotion *motion,
+ {
+ VirtualConsole *vc = opaque;
+ GtkDisplayState *s = vc->s;
+- GdkWindow *window;
+ int x, y;
+ int mx, my;
+ int fbh, fbw;
+@@ -881,10 +880,9 @@ static gboolean gd_motion_event(GtkWidget *widget, GdkEventMotion *motion,
+ fbw = surface_width(vc->gfx.ds) * vc->gfx.scale_x;
+ fbh = surface_height(vc->gfx.ds) * vc->gfx.scale_y;
+
+- window = gtk_widget_get_window(vc->gfx.drawing_area);
+- ww = gdk_window_get_width(window);
+- wh = gdk_window_get_height(window);
+- ws = gdk_window_get_scale_factor(window);
++ ww = gtk_widget_get_allocated_width(widget);
++ wh = gtk_widget_get_allocated_height(widget);
++ ws = gtk_widget_get_scale_factor(widget);
+
+ mx = my = 0;
+ if (ww > fbw) {
+diff --git a/ui/sdl2-gl.c b/ui/sdl2-gl.c
+index 39cab8cde7..bbfa70eac3 100644
+--- a/ui/sdl2-gl.c
++++ b/ui/sdl2-gl.c
+@@ -67,6 +67,10 @@ void sdl2_gl_update(DisplayChangeListener *dcl,
+
+ assert(scon->opengl);
+
++ if (!scon->real_window) {
++ return;
++ }
++
+ SDL_GL_MakeCurrent(scon->real_window, scon->winctx);
+ surface_gl_update_texture(scon->gls, scon->surface, x, y, w, h);
+ scon->updates++;
+diff --git a/ui/sdl2.c b/ui/sdl2.c
+index 8cb77416af..d630459b78 100644
+--- a/ui/sdl2.c
++++ b/ui/sdl2.c
+@@ -849,7 +849,14 @@ static void sdl2_display_init(DisplayState *ds, DisplayOptions *o)
+ #ifdef SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR /* only available since SDL 2.0.8 */
+ SDL_SetHint(SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR, "0");
+ #endif
++#ifndef CONFIG_WIN32
++ /* QEMU uses its own low level keyboard hook procecure on Windows */
+ SDL_SetHint(SDL_HINT_GRAB_KEYBOARD, "1");
++#endif
++#ifdef SDL_HINT_ALLOW_ALT_TAB_WHILE_GRABBED
++ SDL_SetHint(SDL_HINT_ALLOW_ALT_TAB_WHILE_GRABBED, "0");
++#endif
++ SDL_SetHint(SDL_HINT_WINDOWS_NO_CLOSE_ON_ALT_F4, "1");
+ memset(&info, 0, sizeof(info));
+ SDL_VERSION(&info.version);
+
+diff --git a/ui/vnc-jobs.c b/ui/vnc-jobs.c
+index 886f9bf611..fcca7ec632 100644
+--- a/ui/vnc-jobs.c
++++ b/ui/vnc-jobs.c
+@@ -250,12 +250,13 @@ static int vnc_worker_thread_loop(VncJobQueue *queue)
+ /* Here job can only be NULL if queue->exit is true */
+ job = QTAILQ_FIRST(&queue->jobs);
+ vnc_unlock_queue(queue);
+- assert(job->vs->magic == VNC_MAGIC);
+
+ if (queue->exit) {
+ return -1;
+ }
+
++ assert(job->vs->magic == VNC_MAGIC);
++
+ vnc_lock_output(job->vs);
+ if (job->vs->ioc == NULL || job->vs->abort == true) {
+ vnc_unlock_output(job->vs);
diff --git a/debian/patches/v7.2.5.diff b/debian/patches/v7.2.5.diff
new file mode 100644
index 00000000..56749cbe
--- /dev/null
+++ b/debian/patches/v7.2.5.diff
@@ -0,0 +1,1575 @@
+diff --git a/VERSION b/VERSION
+index 2bbaead448..8aea167e72 100644
+--- a/VERSION
++++ b/VERSION
+@@ -1 +1 @@
+-7.2.4
++7.2.5
+diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
+index e09b9c13b7..bbca3a8db3 100644
+--- a/hw/arm/smmu-common.c
++++ b/hw/arm/smmu-common.c
+@@ -193,8 +193,7 @@ static int get_pte(dma_addr_t baseaddr, uint32_t index, uint64_t *pte,
+ dma_addr_t addr = baseaddr + index * sizeof(*pte);
+
+ /* TODO: guarantee 64-bit single-copy atomicity */
+- ret = dma_memory_read(&address_space_memory, addr, pte, sizeof(*pte),
+- MEMTXATTRS_UNSPECIFIED);
++ ret = ldq_le_dma(&address_space_memory, addr, pte, MEMTXATTRS_UNSPECIFIED);
+
+ if (ret != MEMTX_OK) {
+ info->type = SMMU_PTW_ERR_WALK_EABT;
+diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
+index daa80e9c7b..ce7091ff8e 100644
+--- a/hw/arm/smmuv3.c
++++ b/hw/arm/smmuv3.c
+@@ -98,20 +98,34 @@ static void smmuv3_write_gerrorn(SMMUv3State *s, uint32_t new_gerrorn)
+ trace_smmuv3_write_gerrorn(toggled & pending, s->gerrorn);
+ }
+
+-static inline MemTxResult queue_read(SMMUQueue *q, void *data)
++static inline MemTxResult queue_read(SMMUQueue *q, Cmd *cmd)
+ {
+ dma_addr_t addr = Q_CONS_ENTRY(q);
++ MemTxResult ret;
++ int i;
+
+- return dma_memory_read(&address_space_memory, addr, data, q->entry_size,
+- MEMTXATTRS_UNSPECIFIED);
++ ret = dma_memory_read(&address_space_memory, addr, cmd, sizeof(Cmd),
++ MEMTXATTRS_UNSPECIFIED);
++ if (ret != MEMTX_OK) {
++ return ret;
++ }
++ for (i = 0; i < ARRAY_SIZE(cmd->word); i++) {
++ le32_to_cpus(&cmd->word[i]);
++ }
++ return ret;
+ }
+
+-static MemTxResult queue_write(SMMUQueue *q, void *data)
++static MemTxResult queue_write(SMMUQueue *q, Evt *evt_in)
+ {
+ dma_addr_t addr = Q_PROD_ENTRY(q);
+ MemTxResult ret;
++ Evt evt = *evt_in;
++ int i;
+
+- ret = dma_memory_write(&address_space_memory, addr, data, q->entry_size,
++ for (i = 0; i < ARRAY_SIZE(evt.word); i++) {
++ cpu_to_le32s(&evt.word[i]);
++ }
++ ret = dma_memory_write(&address_space_memory, addr, &evt, sizeof(Evt),
+ MEMTXATTRS_UNSPECIFIED);
+ if (ret != MEMTX_OK) {
+ return ret;
+@@ -290,7 +304,7 @@ static void smmuv3_init_regs(SMMUv3State *s)
+ static int smmu_get_ste(SMMUv3State *s, dma_addr_t addr, STE *buf,
+ SMMUEventInfo *event)
+ {
+- int ret;
++ int ret, i;
+
+ trace_smmuv3_get_ste(addr);
+ /* TODO: guarantee 64-bit single-copy atomicity */
+@@ -303,6 +317,9 @@ static int smmu_get_ste(SMMUv3State *s, dma_addr_t addr, STE *buf,
+ event->u.f_ste_fetch.addr = addr;
+ return -EINVAL;
+ }
++ for (i = 0; i < ARRAY_SIZE(buf->word); i++) {
++ le32_to_cpus(&buf->word[i]);
++ }
+ return 0;
+
+ }
+@@ -312,7 +329,7 @@ static int smmu_get_cd(SMMUv3State *s, STE *ste, uint32_t ssid,
+ CD *buf, SMMUEventInfo *event)
+ {
+ dma_addr_t addr = STE_CTXPTR(ste);
+- int ret;
++ int ret, i;
+
+ trace_smmuv3_get_cd(addr);
+ /* TODO: guarantee 64-bit single-copy atomicity */
+@@ -325,6 +342,9 @@ static int smmu_get_cd(SMMUv3State *s, STE *ste, uint32_t ssid,
+ event->u.f_ste_fetch.addr = addr;
+ return -EINVAL;
+ }
++ for (i = 0; i < ARRAY_SIZE(buf->word); i++) {
++ le32_to_cpus(&buf->word[i]);
++ }
+ return 0;
+ }
+
+@@ -406,7 +426,7 @@ static int smmu_find_ste(SMMUv3State *s, uint32_t sid, STE *ste,
+ return -EINVAL;
+ }
+ if (s->features & SMMU_FEATURE_2LVL_STE) {
+- int l1_ste_offset, l2_ste_offset, max_l2_ste, span;
++ int l1_ste_offset, l2_ste_offset, max_l2_ste, span, i;
+ dma_addr_t l1ptr, l2ptr;
+ STEDesc l1std;
+
+@@ -430,6 +450,9 @@ static int smmu_find_ste(SMMUv3State *s, uint32_t sid, STE *ste,
+ event->u.f_ste_fetch.addr = l1ptr;
+ return -EINVAL;
+ }
++ for (i = 0; i < ARRAY_SIZE(l1std.word); i++) {
++ le32_to_cpus(&l1std.word[i]);
++ }
+
+ span = L1STD_SPAN(&l1std);
+
+diff --git a/hw/block/xen-block.c b/hw/block/xen-block.c
+index 345b284d70..5e45a8b729 100644
+--- a/hw/block/xen-block.c
++++ b/hw/block/xen-block.c
+@@ -759,14 +759,15 @@ static XenBlockDrive *xen_block_drive_create(const char *id,
+ drive = g_new0(XenBlockDrive, 1);
+ drive->id = g_strdup(id);
+
+- file_layer = qdict_new();
+- driver_layer = qdict_new();
+-
+ rc = stat(filename, &st);
+ if (rc) {
+ error_setg_errno(errp, errno, "Could not stat file '%s'", filename);
+ goto done;
+ }
++
++ file_layer = qdict_new();
++ driver_layer = qdict_new();
++
+ if (S_ISBLK(st.st_mode)) {
+ qdict_put_str(file_layer, "driver", "host_device");
+ } else {
+@@ -774,7 +775,6 @@ static XenBlockDrive *xen_block_drive_create(const char *id,
+ }
+
+ qdict_put_str(file_layer, "filename", filename);
+- g_free(filename);
+
+ if (mode && *mode != 'w') {
+ qdict_put_bool(file_layer, "read-only", true);
+@@ -809,7 +809,6 @@ static XenBlockDrive *xen_block_drive_create(const char *id,
+ qdict_put_str(file_layer, "locking", "off");
+
+ qdict_put_str(driver_layer, "driver", driver);
+- g_free(driver);
+
+ qdict_put(driver_layer, "file", file_layer);
+
+@@ -820,6 +819,8 @@ static XenBlockDrive *xen_block_drive_create(const char *id,
+ qobject_unref(driver_layer);
+
+ done:
++ g_free(filename);
++ g_free(driver);
+ if (*errp) {
+ xen_block_drive_destroy(drive, NULL);
+ return NULL;
+diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
+index d025ef2873..6640b669e2 100644
+--- a/hw/i386/intel_iommu.c
++++ b/hw/i386/intel_iommu.c
+@@ -755,6 +755,8 @@ static int vtd_get_pdire_from_pdir_table(dma_addr_t pasid_dir_base,
+ return -VTD_FR_PASID_TABLE_INV;
+ }
+
++ pdire->val = le64_to_cpu(pdire->val);
++
+ return 0;
+ }
+
+@@ -779,6 +781,9 @@ static int vtd_get_pe_in_pasid_leaf_table(IntelIOMMUState *s,
+ pe, entry_size, MEMTXATTRS_UNSPECIFIED)) {
+ return -VTD_FR_PASID_TABLE_INV;
+ }
++ for (size_t i = 0; i < ARRAY_SIZE(pe->val); i++) {
++ pe->val[i] = le64_to_cpu(pe->val[i]);
++ }
+
+ /* Do translation type check */
+ if (!vtd_pe_type_check(x86_iommu, pe)) {
+@@ -3318,14 +3323,15 @@ static int vtd_irte_get(IntelIOMMUState *iommu, uint16_t index,
+ return -VTD_FR_IR_ROOT_INVAL;
+ }
+
+- trace_vtd_ir_irte_get(index, le64_to_cpu(entry->data[1]),
+- le64_to_cpu(entry->data[0]));
++ entry->data[0] = le64_to_cpu(entry->data[0]);
++ entry->data[1] = le64_to_cpu(entry->data[1]);
++
++ trace_vtd_ir_irte_get(index, entry->data[1], entry->data[0]);
+
+ if (!entry->irte.present) {
+ error_report_once("%s: detected non-present IRTE "
+ "(index=%u, high=0x%" PRIx64 ", low=0x%" PRIx64 ")",
+- __func__, index, le64_to_cpu(entry->data[1]),
+- le64_to_cpu(entry->data[0]));
++ __func__, index, entry->data[1], entry->data[0]);
+ return -VTD_FR_IR_ENTRY_P;
+ }
+
+@@ -3333,14 +3339,13 @@ static int vtd_irte_get(IntelIOMMUState *iommu, uint16_t index,
+ entry->irte.__reserved_2) {
+ error_report_once("%s: detected non-zero reserved IRTE "
+ "(index=%u, high=0x%" PRIx64 ", low=0x%" PRIx64 ")",
+- __func__, index, le64_to_cpu(entry->data[1]),
+- le64_to_cpu(entry->data[0]));
++ __func__, index, entry->data[1], entry->data[0]);
+ return -VTD_FR_IR_IRTE_RSVD;
+ }
+
+ if (sid != X86_IOMMU_SID_INVALID) {
+ /* Validate IRTE SID */
+- source_id = le32_to_cpu(entry->irte.source_id);
++ source_id = entry->irte.source_id;
+ switch (entry->irte.sid_vtype) {
+ case VTD_SVT_NONE:
+ break;
+@@ -3394,7 +3399,7 @@ static int vtd_remap_irq_get(IntelIOMMUState *iommu, uint16_t index,
+ irq->trigger_mode = irte.irte.trigger_mode;
+ irq->vector = irte.irte.vector;
+ irq->delivery_mode = irte.irte.delivery_mode;
+- irq->dest = le32_to_cpu(irte.irte.dest_id);
++ irq->dest = irte.irte.dest_id;
+ if (!iommu->intr_eime) {
+ #define VTD_IR_APIC_DEST_MASK (0xff00ULL)
+ #define VTD_IR_APIC_DEST_SHIFT (8)
+@@ -3449,7 +3454,7 @@ static int vtd_interrupt_remap_msi(IntelIOMMUState *iommu,
+ goto out;
+ }
+
+- index = addr.addr.index_h << 15 | le16_to_cpu(addr.addr.index_l);
++ index = addr.addr.index_h << 15 | addr.addr.index_l;
+
+ #define VTD_IR_MSI_DATA_SUBHANDLE (0x0000ffff)
+ #define VTD_IR_MSI_DATA_RESERVED (0xffff0000)
+diff --git a/hw/i386/intel_iommu_internal.h b/hw/i386/intel_iommu_internal.h
+index f090e61e11..e4d43ce48c 100644
+--- a/hw/i386/intel_iommu_internal.h
++++ b/hw/i386/intel_iommu_internal.h
+@@ -321,12 +321,21 @@ typedef enum VTDFaultReason {
+
+ /* Interrupt Entry Cache Invalidation Descriptor: VT-d 6.5.2.7. */
+ struct VTDInvDescIEC {
++#if HOST_BIG_ENDIAN
++ uint64_t reserved_2:16;
++ uint64_t index:16; /* Start index to invalidate */
++ uint64_t index_mask:5; /* 2^N for continuous int invalidation */
++ uint64_t resved_1:22;
++ uint64_t granularity:1; /* If set, it's global IR invalidation */
++ uint64_t type:4; /* Should always be 0x4 */
++#else
+ uint32_t type:4; /* Should always be 0x4 */
+ uint32_t granularity:1; /* If set, it's global IR invalidation */
+ uint32_t resved_1:22;
+ uint32_t index_mask:5; /* 2^N for continuous int invalidation */
+ uint32_t index:16; /* Start index to invalidate */
+ uint32_t reserved_2:16;
++#endif
+ };
+ typedef struct VTDInvDescIEC VTDInvDescIEC;
+
+diff --git a/hw/i386/x86-iommu.c b/hw/i386/x86-iommu.c
+index 01d11325a6..726e9e1d16 100644
+--- a/hw/i386/x86-iommu.c
++++ b/hw/i386/x86-iommu.c
+@@ -63,7 +63,7 @@ void x86_iommu_irq_to_msi_message(X86IOMMUIrq *irq, MSIMessage *msg_out)
+ msg.redir_hint = irq->redir_hint;
+ msg.dest = irq->dest;
+ msg.__addr_hi = irq->dest & 0xffffff00;
+- msg.__addr_head = cpu_to_le32(0xfee);
++ msg.__addr_head = 0xfee;
+ /* Keep this from original MSI address bits */
+ msg.__not_used = irq->msi_addr_last_bits;
+
+diff --git a/hw/ide/piix.c b/hw/ide/piix.c
+index 267dbf37db..066be77c8e 100644
+--- a/hw/ide/piix.c
++++ b/hw/ide/piix.c
+@@ -123,7 +123,7 @@ static void piix_ide_reset(DeviceState *dev)
+ pci_set_word(pci_conf + PCI_COMMAND, 0x0000);
+ pci_set_word(pci_conf + PCI_STATUS,
+ PCI_STATUS_DEVSEL_MEDIUM | PCI_STATUS_FAST_BACK);
+- pci_set_byte(pci_conf + 0x20, 0x01); /* BMIBA: 20-23h */
++ pci_set_long(pci_conf + 0x20, 0x1); /* BMIBA: 20-23h */
+ }
+
+ static int pci_piix_init_ports(PCIIDEState *d)
+diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
+index 4abd49e298..8cd7a400a0 100644
+--- a/hw/net/virtio-net.c
++++ b/hw/net/virtio-net.c
+@@ -3888,6 +3888,7 @@ static void virtio_net_class_init(ObjectClass *klass, void *data)
+ vdc->vmsd = &vmstate_virtio_net_device;
+ vdc->primary_unplug_pending = primary_unplug_pending;
+ vdc->get_vhost = virtio_net_get_vhost;
++ vdc->toggle_device_iotlb = vhost_toggle_device_iotlb;
+ }
+
+ static const TypeInfo virtio_net_info = {
+diff --git a/hw/pci/pci_host.c b/hw/pci/pci_host.c
+index eaf217ff55..d2552cff1b 100644
+--- a/hw/pci/pci_host.c
++++ b/hw/pci/pci_host.c
+@@ -62,6 +62,17 @@ static void pci_adjust_config_limit(PCIBus *bus, uint32_t *limit)
+ }
+ }
+
++static bool is_pci_dev_ejected(PCIDevice *pci_dev)
++{
++ /*
++ * device unplug was requested and the guest acked it,
++ * so we stop responding config accesses even if the
++ * device is not deleted (failover flow)
++ */
++ return pci_dev && pci_dev->partially_hotplugged &&
++ !pci_dev->qdev.pending_deleted_event;
++}
++
+ void pci_host_config_write_common(PCIDevice *pci_dev, uint32_t addr,
+ uint32_t limit, uint32_t val, uint32_t len)
+ {
+@@ -75,7 +86,7 @@ void pci_host_config_write_common(PCIDevice *pci_dev, uint32_t addr,
+ * allowing direct removal of unexposed functions.
+ */
+ if ((pci_dev->qdev.hotplugged && !pci_get_function_0(pci_dev)) ||
+- !pci_dev->has_power) {
++ !pci_dev->has_power || is_pci_dev_ejected(pci_dev)) {
+ return;
+ }
+
+@@ -100,7 +111,7 @@ uint32_t pci_host_config_read_common(PCIDevice *pci_dev, uint32_t addr,
+ * allowing direct removal of unexposed functions.
+ */
+ if ((pci_dev->qdev.hotplugged && !pci_get_function_0(pci_dev)) ||
+- !pci_dev->has_power) {
++ !pci_dev->has_power || is_pci_dev_ejected(pci_dev)) {
+ return ~0x0;
+ }
+
+diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
+index 92a45de4c3..71509f9c7e 100644
+--- a/hw/vfio/pci.c
++++ b/hw/vfio/pci.c
+@@ -3158,6 +3158,9 @@ static void vfio_realize(PCIDevice *pdev, Error **errp)
+ return;
+
+ out_deregister:
++ if (vdev->interrupt == VFIO_INT_INTx) {
++ vfio_intx_disable(vdev);
++ }
+ pci_device_set_intx_routing_notifier(&vdev->pdev, NULL);
+ if (vdev->irqchip_change_notifier.notify) {
+ kvm_irqchip_remove_change_notifier(&vdev->irqchip_change_notifier);
+diff --git a/hw/virtio/vhost-stub.c b/hw/virtio/vhost-stub.c
+index c175148fce..aa858ef3fb 100644
+--- a/hw/virtio/vhost-stub.c
++++ b/hw/virtio/vhost-stub.c
+@@ -15,3 +15,7 @@ bool vhost_user_init(VhostUserState *user, CharBackend *chr, Error **errp)
+ void vhost_user_cleanup(VhostUserState *user)
+ {
+ }
++
++void vhost_toggle_device_iotlb(VirtIODevice *vdev)
++{
++}
+diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
+index f38997b3f6..35274393e2 100644
+--- a/hw/virtio/vhost.c
++++ b/hw/virtio/vhost.c
+@@ -781,7 +781,6 @@ static void vhost_iommu_region_add(MemoryListener *listener,
+ Int128 end;
+ int iommu_idx;
+ IOMMUMemoryRegion *iommu_mr;
+- int ret;
+
+ if (!memory_region_is_iommu(section->mr)) {
+ return;
+@@ -796,7 +795,9 @@ static void vhost_iommu_region_add(MemoryListener *listener,
+ iommu_idx = memory_region_iommu_attrs_to_index(iommu_mr,
+ MEMTXATTRS_UNSPECIFIED);
+ iommu_notifier_init(&iommu->n, vhost_iommu_unmap_notify,
+- IOMMU_NOTIFIER_DEVIOTLB_UNMAP,
++ dev->vdev->device_iotlb_enabled ?
++ IOMMU_NOTIFIER_DEVIOTLB_UNMAP :
++ IOMMU_NOTIFIER_UNMAP,
+ section->offset_within_region,
+ int128_get64(end),
+ iommu_idx);
+@@ -804,16 +805,8 @@ static void vhost_iommu_region_add(MemoryListener *listener,
+ iommu->iommu_offset = section->offset_within_address_space -
+ section->offset_within_region;
+ iommu->hdev = dev;
+- ret = memory_region_register_iommu_notifier(section->mr, &iommu->n, NULL);
+- if (ret) {
+- /*
+- * Some vIOMMUs do not support dev-iotlb yet. If so, try to use the
+- * UNMAP legacy message
+- */
+- iommu->n.notifier_flags = IOMMU_NOTIFIER_UNMAP;
+- memory_region_register_iommu_notifier(section->mr, &iommu->n,
+- &error_fatal);
+- }
++ memory_region_register_iommu_notifier(section->mr, &iommu->n,
++ &error_fatal);
+ QLIST_INSERT_HEAD(&dev->iommu_list, iommu, iommu_next);
+ /* TODO: can replay help performance here? */
+ }
+@@ -841,6 +834,27 @@ static void vhost_iommu_region_del(MemoryListener *listener,
+ }
+ }
+
++void vhost_toggle_device_iotlb(VirtIODevice *vdev)
++{
++ VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(vdev);
++ struct vhost_dev *dev;
++ struct vhost_iommu *iommu;
++
++ if (vdev->vhost_started) {
++ dev = vdc->get_vhost(vdev);
++ } else {
++ return;
++ }
++
++ QLIST_FOREACH(iommu, &dev->iommu_list, iommu_next) {
++ memory_region_unregister_iommu_notifier(iommu->mr, &iommu->n);
++ iommu->n.notifier_flags = vdev->device_iotlb_enabled ?
++ IOMMU_NOTIFIER_DEVIOTLB_UNMAP : IOMMU_NOTIFIER_UNMAP;
++ memory_region_register_iommu_notifier(iommu->mr, &iommu->n,
++ &error_fatal);
++ }
++}
++
+ static int vhost_virtqueue_set_addr(struct vhost_dev *dev,
+ struct vhost_virtqueue *vq,
+ unsigned idx, bool enable_log)
+diff --git a/hw/virtio/virtio-crypto.c b/hw/virtio/virtio-crypto.c
+index a6dbdd32da..406b4e5fd0 100644
+--- a/hw/virtio/virtio-crypto.c
++++ b/hw/virtio/virtio-crypto.c
+@@ -635,6 +635,11 @@ virtio_crypto_sym_op_helper(VirtIODevice *vdev,
+ return NULL;
+ }
+
++ if (unlikely(src_len != dst_len)) {
++ virtio_error(vdev, "sym request src len is different from dst len");
++ return NULL;
++ }
++
+ max_len = (uint64_t)iv_len + aad_len + src_len + dst_len + hash_result_len;
+ if (unlikely(max_len > vcrypto->conf.max_size)) {
+ virtio_error(vdev, "virtio-crypto too big length");
+diff --git a/hw/virtio/virtio-iommu.c b/hw/virtio/virtio-iommu.c
+index 62e07ec2e4..eb82462c95 100644
+--- a/hw/virtio/virtio-iommu.c
++++ b/hw/virtio/virtio-iommu.c
+@@ -727,13 +727,15 @@ static void virtio_iommu_handle_command(VirtIODevice *vdev, VirtQueue *vq)
+ VirtIOIOMMU *s = VIRTIO_IOMMU(vdev);
+ struct virtio_iommu_req_head head;
+ struct virtio_iommu_req_tail tail = {};
+- size_t output_size = sizeof(tail), sz;
+ VirtQueueElement *elem;
+ unsigned int iov_cnt;
+ struct iovec *iov;
+ void *buf = NULL;
++ size_t sz;
+
+ for (;;) {
++ size_t output_size = sizeof(tail);
++
+ elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
+ if (!elem) {
+ return;
+diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
+index a1c9dfa7bb..67e771c373 100644
+--- a/hw/virtio/virtio-pci.c
++++ b/hw/virtio/virtio-pci.c
+@@ -631,6 +631,38 @@ virtio_address_space_read(VirtIOPCIProxy *proxy, hwaddr addr,
+ }
+ }
+
++static void virtio_pci_ats_ctrl_trigger(PCIDevice *pci_dev, bool enable)
++{
++ VirtIOPCIProxy *proxy = VIRTIO_PCI(pci_dev);
++ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
++ VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
++
++ vdev->device_iotlb_enabled = enable;
++
++ if (k->toggle_device_iotlb) {
++ k->toggle_device_iotlb(vdev);
++ }
++}
++
++static void pcie_ats_config_write(PCIDevice *dev, uint32_t address,
++ uint32_t val, int len)
++{
++ uint32_t off;
++ uint16_t ats_cap = dev->exp.ats_cap;
++
++ if (!ats_cap || address < ats_cap) {
++ return;
++ }
++ off = address - ats_cap;
++ if (off >= PCI_EXT_CAP_ATS_SIZEOF) {
++ return;
++ }
++
++ if (range_covers_byte(off, len, PCI_ATS_CTRL + 1)) {
++ virtio_pci_ats_ctrl_trigger(dev, !!(val & PCI_ATS_CTRL_ENABLE));
++ }
++}
++
+ static void virtio_write_config(PCIDevice *pci_dev, uint32_t address,
+ uint32_t val, int len)
+ {
+@@ -644,6 +676,10 @@ static void virtio_write_config(PCIDevice *pci_dev, uint32_t address,
+ pcie_cap_flr_write_config(pci_dev, address, val, len);
+ }
+
++ if (proxy->flags & VIRTIO_PCI_FLAG_ATS) {
++ pcie_ats_config_write(pci_dev, address, val, len);
++ }
++
+ if (range_covers_byte(address, len, PCI_COMMAND)) {
+ if (!(pci_dev->config[PCI_COMMAND] & PCI_COMMAND_MASTER)) {
+ virtio_set_disabled(vdev, true);
+diff --git a/include/hw/i386/intel_iommu.h b/include/hw/i386/intel_iommu.h
+index 46d973e629..7660dda768 100644
+--- a/include/hw/i386/intel_iommu.h
++++ b/include/hw/i386/intel_iommu.h
+@@ -142,37 +142,39 @@ enum {
+ union VTD_IR_TableEntry {
+ struct {
+ #if HOST_BIG_ENDIAN
+- uint32_t __reserved_1:8; /* Reserved 1 */
+- uint32_t vector:8; /* Interrupt Vector */
+- uint32_t irte_mode:1; /* IRTE Mode */
+- uint32_t __reserved_0:3; /* Reserved 0 */
+- uint32_t __avail:4; /* Available spaces for software */
+- uint32_t delivery_mode:3; /* Delivery Mode */
+- uint32_t trigger_mode:1; /* Trigger Mode */
+- uint32_t redir_hint:1; /* Redirection Hint */
+- uint32_t dest_mode:1; /* Destination Mode */
+- uint32_t fault_disable:1; /* Fault Processing Disable */
+- uint32_t present:1; /* Whether entry present/available */
++ uint64_t dest_id:32; /* Destination ID */
++ uint64_t __reserved_1:8; /* Reserved 1 */
++ uint64_t vector:8; /* Interrupt Vector */
++ uint64_t irte_mode:1; /* IRTE Mode */
++ uint64_t __reserved_0:3; /* Reserved 0 */
++ uint64_t __avail:4; /* Available spaces for software */
++ uint64_t delivery_mode:3; /* Delivery Mode */
++ uint64_t trigger_mode:1; /* Trigger Mode */
++ uint64_t redir_hint:1; /* Redirection Hint */
++ uint64_t dest_mode:1; /* Destination Mode */
++ uint64_t fault_disable:1; /* Fault Processing Disable */
++ uint64_t present:1; /* Whether entry present/available */
+ #else
+- uint32_t present:1; /* Whether entry present/available */
+- uint32_t fault_disable:1; /* Fault Processing Disable */
+- uint32_t dest_mode:1; /* Destination Mode */
+- uint32_t redir_hint:1; /* Redirection Hint */
+- uint32_t trigger_mode:1; /* Trigger Mode */
+- uint32_t delivery_mode:3; /* Delivery Mode */
+- uint32_t __avail:4; /* Available spaces for software */
+- uint32_t __reserved_0:3; /* Reserved 0 */
+- uint32_t irte_mode:1; /* IRTE Mode */
+- uint32_t vector:8; /* Interrupt Vector */
+- uint32_t __reserved_1:8; /* Reserved 1 */
++ uint64_t present:1; /* Whether entry present/available */
++ uint64_t fault_disable:1; /* Fault Processing Disable */
++ uint64_t dest_mode:1; /* Destination Mode */
++ uint64_t redir_hint:1; /* Redirection Hint */
++ uint64_t trigger_mode:1; /* Trigger Mode */
++ uint64_t delivery_mode:3; /* Delivery Mode */
++ uint64_t __avail:4; /* Available spaces for software */
++ uint64_t __reserved_0:3; /* Reserved 0 */
++ uint64_t irte_mode:1; /* IRTE Mode */
++ uint64_t vector:8; /* Interrupt Vector */
++ uint64_t __reserved_1:8; /* Reserved 1 */
++ uint64_t dest_id:32; /* Destination ID */
+ #endif
+- uint32_t dest_id; /* Destination ID */
+- uint16_t source_id; /* Source-ID */
+ #if HOST_BIG_ENDIAN
+ uint64_t __reserved_2:44; /* Reserved 2 */
+ uint64_t sid_vtype:2; /* Source-ID Validation Type */
+ uint64_t sid_q:2; /* Source-ID Qualifier */
++ uint64_t source_id:16; /* Source-ID */
+ #else
++ uint64_t source_id:16; /* Source-ID */
+ uint64_t sid_q:2; /* Source-ID Qualifier */
+ uint64_t sid_vtype:2; /* Source-ID Validation Type */
+ uint64_t __reserved_2:44; /* Reserved 2 */
+diff --git a/include/hw/i386/x86-iommu.h b/include/hw/i386/x86-iommu.h
+index 7637edb430..02dc2fe9ee 100644
+--- a/include/hw/i386/x86-iommu.h
++++ b/include/hw/i386/x86-iommu.h
+@@ -88,40 +88,42 @@ struct X86IOMMU_MSIMessage {
+ union {
+ struct {
+ #if HOST_BIG_ENDIAN
+- uint32_t __addr_head:12; /* 0xfee */
+- uint32_t dest:8;
+- uint32_t __reserved:8;
+- uint32_t redir_hint:1;
+- uint32_t dest_mode:1;
+- uint32_t __not_used:2;
++ uint64_t __addr_hi:32;
++ uint64_t __addr_head:12; /* 0xfee */
++ uint64_t dest:8;
++ uint64_t __reserved:8;
++ uint64_t redir_hint:1;
++ uint64_t dest_mode:1;
++ uint64_t __not_used:2;
+ #else
+- uint32_t __not_used:2;
+- uint32_t dest_mode:1;
+- uint32_t redir_hint:1;
+- uint32_t __reserved:8;
+- uint32_t dest:8;
+- uint32_t __addr_head:12; /* 0xfee */
++ uint64_t __not_used:2;
++ uint64_t dest_mode:1;
++ uint64_t redir_hint:1;
++ uint64_t __reserved:8;
++ uint64_t dest:8;
++ uint64_t __addr_head:12; /* 0xfee */
++ uint64_t __addr_hi:32;
+ #endif
+- uint32_t __addr_hi;
+ } QEMU_PACKED;
+ uint64_t msi_addr;
+ };
+ union {
+ struct {
+ #if HOST_BIG_ENDIAN
+- uint16_t trigger_mode:1;
+- uint16_t level:1;
+- uint16_t __resved:3;
+- uint16_t delivery_mode:3;
+- uint16_t vector:8;
++ uint32_t __resved1:16;
++ uint32_t trigger_mode:1;
++ uint32_t level:1;
++ uint32_t __resved:3;
++ uint32_t delivery_mode:3;
++ uint32_t vector:8;
+ #else
+- uint16_t vector:8;
+- uint16_t delivery_mode:3;
+- uint16_t __resved:3;
+- uint16_t level:1;
+- uint16_t trigger_mode:1;
++ uint32_t vector:8;
++ uint32_t delivery_mode:3;
++ uint32_t __resved:3;
++ uint32_t level:1;
++ uint32_t trigger_mode:1;
++ uint32_t __resved1:16;
+ #endif
+- uint16_t __resved1;
+ } QEMU_PACKED;
+ uint32_t msi_data;
+ };
+diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h
+index 67a6807fac..c82dbb2c32 100644
+--- a/include/hw/virtio/vhost.h
++++ b/include/hw/virtio/vhost.h
+@@ -297,6 +297,7 @@ bool vhost_has_free_slot(void);
+ int vhost_net_set_backend(struct vhost_dev *hdev,
+ struct vhost_vring_file *file);
+
++void vhost_toggle_device_iotlb(VirtIODevice *vdev);
+ int vhost_device_iotlb_miss(struct vhost_dev *dev, uint64_t iova, int write);
+
+ int vhost_virtqueue_start(struct vhost_dev *dev, struct VirtIODevice *vdev,
+diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
+index acfd4df125..96a56430a6 100644
+--- a/include/hw/virtio/virtio.h
++++ b/include/hw/virtio/virtio.h
+@@ -135,6 +135,7 @@ struct VirtIODevice
+ AddressSpace *dma_as;
+ QLIST_HEAD(, VirtQueue) *vector_queues;
+ QTAILQ_ENTRY(VirtIODevice) next;
++ bool device_iotlb_enabled;
+ };
+
+ struct VirtioDeviceClass {
+@@ -192,6 +193,7 @@ struct VirtioDeviceClass {
+ const VMStateDescription *vmsd;
+ bool (*primary_unplug_pending)(void *opaque);
+ struct vhost_dev *(*get_vhost)(VirtIODevice *vdev);
++ void (*toggle_device_iotlb)(VirtIODevice *vdev);
+ };
+
+ void virtio_instance_init_common(Object *proxy_obj, void *data,
+diff --git a/include/io/channel-tls.h b/include/io/channel-tls.h
+index 5672479e9e..26c67f17e2 100644
+--- a/include/io/channel-tls.h
++++ b/include/io/channel-tls.h
+@@ -48,6 +48,7 @@ struct QIOChannelTLS {
+ QIOChannel *master;
+ QCryptoTLSSession *session;
+ QIOChannelShutdown shutdown;
++ guint hs_ioc_tag;
+ };
+
+ /**
+diff --git a/io/channel-tls.c b/io/channel-tls.c
+index 4ce08ccc28..a91efb57f3 100644
+--- a/io/channel-tls.c
++++ b/io/channel-tls.c
+@@ -198,12 +198,13 @@ static void qio_channel_tls_handshake_task(QIOChannelTLS *ioc,
+ }
+
+ trace_qio_channel_tls_handshake_pending(ioc, status);
+- qio_channel_add_watch_full(ioc->master,
+- condition,
+- qio_channel_tls_handshake_io,
+- data,
+- NULL,
+- context);
++ ioc->hs_ioc_tag =
++ qio_channel_add_watch_full(ioc->master,
++ condition,
++ qio_channel_tls_handshake_io,
++ data,
++ NULL,
++ context);
+ }
+ }
+
+@@ -218,6 +219,7 @@ static gboolean qio_channel_tls_handshake_io(QIOChannel *ioc,
+ QIOChannelTLS *tioc = QIO_CHANNEL_TLS(
+ qio_task_get_source(task));
+
++ tioc->hs_ioc_tag = 0;
+ g_free(data);
+ qio_channel_tls_handshake_task(tioc, task, context);
+
+@@ -377,6 +379,10 @@ static int qio_channel_tls_close(QIOChannel *ioc,
+ {
+ QIOChannelTLS *tioc = QIO_CHANNEL_TLS(ioc);
+
++ if (tioc->hs_ioc_tag) {
++ g_clear_handle_id(&tioc->hs_ioc_tag, g_source_remove);
++ }
++
+ return qio_channel_close(tioc->master, errp);
+ }
+
+diff --git a/linux-user/arm/cpu_loop.c b/linux-user/arm/cpu_loop.c
+index c0790f3246..85804c367a 100644
+--- a/linux-user/arm/cpu_loop.c
++++ b/linux-user/arm/cpu_loop.c
+@@ -117,8 +117,9 @@ static void arm_kernel_cmpxchg32_helper(CPUARMState *env)
+ {
+ uint32_t oldval, newval, val, addr, cpsr, *host_addr;
+
+- oldval = env->regs[0];
+- newval = env->regs[1];
++ /* Swap if host != guest endianness, for the host cmpxchg below */
++ oldval = tswap32(env->regs[0]);
++ newval = tswap32(env->regs[1]);
+ addr = env->regs[2];
+
+ mmap_lock();
+@@ -174,6 +175,10 @@ static void arm_kernel_cmpxchg64_helper(CPUARMState *env)
+ return;
+ }
+
++ /* Swap if host != guest endianness, for the host cmpxchg below */
++ oldval = tswap64(oldval);
++ newval = tswap64(newval);
++
+ #ifdef CONFIG_ATOMIC64
+ val = qatomic_cmpxchg__nocheck(host_addr, oldval, newval);
+ cpsr = (val == oldval) * CPSR_C;
+diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c
+index e533f8a348..1b1a27de02 100644
+--- a/net/vhost-vdpa.c
++++ b/net/vhost-vdpa.c
+@@ -403,8 +403,9 @@ static int vhost_vdpa_net_load_mac(VhostVDPAState *s, const VirtIONet *n)
+ if (unlikely(dev_written < 0)) {
+ return dev_written;
+ }
+-
+- return *s->status != VIRTIO_NET_OK;
++ if (*s->status != VIRTIO_NET_OK) {
++ return -EIO;
++ }
+ }
+
+ return 0;
+@@ -428,8 +429,11 @@ static int vhost_vdpa_net_load_mq(VhostVDPAState *s,
+ if (unlikely(dev_written < 0)) {
+ return dev_written;
+ }
++ if (*s->status != VIRTIO_NET_OK) {
++ return -EIO;
++ }
+
+- return *s->status != VIRTIO_NET_OK;
++ return 0;
+ }
+
+ static int vhost_vdpa_net_load(NetClientState *nc)
+@@ -525,7 +529,16 @@ out:
+ error_report("Bad device CVQ written length");
+ }
+ vhost_svq_push_elem(svq, elem, MIN(in_len, sizeof(status)));
+- g_free(elem);
++ /*
++ * `elem` belongs to vhost_vdpa_net_handle_ctrl_avail() only when
++ * the function successfully forwards the CVQ command, indicated
++ * by a non-negative value of `dev_written`. Otherwise, it still
++ * belongs to SVQ.
++ * This function should only free the `elem` when it owns.
++ */
++ if (dev_written >= 0) {
++ g_free(elem);
++ }
+ return dev_written < 0 ? dev_written : 0;
+ }
+
+diff --git a/qemu-nbd.c b/qemu-nbd.c
+index 0cd5aa6f02..f71f5125d8 100644
+--- a/qemu-nbd.c
++++ b/qemu-nbd.c
+@@ -272,9 +272,14 @@ static void *show_parts(void *arg)
+ return NULL;
+ }
+
++struct NbdClientOpts {
++ char *device;
++ bool fork_process;
++};
++
+ static void *nbd_client_thread(void *arg)
+ {
+- char *device = arg;
++ struct NbdClientOpts *opts = arg;
+ NBDExportInfo info = { .request_sizes = false, .name = g_strdup("") };
+ QIOChannelSocket *sioc;
+ int fd = -1;
+@@ -298,10 +303,10 @@ static void *nbd_client_thread(void *arg)
+ goto out;
+ }
+
+- fd = open(device, O_RDWR);
++ fd = open(opts->device, O_RDWR);
+ if (fd < 0) {
+ /* Linux-only, we can use %m in printf. */
+- error_report("Failed to open %s: %m", device);
++ error_report("Failed to open %s: %m", opts->device);
+ goto out;
+ }
+
+@@ -311,11 +316,11 @@ static void *nbd_client_thread(void *arg)
+ }
+
+ /* update partition table */
+- pthread_create(&show_parts_thread, NULL, show_parts, device);
++ pthread_create(&show_parts_thread, NULL, show_parts, opts->device);
+
+- if (verbose) {
++ if (verbose && !opts->fork_process) {
+ fprintf(stderr, "NBD device %s is now connected to %s\n",
+- device, srcpath);
++ opts->device, srcpath);
+ } else {
+ /* Close stderr so that the qemu-nbd process exits. */
+ dup2(STDOUT_FILENO, STDERR_FILENO);
+@@ -575,11 +580,13 @@ int main(int argc, char **argv)
+ bool writethrough = false; /* Client will flush as needed. */
+ bool fork_process = false;
+ bool list = false;
+- int old_stderr = -1;
+ unsigned socket_activation;
+ const char *pid_file_name = NULL;
+ const char *selinux_label = NULL;
+ BlockExportOptions *export_opts;
++#if HAVE_NBD_DEVICE
++ struct NbdClientOpts opts;
++#endif
+
+ #ifdef CONFIG_POSIX
+ os_setup_early_signal_handling();
+@@ -930,11 +937,6 @@ int main(int argc, char **argv)
+ } else if (pid == 0) {
+ close(stderr_fd[0]);
+
+- /* Remember parent's stderr if we will be restoring it. */
+- if (fork_process) {
+- old_stderr = dup(STDERR_FILENO);
+- }
+-
+ ret = qemu_daemon(1, 0);
+
+ /* Temporarily redirect stderr to the parent's pipe... */
+@@ -1123,8 +1125,12 @@ int main(int argc, char **argv)
+ if (device) {
+ #if HAVE_NBD_DEVICE
+ int ret;
++ opts = (struct NbdClientOpts) {
++ .device = device,
++ .fork_process = fork_process,
++ };
+
+- ret = pthread_create(&client_thread, NULL, nbd_client_thread, device);
++ ret = pthread_create(&client_thread, NULL, nbd_client_thread, &opts);
+ if (ret != 0) {
+ error_report("Failed to create client thread: %s", strerror(ret));
+ exit(EXIT_FAILURE);
+@@ -1150,8 +1156,7 @@ int main(int argc, char **argv)
+ }
+
+ if (fork_process) {
+- dup2(old_stderr, STDERR_FILENO);
+- close(old_stderr);
++ dup2(STDOUT_FILENO, STDERR_FILENO);
+ }
+
+ state = RUNNING;
+diff --git a/qga/installer/qemu-ga.wxs b/qga/installer/qemu-ga.wxs
+index 3442383627..949ba07fd2 100644
+--- a/qga/installer/qemu-ga.wxs
++++ b/qga/installer/qemu-ga.wxs
+@@ -116,22 +116,22 @@
+ </Directory>
+ </Directory>
+
+- <Property Id="cmd" Value="cmd.exe"/>
++ <Property Id="rundll" Value="rundll32.exe"/>
+ <Property Id="REINSTALLMODE" Value="amus"/>
+
+ <?ifdef var.InstallVss?>
+ <CustomAction Id="RegisterCom"
+- ExeCommand='/c "[qemu_ga_directory]qemu-ga.exe" -s vss-install'
++ ExeCommand='"[qemu_ga_directory]qga-vss.dll",DLLCOMRegister'
+ Execute="deferred"
+- Property="cmd"
++ Property="rundll"
+ Impersonate="no"
+ Return="check"
+ >
+ </CustomAction>
+ <CustomAction Id="UnRegisterCom"
+- ExeCommand='/c "[qemu_ga_directory]qemu-ga.exe" -s vss-uninstall'
++ ExeCommand='"[qemu_ga_directory]qga-vss.dll",DLLCOMUnregister'
+ Execute="deferred"
+- Property="cmd"
++ Property="rundll"
+ Impersonate="no"
+ Return="check"
+ >
+diff --git a/qga/vss-win32/install.cpp b/qga/vss-win32/install.cpp
+index b8087e5baa..ff93b08a9e 100644
+--- a/qga/vss-win32/install.cpp
++++ b/qga/vss-win32/install.cpp
+@@ -357,6 +357,15 @@ out:
+ return hr;
+ }
+
++STDAPI_(void) CALLBACK DLLCOMRegister(HWND, HINSTANCE, LPSTR, int)
++{
++ COMRegister();
++}
++
++STDAPI_(void) CALLBACK DLLCOMUnregister(HWND, HINSTANCE, LPSTR, int)
++{
++ COMUnregister();
++}
+
+ static BOOL CreateRegistryKey(LPCTSTR key, LPCTSTR value, LPCTSTR data)
+ {
+diff --git a/qga/vss-win32/qga-vss.def b/qga/vss-win32/qga-vss.def
+index 927782c31b..ee97a81427 100644
+--- a/qga/vss-win32/qga-vss.def
++++ b/qga/vss-win32/qga-vss.def
+@@ -1,6 +1,8 @@
+ LIBRARY "QGA-PROVIDER.DLL"
+
+ EXPORTS
++ DLLCOMRegister
++ DLLCOMUnregister
+ COMRegister PRIVATE
+ COMUnregister PRIVATE
+ DllCanUnloadNow PRIVATE
+diff --git a/target/arm/translate.c b/target/arm/translate.c
+index a06da05640..9cf4a6819e 100644
+--- a/target/arm/translate.c
++++ b/target/arm/translate.c
+@@ -9030,7 +9030,7 @@ static bool trans_IT(DisasContext *s, arg_IT *a)
+ /* v8.1M CSEL/CSINC/CSNEG/CSINV */
+ static bool trans_CSEL(DisasContext *s, arg_CSEL *a)
+ {
+- TCGv_i32 rn, rm, zero;
++ TCGv_i32 rn, rm;
+ DisasCompare c;
+
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
+@@ -9048,16 +9048,17 @@ static bool trans_CSEL(DisasContext *s, arg_CSEL *a)
+ }
+
+ /* In this insn input reg fields of 0b1111 mean "zero", not "PC" */
+- zero = tcg_constant_i32(0);
++ rn = tcg_temp_new_i32();
++ rm = tcg_temp_new_i32();
+ if (a->rn == 15) {
+- rn = zero;
++ tcg_gen_movi_i32(rn, 0);
+ } else {
+- rn = load_reg(s, a->rn);
++ load_reg_var(s, rn, a->rn);
+ }
+ if (a->rm == 15) {
+- rm = zero;
++ tcg_gen_movi_i32(rm, 0);
+ } else {
+- rm = load_reg(s, a->rm);
++ load_reg_var(s, rm, a->rm);
+ }
+
+ switch (a->op) {
+@@ -9077,7 +9078,7 @@ static bool trans_CSEL(DisasContext *s, arg_CSEL *a)
+ }
+
+ arm_test_cc(&c, a->fcond);
+- tcg_gen_movcond_i32(c.cond, rn, c.value, zero, rn, rm);
++ tcg_gen_movcond_i32(c.cond, rn, c.value, tcg_constant_i32(0), rn, rm);
+ arm_free_cc(&c);
+
+ store_reg(s, a->rd, rn);
+diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h
+index 6f3b6beecf..6f441f159b 100644
+--- a/target/hppa/cpu.h
++++ b/target/hppa/cpu.h
+@@ -168,6 +168,9 @@ typedef struct {
+ } hppa_tlb_entry;
+
+ typedef struct CPUArchState {
++ target_ureg iaoq_f; /* front */
++ target_ureg iaoq_b; /* back, aka next instruction */
++
+ target_ureg gr[32];
+ uint64_t fr[32];
+ uint64_t sr[8]; /* stored shifted into place for gva */
+@@ -186,8 +189,6 @@ typedef struct CPUArchState {
+ target_ureg psw_cb; /* in least significant bit of next nibble */
+ target_ureg psw_cb_msb; /* boolean */
+
+- target_ureg iaoq_f; /* front */
+- target_ureg iaoq_b; /* back, aka next instruction */
+ uint64_t iasq_f;
+ uint64_t iasq_b;
+
+diff --git a/target/i386/tcg/decode-new.c.inc b/target/i386/tcg/decode-new.c.inc
+index c2ee712561..ee4f4a899f 100644
+--- a/target/i386/tcg/decode-new.c.inc
++++ b/target/i386/tcg/decode-new.c.inc
+@@ -1815,16 +1815,18 @@ static void disas_insn_new(DisasContext *s, CPUState *cpu, int b)
+ }
+ break;
+
+- case X86_SPECIAL_MMX:
+- if (!(s->prefix & (PREFIX_REPZ | PREFIX_REPNZ | PREFIX_DATA))) {
+- gen_helper_enter_mmx(cpu_env);
+- }
++ default:
+ break;
+ }
+
+ if (!validate_vex(s, &decode)) {
+ return;
+ }
++ if (decode.e.special == X86_SPECIAL_MMX &&
++ !(s->prefix & (PREFIX_REPZ | PREFIX_REPNZ | PREFIX_DATA))) {
++ gen_helper_enter_mmx(cpu_env);
++ }
++
+ if (decode.op[0].has_ea || decode.op[1].has_ea || decode.op[2].has_ea) {
+ gen_load_ea(s, &decode.mem, decode.e.vex_class == 12);
+ }
+diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
+index e15c633b0b..6fc583f3e8 100644
+--- a/target/loongarch/cpu.h
++++ b/target/loongarch/cpu.h
+@@ -317,6 +317,7 @@ typedef struct CPUArchState {
+ uint64_t CSR_DBG;
+ uint64_t CSR_DERA;
+ uint64_t CSR_DSAVE;
++ uint64_t CSR_CPUID;
+
+ #ifndef CONFIG_USER_ONLY
+ LoongArchTLB tlb[LOONGARCH_TLB_MAX];
+diff --git a/target/loongarch/csr_helper.c b/target/loongarch/csr_helper.c
+index 7e02787895..b778e6952d 100644
+--- a/target/loongarch/csr_helper.c
++++ b/target/loongarch/csr_helper.c
+@@ -36,6 +36,15 @@ target_ulong helper_csrrd_pgd(CPULoongArchState *env)
+ return v;
+ }
+
++target_ulong helper_csrrd_cpuid(CPULoongArchState *env)
++{
++ LoongArchCPU *lac = env_archcpu(env);
++
++ env->CSR_CPUID = CPU(lac)->cpu_index;
++
++ return env->CSR_CPUID;
++}
++
+ target_ulong helper_csrrd_tval(CPULoongArchState *env)
+ {
+ LoongArchCPU *cpu = env_archcpu(env);
+diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
+index 9c01823a26..f47b0f2d05 100644
+--- a/target/loongarch/helper.h
++++ b/target/loongarch/helper.h
+@@ -98,6 +98,7 @@ DEF_HELPER_1(rdtime_d, i64, env)
+ #ifndef CONFIG_USER_ONLY
+ /* CSRs helper */
+ DEF_HELPER_1(csrrd_pgd, i64, env)
++DEF_HELPER_1(csrrd_cpuid, i64, env)
+ DEF_HELPER_1(csrrd_tval, i64, env)
+ DEF_HELPER_2(csrwr_estat, i64, env, tl)
+ DEF_HELPER_2(csrwr_asid, i64, env, tl)
+diff --git a/target/loongarch/insn_trans/trans_privileged.c.inc b/target/loongarch/insn_trans/trans_privileged.c.inc
+index 40f82becb0..e3d92c7a22 100644
+--- a/target/loongarch/insn_trans/trans_privileged.c.inc
++++ b/target/loongarch/insn_trans/trans_privileged.c.inc
+@@ -99,13 +99,7 @@ static const CSRInfo csr_info[] = {
+ CSR_OFF(PWCH),
+ CSR_OFF(STLBPS),
+ CSR_OFF(RVACFG),
+- [LOONGARCH_CSR_CPUID] = {
+- .offset = (int)offsetof(CPUState, cpu_index)
+- - (int)offsetof(LoongArchCPU, env),
+- .flags = CSRFL_READONLY,
+- .readfn = NULL,
+- .writefn = NULL
+- },
++ CSR_OFF_FUNCS(CPUID, CSRFL_READONLY, gen_helper_csrrd_cpuid, NULL),
+ CSR_OFF_FLAGS(PRCFG1, CSRFL_READONLY),
+ CSR_OFF_FLAGS(PRCFG2, CSRFL_READONLY),
+ CSR_OFF_FLAGS(PRCFG3, CSRFL_READONLY),
+diff --git a/target/m68k/m68k-semi.c b/target/m68k/m68k-semi.c
+index 87b1314925..7a88205ce7 100644
+--- a/target/m68k/m68k-semi.c
++++ b/target/m68k/m68k-semi.c
+@@ -165,7 +165,7 @@ void do_m68k_semihosting(CPUM68KState *env, int nr)
+ GET_ARG64(2);
+ GET_ARG64(3);
+ semihost_sys_lseek(cs, m68k_semi_u64_cb, arg0,
+- deposit64(arg2, arg1, 32, 32), arg3);
++ deposit64(arg2, 32, 32, arg1), arg3);
+ break;
+
+ case HOSTED_RENAME:
+diff --git a/target/nios2/nios2-semi.c b/target/nios2/nios2-semi.c
+index f76e8588c5..19a7d0e763 100644
+--- a/target/nios2/nios2-semi.c
++++ b/target/nios2/nios2-semi.c
+@@ -132,8 +132,8 @@ void do_nios2_semihosting(CPUNios2State *env)
+ args = env->regs[R_ARG1];
+ switch (nr) {
+ case HOSTED_EXIT:
+- gdb_exit(env->regs[R_ARG0]);
+- exit(env->regs[R_ARG0]);
++ gdb_exit(env->regs[R_ARG1]);
++ exit(env->regs[R_ARG1]);
+
+ case HOSTED_OPEN:
+ GET_ARG(0);
+@@ -168,7 +168,7 @@ void do_nios2_semihosting(CPUNios2State *env)
+ GET_ARG64(2);
+ GET_ARG64(3);
+ semihost_sys_lseek(cs, nios2_semi_u64_cb, arg0,
+- deposit64(arg2, arg1, 32, 32), arg3);
++ deposit64(arg2, 32, 32, arg1), arg3);
+ break;
+
+ case HOSTED_RENAME:
+diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
+index 6cf88f635a..839d95c1eb 100644
+--- a/target/ppc/excp_helper.c
++++ b/target/ppc/excp_helper.c
+@@ -2645,6 +2645,12 @@ void helper_pminsn(CPUPPCState *env, uint32_t insn)
+ env->resume_as_sreset = (insn != PPC_PM_STOP) ||
+ (env->spr[SPR_PSSCR] & PSSCR_EC);
+
++ /* HDECR is not to wake from PM state, it may have already fired */
++ if (env->resume_as_sreset) {
++ PowerPCCPU *cpu = env_archcpu(env);
++ ppc_set_irq(cpu, PPC_INTERRUPT_HDECR, 0);
++ }
++
+ ppc_maybe_interrupt(env);
+ }
+ #endif /* defined(TARGET_PPC64) */
+diff --git a/target/ppc/mmu-hash64.c b/target/ppc/mmu-hash64.c
+index b9b31fd276..64c2a9cab3 100644
+--- a/target/ppc/mmu-hash64.c
++++ b/target/ppc/mmu-hash64.c
+@@ -770,7 +770,8 @@ static bool ppc_hash64_use_vrma(CPUPPCState *env)
+ }
+ }
+
+-static void ppc_hash64_set_isi(CPUState *cs, int mmu_idx, uint64_t error_code)
++static void ppc_hash64_set_isi(CPUState *cs, int mmu_idx, uint64_t slb_vsid,
++ uint64_t error_code)
+ {
+ CPUPPCState *env = &POWERPC_CPU(cs)->env;
+ bool vpm;
+@@ -782,13 +783,15 @@ static void ppc_hash64_set_isi(CPUState *cs, int mmu_idx, uint64_t error_code)
+ }
+ if (vpm && !mmuidx_hv(mmu_idx)) {
+ cs->exception_index = POWERPC_EXCP_HISI;
++ env->spr[SPR_ASDR] = slb_vsid;
+ } else {
+ cs->exception_index = POWERPC_EXCP_ISI;
+ }
+ env->error_code = error_code;
+ }
+
+-static void ppc_hash64_set_dsi(CPUState *cs, int mmu_idx, uint64_t dar, uint64_t dsisr)
++static void ppc_hash64_set_dsi(CPUState *cs, int mmu_idx, uint64_t slb_vsid,
++ uint64_t dar, uint64_t dsisr)
+ {
+ CPUPPCState *env = &POWERPC_CPU(cs)->env;
+ bool vpm;
+@@ -802,6 +805,7 @@ static void ppc_hash64_set_dsi(CPUState *cs, int mmu_idx, uint64_t dar, uint64_t
+ cs->exception_index = POWERPC_EXCP_HDSI;
+ env->spr[SPR_HDAR] = dar;
+ env->spr[SPR_HDSISR] = dsisr;
++ env->spr[SPR_ASDR] = slb_vsid;
+ } else {
+ cs->exception_index = POWERPC_EXCP_DSI;
+ env->spr[SPR_DAR] = dar;
+@@ -870,12 +874,46 @@ static target_ulong rmls_limit(PowerPCCPU *cpu)
+ return rma_sizes[rmls];
+ }
+
+-static int build_vrma_slbe(PowerPCCPU *cpu, ppc_slb_t *slb)
++/* Return the LLP in SLB_VSID format */
++static uint64_t get_vrma_llp(PowerPCCPU *cpu)
+ {
+ CPUPPCState *env = &cpu->env;
+- target_ulong lpcr = env->spr[SPR_LPCR];
+- uint32_t vrmasd = (lpcr & LPCR_VRMASD) >> LPCR_VRMASD_SHIFT;
+- target_ulong vsid = SLB_VSID_VRMA | ((vrmasd << 4) & SLB_VSID_LLP_MASK);
++ uint64_t llp;
++
++ if (env->mmu_model == POWERPC_MMU_3_00) {
++ ppc_v3_pate_t pate;
++ uint64_t ps, l, lp;
++
++ /*
++ * ISA v3.0 removes the LPCR[VRMASD] field and puts the VRMA base
++ * page size (L||LP equivalent) in the PS field in the HPT partition
++ * table entry.
++ */
++ if (!ppc64_v3_get_pate(cpu, cpu->env.spr[SPR_LPIDR], &pate)) {
++ error_report("Bad VRMA with no partition table entry");
++ return 0;
++ }
++ ps = PATE0_GET_PS(pate.dw0);
++ /* PS has L||LP in 3 consecutive bits, put them into SLB LLP format */
++ l = (ps >> 2) & 0x1;
++ lp = ps & 0x3;
++ llp = (l << SLB_VSID_L_SHIFT) | (lp << SLB_VSID_LP_SHIFT);
++
++ } else {
++ uint64_t lpcr = env->spr[SPR_LPCR];
++ target_ulong vrmasd = (lpcr & LPCR_VRMASD) >> LPCR_VRMASD_SHIFT;
++
++ /* VRMASD LLP matches SLB format, just shift and mask it */
++ llp = (vrmasd << SLB_VSID_LP_SHIFT) & SLB_VSID_LLP_MASK;
++ }
++
++ return llp;
++}
++
++static int build_vrma_slbe(PowerPCCPU *cpu, ppc_slb_t *slb)
++{
++ uint64_t llp = get_vrma_llp(cpu);
++ target_ulong vsid = SLB_VSID_VRMA | llp;
+ int i;
+
+ for (i = 0; i < PPC_PAGE_SIZES_MAX_SZ; i++) {
+@@ -893,8 +931,7 @@ static int build_vrma_slbe(PowerPCCPU *cpu, ppc_slb_t *slb)
+ }
+ }
+
+- error_report("Bad page size encoding in LPCR[VRMASD]; LPCR=0x"
+- TARGET_FMT_lx, lpcr);
++ error_report("Bad VRMA page size encoding 0x" TARGET_FMT_lx, llp);
+
+ return -1;
+ }
+@@ -963,13 +1000,13 @@ bool ppc_hash64_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type,
+ }
+ switch (access_type) {
+ case MMU_INST_FETCH:
+- ppc_hash64_set_isi(cs, mmu_idx, SRR1_PROTFAULT);
++ ppc_hash64_set_isi(cs, mmu_idx, 0, SRR1_PROTFAULT);
+ break;
+ case MMU_DATA_LOAD:
+- ppc_hash64_set_dsi(cs, mmu_idx, eaddr, DSISR_PROTFAULT);
++ ppc_hash64_set_dsi(cs, mmu_idx, 0, eaddr, DSISR_PROTFAULT);
+ break;
+ case MMU_DATA_STORE:
+- ppc_hash64_set_dsi(cs, mmu_idx, eaddr,
++ ppc_hash64_set_dsi(cs, mmu_idx, 0, eaddr,
+ DSISR_PROTFAULT | DSISR_ISSTORE);
+ break;
+ default:
+@@ -1022,7 +1059,7 @@ bool ppc_hash64_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type,
+ /* 3. Check for segment level no-execute violation */
+ if (access_type == MMU_INST_FETCH && (slb->vsid & SLB_VSID_N)) {
+ if (guest_visible) {
+- ppc_hash64_set_isi(cs, mmu_idx, SRR1_NOEXEC_GUARD);
++ ppc_hash64_set_isi(cs, mmu_idx, slb->vsid, SRR1_NOEXEC_GUARD);
+ }
+ return false;
+ }
+@@ -1035,13 +1072,14 @@ bool ppc_hash64_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type,
+ }
+ switch (access_type) {
+ case MMU_INST_FETCH:
+- ppc_hash64_set_isi(cs, mmu_idx, SRR1_NOPTE);
++ ppc_hash64_set_isi(cs, mmu_idx, slb->vsid, SRR1_NOPTE);
+ break;
+ case MMU_DATA_LOAD:
+- ppc_hash64_set_dsi(cs, mmu_idx, eaddr, DSISR_NOPTE);
++ ppc_hash64_set_dsi(cs, mmu_idx, slb->vsid, eaddr, DSISR_NOPTE);
+ break;
+ case MMU_DATA_STORE:
+- ppc_hash64_set_dsi(cs, mmu_idx, eaddr, DSISR_NOPTE | DSISR_ISSTORE);
++ ppc_hash64_set_dsi(cs, mmu_idx, slb->vsid, eaddr,
++ DSISR_NOPTE | DSISR_ISSTORE);
+ break;
+ default:
+ g_assert_not_reached();
+@@ -1075,7 +1113,7 @@ bool ppc_hash64_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type,
+ if (PAGE_EXEC & ~amr_prot) {
+ srr1 |= SRR1_IAMR; /* Access violates virt pg class key prot */
+ }
+- ppc_hash64_set_isi(cs, mmu_idx, srr1);
++ ppc_hash64_set_isi(cs, mmu_idx, slb->vsid, srr1);
+ } else {
+ int dsisr = 0;
+ if (need_prot & ~pp_prot) {
+@@ -1087,7 +1125,7 @@ bool ppc_hash64_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type,
+ if (need_prot & ~amr_prot) {
+ dsisr |= DSISR_AMR;
+ }
+- ppc_hash64_set_dsi(cs, mmu_idx, eaddr, dsisr);
++ ppc_hash64_set_dsi(cs, mmu_idx, slb->vsid, eaddr, dsisr);
+ }
+ return false;
+ }
+diff --git a/target/ppc/mmu-hash64.h b/target/ppc/mmu-hash64.h
+index 1496955d38..de653fcae5 100644
+--- a/target/ppc/mmu-hash64.h
++++ b/target/ppc/mmu-hash64.h
+@@ -41,8 +41,10 @@ void ppc_hash64_finalize(PowerPCCPU *cpu);
+ #define SLB_VSID_KP 0x0000000000000400ULL
+ #define SLB_VSID_N 0x0000000000000200ULL /* no-execute */
+ #define SLB_VSID_L 0x0000000000000100ULL
++#define SLB_VSID_L_SHIFT PPC_BIT_NR(55)
+ #define SLB_VSID_C 0x0000000000000080ULL /* class */
+ #define SLB_VSID_LP 0x0000000000000030ULL
++#define SLB_VSID_LP_SHIFT PPC_BIT_NR(59)
+ #define SLB_VSID_ATTR 0x0000000000000FFFULL
+ #define SLB_VSID_LLP_MASK (SLB_VSID_L | SLB_VSID_LP)
+ #define SLB_VSID_4K 0x0000000000000000ULL
+@@ -58,6 +60,9 @@ void ppc_hash64_finalize(PowerPCCPU *cpu);
+ #define SDR_64_HTABSIZE 0x000000000000001FULL
+
+ #define PATE0_HTABORG 0x0FFFFFFFFFFC0000ULL
++#define PATE0_PS PPC_BITMASK(56, 58)
++#define PATE0_GET_PS(dw0) (((dw0) & PATE0_PS) >> PPC_BIT_NR(58))
++
+ #define HPTES_PER_GROUP 8
+ #define HASH_PTE_SIZE_64 16
+ #define HASH_PTEG_SIZE_64 (HASH_PTE_SIZE_64 * HPTES_PER_GROUP)
+diff --git a/target/ppc/translate.c b/target/ppc/translate.c
+index 1de7eca9c4..90f749a728 100644
+--- a/target/ppc/translate.c
++++ b/target/ppc/translate.c
+@@ -4327,6 +4327,9 @@ static void pmu_count_insns(DisasContext *ctx)
+
+ static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
+ {
++ if (unlikely(ctx->singlestep_enabled)) {
++ return false;
++ }
+ return translator_use_goto_tb(&ctx->base, dest);
+ }
+
+diff --git a/target/s390x/tcg/excp_helper.c b/target/s390x/tcg/excp_helper.c
+index fe02d82201..7094020dcd 100644
+--- a/target/s390x/tcg/excp_helper.c
++++ b/target/s390x/tcg/excp_helper.c
+@@ -638,7 +638,7 @@ void monitor_event(CPUS390XState *env,
+ void HELPER(monitor_call)(CPUS390XState *env, uint64_t monitor_code,
+ uint32_t monitor_class)
+ {
+- g_assert(monitor_class <= 0xff);
++ g_assert(monitor_class <= 0xf);
+
+ if (env->cregs[8] & (0x8000 >> monitor_class)) {
+ monitor_event(env, monitor_code, monitor_class, GETPC());
+diff --git a/target/s390x/tcg/fpu_helper.c b/target/s390x/tcg/fpu_helper.c
+index be80b2373c..0bde369768 100644
+--- a/target/s390x/tcg/fpu_helper.c
++++ b/target/s390x/tcg/fpu_helper.c
+@@ -44,7 +44,8 @@ uint8_t s390_softfloat_exc_to_ieee(unsigned int exc)
+ s390_exc |= (exc & float_flag_divbyzero) ? S390_IEEE_MASK_DIVBYZERO : 0;
+ s390_exc |= (exc & float_flag_overflow) ? S390_IEEE_MASK_OVERFLOW : 0;
+ s390_exc |= (exc & float_flag_underflow) ? S390_IEEE_MASK_UNDERFLOW : 0;
+- s390_exc |= (exc & float_flag_inexact) ? S390_IEEE_MASK_INEXACT : 0;
++ s390_exc |= (exc & (float_flag_inexact | float_flag_invalid_cvti)) ?
++ S390_IEEE_MASK_INEXACT : 0;
+
+ return s390_exc;
+ }
+diff --git a/target/s390x/tcg/insn-data.h.inc b/target/s390x/tcg/insn-data.h.inc
+index 4249632af3..0e328ea0fd 100644
+--- a/target/s390x/tcg/insn-data.h.inc
++++ b/target/s390x/tcg/insn-data.h.inc
+@@ -157,7 +157,7 @@
+ C(0xb2fa, NIAI, E, EH, 0, 0, 0, 0, 0, 0)
+
+ /* CHECKSUM */
+- C(0xb241, CKSM, RRE, Z, r1_o, ra2, new, r1_32, cksm, 0)
++ C(0xb241, CKSM, RRE, Z, r1_o, ra2_E, new, r1_32, cksm, 0)
+
+ /* COPY SIGN */
+ F(0xb372, CPSDR, RRF_b, FPSSH, f3, f2, new, f1, cps, 0, IF_AFP1 | IF_AFP2 | IF_AFP3)
+diff --git a/target/s390x/tcg/mem_helper.c b/target/s390x/tcg/mem_helper.c
+index 7e7de5e2f1..791a412d95 100644
+--- a/target/s390x/tcg/mem_helper.c
++++ b/target/s390x/tcg/mem_helper.c
+@@ -704,6 +704,11 @@ uint32_t HELPER(clm)(CPUS390XState *env, uint32_t r1, uint32_t mask,
+ HELPER_LOG("%s: r1 0x%x mask 0x%x addr 0x%" PRIx64 "\n", __func__, r1,
+ mask, addr);
+
++ if (!mask) {
++ /* Recognize access exceptions for the first byte */
++ probe_read(env, addr, 1, cpu_mmu_index(env, false), ra);
++ }
++
+ while (mask) {
+ if (mask & 8) {
+ uint8_t d = cpu_ldub_data_ra(env, addr, ra);
+diff --git a/target/s390x/tcg/translate.c b/target/s390x/tcg/translate.c
+index 0885bf2641..ff64d6c28f 100644
+--- a/target/s390x/tcg/translate.c
++++ b/target/s390x/tcg/translate.c
+@@ -2641,6 +2641,12 @@ static DisasJumpType op_icm(DisasContext *s, DisasOps *o)
+ ccm = ((1ull << len) - 1) << pos;
+ break;
+
++ case 0:
++ /* Recognize access exceptions for the first byte. */
++ tcg_gen_qemu_ld_i64(tmp, o->in2, get_mem_index(s), MO_UB);
++ gen_op_movi_cc(s, 0);
++ return DISAS_NEXT;
++
+ default:
+ /* This is going to be a sequence of loads and inserts. */
+ pos = base + 32 - 8;
+@@ -3344,9 +3350,9 @@ static DisasJumpType op_mc(DisasContext *s, DisasOps *o)
+ #if !defined(CONFIG_USER_ONLY)
+ TCGv_i32 i2;
+ #endif
+- const uint16_t monitor_class = get_field(s, i2);
++ const uint8_t monitor_class = get_field(s, i2);
+
+- if (monitor_class & 0xff00) {
++ if (monitor_class & 0xf0) {
+ gen_program_exception(s, PGM_SPECIFICATION);
+ return DISAS_NORETURN;
+ }
+@@ -5992,6 +5998,12 @@ static void in2_ra2(DisasContext *s, DisasOps *o)
+ }
+ #define SPEC_in2_ra2 0
+
++static void in2_ra2_E(DisasContext *s, DisasOps *o)
++{
++ return in2_ra2(s, o);
++}
++#define SPEC_in2_ra2_E SPEC_r2_even
++
+ static void in2_a2(DisasContext *s, DisasOps *o)
+ {
+ int x2 = have_field(s, x2) ? get_field(s, x2) : 0;
+diff --git a/target/s390x/tcg/translate_vx.c.inc b/target/s390x/tcg/translate_vx.c.inc
+index d39ee81cd6..79e2bbe0a7 100644
+--- a/target/s390x/tcg/translate_vx.c.inc
++++ b/target/s390x/tcg/translate_vx.c.inc
+@@ -3192,7 +3192,7 @@ static DisasJumpType op_vfmax(DisasContext *s, DisasOps *o)
+ const uint8_t m5 = get_field(s, m5);
+ gen_helper_gvec_3_ptr *fn;
+
+- if (m6 == 5 || m6 == 6 || m6 == 7 || m6 > 13) {
++ if (m6 == 5 || m6 == 6 || m6 == 7 || m6 >= 13) {
+ gen_program_exception(s, PGM_SPECIFICATION);
+ return DISAS_NORETURN;
+ }
+diff --git a/ui/vnc-clipboard.c b/ui/vnc-clipboard.c
+index 8aeadfaa21..c759be3438 100644
+--- a/ui/vnc-clipboard.c
++++ b/ui/vnc-clipboard.c
+@@ -50,8 +50,11 @@ static uint8_t *inflate_buffer(uint8_t *in, uint32_t in_len, uint32_t *size)
+ ret = inflate(&stream, Z_FINISH);
+ switch (ret) {
+ case Z_OK:
+- case Z_STREAM_END:
+ break;
++ case Z_STREAM_END:
++ *size = stream.total_out;
++ inflateEnd(&stream);
++ return out;
+ case Z_BUF_ERROR:
+ out_len <<= 1;
+ if (out_len > (1 << 20)) {
+@@ -66,11 +69,6 @@ static uint8_t *inflate_buffer(uint8_t *in, uint32_t in_len, uint32_t *size)
+ }
+ }
+
+- *size = stream.total_out;
+- inflateEnd(&stream);
+-
+- return out;
+-
+ err_end:
+ inflateEnd(&stream);
+ err:
+diff --git a/util/thread-pool.c b/util/thread-pool.c
+index 31113b5860..39accc9ebe 100644
+--- a/util/thread-pool.c
++++ b/util/thread-pool.c
+@@ -120,13 +120,13 @@ static void *worker_thread(void *opaque)
+
+ pool->cur_threads--;
+ qemu_cond_signal(&pool->worker_stopped);
+- qemu_mutex_unlock(&pool->lock);
+
+ /*
+ * Wake up another thread, in case we got a wakeup but decided
+ * to exit due to pool->cur_threads > pool->max_threads.
+ */
+ qemu_cond_signal(&pool->request_cond);
++ qemu_mutex_unlock(&pool->lock);
+ return NULL;
+ }
+
diff --git a/debian/patches/v7.2.6.diff b/debian/patches/v7.2.6.diff
new file mode 100644
index 00000000..95fe7786
--- /dev/null
+++ b/debian/patches/v7.2.6.diff
@@ -0,0 +1,3085 @@
+Subject: v7.2.6
+Date: Thu Sep 21 19:23:47 2023 +0300
+From: Michael Tokarev <mjt@tls.msk.ru>
+Forwarded: not-needed
+
+This is a difference between upstream qemu v7.2.5
+and upstream qemu v7.2.6.
+--
+ .gitlab-ci.d/check-dco.py | 6 +-
+ .gitlab-ci.d/static_checks.yml | 4 +-
+ VERSION | 2 +-
+ accel/kvm/kvm-all.c | 4 +-
+ backends/tpm/tpm_util.c | 11 +-
+ docs/about/license.rst | 2 +-
+ docs/devel/multiple-iothreads.txt | 7 +
+ docs/multi-thread-compression.txt | 12 +-
+ docs/rdma.txt | 2 +-
+ dump/dump.c | 4 +-
+ hw/9pfs/xen-9p-backend.c | 5 +-
+ hw/block/dataplane/virtio-blk.c | 3 +-
+ hw/block/dataplane/xen-block.c | 5 +-
+ hw/char/riscv_htif.c | 3 +-
+ hw/char/virtio-serial-bus.c | 3 +-
+ hw/core/machine-smp.c | 10 +
+ hw/display/qxl.c | 14 +-
+ hw/display/virtio-gpu.c | 6 +-
+ hw/i2c/aspeed_i2c.c | 36 +---
+ hw/ide/ahci.c | 113 ++++++++---
+ hw/ide/ahci_internal.h | 1 +
+ hw/ide/core.c | 6 +-
+ hw/intc/apic.c | 7 +
+ hw/intc/loongarch_ipi.c | 4 +
+ hw/intc/riscv_aclint.c | 11 +-
+ hw/mips/loongson3_virt.c | 2 -
+ hw/misc/bcm2835_property.c | 7 +
+ hw/misc/imx_rngc.c | 6 +-
+ hw/misc/macio/mac_dbdma.c | 2 +-
+ hw/net/virtio-net.c | 3 +-
+ hw/net/vmxnet3.c | 5 +-
+ hw/nvme/ctrl.c | 6 +-
+ hw/nvme/dif.c | 4 +-
+ hw/pci-host/raven.c | 7 +
+ hw/ppc/e500.c | 2 +-
+ hw/ppc/pnv_lpc.c | 3 +
+ hw/ppc/vof.c | 2 +
+ hw/riscv/virt.c | 2 +-
+ hw/s390x/s390-virtio-ccw.c | 1 +
+ hw/scsi/lsi53c895a.c | 7 +
+ hw/scsi/mptsas.c | 3 +-
+ hw/scsi/scsi-bus.c | 3 +-
+ hw/scsi/vmw_pvscsi.c | 3 +-
+ hw/smbios/smbios.c | 16 +-
+ hw/tpm/tpm_tis_sysbus.c | 1 -
+ hw/usb/dev-uas.c | 3 +-
+ hw/usb/hcd-dwc2.c | 3 +-
+ hw/usb/hcd-ehci.c | 3 +-
+ hw/usb/hcd-uhci.c | 2 +-
+ hw/usb/host-libusb.c | 6 +-
+ hw/usb/redirect.c | 6 +-
+ hw/usb/xen-usb.c | 3 +-
+ hw/virtio/virtio-balloon.c | 5 +-
+ hw/virtio/virtio-crypto.c | 3 +-
+ hw/virtio/virtio.c | 37 +++-
+ include/block/aio.h | 18 +-
+ include/exec/memory.h | 5 +
+ include/exec/user/abitypes.h | 13 +-
+ include/hw/boards.h | 2 +
+ include/hw/i2c/aspeed_i2c.h | 4 +-
+ include/hw/qdev-core.h | 7 +
+ include/hw/virtio/virtio-gpu-bswap.h | 3 +
+ include/qemu/main-loop.h | 7 +-
+ include/sysemu/kvm.h | 2 +
+ linux-user/elfload.c | 3 +-
+ linux-user/riscv/signal.c | 4 +-
+ migration/block.c | 11 +-
+ python/.gitignore | 4 +-
+ python/Makefile | 53 +++--
+ python/Pipfile | 13 --
+ python/Pipfile.lock | 347 ---------------------------------
+ python/README.rst | 3 -
+ python/setup.cfg | 4 +-
+ python/tests/minreqs.txt | 45 +++++
+ qemu-options.hx | 20 +-
+ scripts/checkpatch.pl | 8 +
+ softmmu/memory.c | 16 ++
+ target/arm/kvm.c | 7 +
+ target/arm/kvm64.c | 1 +
+ target/arm/sme_helper.c | 2 +-
+ target/arm/translate.c | 2 +-
+ target/i386/kvm/kvm.c | 5 +
+ target/mips/kvm.c | 2 +-
+ target/mips/kvm_mips.h | 9 -
+ target/ppc/cpu.c | 1 +
+ target/ppc/kvm.c | 5 +
+ target/riscv/kvm.c | 5 +
+ target/riscv/pmp.c | 4 +
+ target/s390x/kvm/kvm.c | 5 +
+ target/s390x/tcg/translate_vx.c.inc | 6 +-
+ target/s390x/tcg/vec_helper.c | 2 +-
+ target/s390x/tcg/vec_string_helper.c | 54 ++---
+ tests/docker/dockerfiles/python.docker | 1 -
+ tests/qemu-iotests/181 | 2 +-
+ tests/qtest/libqos/ahci.c | 106 +++++++---
+ tests/qtest/libqos/ahci.h | 8 +-
+ tests/qtest/test-hmp.c | 6 +-
+ tests/unit/ptimer-test-stubs.c | 3 +-
+ ui/console.c | 3 +
+ util/async.c | 20 +-
+ util/main-loop.c | 6 +-
+ util/trace-events | 1 +
+ 102 files changed, 656 insertions(+), 639 deletions(-)
+
+diff --git a/.gitlab-ci.d/check-dco.py b/.gitlab-ci.d/check-dco.py
+index 632c8bcce8..b929571eed 100755
+--- a/.gitlab-ci.d/check-dco.py
++++ b/.gitlab-ci.d/check-dco.py
+@@ -20,12 +20,12 @@
+ repourl = "https://gitlab.com/%s/%s.git" % (namespace, reponame)
+
+ subprocess.check_call(["git", "remote", "add", "check-dco", repourl])
+-subprocess.check_call(["git", "fetch", "check-dco", "master"],
++subprocess.check_call(["git", "fetch", "check-dco", "stable-7.2"],
+ stdout=subprocess.DEVNULL,
+ stderr=subprocess.DEVNULL)
+
+ ancestor = subprocess.check_output(["git", "merge-base",
+- "check-dco/master", "HEAD"],
++ "check-dco/stable-7.2", "HEAD"],
+ universal_newlines=True)
+
+ ancestor = ancestor.strip()
+@@ -85,7 +85,7 @@
+
+ To bulk update all commits on current branch "git rebase" can be used:
+
+- git rebase -i master -x 'git commit --amend --no-edit -s'
++ git rebase -i stable-7.2 -x 'git commit --amend --no-edit -s'
+
+ """)
+
+diff --git a/.gitlab-ci.d/static_checks.yml b/.gitlab-ci.d/static_checks.yml
+index 289ad1359e..b4cbdbce2a 100644
+--- a/.gitlab-ci.d/static_checks.yml
++++ b/.gitlab-ci.d/static_checks.yml
+@@ -23,12 +23,12 @@ check-dco:
+ before_script:
+ - apk -U add git
+
+-check-python-pipenv:
++check-python-minreqs:
+ extends: .base_job_template
+ stage: test
+ image: $CI_REGISTRY_IMAGE/qemu/python:latest
+ script:
+- - make -C python check-pipenv
++ - make -C python check-minreqs
+ variables:
+ GIT_DEPTH: 1
+ needs:
+diff --git a/VERSION b/VERSION
+index 8aea167e72..ba6a7620d4 100644
+--- a/VERSION
++++ b/VERSION
+@@ -1 +1 @@
+-7.2.5
++7.2.6
+diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
+index f99b0becd8..0a127ece11 100644
+--- a/accel/kvm/kvm-all.c
++++ b/accel/kvm/kvm-all.c
+@@ -2294,7 +2294,7 @@ static int kvm_init(MachineState *ms)
+ KVMState *s;
+ const KVMCapabilityInfo *missing_cap;
+ int ret;
+- int type = 0;
++ int type;
+ uint64_t dirty_log_manual_caps;
+
+ qemu_mutex_init(&kml_slots_lock);
+@@ -2358,6 +2358,8 @@ static int kvm_init(MachineState *ms)
+ type = mc->kvm_type(ms, kvm_type);
+ } else if (mc->kvm_type) {
+ type = mc->kvm_type(ms, NULL);
++ } else {
++ type = kvm_arch_get_default_type(ms);
+ }
+
+ do {
+diff --git a/backends/tpm/tpm_util.c b/backends/tpm/tpm_util.c
+index a6e6d3e72f..a9d6f7a1c4 100644
+--- a/backends/tpm/tpm_util.c
++++ b/backends/tpm/tpm_util.c
+@@ -112,12 +112,8 @@ static int tpm_util_request(int fd,
+ void *response,
+ size_t responselen)
+ {
+- fd_set readfds;
++ GPollFD fds[1] = { {.fd = fd, .events = G_IO_IN } };
+ int n;
+- struct timeval tv = {
+- .tv_sec = 1,
+- .tv_usec = 0,
+- };
+
+ n = write(fd, request, requestlen);
+ if (n < 0) {
+@@ -127,11 +123,8 @@ static int tpm_util_request(int fd,
+ return -EFAULT;
+ }
+
+- FD_ZERO(&readfds);
+- FD_SET(fd, &readfds);
+-
+ /* wait for a second */
+- n = select(fd + 1, &readfds, NULL, NULL, &tv);
++ TFR(n = g_poll(fds, 1, 1000));
+ if (n != 1) {
+ return -errno;
+ }
+diff --git a/docs/about/license.rst b/docs/about/license.rst
+index cde3d2d25d..303c55d61b 100644
+--- a/docs/about/license.rst
++++ b/docs/about/license.rst
+@@ -8,4 +8,4 @@ QEMU is a trademark of Fabrice Bellard.
+ QEMU is released under the `GNU General Public
+ License <https://www.gnu.org/licenses/gpl-2.0.txt>`__, version 2. Parts
+ of QEMU have specific licenses, see file
+-`LICENSE <https://git.qemu.org/?p=qemu.git;a=blob_plain;f=LICENSE>`__.
++`LICENSE <https://gitlab.com/qemu-project/qemu/-/raw/master/LICENSE>`__.
+diff --git a/docs/devel/multiple-iothreads.txt b/docs/devel/multiple-iothreads.txt
+index 343120f2ef..a3e949f6b3 100644
+--- a/docs/devel/multiple-iothreads.txt
++++ b/docs/devel/multiple-iothreads.txt
+@@ -61,6 +61,7 @@ There are several old APIs that use the main loop AioContext:
+ * LEGACY qemu_aio_set_event_notifier() - monitor an event notifier
+ * LEGACY timer_new_ms() - create a timer
+ * LEGACY qemu_bh_new() - create a BH
++ * LEGACY qemu_bh_new_guarded() - create a BH with a device re-entrancy guard
+ * LEGACY qemu_aio_wait() - run an event loop iteration
+
+ Since they implicitly work on the main loop they cannot be used in code that
+@@ -72,8 +73,14 @@ Instead, use the AioContext functions directly (see include/block/aio.h):
+ * aio_set_event_notifier() - monitor an event notifier
+ * aio_timer_new() - create a timer
+ * aio_bh_new() - create a BH
++ * aio_bh_new_guarded() - create a BH with a device re-entrancy guard
+ * aio_poll() - run an event loop iteration
+
++The qemu_bh_new_guarded/aio_bh_new_guarded APIs accept a "MemReentrancyGuard"
++argument, which is used to check for and prevent re-entrancy problems. For
++BHs associated with devices, the reentrancy-guard is contained in the
++corresponding DeviceState and named "mem_reentrancy_guard".
++
+ The AioContext can be obtained from the IOThread using
+ iothread_get_aio_context() or for the main loop using qemu_get_aio_context().
+ Code that takes an AioContext argument works both in IOThreads or the main
+diff --git a/docs/multi-thread-compression.txt b/docs/multi-thread-compression.txt
+index bb88c6bdf1..95b1556f67 100644
+--- a/docs/multi-thread-compression.txt
++++ b/docs/multi-thread-compression.txt
+@@ -117,13 +117,13 @@ to support the multiple thread compression migration:
+ {qemu} migrate_set_capability compress on
+
+ 3. Set the compression thread count on source:
+- {qemu} migrate_set_parameter compress_threads 12
++ {qemu} migrate_set_parameter compress-threads 12
+
+ 4. Set the compression level on the source:
+- {qemu} migrate_set_parameter compress_level 1
++ {qemu} migrate_set_parameter compress-level 1
+
+ 5. Set the decompression thread count on destination:
+- {qemu} migrate_set_parameter decompress_threads 3
++ {qemu} migrate_set_parameter decompress-threads 3
+
+ 6. Start outgoing migration:
+ {qemu} migrate -d tcp:destination.host:4444
+@@ -133,9 +133,9 @@ to support the multiple thread compression migration:
+
+ The following are the default settings:
+ compress: off
+- compress_threads: 8
+- decompress_threads: 2
+- compress_level: 1 (which means best speed)
++ compress-threads: 8
++ decompress-threads: 2
++ compress-level: 1 (which means best speed)
+
+ So, only the first two steps are required to use the multiple
+ thread compression in migration. You can do more if the default
+diff --git a/docs/rdma.txt b/docs/rdma.txt
+index 2b4cdea1d8..bd8dd799a9 100644
+--- a/docs/rdma.txt
++++ b/docs/rdma.txt
+@@ -89,7 +89,7 @@ RUNNING:
+ First, set the migration speed to match your hardware's capabilities:
+
+ QEMU Monitor Command:
+-$ migrate_set_parameter max_bandwidth 40g # or whatever is the MAX of your RDMA device
++$ migrate_set_parameter max-bandwidth 40g # or whatever is the MAX of your RDMA device
+
+ Next, on the destination machine, add the following to the QEMU command line:
+
+diff --git a/dump/dump.c b/dump/dump.c
+index df117c847f..0f3b6a58d5 100644
+--- a/dump/dump.c
++++ b/dump/dump.c
+@@ -1298,8 +1298,8 @@ static bool get_next_page(GuestPhysBlock **blockptr, uint64_t *pfnptr,
+
+ memcpy(buf + addr % page_size, hbuf, n);
+ addr += n;
+- if (addr % page_size == 0) {
+- /* we filled up the page */
++ if (addr % page_size == 0 || addr >= block->target_end) {
++ /* we filled up the page or the current block is finished */
+ break;
+ }
+ } else {
+diff --git a/hw/9pfs/xen-9p-backend.c b/hw/9pfs/xen-9p-backend.c
+index ab1df8dd2f..8459736f2d 100644
+--- a/hw/9pfs/xen-9p-backend.c
++++ b/hw/9pfs/xen-9p-backend.c
+@@ -62,6 +62,7 @@ typedef struct Xen9pfsDev {
+
+ int num_rings;
+ Xen9pfsRing *rings;
++ MemReentrancyGuard mem_reentrancy_guard;
+ } Xen9pfsDev;
+
+ static void xen_9pfs_disconnect(struct XenLegacyDevice *xendev);
+@@ -448,7 +449,9 @@ static int xen_9pfs_connect(struct XenLegacyDevice *xendev)
+ xen_9pdev->rings[i].ring.out = xen_9pdev->rings[i].data +
+ XEN_FLEX_RING_SIZE(ring_order);
+
+- xen_9pdev->rings[i].bh = qemu_bh_new(xen_9pfs_bh, &xen_9pdev->rings[i]);
++ xen_9pdev->rings[i].bh = qemu_bh_new_guarded(xen_9pfs_bh,
++ &xen_9pdev->rings[i],
++ &xen_9pdev->mem_reentrancy_guard);
+ xen_9pdev->rings[i].out_cons = 0;
+ xen_9pdev->rings[i].out_size = 0;
+ xen_9pdev->rings[i].inprogress = false;
+diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c
+index 26f965cabc..49e59cef8a 100644
+--- a/hw/block/dataplane/virtio-blk.c
++++ b/hw/block/dataplane/virtio-blk.c
+@@ -127,7 +127,8 @@ bool virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *conf,
+ } else {
+ s->ctx = qemu_get_aio_context();
+ }
+- s->bh = aio_bh_new(s->ctx, notify_guest_bh, s);
++ s->bh = aio_bh_new_guarded(s->ctx, notify_guest_bh, s,
++ &DEVICE(vdev)->mem_reentrancy_guard);
+ s->batch_notify_vqs = bitmap_new(conf->num_queues);
+
+ *dataplane = s;
+diff --git a/hw/block/dataplane/xen-block.c b/hw/block/dataplane/xen-block.c
+index 2785b9e849..e31806b317 100644
+--- a/hw/block/dataplane/xen-block.c
++++ b/hw/block/dataplane/xen-block.c
+@@ -632,8 +632,9 @@ XenBlockDataPlane *xen_block_dataplane_create(XenDevice *xendev,
+ } else {
+ dataplane->ctx = qemu_get_aio_context();
+ }
+- dataplane->bh = aio_bh_new(dataplane->ctx, xen_block_dataplane_bh,
+- dataplane);
++ dataplane->bh = aio_bh_new_guarded(dataplane->ctx, xen_block_dataplane_bh,
++ dataplane,
++ &DEVICE(xendev)->mem_reentrancy_guard);
+
+ return dataplane;
+ }
+diff --git a/hw/char/riscv_htif.c b/hw/char/riscv_htif.c
+index 6577f0e640..c76d333cfc 100644
+--- a/hw/char/riscv_htif.c
++++ b/hw/char/riscv_htif.c
+@@ -146,7 +146,8 @@ static void htif_handle_tohost_write(HTIFState *htifstate, uint64_t val_written)
+ htifstate->env->mtohost = 0; /* clear to indicate we read */
+ return;
+ } else if (cmd == 0x1) {
+- qemu_chr_fe_write(&htifstate->chr, (uint8_t *)&payload, 1);
++ uint8_t ch = (uint8_t)payload;
++ qemu_chr_fe_write(&htifstate->chr, &ch, 1);
+ resp = 0x100 | (uint8_t)payload;
+ } else {
+ qemu_log("HTIF device %d: unknown command\n", device);
+diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c
+index 7d4601cb5d..dd619f0731 100644
+--- a/hw/char/virtio-serial-bus.c
++++ b/hw/char/virtio-serial-bus.c
+@@ -985,7 +985,8 @@ static void virtser_port_device_realize(DeviceState *dev, Error **errp)
+ return;
+ }
+
+- port->bh = qemu_bh_new(flush_queued_data_bh, port);
++ port->bh = qemu_bh_new_guarded(flush_queued_data_bh, port,
++ &dev->mem_reentrancy_guard);
+ port->elem = NULL;
+ }
+
+diff --git a/hw/core/machine-smp.c b/hw/core/machine-smp.c
+index b39ed21e65..903834c0db 100644
+--- a/hw/core/machine-smp.c
++++ b/hw/core/machine-smp.c
+@@ -193,3 +193,13 @@ void machine_parse_smp_config(MachineState *ms,
+ return;
+ }
+ }
++
++unsigned int machine_topo_get_cores_per_socket(const MachineState *ms)
++{
++ return ms->smp.cores * ms->smp.clusters * ms->smp.dies;
++}
++
++unsigned int machine_topo_get_threads_per_socket(const MachineState *ms)
++{
++ return ms->smp.threads * machine_topo_get_cores_per_socket(ms);
++}
+diff --git a/hw/display/qxl.c b/hw/display/qxl.c
+index 6772849dec..6b38e55a21 100644
+--- a/hw/display/qxl.c
++++ b/hw/display/qxl.c
+@@ -1613,7 +1613,10 @@ static void qxl_set_mode(PCIQXLDevice *d, unsigned int modenr, int loadvm)
+ }
+
+ d->guest_slots[0].slot = slot;
+- assert(qxl_add_memslot(d, 0, devmem, QXL_SYNC) == 0);
++ if (qxl_add_memslot(d, 0, devmem, QXL_SYNC) != 0) {
++ qxl_set_guest_bug(d, "device isn't initialized yet");
++ return;
++ }
+
+ d->guest_primary.surface = surface;
+ qxl_create_guest_primary(d, 0, QXL_SYNC);
+@@ -2223,11 +2226,14 @@ static void qxl_realize_common(PCIQXLDevice *qxl, Error **errp)
+
+ qemu_add_vm_change_state_handler(qxl_vm_change_state_handler, qxl);
+
+- qxl->update_irq = qemu_bh_new(qxl_update_irq_bh, qxl);
++ qxl->update_irq = qemu_bh_new_guarded(qxl_update_irq_bh, qxl,
++ &DEVICE(qxl)->mem_reentrancy_guard);
+ qxl_reset_state(qxl);
+
+- qxl->update_area_bh = qemu_bh_new(qxl_render_update_area_bh, qxl);
+- qxl->ssd.cursor_bh = qemu_bh_new(qemu_spice_cursor_refresh_bh, &qxl->ssd);
++ qxl->update_area_bh = qemu_bh_new_guarded(qxl_render_update_area_bh, qxl,
++ &DEVICE(qxl)->mem_reentrancy_guard);
++ qxl->ssd.cursor_bh = qemu_bh_new_guarded(qemu_spice_cursor_refresh_bh, &qxl->ssd,
++ &DEVICE(qxl)->mem_reentrancy_guard);
+ }
+
+ static void qxl_realize_primary(PCIDevice *dev, Error **errp)
+diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
+index 4e2e0dd53a..7c13b056b9 100644
+--- a/hw/display/virtio-gpu.c
++++ b/hw/display/virtio-gpu.c
+@@ -1356,8 +1356,10 @@ void virtio_gpu_device_realize(DeviceState *qdev, Error **errp)
+
+ g->ctrl_vq = virtio_get_queue(vdev, 0);
+ g->cursor_vq = virtio_get_queue(vdev, 1);
+- g->ctrl_bh = qemu_bh_new(virtio_gpu_ctrl_bh, g);
+- g->cursor_bh = qemu_bh_new(virtio_gpu_cursor_bh, g);
++ g->ctrl_bh = qemu_bh_new_guarded(virtio_gpu_ctrl_bh, g,
++ &qdev->mem_reentrancy_guard);
++ g->cursor_bh = qemu_bh_new_guarded(virtio_gpu_cursor_bh, g,
++ &qdev->mem_reentrancy_guard);
+ QTAILQ_INIT(&g->reslist);
+ QTAILQ_INIT(&g->cmdq);
+ QTAILQ_INIT(&g->fenceq);
+diff --git a/hw/i2c/aspeed_i2c.c b/hw/i2c/aspeed_i2c.c
+index c166fd20fa..41d5f84a77 100644
+--- a/hw/i2c/aspeed_i2c.c
++++ b/hw/i2c/aspeed_i2c.c
+@@ -226,7 +226,7 @@ static int aspeed_i2c_dma_read(AspeedI2CBus *bus, uint8_t *data)
+ return 0;
+ }
+
+-static int aspeed_i2c_bus_send(AspeedI2CBus *bus, uint8_t pool_start)
++static int aspeed_i2c_bus_send(AspeedI2CBus *bus)
+ {
+ AspeedI2CClass *aic = ASPEED_I2C_GET_CLASS(bus->controller);
+ int ret = -1;
+@@ -236,10 +236,10 @@ static int aspeed_i2c_bus_send(AspeedI2CBus *bus, uint8_t pool_start)
+ uint32_t reg_byte_buf = aspeed_i2c_bus_byte_buf_offset(bus);
+ uint32_t reg_dma_len = aspeed_i2c_bus_dma_len_offset(bus);
+ int pool_tx_count = SHARED_ARRAY_FIELD_EX32(bus->regs, reg_pool_ctrl,
+- TX_COUNT);
++ TX_COUNT) + 1;
+
+ if (SHARED_ARRAY_FIELD_EX32(bus->regs, reg_cmd, TX_BUFF_EN)) {
+- for (i = pool_start; i < pool_tx_count; i++) {
++ for (i = 0; i < pool_tx_count; i++) {
+ uint8_t *pool_base = aic->bus_pool_base(bus);
+
+ trace_aspeed_i2c_bus_send("BUF", i + 1, pool_tx_count,
+@@ -273,7 +273,7 @@ static int aspeed_i2c_bus_send(AspeedI2CBus *bus, uint8_t pool_start)
+ }
+ SHARED_ARRAY_FIELD_DP32(bus->regs, reg_cmd, TX_DMA_EN, 0);
+ } else {
+- trace_aspeed_i2c_bus_send("BYTE", pool_start, 1,
++ trace_aspeed_i2c_bus_send("BYTE", 0, 1,
+ bus->regs[reg_byte_buf]);
+ ret = i2c_send(bus->bus, bus->regs[reg_byte_buf]);
+ }
+@@ -293,7 +293,7 @@ static void aspeed_i2c_bus_recv(AspeedI2CBus *bus)
+ uint32_t reg_dma_len = aspeed_i2c_bus_dma_len_offset(bus);
+ uint32_t reg_dma_addr = aspeed_i2c_bus_dma_addr_offset(bus);
+ int pool_rx_count = SHARED_ARRAY_FIELD_EX32(bus->regs, reg_pool_ctrl,
+- RX_COUNT);
++ RX_SIZE) + 1;
+
+ if (SHARED_ARRAY_FIELD_EX32(bus->regs, reg_cmd, RX_BUFF_EN)) {
+ uint8_t *pool_base = aic->bus_pool_base(bus);
+@@ -418,7 +418,7 @@ static void aspeed_i2c_bus_cmd_dump(AspeedI2CBus *bus)
+ uint32_t reg_intr_sts = aspeed_i2c_bus_intr_sts_offset(bus);
+ uint32_t reg_dma_len = aspeed_i2c_bus_dma_len_offset(bus);
+ if (SHARED_ARRAY_FIELD_EX32(bus->regs, reg_cmd, RX_BUFF_EN)) {
+- count = SHARED_ARRAY_FIELD_EX32(bus->regs, reg_pool_ctrl, TX_COUNT);
++ count = SHARED_ARRAY_FIELD_EX32(bus->regs, reg_pool_ctrl, TX_COUNT) + 1;
+ } else if (SHARED_ARRAY_FIELD_EX32(bus->regs, reg_cmd, RX_DMA_EN)) {
+ count = bus->regs[reg_dma_len];
+ } else { /* BYTE mode */
+@@ -446,10 +446,8 @@ static void aspeed_i2c_bus_cmd_dump(AspeedI2CBus *bus)
+ */
+ static void aspeed_i2c_bus_handle_cmd(AspeedI2CBus *bus, uint64_t value)
+ {
+- uint8_t pool_start = 0;
+ uint32_t reg_intr_sts = aspeed_i2c_bus_intr_sts_offset(bus);
+ uint32_t reg_cmd = aspeed_i2c_bus_cmd_offset(bus);
+- uint32_t reg_pool_ctrl = aspeed_i2c_bus_pool_ctrl_offset(bus);
+ uint32_t reg_dma_len = aspeed_i2c_bus_dma_len_offset(bus);
+
+ if (!aspeed_i2c_check_sram(bus)) {
+@@ -483,27 +481,11 @@ static void aspeed_i2c_bus_handle_cmd(AspeedI2CBus *bus, uint64_t value)
+
+ SHARED_ARRAY_FIELD_DP32(bus->regs, reg_cmd, M_START_CMD, 0);
+
+- /*
+- * The START command is also a TX command, as the slave
+- * address is sent on the bus. Drop the TX flag if nothing
+- * else needs to be sent in this sequence.
+- */
+- if (SHARED_ARRAY_FIELD_EX32(bus->regs, reg_cmd, TX_BUFF_EN)) {
+- if (SHARED_ARRAY_FIELD_EX32(bus->regs, reg_pool_ctrl, TX_COUNT)
+- == 1) {
+- SHARED_ARRAY_FIELD_DP32(bus->regs, reg_cmd, M_TX_CMD, 0);
+- } else {
+- /*
+- * Increase the start index in the TX pool buffer to
+- * skip the address byte.
+- */
+- pool_start++;
+- }
+- } else if (SHARED_ARRAY_FIELD_EX32(bus->regs, reg_cmd, TX_DMA_EN)) {
++ if (SHARED_ARRAY_FIELD_EX32(bus->regs, reg_cmd, TX_DMA_EN)) {
+ if (bus->regs[reg_dma_len] == 0) {
+ SHARED_ARRAY_FIELD_DP32(bus->regs, reg_cmd, M_TX_CMD, 0);
+ }
+- } else {
++ } else if (!SHARED_ARRAY_FIELD_EX32(bus->regs, reg_cmd, TX_BUFF_EN)) {
+ SHARED_ARRAY_FIELD_DP32(bus->regs, reg_cmd, M_TX_CMD, 0);
+ }
+
+@@ -520,7 +502,7 @@ static void aspeed_i2c_bus_handle_cmd(AspeedI2CBus *bus, uint64_t value)
+
+ if (SHARED_ARRAY_FIELD_EX32(bus->regs, reg_cmd, M_TX_CMD)) {
+ aspeed_i2c_set_state(bus, I2CD_MTXD);
+- if (aspeed_i2c_bus_send(bus, pool_start)) {
++ if (aspeed_i2c_bus_send(bus)) {
+ SHARED_ARRAY_FIELD_DP32(bus->regs, reg_intr_sts, TX_NAK, 1);
+ i2c_end_transfer(bus->bus);
+ } else {
+diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
+index 7ce001cacd..c5e79b6e6d 100644
+--- a/hw/ide/ahci.c
++++ b/hw/ide/ahci.c
+@@ -40,9 +40,10 @@
+ #include "trace.h"
+
+ static void check_cmd(AHCIState *s, int port);
+-static int handle_cmd(AHCIState *s, int port, uint8_t slot);
++static void handle_cmd(AHCIState *s, int port, uint8_t slot);
+ static void ahci_reset_port(AHCIState *s, int port);
+-static bool ahci_write_fis_d2h(AHCIDevice *ad);
++static bool ahci_write_fis_d2h(AHCIDevice *ad, bool d2h_fis_i);
++static void ahci_clear_cmd_issue(AHCIDevice *ad, uint8_t slot);
+ static void ahci_init_d2h(AHCIDevice *ad);
+ static int ahci_dma_prepare_buf(const IDEDMA *dma, int32_t limit);
+ static bool ahci_map_clb_address(AHCIDevice *ad);
+@@ -327,6 +328,11 @@ static void ahci_port_write(AHCIState *s, int port, int offset, uint32_t val)
+ ahci_check_irq(s);
+ break;
+ case AHCI_PORT_REG_CMD:
++ if ((pr->cmd & PORT_CMD_START) && !(val & PORT_CMD_START)) {
++ pr->scr_act = 0;
++ pr->cmd_issue = 0;
++ }
++
+ /* Block any Read-only fields from being set;
+ * including LIST_ON and FIS_ON.
+ * The spec requires to set ICC bits to zero after the ICC change
+@@ -590,9 +596,8 @@ static void check_cmd(AHCIState *s, int port)
+
+ if ((pr->cmd & PORT_CMD_START) && pr->cmd_issue) {
+ for (slot = 0; (slot < 32) && pr->cmd_issue; slot++) {
+- if ((pr->cmd_issue & (1U << slot)) &&
+- !handle_cmd(s, port, slot)) {
+- pr->cmd_issue &= ~(1U << slot);
++ if (pr->cmd_issue & (1U << slot)) {
++ handle_cmd(s, port, slot);
+ }
+ }
+ }
+@@ -617,7 +622,7 @@ static void ahci_init_d2h(AHCIDevice *ad)
+ return;
+ }
+
+- if (ahci_write_fis_d2h(ad)) {
++ if (ahci_write_fis_d2h(ad, true)) {
+ ad->init_d2h_sent = true;
+ /* We're emulating receiving the first Reg H2D Fis from the device;
+ * Update the SIG register, but otherwise proceed as normal. */
+@@ -800,8 +805,14 @@ static void ahci_write_fis_sdb(AHCIState *s, NCQTransferState *ncq_tfs)
+ pr->scr_act &= ~ad->finished;
+ ad->finished = 0;
+
+- /* Trigger IRQ if interrupt bit is set (which currently, it always is) */
+- if (sdb_fis->flags & 0x40) {
++ /*
++ * TFES IRQ is always raised if ERR_STAT is set, regardless of I bit.
++ * If ERR_STAT is not set, trigger SDBS IRQ if interrupt bit is set
++ * (which currently, it always is).
++ */
++ if (sdb_fis->status & ERR_STAT) {
++ ahci_trigger_irq(s, ad, AHCI_PORT_IRQ_BIT_TFES);
++ } else if (sdb_fis->flags & 0x40) {
+ ahci_trigger_irq(s, ad, AHCI_PORT_IRQ_BIT_SDBS);
+ }
+ }
+@@ -849,7 +860,7 @@ static void ahci_write_fis_pio(AHCIDevice *ad, uint16_t len, bool pio_fis_i)
+ }
+ }
+
+-static bool ahci_write_fis_d2h(AHCIDevice *ad)
++static bool ahci_write_fis_d2h(AHCIDevice *ad, bool d2h_fis_i)
+ {
+ AHCIPortRegs *pr = &ad->port_regs;
+ uint8_t *d2h_fis;
+@@ -863,7 +874,7 @@ static bool ahci_write_fis_d2h(AHCIDevice *ad)
+ d2h_fis = &ad->res_fis[RES_FIS_RFIS];
+
+ d2h_fis[0] = SATA_FIS_TYPE_REGISTER_D2H;
+- d2h_fis[1] = (1 << 6); /* interrupt bit */
++ d2h_fis[1] = d2h_fis_i ? (1 << 6) : 0; /* interrupt bit */
+ d2h_fis[2] = s->status;
+ d2h_fis[3] = s->error;
+
+@@ -889,7 +900,10 @@ static bool ahci_write_fis_d2h(AHCIDevice *ad)
+ ahci_trigger_irq(ad->hba, ad, AHCI_PORT_IRQ_BIT_TFES);
+ }
+
+- ahci_trigger_irq(ad->hba, ad, AHCI_PORT_IRQ_BIT_DHRS);
++ if (d2h_fis_i) {
++ ahci_trigger_irq(ad->hba, ad, AHCI_PORT_IRQ_BIT_DHRS);
++ }
++
+ return true;
+ }
+
+@@ -997,7 +1011,6 @@ static void ncq_err(NCQTransferState *ncq_tfs)
+
+ ide_state->error = ABRT_ERR;
+ ide_state->status = READY_STAT | ERR_STAT;
+- ncq_tfs->drive->port_regs.scr_err |= (1 << ncq_tfs->tag);
+ qemu_sglist_destroy(&ncq_tfs->sglist);
+ ncq_tfs->used = 0;
+ }
+@@ -1007,7 +1020,7 @@ static void ncq_finish(NCQTransferState *ncq_tfs)
+ /* If we didn't error out, set our finished bit. Errored commands
+ * do not get a bit set for the SDB FIS ACT register, nor do they
+ * clear the outstanding bit in scr_act (PxSACT). */
+- if (!(ncq_tfs->drive->port_regs.scr_err & (1 << ncq_tfs->tag))) {
++ if (ncq_tfs->used) {
+ ncq_tfs->drive->finished |= (1 << ncq_tfs->tag);
+ }
+
+@@ -1119,6 +1132,24 @@ static void process_ncq_command(AHCIState *s, int port, const uint8_t *cmd_fis,
+ return;
+ }
+
++ /*
++ * A NCQ command clears the bit in PxCI after the command has been QUEUED
++ * successfully (ERROR not set, BUSY and DRQ cleared).
++ *
++ * For NCQ commands, PxCI will always be cleared here.
++ *
++ * (Once the NCQ command is COMPLETED, the device will send a SDB FIS with
++ * the interrupt bit set, which will clear PxSACT and raise an interrupt.)
++ */
++ ahci_clear_cmd_issue(ad, slot);
++
++ /*
++ * In reality, for NCQ commands, PxCI is cleared after receiving a D2H FIS
++ * without the interrupt bit set, but since ahci_write_fis_d2h() can raise
++ * an IRQ on error, we need to call them in reverse order.
++ */
++ ahci_write_fis_d2h(ad, false);
++
+ ncq_tfs->used = 1;
+ ncq_tfs->drive = ad;
+ ncq_tfs->slot = slot;
+@@ -1191,6 +1222,7 @@ static void handle_reg_h2d_fis(AHCIState *s, int port,
+ {
+ IDEState *ide_state = &s->dev[port].port.ifs[0];
+ AHCICmdHdr *cmd = get_cmd_header(s, port, slot);
++ AHCIDevice *ad = &s->dev[port];
+ uint16_t opts = le16_to_cpu(cmd->opts);
+
+ if (cmd_fis[1] & 0x0F) {
+@@ -1267,11 +1299,19 @@ static void handle_reg_h2d_fis(AHCIState *s, int port,
+ /* Reset transferred byte counter */
+ cmd->status = 0;
+
++ /*
++ * A non-NCQ command clears the bit in PxCI after the command has COMPLETED
++ * successfully (ERROR not set, BUSY and DRQ cleared).
++ *
++ * For non-NCQ commands, PxCI will always be cleared by ahci_cmd_done().
++ */
++ ad->busy_slot = slot;
++
+ /* We're ready to process the command in FIS byte 2. */
+ ide_exec_cmd(&s->dev[port].port, cmd_fis[2]);
+ }
+
+-static int handle_cmd(AHCIState *s, int port, uint8_t slot)
++static void handle_cmd(AHCIState *s, int port, uint8_t slot)
+ {
+ IDEState *ide_state;
+ uint64_t tbl_addr;
+@@ -1282,12 +1322,12 @@ static int handle_cmd(AHCIState *s, int port, uint8_t slot)
+ if (s->dev[port].port.ifs[0].status & (BUSY_STAT|DRQ_STAT)) {
+ /* Engine currently busy, try again later */
+ trace_handle_cmd_busy(s, port);
+- return -1;
++ return;
+ }
+
+ if (!s->dev[port].lst) {
+ trace_handle_cmd_nolist(s, port);
+- return -1;
++ return;
+ }
+ cmd = get_cmd_header(s, port, slot);
+ /* remember current slot handle for later */
+@@ -1297,7 +1337,7 @@ static int handle_cmd(AHCIState *s, int port, uint8_t slot)
+ ide_state = &s->dev[port].port.ifs[0];
+ if (!ide_state->blk) {
+ trace_handle_cmd_badport(s, port);
+- return -1;
++ return;
+ }
+
+ tbl_addr = le64_to_cpu(cmd->tbl_addr);
+@@ -1306,7 +1346,7 @@ static int handle_cmd(AHCIState *s, int port, uint8_t slot)
+ DMA_DIRECTION_TO_DEVICE, MEMTXATTRS_UNSPECIFIED);
+ if (!cmd_fis) {
+ trace_handle_cmd_badfis(s, port);
+- return -1;
++ return;
+ } else if (cmd_len != 0x80) {
+ ahci_trigger_irq(s, &s->dev[port], AHCI_PORT_IRQ_BIT_HBFS);
+ trace_handle_cmd_badmap(s, port, cmd_len);
+@@ -1330,15 +1370,6 @@ static int handle_cmd(AHCIState *s, int port, uint8_t slot)
+ out:
+ dma_memory_unmap(s->as, cmd_fis, cmd_len, DMA_DIRECTION_TO_DEVICE,
+ cmd_len);
+-
+- if (s->dev[port].port.ifs[0].status & (BUSY_STAT|DRQ_STAT)) {
+- /* async command, complete later */
+- s->dev[port].busy_slot = slot;
+- return -1;
+- }
+-
+- /* done handling the command */
+- return 0;
+ }
+
+ /* Transfer PIO data between RAM and device */
+@@ -1492,23 +1523,41 @@ static int ahci_dma_rw_buf(const IDEDMA *dma, bool is_write)
+ return 1;
+ }
+
++static void ahci_clear_cmd_issue(AHCIDevice *ad, uint8_t slot)
++{
++ IDEState *ide_state = &ad->port.ifs[0];
++
++ if (!(ide_state->status & ERR_STAT) &&
++ !(ide_state->status & (BUSY_STAT | DRQ_STAT))) {
++ ad->port_regs.cmd_issue &= ~(1 << slot);
++ }
++}
++
++/* Non-NCQ command is done - This function is never called for NCQ commands. */
+ static void ahci_cmd_done(const IDEDMA *dma)
+ {
+ AHCIDevice *ad = DO_UPCAST(AHCIDevice, dma, dma);
++ IDEState *ide_state = &ad->port.ifs[0];
+
+ trace_ahci_cmd_done(ad->hba, ad->port_no);
+
+ /* no longer busy */
+ if (ad->busy_slot != -1) {
+- ad->port_regs.cmd_issue &= ~(1 << ad->busy_slot);
++ ahci_clear_cmd_issue(ad, ad->busy_slot);
+ ad->busy_slot = -1;
+ }
+
+- /* update d2h status */
+- ahci_write_fis_d2h(ad);
++ /*
++ * In reality, for non-NCQ commands, PxCI is cleared after receiving a D2H
++ * FIS with the interrupt bit set, but since ahci_write_fis_d2h() will raise
++ * an IRQ, we need to call them in reverse order.
++ */
++ ahci_write_fis_d2h(ad, true);
+
+- if (ad->port_regs.cmd_issue && !ad->check_bh) {
+- ad->check_bh = qemu_bh_new(ahci_check_cmd_bh, ad);
++ if (!(ide_state->status & ERR_STAT) &&
++ ad->port_regs.cmd_issue && !ad->check_bh) {
++ ad->check_bh = qemu_bh_new_guarded(ahci_check_cmd_bh, ad,
++ &ad->mem_reentrancy_guard);
+ qemu_bh_schedule(ad->check_bh);
+ }
+ }
+diff --git a/hw/ide/ahci_internal.h b/hw/ide/ahci_internal.h
+index 109de9e2d1..a7768dd69e 100644
+--- a/hw/ide/ahci_internal.h
++++ b/hw/ide/ahci_internal.h
+@@ -321,6 +321,7 @@ struct AHCIDevice {
+ bool init_d2h_sent;
+ AHCICmdHdr *cur_cmd;
+ NCQTransferState ncq_tfs[AHCI_MAX_CMDS];
++ MemReentrancyGuard mem_reentrancy_guard;
+ };
+
+ struct AHCIPCIState {
+diff --git a/hw/ide/core.c b/hw/ide/core.c
+index 39afdc0006..1477935270 100644
+--- a/hw/ide/core.c
++++ b/hw/ide/core.c
+@@ -512,6 +512,7 @@ BlockAIOCB *ide_issue_trim(
+ BlockCompletionFunc *cb, void *cb_opaque, void *opaque)
+ {
+ IDEState *s = opaque;
++ IDEDevice *dev = s->unit ? s->bus->slave : s->bus->master;
+ TrimAIOCB *iocb;
+
+ /* Paired with a decrement in ide_trim_bh_cb() */
+@@ -519,7 +520,8 @@ BlockAIOCB *ide_issue_trim(
+
+ iocb = blk_aio_get(&trim_aiocb_info, s->blk, cb, cb_opaque);
+ iocb->s = s;
+- iocb->bh = qemu_bh_new(ide_trim_bh_cb, iocb);
++ iocb->bh = qemu_bh_new_guarded(ide_trim_bh_cb, iocb,
++ &DEVICE(dev)->mem_reentrancy_guard);
+ iocb->ret = 0;
+ iocb->qiov = qiov;
+ iocb->i = -1;
+@@ -530,9 +532,9 @@ BlockAIOCB *ide_issue_trim(
+
+ void ide_abort_command(IDEState *s)
+ {
+- ide_transfer_stop(s);
+ s->status = READY_STAT | ERR_STAT;
+ s->error = ABRT_ERR;
++ ide_transfer_stop(s);
+ }
+
+ static void ide_set_retry(IDEState *s)
+diff --git a/hw/intc/apic.c b/hw/intc/apic.c
+index 3df11c34d6..a7c2b301a8 100644
+--- a/hw/intc/apic.c
++++ b/hw/intc/apic.c
+@@ -883,6 +883,13 @@ static void apic_realize(DeviceState *dev, Error **errp)
+ memory_region_init_io(&s->io_memory, OBJECT(s), &apic_io_ops, s, "apic-msi",
+ APIC_SPACE_SIZE);
+
++ /*
++ * apic-msi's apic_mem_write can call into ioapic_eoi_broadcast, which can
++ * write back to apic-msi. As such mark the apic-msi region re-entrancy
++ * safe.
++ */
++ s->io_memory.disable_reentrancy_guard = true;
++
+ s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, apic_timer, s);
+ local_apics[s->id] = s;
+
+diff --git a/hw/intc/loongarch_ipi.c b/hw/intc/loongarch_ipi.c
+index aa4bf9eb74..40e98af2ce 100644
+--- a/hw/intc/loongarch_ipi.c
++++ b/hw/intc/loongarch_ipi.c
+@@ -215,6 +215,10 @@ static void loongarch_ipi_init(Object *obj)
+ for (cpu = 0; cpu < MAX_IPI_CORE_NUM; cpu++) {
+ memory_region_init_io(&s->ipi_iocsr_mem[cpu], obj, &loongarch_ipi_ops,
+ &lams->ipi_core[cpu], "loongarch_ipi_iocsr", 0x48);
++
++ /* loongarch_ipi_iocsr performs re-entrant IO through ipi_send */
++ s->ipi_iocsr_mem[cpu].disable_reentrancy_guard = true;
++
+ sysbus_init_mmio(sbd, &s->ipi_iocsr_mem[cpu]);
+
+ memory_region_init_io(&s->ipi64_iocsr_mem[cpu], obj, &loongarch_ipi64_ops,
+diff --git a/hw/intc/riscv_aclint.c b/hw/intc/riscv_aclint.c
+index eee04643cb..908edcbb80 100644
+--- a/hw/intc/riscv_aclint.c
++++ b/hw/intc/riscv_aclint.c
+@@ -64,13 +64,13 @@ static void riscv_aclint_mtimer_write_timecmp(RISCVAclintMTimerState *mtimer,
+ uint64_t next;
+ uint64_t diff;
+
+- uint64_t rtc_r = cpu_riscv_read_rtc(mtimer);
++ uint64_t rtc = cpu_riscv_read_rtc(mtimer);
+
+ /* Compute the relative hartid w.r.t the socket */
+ hartid = hartid - mtimer->hartid_base;
+
+ mtimer->timecmp[hartid] = value;
+- if (mtimer->timecmp[hartid] <= rtc_r) {
++ if (mtimer->timecmp[hartid] <= rtc) {
+ /*
+ * If we're setting an MTIMECMP value in the "past",
+ * immediately raise the timer interrupt
+@@ -81,7 +81,7 @@ static void riscv_aclint_mtimer_write_timecmp(RISCVAclintMTimerState *mtimer,
+
+ /* otherwise, set up the future timer interrupt */
+ qemu_irq_lower(mtimer->timer_irqs[hartid]);
+- diff = mtimer->timecmp[hartid] - rtc_r;
++ diff = mtimer->timecmp[hartid] - rtc;
+ /* back to ns (note args switched in muldiv64) */
+ uint64_t ns_diff = muldiv64(diff, NANOSECONDS_PER_SECOND, timebase_freq);
+
+@@ -208,11 +208,12 @@ static void riscv_aclint_mtimer_write(void *opaque, hwaddr addr,
+ return;
+ } else if (addr == mtimer->time_base || addr == mtimer->time_base + 4) {
+ uint64_t rtc_r = cpu_riscv_read_rtc_raw(mtimer->timebase_freq);
++ uint64_t rtc = cpu_riscv_read_rtc(mtimer);
+
+ if (addr == mtimer->time_base) {
+ if (size == 4) {
+ /* time_lo for RV32/RV64 */
+- mtimer->time_delta = ((rtc_r & ~0xFFFFFFFFULL) | value) - rtc_r;
++ mtimer->time_delta = ((rtc & ~0xFFFFFFFFULL) | value) - rtc_r;
+ } else {
+ /* time for RV64 */
+ mtimer->time_delta = value - rtc_r;
+@@ -220,7 +221,7 @@ static void riscv_aclint_mtimer_write(void *opaque, hwaddr addr,
+ } else {
+ if (size == 4) {
+ /* time_hi for RV32/RV64 */
+- mtimer->time_delta = (value << 32 | (rtc_r & 0xFFFFFFFF)) - rtc_r;
++ mtimer->time_delta = (value << 32 | (rtc & 0xFFFFFFFF)) - rtc_r;
+ } else {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "aclint-mtimer: invalid time_hi write: %08x",
+diff --git a/hw/mips/loongson3_virt.c b/hw/mips/loongson3_virt.c
+index 25534288dd..b4f6bff1b8 100644
+--- a/hw/mips/loongson3_virt.c
++++ b/hw/mips/loongson3_virt.c
+@@ -29,7 +29,6 @@
+ #include "qemu/datadir.h"
+ #include "qapi/error.h"
+ #include "elf.h"
+-#include "kvm_mips.h"
+ #include "hw/char/serial.h"
+ #include "hw/intc/loongson_liointc.h"
+ #include "hw/mips/mips.h"
+@@ -617,7 +616,6 @@ static void loongson3v_machine_class_init(ObjectClass *oc, void *data)
+ mc->max_cpus = LOONGSON_MAX_VCPUS;
+ mc->default_ram_id = "loongson3.highram";
+ mc->default_ram_size = 1600 * MiB;
+- mc->kvm_type = mips_kvm_type;
+ mc->minimum_page_bits = 14;
+ }
+
+diff --git a/hw/misc/bcm2835_property.c b/hw/misc/bcm2835_property.c
+index 890ae7bae5..de056ea2df 100644
+--- a/hw/misc/bcm2835_property.c
++++ b/hw/misc/bcm2835_property.c
+@@ -382,6 +382,13 @@ static void bcm2835_property_init(Object *obj)
+
+ memory_region_init_io(&s->iomem, OBJECT(s), &bcm2835_property_ops, s,
+ TYPE_BCM2835_PROPERTY, 0x10);
++
++ /*
++ * bcm2835_property_ops call into bcm2835_mbox, which in-turn reads from
++ * iomem. As such, mark iomem as re-entracy safe.
++ */
++ s->iomem.disable_reentrancy_guard = true;
++
+ sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
+ sysbus_init_irq(SYS_BUS_DEVICE(s), &s->mbox_irq);
+ }
+diff --git a/hw/misc/imx_rngc.c b/hw/misc/imx_rngc.c
+index 632c03779c..082c6980ad 100644
+--- a/hw/misc/imx_rngc.c
++++ b/hw/misc/imx_rngc.c
+@@ -228,8 +228,10 @@ static void imx_rngc_realize(DeviceState *dev, Error **errp)
+ sysbus_init_mmio(sbd, &s->iomem);
+
+ sysbus_init_irq(sbd, &s->irq);
+- s->self_test_bh = qemu_bh_new(imx_rngc_self_test, s);
+- s->seed_bh = qemu_bh_new(imx_rngc_seed, s);
++ s->self_test_bh = qemu_bh_new_guarded(imx_rngc_self_test, s,
++ &dev->mem_reentrancy_guard);
++ s->seed_bh = qemu_bh_new_guarded(imx_rngc_seed, s,
++ &dev->mem_reentrancy_guard);
+ }
+
+ static void imx_rngc_reset(DeviceState *dev)
+diff --git a/hw/misc/macio/mac_dbdma.c b/hw/misc/macio/mac_dbdma.c
+index efcc02609f..cc7e02203d 100644
+--- a/hw/misc/macio/mac_dbdma.c
++++ b/hw/misc/macio/mac_dbdma.c
+@@ -914,7 +914,7 @@ static void mac_dbdma_realize(DeviceState *dev, Error **errp)
+ {
+ DBDMAState *s = MAC_DBDMA(dev);
+
+- s->bh = qemu_bh_new(DBDMA_run_bh, s);
++ s->bh = qemu_bh_new_guarded(DBDMA_run_bh, s, &dev->mem_reentrancy_guard);
+ }
+
+ static void mac_dbdma_class_init(ObjectClass *oc, void *data)
+diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
+index 8cd7a400a0..1b10cdc127 100644
+--- a/hw/net/virtio-net.c
++++ b/hw/net/virtio-net.c
+@@ -2875,7 +2875,8 @@ static void virtio_net_add_queue(VirtIONet *n, int index)
+ n->vqs[index].tx_vq =
+ virtio_add_queue(vdev, n->net_conf.tx_queue_size,
+ virtio_net_handle_tx_bh);
+- n->vqs[index].tx_bh = qemu_bh_new(virtio_net_tx_bh, &n->vqs[index]);
++ n->vqs[index].tx_bh = qemu_bh_new_guarded(virtio_net_tx_bh, &n->vqs[index],
++ &DEVICE(vdev)->mem_reentrancy_guard);
+ }
+
+ n->vqs[index].tx_waiting = 0;
+diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c
+index 56559cda24..399fc14129 100644
+--- a/hw/net/vmxnet3.c
++++ b/hw/net/vmxnet3.c
+@@ -1441,7 +1441,10 @@ static void vmxnet3_activate_device(VMXNET3State *s)
+ vmxnet3_setup_rx_filtering(s);
+ /* Cache fields from shared memory */
+ s->mtu = VMXNET3_READ_DRV_SHARED32(d, s->drv_shmem, devRead.misc.mtu);
+- assert(VMXNET3_MIN_MTU <= s->mtu && s->mtu <= VMXNET3_MAX_MTU);
++ if (s->mtu < VMXNET3_MIN_MTU || s->mtu > VMXNET3_MAX_MTU) {
++ qemu_log_mask(LOG_GUEST_ERROR, "vmxnet3: Bad MTU size: %u\n", s->mtu);
++ return;
++ }
+ VMW_CFPRN("MTU is %u", s->mtu);
+
+ s->max_rx_frags =
+diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c
+index 749a6938dd..4d29033556 100644
+--- a/hw/nvme/ctrl.c
++++ b/hw/nvme/ctrl.c
+@@ -4318,7 +4318,8 @@ static void nvme_init_sq(NvmeSQueue *sq, NvmeCtrl *n, uint64_t dma_addr,
+ QTAILQ_INSERT_TAIL(&(sq->req_list), &sq->io_req[i], entry);
+ }
+
+- sq->bh = qemu_bh_new(nvme_process_sq, sq);
++ sq->bh = qemu_bh_new_guarded(nvme_process_sq, sq,
++ &DEVICE(sq->ctrl)->mem_reentrancy_guard);
+
+ if (n->dbbuf_enabled) {
+ sq->db_addr = n->dbbuf_dbs + (sqid << 3);
+@@ -4705,7 +4706,8 @@ static void nvme_init_cq(NvmeCQueue *cq, NvmeCtrl *n, uint64_t dma_addr,
+ }
+ }
+ n->cq[cqid] = cq;
+- cq->bh = qemu_bh_new(nvme_post_cqes, cq);
++ cq->bh = qemu_bh_new_guarded(nvme_post_cqes, cq,
++ &DEVICE(cq->ctrl)->mem_reentrancy_guard);
+ }
+
+ static uint16_t nvme_create_cq(NvmeCtrl *n, NvmeRequest *req)
+diff --git a/hw/nvme/dif.c b/hw/nvme/dif.c
+index 63c44c86ab..01b19c3373 100644
+--- a/hw/nvme/dif.c
++++ b/hw/nvme/dif.c
+@@ -115,7 +115,7 @@ static void nvme_dif_pract_generate_dif_crc64(NvmeNamespace *ns, uint8_t *buf,
+ uint64_t crc = crc64_nvme(~0ULL, buf, ns->lbasz);
+
+ if (pil) {
+- crc = crc64_nvme(crc, mbuf, pil);
++ crc = crc64_nvme(~crc, mbuf, pil);
+ }
+
+ dif->g64.guard = cpu_to_be64(crc);
+@@ -246,7 +246,7 @@ static uint16_t nvme_dif_prchk_crc64(NvmeNamespace *ns, NvmeDifTuple *dif,
+ uint64_t crc = crc64_nvme(~0ULL, buf, ns->lbasz);
+
+ if (pil) {
+- crc = crc64_nvme(crc, mbuf, pil);
++ crc = crc64_nvme(~crc, mbuf, pil);
+ }
+
+ trace_pci_nvme_dif_prchk_guard_crc64(be64_to_cpu(dif->g64.guard), crc);
+diff --git a/hw/pci-host/raven.c b/hw/pci-host/raven.c
+index 7a105e4a63..42fb02b7e6 100644
+--- a/hw/pci-host/raven.c
++++ b/hw/pci-host/raven.c
+@@ -293,6 +293,13 @@ static void raven_pcihost_initfn(Object *obj)
+ memory_region_init(&s->pci_memory, obj, "pci-memory", 0x3f000000);
+ address_space_init(&s->pci_io_as, &s->pci_io, "raven-io");
+
++ /*
++ * Raven's raven_io_ops use the address-space API to access pci-conf-idx
++ * (which is also owned by the raven device). As such, mark the
++ * pci_io_non_contiguous as re-entrancy safe.
++ */
++ s->pci_io_non_contiguous.disable_reentrancy_guard = true;
++
+ /* CPU address space */
+ memory_region_add_subregion(address_space_mem, PCI_IO_BASE_ADDR,
+ &s->pci_io);
+diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
+index 2fe496677c..8d5eb08381 100644
+--- a/hw/ppc/e500.c
++++ b/hw/ppc/e500.c
+@@ -683,7 +683,7 @@ static int ppce500_prep_device_tree(PPCE500MachineState *machine,
+ p->kernel_base = kernel_base;
+ p->kernel_size = kernel_size;
+
+- qemu_register_reset(ppce500_reset_device_tree, p);
++ qemu_register_reset_nosnapshotload(ppce500_reset_device_tree, p);
+ p->notifier.notify = ppce500_init_notify;
+ qemu_add_machine_init_done_notifier(&p->notifier);
+
+diff --git a/hw/ppc/pnv_lpc.c b/hw/ppc/pnv_lpc.c
+index ee890e7ab4..ef29314891 100644
+--- a/hw/ppc/pnv_lpc.c
++++ b/hw/ppc/pnv_lpc.c
+@@ -733,10 +733,13 @@ static void pnv_lpc_realize(DeviceState *dev, Error **errp)
+ /* Create MMIO regions for LPC HC and OPB registers */
+ memory_region_init_io(&lpc->opb_master_regs, OBJECT(dev), &opb_master_ops,
+ lpc, "lpc-opb-master", LPC_OPB_REGS_OPB_SIZE);
++ lpc->opb_master_regs.disable_reentrancy_guard = true;
+ memory_region_add_subregion(&lpc->opb_mr, LPC_OPB_REGS_OPB_ADDR,
+ &lpc->opb_master_regs);
+ memory_region_init_io(&lpc->lpc_hc_regs, OBJECT(dev), &lpc_hc_ops, lpc,
+ "lpc-hc", LPC_HC_REGS_OPB_SIZE);
++ /* xscom writes to lpc-hc. As such mark lpc-hc re-entrancy safe */
++ lpc->lpc_hc_regs.disable_reentrancy_guard = true;
+ memory_region_add_subregion(&lpc->opb_mr, LPC_HC_REGS_OPB_ADDR,
+ &lpc->lpc_hc_regs);
+
+diff --git a/hw/ppc/vof.c b/hw/ppc/vof.c
+index 18c3f92317..e3b430a81f 100644
+--- a/hw/ppc/vof.c
++++ b/hw/ppc/vof.c
+@@ -1024,6 +1024,8 @@ void vof_cleanup(Vof *vof)
+ }
+ vof->claimed = NULL;
+ vof->of_instances = NULL;
++ vof->of_instance_last = 0;
++ vof->claimed_base = 0;
+ }
+
+ void vof_build_dt(void *fdt, Vof *vof)
+diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
+index a5bc7353b4..3a99b4b801 100644
+--- a/hw/riscv/virt.c
++++ b/hw/riscv/virt.c
+@@ -715,7 +715,7 @@ static void create_fdt_pmu(RISCVVirtState *s)
+ MachineState *mc = MACHINE(s);
+ RISCVCPU hart = s->soc[0].harts[0];
+
+- pmu_name = g_strdup_printf("/soc/pmu");
++ pmu_name = g_strdup_printf("/pmu");
+ qemu_fdt_add_subnode(mc->fdt, pmu_name);
+ qemu_fdt_setprop_string(mc->fdt, pmu_name, "compatible", "riscv,pmu");
+ riscv_pmu_generate_fdt_node(mc->fdt, hart.cfg.pmu_num, pmu_name);
+diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
+index 2e64ffab45..16899a1814 100644
+--- a/hw/s390x/s390-virtio-ccw.c
++++ b/hw/s390x/s390-virtio-ccw.c
+@@ -108,6 +108,7 @@ static const char *const reset_dev_types[] = {
+ "s390-flic",
+ "diag288",
+ TYPE_S390_PCI_HOST_BRIDGE,
++ TYPE_AP_BRIDGE,
+ };
+
+ static void subsystem_reset(void)
+diff --git a/hw/scsi/lsi53c895a.c b/hw/scsi/lsi53c895a.c
+index 42532c4744..ca619ed564 100644
+--- a/hw/scsi/lsi53c895a.c
++++ b/hw/scsi/lsi53c895a.c
+@@ -2313,6 +2313,13 @@ static void lsi_scsi_realize(PCIDevice *dev, Error **errp)
+ memory_region_init_io(&s->io_io, OBJECT(s), &lsi_io_ops, s,
+ "lsi-io", 256);
+
++ /*
++ * Since we use the address-space API to interact with ram_io, disable the
++ * re-entrancy guard.
++ */
++ s->ram_io.disable_reentrancy_guard = true;
++ s->mmio_io.disable_reentrancy_guard = true;
++
+ address_space_init(&s->pci_io_as, pci_address_space_io(dev), "lsi-pci-io");
+ qdev_init_gpio_out(d, &s->ext_irq, 1);
+
+diff --git a/hw/scsi/mptsas.c b/hw/scsi/mptsas.c
+index c485da792c..3de288b454 100644
+--- a/hw/scsi/mptsas.c
++++ b/hw/scsi/mptsas.c
+@@ -1322,7 +1322,8 @@ static void mptsas_scsi_realize(PCIDevice *dev, Error **errp)
+ }
+ s->max_devices = MPTSAS_NUM_PORTS;
+
+- s->request_bh = qemu_bh_new(mptsas_fetch_requests, s);
++ s->request_bh = qemu_bh_new_guarded(mptsas_fetch_requests, s,
++ &DEVICE(dev)->mem_reentrancy_guard);
+
+ scsi_bus_init(&s->bus, sizeof(s->bus), &dev->qdev, &mptsas_scsi_info);
+ }
+diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c
+index ceceafb2cd..e5c9f7a53d 100644
+--- a/hw/scsi/scsi-bus.c
++++ b/hw/scsi/scsi-bus.c
+@@ -193,7 +193,8 @@ static void scsi_dma_restart_cb(void *opaque, bool running, RunState state)
+ AioContext *ctx = blk_get_aio_context(s->conf.blk);
+ /* The reference is dropped in scsi_dma_restart_bh.*/
+ object_ref(OBJECT(s));
+- s->bh = aio_bh_new(ctx, scsi_dma_restart_bh, s);
++ s->bh = aio_bh_new_guarded(ctx, scsi_dma_restart_bh, s,
++ &DEVICE(s)->mem_reentrancy_guard);
+ qemu_bh_schedule(s->bh);
+ }
+ }
+diff --git a/hw/scsi/vmw_pvscsi.c b/hw/scsi/vmw_pvscsi.c
+index fa76696855..4de34536e9 100644
+--- a/hw/scsi/vmw_pvscsi.c
++++ b/hw/scsi/vmw_pvscsi.c
+@@ -1184,7 +1184,8 @@ pvscsi_realizefn(PCIDevice *pci_dev, Error **errp)
+ pcie_endpoint_cap_init(pci_dev, PVSCSI_EXP_EP_OFFSET);
+ }
+
+- s->completion_worker = qemu_bh_new(pvscsi_process_completion_queue, s);
++ s->completion_worker = qemu_bh_new_guarded(pvscsi_process_completion_queue, s,
++ &DEVICE(pci_dev)->mem_reentrancy_guard);
+
+ scsi_bus_init(&s->bus, sizeof(s->bus), DEVICE(pci_dev), &pvscsi_scsi_info);
+ /* override default SCSI bus hotplug-handler, with pvscsi's one */
+diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c
+index 66a020999b..cd43185417 100644
+--- a/hw/smbios/smbios.c
++++ b/hw/smbios/smbios.c
+@@ -712,6 +712,8 @@ static void smbios_build_type_4_table(MachineState *ms, unsigned instance)
+ {
+ char sock_str[128];
+ size_t tbl_len = SMBIOS_TYPE_4_LEN_V28;
++ unsigned threads_per_socket;
++ unsigned cores_per_socket;
+
+ if (smbios_ep_type == SMBIOS_ENTRY_POINT_TYPE_64) {
+ tbl_len = SMBIOS_TYPE_4_LEN_V30;
+@@ -746,17 +748,20 @@ static void smbios_build_type_4_table(MachineState *ms, unsigned instance)
+ SMBIOS_TABLE_SET_STR(4, asset_tag_number_str, type4.asset);
+ SMBIOS_TABLE_SET_STR(4, part_number_str, type4.part);
+
+- t->core_count = (ms->smp.cores > 255) ? 0xFF : ms->smp.cores;
++ threads_per_socket = machine_topo_get_threads_per_socket(ms);
++ cores_per_socket = machine_topo_get_cores_per_socket(ms);
++
++ t->core_count = (cores_per_socket > 255) ? 0xFF : cores_per_socket;
+ t->core_enabled = t->core_count;
+
+- t->thread_count = (ms->smp.threads > 255) ? 0xFF : ms->smp.threads;
++ t->thread_count = (threads_per_socket > 255) ? 0xFF : threads_per_socket;
+
+ t->processor_characteristics = cpu_to_le16(0x02); /* Unknown */
+ t->processor_family2 = cpu_to_le16(0x01); /* Other */
+
+ if (tbl_len == SMBIOS_TYPE_4_LEN_V30) {
+- t->core_count2 = t->core_enabled2 = cpu_to_le16(ms->smp.cores);
+- t->thread_count2 = cpu_to_le16(ms->smp.threads);
++ t->core_count2 = t->core_enabled2 = cpu_to_le16(cores_per_socket);
++ t->thread_count2 = cpu_to_le16(threads_per_socket);
+ }
+
+ SMBIOS_BUILD_TABLE_POST;
+@@ -1087,8 +1092,7 @@ void smbios_get_tables(MachineState *ms,
+ smbios_build_type_2_table();
+ smbios_build_type_3_table();
+
+- smbios_smp_sockets = DIV_ROUND_UP(ms->smp.cpus,
+- ms->smp.cores * ms->smp.threads);
++ smbios_smp_sockets = ms->smp.sockets;
+ assert(smbios_smp_sockets >= 1);
+
+ for (i = 0; i < smbios_smp_sockets; i++) {
+diff --git a/hw/tpm/tpm_tis_sysbus.c b/hw/tpm/tpm_tis_sysbus.c
+index 45e63efd63..6724b3d4f6 100644
+--- a/hw/tpm/tpm_tis_sysbus.c
++++ b/hw/tpm/tpm_tis_sysbus.c
+@@ -93,7 +93,6 @@ static void tpm_tis_sysbus_reset(DeviceState *dev)
+ static Property tpm_tis_sysbus_properties[] = {
+ DEFINE_PROP_UINT32("irq", TPMStateSysBus, state.irq_num, TPM_TIS_IRQ),
+ DEFINE_PROP_TPMBE("tpmdev", TPMStateSysBus, state.be_driver),
+- DEFINE_PROP_BOOL("ppi", TPMStateSysBus, state.ppi_enabled, false),
+ DEFINE_PROP_END_OF_LIST(),
+ };
+
+diff --git a/hw/usb/dev-uas.c b/hw/usb/dev-uas.c
+index 5192b062d6..18c319043e 100644
+--- a/hw/usb/dev-uas.c
++++ b/hw/usb/dev-uas.c
+@@ -937,7 +937,8 @@ static void usb_uas_realize(USBDevice *dev, Error **errp)
+
+ QTAILQ_INIT(&uas->results);
+ QTAILQ_INIT(&uas->requests);
+- uas->status_bh = qemu_bh_new(usb_uas_send_status_bh, uas);
++ uas->status_bh = qemu_bh_new_guarded(usb_uas_send_status_bh, uas,
++ &d->mem_reentrancy_guard);
+
+ dev->flags |= (1 << USB_DEV_FLAG_IS_SCSI_STORAGE);
+ scsi_bus_init(&uas->bus, sizeof(uas->bus), DEVICE(dev), &usb_uas_scsi_info);
+diff --git a/hw/usb/hcd-dwc2.c b/hw/usb/hcd-dwc2.c
+index 8755e9cbb0..a0c4e782b2 100644
+--- a/hw/usb/hcd-dwc2.c
++++ b/hw/usb/hcd-dwc2.c
+@@ -1364,7 +1364,8 @@ static void dwc2_realize(DeviceState *dev, Error **errp)
+ s->fi = USB_FRMINTVL - 1;
+ s->eof_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, dwc2_frame_boundary, s);
+ s->frame_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, dwc2_work_timer, s);
+- s->async_bh = qemu_bh_new(dwc2_work_bh, s);
++ s->async_bh = qemu_bh_new_guarded(dwc2_work_bh, s,
++ &dev->mem_reentrancy_guard);
+
+ sysbus_init_irq(sbd, &s->irq);
+ }
+diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
+index d4da8dcb8d..c930c60921 100644
+--- a/hw/usb/hcd-ehci.c
++++ b/hw/usb/hcd-ehci.c
+@@ -2533,7 +2533,8 @@ void usb_ehci_realize(EHCIState *s, DeviceState *dev, Error **errp)
+ }
+
+ s->frame_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, ehci_work_timer, s);
+- s->async_bh = qemu_bh_new(ehci_work_bh, s);
++ s->async_bh = qemu_bh_new_guarded(ehci_work_bh, s,
++ &dev->mem_reentrancy_guard);
+ s->device = dev;
+
+ s->vmstate = qemu_add_vm_change_state_handler(usb_ehci_vm_state_change, s);
+diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c
+index d1b5657d72..ef967c42a1 100644
+--- a/hw/usb/hcd-uhci.c
++++ b/hw/usb/hcd-uhci.c
+@@ -1193,7 +1193,7 @@ void usb_uhci_common_realize(PCIDevice *dev, Error **errp)
+ USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
+ }
+ }
+- s->bh = qemu_bh_new(uhci_bh, s);
++ s->bh = qemu_bh_new_guarded(uhci_bh, s, &DEVICE(dev)->mem_reentrancy_guard);
+ s->frame_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, uhci_frame_timer, s);
+ s->num_ports_vmstate = NB_PORTS;
+ QTAILQ_INIT(&s->queues);
+diff --git a/hw/usb/host-libusb.c b/hw/usb/host-libusb.c
+index 176868d345..f500db85ab 100644
+--- a/hw/usb/host-libusb.c
++++ b/hw/usb/host-libusb.c
+@@ -1141,7 +1141,8 @@ static void usb_host_nodev_bh(void *opaque)
+ static void usb_host_nodev(USBHostDevice *s)
+ {
+ if (!s->bh_nodev) {
+- s->bh_nodev = qemu_bh_new(usb_host_nodev_bh, s);
++ s->bh_nodev = qemu_bh_new_guarded(usb_host_nodev_bh, s,
++ &DEVICE(s)->mem_reentrancy_guard);
+ }
+ qemu_bh_schedule(s->bh_nodev);
+ }
+@@ -1739,7 +1740,8 @@ static int usb_host_post_load(void *opaque, int version_id)
+ USBHostDevice *dev = opaque;
+
+ if (!dev->bh_postld) {
+- dev->bh_postld = qemu_bh_new(usb_host_post_load_bh, dev);
++ dev->bh_postld = qemu_bh_new_guarded(usb_host_post_load_bh, dev,
++ &DEVICE(dev)->mem_reentrancy_guard);
+ }
+ qemu_bh_schedule(dev->bh_postld);
+ dev->bh_postld_pending = true;
+diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
+index fd7df599bc..39fbaaab16 100644
+--- a/hw/usb/redirect.c
++++ b/hw/usb/redirect.c
+@@ -1441,8 +1441,10 @@ static void usbredir_realize(USBDevice *udev, Error **errp)
+ }
+ }
+
+- dev->chardev_close_bh = qemu_bh_new(usbredir_chardev_close_bh, dev);
+- dev->device_reject_bh = qemu_bh_new(usbredir_device_reject_bh, dev);
++ dev->chardev_close_bh = qemu_bh_new_guarded(usbredir_chardev_close_bh, dev,
++ &DEVICE(dev)->mem_reentrancy_guard);
++ dev->device_reject_bh = qemu_bh_new_guarded(usbredir_device_reject_bh, dev,
++ &DEVICE(dev)->mem_reentrancy_guard);
+ dev->attach_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, usbredir_do_attach, dev);
+
+ packet_id_queue_init(&dev->cancelled, dev, "cancelled");
+diff --git a/hw/usb/xen-usb.c b/hw/usb/xen-usb.c
+index 0f7369e7ed..dec91294ad 100644
+--- a/hw/usb/xen-usb.c
++++ b/hw/usb/xen-usb.c
+@@ -1021,7 +1021,8 @@ static void usbback_alloc(struct XenLegacyDevice *xendev)
+
+ QTAILQ_INIT(&usbif->req_free_q);
+ QSIMPLEQ_INIT(&usbif->hotplug_q);
+- usbif->bh = qemu_bh_new(usbback_bh, usbif);
++ usbif->bh = qemu_bh_new_guarded(usbback_bh, usbif,
++ &DEVICE(xendev)->mem_reentrancy_guard);
+ }
+
+ static int usbback_free(struct XenLegacyDevice *xendev)
+diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c
+index 73ac5eb675..e4c4c2d3c8 100644
+--- a/hw/virtio/virtio-balloon.c
++++ b/hw/virtio/virtio-balloon.c
+@@ -910,8 +910,9 @@ static void virtio_balloon_device_realize(DeviceState *dev, Error **errp)
+ precopy_add_notifier(&s->free_page_hint_notify);
+
+ object_ref(OBJECT(s->iothread));
+- s->free_page_bh = aio_bh_new(iothread_get_aio_context(s->iothread),
+- virtio_ballloon_get_free_page_hints, s);
++ s->free_page_bh = aio_bh_new_guarded(iothread_get_aio_context(s->iothread),
++ virtio_ballloon_get_free_page_hints, s,
++ &dev->mem_reentrancy_guard);
+ }
+
+ if (virtio_has_feature(s->host_features, VIRTIO_BALLOON_F_REPORTING)) {
+diff --git a/hw/virtio/virtio-crypto.c b/hw/virtio/virtio-crypto.c
+index 406b4e5fd0..b2e0646d9a 100644
+--- a/hw/virtio/virtio-crypto.c
++++ b/hw/virtio/virtio-crypto.c
+@@ -1057,7 +1057,8 @@ static void virtio_crypto_device_realize(DeviceState *dev, Error **errp)
+ vcrypto->vqs[i].dataq =
+ virtio_add_queue(vdev, 1024, virtio_crypto_handle_dataq_bh);
+ vcrypto->vqs[i].dataq_bh =
+- qemu_bh_new(virtio_crypto_dataq_bh, &vcrypto->vqs[i]);
++ qemu_bh_new_guarded(virtio_crypto_dataq_bh, &vcrypto->vqs[i],
++ &dev->mem_reentrancy_guard);
+ vcrypto->vqs[i].vcrypto = vcrypto;
+ }
+
+diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
+index 384c8f0f08..b7da7f074d 100644
+--- a/hw/virtio/virtio.c
++++ b/hw/virtio/virtio.c
+@@ -3451,6 +3451,39 @@ static int virtio_set_features_nocheck(VirtIODevice *vdev, uint64_t val)
+ return bad ? -1 : 0;
+ }
+
++typedef struct VirtioSetFeaturesNocheckData {
++ Coroutine *co;
++ VirtIODevice *vdev;
++ uint64_t val;
++ int ret;
++} VirtioSetFeaturesNocheckData;
++
++static void virtio_set_features_nocheck_bh(void *opaque)
++{
++ VirtioSetFeaturesNocheckData *data = opaque;
++
++ data->ret = virtio_set_features_nocheck(data->vdev, data->val);
++ aio_co_wake(data->co);
++}
++
++static int
++virtio_set_features_nocheck_maybe_co(VirtIODevice *vdev, uint64_t val)
++{
++ if (qemu_in_coroutine()) {
++ VirtioSetFeaturesNocheckData data = {
++ .co = qemu_coroutine_self(),
++ .vdev = vdev,
++ .val = val,
++ };
++ aio_bh_schedule_oneshot(qemu_get_current_aio_context(),
++ virtio_set_features_nocheck_bh, &data);
++ qemu_coroutine_yield();
++ return data.ret;
++ } else {
++ return virtio_set_features_nocheck(vdev, val);
++ }
++}
++
+ int virtio_set_features(VirtIODevice *vdev, uint64_t val)
+ {
+ int ret;
+@@ -3621,14 +3654,14 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id)
+ * host_features.
+ */
+ uint64_t features64 = vdev->guest_features;
+- if (virtio_set_features_nocheck(vdev, features64) < 0) {
++ if (virtio_set_features_nocheck_maybe_co(vdev, features64) < 0) {
+ error_report("Features 0x%" PRIx64 " unsupported. "
+ "Allowed features: 0x%" PRIx64,
+ features64, vdev->host_features);
+ return -1;
+ }
+ } else {
+- if (virtio_set_features_nocheck(vdev, features) < 0) {
++ if (virtio_set_features_nocheck_maybe_co(vdev, features) < 0) {
+ error_report("Features 0x%x unsupported. "
+ "Allowed features: 0x%" PRIx64,
+ features, vdev->host_features);
+diff --git a/include/block/aio.h b/include/block/aio.h
+index d128558f1d..0dbfd435ae 100644
+--- a/include/block/aio.h
++++ b/include/block/aio.h
+@@ -22,6 +22,8 @@
+ #include "qemu/event_notifier.h"
+ #include "qemu/thread.h"
+ #include "qemu/timer.h"
++#include "hw/qdev-core.h"
++
+
+ typedef struct BlockAIOCB BlockAIOCB;
+ typedef void BlockCompletionFunc(void *opaque, int ret);
+@@ -323,9 +325,11 @@ void aio_bh_schedule_oneshot_full(AioContext *ctx, QEMUBHFunc *cb, void *opaque,
+ * is opaque and must be allocated prior to its use.
+ *
+ * @name: A human-readable identifier for debugging purposes.
++ * @reentrancy_guard: A guard set when entering a cb to prevent
++ * device-reentrancy issues
+ */
+ QEMUBH *aio_bh_new_full(AioContext *ctx, QEMUBHFunc *cb, void *opaque,
+- const char *name);
++ const char *name, MemReentrancyGuard *reentrancy_guard);
+
+ /**
+ * aio_bh_new: Allocate a new bottom half structure
+@@ -334,7 +338,17 @@ QEMUBH *aio_bh_new_full(AioContext *ctx, QEMUBHFunc *cb, void *opaque,
+ * string.
+ */
+ #define aio_bh_new(ctx, cb, opaque) \
+- aio_bh_new_full((ctx), (cb), (opaque), (stringify(cb)))
++ aio_bh_new_full((ctx), (cb), (opaque), (stringify(cb)), NULL)
++
++/**
++ * aio_bh_new_guarded: Allocate a new bottom half structure with a
++ * reentrancy_guard
++ *
++ * A convenience wrapper for aio_bh_new_full() that uses the cb as the name
++ * string.
++ */
++#define aio_bh_new_guarded(ctx, cb, opaque, guard) \
++ aio_bh_new_full((ctx), (cb), (opaque), (stringify(cb)), guard)
+
+ /**
+ * aio_notify: Force processing of pending events.
+diff --git a/include/exec/memory.h b/include/exec/memory.h
+index 91f8a2395a..124628ada4 100644
+--- a/include/exec/memory.h
++++ b/include/exec/memory.h
+@@ -741,6 +741,8 @@ struct MemoryRegion {
+ bool is_iommu;
+ RAMBlock *ram_block;
+ Object *owner;
++ /* owner as TYPE_DEVICE. Used for re-entrancy checks in MR access hotpath */
++ DeviceState *dev;
+
+ const MemoryRegionOps *ops;
+ void *opaque;
+@@ -765,6 +767,9 @@ struct MemoryRegion {
+ unsigned ioeventfd_nb;
+ MemoryRegionIoeventfd *ioeventfds;
+ RamDiscardManager *rdm; /* Only for RAM */
++
++ /* For devices designed to perform re-entrant IO into their own IO MRs */
++ bool disable_reentrancy_guard;
+ };
+
+ struct IOMMUMemoryRegion {
+diff --git a/include/exec/user/abitypes.h b/include/exec/user/abitypes.h
+index 743b8bb9ea..6178453d94 100644
+--- a/include/exec/user/abitypes.h
++++ b/include/exec/user/abitypes.h
+@@ -15,7 +15,18 @@
+ #define ABI_LLONG_ALIGNMENT 2
+ #endif
+
+-#if (defined(TARGET_I386) && !defined(TARGET_X86_64)) || defined(TARGET_SH4)
++#ifdef TARGET_CRIS
++#define ABI_SHORT_ALIGNMENT 1
++#define ABI_INT_ALIGNMENT 1
++#define ABI_LONG_ALIGNMENT 1
++#define ABI_LLONG_ALIGNMENT 1
++#endif
++
++#if (defined(TARGET_I386) && !defined(TARGET_X86_64)) \
++ || defined(TARGET_SH4) \
++ || defined(TARGET_OPENRISC) \
++ || defined(TARGET_MICROBLAZE) \
++ || defined(TARGET_NIOS2)
+ #define ABI_LLONG_ALIGNMENT 4
+ #endif
+
+diff --git a/include/hw/boards.h b/include/hw/boards.h
+index 90f1dd3aeb..ca2f0d3592 100644
+--- a/include/hw/boards.h
++++ b/include/hw/boards.h
+@@ -36,6 +36,8 @@ void machine_set_cpu_numa_node(MachineState *machine,
+ Error **errp);
+ void machine_parse_smp_config(MachineState *ms,
+ const SMPConfiguration *config, Error **errp);
++unsigned int machine_topo_get_cores_per_socket(const MachineState *ms);
++unsigned int machine_topo_get_threads_per_socket(const MachineState *ms);
+
+ /**
+ * machine_class_allow_dynamic_sysbus_dev: Add type to list of valid devices
+diff --git a/include/hw/i2c/aspeed_i2c.h b/include/hw/i2c/aspeed_i2c.h
+index adc904d6c1..91d0e7157c 100644
+--- a/include/hw/i2c/aspeed_i2c.h
++++ b/include/hw/i2c/aspeed_i2c.h
+@@ -132,9 +132,9 @@ REG32(I2CD_CMD, 0x14) /* I2CD Command/Status */
+ REG32(I2CD_DEV_ADDR, 0x18) /* Slave Device Address */
+ SHARED_FIELD(SLAVE_DEV_ADDR1, 0, 7)
+ REG32(I2CD_POOL_CTRL, 0x1C) /* Pool Buffer Control */
+- SHARED_FIELD(RX_COUNT, 24, 5)
++ SHARED_FIELD(RX_COUNT, 24, 6)
+ SHARED_FIELD(RX_SIZE, 16, 5)
+- SHARED_FIELD(TX_COUNT, 9, 5)
++ SHARED_FIELD(TX_COUNT, 8, 5)
+ FIELD(I2CD_POOL_CTRL, OFFSET, 2, 6) /* AST2400 */
+ REG32(I2CD_BYTE_BUF, 0x20) /* Transmit/Receive Byte Buffer */
+ SHARED_FIELD(RX_BUF, 8, 8)
+diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
+index 785dd5a56e..886f6bb79e 100644
+--- a/include/hw/qdev-core.h
++++ b/include/hw/qdev-core.h
+@@ -162,6 +162,10 @@ struct NamedClockList {
+ QLIST_ENTRY(NamedClockList) node;
+ };
+
++typedef struct {
++ bool engaged_in_io;
++} MemReentrancyGuard;
++
+ /**
+ * DeviceState:
+ * @realized: Indicates whether the device has been fully constructed.
+@@ -194,6 +198,9 @@ struct DeviceState {
+ int alias_required_for_version;
+ ResettableState reset;
+ GSList *unplug_blockers;
++
++ /* Is the device currently in mmio/pio/dma? Used to prevent re-entrancy */
++ MemReentrancyGuard mem_reentrancy_guard;
+ };
+
+ struct DeviceListener {
+diff --git a/include/hw/virtio/virtio-gpu-bswap.h b/include/hw/virtio/virtio-gpu-bswap.h
+index 9124108485..637a0585d0 100644
+--- a/include/hw/virtio/virtio-gpu-bswap.h
++++ b/include/hw/virtio/virtio-gpu-bswap.h
+@@ -63,7 +63,10 @@ virtio_gpu_create_blob_bswap(struct virtio_gpu_resource_create_blob *cblob)
+ {
+ virtio_gpu_ctrl_hdr_bswap(&cblob->hdr);
+ le32_to_cpus(&cblob->resource_id);
++ le32_to_cpus(&cblob->blob_mem);
+ le32_to_cpus(&cblob->blob_flags);
++ le32_to_cpus(&cblob->nr_entries);
++ le64_to_cpus(&cblob->blob_id);
+ le64_to_cpus(&cblob->size);
+ }
+
+diff --git a/include/qemu/main-loop.h b/include/qemu/main-loop.h
+index 3c9a9a982d..5c7e95601c 100644
+--- a/include/qemu/main-loop.h
++++ b/include/qemu/main-loop.h
+@@ -360,9 +360,12 @@ void qemu_cond_timedwait_iothread(QemuCond *cond, int ms);
+
+ void qemu_fd_register(int fd);
+
++#define qemu_bh_new_guarded(cb, opaque, guard) \
++ qemu_bh_new_full((cb), (opaque), (stringify(cb)), guard)
+ #define qemu_bh_new(cb, opaque) \
+- qemu_bh_new_full((cb), (opaque), (stringify(cb)))
+-QEMUBH *qemu_bh_new_full(QEMUBHFunc *cb, void *opaque, const char *name);
++ qemu_bh_new_full((cb), (opaque), (stringify(cb)), NULL)
++QEMUBH *qemu_bh_new_full(QEMUBHFunc *cb, void *opaque, const char *name,
++ MemReentrancyGuard *reentrancy_guard);
+ void qemu_bh_schedule_idle(QEMUBH *bh);
+
+ enum {
+diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
+index e9a97eda8c..c4ff7d9a4c 100644
+--- a/include/sysemu/kvm.h
++++ b/include/sysemu/kvm.h
+@@ -369,6 +369,8 @@ int kvm_arch_get_registers(CPUState *cpu);
+
+ int kvm_arch_put_registers(CPUState *cpu, int level);
+
++int kvm_arch_get_default_type(MachineState *ms);
++
+ int kvm_arch_init(MachineState *ms, KVMState *s);
+
+ int kvm_arch_init_vcpu(CPUState *cpu);
+diff --git a/linux-user/elfload.c b/linux-user/elfload.c
+index 20894b633f..c2c095d383 100644
+--- a/linux-user/elfload.c
++++ b/linux-user/elfload.c
+@@ -1664,7 +1664,8 @@ static uint32_t get_elf_hwcap(void)
+ #define MISA_BIT(EXT) (1 << (EXT - 'A'))
+ RISCVCPU *cpu = RISCV_CPU(thread_cpu);
+ uint32_t mask = MISA_BIT('I') | MISA_BIT('M') | MISA_BIT('A')
+- | MISA_BIT('F') | MISA_BIT('D') | MISA_BIT('C');
++ | MISA_BIT('F') | MISA_BIT('D') | MISA_BIT('C')
++ | MISA_BIT('V');
+
+ return cpu->env.misa_ext & mask;
+ #undef MISA_BIT
+diff --git a/linux-user/riscv/signal.c b/linux-user/riscv/signal.c
+index eaa168199a..f989f7f51f 100644
+--- a/linux-user/riscv/signal.c
++++ b/linux-user/riscv/signal.c
+@@ -38,8 +38,8 @@ struct target_sigcontext {
+ }; /* cf. riscv-linux:arch/riscv/include/uapi/asm/ptrace.h */
+
+ struct target_ucontext {
+- unsigned long uc_flags;
+- struct target_ucontext *uc_link;
++ abi_ulong uc_flags;
++ abi_ptr uc_link;
+ target_stack_t uc_stack;
+ target_sigset_t uc_sigmask;
+ uint8_t __unused[1024 / 8 - sizeof(target_sigset_t)];
+diff --git a/migration/block.c b/migration/block.c
+index 4347da1526..4026b73f75 100644
+--- a/migration/block.c
++++ b/migration/block.c
+@@ -376,7 +376,9 @@ static void unset_dirty_tracking(void)
+ BlkMigDevState *bmds;
+
+ QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
+- bdrv_release_dirty_bitmap(bmds->dirty_bitmap);
++ if (bmds->dirty_bitmap) {
++ bdrv_release_dirty_bitmap(bmds->dirty_bitmap);
++ }
+ }
+ }
+
+@@ -684,13 +686,18 @@ static int64_t get_remaining_dirty(void)
+ static void block_migration_cleanup_bmds(void)
+ {
+ BlkMigDevState *bmds;
++ BlockDriverState *bs;
+ AioContext *ctx;
+
+ unset_dirty_tracking();
+
+ while ((bmds = QSIMPLEQ_FIRST(&block_mig_state.bmds_list)) != NULL) {
+ QSIMPLEQ_REMOVE_HEAD(&block_mig_state.bmds_list, entry);
+- bdrv_op_unblock_all(blk_bs(bmds->blk), bmds->blocker);
++
++ bs = blk_bs(bmds->blk);
++ if (bs) {
++ bdrv_op_unblock_all(bs, bmds->blocker);
++ }
+ error_free(bmds->blocker);
+
+ /* Save ctx, because bmds->blk can disappear during blk_unref. */
+diff --git a/python/.gitignore b/python/.gitignore
+index 904f324bb1..c3ceb1ca0a 100644
+--- a/python/.gitignore
++++ b/python/.gitignore
+@@ -11,8 +11,8 @@ qemu.egg-info/
+ .idea/
+ .vscode/
+
+-# virtual environments (pipenv et al)
+-.venv/
++# virtual environments
++.min-venv/
+ .tox/
+ .dev-venv/
+
+diff --git a/python/Makefile b/python/Makefile
+index b170708398..c5bd6ff83a 100644
+--- a/python/Makefile
++++ b/python/Makefile
+@@ -1,15 +1,16 @@
+ QEMU_VENV_DIR=.dev-venv
++QEMU_MINVENV_DIR=.min-venv
+ QEMU_TOX_EXTRA_ARGS ?=
+
+ .PHONY: help
+ help:
+ @echo "python packaging help:"
+ @echo ""
+- @echo "make check-pipenv:"
+- @echo " Run tests in pipenv's virtual environment."
++ @echo "make check-minreqs:"
++ @echo " Run tests in the minreqs virtual environment."
+ @echo " These tests use the oldest dependencies."
+- @echo " Requires: Python 3.6 and pipenv."
+- @echo " Hint (Fedora): 'sudo dnf install python3.6 pipenv'"
++ @echo " Requires: Python 3.6"
++ @echo " Hint (Fedora): 'sudo dnf install python3.6'"
+ @echo ""
+ @echo "make check-tox:"
+ @echo " Run tests against multiple python versions."
+@@ -33,8 +34,8 @@ help:
+ @echo " and install the qemu package in editable mode."
+ @echo " (Can be used in or outside of a venv.)"
+ @echo ""
+- @echo "make pipenv"
+- @echo " Creates pipenv's virtual environment (.venv)"
++ @echo "make min-venv"
++ @echo " Creates the minreqs virtual environment ($(QEMU_MINVENV_DIR))"
+ @echo ""
+ @echo "make dev-venv"
+ @echo " Creates a simple venv for check-dev. ($(QEMU_VENV_DIR))"
+@@ -43,21 +44,38 @@ help:
+ @echo " Remove package build output."
+ @echo ""
+ @echo "make distclean:"
+- @echo " remove pipenv/venv files, qemu package forwarder,"
++ @echo " remove venv files, qemu package forwarder,"
+ @echo " built distribution files, and everything from 'make clean'."
+ @echo ""
+ @echo -e "Have a nice day ^_^\n"
+
+-.PHONY: pipenv
+-pipenv: .venv
+-.venv: Pipfile.lock
+- @PIPENV_VENV_IN_PROJECT=1 pipenv sync --dev --keep-outdated
+- rm -f pyproject.toml
+- @touch .venv
++.PHONY: pipenv check-pipenv
++pipenv check-pipenv:
++ @echo "pipenv was dropped; try 'make check-minreqs' or 'make min-venv'"
++ @exit 1
++
++.PHONY: min-venv
++min-venv: $(QEMU_MINVENV_DIR) $(QEMU_MINVENV_DIR)/bin/activate
++$(QEMU_MINVENV_DIR) $(QEMU_MINVENV_DIR)/bin/activate: setup.cfg tests/minreqs.txt
++ @echo "VENV $(QEMU_MINVENV_DIR)"
++ @python3.6 -m venv $(QEMU_MINVENV_DIR)
++ @( \
++ echo "ACTIVATE $(QEMU_MINVENV_DIR)"; \
++ . $(QEMU_MINVENV_DIR)/bin/activate; \
++ echo "INSTALL -r tests/minreqs.txt $(QEMU_MINVENV_DIR)";\
++ pip install -r tests/minreqs.txt 1>/dev/null; \
++ echo "INSTALL -e qemu $(QEMU_MINVENV_DIR)"; \
++ pip install -e . 1>/dev/null; \
++ )
++ @touch $(QEMU_MINVENV_DIR)
+
+-.PHONY: check-pipenv
+-check-pipenv: pipenv
+- @pipenv run make check
++.PHONY: check-minreqs
++check-minreqs: min-venv
++ @( \
++ echo "ACTIVATE $(QEMU_MINVENV_DIR)"; \
++ . $(QEMU_MINVENV_DIR)/bin/activate; \
++ make check; \
++ )
+
+ .PHONY: dev-venv
+ dev-venv: $(QEMU_VENV_DIR) $(QEMU_VENV_DIR)/bin/activate
+@@ -106,6 +124,7 @@ clean:
+
+ .PHONY: distclean
+ distclean: clean
+- rm -rf qemu.egg-info/ .venv/ .tox/ $(QEMU_VENV_DIR) dist/
++ rm -rf qemu.egg-info/ .eggs/ dist/
++ rm -rf $(QEMU_VENV_DIR) $(QEMU_MINVENV_DIR) .tox/
+ rm -f .coverage .coverage.*
+ rm -rf htmlcov/
+diff --git a/python/Pipfile b/python/Pipfile
+deleted file mode 100644
+index e7acb8cefa..0000000000
+--- a/python/Pipfile
++++ /dev/null
+@@ -1,13 +0,0 @@
+-[[source]]
+-name = "pypi"
+-url = "https://pypi.org/simple"
+-verify_ssl = true
+-
+-[dev-packages]
+-qemu = {editable = true, extras = ["devel"], path = "."}
+-
+-[packages]
+-qemu = {editable = true,path = "."}
+-
+-[requires]
+-python_version = "3.6"
+diff --git a/python/Pipfile.lock b/python/Pipfile.lock
+deleted file mode 100644
+index ce46404ce0..0000000000
+--- a/python/Pipfile.lock
++++ /dev/null
+@@ -1,347 +0,0 @@
+-{
+- "_meta": {
+- "hash": {
+- "sha256": "f1a25654d884a5b450e38d78b1f2e3ebb9073e421cc4358d4bbb83ac251a5670"
+- },
+- "pipfile-spec": 6,
+- "requires": {
+- "python_version": "3.6"
+- },
+- "sources": [
+- {
+- "name": "pypi",
+- "url": "https://pypi.org/simple",
+- "verify_ssl": true
+- }
+- ]
+- },
+- "default": {
+- "qemu": {
+- "editable": true,
+- "path": "."
+- }
+- },
+- "develop": {
+- "appdirs": {
+- "hashes": [
+- "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41",
+- "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128"
+- ],
+- "version": "==1.4.4"
+- },
+- "astroid": {
+- "hashes": [
+- "sha256:09bdb456e02564731f8b5957cdd0c98a7f01d2db5e90eb1d794c353c28bfd705",
+- "sha256:6a8a51f64dae307f6e0c9db752b66a7951e282389d8362cc1d39a56f3feeb31d"
+- ],
+- "index": "pypi",
+- "version": "==2.6.0"
+- },
+- "avocado-framework": {
+- "hashes": [
+- "sha256:244cb569f8eb4e50a22ac82e1a2b2bba2458999f4281efbe2651bd415d59c65b",
+- "sha256:6f15998b67ecd0e7dde790c4de4dd249d6df52dfe6d5cc4e2dd6596df51c3583"
+- ],
+- "index": "pypi",
+- "version": "==90.0"
+- },
+- "distlib": {
+- "hashes": [
+- "sha256:106fef6dc37dd8c0e2c0a60d3fca3e77460a48907f335fa28420463a6f799736",
+- "sha256:23e223426b28491b1ced97dc3bbe183027419dfc7982b4fa2f05d5f3ff10711c"
+- ],
+- "index": "pypi",
+- "version": "==0.3.2"
+- },
+- "filelock": {
+- "hashes": [
+- "sha256:18d82244ee114f543149c66a6e0c14e9c4f8a1044b5cdaadd0f82159d6a6ff59",
+- "sha256:929b7d63ec5b7d6b71b0fa5ac14e030b3f70b75747cef1b10da9b879fef15836"
+- ],
+- "index": "pypi",
+- "version": "==3.0.12"
+- },
+- "flake8": {
+- "hashes": [
+- "sha256:6a35f5b8761f45c5513e3405f110a86bea57982c3b75b766ce7b65217abe1670",
+- "sha256:c01f8a3963b3571a8e6bd7a4063359aff90749e160778e03817cd9b71c9e07d2"
+- ],
+- "index": "pypi",
+- "version": "==3.6.0"
+- },
+- "fusepy": {
+- "hashes": [
+- "sha256:10f5c7f5414241bffecdc333c4d3a725f1d6605cae6b4eaf86a838ff49cdaf6c",
+- "sha256:a9f3a3699080ddcf0919fd1eb2cf743e1f5859ca54c2018632f939bdfac269ee"
+- ],
+- "index": "pypi",
+- "version": "==2.0.4"
+- },
+- "importlib-metadata": {
+- "hashes": [
+- "sha256:90bb658cdbbf6d1735b6341ce708fc7024a3e14e99ffdc5783edea9f9b077f83",
+- "sha256:dc15b2969b4ce36305c51eebe62d418ac7791e9a157911d58bfb1f9ccd8e2070"
+- ],
+- "markers": "python_version < '3.8'",
+- "version": "==1.7.0"
+- },
+- "importlib-resources": {
+- "hashes": [
+- "sha256:54161657e8ffc76596c4ede7080ca68cb02962a2e074a2586b695a93a925d36e",
+- "sha256:e962bff7440364183203d179d7ae9ad90cb1f2b74dcb84300e88ecc42dca3351"
+- ],
+- "index": "pypi",
+- "version": "==5.1.4"
+- },
+- "isort": {
+- "hashes": [
+- "sha256:408e4d75d84f51b64d0824894afee44469eba34a4caee621dc53799f80d71ccc",
+- "sha256:64022dea6a06badfa09b300b4dfe8ba968114a737919e8ed50aea1c288f078aa"
+- ],
+- "index": "pypi",
+- "version": "==5.1.2"
+- },
+- "lazy-object-proxy": {
+- "hashes": [
+- "sha256:17e0967ba374fc24141738c69736da90e94419338fd4c7c7bef01ee26b339653",
+- "sha256:1fee665d2638491f4d6e55bd483e15ef21f6c8c2095f235fef72601021e64f61",
+- "sha256:22ddd618cefe54305df49e4c069fa65715be4ad0e78e8d252a33debf00f6ede2",
+- "sha256:24a5045889cc2729033b3e604d496c2b6f588c754f7a62027ad4437a7ecc4837",
+- "sha256:410283732af311b51b837894fa2f24f2c0039aa7f220135192b38fcc42bd43d3",
+- "sha256:4732c765372bd78a2d6b2150a6e99d00a78ec963375f236979c0626b97ed8e43",
+- "sha256:489000d368377571c6f982fba6497f2aa13c6d1facc40660963da62f5c379726",
+- "sha256:4f60460e9f1eb632584c9685bccea152f4ac2130e299784dbaf9fae9f49891b3",
+- "sha256:5743a5ab42ae40caa8421b320ebf3a998f89c85cdc8376d6b2e00bd12bd1b587",
+- "sha256:85fb7608121fd5621cc4377a8961d0b32ccf84a7285b4f1d21988b2eae2868e8",
+- "sha256:9698110e36e2df951c7c36b6729e96429c9c32b3331989ef19976592c5f3c77a",
+- "sha256:9d397bf41caad3f489e10774667310d73cb9c4258e9aed94b9ec734b34b495fd",
+- "sha256:b579f8acbf2bdd9ea200b1d5dea36abd93cabf56cf626ab9c744a432e15c815f",
+- "sha256:b865b01a2e7f96db0c5d12cfea590f98d8c5ba64ad222300d93ce6ff9138bcad",
+- "sha256:bf34e368e8dd976423396555078def5cfc3039ebc6fc06d1ae2c5a65eebbcde4",
+- "sha256:c6938967f8528b3668622a9ed3b31d145fab161a32f5891ea7b84f6b790be05b",
+- "sha256:d1c2676e3d840852a2de7c7d5d76407c772927addff8d742b9808fe0afccebdf",
+- "sha256:d7124f52f3bd259f510651450e18e0fd081ed82f3c08541dffc7b94b883aa981",
+- "sha256:d900d949b707778696fdf01036f58c9876a0d8bfe116e8d220cfd4b15f14e741",
+- "sha256:ebfd274dcd5133e0afae738e6d9da4323c3eb021b3e13052d8cbd0e457b1256e",
+- "sha256:ed361bb83436f117f9917d282a456f9e5009ea12fd6de8742d1a4752c3017e93",
+- "sha256:f5144c75445ae3ca2057faac03fda5a902eff196702b0a24daf1d6ce0650514b"
+- ],
+- "index": "pypi",
+- "version": "==1.6.0"
+- },
+- "mccabe": {
+- "hashes": [
+- "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42",
+- "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"
+- ],
+- "version": "==0.6.1"
+- },
+- "mypy": {
+- "hashes": [
+- "sha256:00cb1964a7476e871d6108341ac9c1a857d6bd20bf5877f4773ac5e9d92cd3cd",
+- "sha256:127de5a9b817a03a98c5ae8a0c46a20dc44442af6dcfa2ae7f96cb519b312efa",
+- "sha256:1f3976a945ad7f0a0727aafdc5651c2d3278e3c88dee94e2bf75cd3386b7b2f4",
+- "sha256:2f8c098f12b402c19b735aec724cc9105cc1a9eea405d08814eb4b14a6fb1a41",
+- "sha256:4ef13b619a289aa025f2273e05e755f8049bb4eaba6d703a425de37d495d178d",
+- "sha256:5d142f219bf8c7894dfa79ebfb7d352c4c63a325e75f10dfb4c3db9417dcd135",
+- "sha256:62eb5dd4ea86bda8ce386f26684f7f26e4bfe6283c9f2b6ca6d17faf704dcfad",
+- "sha256:64c36eb0936d0bfb7d8da49f92c18e312ad2e3ed46e5548ae4ca997b0d33bd59",
+- "sha256:75eed74d2faf2759f79c5f56f17388defd2fc994222312ec54ee921e37b31ad4",
+- "sha256:974bebe3699b9b46278a7f076635d219183da26e1a675c1f8243a69221758273",
+- "sha256:a5e5bb12b7982b179af513dddb06fca12285f0316d74f3964078acbfcf4c68f2",
+- "sha256:d31291df31bafb997952dc0a17ebb2737f802c754aed31dd155a8bfe75112c57",
+- "sha256:d3b4941de44341227ece1caaf5b08b23e42ad4eeb8b603219afb11e9d4cfb437",
+- "sha256:eadb865126da4e3c4c95bdb47fe1bb087a3e3ea14d39a3b13224b8a4d9f9a102"
+- ],
+- "index": "pypi",
+- "version": "==0.780"
+- },
+- "mypy-extensions": {
+- "hashes": [
+- "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d",
+- "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"
+- ],
+- "version": "==0.4.3"
+- },
+- "packaging": {
+- "hashes": [
+- "sha256:5b327ac1320dc863dca72f4514ecc086f31186744b84a230374cc1fd776feae5",
+- "sha256:67714da7f7bc052e064859c05c595155bd1ee9f69f76557e21f051443c20947a"
+- ],
+- "index": "pypi",
+- "version": "==20.9"
+- },
+- "pluggy": {
+- "hashes": [
+- "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0",
+- "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"
+- ],
+- "index": "pypi",
+- "version": "==0.13.1"
+- },
+- "py": {
+- "hashes": [
+- "sha256:21b81bda15b66ef5e1a777a21c4dcd9c20ad3efd0b3f817e7a809035269e1bd3",
+- "sha256:3b80836aa6d1feeaa108e046da6423ab8f6ceda6468545ae8d02d9d58d18818a"
+- ],
+- "index": "pypi",
+- "version": "==1.10.0"
+- },
+- "pycodestyle": {
+- "hashes": [
+- "sha256:74abc4e221d393ea5ce1f129ea6903209940c1ecd29e002e8c6933c2b21026e0",
+- "sha256:cbc619d09254895b0d12c2c691e237b2e91e9b2ecf5e84c26b35400f93dcfb83",
+- "sha256:cbfca99bd594a10f674d0cd97a3d802a1fdef635d4361e1a2658de47ed261e3a"
+- ],
+- "version": "==2.4.0"
+- },
+- "pyflakes": {
+- "hashes": [
+- "sha256:9a7662ec724d0120012f6e29d6248ae3727d821bba522a0e6b356eff19126a49",
+- "sha256:f661252913bc1dbe7fcfcbf0af0db3f42ab65aabd1a6ca68fe5d466bace94dae"
+- ],
+- "version": "==2.0.0"
+- },
+- "pygments": {
+- "hashes": [
+- "sha256:a18f47b506a429f6f4b9df81bb02beab9ca21d0a5fee38ed15aef65f0545519f",
+- "sha256:d66e804411278594d764fc69ec36ec13d9ae9147193a1740cd34d272ca383b8e"
+- ],
+- "index": "pypi",
+- "version": "==2.9.0"
+- },
+- "pylint": {
+- "hashes": [
+- "sha256:082a6d461b54f90eea49ca90fff4ee8b6e45e8029e5dbd72f6107ef84f3779c0",
+- "sha256:a01cd675eccf6e25b3bdb42be184eb46aaf89187d612ba0fb5f93328ed6b0fd5"
+- ],
+- "index": "pypi",
+- "version": "==2.8.0"
+- },
+- "pyparsing": {
+- "hashes": [
+- "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1",
+- "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"
+- ],
+- "index": "pypi",
+- "version": "==2.4.7"
+- },
+- "qemu": {
+- "editable": true,
+- "path": "."
+- },
+- "setuptools": {
+- "hashes": [
+- "sha256:22c7348c6d2976a52632c67f7ab0cdf40147db7789f9aed18734643fe9cf3373",
+- "sha256:4ce92f1e1f8f01233ee9952c04f6b81d1e02939d6e1b488428154974a4d0783e"
+- ],
+- "markers": "python_version >= '3.6'",
+- "version": "==59.6.0"
+- },
+- "six": {
+- "hashes": [
+- "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926",
+- "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
+- ],
+- "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+- "version": "==1.16.0"
+- },
+- "toml": {
+- "hashes": [
+- "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b",
+- "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"
+- ],
+- "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+- "version": "==0.10.2"
+- },
+- "tox": {
+- "hashes": [
+- "sha256:c60692d92fe759f46c610ac04c03cf0169432d1ff8e981e8ae63e068d0954fc3",
+- "sha256:f179cb4043d7dc1339425dd49ab1dd8c916246b0d9173143c1b0af7498a03ab0"
+- ],
+- "index": "pypi",
+- "version": "==3.18.0"
+- },
+- "typed-ast": {
+- "hashes": [
+- "sha256:01ae5f73431d21eead5015997ab41afa53aa1fbe252f9da060be5dad2c730ace",
+- "sha256:067a74454df670dcaa4e59349a2e5c81e567d8d65458d480a5b3dfecec08c5ff",
+- "sha256:0fb71b8c643187d7492c1f8352f2c15b4c4af3f6338f21681d3681b3dc31a266",
+- "sha256:1b3ead4a96c9101bef08f9f7d1217c096f31667617b58de957f690c92378b528",
+- "sha256:2068531575a125b87a41802130fa7e29f26c09a2833fea68d9a40cf33902eba6",
+- "sha256:209596a4ec71d990d71d5e0d312ac935d86930e6eecff6ccc7007fe54d703808",
+- "sha256:2c726c276d09fc5c414693a2de063f521052d9ea7c240ce553316f70656c84d4",
+- "sha256:398e44cd480f4d2b7ee8d98385ca104e35c81525dd98c519acff1b79bdaac363",
+- "sha256:52b1eb8c83f178ab787f3a4283f68258525f8d70f778a2f6dd54d3b5e5fb4341",
+- "sha256:5feca99c17af94057417d744607b82dd0a664fd5e4ca98061480fd8b14b18d04",
+- "sha256:7538e495704e2ccda9b234b82423a4038f324f3a10c43bc088a1636180f11a41",
+- "sha256:760ad187b1041a154f0e4d0f6aae3e40fdb51d6de16e5c99aedadd9246450e9e",
+- "sha256:777a26c84bea6cd934422ac2e3b78863a37017618b6e5c08f92ef69853e765d3",
+- "sha256:95431a26309a21874005845c21118c83991c63ea800dd44843e42a916aec5899",
+- "sha256:9ad2c92ec681e02baf81fdfa056fe0d818645efa9af1f1cd5fd6f1bd2bdfd805",
+- "sha256:9c6d1a54552b5330bc657b7ef0eae25d00ba7ffe85d9ea8ae6540d2197a3788c",
+- "sha256:aee0c1256be6c07bd3e1263ff920c325b59849dc95392a05f258bb9b259cf39c",
+- "sha256:af3d4a73793725138d6b334d9d247ce7e5f084d96284ed23f22ee626a7b88e39",
+- "sha256:b36b4f3920103a25e1d5d024d155c504080959582b928e91cb608a65c3a49e1a",
+- "sha256:b9574c6f03f685070d859e75c7f9eeca02d6933273b5e69572e5ff9d5e3931c3",
+- "sha256:bff6ad71c81b3bba8fa35f0f1921fb24ff4476235a6e94a26ada2e54370e6da7",
+- "sha256:c190f0899e9f9f8b6b7863debfb739abcb21a5c054f911ca3596d12b8a4c4c7f",
+- "sha256:c907f561b1e83e93fad565bac5ba9c22d96a54e7ea0267c708bffe863cbe4075",
+- "sha256:cae53c389825d3b46fb37538441f75d6aecc4174f615d048321b716df2757fb0",
+- "sha256:dd4a21253f42b8d2b48410cb31fe501d32f8b9fbeb1f55063ad102fe9c425e40",
+- "sha256:dde816ca9dac1d9c01dd504ea5967821606f02e510438120091b84e852367428",
+- "sha256:f2362f3cb0f3172c42938946dbc5b7843c2a28aec307c49100c8b38764eb6927",
+- "sha256:f328adcfebed9f11301eaedfa48e15bdece9b519fb27e6a8c01aa52a17ec31b3",
+- "sha256:f8afcf15cc511ada719a88e013cec87c11aff7b91f019295eb4530f96fe5ef2f",
+- "sha256:fb1bbeac803adea29cedd70781399c99138358c26d05fcbd23c13016b7f5ec65"
+- ],
+- "markers": "python_version < '3.8' and implementation_name == 'cpython'",
+- "version": "==1.4.3"
+- },
+- "typing-extensions": {
+- "hashes": [
+- "sha256:0ac0f89795dd19de6b97debb0c6af1c70987fd80a2d62d1958f7e56fcc31b497",
+- "sha256:50b6f157849174217d0656f99dc82fe932884fb250826c18350e159ec6cdf342",
+- "sha256:779383f6086d90c99ae41cf0ff39aac8a7937a9283ce0a414e5dd782f4c94a84"
+- ],
+- "index": "pypi",
+- "version": "==3.10.0.0"
+- },
+- "urwid": {
+- "hashes": [
+- "sha256:588bee9c1cb208d0906a9f73c613d2bd32c3ed3702012f51efe318a3f2127eae"
+- ],
+- "index": "pypi",
+- "version": "==2.1.2"
+- },
+- "urwid-readline": {
+- "hashes": [
+- "sha256:018020cbc864bb5ed87be17dc26b069eae2755cb29f3a9c569aac3bded1efaf4"
+- ],
+- "index": "pypi",
+- "version": "==0.13"
+- },
+- "virtualenv": {
+- "hashes": [
+- "sha256:14fdf849f80dbb29a4eb6caa9875d476ee2a5cf76a5f5415fa2f1606010ab467",
+- "sha256:2b0126166ea7c9c3661f5b8e06773d28f83322de7a3ff7d06f0aed18c9de6a76"
+- ],
+- "index": "pypi",
+- "version": "==20.4.7"
+- },
+- "wrapt": {
+- "hashes": [
+- "sha256:b62ffa81fb85f4332a4f609cab4ac40709470da05643a082ec1eb88e6d9b97d7"
+- ],
+- "version": "==1.12.1"
+- },
+- "zipp": {
+- "hashes": [
+- "sha256:3607921face881ba3e026887d8150cca609d517579abe052ac81fc5aeffdbd76",
+- "sha256:51cb66cc54621609dd593d1787f286ee42a5c0adbb4b29abea5a63edc3e03098"
+- ],
+- "index": "pypi",
+- "version": "==3.4.1"
+- }
+- }
+-}
+diff --git a/python/README.rst b/python/README.rst
+index 9c1fceaee7..d62e71528d 100644
+--- a/python/README.rst
++++ b/python/README.rst
+@@ -77,9 +77,6 @@ Files in this directory
+ - ``MANIFEST.in`` is read by python setuptools, it specifies additional files
+ that should be included by a source distribution.
+ - ``PACKAGE.rst`` is used as the README file that is visible on PyPI.org.
+-- ``Pipfile`` is used by Pipenv to generate ``Pipfile.lock``.
+-- ``Pipfile.lock`` is a set of pinned package dependencies that this package
+- is tested under in our CI suite. It is used by ``make check-pipenv``.
+ - ``README.rst`` you are here!
+ - ``VERSION`` contains the PEP-440 compliant version used to describe
+ this package; it is referenced by ``setup.cfg``.
+diff --git a/python/setup.cfg b/python/setup.cfg
+index c2c61c7519..c16bedf398 100644
+--- a/python/setup.cfg
++++ b/python/setup.cfg
+@@ -32,9 +32,7 @@ packages =
+ * = py.typed
+
+ [options.extras_require]
+-# For the devel group, When adding new dependencies or bumping the minimum
+-# version, use e.g. "pipenv install --dev pylint==3.0.0".
+-# Subsequently, edit 'Pipfile' to remove e.g. 'pylint = "==3.0.0'.
++# Remember to update tests/minreqs.txt if changing anything below:
+ devel =
+ avocado-framework >= 90.0
+ flake8 >= 3.6.0
+diff --git a/python/tests/minreqs.txt b/python/tests/minreqs.txt
+new file mode 100644
+index 0000000000..dfb8abb155
+--- /dev/null
++++ b/python/tests/minreqs.txt
+@@ -0,0 +1,45 @@
++# This file lists the ***oldest possible dependencies*** needed to run
++# "make check" successfully under ***Python 3.6***. It is used primarily
++# by GitLab CI to ensure that our stated minimum versions in setup.cfg
++# are truthful and regularly validated.
++#
++# This file should not contain any dependencies that are not expressed
++# by the [devel] section of setup.cfg, except for transitive
++# dependencies which must be enumerated here explicitly to eliminate
++# dependency resolution ambiguity.
++#
++# When adding new dependencies, pin the very oldest non-yanked version
++# on PyPI that allows the test suite to pass.
++
++# Dependencies for the TUI addon (Required for successful linting)
++urwid==2.1.2
++urwid-readline==0.13
++Pygments==2.9.0
++
++# Dependencies for FUSE support for qom-fuse
++fusepy==2.0.4
++
++# Test-runners, utilities, etc.
++avocado-framework==90.0
++
++# Linters
++flake8==3.6.0
++isort==5.1.2
++mypy==0.780
++pylint==2.8.0
++
++# Transitive flake8 dependencies
++mccabe==0.6.0
++pycodestyle==2.4.0
++pyflakes==2.0.0
++
++# Transitive mypy dependencies
++mypy-extensions==0.4.3
++typed-ast==1.4.0
++typing-extensions==3.7.4
++
++# Transitive pylint dependencies
++astroid==2.5.4
++lazy-object-proxy==1.4.0
++toml==0.10.0
++wrapt==1.12.1
+diff --git a/qemu-options.hx b/qemu-options.hx
+index e52289479b..379692da86 100644
+--- a/qemu-options.hx
++++ b/qemu-options.hx
+@@ -1171,10 +1171,10 @@ SRST
+ ERST
+
+ DEF("hda", HAS_ARG, QEMU_OPTION_hda,
+- "-hda/-hdb file use 'file' as IDE hard disk 0/1 image\n", QEMU_ARCH_ALL)
++ "-hda/-hdb file use 'file' as hard disk 0/1 image\n", QEMU_ARCH_ALL)
+ DEF("hdb", HAS_ARG, QEMU_OPTION_hdb, "", QEMU_ARCH_ALL)
+ DEF("hdc", HAS_ARG, QEMU_OPTION_hdc,
+- "-hdc/-hdd file use 'file' as IDE hard disk 2/3 image\n", QEMU_ARCH_ALL)
++ "-hdc/-hdd file use 'file' as hard disk 2/3 image\n", QEMU_ARCH_ALL)
+ DEF("hdd", HAS_ARG, QEMU_OPTION_hdd, "", QEMU_ARCH_ALL)
+ SRST
+ ``-hda file``
+@@ -1184,18 +1184,22 @@ SRST
+ ``-hdc file``
+ \
+ ``-hdd file``
+- Use file as hard disk 0, 1, 2 or 3 image (see the :ref:`disk images`
+- chapter in the System Emulation Users Guide).
++ Use file as hard disk 0, 1, 2 or 3 image on the default bus of the
++ emulated machine (this is for example the IDE bus on most x86 machines,
++ but it can also be SCSI, virtio or something else on other target
++ architectures). See also the :ref:`disk images` chapter in the System
++ Emulation Users Guide.
+ ERST
+
+ DEF("cdrom", HAS_ARG, QEMU_OPTION_cdrom,
+- "-cdrom file use 'file' as IDE cdrom image (cdrom is ide1 master)\n",
++ "-cdrom file use 'file' as CD-ROM image\n",
+ QEMU_ARCH_ALL)
+ SRST
+ ``-cdrom file``
+- Use file as CD-ROM image (you cannot use ``-hdc`` and ``-cdrom`` at
+- the same time). You can use the host CD-ROM by using ``/dev/cdrom``
+- as filename.
++ Use file as CD-ROM image on the default bus of the emulated machine
++ (which is IDE1 master on x86, so you cannot use ``-hdc`` and ``-cdrom``
++ at the same time there). On systems that support it, you can use the
++ host CD-ROM by using ``/dev/cdrom`` as filename.
+ ERST
+
+ DEF("blockdev", HAS_ARG, QEMU_OPTION_blockdev,
+diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
+index 6ecabfb2b5..fbb71c70f8 100755
+--- a/scripts/checkpatch.pl
++++ b/scripts/checkpatch.pl
+@@ -2865,6 +2865,14 @@ sub process {
+ if ($line =~ /\bsignal\s*\(/ && !($line =~ /SIG_(?:IGN|DFL)/)) {
+ ERROR("use sigaction to establish signal handlers; signal is not portable\n" . $herecurr);
+ }
++# recommend qemu_bh_new_guarded instead of qemu_bh_new
++ if ($realfile =~ /.*\/hw\/.*/ && $line =~ /\bqemu_bh_new\s*\(/) {
++ ERROR("use qemu_bh_new_guarded() instead of qemu_bh_new() to avoid reentrancy problems\n" . $herecurr);
++ }
++# recommend aio_bh_new_guarded instead of aio_bh_new
++ if ($realfile =~ /.*\/hw\/.*/ && $line =~ /\baio_bh_new\s*\(/) {
++ ERROR("use aio_bh_new_guarded() instead of aio_bh_new() to avoid reentrancy problems\n" . $herecurr);
++ }
+ # check for module_init(), use category-specific init macros explicitly please
+ if ($line =~ /^module_init\s*\(/) {
+ ERROR("please use block_init(), type_init() etc. instead of module_init()\n" . $herecurr);
+diff --git a/softmmu/memory.c b/softmmu/memory.c
+index bc0be3f62c..61569f8306 100644
+--- a/softmmu/memory.c
++++ b/softmmu/memory.c
+@@ -542,6 +542,18 @@ static MemTxResult access_with_adjusted_size(hwaddr addr,
+ access_size_max = 4;
+ }
+
++ /* Do not allow more than one simultaneous access to a device's IO Regions */
++ if (mr->dev && !mr->disable_reentrancy_guard &&
++ !mr->ram_device && !mr->ram && !mr->rom_device && !mr->readonly) {
++ if (mr->dev->mem_reentrancy_guard.engaged_in_io) {
++ warn_report_once("Blocked re-entrant IO on MemoryRegion: "
++ "%s at addr: 0x%" HWADDR_PRIX,
++ memory_region_name(mr), addr);
++ return MEMTX_ACCESS_ERROR;
++ }
++ mr->dev->mem_reentrancy_guard.engaged_in_io = true;
++ }
++
+ /* FIXME: support unaligned access? */
+ access_size = MAX(MIN(size, access_size_max), access_size_min);
+ access_mask = MAKE_64BIT_MASK(0, access_size * 8);
+@@ -556,6 +568,9 @@ static MemTxResult access_with_adjusted_size(hwaddr addr,
+ access_mask, attrs);
+ }
+ }
++ if (mr->dev) {
++ mr->dev->mem_reentrancy_guard.engaged_in_io = false;
++ }
+ return r;
+ }
+
+@@ -1170,6 +1185,7 @@ static void memory_region_do_init(MemoryRegion *mr,
+ }
+ mr->name = g_strdup(name);
+ mr->owner = owner;
++ mr->dev = (DeviceState *) object_dynamic_cast(mr->owner, TYPE_DEVICE);
+ mr->ram_block = NULL;
+
+ if (name) {
+diff --git a/target/arm/kvm.c b/target/arm/kvm.c
+index 84da49332c..e219f78535 100644
+--- a/target/arm/kvm.c
++++ b/target/arm/kvm.c
+@@ -247,6 +247,13 @@ int kvm_arm_get_max_vm_ipa_size(MachineState *ms, bool *fixed_ipa)
+ return ret > 0 ? ret : 40;
+ }
+
++int kvm_arch_get_default_type(MachineState *ms)
++{
++ bool fixed_ipa;
++ int size = kvm_arm_get_max_vm_ipa_size(ms, &fixed_ipa);
++ return fixed_ipa ? 0 : size;
++}
++
+ int kvm_arch_init(MachineState *ms, KVMState *s)
+ {
+ int ret = 0;
+diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
+index 810db33ccb..ed85bcfb5c 100644
+--- a/target/arm/kvm64.c
++++ b/target/arm/kvm64.c
+@@ -950,6 +950,7 @@ typedef struct CPRegStateLevel {
+ */
+ static const CPRegStateLevel non_runtime_cpregs[] = {
+ { KVM_REG_ARM_TIMER_CNT, KVM_PUT_FULL_STATE },
++ { KVM_REG_ARM_PTIMER_CNT, KVM_PUT_FULL_STATE },
+ };
+
+ int kvm_arm_cpreg_level(uint64_t regidx)
+diff --git a/target/arm/sme_helper.c b/target/arm/sme_helper.c
+index f891306bb9..73dd838330 100644
+--- a/target/arm/sme_helper.c
++++ b/target/arm/sme_helper.c
+@@ -412,7 +412,7 @@ static inline void HNAME##_host(void *za, intptr_t off, void *host) \
+ { \
+ uint64_t *ptr = za + off; \
+ HOST(host, ptr[BE]); \
+- HOST(host + 1, ptr[!BE]); \
++ HOST(host + 8, ptr[!BE]); \
+ } \
+ static inline void VNAME##_v_host(void *za, intptr_t off, void *host) \
+ { \
+diff --git a/target/arm/translate.c b/target/arm/translate.c
+index 9cf4a6819e..10dfa11a2b 100644
+--- a/target/arm/translate.c
++++ b/target/arm/translate.c
+@@ -3138,7 +3138,7 @@ void gen_gvec_ssra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
+ .vece = MO_32 },
+ { .fni8 = gen_ssra64_i64,
+ .fniv = gen_ssra_vec,
+- .fno = gen_helper_gvec_ssra_b,
++ .fno = gen_helper_gvec_ssra_d,
+ .prefer_i64 = TCG_TARGET_REG_BITS == 64,
+ .opt_opc = vecop_list,
+ .load_dest = true,
+diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
+index a213209379..002b699030 100644
+--- a/target/i386/kvm/kvm.c
++++ b/target/i386/kvm/kvm.c
+@@ -2455,6 +2455,11 @@ static void register_smram_listener(Notifier *n, void *unused)
+ &smram_address_space, 1, "kvm-smram");
+ }
+
++int kvm_arch_get_default_type(MachineState *ms)
++{
++ return 0;
++}
++
+ int kvm_arch_init(MachineState *ms, KVMState *s)
+ {
+ uint64_t identity_base = 0xfffbc000;
+diff --git a/target/mips/kvm.c b/target/mips/kvm.c
+index bcb8e06b2c..27cf4e8c1b 100644
+--- a/target/mips/kvm.c
++++ b/target/mips/kvm.c
+@@ -1266,7 +1266,7 @@ int kvm_arch_msi_data_to_gsi(uint32_t data)
+ abort();
+ }
+
+-int mips_kvm_type(MachineState *machine, const char *vm_type)
++int kvm_arch_get_default_type(MachineState *machine)
+ {
+ #if defined(KVM_CAP_MIPS_VZ) || defined(KVM_CAP_MIPS_TE)
+ int r;
+diff --git a/target/mips/kvm_mips.h b/target/mips/kvm_mips.h
+index 171d53dbe1..c711269d0a 100644
+--- a/target/mips/kvm_mips.h
++++ b/target/mips/kvm_mips.h
+@@ -25,13 +25,4 @@ void kvm_mips_reset_vcpu(MIPSCPU *cpu);
+ int kvm_mips_set_interrupt(MIPSCPU *cpu, int irq, int level);
+ int kvm_mips_set_ipi_interrupt(MIPSCPU *cpu, int irq, int level);
+
+-#ifdef CONFIG_KVM
+-int mips_kvm_type(MachineState *machine, const char *vm_type);
+-#else
+-static inline int mips_kvm_type(MachineState *machine, const char *vm_type)
+-{
+- return 0;
+-}
+-#endif
+-
+ #endif /* KVM_MIPS_H */
+diff --git a/target/ppc/cpu.c b/target/ppc/cpu.c
+index 1a97b41c6b..6e597680fb 100644
+--- a/target/ppc/cpu.c
++++ b/target/ppc/cpu.c
+@@ -59,6 +59,7 @@ void ppc_store_vscr(CPUPPCState *env, uint32_t vscr)
+ env->vscr_sat.u64[0] = vscr & (1u << VSCR_SAT);
+ env->vscr_sat.u64[1] = 0;
+ set_flush_to_zero((vscr >> VSCR_NJ) & 1, &env->vec_status);
++ set_flush_inputs_to_zero((vscr >> VSCR_NJ) & 1, &env->vec_status);
+ }
+
+ uint32_t ppc_get_vscr(CPUPPCState *env)
+diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c
+index 7c25348b7b..4bcda6e2dc 100644
+--- a/target/ppc/kvm.c
++++ b/target/ppc/kvm.c
+@@ -108,6 +108,11 @@ static int kvm_ppc_register_host_cpu_type(void);
+ static void kvmppc_get_cpu_characteristics(KVMState *s);
+ static int kvmppc_get_dec_bits(void);
+
++int kvm_arch_get_default_type(MachineState *ms)
++{
++ return 0;
++}
++
+ int kvm_arch_init(MachineState *ms, KVMState *s)
+ {
+ cap_interrupt_unset = kvm_check_extension(s, KVM_CAP_PPC_UNSET_IRQ);
+diff --git a/target/riscv/kvm.c b/target/riscv/kvm.c
+index 30f21453d6..d28d5241f9 100644
+--- a/target/riscv/kvm.c
++++ b/target/riscv/kvm.c
+@@ -426,6 +426,11 @@ int kvm_arch_add_msi_route_post(struct kvm_irq_routing_entry *route,
+ return 0;
+ }
+
++int kvm_arch_get_default_type(MachineState *ms)
++{
++ return 0;
++}
++
+ int kvm_arch_init(MachineState *ms, KVMState *s)
+ {
+ return 0;
+diff --git a/target/riscv/pmp.c b/target/riscv/pmp.c
+index 2b43e399b8..575cea1b28 100644
+--- a/target/riscv/pmp.c
++++ b/target/riscv/pmp.c
+@@ -45,6 +45,10 @@ static inline uint8_t pmp_get_a_field(uint8_t cfg)
+ */
+ static inline int pmp_is_locked(CPURISCVState *env, uint32_t pmp_index)
+ {
++ /* mseccfg.RLB is set */
++ if (MSECCFG_RLB_ISSET(env)) {
++ return 0;
++ }
+
+ if (env->pmp_state.pmp[pmp_index].cfg_reg & PMP_LOCK) {
+ return 1;
+diff --git a/target/s390x/kvm/kvm.c b/target/s390x/kvm/kvm.c
+index 3ac7ec9acf..8ffe140513 100644
+--- a/target/s390x/kvm/kvm.c
++++ b/target/s390x/kvm/kvm.c
+@@ -340,6 +340,11 @@ static void ccw_machine_class_foreach(ObjectClass *oc, void *opaque)
+ mc->default_cpu_type = S390_CPU_TYPE_NAME("host");
+ }
+
++int kvm_arch_get_default_type(MachineState *ms)
++{
++ return 0;
++}
++
+ int kvm_arch_init(MachineState *ms, KVMState *s)
+ {
+ object_class_foreach(ccw_machine_class_foreach, TYPE_S390_CCW_MACHINE,
+diff --git a/target/s390x/tcg/translate_vx.c.inc b/target/s390x/tcg/translate_vx.c.inc
+index 79e2bbe0a7..25e974c99f 100644
+--- a/target/s390x/tcg/translate_vx.c.inc
++++ b/target/s390x/tcg/translate_vx.c.inc
+@@ -57,7 +57,7 @@
+ #define FPF_LONG 3
+ #define FPF_EXT 4
+
+-static inline bool valid_vec_element(uint8_t enr, MemOp es)
++static inline bool valid_vec_element(uint16_t enr, MemOp es)
+ {
+ return !(enr & ~(NUM_VEC_ELEMENTS(es) - 1));
+ }
+@@ -1014,7 +1014,7 @@ static DisasJumpType op_vpdi(DisasContext *s, DisasOps *o)
+
+ static DisasJumpType op_vrep(DisasContext *s, DisasOps *o)
+ {
+- const uint8_t enr = get_field(s, i2);
++ const uint16_t enr = get_field(s, i2);
+ const uint8_t es = get_field(s, m4);
+
+ if (es > ES_64 || !valid_vec_element(enr, es)) {
+@@ -3192,7 +3192,7 @@ static DisasJumpType op_vfmax(DisasContext *s, DisasOps *o)
+ const uint8_t m5 = get_field(s, m5);
+ gen_helper_gvec_3_ptr *fn;
+
+- if (m6 == 5 || m6 == 6 || m6 == 7 || m6 >= 13) {
++ if (m6 == 5 || m6 == 6 || m6 == 7 || m6 >= 13 || (m5 & 7)) {
+ gen_program_exception(s, PGM_SPECIFICATION);
+ return DISAS_NORETURN;
+ }
+diff --git a/target/s390x/tcg/vec_helper.c b/target/s390x/tcg/vec_helper.c
+index 48d86722b2..dafc4c3582 100644
+--- a/target/s390x/tcg/vec_helper.c
++++ b/target/s390x/tcg/vec_helper.c
+@@ -193,7 +193,7 @@ void HELPER(vstl)(CPUS390XState *env, const void *v1, uint64_t addr,
+ uint64_t bytes)
+ {
+ /* Probe write access before actually modifying memory */
+- probe_write_access(env, addr, bytes, GETPC());
++ probe_write_access(env, addr, MIN(bytes, 16), GETPC());
+
+ if (likely(bytes >= 16)) {
+ cpu_stq_data_ra(env, addr, s390_vec_read_element64(v1, 0), GETPC());
+diff --git a/target/s390x/tcg/vec_string_helper.c b/target/s390x/tcg/vec_string_helper.c
+index 9b85becdfb..a19f429768 100644
+--- a/target/s390x/tcg/vec_string_helper.c
++++ b/target/s390x/tcg/vec_string_helper.c
+@@ -474,9 +474,9 @@ DEF_VSTRC_CC_RT_HELPER(32)
+ static int vstrs(S390Vector *v1, const S390Vector *v2, const S390Vector *v3,
+ const S390Vector *v4, uint8_t es, bool zs)
+ {
+- int substr_elen, substr_0, str_elen, i, j, k, cc;
++ int substr_elen, i, j, k, cc;
+ int nelem = 16 >> es;
+- bool eos = false;
++ int str_leftmost_0;
+
+ substr_elen = s390_vec_read_element8(v4, 7) >> es;
+
+@@ -498,47 +498,20 @@ static int vstrs(S390Vector *v1, const S390Vector *v2, const S390Vector *v3,
+ }
+
+ /* If ZS, look for eos in the searched string. */
++ str_leftmost_0 = nelem;
+ if (zs) {
+ for (k = 0; k < nelem; k++) {
+ if (s390_vec_read_element(v2, k, es) == 0) {
+- eos = true;
++ str_leftmost_0 = k;
+ break;
+ }
+ }
+- str_elen = k;
+- } else {
+- str_elen = nelem;
+ }
+
+- substr_0 = s390_vec_read_element(v3, 0, es);
+-
+- for (k = 0; ; k++) {
+- for (; k < str_elen; k++) {
+- if (s390_vec_read_element(v2, k, es) == substr_0) {
+- break;
+- }
+- }
+-
+- /* If we reached the end of the string, no match. */
+- if (k == str_elen) {
+- cc = eos; /* no match (with or without zero char) */
+- goto done;
+- }
+-
+- /* If the substring is only one char, match. */
+- if (substr_elen == 1) {
+- cc = 2; /* full match */
+- goto done;
+- }
+-
+- /* If the match begins at the last char, we have a partial match. */
+- if (k == str_elen - 1) {
+- cc = 3; /* partial match */
+- goto done;
+- }
+-
++ cc = str_leftmost_0 == nelem ? 0 : 1; /* No match. */
++ for (k = 0; k < nelem; k++) {
+ i = MIN(nelem, k + substr_elen);
+- for (j = k + 1; j < i; j++) {
++ for (j = k; j < i; j++) {
+ uint32_t e2 = s390_vec_read_element(v2, j, es);
+ uint32_t e3 = s390_vec_read_element(v3, j - k, es);
+ if (e2 != e3) {
+@@ -546,9 +519,16 @@ static int vstrs(S390Vector *v1, const S390Vector *v2, const S390Vector *v3,
+ }
+ }
+ if (j == i) {
+- /* Matched up until "end". */
+- cc = i - k == substr_elen ? 2 : 3; /* full or partial match */
+- goto done;
++ /* All elements matched. */
++ if (k > str_leftmost_0) {
++ cc = 1; /* Ignored match. */
++ k = nelem;
++ } else if (i - k == substr_elen) {
++ cc = 2; /* Full match. */
++ } else {
++ cc = 3; /* Partial match. */
++ }
++ break;
+ }
+ }
+
+diff --git a/tests/docker/dockerfiles/python.docker b/tests/docker/dockerfiles/python.docker
+index 56d88417df..175c10a34e 100644
+--- a/tests/docker/dockerfiles/python.docker
++++ b/tests/docker/dockerfiles/python.docker
+@@ -7,7 +7,6 @@ MAINTAINER John Snow <jsnow@redhat.com>
+ ENV PACKAGES \
+ gcc \
+ make \
+- pipenv \
+ python3 \
+ python3-pip \
+ python3-tox \
+diff --git a/tests/qemu-iotests/181 b/tests/qemu-iotests/181
+index cb96d09ae5..dc90a10757 100755
+--- a/tests/qemu-iotests/181
++++ b/tests/qemu-iotests/181
+@@ -109,7 +109,7 @@ if [ ${QEMU_STATUS[$dest]} -lt 0 ]; then
+ _notrun 'Postcopy is not supported'
+ fi
+
+-_send_qemu_cmd $src 'migrate_set_parameter max_bandwidth 4k' "(qemu)"
++_send_qemu_cmd $src 'migrate_set_parameter max-bandwidth 4k' "(qemu)"
+ _send_qemu_cmd $src 'migrate_set_capability postcopy-ram on' "(qemu)"
+ _send_qemu_cmd $src "migrate -d unix:${MIG_SOCKET}" "(qemu)"
+ _send_qemu_cmd $src 'migrate_start_postcopy' "(qemu)"
+diff --git a/tests/qtest/libqos/ahci.c b/tests/qtest/libqos/ahci.c
+index f53f12aa99..a2c94c6e06 100644
+--- a/tests/qtest/libqos/ahci.c
++++ b/tests/qtest/libqos/ahci.c
+@@ -404,57 +404,110 @@ void ahci_port_clear(AHCIQState *ahci, uint8_t port)
+ /**
+ * Check a port for errors.
+ */
+-void ahci_port_check_error(AHCIQState *ahci, uint8_t port,
+- uint32_t imask, uint8_t emask)
++void ahci_port_check_error(AHCIQState *ahci, AHCICommand *cmd)
+ {
++ uint8_t port = cmd->port;
+ uint32_t reg;
+
+- /* The upper 9 bits of the IS register all indicate errors. */
+- reg = ahci_px_rreg(ahci, port, AHCI_PX_IS);
+- reg &= ~imask;
+- reg >>= 23;
+- g_assert_cmphex(reg, ==, 0);
++ /* If expecting TF error, ensure that TFES is set. */
++ if (cmd->errors) {
++ reg = ahci_px_rreg(ahci, port, AHCI_PX_IS);
++ ASSERT_BIT_SET(reg, AHCI_PX_IS_TFES);
++ } else {
++ /* The upper 9 bits of the IS register all indicate errors. */
++ reg = ahci_px_rreg(ahci, port, AHCI_PX_IS);
++ reg &= ~cmd->interrupts;
++ reg >>= 23;
++ g_assert_cmphex(reg, ==, 0);
++ }
+
+- /* The Sata Error Register should be empty. */
++ /* The Sata Error Register should be empty, even when expecting TF error. */
+ reg = ahci_px_rreg(ahci, port, AHCI_PX_SERR);
+ g_assert_cmphex(reg, ==, 0);
+
++ /* If expecting TF error, and TFES was set, perform error recovery
++ * (see AHCI 1.3 section 6.2.2.1) such that we can send new commands. */
++ if (cmd->errors) {
++ /* This will clear PxCI. */
++ ahci_px_clr(ahci, port, AHCI_PX_CMD, AHCI_PX_CMD_ST);
++
++ /* The port has 500ms to disengage. */
++ usleep(500000);
++ reg = ahci_px_rreg(ahci, port, AHCI_PX_CMD);
++ ASSERT_BIT_CLEAR(reg, AHCI_PX_CMD_CR);
++
++ /* Clear PxIS. */
++ reg = ahci_px_rreg(ahci, port, AHCI_PX_IS);
++ ahci_px_wreg(ahci, port, AHCI_PX_IS, reg);
++
++ /* Check if we need to perform a COMRESET.
++ * Not implemented right now, as there is no reason why our QEMU model
++ * should need a COMRESET when expecting TF error. */
++ reg = ahci_px_rreg(ahci, port, AHCI_PX_TFD);
++ ASSERT_BIT_CLEAR(reg, AHCI_PX_TFD_STS_BSY | AHCI_PX_TFD_STS_DRQ);
++
++ /* Enable issuing new commands. */
++ ahci_px_set(ahci, port, AHCI_PX_CMD, AHCI_PX_CMD_ST);
++ }
++
+ /* The TFD also has two error sections. */
+ reg = ahci_px_rreg(ahci, port, AHCI_PX_TFD);
+- if (!emask) {
++ if (!cmd->errors) {
+ ASSERT_BIT_CLEAR(reg, AHCI_PX_TFD_STS_ERR);
+ } else {
+ ASSERT_BIT_SET(reg, AHCI_PX_TFD_STS_ERR);
+ }
+- ASSERT_BIT_CLEAR(reg, AHCI_PX_TFD_ERR & (~emask << 8));
+- ASSERT_BIT_SET(reg, AHCI_PX_TFD_ERR & (emask << 8));
++ ASSERT_BIT_CLEAR(reg, AHCI_PX_TFD_ERR & (~cmd->errors << 8));
++ ASSERT_BIT_SET(reg, AHCI_PX_TFD_ERR & (cmd->errors << 8));
+ }
+
+-void ahci_port_check_interrupts(AHCIQState *ahci, uint8_t port,
+- uint32_t intr_mask)
++void ahci_port_check_interrupts(AHCIQState *ahci, AHCICommand *cmd)
+ {
++ uint8_t port = cmd->port;
+ uint32_t reg;
+
++ /* If we expect errors, error handling in ahci_port_check_error() will
++ * already have cleared PxIS, so in that case this function cannot verify
++ * and clear expected interrupts. */
++ if (cmd->errors) {
++ return;
++ }
++
+ /* Check for expected interrupts */
+ reg = ahci_px_rreg(ahci, port, AHCI_PX_IS);
+- ASSERT_BIT_SET(reg, intr_mask);
++ ASSERT_BIT_SET(reg, cmd->interrupts);
+
+ /* Clear expected interrupts and assert all interrupts now cleared. */
+- ahci_px_wreg(ahci, port, AHCI_PX_IS, intr_mask);
++ ahci_px_wreg(ahci, port, AHCI_PX_IS, cmd->interrupts);
+ g_assert_cmphex(ahci_px_rreg(ahci, port, AHCI_PX_IS), ==, 0);
+ }
+
+-void ahci_port_check_nonbusy(AHCIQState *ahci, uint8_t port, uint8_t slot)
++void ahci_port_check_nonbusy(AHCIQState *ahci, AHCICommand *cmd)
+ {
++ uint8_t slot = cmd->slot;
++ uint8_t port = cmd->port;
+ uint32_t reg;
+
+- /* Assert that the command slot is no longer busy (NCQ) */
++ /* For NCQ command with error PxSACT bit should still be set.
++ * For NCQ command without error, PxSACT bit should be cleared.
++ * For non-NCQ command, PxSACT bit should always be cleared. */
+ reg = ahci_px_rreg(ahci, port, AHCI_PX_SACT);
+- ASSERT_BIT_CLEAR(reg, (1 << slot));
++ if (cmd->props->ncq && cmd->errors) {
++ ASSERT_BIT_SET(reg, (1 << slot));
++ } else {
++ ASSERT_BIT_CLEAR(reg, (1 << slot));
++ }
+
+- /* Non-NCQ */
++ /* For non-NCQ command with error, PxCI bit should still be set.
++ * For non-NCQ command without error, PxCI bit should be cleared.
++ * For NCQ command without error, PxCI bit should be cleared.
++ * For NCQ command with error, PxCI bit may or may not be cleared. */
+ reg = ahci_px_rreg(ahci, port, AHCI_PX_CI);
+- ASSERT_BIT_CLEAR(reg, (1 << slot));
++ if (!cmd->props->ncq && cmd->errors) {
++ ASSERT_BIT_SET(reg, (1 << slot));
++ } else if (!cmd->errors) {
++ ASSERT_BIT_CLEAR(reg, (1 << slot));
++ }
+
+ /* And assert that we are generally not busy. */
+ reg = ahci_px_rreg(ahci, port, AHCI_PX_TFD);
+@@ -1207,9 +1260,10 @@ void ahci_command_wait(AHCIQState *ahci, AHCICommand *cmd)
+
+ #define RSET(REG, MASK) (BITSET(ahci_px_rreg(ahci, cmd->port, (REG)), (MASK)))
+
+- while (RSET(AHCI_PX_TFD, AHCI_PX_TFD_STS_BSY) ||
+- RSET(AHCI_PX_CI, 1 << cmd->slot) ||
+- (cmd->props->ncq && RSET(AHCI_PX_SACT, 1 << cmd->slot))) {
++ while (!RSET(AHCI_PX_TFD, AHCI_PX_TFD_STS_ERR) &&
++ (RSET(AHCI_PX_TFD, AHCI_PX_TFD_STS_BSY) ||
++ RSET(AHCI_PX_CI, 1 << cmd->slot) ||
++ (cmd->props->ncq && RSET(AHCI_PX_SACT, 1 << cmd->slot)))) {
+ usleep(50);
+ }
+
+@@ -1226,9 +1280,9 @@ void ahci_command_verify(AHCIQState *ahci, AHCICommand *cmd)
+ uint8_t slot = cmd->slot;
+ uint8_t port = cmd->port;
+
+- ahci_port_check_error(ahci, port, cmd->interrupts, cmd->errors);
+- ahci_port_check_interrupts(ahci, port, cmd->interrupts);
+- ahci_port_check_nonbusy(ahci, port, slot);
++ ahci_port_check_nonbusy(ahci, cmd);
++ ahci_port_check_error(ahci, cmd);
++ ahci_port_check_interrupts(ahci, cmd);
+ ahci_port_check_cmd_sanity(ahci, cmd);
+ if (cmd->interrupts & AHCI_PX_IS_DHRS) {
+ ahci_port_check_d2h_sanity(ahci, port, slot);
+diff --git a/tests/qtest/libqos/ahci.h b/tests/qtest/libqos/ahci.h
+index 88835b6228..48017864bf 100644
+--- a/tests/qtest/libqos/ahci.h
++++ b/tests/qtest/libqos/ahci.h
+@@ -590,11 +590,9 @@ void ahci_set_command_header(AHCIQState *ahci, uint8_t port,
+ void ahci_destroy_command(AHCIQState *ahci, uint8_t port, uint8_t slot);
+
+ /* AHCI sanity check routines */
+-void ahci_port_check_error(AHCIQState *ahci, uint8_t port,
+- uint32_t imask, uint8_t emask);
+-void ahci_port_check_interrupts(AHCIQState *ahci, uint8_t port,
+- uint32_t intr_mask);
+-void ahci_port_check_nonbusy(AHCIQState *ahci, uint8_t port, uint8_t slot);
++void ahci_port_check_error(AHCIQState *ahci, AHCICommand *cmd);
++void ahci_port_check_interrupts(AHCIQState *ahci, AHCICommand *cmd);
++void ahci_port_check_nonbusy(AHCIQState *ahci, AHCICommand *cmd);
+ void ahci_port_check_d2h_sanity(AHCIQState *ahci, uint8_t port, uint8_t slot);
+ void ahci_port_check_pio_sanity(AHCIQState *ahci, AHCICommand *cmd);
+ void ahci_port_check_cmd_sanity(AHCIQState *ahci, AHCICommand *cmd);
+diff --git a/tests/qtest/test-hmp.c b/tests/qtest/test-hmp.c
+index f8b22abe4c..c38d0b9db9 100644
+--- a/tests/qtest/test-hmp.c
++++ b/tests/qtest/test-hmp.c
+@@ -45,9 +45,9 @@ static const char *hmp_cmds[] = {
+ "log all",
+ "log none",
+ "memsave 0 4096 \"/dev/null\"",
+- "migrate_set_parameter xbzrle_cache_size 1",
+- "migrate_set_parameter downtime_limit 1",
+- "migrate_set_parameter max_bandwidth 1",
++ "migrate_set_parameter xbzrle-cache-size 1",
++ "migrate_set_parameter downtime-limit 1",
++ "migrate_set_parameter max-bandwidth 1",
+ "netdev_add user,id=net1",
+ "set_link net1 off",
+ "set_link net1 on",
+diff --git a/tests/unit/ptimer-test-stubs.c b/tests/unit/ptimer-test-stubs.c
+index f5e75a96b6..24d5413f9d 100644
+--- a/tests/unit/ptimer-test-stubs.c
++++ b/tests/unit/ptimer-test-stubs.c
+@@ -107,7 +107,8 @@ int64_t qemu_clock_deadline_ns_all(QEMUClockType type, int attr_mask)
+ return deadline;
+ }
+
+-QEMUBH *qemu_bh_new_full(QEMUBHFunc *cb, void *opaque, const char *name)
++QEMUBH *qemu_bh_new_full(QEMUBHFunc *cb, void *opaque, const char *name,
++ MemReentrancyGuard *reentrancy_guard)
+ {
+ QEMUBH *bh = g_new(QEMUBH, 1);
+
+diff --git a/ui/console.c b/ui/console.c
+index 646202214a..52414d6aa3 100644
+--- a/ui/console.c
++++ b/ui/console.c
+@@ -1697,6 +1697,9 @@ bool dpy_ui_info_supported(QemuConsole *con)
+ if (con == NULL) {
+ con = active_console;
+ }
++ if (con == NULL) {
++ return false;
++ }
+
+ return con->hw_ops->ui_info != NULL;
+ }
+diff --git a/util/async.c b/util/async.c
+index f449c3444e..a1f07fc5a7 100644
+--- a/util/async.c
++++ b/util/async.c
+@@ -64,6 +64,7 @@ struct QEMUBH {
+ void *opaque;
+ QSLIST_ENTRY(QEMUBH) next;
+ unsigned flags;
++ MemReentrancyGuard *reentrancy_guard;
+ };
+
+ /* Called concurrently from any thread */
+@@ -132,7 +133,7 @@ void aio_bh_schedule_oneshot_full(AioContext *ctx, QEMUBHFunc *cb,
+ }
+
+ QEMUBH *aio_bh_new_full(AioContext *ctx, QEMUBHFunc *cb, void *opaque,
+- const char *name)
++ const char *name, MemReentrancyGuard *reentrancy_guard)
+ {
+ QEMUBH *bh;
+ bh = g_new(QEMUBH, 1);
+@@ -141,13 +142,30 @@ QEMUBH *aio_bh_new_full(AioContext *ctx, QEMUBHFunc *cb, void *opaque,
+ .cb = cb,
+ .opaque = opaque,
+ .name = name,
++ .reentrancy_guard = reentrancy_guard,
+ };
+ return bh;
+ }
+
+ void aio_bh_call(QEMUBH *bh)
+ {
++ bool last_engaged_in_io = false;
++
++ /* Make a copy of the guard-pointer as cb may free the bh */
++ MemReentrancyGuard *reentrancy_guard = bh->reentrancy_guard;
++ if (reentrancy_guard) {
++ last_engaged_in_io = reentrancy_guard->engaged_in_io;
++ if (reentrancy_guard->engaged_in_io) {
++ trace_reentrant_aio(bh->ctx, bh->name);
++ }
++ reentrancy_guard->engaged_in_io = true;
++ }
++
+ bh->cb(bh->opaque);
++
++ if (reentrancy_guard) {
++ reentrancy_guard->engaged_in_io = last_engaged_in_io;
++ }
+ }
+
+ /* Multiple occurrences of aio_bh_poll cannot be called concurrently. */
+diff --git a/util/main-loop.c b/util/main-loop.c
+index 10fa74c6e3..4d49e0bcbf 100644
+--- a/util/main-loop.c
++++ b/util/main-loop.c
+@@ -619,9 +619,11 @@ void main_loop_wait(int nonblocking)
+
+ /* Functions to operate on the main QEMU AioContext. */
+
+-QEMUBH *qemu_bh_new_full(QEMUBHFunc *cb, void *opaque, const char *name)
++QEMUBH *qemu_bh_new_full(QEMUBHFunc *cb, void *opaque, const char *name,
++ MemReentrancyGuard *reentrancy_guard)
+ {
+- return aio_bh_new_full(qemu_aio_context, cb, opaque, name);
++ return aio_bh_new_full(qemu_aio_context, cb, opaque, name,
++ reentrancy_guard);
+ }
+
+ /*
+diff --git a/util/trace-events b/util/trace-events
+index c8f53d7d9f..dc3b1eb3bf 100644
+--- a/util/trace-events
++++ b/util/trace-events
+@@ -11,6 +11,7 @@ poll_remove(void *ctx, void *node, int fd) "ctx %p node %p fd %d"
+ # async.c
+ aio_co_schedule(void *ctx, void *co) "ctx %p co %p"
+ aio_co_schedule_bh_cb(void *ctx, void *co) "ctx %p co %p"
++reentrant_aio(void *ctx, const char *name) "ctx %p name %s"
+
+ # thread-pool.c
+ thread_pool_submit(void *pool, void *req, void *opaque) "pool %p req %p opaque %p"
diff --git a/debian/patches/v7.2.7.diff b/debian/patches/v7.2.7.diff
new file mode 100644
index 00000000..ebade3bf
--- /dev/null
+++ b/debian/patches/v7.2.7.diff
@@ -0,0 +1,2307 @@
+Subject: v7.2.7
+Date: Tue Nov 21 12:02:48 2023 +0300
+From: Michael Tokarev <mjt@tls.msk.ru>
+Forwarded: not-needed
+
+This is a difference between upstream qemu v7.2.6
+and upstream qemu v7.2.7.
+--
+ VERSION | 2 +-
+ accel/tcg/tcg-accel-ops-mttcg.c | 9 +---
+ block/nvme.c | 7 +--
+ chardev/char-pty.c | 22 +++++++--
+ disas/riscv.c | 4 +-
+ hw/audio/es1370.c | 2 +-
+ hw/cxl/cxl-host.c | 12 ++---
+ hw/display/ati.c | 8 ++++
+ hw/display/ati_2d.c | 75 +++++++++++++++++++++---------
+ hw/display/ati_int.h | 1 +
+ hw/display/ramfb.c | 1 +
+ hw/i386/amd_iommu.c | 9 +---
+ hw/i386/amd_iommu.h | 2 -
+ hw/ide/core.c | 14 +++---
+ hw/input/lasips2.c | 10 ++++
+ hw/misc/led.c | 2 +-
+ hw/ppc/ppc.c | 97 +++++++++++++++++++++++---------------
+ hw/rdma/vmw/pvrdma_main.c | 16 ++++++-
+ hw/scsi/esp.c | 5 +-
+ hw/scsi/scsi-disk.c | 9 +++-
+ hw/sd/sdhci.c | 15 ++++--
+ include/qemu/host-utils.h | 21 ++++++++-
+ linux-user/hppa/signal.c | 8 ++--
+ linux-user/mips/cpu_loop.c | 4 +-
+ linux-user/sh4/signal.c | 8 ++++
+ linux-user/syscall.c | 43 -----------------
+ meson.build | 2 -
+ migration/migration.c | 9 +++-
+ pc-bios/optionrom/Makefile | 2 +-
+ qemu-img.c | 13 +++++-
+ scripts/analyze-migration.py | 6 +--
+ scripts/tracetool/__init__.py | 2 +-
+ target/arm/helper.c | 9 ++++
+ target/arm/internals.h | 1 -
+ target/arm/ptw.c | 89 ++++++++++++++++++++++++-----------
+ target/i386/tcg/decode-new.c.inc | 98 ++++++++++++++++++++++-----------------
+ target/i386/tcg/decode-new.h | 2 +-
+ target/i386/tcg/emit.c.inc | 30 ++++++++++--
+ target/mips/tcg/msa.decode | 4 +-
+ target/mips/tcg/tx79.decode | 2 +-
+ target/s390x/tcg/insn-data.h.inc | 2 +-
+ target/s390x/tcg/translate.c | 19 +++++++-
+ target/tricore/cpu.c | 6 +--
+ target/tricore/cpu.h | 2 +-
+ target/tricore/op_helper.c | 4 +-
+ tests/migration/s390x/Makefile | 4 +-
+ tests/qemu-iotests/024 | 57 +++++++++++++++++++++++
+ tests/qemu-iotests/024.out | 30 ++++++++++++
+ tests/qtest/ahci-test.c | 86 +++++++++++++++++++++++++++++++++-
+ tests/tcg/Makefile.target | 2 +-
+ tests/tcg/aarch64/Makefile.target | 2 +-
+ tests/tcg/arm/Makefile.target | 2 +-
+ tests/tcg/cris/Makefile.target | 2 +-
+ tests/tcg/hexagon/Makefile.target | 2 +-
+ tests/tcg/i386/Makefile.target | 2 +-
+ tests/tcg/i386/test-avx.py | 2 +-
+ tests/tcg/minilib/Makefile.target | 2 +-
+ tests/tcg/mips/Makefile.target | 2 +-
+ tests/tcg/mips/hello-mips.c | 4 +-
+ tests/tcg/s390x/Makefile.target | 1 +
+ tests/tcg/s390x/laalg.c | 27 +++++++++++
+ ui/gtk-egl.c | 14 +++---
+ ui/gtk.c | 10 ++++
+ ui/vnc.c | 6 +--
+ 64 files changed, 686 insertions(+), 279 deletions(-)
+
+diff --git a/VERSION b/VERSION
+index ba6a7620d4..4afc54e7b7 100644
+--- a/VERSION
++++ b/VERSION
+@@ -1 +1 @@
+-7.2.6
++7.2.7
+diff --git a/accel/tcg/tcg-accel-ops-mttcg.c b/accel/tcg/tcg-accel-ops-mttcg.c
+index d50239e0e2..3a021624f4 100644
+--- a/accel/tcg/tcg-accel-ops-mttcg.c
++++ b/accel/tcg/tcg-accel-ops-mttcg.c
+@@ -100,14 +100,9 @@ static void *mttcg_cpu_thread_fn(void *arg)
+ break;
+ case EXCP_HALTED:
+ /*
+- * during start-up the vCPU is reset and the thread is
+- * kicked several times. If we don't ensure we go back
+- * to sleep in the halted state we won't cleanly
+- * start-up when the vCPU is enabled.
+- *
+- * cpu->halted should ensure we sleep in wait_io_event
++ * Usually cpu->halted is set, but may have already been
++ * reset by another thread by the time we arrive here.
+ */
+- g_assert(cpu->halted);
+ break;
+ case EXCP_ATOMIC:
+ qemu_mutex_unlock_iothread();
+diff --git a/block/nvme.c b/block/nvme.c
+index 656624c585..14d01a5ea9 100644
+--- a/block/nvme.c
++++ b/block/nvme.c
+@@ -419,9 +419,10 @@ static bool nvme_process_completion(NVMeQueuePair *q)
+ q->cq_phase = !q->cq_phase;
+ }
+ cid = le16_to_cpu(c->cid);
+- if (cid == 0 || cid > NVME_QUEUE_SIZE) {
+- warn_report("NVMe: Unexpected CID in completion queue: %"PRIu32", "
+- "queue size: %u", cid, NVME_QUEUE_SIZE);
++ if (cid == 0 || cid > NVME_NUM_REQS) {
++ warn_report("NVMe: Unexpected CID in completion queue: %" PRIu32
++ ", should be within: 1..%u inclusively", cid,
++ NVME_NUM_REQS);
+ continue;
+ }
+ trace_nvme_complete_command(s, q->index, cid);
+diff --git a/chardev/char-pty.c b/chardev/char-pty.c
+index 53f25c6bbd..e6d0b05211 100644
+--- a/chardev/char-pty.c
++++ b/chardev/char-pty.c
+@@ -108,11 +108,27 @@ static void pty_chr_update_read_handler(Chardev *chr)
+ static int char_pty_chr_write(Chardev *chr, const uint8_t *buf, int len)
+ {
+ PtyChardev *s = PTY_CHARDEV(chr);
++ GPollFD pfd;
++ int rc;
+
+- if (!s->connected) {
+- return len;
++ if (s->connected) {
++ return io_channel_send(s->ioc, buf, len);
++ }
++
++ /*
++ * The other side might already be re-connected, but the timer might
++ * not have fired yet. So let's check here whether we can write again:
++ */
++ pfd.fd = QIO_CHANNEL_FILE(s->ioc)->fd;
++ pfd.events = G_IO_OUT;
++ pfd.revents = 0;
++ TFR(rc = g_poll(&pfd, 1, 0));
++ g_assert(rc >= 0);
++ if (!(pfd.revents & G_IO_HUP) && (pfd.revents & G_IO_OUT)) {
++ io_channel_send(s->ioc, buf, len);
+ }
+- return io_channel_send(s->ioc, buf, len);
++
++ return len;
+ }
+
+ static GSource *pty_chr_add_watch(Chardev *chr, GIOCondition cond)
+diff --git a/disas/riscv.c b/disas/riscv.c
+index d216b9c39b..dee4e580a0 100644
+--- a/disas/riscv.c
++++ b/disas/riscv.c
+@@ -2173,8 +2173,8 @@ static const char *csr_name(int csrno)
+ case 0x03ba: return "pmpaddr10";
+ case 0x03bb: return "pmpaddr11";
+ case 0x03bc: return "pmpaddr12";
+- case 0x03bd: return "pmpaddr14";
+- case 0x03be: return "pmpaddr13";
++ case 0x03bd: return "pmpaddr13";
++ case 0x03be: return "pmpaddr14";
+ case 0x03bf: return "pmpaddr15";
+ case 0x0780: return "mtohost";
+ case 0x0781: return "mfromhost";
+diff --git a/hw/audio/es1370.c b/hw/audio/es1370.c
+index 6904589814..7032bee2f6 100644
+--- a/hw/audio/es1370.c
++++ b/hw/audio/es1370.c
+@@ -503,7 +503,7 @@ static void es1370_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
+ case ES1370_REG_DAC2_SCOUNT:
+ case ES1370_REG_ADC_SCOUNT:
+ d += (addr - ES1370_REG_DAC1_SCOUNT) >> 2;
+- d->scount = (val & 0xffff) | (d->scount & ~0xffff);
++ d->scount = (val & 0xffff) << 16 | (val & 0xffff);
+ ldebug ("chan %td CURR_SAMP_CT %d, SAMP_CT %d\n",
+ d - &s->chan[0], val >> 16, (val & 0xffff));
+ break;
+diff --git a/hw/cxl/cxl-host.c b/hw/cxl/cxl-host.c
+index 1adf61231a..0fc3e57138 100644
+--- a/hw/cxl/cxl-host.c
++++ b/hw/cxl/cxl-host.c
+@@ -39,12 +39,6 @@ static void cxl_fixed_memory_window_config(CXLState *cxl_state,
+ return;
+ }
+
+- fw->targets = g_malloc0_n(fw->num_targets, sizeof(*fw->targets));
+- for (i = 0, target = object->targets; target; i++, target = target->next) {
+- /* This link cannot be resolved yet, so stash the name for now */
+- fw->targets[i] = g_strdup(target->value);
+- }
+-
+ if (object->size % (256 * MiB)) {
+ error_setg(errp,
+ "Size of a CXL fixed memory window must my a multiple of 256MiB");
+@@ -64,6 +58,12 @@ static void cxl_fixed_memory_window_config(CXLState *cxl_state,
+ fw->enc_int_gran = 0;
+ }
+
++ fw->targets = g_malloc0_n(fw->num_targets, sizeof(*fw->targets));
++ for (i = 0, target = object->targets; target; i++, target = target->next) {
++ /* This link cannot be resolved yet, so stash the name for now */
++ fw->targets[i] = g_strdup(target->value);
++ }
++
+ cxl_state->fixed_windows = g_list_append(cxl_state->fixed_windows,
+ g_steal_pointer(&fw));
+
+diff --git a/hw/display/ati.c b/hw/display/ati.c
+index 6e38e00502..4f3bebcfd3 100644
+--- a/hw/display/ati.c
++++ b/hw/display/ati.c
+@@ -1014,6 +1014,7 @@ static Property ati_vga_properties[] = {
+ DEFINE_PROP_UINT16("x-device-id", ATIVGAState, dev_id,
+ PCI_DEVICE_ID_ATI_RAGE128_PF),
+ DEFINE_PROP_BOOL("guest_hwcursor", ATIVGAState, cursor_guest_mode, false),
++ DEFINE_PROP_UINT8("x-pixman", ATIVGAState, use_pixman, 3),
+ DEFINE_PROP_END_OF_LIST()
+ };
+
+@@ -1035,11 +1036,18 @@ static void ati_vga_class_init(ObjectClass *klass, void *data)
+ k->exit = ati_vga_exit;
+ }
+
++static void ati_vga_init(Object *o)
++{
++ object_property_set_description(o, "x-pixman", "Use pixman for: "
++ "1: fill, 2: blit");
++}
++
+ static const TypeInfo ati_vga_info = {
+ .name = TYPE_ATI_VGA,
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(ATIVGAState),
+ .class_init = ati_vga_class_init,
++ .instance_init = ati_vga_init,
+ .interfaces = (InterfaceInfo[]) {
+ { INTERFACE_CONVENTIONAL_PCI_DEVICE },
+ { },
+diff --git a/hw/display/ati_2d.c b/hw/display/ati_2d.c
+index 7d786653e8..0e6b8e4367 100644
+--- a/hw/display/ati_2d.c
++++ b/hw/display/ati_2d.c
+@@ -92,6 +92,7 @@ void ati_2d_blt(ATIVGAState *s)
+ switch (s->regs.dp_mix & GMC_ROP3_MASK) {
+ case ROP3_SRCCOPY:
+ {
++ bool fallback = false;
+ unsigned src_x = (s->regs.dp_cntl & DST_X_LEFT_TO_RIGHT ?
+ s->regs.src_x : s->regs.src_x + 1 - s->regs.dst_width);
+ unsigned src_y = (s->regs.dp_cntl & DST_Y_TOP_TO_BOTTOM ?
+@@ -122,27 +123,50 @@ void ati_2d_blt(ATIVGAState *s)
+ src_bits, dst_bits, src_stride, dst_stride, bpp, bpp,
+ src_x, src_y, dst_x, dst_y,
+ s->regs.dst_width, s->regs.dst_height);
+- if (s->regs.dp_cntl & DST_X_LEFT_TO_RIGHT &&
++ if ((s->use_pixman & BIT(1)) &&
++ s->regs.dp_cntl & DST_X_LEFT_TO_RIGHT &&
+ s->regs.dp_cntl & DST_Y_TOP_TO_BOTTOM) {
+- pixman_blt((uint32_t *)src_bits, (uint32_t *)dst_bits,
+- src_stride, dst_stride, bpp, bpp,
+- src_x, src_y, dst_x, dst_y,
+- s->regs.dst_width, s->regs.dst_height);
+- } else {
++ fallback = !pixman_blt((uint32_t *)src_bits, (uint32_t *)dst_bits,
++ src_stride, dst_stride, bpp, bpp,
++ src_x, src_y, dst_x, dst_y,
++ s->regs.dst_width, s->regs.dst_height);
++ } else if (s->use_pixman & BIT(1)) {
+ /* FIXME: We only really need a temporary if src and dst overlap */
+ int llb = s->regs.dst_width * (bpp / 8);
+ int tmp_stride = DIV_ROUND_UP(llb, sizeof(uint32_t));
+ uint32_t *tmp = g_malloc(tmp_stride * sizeof(uint32_t) *
+ s->regs.dst_height);
+- pixman_blt((uint32_t *)src_bits, tmp,
+- src_stride, tmp_stride, bpp, bpp,
+- src_x, src_y, 0, 0,
+- s->regs.dst_width, s->regs.dst_height);
+- pixman_blt(tmp, (uint32_t *)dst_bits,
+- tmp_stride, dst_stride, bpp, bpp,
+- 0, 0, dst_x, dst_y,
+- s->regs.dst_width, s->regs.dst_height);
++ fallback = !pixman_blt((uint32_t *)src_bits, tmp,
++ src_stride, tmp_stride, bpp, bpp,
++ src_x, src_y, 0, 0,
++ s->regs.dst_width, s->regs.dst_height);
++ if (!fallback) {
++ fallback = !pixman_blt(tmp, (uint32_t *)dst_bits,
++ tmp_stride, dst_stride, bpp, bpp,
++ 0, 0, dst_x, dst_y,
++ s->regs.dst_width, s->regs.dst_height);
++ }
+ g_free(tmp);
++ } else {
++ fallback = true;
++ }
++ if (fallback) {
++ unsigned int y, i, j, bypp = bpp / 8;
++ unsigned int src_pitch = src_stride * sizeof(uint32_t);
++ unsigned int dst_pitch = dst_stride * sizeof(uint32_t);
++
++ for (y = 0; y < s->regs.dst_height; y++) {
++ i = dst_x * bypp;
++ j = src_x * bypp;
++ if (s->regs.dp_cntl & DST_Y_TOP_TO_BOTTOM) {
++ i += (dst_y + y) * dst_pitch;
++ j += (src_y + y) * src_pitch;
++ } else {
++ i += (dst_y + s->regs.dst_height - 1 - y) * dst_pitch;
++ j += (src_y + s->regs.dst_height - 1 - y) * src_pitch;
++ }
++ memmove(&dst_bits[i], &src_bits[j], s->regs.dst_width * bypp);
++ }
+ }
+ if (dst_bits >= s->vga.vram_ptr + s->vga.vbe_start_addr &&
+ dst_bits < s->vga.vram_ptr + s->vga.vbe_start_addr +
+@@ -180,14 +204,21 @@ void ati_2d_blt(ATIVGAState *s)
+
+ dst_stride /= sizeof(uint32_t);
+ DPRINTF("pixman_fill(%p, %d, %d, %d, %d, %d, %d, %x)\n",
+- dst_bits, dst_stride, bpp,
+- dst_x, dst_y,
+- s->regs.dst_width, s->regs.dst_height,
+- filler);
+- pixman_fill((uint32_t *)dst_bits, dst_stride, bpp,
+- dst_x, dst_y,
+- s->regs.dst_width, s->regs.dst_height,
+- filler);
++ dst_bits, dst_stride, bpp, dst_x, dst_y,
++ s->regs.dst_width, s->regs.dst_height, filler);
++ if (!(s->use_pixman & BIT(0)) ||
++ !pixman_fill((uint32_t *)dst_bits, dst_stride, bpp, dst_x, dst_y,
++ s->regs.dst_width, s->regs.dst_height, filler)) {
++ /* fallback when pixman failed or we don't want to call it */
++ unsigned int x, y, i, bypp = bpp / 8;
++ unsigned int dst_pitch = dst_stride * sizeof(uint32_t);
++ for (y = 0; y < s->regs.dst_height; y++) {
++ i = dst_x * bypp + (dst_y + y) * dst_pitch;
++ for (x = 0; x < s->regs.dst_width; x++, i += bypp) {
++ stn_he_p(&dst_bits[i], bypp, filler);
++ }
++ }
++ }
+ if (dst_bits >= s->vga.vram_ptr + s->vga.vbe_start_addr &&
+ dst_bits < s->vga.vram_ptr + s->vga.vbe_start_addr +
+ s->vga.vbe_regs[VBE_DISPI_INDEX_YRES] * s->vga.vbe_line_offset) {
+diff --git a/hw/display/ati_int.h b/hw/display/ati_int.h
+index 8acb9c7466..055aa2d140 100644
+--- a/hw/display/ati_int.h
++++ b/hw/display/ati_int.h
+@@ -89,6 +89,7 @@ struct ATIVGAState {
+ char *model;
+ uint16_t dev_id;
+ uint8_t mode;
++ uint8_t use_pixman;
+ bool cursor_guest_mode;
+ uint16_t cursor_size;
+ uint32_t cursor_offset;
+diff --git a/hw/display/ramfb.c b/hw/display/ramfb.c
+index 79b9754a58..c2b002d534 100644
+--- a/hw/display/ramfb.c
++++ b/hw/display/ramfb.c
+@@ -97,6 +97,7 @@ static void ramfb_fw_cfg_write(void *dev, off_t offset, size_t len)
+
+ s->width = width;
+ s->height = height;
++ qemu_free_displaysurface(s->ds);
+ s->ds = surface;
+ }
+
+diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c
+index 725f69095b..a20f3e1d50 100644
+--- a/hw/i386/amd_iommu.c
++++ b/hw/i386/amd_iommu.c
+@@ -1246,13 +1246,8 @@ static int amdvi_int_remap_msi(AMDVIState *iommu,
+ return -AMDVI_IR_ERR;
+ }
+
+- if (origin->address & AMDVI_MSI_ADDR_HI_MASK) {
+- trace_amdvi_err("MSI address high 32 bits non-zero when "
+- "Interrupt Remapping enabled.");
+- return -AMDVI_IR_ERR;
+- }
+-
+- if ((origin->address & AMDVI_MSI_ADDR_LO_MASK) != APIC_DEFAULT_ADDRESS) {
++ if (origin->address < AMDVI_INT_ADDR_FIRST ||
++ origin->address + sizeof(origin->data) > AMDVI_INT_ADDR_LAST + 1) {
+ trace_amdvi_err("MSI is not from IOAPIC.");
+ return -AMDVI_IR_ERR;
+ }
+diff --git a/hw/i386/amd_iommu.h b/hw/i386/amd_iommu.h
+index 79d38a3e41..210a37dfb1 100644
+--- a/hw/i386/amd_iommu.h
++++ b/hw/i386/amd_iommu.h
+@@ -210,8 +210,6 @@
+ #define AMDVI_INT_ADDR_FIRST 0xfee00000
+ #define AMDVI_INT_ADDR_LAST 0xfeefffff
+ #define AMDVI_INT_ADDR_SIZE (AMDVI_INT_ADDR_LAST - AMDVI_INT_ADDR_FIRST + 1)
+-#define AMDVI_MSI_ADDR_HI_MASK (0xffffffff00000000ULL)
+-#define AMDVI_MSI_ADDR_LO_MASK (0x00000000ffffffffULL)
+
+ /* SB IOAPIC is always on this device in AMD systems */
+ #define AMDVI_IOAPIC_SB_DEVID PCI_BUILD_BDF(0, PCI_DEVFN(0x14, 0))
+diff --git a/hw/ide/core.c b/hw/ide/core.c
+index 1477935270..3e97d665d9 100644
+--- a/hw/ide/core.c
++++ b/hw/ide/core.c
+@@ -2491,19 +2491,19 @@ static void ide_dummy_transfer_stop(IDEState *s)
+
+ void ide_bus_reset(IDEBus *bus)
+ {
+- bus->unit = 0;
+- bus->cmd = 0;
+- ide_reset(&bus->ifs[0]);
+- ide_reset(&bus->ifs[1]);
+- ide_clear_hob(bus);
+-
+- /* pending async DMA */
++ /* pending async DMA - needs the IDEState before it is reset */
+ if (bus->dma->aiocb) {
+ trace_ide_bus_reset_aio();
+ blk_aio_cancel(bus->dma->aiocb);
+ bus->dma->aiocb = NULL;
+ }
+
++ bus->unit = 0;
++ bus->cmd = 0;
++ ide_reset(&bus->ifs[0]);
++ ide_reset(&bus->ifs[1]);
++ ide_clear_hob(bus);
++
+ /* reset dma provider too */
+ if (bus->dma->ops->reset) {
+ bus->dma->ops->reset(bus->dma);
+diff --git a/hw/input/lasips2.c b/hw/input/lasips2.c
+index ea7c07a2ba..6075121b72 100644
+--- a/hw/input/lasips2.c
++++ b/hw/input/lasips2.c
+@@ -351,6 +351,11 @@ static void lasips2_port_class_init(ObjectClass *klass, void *data)
+ {
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
++ /*
++ * The PS/2 mouse port is integreal part of LASI and can not be
++ * created by users without LASI.
++ */
++ dc->user_creatable = false;
+ dc->realize = lasips2_port_realize;
+ }
+
+@@ -397,6 +402,11 @@ static void lasips2_kbd_port_class_init(ObjectClass *klass, void *data)
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ LASIPS2PortDeviceClass *lpdc = LASIPS2_PORT_CLASS(klass);
+
++ /*
++ * The PS/2 keyboard port is integreal part of LASI and can not be
++ * created by users without LASI.
++ */
++ dc->user_creatable = false;
+ device_class_set_parent_realize(dc, lasips2_kbd_port_realize,
+ &lpdc->parent_realize);
+ }
+diff --git a/hw/misc/led.c b/hw/misc/led.c
+index f6d6d68bce..42bb43a39a 100644
+--- a/hw/misc/led.c
++++ b/hw/misc/led.c
+@@ -63,7 +63,7 @@ static void led_set_state_gpio_handler(void *opaque, int line, int new_state)
+ LEDState *s = LED(opaque);
+
+ assert(line == 0);
+- led_set_state(s, !!new_state != s->gpio_active_high);
++ led_set_state(s, !!new_state == s->gpio_active_high);
+ }
+
+ static void led_reset(DeviceState *dev)
+diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c
+index fbdc48911e..b17804fc17 100644
+--- a/hw/ppc/ppc.c
++++ b/hw/ppc/ppc.c
+@@ -490,10 +490,32 @@ void ppce500_set_mpic_proxy(bool enabled)
+ /*****************************************************************************/
+ /* PowerPC time base and decrementer emulation */
+
++/*
++ * Conversion between QEMU_CLOCK_VIRTUAL ns and timebase (TB) ticks:
++ * TB ticks are arrived at by multiplying tb_freq then dividing by
++ * ns per second, and rounding down. TB ticks drive all clocks and
++ * timers in the target machine.
++ *
++ * Converting TB intervals to ns for the purpose of setting a
++ * QEMU_CLOCK_VIRTUAL timer should go the other way, but rounding
++ * up. Rounding down could cause the timer to fire before the TB
++ * value has been reached.
++ */
++static uint64_t ns_to_tb(uint32_t freq, int64_t clock)
++{
++ return muldiv64(clock, freq, NANOSECONDS_PER_SECOND);
++}
++
++/* virtual clock in TB ticks, not adjusted by TB offset */
++static int64_t tb_to_ns_round_up(uint32_t freq, uint64_t tb)
++{
++ return muldiv64_round_up(tb, NANOSECONDS_PER_SECOND, freq);
++}
++
+ uint64_t cpu_ppc_get_tb(ppc_tb_t *tb_env, uint64_t vmclk, int64_t tb_offset)
+ {
+ /* TB time in tb periods */
+- return muldiv64(vmclk, tb_env->tb_freq, NANOSECONDS_PER_SECOND) + tb_offset;
++ return ns_to_tb(tb_env->tb_freq, vmclk) + tb_offset;
+ }
+
+ uint64_t cpu_ppc_load_tbl (CPUPPCState *env)
+@@ -534,8 +556,7 @@ uint32_t cpu_ppc_load_tbu (CPUPPCState *env)
+ static inline void cpu_ppc_store_tb(ppc_tb_t *tb_env, uint64_t vmclk,
+ int64_t *tb_offsetp, uint64_t value)
+ {
+- *tb_offsetp = value -
+- muldiv64(vmclk, tb_env->tb_freq, NANOSECONDS_PER_SECOND);
++ *tb_offsetp = value - ns_to_tb(tb_env->tb_freq, vmclk);
+
+ trace_ppc_tb_store(value, *tb_offsetp);
+ }
+@@ -693,16 +714,17 @@ bool ppc_decr_clear_on_delivery(CPUPPCState *env)
+ static inline int64_t _cpu_ppc_load_decr(CPUPPCState *env, uint64_t next)
+ {
+ ppc_tb_t *tb_env = env->tb_env;
+- int64_t decr, diff;
++ uint64_t now, n;
++ int64_t decr;
+
+- diff = next - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+- if (diff >= 0) {
+- decr = muldiv64(diff, tb_env->decr_freq, NANOSECONDS_PER_SECOND);
+- } else if (tb_env->flags & PPC_TIMER_BOOKE) {
++ now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
++ n = ns_to_tb(tb_env->decr_freq, now);
++ if (next > n && tb_env->flags & PPC_TIMER_BOOKE) {
+ decr = 0;
+- } else {
+- decr = -muldiv64(-diff, tb_env->decr_freq, NANOSECONDS_PER_SECOND);
++ } else {
++ decr = next - n;
+ }
++
+ trace_ppc_decr_load(decr);
+
+ return decr;
+@@ -724,7 +746,9 @@ target_ulong cpu_ppc_load_decr(CPUPPCState *env)
+ * to 64 bits, otherwise it is a 32 bit value.
+ */
+ if (env->spr[SPR_LPCR] & LPCR_LD) {
+- return decr;
++ PowerPCCPU *cpu = env_archcpu(env);
++ PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
++ return sextract64(decr, 0, pcc->lrg_decr_bits);
+ }
+ return (uint32_t) decr;
+ }
+@@ -743,7 +767,7 @@ target_ulong cpu_ppc_load_hdecr(CPUPPCState *env)
+ * extended to 64 bits, otherwise it is 32 bits.
+ */
+ if (pcc->lrg_decr_bits > 32) {
+- return hdecr;
++ return sextract64(hdecr, 0, pcc->lrg_decr_bits);
+ }
+ return (uint32_t) hdecr;
+ }
+@@ -819,11 +843,17 @@ static void __cpu_ppc_store_decr(PowerPCCPU *cpu, uint64_t *nextp,
+ }
+
+ /*
+- * Going from 2 -> 1, 1 -> 0 or 0 -> -1 is the event to generate a DEC
+- * interrupt.
+- *
+- * If we get a really small DEC value, we can assume that by the time we
+- * handled it we should inject an interrupt already.
++ * Calculate the next decrementer event and set a timer.
++ * decr_next is in timebase units to keep rounding simple. Note it is
++ * not adjusted by tb_offset because if TB changes via tb_offset changing,
++ * decrementer does not change, so not directly comparable with TB.
++ */
++ now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
++ next = ns_to_tb(tb_env->decr_freq, now) + value;
++ *nextp = next; /* nextp is in timebase units */
++
++ /*
++ * Going from 1 -> 0 or 0 -> -1 is the event to generate a DEC interrupt.
+ *
+ * On MSB level based DEC implementations the MSB always means the interrupt
+ * is pending, so raise it on those.
+@@ -831,8 +861,7 @@ static void __cpu_ppc_store_decr(PowerPCCPU *cpu, uint64_t *nextp,
+ * On MSB edge based DEC implementations the MSB going from 0 -> 1 triggers
+ * an edge interrupt, so raise it here too.
+ */
+- if ((value < 3) ||
+- ((tb_env->flags & PPC_DECR_UNDERFLOW_LEVEL) && signed_value < 0) ||
++ if (((tb_env->flags & PPC_DECR_UNDERFLOW_LEVEL) && signed_value < 0) ||
+ ((tb_env->flags & PPC_DECR_UNDERFLOW_TRIGGERED) && signed_value < 0
+ && signed_decr >= 0)) {
+ (*raise_excp)(cpu);
+@@ -844,13 +873,8 @@ static void __cpu_ppc_store_decr(PowerPCCPU *cpu, uint64_t *nextp,
+ (*lower_excp)(cpu);
+ }
+
+- /* Calculate the next timer event */
+- now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+- next = now + muldiv64(value, NANOSECONDS_PER_SECOND, tb_env->decr_freq);
+- *nextp = next;
+-
+ /* Adjust timer */
+- timer_mod(timer, next);
++ timer_mod(timer, tb_to_ns_round_up(tb_env->decr_freq, next));
+ }
+
+ static inline void _cpu_ppc_store_decr(PowerPCCPU *cpu, target_ulong decr,
+@@ -1135,9 +1159,7 @@ static void cpu_4xx_fit_cb (void *opaque)
+ /* Cannot occur, but makes gcc happy */
+ return;
+ }
+- next = now + muldiv64(next, NANOSECONDS_PER_SECOND, tb_env->tb_freq);
+- if (next == now)
+- next++;
++ next = now + tb_to_ns_round_up(tb_env->tb_freq, next);
+ timer_mod(ppc40x_timer->fit_timer, next);
+ env->spr[SPR_40x_TSR] |= 1 << 26;
+ if ((env->spr[SPR_40x_TCR] >> 23) & 0x1) {
+@@ -1163,14 +1185,15 @@ static void start_stop_pit (CPUPPCState *env, ppc_tb_t *tb_env, int is_excp)
+ } else {
+ trace_ppc4xx_pit_start(ppc40x_timer->pit_reload);
+ now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+- next = now + muldiv64(ppc40x_timer->pit_reload,
+- NANOSECONDS_PER_SECOND, tb_env->decr_freq);
+- if (is_excp)
+- next += tb_env->decr_next - now;
+- if (next == now)
+- next++;
++
++ if (is_excp) {
++ tb_env->decr_next += ppc40x_timer->pit_reload;
++ } else {
++ tb_env->decr_next = ns_to_tb(tb_env->decr_freq, now)
++ + ppc40x_timer->pit_reload;
++ }
++ next = tb_to_ns_round_up(tb_env->decr_freq, tb_env->decr_next);
+ timer_mod(tb_env->decr_timer, next);
+- tb_env->decr_next = next;
+ }
+ }
+
+@@ -1223,9 +1246,7 @@ static void cpu_4xx_wdt_cb (void *opaque)
+ /* Cannot occur, but makes gcc happy */
+ return;
+ }
+- next = now + muldiv64(next, NANOSECONDS_PER_SECOND, tb_env->decr_freq);
+- if (next == now)
+- next++;
++ next = now + tb_to_ns_round_up(tb_env->decr_freq, next);
+ trace_ppc4xx_wdt(env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR]);
+ switch ((env->spr[SPR_40x_TSR] >> 30) & 0x3) {
+ case 0x0:
+diff --git a/hw/rdma/vmw/pvrdma_main.c b/hw/rdma/vmw/pvrdma_main.c
+index 4fc6712025..55b338046e 100644
+--- a/hw/rdma/vmw/pvrdma_main.c
++++ b/hw/rdma/vmw/pvrdma_main.c
+@@ -91,19 +91,33 @@ static int init_dev_ring(PvrdmaRing *ring, PvrdmaRingState **ring_state,
+ dma_addr_t dir_addr, uint32_t num_pages)
+ {
+ uint64_t *dir, *tbl;
+- int rc = 0;
++ int max_pages, rc = 0;
+
+ if (!num_pages) {
+ rdma_error_report("Ring pages count must be strictly positive");
+ return -EINVAL;
+ }
+
++ /*
++ * Make sure we can satisfy the requested number of pages in a single
++ * TARGET_PAGE_SIZE sized page table (taking into account that first entry
++ * is reserved for ring-state)
++ */
++ max_pages = TARGET_PAGE_SIZE / sizeof(dma_addr_t) - 1;
++ if (num_pages > max_pages) {
++ rdma_error_report("Maximum pages on a single directory must not exceed %d\n",
++ max_pages);
++ return -EINVAL;
++ }
++
+ dir = rdma_pci_dma_map(pci_dev, dir_addr, TARGET_PAGE_SIZE);
+ if (!dir) {
+ rdma_error_report("Failed to map to page directory (ring %s)", name);
+ rc = -ENOMEM;
+ goto out;
+ }
++
++ /* We support only one page table for a ring */
+ tbl = rdma_pci_dma_map(pci_dev, dir[0], TARGET_PAGE_SIZE);
+ if (!tbl) {
+ rdma_error_report("Failed to map to page table (ring %s)", name);
+diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c
+index e52188d022..9b11d8c573 100644
+--- a/hw/scsi/esp.c
++++ b/hw/scsi/esp.c
+@@ -759,7 +759,8 @@ static void esp_do_nodma(ESPState *s)
+ }
+
+ if (to_device) {
+- len = MIN(fifo8_num_used(&s->fifo), ESP_FIFO_SZ);
++ len = MIN(s->async_len, ESP_FIFO_SZ);
++ len = MIN(len, fifo8_num_used(&s->fifo));
+ esp_fifo_pop_buf(&s->fifo, s->async_buf, len);
+ s->async_buf += len;
+ s->async_len -= len;
+@@ -1395,7 +1396,7 @@ static void sysbus_esp_gpio_demux(void *opaque, int irq, int level)
+ parent_esp_reset(s, irq, level);
+ break;
+ case 1:
+- esp_dma_enable(opaque, irq, level);
++ esp_dma_enable(s, irq, level);
+ break;
+ }
+ }
+diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
+index e493c28814..b884a6f135 100644
+--- a/hw/scsi/scsi-disk.c
++++ b/hw/scsi/scsi-disk.c
+@@ -1624,9 +1624,10 @@ static void scsi_disk_emulate_mode_select(SCSIDiskReq *r, uint8_t *inbuf)
+ * Since the existing code only checks/updates bits 8-15 of the block
+ * size, restrict ourselves to the same requirement for now to ensure
+ * that a block size set by a block descriptor and then read back by
+- * a subsequent SCSI command will be the same
++ * a subsequent SCSI command will be the same. Also disallow a block
++ * size of 256 since we cannot handle anything below BDRV_SECTOR_SIZE.
+ */
+- if (bs && !(bs & ~0xff00) && bs != s->qdev.blocksize) {
++ if (bs && !(bs & ~0xfe00) && bs != s->qdev.blocksize) {
+ s->qdev.blocksize = bs;
+ trace_scsi_disk_mode_select_set_blocksize(s->qdev.blocksize);
+ }
+@@ -1951,6 +1952,10 @@ static void scsi_disk_emulate_write_data(SCSIRequest *req)
+ scsi_disk_emulate_write_same(r, r->iov.iov_base);
+ break;
+
++ case FORMAT_UNIT:
++ scsi_req_complete(&r->req, GOOD);
++ break;
++
+ default:
+ abort();
+ }
+diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
+index 306070c872..ef60badc6b 100644
+--- a/hw/sd/sdhci.c
++++ b/hw/sd/sdhci.c
+@@ -321,6 +321,8 @@ static void sdhci_poweron_reset(DeviceState *dev)
+
+ static void sdhci_data_transfer(void *opaque);
+
++#define BLOCK_SIZE_MASK (4 * KiB - 1)
++
+ static void sdhci_send_command(SDHCIState *s)
+ {
+ SDRequest request;
+@@ -371,7 +373,8 @@ static void sdhci_send_command(SDHCIState *s)
+
+ sdhci_update_irq(s);
+
+- if (!timeout && s->blksize && (s->cmdreg & SDHC_CMD_DATA_PRESENT)) {
++ if (!timeout && (s->blksize & BLOCK_SIZE_MASK) &&
++ (s->cmdreg & SDHC_CMD_DATA_PRESENT)) {
+ s->data_count = 0;
+ sdhci_data_transfer(s);
+ }
+@@ -406,7 +409,6 @@ static void sdhci_end_transfer(SDHCIState *s)
+ /*
+ * Programmed i/o data transfer
+ */
+-#define BLOCK_SIZE_MASK (4 * KiB - 1)
+
+ /* Fill host controller's read buffer with BLKSIZE bytes of data from card */
+ static void sdhci_read_block_from_card(SDHCIState *s)
+@@ -1154,7 +1156,8 @@ sdhci_write(void *opaque, hwaddr offset, uint64_t val, unsigned size)
+ s->sdmasysad = (s->sdmasysad & mask) | value;
+ MASKED_WRITE(s->sdmasysad, mask, value);
+ /* Writing to last byte of sdmasysad might trigger transfer */
+- if (!(mask & 0xFF000000) && s->blkcnt && s->blksize &&
++ if (!(mask & 0xFF000000) && s->blkcnt &&
++ (s->blksize & BLOCK_SIZE_MASK) &&
+ SDHC_DMA_TYPE(s->hostctl1) == SDHC_CTRL_SDMA) {
+ if (s->trnmod & SDHC_TRNS_MULTI) {
+ sdhci_sdma_transfer_multi_blocks(s);
+@@ -1168,7 +1171,11 @@ sdhci_write(void *opaque, hwaddr offset, uint64_t val, unsigned size)
+ if (!TRANSFERRING_DATA(s->prnsts)) {
+ uint16_t blksize = s->blksize;
+
+- MASKED_WRITE(s->blksize, mask, extract32(value, 0, 12));
++ /*
++ * [14:12] SDMA Buffer Boundary
++ * [11:00] Transfer Block Size
++ */
++ MASKED_WRITE(s->blksize, mask, extract32(value, 0, 15));
+ MASKED_WRITE(s->blkcnt, mask >> 16, value >> 16);
+
+ /* Limit block size to the maximum buffer size */
+diff --git a/include/qemu/host-utils.h b/include/qemu/host-utils.h
+index b3434ec0bc..09daf58787 100644
+--- a/include/qemu/host-utils.h
++++ b/include/qemu/host-utils.h
+@@ -57,6 +57,11 @@ static inline uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
+ return (__int128_t)a * b / c;
+ }
+
++static inline uint64_t muldiv64_round_up(uint64_t a, uint32_t b, uint32_t c)
++{
++ return ((__int128_t)a * b + c - 1) / c;
++}
++
+ static inline uint64_t divu128(uint64_t *plow, uint64_t *phigh,
+ uint64_t divisor)
+ {
+@@ -84,7 +89,8 @@ void mulu64(uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b);
+ uint64_t divu128(uint64_t *plow, uint64_t *phigh, uint64_t divisor);
+ int64_t divs128(uint64_t *plow, int64_t *phigh, int64_t divisor);
+
+-static inline uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
++static inline uint64_t muldiv64_rounding(uint64_t a, uint32_t b, uint32_t c,
++ bool round_up)
+ {
+ union {
+ uint64_t ll;
+@@ -100,12 +106,25 @@ static inline uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
+
+ u.ll = a;
+ rl = (uint64_t)u.l.low * (uint64_t)b;
++ if (round_up) {
++ rl += c - 1;
++ }
+ rh = (uint64_t)u.l.high * (uint64_t)b;
+ rh += (rl >> 32);
+ res.l.high = rh / c;
+ res.l.low = (((rh % c) << 32) + (rl & 0xffffffff)) / c;
+ return res.ll;
+ }
++
++static inline uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
++{
++ return muldiv64_rounding(a, b, c, false);
++}
++
++static inline uint64_t muldiv64_round_up(uint64_t a, uint32_t b, uint32_t c)
++{
++ return muldiv64_rounding(a, b, c, true);
++}
+ #endif
+
+ /**
+diff --git a/linux-user/hppa/signal.c b/linux-user/hppa/signal.c
+index f253a15864..ec5f5412d1 100644
+--- a/linux-user/hppa/signal.c
++++ b/linux-user/hppa/signal.c
+@@ -25,7 +25,7 @@
+ struct target_sigcontext {
+ abi_ulong sc_flags;
+ abi_ulong sc_gr[32];
+- uint64_t sc_fr[32];
++ abi_ullong sc_fr[32];
+ abi_ulong sc_iasq[2];
+ abi_ulong sc_iaoq[2];
+ abi_ulong sc_sar;
+@@ -149,16 +149,18 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
+ target_ulong *fdesc, dest;
+
+ haddr &= -4;
+- if (!lock_user_struct(VERIFY_READ, fdesc, haddr, 1)) {
++ fdesc = lock_user(VERIFY_READ, haddr, 2 * sizeof(target_ulong), 1);
++ if (!fdesc) {
+ goto give_sigsegv;
+ }
+ __get_user(dest, fdesc);
+ __get_user(env->gr[19], fdesc + 1);
+- unlock_user_struct(fdesc, haddr, 1);
++ unlock_user(fdesc, haddr, 0);
+ haddr = dest;
+ }
+ env->iaoq_f = haddr;
+ env->iaoq_b = haddr + 4;
++ env->psw_n = 0;
+ return;
+
+ give_sigsegv:
+diff --git a/linux-user/mips/cpu_loop.c b/linux-user/mips/cpu_loop.c
+index 8735e58bad..990b03e727 100644
+--- a/linux-user/mips/cpu_loop.c
++++ b/linux-user/mips/cpu_loop.c
+@@ -180,7 +180,9 @@ done_syscall:
+ }
+ force_sig_fault(TARGET_SIGFPE, si_code, env->active_tc.PC);
+ break;
+-
++ case EXCP_OVERFLOW:
++ force_sig_fault(TARGET_SIGFPE, TARGET_FPE_INTOVF, env->active_tc.PC);
++ break;
+ /* The code below was inspired by the MIPS Linux kernel trap
+ * handling code in arch/mips/kernel/traps.c.
+ */
+diff --git a/linux-user/sh4/signal.c b/linux-user/sh4/signal.c
+index c4ba962708..c16c2c2d57 100644
+--- a/linux-user/sh4/signal.c
++++ b/linux-user/sh4/signal.c
+@@ -104,6 +104,14 @@ static void unwind_gusa(CPUSH4State *regs)
+
+ /* Reset the SP to the saved version in R1. */
+ regs->gregs[15] = regs->gregs[1];
++ } else if (regs->gregs[15] >= -128u && regs->pc == regs->gregs[0]) {
++ /* If we are on the last instruction of a gUSA region, we must reset
++ the SP, otherwise we would be pushing the signal context to
++ invalid memory. */
++ regs->gregs[15] = regs->gregs[1];
++ } else if (regs->flags & TB_FLAG_DELAY_SLOT) {
++ /* If we are in a delay slot, push the previous instruction. */
++ regs->pc -= 2;
+ }
+ }
+
+diff --git a/linux-user/syscall.c b/linux-user/syscall.c
+index cedf22c5b5..aead0f6ac9 100644
+--- a/linux-user/syscall.c
++++ b/linux-user/syscall.c
+@@ -95,50 +95,7 @@
+ #include <linux/soundcard.h>
+ #include <linux/kd.h>
+ #include <linux/mtio.h>
+-
+-#ifdef HAVE_SYS_MOUNT_FSCONFIG
+-/*
+- * glibc >= 2.36 linux/mount.h conflicts with sys/mount.h,
+- * which in turn prevents use of linux/fs.h. So we have to
+- * define the constants ourselves for now.
+- */
+-#define FS_IOC_GETFLAGS _IOR('f', 1, long)
+-#define FS_IOC_SETFLAGS _IOW('f', 2, long)
+-#define FS_IOC_GETVERSION _IOR('v', 1, long)
+-#define FS_IOC_SETVERSION _IOW('v', 2, long)
+-#define FS_IOC_FIEMAP _IOWR('f', 11, struct fiemap)
+-#define FS_IOC32_GETFLAGS _IOR('f', 1, int)
+-#define FS_IOC32_SETFLAGS _IOW('f', 2, int)
+-#define FS_IOC32_GETVERSION _IOR('v', 1, int)
+-#define FS_IOC32_SETVERSION _IOW('v', 2, int)
+-
+-#define BLKGETSIZE64 _IOR(0x12,114,size_t)
+-#define BLKDISCARD _IO(0x12,119)
+-#define BLKIOMIN _IO(0x12,120)
+-#define BLKIOOPT _IO(0x12,121)
+-#define BLKALIGNOFF _IO(0x12,122)
+-#define BLKPBSZGET _IO(0x12,123)
+-#define BLKDISCARDZEROES _IO(0x12,124)
+-#define BLKSECDISCARD _IO(0x12,125)
+-#define BLKROTATIONAL _IO(0x12,126)
+-#define BLKZEROOUT _IO(0x12,127)
+-
+-#define FIBMAP _IO(0x00,1)
+-#define FIGETBSZ _IO(0x00,2)
+-
+-struct file_clone_range {
+- __s64 src_fd;
+- __u64 src_offset;
+- __u64 src_length;
+- __u64 dest_offset;
+-};
+-
+-#define FICLONE _IOW(0x94, 9, int)
+-#define FICLONERANGE _IOW(0x94, 13, struct file_clone_range)
+-
+-#else
+ #include <linux/fs.h>
+-#endif
+ #include <linux/fd.h>
+ #if defined(CONFIG_FIEMAP)
+ #include <linux/fiemap.h>
+diff --git a/meson.build b/meson.build
+index 450c48a9f0..787f91855e 100644
+--- a/meson.build
++++ b/meson.build
+@@ -2032,8 +2032,6 @@ config_host_data.set('HAVE_OPTRESET',
+ cc.has_header_symbol('getopt.h', 'optreset'))
+ config_host_data.set('HAVE_IPPROTO_MPTCP',
+ cc.has_header_symbol('netinet/in.h', 'IPPROTO_MPTCP'))
+-config_host_data.set('HAVE_SYS_MOUNT_FSCONFIG',
+- cc.has_header_symbol('sys/mount.h', 'FSCONFIG_SET_FLAG'))
+
+ # has_member
+ config_host_data.set('HAVE_SIGEV_NOTIFY_THREAD_ID',
+diff --git a/migration/migration.c b/migration/migration.c
+index c19fb5cb3e..c8ca7927b4 100644
+--- a/migration/migration.c
++++ b/migration/migration.c
+@@ -1809,20 +1809,25 @@ void qmp_migrate_set_parameters(MigrateSetParameters *params, Error **errp)
+ {
+ MigrationParameters tmp;
+
+- /* TODO Rewrite "" to null instead */
++ /* TODO Rewrite "" to null instead for all three tls_* parameters */
+ if (params->has_tls_creds
+ && params->tls_creds->type == QTYPE_QNULL) {
+ qobject_unref(params->tls_creds->u.n);
+ params->tls_creds->type = QTYPE_QSTRING;
+ params->tls_creds->u.s = strdup("");
+ }
+- /* TODO Rewrite "" to null instead */
+ if (params->has_tls_hostname
+ && params->tls_hostname->type == QTYPE_QNULL) {
+ qobject_unref(params->tls_hostname->u.n);
+ params->tls_hostname->type = QTYPE_QSTRING;
+ params->tls_hostname->u.s = strdup("");
+ }
++ if (params->tls_authz
++ && params->tls_authz->type == QTYPE_QNULL) {
++ qobject_unref(params->tls_authz->u.n);
++ params->tls_authz->type = QTYPE_QSTRING;
++ params->tls_authz->u.s = strdup("");
++ }
+
+ migrate_params_test_apply(params, &tmp);
+
+diff --git a/pc-bios/optionrom/Makefile b/pc-bios/optionrom/Makefile
+index b1fff0ba6c..30d07026c7 100644
+--- a/pc-bios/optionrom/Makefile
++++ b/pc-bios/optionrom/Makefile
+@@ -36,7 +36,7 @@ config-cc.mak: Makefile
+ $(call cc-option,-Wno-array-bounds)) 3> config-cc.mak
+ -include config-cc.mak
+
+-override LDFLAGS = -nostdlib -Wl,-T,$(SRC_DIR)/flat.lds
++override LDFLAGS = -nostdlib -Wl,--build-id=none,-T,$(SRC_DIR)/flat.lds
+
+ pvh.img: pvh.o pvh_main.o
+
+diff --git a/qemu-img.c b/qemu-img.c
+index a9b3a8103c..2c32d9da4e 100644
+--- a/qemu-img.c
++++ b/qemu-img.c
+@@ -3753,6 +3753,8 @@ static int img_rebase(int argc, char **argv)
+ }
+
+ if (prefix_chain_bs) {
++ uint64_t bytes = n;
++
+ /*
+ * If cluster wasn't changed since prefix_chain, we don't need
+ * to take action
+@@ -3765,9 +3767,18 @@ static int img_rebase(int argc, char **argv)
+ strerror(-ret));
+ goto out;
+ }
+- if (!ret) {
++ if (!ret && n) {
+ continue;
+ }
++ if (!n) {
++ /*
++ * If we've reached EOF of the old backing, it means that
++ * offsets beyond the old backing size were read as zeroes.
++ * Now we will need to explicitly zero the cluster in
++ * order to preserve that state after the rebase.
++ */
++ n = bytes;
++ }
+ }
+
+ /*
+diff --git a/scripts/analyze-migration.py b/scripts/analyze-migration.py
+index b82a1b0c58..44d306aedc 100755
+--- a/scripts/analyze-migration.py
++++ b/scripts/analyze-migration.py
+@@ -38,13 +38,13 @@ def __init__(self, filename):
+ self.file = open(self.filename, "rb")
+
+ def read64(self):
+- return int.from_bytes(self.file.read(8), byteorder='big', signed=True)
++ return int.from_bytes(self.file.read(8), byteorder='big', signed=False)
+
+ def read32(self):
+- return int.from_bytes(self.file.read(4), byteorder='big', signed=True)
++ return int.from_bytes(self.file.read(4), byteorder='big', signed=False)
+
+ def read16(self):
+- return int.from_bytes(self.file.read(2), byteorder='big', signed=True)
++ return int.from_bytes(self.file.read(2), byteorder='big', signed=False)
+
+ def read8(self):
+ return int.from_bytes(self.file.read(1), byteorder='big', signed=True)
+diff --git a/scripts/tracetool/__init__.py b/scripts/tracetool/__init__.py
+index 5393c7fc5c..cd46e7597c 100644
+--- a/scripts/tracetool/__init__.py
++++ b/scripts/tracetool/__init__.py
+@@ -92,7 +92,7 @@ def out(*lines, **kwargs):
+ def validate_type(name):
+ bits = name.split(" ")
+ for bit in bits:
+- bit = re.sub("\*", "", bit)
++ bit = re.sub(r"\*", "", bit)
+ if bit == "":
+ continue
+ if bit == "const":
+diff --git a/target/arm/helper.c b/target/arm/helper.c
+index 22bc935242..a52ef3dfe4 100644
+--- a/target/arm/helper.c
++++ b/target/arm/helper.c
+@@ -11301,6 +11301,15 @@ static CPUARMTBFlags rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
+ && !(env->pstate & PSTATE_TCO)
+ && (sctlr & (el == 0 ? SCTLR_TCF0 : SCTLR_TCF))) {
+ DP_TBFLAG_A64(flags, MTE_ACTIVE, 1);
++ if (!EX_TBFLAG_A64(flags, UNPRIV)) {
++ /*
++ * In non-unpriv contexts (eg EL0), unpriv load/stores
++ * act like normal ones; duplicate the MTE info to
++ * avoid translate-a64.c having to check UNPRIV to see
++ * whether it is OK to index into MTE_ACTIVE[].
++ */
++ DP_TBFLAG_A64(flags, MTE0_ACTIVE, 1);
++ }
+ }
+ }
+ /* And again for unprivileged accesses, if required. */
+diff --git a/target/arm/internals.h b/target/arm/internals.h
+index 161e42d50f..3c7ff51c99 100644
+--- a/target/arm/internals.h
++++ b/target/arm/internals.h
+@@ -1129,7 +1129,6 @@ typedef struct ARMCacheAttrs {
+ unsigned int attrs:8;
+ unsigned int shareability:2; /* as in the SH field of the VMSAv8-64 PTEs */
+ bool is_s2_format:1;
+- bool guarded:1; /* guarded bit of the v8-64 PTE */
+ } ARMCacheAttrs;
+
+ /* Fields that are valid upon success. */
+diff --git a/target/arm/ptw.c b/target/arm/ptw.c
+index 0b16068557..be0cc3e347 100644
+--- a/target/arm/ptw.c
++++ b/target/arm/ptw.c
+@@ -103,6 +103,37 @@ ARMMMUIdx arm_stage1_mmu_idx(CPUARMState *env)
+ return stage_1_mmu_idx(arm_mmu_idx(env));
+ }
+
++/*
++ * Return where we should do ptw loads from for a stage 2 walk.
++ * This depends on whether the address we are looking up is a
++ * Secure IPA or a NonSecure IPA, which we know from whether this is
++ * Stage2 or Stage2_S.
++ * If this is the Secure EL1&0 regime we need to check the NSW and SW bits.
++ */
++static ARMMMUIdx ptw_idx_for_stage_2(CPUARMState *env, ARMMMUIdx stage2idx)
++{
++ bool s2walk_secure;
++
++ /*
++ * We're OK to check the current state of the CPU here because
++ * (1) we always invalidate all TLBs when the SCR_EL3.NS bit changes
++ * (2) there's no way to do a lookup that cares about Stage 2 for a
++ * different security state to the current one for AArch64, and AArch32
++ * never has a secure EL2. (AArch32 ATS12NSO[UP][RW] allow EL3 to do
++ * an NS stage 1+2 lookup while the NS bit is 0.)
++ */
++ if (!arm_is_secure_below_el3(env) || !arm_el_is_aa64(env, 3)) {
++ return ARMMMUIdx_Phys_NS;
++ }
++ if (stage2idx == ARMMMUIdx_Stage2_S) {
++ s2walk_secure = !(env->cp15.vstcr_el2 & VSTCR_SW);
++ } else {
++ s2walk_secure = !(env->cp15.vtcr_el2 & VTCR_NSW);
++ }
++ return s2walk_secure ? ARMMMUIdx_Phys_S : ARMMMUIdx_Phys_NS;
++
++}
++
+ static bool regime_translation_big_endian(CPUARMState *env, ARMMMUIdx mmu_idx)
+ {
+ return (regime_sctlr(env, mmu_idx) & SCTLR_EE) != 0;
+@@ -220,7 +251,6 @@ static bool S1_ptw_translate(CPUARMState *env, S1Translate *ptw,
+ ARMMMUIdx mmu_idx = ptw->in_mmu_idx;
+ ARMMMUIdx s2_mmu_idx = ptw->in_ptw_idx;
+ uint8_t pte_attrs;
+- bool pte_secure;
+
+ ptw->out_virt = addr;
+
+@@ -232,8 +262,8 @@ static bool S1_ptw_translate(CPUARMState *env, S1Translate *ptw,
+ if (regime_is_stage2(s2_mmu_idx)) {
+ S1Translate s2ptw = {
+ .in_mmu_idx = s2_mmu_idx,
+- .in_ptw_idx = is_secure ? ARMMMUIdx_Phys_S : ARMMMUIdx_Phys_NS,
+- .in_secure = is_secure,
++ .in_ptw_idx = ptw_idx_for_stage_2(env, s2_mmu_idx),
++ .in_secure = s2_mmu_idx == ARMMMUIdx_Stage2_S,
+ .in_debug = true,
+ };
+ GetPhysAddrResult s2 = { };
+@@ -244,16 +274,17 @@ static bool S1_ptw_translate(CPUARMState *env, S1Translate *ptw,
+ }
+ ptw->out_phys = s2.f.phys_addr;
+ pte_attrs = s2.cacheattrs.attrs;
+- pte_secure = s2.f.attrs.secure;
++ ptw->out_secure = s2.f.attrs.secure;
+ } else {
+ /* Regime is physical. */
+ ptw->out_phys = addr;
+ pte_attrs = 0;
+- pte_secure = is_secure;
++ ptw->out_secure = s2_mmu_idx == ARMMMUIdx_Phys_S;
+ }
+ ptw->out_host = NULL;
+ ptw->out_rw = false;
+ } else {
++#ifdef CONFIG_TCG
+ CPUTLBEntryFull *full;
+ int flags;
+
+@@ -269,7 +300,10 @@ static bool S1_ptw_translate(CPUARMState *env, S1Translate *ptw,
+ ptw->out_phys = full->phys_addr | (addr & ~TARGET_PAGE_MASK);
+ ptw->out_rw = full->prot & PAGE_WRITE;
+ pte_attrs = full->pte_attrs;
+- pte_secure = full->attrs.secure;
++ ptw->out_secure = full->attrs.secure;
++#else
++ g_assert_not_reached();
++#endif
+ }
+
+ if (regime_is_stage2(s2_mmu_idx)) {
+@@ -289,11 +323,6 @@ static bool S1_ptw_translate(CPUARMState *env, S1Translate *ptw,
+ }
+ }
+
+- /* Check if page table walk is to secure or non-secure PA space. */
+- ptw->out_secure = (is_secure
+- && !(pte_secure
+- ? env->cp15.vstcr_el2 & VSTCR_SW
+- : env->cp15.vtcr_el2 & VTCR_NSW));
+ ptw->out_be = regime_translation_big_endian(env, mmu_idx);
+ return true;
+
+@@ -1378,17 +1407,18 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
+ descaddrmask &= ~indexmask_grainsize;
+
+ /*
+- * Secure accesses start with the page table in secure memory and
++ * Secure stage 1 accesses start with the page table in secure memory and
+ * can be downgraded to non-secure at any step. Non-secure accesses
+ * remain non-secure. We implement this by just ORing in the NSTable/NS
+ * bits at each step.
++ * Stage 2 never gets this kind of downgrade.
+ */
+ tableattrs = is_secure ? 0 : (1 << 4);
+
+ next_level:
+ descaddr |= (address >> (stride * (4 - level))) & indexmask;
+ descaddr &= ~7ULL;
+- nstable = extract32(tableattrs, 4, 1);
++ nstable = !regime_is_stage2(mmu_idx) && extract32(tableattrs, 4, 1);
+ if (nstable) {
+ /*
+ * Stage2_S -> Stage2 or Phys_S -> Phys_NS
+@@ -2605,7 +2635,7 @@ static bool get_phys_addr_twostage(CPUARMState *env, S1Translate *ptw,
+ hwaddr ipa;
+ int s1_prot, s1_lgpgsz;
+ bool is_secure = ptw->in_secure;
+- bool ret, ipa_secure, s2walk_secure;
++ bool ret, ipa_secure, s1_guarded;
+ ARMCacheAttrs cacheattrs1;
+ bool is_el0;
+ uint64_t hcr;
+@@ -2619,20 +2649,11 @@ static bool get_phys_addr_twostage(CPUARMState *env, S1Translate *ptw,
+
+ ipa = result->f.phys_addr;
+ ipa_secure = result->f.attrs.secure;
+- if (is_secure) {
+- /* Select TCR based on the NS bit from the S1 walk. */
+- s2walk_secure = !(ipa_secure
+- ? env->cp15.vstcr_el2 & VSTCR_SW
+- : env->cp15.vtcr_el2 & VTCR_NSW);
+- } else {
+- assert(!ipa_secure);
+- s2walk_secure = false;
+- }
+
+ is_el0 = ptw->in_mmu_idx == ARMMMUIdx_Stage1_E0;
+- ptw->in_mmu_idx = s2walk_secure ? ARMMMUIdx_Stage2_S : ARMMMUIdx_Stage2;
+- ptw->in_ptw_idx = s2walk_secure ? ARMMMUIdx_Phys_S : ARMMMUIdx_Phys_NS;
+- ptw->in_secure = s2walk_secure;
++ ptw->in_mmu_idx = ipa_secure ? ARMMMUIdx_Stage2_S : ARMMMUIdx_Stage2;
++ ptw->in_secure = ipa_secure;
++ ptw->in_ptw_idx = ptw_idx_for_stage_2(env, ptw->in_mmu_idx);
+
+ /*
+ * S1 is done, now do S2 translation.
+@@ -2640,6 +2661,7 @@ static bool get_phys_addr_twostage(CPUARMState *env, S1Translate *ptw,
+ */
+ s1_prot = result->f.prot;
+ s1_lgpgsz = result->f.lg_page_size;
++ s1_guarded = result->f.guarded;
+ cacheattrs1 = result->cacheattrs;
+ memset(result, 0, sizeof(*result));
+
+@@ -2680,6 +2702,9 @@ static bool get_phys_addr_twostage(CPUARMState *env, S1Translate *ptw,
+ result->cacheattrs = combine_cacheattrs(hcr, cacheattrs1,
+ result->cacheattrs);
+
++ /* No BTI GP information in stage 2, we just use the S1 value */
++ result->f.guarded = s1_guarded;
++
+ /*
+ * Check if IPA translates to secure or non-secure PA space.
+ * Note that VSTCR overrides VTCR and {N}SW overrides {N}SA.
+@@ -2724,6 +2749,16 @@ static bool get_phys_addr_with_struct(CPUARMState *env, S1Translate *ptw,
+ ptw->in_ptw_idx = is_secure ? ARMMMUIdx_Stage2_S : ARMMMUIdx_Stage2;
+ break;
+
++ case ARMMMUIdx_Stage2:
++ case ARMMMUIdx_Stage2_S:
++ /*
++ * Second stage lookup uses physical for ptw; whether this is S or
++ * NS may depend on the SW/NSW bits if this is a stage 2 lookup for
++ * the Secure EL2&0 regime.
++ */
++ ptw->in_ptw_idx = ptw_idx_for_stage_2(env, mmu_idx);
++ break;
++
+ case ARMMMUIdx_E10_0:
+ s1_mmu_idx = ARMMMUIdx_Stage1_E0;
+ goto do_twostage;
+@@ -2747,7 +2782,7 @@ static bool get_phys_addr_with_struct(CPUARMState *env, S1Translate *ptw,
+ /* fall through */
+
+ default:
+- /* Single stage and second stage uses physical for ptw. */
++ /* Single stage uses physical for ptw. */
+ ptw->in_ptw_idx = is_secure ? ARMMMUIdx_Phys_S : ARMMMUIdx_Phys_NS;
+ break;
+ }
+diff --git a/target/i386/tcg/decode-new.c.inc b/target/i386/tcg/decode-new.c.inc
+index ee4f4a899f..528e2fdfbb 100644
+--- a/target/i386/tcg/decode-new.c.inc
++++ b/target/i386/tcg/decode-new.c.inc
+@@ -105,6 +105,7 @@
+ #define vex3 .vex_class = 3,
+ #define vex4 .vex_class = 4,
+ #define vex4_unal .vex_class = 4, .vex_special = X86_VEX_SSEUnaligned,
++#define vex4_rep5 .vex_class = 4, .vex_special = X86_VEX_REPScalar,
+ #define vex5 .vex_class = 5,
+ #define vex6 .vex_class = 6,
+ #define vex7 .vex_class = 7,
+@@ -236,7 +237,7 @@ static void decode_group14(DisasContext *s, CPUX86State *env, X86OpEntry *entry,
+ static void decode_0F6F(DisasContext *s, CPUX86State *env, X86OpEntry *entry, uint8_t *b)
+ {
+ static const X86OpEntry opcodes_0F6F[4] = {
+- X86_OP_ENTRY3(MOVDQ, P,q, None,None, Q,q, vex1 mmx), /* movq */
++ X86_OP_ENTRY3(MOVDQ, P,q, None,None, Q,q, vex5 mmx), /* movq */
+ X86_OP_ENTRY3(MOVDQ, V,x, None,None, W,x, vex1), /* movdqa */
+ X86_OP_ENTRY3(MOVDQ, V,x, None,None, W,x, vex4_unal), /* movdqu */
+ {},
+@@ -273,9 +274,9 @@ static void decode_0F78(DisasContext *s, CPUX86State *env, X86OpEntry *entry, ui
+ {
+ static const X86OpEntry opcodes_0F78[4] = {
+ {},
+- X86_OP_ENTRY3(EXTRQ_i, V,x, None,None, I,w, cpuid(SSE4A)),
++ X86_OP_ENTRY3(EXTRQ_i, V,x, None,None, I,w, cpuid(SSE4A)), /* AMD extension */
+ {},
+- X86_OP_ENTRY3(INSERTQ_i, V,x, U,x, I,w, cpuid(SSE4A)),
++ X86_OP_ENTRY3(INSERTQ_i, V,x, U,x, I,w, cpuid(SSE4A)), /* AMD extension */
+ };
+ *entry = *decode_by_prefix(s, opcodes_0F78);
+ }
+@@ -283,9 +284,9 @@ static void decode_0F78(DisasContext *s, CPUX86State *env, X86OpEntry *entry, ui
+ static void decode_0F79(DisasContext *s, CPUX86State *env, X86OpEntry *entry, uint8_t *b)
+ {
+ if (s->prefix & PREFIX_REPNZ) {
+- entry->gen = gen_INSERTQ_r;
++ entry->gen = gen_INSERTQ_r; /* AMD extension */
+ } else if (s->prefix & PREFIX_DATA) {
+- entry->gen = gen_EXTRQ_r;
++ entry->gen = gen_EXTRQ_r; /* AMD extension */
+ } else {
+ entry->gen = NULL;
+ };
+@@ -305,7 +306,7 @@ static void decode_0F7E(DisasContext *s, CPUX86State *env, X86OpEntry *entry, ui
+ static void decode_0F7F(DisasContext *s, CPUX86State *env, X86OpEntry *entry, uint8_t *b)
+ {
+ static const X86OpEntry opcodes_0F7F[4] = {
+- X86_OP_ENTRY3(MOVDQ, W,x, None,None, V,x, vex1 mmx), /* movq */
++ X86_OP_ENTRY3(MOVDQ, W,x, None,None, V,x, vex5 mmx), /* movq */
+ X86_OP_ENTRY3(MOVDQ, W,x, None,None, V,x, vex1), /* movdqa */
+ X86_OP_ENTRY3(MOVDQ, W,x, None,None, V,x, vex4_unal), /* movdqu */
+ {},
+@@ -336,7 +337,7 @@ static const X86OpEntry opcodes_0F38_00toEF[240] = {
+ [0x07] = X86_OP_ENTRY3(PHSUBSW, V,x, H,x, W,x, vex4 cpuid(SSSE3) mmx avx2_256 p_00_66),
+
+ [0x10] = X86_OP_ENTRY2(PBLENDVB, V,x, W,x, vex4 cpuid(SSE41) avx2_256 p_66),
+- [0x13] = X86_OP_ENTRY2(VCVTPH2PS, V,x, W,ph, vex11 cpuid(F16C) p_66),
++ [0x13] = X86_OP_ENTRY2(VCVTPH2PS, V,x, W,xh, vex11 cpuid(F16C) p_66),
+ [0x14] = X86_OP_ENTRY2(BLENDVPS, V,x, W,x, vex4 cpuid(SSE41) p_66),
+ [0x15] = X86_OP_ENTRY2(BLENDVPD, V,x, W,x, vex4 cpuid(SSE41) p_66),
+ /* Listed incorrectly as type 4 */
+@@ -564,7 +565,7 @@ static const X86OpEntry opcodes_0F3A[256] = {
+ [0x15] = X86_OP_ENTRY3(PEXTRW, E,w, V,dq, I,b, vex5 cpuid(SSE41) zext0 p_66),
+ [0x16] = X86_OP_ENTRY3(PEXTR, E,y, V,dq, I,b, vex5 cpuid(SSE41) p_66),
+ [0x17] = X86_OP_ENTRY3(VEXTRACTPS, E,d, V,dq, I,b, vex5 cpuid(SSE41) p_66),
+- [0x1d] = X86_OP_ENTRY3(VCVTPS2PH, W,ph, V,x, I,b, vex11 cpuid(F16C) p_66),
++ [0x1d] = X86_OP_ENTRY3(VCVTPS2PH, W,xh, V,x, I,b, vex11 cpuid(F16C) p_66),
+
+ [0x20] = X86_OP_ENTRY4(PINSRB, V,dq, H,dq, E,b, vex5 cpuid(SSE41) zext2 p_66),
+ [0x21] = X86_OP_GROUP0(VINSERTPS),
+@@ -638,15 +639,15 @@ static void decode_0F10(DisasContext *s, CPUX86State *env, X86OpEntry *entry, ui
+ static const X86OpEntry opcodes_0F10_reg[4] = {
+ X86_OP_ENTRY3(MOVDQ, V,x, None,None, W,x, vex4_unal), /* MOVUPS */
+ X86_OP_ENTRY3(MOVDQ, V,x, None,None, W,x, vex4_unal), /* MOVUPD */
+- X86_OP_ENTRY3(VMOVSS, V,x, H,x, W,x, vex4),
+- X86_OP_ENTRY3(VMOVLPx, V,x, H,x, W,x, vex4), /* MOVSD */
++ X86_OP_ENTRY3(VMOVSS, V,x, H,x, W,x, vex5),
++ X86_OP_ENTRY3(VMOVLPx, V,x, H,x, W,x, vex5), /* MOVSD */
+ };
+
+ static const X86OpEntry opcodes_0F10_mem[4] = {
+ X86_OP_ENTRY3(MOVDQ, V,x, None,None, W,x, vex4_unal), /* MOVUPS */
+ X86_OP_ENTRY3(MOVDQ, V,x, None,None, W,x, vex4_unal), /* MOVUPD */
+- X86_OP_ENTRY3(VMOVSS_ld, V,x, H,x, M,ss, vex4),
+- X86_OP_ENTRY3(VMOVSD_ld, V,x, H,x, M,sd, vex4),
++ X86_OP_ENTRY3(VMOVSS_ld, V,x, H,x, M,ss, vex5),
++ X86_OP_ENTRY3(VMOVSD_ld, V,x, H,x, M,sd, vex5),
+ };
+
+ if ((get_modrm(s, env) >> 6) == 3) {
+@@ -659,17 +660,17 @@ static void decode_0F10(DisasContext *s, CPUX86State *env, X86OpEntry *entry, ui
+ static void decode_0F11(DisasContext *s, CPUX86State *env, X86OpEntry *entry, uint8_t *b)
+ {
+ static const X86OpEntry opcodes_0F11_reg[4] = {
+- X86_OP_ENTRY3(MOVDQ, W,x, None,None, V,x, vex4), /* MOVPS */
+- X86_OP_ENTRY3(MOVDQ, W,x, None,None, V,x, vex4), /* MOVPD */
+- X86_OP_ENTRY3(VMOVSS, W,x, H,x, V,x, vex4),
+- X86_OP_ENTRY3(VMOVLPx, W,x, H,x, V,q, vex4), /* MOVSD */
++ X86_OP_ENTRY3(MOVDQ, W,x, None,None, V,x, vex4), /* MOVUPS */
++ X86_OP_ENTRY3(MOVDQ, W,x, None,None, V,x, vex4), /* MOVUPD */
++ X86_OP_ENTRY3(VMOVSS, W,x, H,x, V,x, vex5),
++ X86_OP_ENTRY3(VMOVLPx, W,x, H,x, V,q, vex5), /* MOVSD */
+ };
+
+ static const X86OpEntry opcodes_0F11_mem[4] = {
+- X86_OP_ENTRY3(MOVDQ, W,x, None,None, V,x, vex4), /* MOVPS */
+- X86_OP_ENTRY3(MOVDQ, W,x, None,None, V,x, vex4), /* MOVPD */
+- X86_OP_ENTRY3(VMOVSS_st, M,ss, None,None, V,x, vex4),
+- X86_OP_ENTRY3(VMOVLPx_st, M,sd, None,None, V,x, vex4), /* MOVSD */
++ X86_OP_ENTRY3(MOVDQ, W,x, None,None, V,x, vex4), /* MOVUPS */
++ X86_OP_ENTRY3(MOVDQ, W,x, None,None, V,x, vex4), /* MOVUPD */
++ X86_OP_ENTRY3(VMOVSS_st, M,ss, None,None, V,x, vex5),
++ X86_OP_ENTRY3(VMOVLPx_st, M,sd, None,None, V,x, vex5), /* MOVSD */
+ };
+
+ if ((get_modrm(s, env) >> 6) == 3) {
+@@ -686,16 +687,16 @@ static void decode_0F12(DisasContext *s, CPUX86State *env, X86OpEntry *entry, ui
+ * Use dq for operand for compatibility with gen_MOVSD and
+ * to allow VEX128 only.
+ */
+- X86_OP_ENTRY3(VMOVLPx_ld, V,dq, H,dq, M,q, vex4), /* MOVLPS */
+- X86_OP_ENTRY3(VMOVLPx_ld, V,dq, H,dq, M,q, vex4), /* MOVLPD */
++ X86_OP_ENTRY3(VMOVLPx_ld, V,dq, H,dq, M,q, vex5), /* MOVLPS */
++ X86_OP_ENTRY3(VMOVLPx_ld, V,dq, H,dq, M,q, vex5), /* MOVLPD */
+ X86_OP_ENTRY3(VMOVSLDUP, V,x, None,None, W,x, vex4 cpuid(SSE3)),
+- X86_OP_ENTRY3(VMOVDDUP, V,x, None,None, WM,q, vex4 cpuid(SSE3)), /* qq if VEX.256 */
++ X86_OP_ENTRY3(VMOVDDUP, V,x, None,None, WM,q, vex5 cpuid(SSE3)), /* qq if VEX.256 */
+ };
+ static const X86OpEntry opcodes_0F12_reg[4] = {
+- X86_OP_ENTRY3(VMOVHLPS, V,dq, H,dq, U,dq, vex4),
+- X86_OP_ENTRY3(VMOVLPx, W,x, H,x, U,q, vex4), /* MOVLPD */
++ X86_OP_ENTRY3(VMOVHLPS, V,dq, H,dq, U,dq, vex7),
++ X86_OP_ENTRY3(VMOVLPx, W,x, H,x, U,q, vex5), /* MOVLPD */
+ X86_OP_ENTRY3(VMOVSLDUP, V,x, None,None, U,x, vex4 cpuid(SSE3)),
+- X86_OP_ENTRY3(VMOVDDUP, V,x, None,None, U,x, vex4 cpuid(SSE3)),
++ X86_OP_ENTRY3(VMOVDDUP, V,x, None,None, U,x, vex5 cpuid(SSE3)),
+ };
+
+ if ((get_modrm(s, env) >> 6) == 3) {
+@@ -715,15 +716,15 @@ static void decode_0F16(DisasContext *s, CPUX86State *env, X86OpEntry *entry, ui
+ * Operand 1 technically only reads the low 64 bits, but uses dq so that
+ * it is easier to check for op0 == op1 in an endianness-neutral manner.
+ */
+- X86_OP_ENTRY3(VMOVHPx_ld, V,dq, H,dq, M,q, vex4), /* MOVHPS */
+- X86_OP_ENTRY3(VMOVHPx_ld, V,dq, H,dq, M,q, vex4), /* MOVHPD */
++ X86_OP_ENTRY3(VMOVHPx_ld, V,dq, H,dq, M,q, vex5), /* MOVHPS */
++ X86_OP_ENTRY3(VMOVHPx_ld, V,dq, H,dq, M,q, vex5), /* MOVHPD */
+ X86_OP_ENTRY3(VMOVSHDUP, V,x, None,None, W,x, vex4 cpuid(SSE3)),
+ {},
+ };
+ static const X86OpEntry opcodes_0F16_reg[4] = {
+ /* Same as above, operand 1 could be Hq if it wasn't for big-endian. */
+- X86_OP_ENTRY3(VMOVLHPS, V,dq, H,dq, U,q, vex4),
+- X86_OP_ENTRY3(VMOVHPx, V,x, H,x, U,x, vex4), /* MOVHPD */
++ X86_OP_ENTRY3(VMOVLHPS, V,dq, H,dq, U,q, vex7),
++ X86_OP_ENTRY3(VMOVHPx, V,x, H,x, U,x, vex5), /* MOVHPD */
+ X86_OP_ENTRY3(VMOVSHDUP, V,x, None,None, U,x, vex4 cpuid(SSE3)),
+ {},
+ };
+@@ -749,8 +750,9 @@ static void decode_0F2A(DisasContext *s, CPUX86State *env, X86OpEntry *entry, ui
+ static void decode_0F2B(DisasContext *s, CPUX86State *env, X86OpEntry *entry, uint8_t *b)
+ {
+ static const X86OpEntry opcodes_0F2B[4] = {
+- X86_OP_ENTRY3(MOVDQ, M,x, None,None, V,x, vex4), /* MOVNTPS */
+- X86_OP_ENTRY3(MOVDQ, M,x, None,None, V,x, vex4), /* MOVNTPD */
++ X86_OP_ENTRY3(MOVDQ, M,x, None,None, V,x, vex1), /* MOVNTPS */
++ X86_OP_ENTRY3(MOVDQ, M,x, None,None, V,x, vex1), /* MOVNTPD */
++ /* AMD extensions */
+ X86_OP_ENTRY3(VMOVSS_st, M,ss, None,None, V,x, vex4 cpuid(SSE4A)), /* MOVNTSS */
+ X86_OP_ENTRY3(VMOVLPx_st, M,sd, None,None, V,x, vex4 cpuid(SSE4A)), /* MOVNTSD */
+ };
+@@ -803,10 +805,20 @@ static void decode_sse_unary(DisasContext *s, CPUX86State *env, X86OpEntry *entr
+ case 0x51: entry->gen = gen_VSQRT; break;
+ case 0x52: entry->gen = gen_VRSQRT; break;
+ case 0x53: entry->gen = gen_VRCP; break;
+- case 0x5A: entry->gen = gen_VCVTfp2fp; break;
+ }
+ }
+
++static void decode_0F5A(DisasContext *s, CPUX86State *env, X86OpEntry *entry, uint8_t *b)
++{
++ static const X86OpEntry opcodes_0F5A[4] = {
++ X86_OP_ENTRY2(VCVTPS2PD, V,x, W,xh, vex2), /* VCVTPS2PD */
++ X86_OP_ENTRY2(VCVTPD2PS, V,x, W,x, vex2), /* VCVTPD2PS */
++ X86_OP_ENTRY3(VCVTSS2SD, V,x, H,x, W,x, vex2_rep3), /* VCVTSS2SD */
++ X86_OP_ENTRY3(VCVTSD2SS, V,x, H,x, W,x, vex2_rep3), /* VCVTSD2SS */
++ };
++ *entry = *decode_by_prefix(s, opcodes_0F5A);
++}
++
+ static void decode_0F5B(DisasContext *s, CPUX86State *env, X86OpEntry *entry, uint8_t *b)
+ {
+ static const X86OpEntry opcodes_0F5B[4] = {
+@@ -823,7 +835,7 @@ static void decode_0FE6(DisasContext *s, CPUX86State *env, X86OpEntry *entry, ui
+ static const X86OpEntry opcodes_0FE6[4] = {
+ {},
+ X86_OP_ENTRY2(VCVTTPD2DQ, V,x, W,x, vex2),
+- X86_OP_ENTRY2(VCVTDQ2PD, V,x, W,x, vex2),
++ X86_OP_ENTRY2(VCVTDQ2PD, V,x, W,x, vex5),
+ X86_OP_ENTRY2(VCVTPD2DQ, V,x, W,x, vex2),
+ };
+ *entry = *decode_by_prefix(s, opcodes_0FE6);
+@@ -841,17 +853,17 @@ static const X86OpEntry opcodes_0F[256] = {
+ [0x10] = X86_OP_GROUP0(0F10),
+ [0x11] = X86_OP_GROUP0(0F11),
+ [0x12] = X86_OP_GROUP0(0F12),
+- [0x13] = X86_OP_ENTRY3(VMOVLPx_st, M,q, None,None, V,q, vex4 p_00_66),
++ [0x13] = X86_OP_ENTRY3(VMOVLPx_st, M,q, None,None, V,q, vex5 p_00_66),
+ [0x14] = X86_OP_ENTRY3(VUNPCKLPx, V,x, H,x, W,x, vex4 p_00_66),
+ [0x15] = X86_OP_ENTRY3(VUNPCKHPx, V,x, H,x, W,x, vex4 p_00_66),
+ [0x16] = X86_OP_GROUP0(0F16),
+ /* Incorrectly listed as Mq,Vq in the manual */
+- [0x17] = X86_OP_ENTRY3(VMOVHPx_st, M,q, None,None, V,dq, vex4 p_00_66),
++ [0x17] = X86_OP_ENTRY3(VMOVHPx_st, M,q, None,None, V,dq, vex5 p_00_66),
+
+ [0x50] = X86_OP_ENTRY3(MOVMSK, G,y, None,None, U,x, vex7 p_00_66),
+- [0x51] = X86_OP_GROUP3(sse_unary, V,x, H,x, W,x, vex2_rep3 p_00_66_f3_f2),
+- [0x52] = X86_OP_GROUP3(sse_unary, V,x, H,x, W,x, vex5 p_00_f3),
+- [0x53] = X86_OP_GROUP3(sse_unary, V,x, H,x, W,x, vex5 p_00_f3),
++ [0x51] = X86_OP_GROUP3(sse_unary, V,x, H,x, W,x, vex2_rep3 p_00_66_f3_f2), /* sqrtps */
++ [0x52] = X86_OP_GROUP3(sse_unary, V,x, H,x, W,x, vex4_rep5 p_00_f3), /* rsqrtps */
++ [0x53] = X86_OP_GROUP3(sse_unary, V,x, H,x, W,x, vex4_rep5 p_00_f3), /* rcpps */
+ [0x54] = X86_OP_ENTRY3(PAND, V,x, H,x, W,x, vex4 p_00_66), /* vand */
+ [0x55] = X86_OP_ENTRY3(PANDN, V,x, H,x, W,x, vex4 p_00_66), /* vandn */
+ [0x56] = X86_OP_ENTRY3(POR, V,x, H,x, W,x, vex4 p_00_66), /* vor */
+@@ -889,7 +901,7 @@ static const X86OpEntry opcodes_0F[256] = {
+
+ [0x58] = X86_OP_ENTRY3(VADD, V,x, H,x, W,x, vex2_rep3 p_00_66_f3_f2),
+ [0x59] = X86_OP_ENTRY3(VMUL, V,x, H,x, W,x, vex2_rep3 p_00_66_f3_f2),
+- [0x5a] = X86_OP_GROUP3(sse_unary, V,x, H,x, W,x, vex3 p_00_66_f3_f2),
++ [0x5a] = X86_OP_GROUP0(0F5A),
+ [0x5b] = X86_OP_GROUP0(0F5B),
+ [0x5c] = X86_OP_ENTRY3(VSUB, V,x, H,x, W,x, vex2_rep3 p_00_66_f3_f2),
+ [0x5d] = X86_OP_ENTRY3(VMIN, V,x, H,x, W,x, vex2_rep3 p_00_66_f3_f2),
+@@ -1102,7 +1114,7 @@ static bool decode_op_size(DisasContext *s, X86OpEntry *e, X86OpSize size, MemOp
+ *ot = s->vex_l ? MO_256 : MO_128;
+ return true;
+
+- case X86_SIZE_ph: /* SSE/AVX packed half precision */
++ case X86_SIZE_xh: /* SSE/AVX packed half register */
+ *ot = s->vex_l ? MO_128 : MO_64;
+ return true;
+
+@@ -1458,9 +1470,9 @@ static bool validate_vex(DisasContext *s, X86DecodedInsn *decode)
+ * Instructions which differ between 00/66 and F2/F3 in the
+ * exception classification and the size of the memory operand.
+ */
+- assert(e->vex_class == 1 || e->vex_class == 2);
++ assert(e->vex_class == 1 || e->vex_class == 2 || e->vex_class == 4);
+ if (s->prefix & (PREFIX_REPZ | PREFIX_REPNZ)) {
+- e->vex_class = 3;
++ e->vex_class = e->vex_class < 4 ? 3 : 5;
+ if (s->vex_l) {
+ goto illegal;
+ }
+diff --git a/target/i386/tcg/decode-new.h b/target/i386/tcg/decode-new.h
+index cb6b8bcf67..a542ec1681 100644
+--- a/target/i386/tcg/decode-new.h
++++ b/target/i386/tcg/decode-new.h
+@@ -92,7 +92,7 @@ typedef enum X86OpSize {
+ /* Custom */
+ X86_SIZE_d64,
+ X86_SIZE_f64,
+- X86_SIZE_ph, /* SSE/AVX packed half precision */
++ X86_SIZE_xh, /* SSE/AVX packed half register */
+ } X86OpSize;
+
+ typedef enum X86CPUIDFeature {
+diff --git a/target/i386/tcg/emit.c.inc b/target/i386/tcg/emit.c.inc
+index 5d31fce65d..d6a9de8b3d 100644
+--- a/target/i386/tcg/emit.c.inc
++++ b/target/i386/tcg/emit.c.inc
+@@ -1917,12 +1917,22 @@ static void gen_VCOMI(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+ set_cc_op(s, CC_OP_EFLAGS);
+ }
+
+-static void gen_VCVTfp2fp(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
++static void gen_VCVTPD2PS(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+ {
+- gen_unary_fp_sse(s, env, decode,
+- gen_helper_cvtpd2ps_xmm, gen_helper_cvtps2pd_xmm,
+- gen_helper_cvtpd2ps_ymm, gen_helper_cvtps2pd_ymm,
+- gen_helper_cvtsd2ss, gen_helper_cvtss2sd);
++ if (s->vex_l) {
++ gen_helper_cvtpd2ps_ymm(cpu_env, OP_PTR0, OP_PTR2);
++ } else {
++ gen_helper_cvtpd2ps_xmm(cpu_env, OP_PTR0, OP_PTR2);
++ }
++}
++
++static void gen_VCVTPS2PD(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
++{
++ if (s->vex_l) {
++ gen_helper_cvtps2pd_ymm(cpu_env, OP_PTR0, OP_PTR2);
++ } else {
++ gen_helper_cvtps2pd_xmm(cpu_env, OP_PTR0, OP_PTR2);
++ }
+ }
+
+ static void gen_VCVTPS2PH(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+@@ -1939,6 +1949,16 @@ static void gen_VCVTPS2PH(DisasContext *s, CPUX86State *env, X86DecodedInsn *dec
+ }
+ }
+
++static void gen_VCVTSD2SS(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
++{
++ gen_helper_cvtsd2ss(cpu_env, OP_PTR0, OP_PTR1, OP_PTR2);
++}
++
++static void gen_VCVTSS2SD(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
++{
++ gen_helper_cvtss2sd(cpu_env, OP_PTR0, OP_PTR1, OP_PTR2);
++}
++
+ static void gen_VCVTSI2Sx(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+ {
+ int vec_len = vector_len(s, decode);
+diff --git a/target/mips/tcg/msa.decode b/target/mips/tcg/msa.decode
+index 9575289195..4410e2a02e 100644
+--- a/target/mips/tcg/msa.decode
++++ b/target/mips/tcg/msa.decode
+@@ -31,8 +31,8 @@
+
+ @lsa ...... rs:5 rt:5 rd:5 ... sa:2 ...... &r
+ @ldst ...... sa:s10 ws:5 wd:5 .... df:2 &msa_i
+-@bz_v ...... ... .. wt:5 sa:16 &msa_bz df=3
+-@bz ...... ... df:2 wt:5 sa:16 &msa_bz
++@bz_v ...... ... .. wt:5 sa:s16 &msa_bz df=3
++@bz ...... ... df:2 wt:5 sa:s16 &msa_bz
+ @elm_df ...... .... ...... ws:5 wd:5 ...... &msa_elm_df df=%elm_df n=%elm_n
+ @elm ...... .......... ws:5 wd:5 ...... &msa_elm
+ @vec ...... ..... wt:5 ws:5 wd:5 ...... &msa_r df=0
+diff --git a/target/mips/tcg/tx79.decode b/target/mips/tcg/tx79.decode
+index 57d87a2076..578b8c54c0 100644
+--- a/target/mips/tcg/tx79.decode
++++ b/target/mips/tcg/tx79.decode
+@@ -24,7 +24,7 @@
+ @rs ...... rs:5 ..... .......... ...... &r sa=0 rt=0 rd=0
+ @rd ...... .......... rd:5 ..... ...... &r sa=0 rs=0 rt=0
+
+-@ldst ...... base:5 rt:5 offset:16 &i
++@ldst ...... base:5 rt:5 offset:s16 &i
+
+ ###########################################################################
+
+diff --git a/target/s390x/tcg/insn-data.h.inc b/target/s390x/tcg/insn-data.h.inc
+index 0e328ea0fd..7c3362d2e7 100644
+--- a/target/s390x/tcg/insn-data.h.inc
++++ b/target/s390x/tcg/insn-data.h.inc
+@@ -442,7 +442,7 @@
+ D(0xebe8, LAAG, RSY_a, ILA, r3, a2, new, in2_r1, laa, adds64, MO_TEUQ)
+ /* LOAD AND ADD LOGICAL */
+ D(0xebfa, LAAL, RSY_a, ILA, r3_32u, a2, new, in2_r1_32, laa, addu32, MO_TEUL)
+- D(0xebea, LAALG, RSY_a, ILA, r3, a2, new, in2_r1, laa, addu64, MO_TEUQ)
++ D(0xebea, LAALG, RSY_a, ILA, r3, a2, new, in2_r1, laa_addu64, addu64, MO_TEUQ)
+ /* LOAD AND AND */
+ D(0xebf4, LAN, RSY_a, ILA, r3_32s, a2, new, in2_r1_32, lan, nz32, MO_TESL)
+ D(0xebe4, LANG, RSY_a, ILA, r3, a2, new, in2_r1, lan, nz64, MO_TEUQ)
+diff --git a/target/s390x/tcg/translate.c b/target/s390x/tcg/translate.c
+index ff64d6c28f..b0173e968e 100644
+--- a/target/s390x/tcg/translate.c
++++ b/target/s390x/tcg/translate.c
+@@ -2809,17 +2809,32 @@ static DisasJumpType op_kxb(DisasContext *s, DisasOps *o)
+ return DISAS_NEXT;
+ }
+
+-static DisasJumpType op_laa(DisasContext *s, DisasOps *o)
++static DisasJumpType help_laa(DisasContext *s, DisasOps *o, bool addu64)
+ {
+ /* The real output is indeed the original value in memory;
+ recompute the addition for the computation of CC. */
+ tcg_gen_atomic_fetch_add_i64(o->in2, o->in2, o->in1, get_mem_index(s),
+ s->insn->data | MO_ALIGN);
+ /* However, we need to recompute the addition for setting CC. */
+- tcg_gen_add_i64(o->out, o->in1, o->in2);
++ if (addu64) {
++ tcg_gen_movi_i64(cc_src, 0);
++ tcg_gen_add2_i64(o->out, cc_src, o->in1, cc_src, o->in2, cc_src);
++ } else {
++ tcg_gen_add_i64(o->out, o->in1, o->in2);
++ }
+ return DISAS_NEXT;
+ }
+
++static DisasJumpType op_laa(DisasContext *s, DisasOps *o)
++{
++ return help_laa(s, o, false);
++}
++
++static DisasJumpType op_laa_addu64(DisasContext *s, DisasOps *o)
++{
++ return help_laa(s, o, true);
++}
++
+ static DisasJumpType op_lan(DisasContext *s, DisasOps *o)
+ {
+ /* The real output is indeed the original value in memory;
+diff --git a/target/tricore/cpu.c b/target/tricore/cpu.c
+index 2c54a2825f..0594d3843b 100644
+--- a/target/tricore/cpu.c
++++ b/target/tricore/cpu.c
+@@ -100,14 +100,14 @@ static void tricore_cpu_realizefn(DeviceState *dev, Error **errp)
+ }
+
+ /* Some features automatically imply others */
+- if (tricore_feature(env, TRICORE_FEATURE_161)) {
++ if (tricore_has_feature(env, TRICORE_FEATURE_161)) {
+ set_feature(env, TRICORE_FEATURE_16);
+ }
+
+- if (tricore_feature(env, TRICORE_FEATURE_16)) {
++ if (tricore_has_feature(env, TRICORE_FEATURE_16)) {
+ set_feature(env, TRICORE_FEATURE_131);
+ }
+- if (tricore_feature(env, TRICORE_FEATURE_131)) {
++ if (tricore_has_feature(env, TRICORE_FEATURE_131)) {
+ set_feature(env, TRICORE_FEATURE_13);
+ }
+ cpu_reset(cs);
+diff --git a/target/tricore/cpu.h b/target/tricore/cpu.h
+index 3b9c533a7c..2e122b44a7 100644
+--- a/target/tricore/cpu.h
++++ b/target/tricore/cpu.h
+@@ -269,7 +269,7 @@ enum tricore_features {
+ TRICORE_FEATURE_161,
+ };
+
+-static inline int tricore_feature(CPUTriCoreState *env, int feature)
++static inline int tricore_has_feature(CPUTriCoreState *env, int feature)
+ {
+ return (env->features & (1ULL << feature)) != 0;
+ }
+diff --git a/target/tricore/op_helper.c b/target/tricore/op_helper.c
+index 532ae6b74c..676529f754 100644
+--- a/target/tricore/op_helper.c
++++ b/target/tricore/op_helper.c
+@@ -2528,7 +2528,7 @@ void helper_ret(CPUTriCoreState *env)
+ /* PCXI = new_PCXI; */
+ env->PCXI = new_PCXI;
+
+- if (tricore_feature(env, TRICORE_FEATURE_13)) {
++ if (tricore_has_feature(env, TRICORE_FEATURE_13)) {
+ /* PSW = new_PSW */
+ psw_write(env, new_PSW);
+ } else {
+@@ -2639,7 +2639,7 @@ void helper_rfm(CPUTriCoreState *env)
+ env->gpr_a[10] = cpu_ldl_data(env, env->DCX+8);
+ env->gpr_a[11] = cpu_ldl_data(env, env->DCX+12);
+
+- if (tricore_feature(env, TRICORE_FEATURE_131)) {
++ if (tricore_has_feature(env, TRICORE_FEATURE_131)) {
+ env->DBGTCR = 0;
+ }
+ }
+diff --git a/tests/migration/s390x/Makefile b/tests/migration/s390x/Makefile
+index 6393c3e5b9..6671de2efc 100644
+--- a/tests/migration/s390x/Makefile
++++ b/tests/migration/s390x/Makefile
+@@ -6,8 +6,8 @@ all: a-b-bios.h
+ fwdir=../../../pc-bios/s390-ccw
+
+ CFLAGS+=-ffreestanding -fno-delete-null-pointer-checks -fPIE -Os \
+- -msoft-float -march=z900 -fno-asynchronous-unwind-tables -Wl,-pie \
+- -Wl,--build-id=none -nostdlib
++ -msoft-float -march=z900 -fno-asynchronous-unwind-tables \
++ -fno-stack-protector -Wl,-pie -Wl,--build-id=none -nostdlib
+
+ a-b-bios.h: s390x.elf
+ echo "$$__note" > header.tmp
+diff --git a/tests/qemu-iotests/024 b/tests/qemu-iotests/024
+index 25a564a150..98a7c8fd65 100755
+--- a/tests/qemu-iotests/024
++++ b/tests/qemu-iotests/024
+@@ -199,6 +199,63 @@ echo
+ # $BASE_OLD and $BASE_NEW)
+ $QEMU_IMG map "$OVERLAY" | _filter_qemu_img_map
+
++# Check that rebase within the chain is working when
++# overlay_size > old_backing_size
++#
++# base_new <-- base_old <-- overlay
++#
++# Backing (new): 11 11 11 11 11
++# Backing (old): 22 22 22 22
++# Overlay: -- -- -- -- --
++#
++# As a result, overlay should contain data identical to base_old, with the
++# last cluster remaining unallocated.
++
++echo
++echo "=== Test rebase within one backing chain ==="
++echo
++
++echo "Creating backing chain"
++echo
++
++TEST_IMG=$BASE_NEW _make_test_img $(( CLUSTER_SIZE * 5 ))
++TEST_IMG=$BASE_OLD _make_test_img -b "$BASE_NEW" -F $IMGFMT \
++ $(( CLUSTER_SIZE * 4 ))
++TEST_IMG=$OVERLAY _make_test_img -b "$BASE_OLD" -F $IMGFMT \
++ $(( CLUSTER_SIZE * 5 ))
++
++echo
++echo "Fill backing files with data"
++echo
++
++$QEMU_IO "$BASE_NEW" -c "write -P 0x11 0 $(( CLUSTER_SIZE * 5 ))" \
++ | _filter_qemu_io
++$QEMU_IO "$BASE_OLD" -c "write -P 0x22 0 $(( CLUSTER_SIZE * 4 ))" \
++ | _filter_qemu_io
++
++echo
++echo "Check the last cluster is zeroed in overlay before the rebase"
++echo
++$QEMU_IO "$OVERLAY" -c "read -P 0x00 $(( CLUSTER_SIZE * 4 )) $CLUSTER_SIZE" \
++ | _filter_qemu_io
++
++echo
++echo "Rebase onto another image in the same chain"
++echo
++
++$QEMU_IMG rebase -b "$BASE_NEW" -F $IMGFMT "$OVERLAY"
++
++echo "Verify that data is read the same before and after rebase"
++echo
++
++# Verify the first 4 clusters are still read the same as in the old base
++$QEMU_IO "$OVERLAY" -c "read -P 0x22 0 $(( CLUSTER_SIZE * 4 ))" \
++ | _filter_qemu_io
++# Verify the last cluster still reads as zeroes
++$QEMU_IO "$OVERLAY" -c "read -P 0x00 $(( CLUSTER_SIZE * 4 )) $CLUSTER_SIZE" \
++ | _filter_qemu_io
++
++echo
+
+ # success, all done
+ echo "*** done"
+diff --git a/tests/qemu-iotests/024.out b/tests/qemu-iotests/024.out
+index 973a5a3711..245fe8b1d1 100644
+--- a/tests/qemu-iotests/024.out
++++ b/tests/qemu-iotests/024.out
+@@ -171,4 +171,34 @@ read 65536/65536 bytes at offset 196608
+ Offset Length File
+ 0 0x30000 TEST_DIR/subdir/t.IMGFMT
+ 0x30000 0x10000 TEST_DIR/subdir/t.IMGFMT.base_new
++
++=== Test rebase within one backing chain ===
++
++Creating backing chain
++
++Formatting 'TEST_DIR/subdir/t.IMGFMT.base_new', fmt=IMGFMT size=327680
++Formatting 'TEST_DIR/subdir/t.IMGFMT.base_old', fmt=IMGFMT size=262144 backing_file=TEST_DIR/subdir/t.IMGFMT.base_new backing_fmt=IMGFMT
++Formatting 'TEST_DIR/subdir/t.IMGFMT', fmt=IMGFMT size=327680 backing_file=TEST_DIR/subdir/t.IMGFMT.base_old backing_fmt=IMGFMT
++
++Fill backing files with data
++
++wrote 327680/327680 bytes at offset 0
++320 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
++wrote 262144/262144 bytes at offset 0
++256 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
++
++Check the last cluster is zeroed in overlay before the rebase
++
++read 65536/65536 bytes at offset 262144
++64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
++
++Rebase onto another image in the same chain
++
++Verify that data is read the same before and after rebase
++
++read 262144/262144 bytes at offset 0
++256 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
++read 65536/65536 bytes at offset 262144
++64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
++
+ *** done
+diff --git a/tests/qtest/ahci-test.c b/tests/qtest/ahci-test.c
+index 66652fed04..388223291f 100644
+--- a/tests/qtest/ahci-test.c
++++ b/tests/qtest/ahci-test.c
+@@ -1424,6 +1424,89 @@ static void test_reset(void)
+ ahci_shutdown(ahci);
+ }
+
++static void test_reset_pending_callback(void)
++{
++ AHCIQState *ahci;
++ AHCICommand *cmd;
++ uint8_t port;
++ uint64_t ptr1;
++ uint64_t ptr2;
++
++ int bufsize = 4 * 1024;
++ int speed = bufsize + (bufsize / 2);
++ int offset1 = 0;
++ int offset2 = bufsize / AHCI_SECTOR_SIZE;
++
++ g_autofree unsigned char *tx1 = g_malloc(bufsize);
++ g_autofree unsigned char *tx2 = g_malloc(bufsize);
++ g_autofree unsigned char *rx1 = g_malloc0(bufsize);
++ g_autofree unsigned char *rx2 = g_malloc0(bufsize);
++
++ /* Uses throttling to make test independent of specific environment. */
++ ahci = ahci_boot_and_enable("-drive if=none,id=drive0,file=%s,"
++ "cache=writeback,format=%s,"
++ "throttling.bps-write=%d "
++ "-M q35 "
++ "-device ide-hd,drive=drive0 ",
++ tmp_path, imgfmt, speed);
++
++ port = ahci_port_select(ahci);
++ ahci_port_clear(ahci, port);
++
++ ptr1 = ahci_alloc(ahci, bufsize);
++ ptr2 = ahci_alloc(ahci, bufsize);
++
++ g_assert(ptr1 && ptr2);
++
++ /* Need two different patterns. */
++ do {
++ generate_pattern(tx1, bufsize, AHCI_SECTOR_SIZE);
++ generate_pattern(tx2, bufsize, AHCI_SECTOR_SIZE);
++ } while (memcmp(tx1, tx2, bufsize) == 0);
++
++ qtest_bufwrite(ahci->parent->qts, ptr1, tx1, bufsize);
++ qtest_bufwrite(ahci->parent->qts, ptr2, tx2, bufsize);
++
++ /* Write to beginning of disk to check it wasn't overwritten later. */
++ ahci_guest_io(ahci, port, CMD_WRITE_DMA_EXT, ptr1, bufsize, offset1);
++
++ /* Issue asynchronously to get a pending callback during reset. */
++ cmd = ahci_command_create(CMD_WRITE_DMA_EXT);
++ ahci_command_adjust(cmd, offset2, ptr2, bufsize, 0);
++ ahci_command_commit(ahci, cmd, port);
++ ahci_command_issue_async(ahci, cmd);
++
++ ahci_set(ahci, AHCI_GHC, AHCI_GHC_HR);
++
++ ahci_command_free(cmd);
++
++ /* Wait for throttled write to finish. */
++ sleep(1);
++
++ /* Start again. */
++ ahci_clean_mem(ahci);
++ ahci_pci_enable(ahci);
++ ahci_hba_enable(ahci);
++ port = ahci_port_select(ahci);
++ ahci_port_clear(ahci, port);
++
++ /* Read and verify. */
++ ahci_guest_io(ahci, port, CMD_READ_DMA_EXT, ptr1, bufsize, offset1);
++ qtest_bufread(ahci->parent->qts, ptr1, rx1, bufsize);
++ g_assert_cmphex(memcmp(tx1, rx1, bufsize), ==, 0);
++
++ ahci_guest_io(ahci, port, CMD_READ_DMA_EXT, ptr2, bufsize, offset2);
++ qtest_bufread(ahci->parent->qts, ptr2, rx2, bufsize);
++ g_assert_cmphex(memcmp(tx2, rx2, bufsize), ==, 0);
++
++ ahci_free(ahci, ptr1);
++ ahci_free(ahci, ptr2);
++
++ ahci_clean_mem(ahci);
++
++ ahci_shutdown(ahci);
++}
++
+ static void test_ncq_simple(void)
+ {
+ AHCIQState *ahci;
+@@ -1943,7 +2026,8 @@ int main(int argc, char **argv)
+ qtest_add_func("/ahci/migrate/dma/halted", test_migrate_halted_dma);
+
+ qtest_add_func("/ahci/max", test_max);
+- qtest_add_func("/ahci/reset", test_reset);
++ qtest_add_func("/ahci/reset/simple", test_reset);
++ qtest_add_func("/ahci/reset/pending_callback", test_reset_pending_callback);
+
+ qtest_add_func("/ahci/io/ncq/simple", test_ncq_simple);
+ qtest_add_func("/ahci/migrate/ncq/simple", test_migrate_ncq);
+diff --git a/tests/tcg/Makefile.target b/tests/tcg/Makefile.target
+index 14bc013181..368a053392 100644
+--- a/tests/tcg/Makefile.target
++++ b/tests/tcg/Makefile.target
+@@ -123,7 +123,7 @@ else
+ # For softmmu targets we include a different Makefile fragement as the
+ # build options for bare programs are usually pretty different. They
+ # are expected to provide their own build recipes.
+-EXTRA_CFLAGS += -ffreestanding
++EXTRA_CFLAGS += -ffreestanding -fno-stack-protector
+ -include $(SRC_PATH)/tests/tcg/minilib/Makefile.target
+ -include $(SRC_PATH)/tests/tcg/multiarch/system/Makefile.softmmu-target
+ -include $(SRC_PATH)/tests/tcg/$(TARGET_NAME)/Makefile.softmmu-target
+diff --git a/tests/tcg/aarch64/Makefile.target b/tests/tcg/aarch64/Makefile.target
+index fc8d90ed69..a72578fccb 100644
+--- a/tests/tcg/aarch64/Makefile.target
++++ b/tests/tcg/aarch64/Makefile.target
+@@ -38,7 +38,7 @@ endif
+ # bti-1 tests the elf notes, so we require special compiler support.
+ ifneq ($(CROSS_CC_HAS_ARMV8_BTI),)
+ AARCH64_TESTS += bti-1 bti-3
+-bti-1 bti-3: CFLAGS += -mbranch-protection=standard
++bti-1 bti-3: CFLAGS += -fno-stack-protector -mbranch-protection=standard
+ bti-1 bti-3: LDFLAGS += -nostdlib
+ endif
+ # bti-2 tests PROT_BTI, so no special compiler support required.
+diff --git a/tests/tcg/arm/Makefile.target b/tests/tcg/arm/Makefile.target
+index b3b1504a1c..6b69672fcf 100644
+--- a/tests/tcg/arm/Makefile.target
++++ b/tests/tcg/arm/Makefile.target
+@@ -12,7 +12,7 @@ float_madds: CFLAGS+=-mfpu=neon-vfpv4
+
+ # Basic Hello World
+ ARM_TESTS = hello-arm
+-hello-arm: CFLAGS+=-marm -ffreestanding
++hello-arm: CFLAGS+=-marm -ffreestanding -fno-stack-protector
+ hello-arm: LDFLAGS+=-nostdlib
+
+ # IWMXT floating point extensions
+diff --git a/tests/tcg/cris/Makefile.target b/tests/tcg/cris/Makefile.target
+index 372287bd03..ea1053236f 100644
+--- a/tests/tcg/cris/Makefile.target
++++ b/tests/tcg/cris/Makefile.target
+@@ -30,7 +30,7 @@ AS = $(CC) -x assembler-with-cpp
+ LD = $(CC)
+
+ # we rely on GCC inline:ing the stuff we tell it to in many places here.
+-CFLAGS = -Winline -Wall -g -O2 -static
++CFLAGS = -Winline -Wall -g -O2 -static -fno-stack-protector
+ NOSTDFLAGS = -nostartfiles -nostdlib
+ ASFLAGS += -mcpu=v10 -g -Wa,-I,$(SRC_PATH)/tests/tcg/cris/bare
+ CRT_FILES = crt.o sys.o
+diff --git a/tests/tcg/hexagon/Makefile.target b/tests/tcg/hexagon/Makefile.target
+index 96a4d7a614..1b2b26e843 100644
+--- a/tests/tcg/hexagon/Makefile.target
++++ b/tests/tcg/hexagon/Makefile.target
+@@ -19,7 +19,7 @@
+ EXTRA_RUNS =
+
+ CFLAGS += -Wno-incompatible-pointer-types -Wno-undefined-internal
+-CFLAGS += -fno-unroll-loops
++CFLAGS += -fno-unroll-loops -fno-stack-protector
+
+ HEX_SRC=$(SRC_PATH)/tests/tcg/hexagon
+ VPATH += $(HEX_SRC)
+diff --git a/tests/tcg/i386/Makefile.target b/tests/tcg/i386/Makefile.target
+index bafd8c2180..3aec3bba77 100644
+--- a/tests/tcg/i386/Makefile.target
++++ b/tests/tcg/i386/Makefile.target
+@@ -35,7 +35,7 @@ run-plugin-test-i386-adcox-%: QEMU_OPTS += -cpu max
+ #
+ # hello-i386 is a barebones app
+ #
+-hello-i386: CFLAGS+=-ffreestanding
++hello-i386: CFLAGS+=-ffreestanding -fno-stack-protector
+ hello-i386: LDFLAGS+=-nostdlib
+
+ # test-386 includes a couple of additional objects that need to be
+diff --git a/tests/tcg/i386/test-avx.py b/tests/tcg/i386/test-avx.py
+index d9ca00a49e..641a2ef69e 100755
+--- a/tests/tcg/i386/test-avx.py
++++ b/tests/tcg/i386/test-avx.py
+@@ -49,7 +49,7 @@
+ 'VEXTRACT[FI]128': 0x01,
+ 'VINSERT[FI]128': 0x01,
+ 'VPBLENDD': 0xff,
+- 'VPERM2[FI]128': 0x33,
++ 'VPERM2[FI]128': 0xbb,
+ 'VPERMPD': 0xff,
+ 'VPERMQ': 0xff,
+ 'VPERMILPS': 0xff,
+diff --git a/tests/tcg/minilib/Makefile.target b/tests/tcg/minilib/Makefile.target
+index c821d2806a..af0bf54be9 100644
+--- a/tests/tcg/minilib/Makefile.target
++++ b/tests/tcg/minilib/Makefile.target
+@@ -12,7 +12,7 @@ SYSTEM_MINILIB_SRC=$(SRC_PATH)/tests/tcg/minilib
+ MINILIB_SRCS=$(wildcard $(SYSTEM_MINILIB_SRC)/*.c)
+ MINILIB_OBJS=$(patsubst $(SYSTEM_MINILIB_SRC)/%.c, %.o, $(MINILIB_SRCS))
+
+-MINILIB_CFLAGS+=-nostdlib -ggdb -O0
++MINILIB_CFLAGS+=-nostdlib -fno-stack-protector -ggdb -O0
+ MINILIB_INC=-isystem $(SYSTEM_MINILIB_SRC)
+
+ .PRECIOUS: $(MINILIB_OBJS)
+diff --git a/tests/tcg/mips/Makefile.target b/tests/tcg/mips/Makefile.target
+index 1a994d5525..5d17c1706e 100644
+--- a/tests/tcg/mips/Makefile.target
++++ b/tests/tcg/mips/Makefile.target
+@@ -14,6 +14,6 @@ MIPS_TESTS=hello-mips
+
+ TESTS += $(MIPS_TESTS)
+
+-hello-mips: CFLAGS+=-mno-abicalls -fno-PIC -mabi=32
++hello-mips: CFLAGS+=-mno-abicalls -fno-PIC -fno-stack-protector -mabi=32
+ hello-mips: LDFLAGS+=-nostdlib
+ endif
+diff --git a/tests/tcg/mips/hello-mips.c b/tests/tcg/mips/hello-mips.c
+index 4e1cf501af..38e22d00e3 100644
+--- a/tests/tcg/mips/hello-mips.c
++++ b/tests/tcg/mips/hello-mips.c
+@@ -5,8 +5,8 @@
+ * http://www.linux-mips.org/wiki/MIPSABIHistory
+ * http://www.linux.com/howtos/Assembly-HOWTO/mips.shtml
+ *
+-* mipsel-linux-gcc -nostdlib -mno-abicalls -fno-PIC -mabi=32 \
+-* -O2 -static -o hello-mips hello-mips.c
++* mipsel-linux-gcc -nostdlib -mno-abicalls -fno-PIC -fno-stack-protector \
++* -mabi=32 -O2 -static -o hello-mips hello-mips.c
+ *
+ */
+ #define __NR_SYSCALL_BASE 4000
+diff --git a/tests/tcg/s390x/Makefile.target b/tests/tcg/s390x/Makefile.target
+index cb90d4183d..ea9fa67152 100644
+--- a/tests/tcg/s390x/Makefile.target
++++ b/tests/tcg/s390x/Makefile.target
+@@ -24,6 +24,7 @@ TESTS+=trap
+ TESTS+=signals-s390x
+ TESTS+=branch-relative-long
+ TESTS+=noexec
++TESTS+=laalg
+
+ Z13_TESTS=vistr
+ Z13_TESTS+=lcbb
+diff --git a/tests/tcg/s390x/laalg.c b/tests/tcg/s390x/laalg.c
+new file mode 100644
+index 0000000000..797d168bb1
+--- /dev/null
++++ b/tests/tcg/s390x/laalg.c
+@@ -0,0 +1,27 @@
++/*
++ * Test the LAALG instruction.
++ *
++ * SPDX-License-Identifier: GPL-2.0-or-later
++ */
++#include <assert.h>
++#include <stdlib.h>
++
++int main(void)
++{
++ unsigned long cc = 0, op1, op2 = 40, op3 = 2;
++
++ asm("slgfi %[cc],1\n" /* Set cc_src = -1. */
++ "laalg %[op1],%[op3],%[op2]\n"
++ "ipm %[cc]"
++ : [cc] "+r" (cc)
++ , [op1] "=r" (op1)
++ , [op2] "+T" (op2)
++ : [op3] "r" (op3)
++ : "cc");
++
++ assert(cc == 0xffffffff10ffffff);
++ assert(op1 == 40);
++ assert(op2 == 42);
++
++ return EXIT_SUCCESS;
++}
+diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c
+index e99e3b0d8c..52c6246a33 100644
+--- a/ui/gtk-egl.c
++++ b/ui/gtk-egl.c
+@@ -66,15 +66,16 @@ void gd_egl_draw(VirtualConsole *vc)
+ #ifdef CONFIG_GBM
+ QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf;
+ #endif
+- int ww, wh;
++ int ww, wh, ws;
+
+ if (!vc->gfx.gls) {
+ return;
+ }
+
+ window = gtk_widget_get_window(vc->gfx.drawing_area);
+- ww = gdk_window_get_width(window);
+- wh = gdk_window_get_height(window);
++ ws = gdk_window_get_scale_factor(window);
++ ww = gdk_window_get_width(window) * ws;
++ wh = gdk_window_get_height(window) * ws;
+
+ if (vc->gfx.scanout_mode) {
+ #ifdef CONFIG_GBM
+@@ -300,7 +301,7 @@ void gd_egl_scanout_flush(DisplayChangeListener *dcl,
+ {
+ VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl);
+ GdkWindow *window;
+- int ww, wh;
++ int ww, wh, ws;
+
+ if (!vc->gfx.scanout_mode) {
+ return;
+@@ -313,8 +314,9 @@ void gd_egl_scanout_flush(DisplayChangeListener *dcl,
+ vc->gfx.esurface, vc->gfx.ectx);
+
+ window = gtk_widget_get_window(vc->gfx.drawing_area);
+- ww = gdk_window_get_width(window);
+- wh = gdk_window_get_height(window);
++ ws = gdk_window_get_scale_factor(window);
++ ww = gdk_window_get_width(window) * ws;
++ wh = gdk_window_get_height(window) * ws;
+ egl_fb_setup_default(&vc->gfx.win_fb, ww, wh);
+ if (vc->gfx.cursor_fb.texture) {
+ egl_texture_blit(vc->gfx.gls, &vc->gfx.win_fb, &vc->gfx.guest_fb,
+diff --git a/ui/gtk.c b/ui/gtk.c
+index e681e8c319..283c41a1a1 100644
+--- a/ui/gtk.c
++++ b/ui/gtk.c
+@@ -2317,6 +2317,7 @@ static void gtk_display_init(DisplayState *ds, DisplayOptions *opts)
+ GdkDisplay *window_display;
+ GtkIconTheme *theme;
+ char *dir;
++ int idx;
+
+ if (!gtkinit) {
+ fprintf(stderr, "gtk initialization failed\n");
+@@ -2379,6 +2380,15 @@ static void gtk_display_init(DisplayState *ds, DisplayOptions *opts)
+ gtk_container_add(GTK_CONTAINER(s->window), s->vbox);
+
+ gtk_widget_show_all(s->window);
++
++ for (idx = 0;; idx++) {
++ QemuConsole *con = qemu_console_lookup_by_index(idx);
++ if (!con) {
++ break;
++ }
++ gtk_widget_realize(s->vc[idx].gfx.drawing_area);
++ }
++
+ if (opts->u.gtk.has_show_menubar &&
+ !opts->u.gtk.show_menubar) {
+ gtk_widget_hide(s->menu_bar);
+diff --git a/ui/vnc.c b/ui/vnc.c
+index 1856d57380..1ca16c0ff6 100644
+--- a/ui/vnc.c
++++ b/ui/vnc.c
+@@ -2219,7 +2219,7 @@ static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings)
+ break;
+ case VNC_ENCODING_XVP:
+ if (vs->vd->power_control) {
+- vs->features |= VNC_FEATURE_XVP;
++ vs->features |= VNC_FEATURE_XVP_MASK;
+ send_xvp_message(vs, VNC_XVP_CODE_INIT);
+ }
+ break;
+@@ -2468,7 +2468,7 @@ static int protocol_client_msg(VncState *vs, uint8_t *data, size_t len)
+ vnc_client_cut_text(vs, read_u32(data, 4), data + 8);
+ break;
+ case VNC_MSG_CLIENT_XVP:
+- if (!(vs->features & VNC_FEATURE_XVP)) {
++ if (!vnc_has_feature(vs, VNC_FEATURE_XVP)) {
+ error_report("vnc: xvp client message while disabled");
+ vnc_client_error(vs);
+ break;
+@@ -2565,7 +2565,7 @@ static int protocol_client_msg(VncState *vs, uint8_t *data, size_t len)
+ vs, vs->ioc, vs->as.fmt, vs->as.nchannels, vs->as.freq);
+ break;
+ default:
+- VNC_DEBUG("Invalid audio message %d\n", read_u8(data, 4));
++ VNC_DEBUG("Invalid audio message %d\n", read_u8(data, 2));
+ vnc_client_error(vs);
+ break;
+ }
diff --git a/debian/patches/v7.2.8.diff b/debian/patches/v7.2.8.diff
new file mode 100644
index 00000000..c7461c5b
--- /dev/null
+++ b/debian/patches/v7.2.8.diff
@@ -0,0 +1,1524 @@
+Subject: v7.2.8
+Date: Fri Dec 22 21:59:29 2023 +0300
+From: Michael Tokarev <mjt@tls.msk.ru>
+Forwarded: not-needed
+
+This is a difference between upstream qemu v7.2.7
+and upstream qemu v7.2.8.
+
+ VERSION | 2 +-
+ block/vmdk.c | 28 +++++++---
+ docs/devel/testing.rst | 4 +-
+ hw/acpi/erst.c | 10 ++++
+ hw/audio/hda-codec.c | 29 +++++++---
+ hw/ide/ahci.c | 27 ++++++++-
+ hw/mips/malta.c | 4 +-
+ hw/misc/mps2-scc.c | 8 +++
+ hw/net/allwinner-sun8i-emac.c | 3 +-
+ hw/net/allwinner_emac.c | 3 +-
+ hw/net/cadence_gem.c | 3 +-
+ hw/net/dp8393x.c | 3 +-
+ hw/net/e1000.c | 3 +-
+ hw/net/e1000e.c | 2 +-
+ hw/net/eepro100.c | 4 +-
+ hw/net/etraxfs_eth.c | 3 +-
+ hw/net/fsl_etsec/etsec.c | 3 +-
+ hw/net/ftgmac100.c | 3 +-
+ hw/net/i82596.c | 2 +-
+ hw/net/imx_fec.c | 2 +-
+ hw/net/lan9118.c | 3 +-
+ hw/net/mcf_fec.c | 3 +-
+ hw/net/mipsnet.c | 3 +-
+ hw/net/msf2-emac.c | 3 +-
+ hw/net/mv88w8618_eth.c | 3 +-
+ hw/net/ne2000-isa.c | 3 +-
+ hw/net/ne2000-pci.c | 3 +-
+ hw/net/npcm7xx_emc.c | 3 +-
+ hw/net/opencores_eth.c | 3 +-
+ hw/net/pcnet.c | 3 +-
+ hw/net/rocker/rocker_fp.c | 4 +-
+ hw/net/rtl8139.c | 3 +-
+ hw/net/smc91c111.c | 3 +-
+ hw/net/spapr_llan.c | 3 +-
+ hw/net/stellaris_enet.c | 3 +-
+ hw/net/sungem.c | 2 +-
+ hw/net/sunhme.c | 3 +-
+ hw/net/tulip.c | 3 +-
+ hw/net/virtio-net.c | 6 +-
+ hw/net/vmxnet3.c | 2 +-
+ hw/net/xen_nic.c | 3 +-
+ hw/net/xgmac.c | 3 +-
+ hw/net/xilinx_axienet.c | 3 +-
+ hw/net/xilinx_ethlite.c | 3 +-
+ hw/nvram/xlnx-efuse.c | 8 +++
+ hw/nvram/xlnx-versal-efuse-ctrl.c | 8 +++
+ hw/pci/msix.c | 1 +
+ hw/pci/pcie_sriov.c | 1 -
+ hw/usb/dev-network.c | 3 +-
+ hw/virtio/virtio-iommu-pci.c | 8 +++
+ hw/virtio/virtio-pci.c | 1 +
+ include/hw/virtio/virtio-pci.h | 1 +
+ include/net/net.h | 2 +
+ linux-user/elfload.c | 2 +-
+ net/net.c | 15 +++++
+ softmmu/memory.c | 32 +----------
+ target/arm/cpu.c | 10 ++++
+ target/arm/helper.c | 22 +++++++-
+ target/arm/sme_helper.c | 10 ++--
+ target/arm/syndrome.h | 6 +-
+ tests/avocado/cpu_queries.py | 2 +-
+ tests/avocado/empty_cpu_model.py | 2 +-
+ tests/avocado/pc_cpu_hotplug_props.py | 2 +-
+ tests/avocado/version.py | 2 +-
+ tests/avocado/x86_cpu_model_versions.py | 97 +++++++++++++++++----------------
+ tests/qemu-iotests/059 | 2 +
+ tests/qemu-iotests/059.out | 4 ++
+ ui/gtk-egl.c | 7 +++
+ ui/vnc-clipboard.c | 5 ++
+ 69 files changed, 317 insertions(+), 156 deletions(-)
+
+diff --git a/VERSION b/VERSION
+index 4afc54e7b7..31554632ab 100644
+--- a/VERSION
++++ b/VERSION
+@@ -1 +1 @@
+-7.2.7
++7.2.8
+diff --git a/block/vmdk.c b/block/vmdk.c
+index 26376352b9..f8d3a13568 100644
+--- a/block/vmdk.c
++++ b/block/vmdk.c
+@@ -346,29 +346,41 @@ static int vmdk_write_cid(BlockDriverState *bs, uint32_t cid)
+ BDRVVmdkState *s = bs->opaque;
+ int ret = 0;
+
+- desc = g_malloc0(DESC_SIZE);
+- tmp_desc = g_malloc0(DESC_SIZE);
+- ret = bdrv_pread(bs->file, s->desc_offset, DESC_SIZE, desc, 0);
++ size_t desc_buf_size;
++
++ if (s->desc_offset == 0) {
++ desc_buf_size = bdrv_getlength(bs->file->bs);
++ if (desc_buf_size > 16ULL << 20) {
++ error_report("VMDK description file too big");
++ return -EFBIG;
++ }
++ } else {
++ desc_buf_size = DESC_SIZE;
++ }
++
++ desc = g_malloc0(desc_buf_size);
++ tmp_desc = g_malloc0(desc_buf_size);
++ ret = bdrv_pread(bs->file, s->desc_offset, desc_buf_size, desc, 0);
+ if (ret < 0) {
+ goto out;
+ }
+
+- desc[DESC_SIZE - 1] = '\0';
++ desc[desc_buf_size - 1] = '\0';
+ tmp_str = strstr(desc, "parentCID");
+ if (tmp_str == NULL) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+- pstrcpy(tmp_desc, DESC_SIZE, tmp_str);
++ pstrcpy(tmp_desc, desc_buf_size, tmp_str);
+ p_name = strstr(desc, "CID");
+ if (p_name != NULL) {
+ p_name += sizeof("CID");
+- snprintf(p_name, DESC_SIZE - (p_name - desc), "%" PRIx32 "\n", cid);
+- pstrcat(desc, DESC_SIZE, tmp_desc);
++ snprintf(p_name, desc_buf_size - (p_name - desc), "%" PRIx32 "\n", cid);
++ pstrcat(desc, desc_buf_size, tmp_desc);
+ }
+
+- ret = bdrv_pwrite_sync(bs->file, s->desc_offset, DESC_SIZE, desc, 0);
++ ret = bdrv_pwrite_sync(bs->file, s->desc_offset, desc_buf_size, desc, 0);
+
+ out:
+ g_free(desc);
+diff --git a/docs/devel/testing.rst b/docs/devel/testing.rst
+index e10c47b5a7..98c26ecf18 100644
+--- a/docs/devel/testing.rst
++++ b/docs/devel/testing.rst
+@@ -990,7 +990,7 @@ class. Here's a simple usage example:
+ self.vm.launch()
+ res = self.vm.command('human-monitor-command',
+ command_line='info version')
+- self.assertRegexpMatches(res, r'^(\d+\.\d+\.\d)')
++ self.assertRegex(res, r'^(\d+\.\d+\.\d)')
+
+ To execute your test, run:
+
+@@ -1051,7 +1051,7 @@ and hypothetical example follows:
+ 'human-monitor-command',
+ command_line='info version')
+
+- self.assertEquals(first_res, second_res, third_res)
++ self.assertEqual(first_res, second_res, third_res)
+
+ At test "tear down", ``avocado_qemu.Test`` handles all the QEMUMachines
+ shutdown.
+diff --git a/hw/acpi/erst.c b/hw/acpi/erst.c
+index aefcc03ad6..2e057b1800 100644
+--- a/hw/acpi/erst.c
++++ b/hw/acpi/erst.c
+@@ -947,6 +947,7 @@ static const VMStateDescription erst_vmstate = {
+
+ static void erst_realizefn(PCIDevice *pci_dev, Error **errp)
+ {
++ ERRP_GUARD();
+ ERSTDeviceState *s = ACPIERST(pci_dev);
+
+ trace_acpi_erst_realizefn_in();
+@@ -964,9 +965,15 @@ static void erst_realizefn(PCIDevice *pci_dev, Error **errp)
+
+ /* HostMemoryBackend size will be multiple of PAGE_SIZE */
+ s->storage_size = object_property_get_int(OBJECT(s->hostmem), "size", errp);
++ if (*errp) {
++ return;
++ }
+
+ /* Initialize backend storage and record_count */
+ check_erst_backend_storage(s, errp);
++ if (*errp) {
++ return;
++ }
+
+ /* BAR 0: Programming registers */
+ memory_region_init_io(&s->iomem_mr, OBJECT(pci_dev), &erst_reg_ops, s,
+@@ -977,6 +984,9 @@ static void erst_realizefn(PCIDevice *pci_dev, Error **errp)
+ memory_region_init_ram(&s->exchange_mr, OBJECT(pci_dev),
+ "erst.exchange",
+ le32_to_cpu(s->header->record_size), errp);
++ if (*errp) {
++ return;
++ }
+ pci_register_bar(pci_dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY,
+ &s->exchange_mr);
+
+diff --git a/hw/audio/hda-codec.c b/hw/audio/hda-codec.c
+index feb8f9e2bb..0f66754b6a 100644
+--- a/hw/audio/hda-codec.c
++++ b/hw/audio/hda-codec.c
+@@ -22,6 +22,7 @@
+ #include "hw/qdev-properties.h"
+ #include "intel-hda.h"
+ #include "migration/vmstate.h"
++#include "qemu/host-utils.h"
+ #include "qemu/module.h"
+ #include "intel-hda-defs.h"
+ #include "audio/audio.h"
+@@ -190,9 +191,9 @@ struct HDAAudioState {
+ bool use_timer;
+ };
+
+-static inline int64_t hda_bytes_per_second(HDAAudioStream *st)
++static inline uint32_t hda_bytes_per_second(HDAAudioStream *st)
+ {
+- return 2LL * st->as.nchannels * st->as.freq;
++ return 2 * (uint32_t)st->as.nchannels * (uint32_t)st->as.freq;
+ }
+
+ static inline void hda_timer_sync_adjust(HDAAudioStream *st, int64_t target_pos)
+@@ -223,12 +224,18 @@ static void hda_audio_input_timer(void *opaque)
+
+ int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+
+- int64_t buft_start = st->buft_start;
++ int64_t uptime = now - st->buft_start;
+ int64_t wpos = st->wpos;
+ int64_t rpos = st->rpos;
++ int64_t wanted_rpos;
+
+- int64_t wanted_rpos = hda_bytes_per_second(st) * (now - buft_start)
+- / NANOSECONDS_PER_SECOND;
++ if (uptime <= 0) {
++ /* wanted_rpos <= 0 */
++ goto out_timer;
++ }
++
++ wanted_rpos = muldiv64(uptime, hda_bytes_per_second(st),
++ NANOSECONDS_PER_SECOND);
+ wanted_rpos &= -4; /* IMPORTANT! clip to frames */
+
+ if (wanted_rpos <= rpos) {
+@@ -287,12 +294,18 @@ static void hda_audio_output_timer(void *opaque)
+
+ int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+
+- int64_t buft_start = st->buft_start;
++ int64_t uptime = now - st->buft_start;
+ int64_t wpos = st->wpos;
+ int64_t rpos = st->rpos;
++ int64_t wanted_wpos;
++
++ if (uptime <= 0) {
++ /* wanted_wpos <= 0 */
++ goto out_timer;
++ }
+
+- int64_t wanted_wpos = hda_bytes_per_second(st) * (now - buft_start)
+- / NANOSECONDS_PER_SECOND;
++ wanted_wpos = muldiv64(uptime, hda_bytes_per_second(st),
++ NANOSECONDS_PER_SECOND);
+ wanted_wpos &= -4; /* IMPORTANT! clip to frames */
+
+ if (wanted_wpos <= wpos) {
+diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
+index c5e79b6e6d..0167ab3680 100644
+--- a/hw/ide/ahci.c
++++ b/hw/ide/ahci.c
+@@ -622,9 +622,13 @@ static void ahci_init_d2h(AHCIDevice *ad)
+ return;
+ }
+
++ /*
++ * For simplicity, do not call ahci_clear_cmd_issue() for this
++ * ahci_write_fis_d2h(). (The reset value for PxCI is 0.)
++ */
+ if (ahci_write_fis_d2h(ad, true)) {
+ ad->init_d2h_sent = true;
+- /* We're emulating receiving the first Reg H2D Fis from the device;
++ /* We're emulating receiving the first Reg D2H FIS from the device;
+ * Update the SIG register, but otherwise proceed as normal. */
+ pr->sig = ((uint32_t)ide_state->hcyl << 24) |
+ (ide_state->lcyl << 16) |
+@@ -662,6 +666,7 @@ static void ahci_reset_port(AHCIState *s, int port)
+ pr->scr_act = 0;
+ pr->tfdata = 0x7F;
+ pr->sig = 0xFFFFFFFF;
++ pr->cmd_issue = 0;
+ d->busy_slot = -1;
+ d->init_d2h_sent = false;
+
+@@ -1242,10 +1247,30 @@ static void handle_reg_h2d_fis(AHCIState *s, int port,
+ case STATE_RUN:
+ if (cmd_fis[15] & ATA_SRST) {
+ s->dev[port].port_state = STATE_RESET;
++ /*
++ * When setting SRST in the first H2D FIS in the reset sequence,
++ * the device does not send a D2H FIS. Host software thus has to
++ * set the "Clear Busy upon R_OK" bit such that PxCI (and BUSY)
++ * gets cleared. See AHCI 1.3.1, section 10.4.1 Software Reset.
++ */
++ if (opts & AHCI_CMD_CLR_BUSY) {
++ ahci_clear_cmd_issue(ad, slot);
++ }
+ }
+ break;
+ case STATE_RESET:
+ if (!(cmd_fis[15] & ATA_SRST)) {
++ /*
++ * When clearing SRST in the second H2D FIS in the reset
++ * sequence, the device will execute diagnostics. When this is
++ * done, the device will send a D2H FIS with the good status.
++ * See SATA 3.5a Gold, section 11.4 Software reset protocol.
++ *
++ * This D2H FIS is the first D2H FIS received from the device,
++ * and is received regardless if the reset was performed by a
++ * COMRESET or by setting and clearing the SRST bit. Therefore,
++ * the logic for this is found in ahci_init_d2h() and not here.
++ */
+ ahci_reset_port(s, port);
+ }
+ break;
+diff --git a/hw/mips/malta.c b/hw/mips/malta.c
+index c0a2e0ab04..da7c110b73 100644
+--- a/hw/mips/malta.c
++++ b/hw/mips/malta.c
+@@ -877,9 +877,9 @@ static void write_bootloader(uint8_t *base, uint64_t run_addr,
+
+ /* Bus endianess is always reversed */
+ #if TARGET_BIG_ENDIAN
+-#define cpu_to_gt32 cpu_to_le32
++#define cpu_to_gt32(x) (x)
+ #else
+-#define cpu_to_gt32 cpu_to_be32
++#define cpu_to_gt32(x) bswap32(x)
+ #endif
+
+ /* move GT64120 registers from 0x14000000 to 0x1be00000 */
+diff --git a/hw/misc/mps2-scc.c b/hw/misc/mps2-scc.c
+index b3b42a792c..fe5034db14 100644
+--- a/hw/misc/mps2-scc.c
++++ b/hw/misc/mps2-scc.c
+@@ -329,6 +329,13 @@ static void mps2_scc_realize(DeviceState *dev, Error **errp)
+ s->oscclk = g_new0(uint32_t, s->num_oscclk);
+ }
+
++static void mps2_scc_finalize(Object *obj)
++{
++ MPS2SCC *s = MPS2_SCC(obj);
++
++ g_free(s->oscclk_reset);
++}
++
+ static const VMStateDescription mps2_scc_vmstate = {
+ .name = "mps2-scc",
+ .version_id = 3,
+@@ -385,6 +392,7 @@ static const TypeInfo mps2_scc_info = {
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(MPS2SCC),
+ .instance_init = mps2_scc_init,
++ .instance_finalize = mps2_scc_finalize,
+ .class_init = mps2_scc_class_init,
+ };
+
+diff --git a/hw/net/allwinner-sun8i-emac.c b/hw/net/allwinner-sun8i-emac.c
+index c3fed5fcbe..1a6a79f5ae 100644
+--- a/hw/net/allwinner-sun8i-emac.c
++++ b/hw/net/allwinner-sun8i-emac.c
+@@ -824,7 +824,8 @@ static void allwinner_sun8i_emac_realize(DeviceState *dev, Error **errp)
+
+ qemu_macaddr_default_if_unset(&s->conf.macaddr);
+ s->nic = qemu_new_nic(&net_allwinner_sun8i_emac_info, &s->conf,
+- object_get_typename(OBJECT(dev)), dev->id, s);
++ object_get_typename(OBJECT(dev)), dev->id,
++ &dev->mem_reentrancy_guard, s);
+ qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
+ }
+
+diff --git a/hw/net/allwinner_emac.c b/hw/net/allwinner_emac.c
+index ddddf35c45..b3d73143bf 100644
+--- a/hw/net/allwinner_emac.c
++++ b/hw/net/allwinner_emac.c
+@@ -453,7 +453,8 @@ static void aw_emac_realize(DeviceState *dev, Error **errp)
+
+ qemu_macaddr_default_if_unset(&s->conf.macaddr);
+ s->nic = qemu_new_nic(&net_aw_emac_info, &s->conf,
+- object_get_typename(OBJECT(dev)), dev->id, s);
++ object_get_typename(OBJECT(dev)), dev->id,
++ &dev->mem_reentrancy_guard, s);
+ qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
+
+ fifo8_create(&s->rx_fifo, RX_FIFO_SIZE);
+diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c
+index 24b3a0ff66..cb61a76417 100644
+--- a/hw/net/cadence_gem.c
++++ b/hw/net/cadence_gem.c
+@@ -1633,7 +1633,8 @@ static void gem_realize(DeviceState *dev, Error **errp)
+ qemu_macaddr_default_if_unset(&s->conf.macaddr);
+
+ s->nic = qemu_new_nic(&net_gem_info, &s->conf,
+- object_get_typename(OBJECT(dev)), dev->id, s);
++ object_get_typename(OBJECT(dev)), dev->id,
++ &dev->mem_reentrancy_guard, s);
+
+ if (s->jumbo_max_len > MAX_FRAME_SIZE) {
+ error_setg(errp, "jumbo-max-len is greater than %d",
+diff --git a/hw/net/dp8393x.c b/hw/net/dp8393x.c
+index 45b954e46c..abfcc6f69f 100644
+--- a/hw/net/dp8393x.c
++++ b/hw/net/dp8393x.c
+@@ -943,7 +943,8 @@ static void dp8393x_realize(DeviceState *dev, Error **errp)
+ "dp8393x-regs", SONIC_REG_COUNT << s->it_shift);
+
+ s->nic = qemu_new_nic(&net_dp83932_info, &s->conf,
+- object_get_typename(OBJECT(dev)), dev->id, s);
++ object_get_typename(OBJECT(dev)), dev->id,
++ &dev->mem_reentrancy_guard, s);
+ qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
+
+ s->watchdog = timer_new_ns(QEMU_CLOCK_VIRTUAL, dp8393x_watchdog, s);
+diff --git a/hw/net/e1000.c b/hw/net/e1000.c
+index 0dfdf47313..0a78ad3a58 100644
+--- a/hw/net/e1000.c
++++ b/hw/net/e1000.c
+@@ -1735,7 +1735,8 @@ static void pci_e1000_realize(PCIDevice *pci_dev, Error **errp)
+ macaddr);
+
+ d->nic = qemu_new_nic(&net_e1000_info, &d->conf,
+- object_get_typename(OBJECT(d)), dev->id, d);
++ object_get_typename(OBJECT(d)), dev->id,
++ &dev->mem_reentrancy_guard, d);
+
+ qemu_format_nic_info_str(qemu_get_queue(d->nic), macaddr);
+
+diff --git a/hw/net/e1000e.c b/hw/net/e1000e.c
+index 7523e9f5d2..6573cc3cc3 100644
+--- a/hw/net/e1000e.c
++++ b/hw/net/e1000e.c
+@@ -319,7 +319,7 @@ e1000e_init_net_peer(E1000EState *s, PCIDevice *pci_dev, uint8_t *macaddr)
+ int i;
+
+ s->nic = qemu_new_nic(&net_e1000e_info, &s->conf,
+- object_get_typename(OBJECT(s)), dev->id, s);
++ object_get_typename(OBJECT(s)), dev->id, &dev->mem_reentrancy_guard, s);
+
+ s->core.max_queue_num = s->conf.peers.queues ? s->conf.peers.queues - 1 : 0;
+
+diff --git a/hw/net/eepro100.c b/hw/net/eepro100.c
+index 679f52f80f..871d9a0950 100644
+--- a/hw/net/eepro100.c
++++ b/hw/net/eepro100.c
+@@ -1874,7 +1874,9 @@ static void e100_nic_realize(PCIDevice *pci_dev, Error **errp)
+ nic_reset(s);
+
+ s->nic = qemu_new_nic(&net_eepro100_info, &s->conf,
+- object_get_typename(OBJECT(pci_dev)), pci_dev->qdev.id, s);
++ object_get_typename(OBJECT(pci_dev)),
++ pci_dev->qdev.id,
++ &pci_dev->qdev.mem_reentrancy_guard, s);
+
+ qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
+ TRACE(OTHER, logout("%s\n", qemu_get_queue(s->nic)->info_str));
+diff --git a/hw/net/etraxfs_eth.c b/hw/net/etraxfs_eth.c
+index 1b82aec794..ba57a978d1 100644
+--- a/hw/net/etraxfs_eth.c
++++ b/hw/net/etraxfs_eth.c
+@@ -618,7 +618,8 @@ static void etraxfs_eth_realize(DeviceState *dev, Error **errp)
+
+ qemu_macaddr_default_if_unset(&s->conf.macaddr);
+ s->nic = qemu_new_nic(&net_etraxfs_info, &s->conf,
+- object_get_typename(OBJECT(s)), dev->id, s);
++ object_get_typename(OBJECT(s)), dev->id,
++ &dev->mem_reentrancy_guard, s);
+ qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
+
+ s->phy.read = tdk_read;
+diff --git a/hw/net/fsl_etsec/etsec.c b/hw/net/fsl_etsec/etsec.c
+index b75d8e3dce..102ba69658 100644
+--- a/hw/net/fsl_etsec/etsec.c
++++ b/hw/net/fsl_etsec/etsec.c
+@@ -390,7 +390,8 @@ static void etsec_realize(DeviceState *dev, Error **errp)
+ eTSEC *etsec = ETSEC_COMMON(dev);
+
+ etsec->nic = qemu_new_nic(&net_etsec_info, &etsec->conf,
+- object_get_typename(OBJECT(dev)), dev->id, etsec);
++ object_get_typename(OBJECT(dev)), dev->id,
++ &dev->mem_reentrancy_guard, etsec);
+ qemu_format_nic_info_str(qemu_get_queue(etsec->nic), etsec->conf.macaddr.a);
+
+ etsec->ptimer = ptimer_init(etsec_timer_hit, etsec, PTIMER_POLICY_LEGACY);
+diff --git a/hw/net/ftgmac100.c b/hw/net/ftgmac100.c
+index 83ef0a783e..346485ab49 100644
+--- a/hw/net/ftgmac100.c
++++ b/hw/net/ftgmac100.c
+@@ -1118,7 +1118,8 @@ static void ftgmac100_realize(DeviceState *dev, Error **errp)
+ qemu_macaddr_default_if_unset(&s->conf.macaddr);
+
+ s->nic = qemu_new_nic(&net_ftgmac100_info, &s->conf,
+- object_get_typename(OBJECT(dev)), dev->id, s);
++ object_get_typename(OBJECT(dev)), dev->id,
++ &dev->mem_reentrancy_guard, s);
+ qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
+ }
+
+diff --git a/hw/net/i82596.c b/hw/net/i82596.c
+index ec21e2699a..dc64246f75 100644
+--- a/hw/net/i82596.c
++++ b/hw/net/i82596.c
+@@ -743,7 +743,7 @@ void i82596_common_init(DeviceState *dev, I82596State *s, NetClientInfo *info)
+ qemu_macaddr_default_if_unset(&s->conf.macaddr);
+ }
+ s->nic = qemu_new_nic(info, &s->conf, object_get_typename(OBJECT(dev)),
+- dev->id, s);
++ dev->id, &dev->mem_reentrancy_guard, s);
+ qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
+
+ if (USE_TIMER) {
+diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
+index 8c11b237de..7eb2fef626 100644
+--- a/hw/net/imx_fec.c
++++ b/hw/net/imx_fec.c
+@@ -1318,7 +1318,7 @@ static void imx_eth_realize(DeviceState *dev, Error **errp)
+
+ s->nic = qemu_new_nic(&imx_eth_net_info, &s->conf,
+ object_get_typename(OBJECT(dev)),
+- dev->id, s);
++ dev->id, &dev->mem_reentrancy_guard, s);
+
+ qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
+ }
+diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c
+index f1cba55967..00a6d82efb 100644
+--- a/hw/net/lan9118.c
++++ b/hw/net/lan9118.c
+@@ -1362,7 +1362,8 @@ static void lan9118_realize(DeviceState *dev, Error **errp)
+ qemu_macaddr_default_if_unset(&s->conf.macaddr);
+
+ s->nic = qemu_new_nic(&net_lan9118_info, &s->conf,
+- object_get_typename(OBJECT(dev)), dev->id, s);
++ object_get_typename(OBJECT(dev)), dev->id,
++ &dev->mem_reentrancy_guard, s);
+ qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
+ s->eeprom[0] = 0xa5;
+ for (i = 0; i < 6; i++) {
+diff --git a/hw/net/mcf_fec.c b/hw/net/mcf_fec.c
+index 8aa27bd322..57dd49abea 100644
+--- a/hw/net/mcf_fec.c
++++ b/hw/net/mcf_fec.c
+@@ -643,7 +643,8 @@ static void mcf_fec_realize(DeviceState *dev, Error **errp)
+ mcf_fec_state *s = MCF_FEC_NET(dev);
+
+ s->nic = qemu_new_nic(&net_mcf_fec_info, &s->conf,
+- object_get_typename(OBJECT(dev)), dev->id, s);
++ object_get_typename(OBJECT(dev)), dev->id,
++ &dev->mem_reentrancy_guard, s);
+ qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
+ }
+
+diff --git a/hw/net/mipsnet.c b/hw/net/mipsnet.c
+index 2ade72dea0..8e925de867 100644
+--- a/hw/net/mipsnet.c
++++ b/hw/net/mipsnet.c
+@@ -255,7 +255,8 @@ static void mipsnet_realize(DeviceState *dev, Error **errp)
+ sysbus_init_irq(sbd, &s->irq);
+
+ s->nic = qemu_new_nic(&net_mipsnet_info, &s->conf,
+- object_get_typename(OBJECT(dev)), dev->id, s);
++ object_get_typename(OBJECT(dev)), dev->id,
++ &dev->mem_reentrancy_guard, s);
+ qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
+ }
+
+diff --git a/hw/net/msf2-emac.c b/hw/net/msf2-emac.c
+index db3a04deb1..145a5e46ab 100644
+--- a/hw/net/msf2-emac.c
++++ b/hw/net/msf2-emac.c
+@@ -530,7 +530,8 @@ static void msf2_emac_realize(DeviceState *dev, Error **errp)
+
+ qemu_macaddr_default_if_unset(&s->conf.macaddr);
+ s->nic = qemu_new_nic(&net_msf2_emac_info, &s->conf,
+- object_get_typename(OBJECT(dev)), dev->id, s);
++ object_get_typename(OBJECT(dev)), dev->id,
++ &dev->mem_reentrancy_guard, s);
+ qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
+ }
+
+diff --git a/hw/net/mv88w8618_eth.c b/hw/net/mv88w8618_eth.c
+index ef30b0d4a6..2185f1131a 100644
+--- a/hw/net/mv88w8618_eth.c
++++ b/hw/net/mv88w8618_eth.c
+@@ -350,7 +350,8 @@ static void mv88w8618_eth_realize(DeviceState *dev, Error **errp)
+
+ address_space_init(&s->dma_as, s->dma_mr, "emac-dma");
+ s->nic = qemu_new_nic(&net_mv88w8618_info, &s->conf,
+- object_get_typename(OBJECT(dev)), dev->id, s);
++ object_get_typename(OBJECT(dev)), dev->id,
++ &dev->mem_reentrancy_guard, s);
+ }
+
+ static const VMStateDescription mv88w8618_eth_vmsd = {
+diff --git a/hw/net/ne2000-isa.c b/hw/net/ne2000-isa.c
+index 6ced6775ff..a79f7fad1f 100644
+--- a/hw/net/ne2000-isa.c
++++ b/hw/net/ne2000-isa.c
+@@ -74,7 +74,8 @@ static void isa_ne2000_realizefn(DeviceState *dev, Error **errp)
+ ne2000_reset(s);
+
+ s->nic = qemu_new_nic(&net_ne2000_isa_info, &s->c,
+- object_get_typename(OBJECT(dev)), dev->id, s);
++ object_get_typename(OBJECT(dev)), dev->id,
++ &dev->mem_reentrancy_guard, s);
+ qemu_format_nic_info_str(qemu_get_queue(s->nic), s->c.macaddr.a);
+ }
+
+diff --git a/hw/net/ne2000-pci.c b/hw/net/ne2000-pci.c
+index 9e5d10859a..4f8a699081 100644
+--- a/hw/net/ne2000-pci.c
++++ b/hw/net/ne2000-pci.c
+@@ -71,7 +71,8 @@ static void pci_ne2000_realize(PCIDevice *pci_dev, Error **errp)
+
+ s->nic = qemu_new_nic(&net_ne2000_info, &s->c,
+ object_get_typename(OBJECT(pci_dev)),
+- pci_dev->qdev.id, s);
++ pci_dev->qdev.id,
++ &pci_dev->qdev.mem_reentrancy_guard, s);
+ qemu_format_nic_info_str(qemu_get_queue(s->nic), s->c.macaddr.a);
+ }
+
+diff --git a/hw/net/npcm7xx_emc.c b/hw/net/npcm7xx_emc.c
+index 7c86bb52e5..4bb4e7147d 100644
+--- a/hw/net/npcm7xx_emc.c
++++ b/hw/net/npcm7xx_emc.c
+@@ -803,7 +803,8 @@ static void npcm7xx_emc_realize(DeviceState *dev, Error **errp)
+
+ qemu_macaddr_default_if_unset(&emc->conf.macaddr);
+ emc->nic = qemu_new_nic(&net_npcm7xx_emc_info, &emc->conf,
+- object_get_typename(OBJECT(dev)), dev->id, emc);
++ object_get_typename(OBJECT(dev)), dev->id,
++ &dev->mem_reentrancy_guard, emc);
+ qemu_format_nic_info_str(qemu_get_queue(emc->nic), emc->conf.macaddr.a);
+ }
+
+diff --git a/hw/net/opencores_eth.c b/hw/net/opencores_eth.c
+index 0b3dc3146e..f96d6ea2cc 100644
+--- a/hw/net/opencores_eth.c
++++ b/hw/net/opencores_eth.c
+@@ -732,7 +732,8 @@ static void sysbus_open_eth_realize(DeviceState *dev, Error **errp)
+ sysbus_init_irq(sbd, &s->irq);
+
+ s->nic = qemu_new_nic(&net_open_eth_info, &s->conf,
+- object_get_typename(OBJECT(s)), dev->id, s);
++ object_get_typename(OBJECT(s)), dev->id,
++ &dev->mem_reentrancy_guard, s);
+ }
+
+ static void qdev_open_eth_reset(DeviceState *dev)
+diff --git a/hw/net/pcnet.c b/hw/net/pcnet.c
+index e63e524913..56c3d14ad6 100644
+--- a/hw/net/pcnet.c
++++ b/hw/net/pcnet.c
+@@ -1718,7 +1718,8 @@ void pcnet_common_init(DeviceState *dev, PCNetState *s, NetClientInfo *info)
+ s->poll_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, pcnet_poll_timer, s);
+
+ qemu_macaddr_default_if_unset(&s->conf.macaddr);
+- s->nic = qemu_new_nic(info, &s->conf, object_get_typename(OBJECT(dev)), dev->id, s);
++ s->nic = qemu_new_nic(info, &s->conf, object_get_typename(OBJECT(dev)),
++ dev->id, &dev->mem_reentrancy_guard, s);
+ qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
+
+ /* Initialize the PROM */
+diff --git a/hw/net/rocker/rocker_fp.c b/hw/net/rocker/rocker_fp.c
+index cbeed65bd5..0d21948ada 100644
+--- a/hw/net/rocker/rocker_fp.c
++++ b/hw/net/rocker/rocker_fp.c
+@@ -241,8 +241,8 @@ FpPort *fp_port_alloc(Rocker *r, char *sw_name,
+ port->conf.bootindex = -1;
+ port->conf.peers = *peers;
+
+- port->nic = qemu_new_nic(&fp_port_info, &port->conf,
+- sw_name, NULL, port);
++ port->nic = qemu_new_nic(&fp_port_info, &port->conf, sw_name, NULL,
++ &DEVICE(r)->mem_reentrancy_guard, port);
+ qemu_format_nic_info_str(qemu_get_queue(port->nic),
+ port->conf.macaddr.a);
+
+diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c
+index eb679d7c40..a4462af431 100644
+--- a/hw/net/rtl8139.c
++++ b/hw/net/rtl8139.c
+@@ -3400,7 +3400,8 @@ static void pci_rtl8139_realize(PCIDevice *dev, Error **errp)
+ s->eeprom.contents[9] = s->conf.macaddr.a[4] | s->conf.macaddr.a[5] << 8;
+
+ s->nic = qemu_new_nic(&net_rtl8139_info, &s->conf,
+- object_get_typename(OBJECT(dev)), d->id, s);
++ object_get_typename(OBJECT(dev)), d->id,
++ &d->mem_reentrancy_guard, s);
+ qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
+
+ s->cplus_txbuffer = NULL;
+diff --git a/hw/net/smc91c111.c b/hw/net/smc91c111.c
+index ad778cd8fc..4eda971ef3 100644
+--- a/hw/net/smc91c111.c
++++ b/hw/net/smc91c111.c
+@@ -783,7 +783,8 @@ static void smc91c111_realize(DeviceState *dev, Error **errp)
+ sysbus_init_irq(sbd, &s->irq);
+ qemu_macaddr_default_if_unset(&s->conf.macaddr);
+ s->nic = qemu_new_nic(&net_smc91c111_info, &s->conf,
+- object_get_typename(OBJECT(dev)), dev->id, s);
++ object_get_typename(OBJECT(dev)), dev->id,
++ &dev->mem_reentrancy_guard, s);
+ qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
+ /* ??? Save/restore. */
+ }
+diff --git a/hw/net/spapr_llan.c b/hw/net/spapr_llan.c
+index a6876a936d..475d5f3a34 100644
+--- a/hw/net/spapr_llan.c
++++ b/hw/net/spapr_llan.c
+@@ -325,7 +325,8 @@ static void spapr_vlan_realize(SpaprVioDevice *sdev, Error **errp)
+ memcpy(&dev->perm_mac.a, &dev->nicconf.macaddr.a, sizeof(dev->perm_mac.a));
+
+ dev->nic = qemu_new_nic(&net_spapr_vlan_info, &dev->nicconf,
+- object_get_typename(OBJECT(sdev)), sdev->qdev.id, dev);
++ object_get_typename(OBJECT(sdev)), sdev->qdev.id,
++ &sdev->qdev.mem_reentrancy_guard, dev);
+ qemu_format_nic_info_str(qemu_get_queue(dev->nic), dev->nicconf.macaddr.a);
+
+ dev->rxp_timer = timer_new_us(QEMU_CLOCK_VIRTUAL, spapr_vlan_flush_rx_queue,
+diff --git a/hw/net/stellaris_enet.c b/hw/net/stellaris_enet.c
+index 8dd60783d8..6768a6912f 100644
+--- a/hw/net/stellaris_enet.c
++++ b/hw/net/stellaris_enet.c
+@@ -492,7 +492,8 @@ static void stellaris_enet_realize(DeviceState *dev, Error **errp)
+ qemu_macaddr_default_if_unset(&s->conf.macaddr);
+
+ s->nic = qemu_new_nic(&net_stellaris_enet_info, &s->conf,
+- object_get_typename(OBJECT(dev)), dev->id, s);
++ object_get_typename(OBJECT(dev)), dev->id,
++ &dev->mem_reentrancy_guard, s);
+ qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
+ }
+
+diff --git a/hw/net/sungem.c b/hw/net/sungem.c
+index 3684a4d733..c12d44e9dc 100644
+--- a/hw/net/sungem.c
++++ b/hw/net/sungem.c
+@@ -1361,7 +1361,7 @@ static void sungem_realize(PCIDevice *pci_dev, Error **errp)
+ qemu_macaddr_default_if_unset(&s->conf.macaddr);
+ s->nic = qemu_new_nic(&net_sungem_info, &s->conf,
+ object_get_typename(OBJECT(dev)),
+- dev->id, s);
++ dev->id, &dev->mem_reentrancy_guard, s);
+ qemu_format_nic_info_str(qemu_get_queue(s->nic),
+ s->conf.macaddr.a);
+ }
+diff --git a/hw/net/sunhme.c b/hw/net/sunhme.c
+index fc34905f87..fa98528d71 100644
+--- a/hw/net/sunhme.c
++++ b/hw/net/sunhme.c
+@@ -892,7 +892,8 @@ static void sunhme_realize(PCIDevice *pci_dev, Error **errp)
+
+ qemu_macaddr_default_if_unset(&s->conf.macaddr);
+ s->nic = qemu_new_nic(&net_sunhme_info, &s->conf,
+- object_get_typename(OBJECT(d)), d->id, s);
++ object_get_typename(OBJECT(d)), d->id,
++ &d->mem_reentrancy_guard, s);
+ qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
+ }
+
+diff --git a/hw/net/tulip.c b/hw/net/tulip.c
+index c2b3b1bdfa..956093abd7 100644
+--- a/hw/net/tulip.c
++++ b/hw/net/tulip.c
+@@ -983,7 +983,8 @@ static void pci_tulip_realize(PCIDevice *pci_dev, Error **errp)
+
+ s->nic = qemu_new_nic(&net_tulip_info, &s->c,
+ object_get_typename(OBJECT(pci_dev)),
+- pci_dev->qdev.id, s);
++ pci_dev->qdev.id,
++ &pci_dev->qdev.mem_reentrancy_guard, s);
+ qemu_format_nic_info_str(qemu_get_queue(s->nic), s->c.macaddr.a);
+ }
+
+diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
+index 1b10cdc127..06f35ac2d8 100644
+--- a/hw/net/virtio-net.c
++++ b/hw/net/virtio-net.c
+@@ -3633,10 +3633,12 @@ static void virtio_net_device_realize(DeviceState *dev, Error **errp)
+ * Happen when virtio_net_set_netclient_name has been called.
+ */
+ n->nic = qemu_new_nic(&net_virtio_info, &n->nic_conf,
+- n->netclient_type, n->netclient_name, n);
++ n->netclient_type, n->netclient_name,
++ &dev->mem_reentrancy_guard, n);
+ } else {
+ n->nic = qemu_new_nic(&net_virtio_info, &n->nic_conf,
+- object_get_typename(OBJECT(dev)), dev->id, n);
++ object_get_typename(OBJECT(dev)), dev->id,
++ &dev->mem_reentrancy_guard, n);
+ }
+
+ for (i = 0; i < n->max_queue_pairs; i++) {
+diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c
+index 399fc14129..e49b4a7a6c 100644
+--- a/hw/net/vmxnet3.c
++++ b/hw/net/vmxnet3.c
+@@ -2083,7 +2083,7 @@ static void vmxnet3_net_init(VMXNET3State *s)
+
+ s->nic = qemu_new_nic(&net_vmxnet3_info, &s->conf,
+ object_get_typename(OBJECT(s)),
+- d->id, s);
++ d->id, &d->mem_reentrancy_guard, s);
+
+ s->peer_has_vhdr = vmxnet3_peer_has_vnet_hdr(s);
+ s->tx_sop = true;
+diff --git a/hw/net/xen_nic.c b/hw/net/xen_nic.c
+index 7d92c2d022..1014e84518 100644
+--- a/hw/net/xen_nic.c
++++ b/hw/net/xen_nic.c
+@@ -294,7 +294,8 @@ static int net_init(struct XenLegacyDevice *xendev)
+ }
+
+ netdev->nic = qemu_new_nic(&net_xen_info, &netdev->conf,
+- "xen", NULL, netdev);
++ "xen", NULL,
++ &xendev->qdev.mem_reentrancy_guard, netdev);
+
+ qemu_set_info_str(qemu_get_queue(netdev->nic),
+ "nic: xenbus vif macaddr=%s", netdev->mac);
+diff --git a/hw/net/xgmac.c b/hw/net/xgmac.c
+index 0ab6ae91aa..1f4f277d84 100644
+--- a/hw/net/xgmac.c
++++ b/hw/net/xgmac.c
+@@ -402,7 +402,8 @@ static void xgmac_enet_realize(DeviceState *dev, Error **errp)
+
+ qemu_macaddr_default_if_unset(&s->conf.macaddr);
+ s->nic = qemu_new_nic(&net_xgmac_enet_info, &s->conf,
+- object_get_typename(OBJECT(dev)), dev->id, s);
++ object_get_typename(OBJECT(dev)), dev->id,
++ &dev->mem_reentrancy_guard, s);
+ qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
+
+ s->regs[XGMAC_ADDR_HIGH(0)] = (s->conf.macaddr.a[5] << 8) |
+diff --git a/hw/net/xilinx_axienet.c b/hw/net/xilinx_axienet.c
+index 990ff3a1c2..8a34243803 100644
+--- a/hw/net/xilinx_axienet.c
++++ b/hw/net/xilinx_axienet.c
+@@ -968,7 +968,8 @@ static void xilinx_enet_realize(DeviceState *dev, Error **errp)
+
+ qemu_macaddr_default_if_unset(&s->conf.macaddr);
+ s->nic = qemu_new_nic(&net_xilinx_enet_info, &s->conf,
+- object_get_typename(OBJECT(dev)), dev->id, s);
++ object_get_typename(OBJECT(dev)), dev->id,
++ &dev->mem_reentrancy_guard, s);
+ qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
+
+ tdk_init(&s->TEMAC.phy);
+diff --git a/hw/net/xilinx_ethlite.c b/hw/net/xilinx_ethlite.c
+index 6e09f7e422..80cb869e22 100644
+--- a/hw/net/xilinx_ethlite.c
++++ b/hw/net/xilinx_ethlite.c
+@@ -235,7 +235,8 @@ static void xilinx_ethlite_realize(DeviceState *dev, Error **errp)
+
+ qemu_macaddr_default_if_unset(&s->conf.macaddr);
+ s->nic = qemu_new_nic(&net_xilinx_ethlite_info, &s->conf,
+- object_get_typename(OBJECT(dev)), dev->id, s);
++ object_get_typename(OBJECT(dev)), dev->id,
++ &dev->mem_reentrancy_guard, s);
+ qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
+ }
+
+diff --git a/hw/nvram/xlnx-efuse.c b/hw/nvram/xlnx-efuse.c
+index fdfffaab99..aff5254129 100644
+--- a/hw/nvram/xlnx-efuse.c
++++ b/hw/nvram/xlnx-efuse.c
+@@ -217,6 +217,13 @@ static void efuse_realize(DeviceState *dev, Error **errp)
+ }
+ }
+
++static void efuse_finalize(Object *obj)
++{
++ XlnxEFuse *s = XLNX_EFUSE(obj);
++
++ g_free(s->ro_bits);
++}
++
+ static void efuse_prop_set_drive(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
+ {
+@@ -273,6 +280,7 @@ static const TypeInfo efuse_info = {
+ .name = TYPE_XLNX_EFUSE,
+ .parent = TYPE_DEVICE,
+ .instance_size = sizeof(XlnxEFuse),
++ .instance_finalize = efuse_finalize,
+ .class_init = efuse_class_init,
+ };
+
+diff --git a/hw/nvram/xlnx-versal-efuse-ctrl.c b/hw/nvram/xlnx-versal-efuse-ctrl.c
+index b35ba65ab5..2d2dc09526 100644
+--- a/hw/nvram/xlnx-versal-efuse-ctrl.c
++++ b/hw/nvram/xlnx-versal-efuse-ctrl.c
+@@ -725,6 +725,13 @@ static void efuse_ctrl_init(Object *obj)
+ sysbus_init_irq(sbd, &s->irq_efuse_imr);
+ }
+
++static void efuse_ctrl_finalize(Object *obj)
++{
++ XlnxVersalEFuseCtrl *s = XLNX_VERSAL_EFUSE_CTRL(obj);
++
++ g_free(s->extra_pg0_lock_spec);
++}
++
+ static const VMStateDescription vmstate_efuse_ctrl = {
+ .name = TYPE_XLNX_VERSAL_EFUSE_CTRL,
+ .version_id = 1,
+@@ -762,6 +769,7 @@ static const TypeInfo efuse_ctrl_info = {
+ .instance_size = sizeof(XlnxVersalEFuseCtrl),
+ .class_init = efuse_ctrl_class_init,
+ .instance_init = efuse_ctrl_init,
++ .instance_finalize = efuse_ctrl_finalize,
+ };
+
+ static void efuse_ctrl_register_types(void)
+diff --git a/hw/pci/msix.c b/hw/pci/msix.c
+index 9e70fcd6fa..4b258566d4 100644
+--- a/hw/pci/msix.c
++++ b/hw/pci/msix.c
+@@ -639,6 +639,7 @@ undo:
+ }
+ dev->msix_vector_use_notifier = NULL;
+ dev->msix_vector_release_notifier = NULL;
++ dev->msix_vector_poll_notifier = NULL;
+ return ret;
+ }
+
+diff --git a/hw/pci/pcie_sriov.c b/hw/pci/pcie_sriov.c
+index 8e3faf1f59..61a4e06768 100644
+--- a/hw/pci/pcie_sriov.c
++++ b/hw/pci/pcie_sriov.c
+@@ -178,7 +178,6 @@ static void register_vfs(PCIDevice *dev)
+ num_vfs = pci_get_word(dev->config + sriov_cap + PCI_SRIOV_NUM_VF);
+
+ dev->exp.sriov_pf.vf = g_new(PCIDevice *, num_vfs);
+- assert(dev->exp.sriov_pf.vf);
+
+ trace_sriov_register_vfs(dev->name, PCI_SLOT(dev->devfn),
+ PCI_FUNC(dev->devfn), num_vfs);
+diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c
+index 5fff487ee5..2c33e36cad 100644
+--- a/hw/usb/dev-network.c
++++ b/hw/usb/dev-network.c
+@@ -1386,7 +1386,8 @@ static void usb_net_realize(USBDevice *dev, Error **errp)
+
+ qemu_macaddr_default_if_unset(&s->conf.macaddr);
+ s->nic = qemu_new_nic(&net_usbnet_info, &s->conf,
+- object_get_typename(OBJECT(s)), s->dev.qdev.id, s);
++ object_get_typename(OBJECT(s)), s->dev.qdev.id,
++ &s->dev.qdev.mem_reentrancy_guard, s);
+ qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
+ snprintf(s->usbstring_mac, sizeof(s->usbstring_mac),
+ "%02x%02x%02x%02x%02x%02x",
+diff --git a/hw/virtio/virtio-iommu-pci.c b/hw/virtio/virtio-iommu-pci.c
+index 7ef2f9dcdb..eab6e1c793 100644
+--- a/hw/virtio/virtio-iommu-pci.c
++++ b/hw/virtio/virtio-iommu-pci.c
+@@ -95,10 +95,18 @@ static void virtio_iommu_pci_instance_init(Object *obj)
+ TYPE_VIRTIO_IOMMU);
+ }
+
++static void virtio_iommu_pci_instance_finalize(Object *obj)
++{
++ VirtIOIOMMUPCI *dev = VIRTIO_IOMMU_PCI(obj);
++
++ g_free(dev->vdev.reserved_regions);
++}
++
+ static const VirtioPCIDeviceTypeInfo virtio_iommu_pci_info = {
+ .generic_name = TYPE_VIRTIO_IOMMU_PCI,
+ .instance_size = sizeof(VirtIOIOMMUPCI),
+ .instance_init = virtio_iommu_pci_instance_init,
++ .instance_finalize = virtio_iommu_pci_instance_finalize,
+ .class_init = virtio_iommu_pci_class_init,
+ };
+
+diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
+index 67e771c373..e5e74a7160 100644
+--- a/hw/virtio/virtio-pci.c
++++ b/hw/virtio/virtio-pci.c
+@@ -2174,6 +2174,7 @@ void virtio_pci_types_register(const VirtioPCIDeviceTypeInfo *t)
+ .parent = t->parent ? t->parent : TYPE_VIRTIO_PCI,
+ .instance_size = t->instance_size,
+ .instance_init = t->instance_init,
++ .instance_finalize = t->instance_finalize,
+ .class_size = t->class_size,
+ .abstract = true,
+ .interfaces = t->interfaces,
+diff --git a/include/hw/virtio/virtio-pci.h b/include/hw/virtio/virtio-pci.h
+index 938799e8f6..c4676ff4d4 100644
+--- a/include/hw/virtio/virtio-pci.h
++++ b/include/hw/virtio/virtio-pci.h
+@@ -241,6 +241,7 @@ typedef struct VirtioPCIDeviceTypeInfo {
+ size_t instance_size;
+ size_t class_size;
+ void (*instance_init)(Object *obj);
++ void (*instance_finalize)(Object *obj);
+ void (*class_init)(ObjectClass *klass, void *data);
+ InterfaceInfo *interfaces;
+ } VirtioPCIDeviceTypeInfo;
+diff --git a/include/net/net.h b/include/net/net.h
+index dc20b31e9f..5a7c0e9ebf 100644
+--- a/include/net/net.h
++++ b/include/net/net.h
+@@ -118,6 +118,7 @@ struct NetClientState {
+ typedef struct NICState {
+ NetClientState *ncs;
+ NICConf *conf;
++ MemReentrancyGuard *reentrancy_guard;
+ void *opaque;
+ bool peer_deleted;
+ } NICState;
+@@ -151,6 +152,7 @@ NICState *qemu_new_nic(NetClientInfo *info,
+ NICConf *conf,
+ const char *model,
+ const char *name,
++ MemReentrancyGuard *reentrancy_guard,
+ void *opaque);
+ void qemu_del_nic(NICState *nic);
+ NetClientState *qemu_get_subqueue(NICState *nic, int queue_index);
+diff --git a/linux-user/elfload.c b/linux-user/elfload.c
+index c2c095d383..87895847ec 100644
+--- a/linux-user/elfload.c
++++ b/linux-user/elfload.c
+@@ -3001,7 +3001,7 @@ static void load_elf_image(const char *image_name, int image_fd,
+ for (i = 0; i < ehdr->e_phnum; ++i) {
+ struct elf_phdr *eppnt = phdr + i;
+ if (eppnt->p_type == PT_LOAD) {
+- abi_ulong a = eppnt->p_vaddr - eppnt->p_offset;
++ abi_ulong a = eppnt->p_vaddr & TARGET_PAGE_MASK;
+ if (a < loaddr) {
+ loaddr = a;
+ }
+diff --git a/net/net.c b/net/net.c
+index 840ad9dca5..c3391168f6 100644
+--- a/net/net.c
++++ b/net/net.c
+@@ -319,6 +319,7 @@ NICState *qemu_new_nic(NetClientInfo *info,
+ NICConf *conf,
+ const char *model,
+ const char *name,
++ MemReentrancyGuard *reentrancy_guard,
+ void *opaque)
+ {
+ NetClientState **peers = conf->peers.ncs;
+@@ -331,6 +332,7 @@ NICState *qemu_new_nic(NetClientInfo *info,
+ nic = g_malloc0(info->size + sizeof(NetClientState) * queues);
+ nic->ncs = (void *)nic + info->size;
+ nic->conf = conf;
++ nic->reentrancy_guard = reentrancy_guard,
+ nic->opaque = opaque;
+
+ for (i = 0; i < queues; i++) {
+@@ -786,6 +788,7 @@ static ssize_t qemu_deliver_packet_iov(NetClientState *sender,
+ int iovcnt,
+ void *opaque)
+ {
++ MemReentrancyGuard *owned_reentrancy_guard;
+ NetClientState *nc = opaque;
+ int ret;
+
+@@ -798,12 +801,24 @@ static ssize_t qemu_deliver_packet_iov(NetClientState *sender,
+ return 0;
+ }
+
++ if (nc->info->type != NET_CLIENT_DRIVER_NIC ||
++ qemu_get_nic(nc)->reentrancy_guard->engaged_in_io) {
++ owned_reentrancy_guard = NULL;
++ } else {
++ owned_reentrancy_guard = qemu_get_nic(nc)->reentrancy_guard;
++ owned_reentrancy_guard->engaged_in_io = true;
++ }
++
+ if (nc->info->receive_iov && !(flags & QEMU_NET_PACKET_FLAG_RAW)) {
+ ret = nc->info->receive_iov(nc, iov, iovcnt);
+ } else {
+ ret = nc_sendv_compat(nc, iov, iovcnt, flags);
+ }
+
++ if (owned_reentrancy_guard) {
++ owned_reentrancy_guard->engaged_in_io = false;
++ }
++
+ if (ret == 0) {
+ nc->receive_disabled = 1;
+ }
+diff --git a/softmmu/memory.c b/softmmu/memory.c
+index 61569f8306..2b03596bc7 100644
+--- a/softmmu/memory.c
++++ b/softmmu/memory.c
+@@ -1326,22 +1326,7 @@ static uint64_t memory_region_ram_device_read(void *opaque,
+ hwaddr addr, unsigned size)
+ {
+ MemoryRegion *mr = opaque;
+- uint64_t data = (uint64_t)~0;
+-
+- switch (size) {
+- case 1:
+- data = *(uint8_t *)(mr->ram_block->host + addr);
+- break;
+- case 2:
+- data = *(uint16_t *)(mr->ram_block->host + addr);
+- break;
+- case 4:
+- data = *(uint32_t *)(mr->ram_block->host + addr);
+- break;
+- case 8:
+- data = *(uint64_t *)(mr->ram_block->host + addr);
+- break;
+- }
++ uint64_t data = ldn_he_p(mr->ram_block->host + addr, size);
+
+ trace_memory_region_ram_device_read(get_cpu_index(), mr, addr, data, size);
+
+@@ -1355,20 +1340,7 @@ static void memory_region_ram_device_write(void *opaque, hwaddr addr,
+
+ trace_memory_region_ram_device_write(get_cpu_index(), mr, addr, data, size);
+
+- switch (size) {
+- case 1:
+- *(uint8_t *)(mr->ram_block->host + addr) = (uint8_t)data;
+- break;
+- case 2:
+- *(uint16_t *)(mr->ram_block->host + addr) = (uint16_t)data;
+- break;
+- case 4:
+- *(uint32_t *)(mr->ram_block->host + addr) = (uint32_t)data;
+- break;
+- case 8:
+- *(uint64_t *)(mr->ram_block->host + addr) = data;
+- break;
+- }
++ stn_he_p(mr->ram_block->host + addr, size, data);
+ }
+
+ static const MemoryRegionOps ram_device_mem_ops = {
+diff --git a/target/arm/cpu.c b/target/arm/cpu.c
+index 38d066c294..6cf7a33591 100644
+--- a/target/arm/cpu.c
++++ b/target/arm/cpu.c
+@@ -1498,6 +1498,16 @@ void arm_cpu_finalize_features(ARMCPU *cpu, Error **errp)
+ return;
+ }
+
++ /*
++ * FEAT_SME is not architecturally dependent on FEAT_SVE (unless
++ * FEAT_SME_FA64 is present). However our implementation currently
++ * assumes it, so if the user asked for sve=off then turn off SME also.
++ * (KVM doesn't currently support SME at all.)
++ */
++ if (cpu_isar_feature(aa64_sme, cpu) && !cpu_isar_feature(aa64_sve, cpu)) {
++ object_property_set_bool(OBJECT(cpu), "sme", false, &error_abort);
++ }
++
+ arm_cpu_sme_finalize(cpu, &local_err);
+ if (local_err != NULL) {
+ error_propagate(errp, local_err);
+diff --git a/target/arm/helper.c b/target/arm/helper.c
+index a52ef3dfe4..02cfeece45 100644
+--- a/target/arm/helper.c
++++ b/target/arm/helper.c
+@@ -1431,6 +1431,22 @@ static void pmcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
+ pmu_op_finish(env);
+ }
+
++static uint64_t pmcr_read(CPUARMState *env, const ARMCPRegInfo *ri)
++{
++ uint64_t pmcr = env->cp15.c9_pmcr;
++
++ /*
++ * If EL2 is implemented and enabled for the current security state, reads
++ * of PMCR.N from EL1 or EL0 return the value of MDCR_EL2.HPMN or HDCR.HPMN.
++ */
++ if (arm_current_el(env) <= 1 && arm_is_el2_enabled(env)) {
++ pmcr &= ~PMCRN_MASK;
++ pmcr |= (env->cp15.mdcr_el2 & MDCR_HPMN) << PMCRN_SHIFT;
++ }
++
++ return pmcr;
++}
++
+ static void pmswinc_write(CPUARMState *env, const ARMCPRegInfo *ri,
+ uint64_t value)
+ {
+@@ -6499,8 +6515,9 @@ static void define_pmu_regs(ARMCPU *cpu)
+ .access = PL0_RW,
+ .type = ARM_CP_IO | ARM_CP_ALIAS,
+ .fieldoffset = offsetoflow32(CPUARMState, cp15.c9_pmcr),
+- .accessfn = pmreg_access, .writefn = pmcr_write,
+- .raw_writefn = raw_write,
++ .accessfn = pmreg_access,
++ .readfn = pmcr_read, .raw_readfn = raw_read,
++ .writefn = pmcr_write, .raw_writefn = raw_write,
+ };
+ ARMCPRegInfo pmcr64 = {
+ .name = "PMCR_EL0", .state = ARM_CP_STATE_AA64,
+@@ -6509,6 +6526,7 @@ static void define_pmu_regs(ARMCPU *cpu)
+ .type = ARM_CP_IO,
+ .fieldoffset = offsetof(CPUARMState, cp15.c9_pmcr),
+ .resetvalue = cpu->isar.reset_pmcr_el0,
++ .readfn = pmcr_read, .raw_readfn = raw_read,
+ .writefn = pmcr_write, .raw_writefn = raw_write,
+ };
+
+diff --git a/target/arm/sme_helper.c b/target/arm/sme_helper.c
+index 73dd838330..8856773635 100644
+--- a/target/arm/sme_helper.c
++++ b/target/arm/sme_helper.c
+@@ -1070,10 +1070,9 @@ void HELPER(sme_fmopa_h)(void *vza, void *vzn, void *vzm, void *vpn,
+
+ m = f16mop_adj_pair(m, pcol, 0);
+ *a = f16_dotadd(*a, n, m, &fpst_std, &fpst_odd);
+-
+- col += 4;
+- pcol >>= 4;
+ }
++ col += 4;
++ pcol >>= 4;
+ } while (col & 15);
+ }
+ row += 4;
+@@ -1106,10 +1105,9 @@ void HELPER(sme_bfmopa)(void *vza, void *vzn, void *vzm, void *vpn,
+
+ m = f16mop_adj_pair(m, pcol, 0);
+ *a = bfdotadd(*a, n, m);
+-
+- col += 4;
+- pcol >>= 4;
+ }
++ col += 4;
++ pcol >>= 4;
+ } while (col & 15);
+ }
+ row += 4;
+diff --git a/target/arm/syndrome.h b/target/arm/syndrome.h
+index 73df5e3793..15334a3d15 100644
+--- a/target/arm/syndrome.h
++++ b/target/arm/syndrome.h
+@@ -212,7 +212,7 @@ static inline uint32_t syn_simd_access_trap(int cv, int cond, bool is_16bit)
+
+ static inline uint32_t syn_sve_access_trap(void)
+ {
+- return EC_SVEACCESSTRAP << ARM_EL_EC_SHIFT;
++ return (EC_SVEACCESSTRAP << ARM_EL_EC_SHIFT) | ARM_EL_IL;
+ }
+
+ static inline uint32_t syn_smetrap(SMEExceptionType etype, bool is_16bit)
+@@ -223,12 +223,12 @@ static inline uint32_t syn_smetrap(SMEExceptionType etype, bool is_16bit)
+
+ static inline uint32_t syn_pactrap(void)
+ {
+- return EC_PACTRAP << ARM_EL_EC_SHIFT;
++ return (EC_PACTRAP << ARM_EL_EC_SHIFT) | ARM_EL_IL;
+ }
+
+ static inline uint32_t syn_btitrap(int btype)
+ {
+- return (EC_BTITRAP << ARM_EL_EC_SHIFT) | btype;
++ return (EC_BTITRAP << ARM_EL_EC_SHIFT) | ARM_EL_IL | btype;
+ }
+
+ static inline uint32_t syn_bxjtrap(int cv, int cond, int rm)
+diff --git a/tests/avocado/cpu_queries.py b/tests/avocado/cpu_queries.py
+index cf69f69b11..295642772e 100644
+--- a/tests/avocado/cpu_queries.py
++++ b/tests/avocado/cpu_queries.py
+@@ -31,4 +31,4 @@ def test(self):
+ for c in cpus:
+ model = {'name': c['name']}
+ e = self.vm.command('query-cpu-model-expansion', model=model, type='full')
+- self.assertEquals(e['model']['name'], c['name'])
++ self.assertEqual(e['model']['name'], c['name'])
+diff --git a/tests/avocado/empty_cpu_model.py b/tests/avocado/empty_cpu_model.py
+index 22f504418d..d906ef3d3c 100644
+--- a/tests/avocado/empty_cpu_model.py
++++ b/tests/avocado/empty_cpu_model.py
+@@ -15,5 +15,5 @@ def test(self):
+ self.vm.set_qmp_monitor(enabled=False)
+ self.vm.launch()
+ self.vm.wait()
+- self.assertEquals(self.vm.exitcode(), 1, "QEMU exit code should be 1")
++ self.assertEqual(self.vm.exitcode(), 1, "QEMU exit code should be 1")
+ self.assertRegex(self.vm.get_log(), r'-cpu option cannot be empty')
+diff --git a/tests/avocado/pc_cpu_hotplug_props.py b/tests/avocado/pc_cpu_hotplug_props.py
+index 52b878188e..6100fb7760 100644
+--- a/tests/avocado/pc_cpu_hotplug_props.py
++++ b/tests/avocado/pc_cpu_hotplug_props.py
+@@ -32,4 +32,4 @@ def test_no_die_id(self):
+ self.vm.add_args('-smp', '1,sockets=2,cores=2,threads=2,maxcpus=8')
+ self.vm.add_args('-device', 'qemu64-x86_64-cpu,socket-id=1,core-id=0,thread-id=0')
+ self.vm.launch()
+- self.assertEquals(len(self.vm.command('query-cpus-fast')), 2)
++ self.assertEqual(len(self.vm.command('query-cpus-fast')), 2)
+diff --git a/tests/avocado/version.py b/tests/avocado/version.py
+index ded7f039c1..5f88ff300b 100644
+--- a/tests/avocado/version.py
++++ b/tests/avocado/version.py
+@@ -21,4 +21,4 @@ def test_qmp_human_info_version(self):
+ self.vm.launch()
+ res = self.vm.command('human-monitor-command',
+ command_line='info version')
+- self.assertRegexpMatches(res, r'^(\d+\.\d+\.\d)')
++ self.assertRegex(res, r'^(\d+\.\d+\.\d)')
+diff --git a/tests/avocado/x86_cpu_model_versions.py b/tests/avocado/x86_cpu_model_versions.py
+index a6edf74c1c..262d6a77fb 100644
+--- a/tests/avocado/x86_cpu_model_versions.py
++++ b/tests/avocado/x86_cpu_model_versions.py
+@@ -119,94 +119,95 @@ def test_4_1_alias(self):
+
+ self.assertFalse(cpus['Cascadelake-Server']['static'],
+ 'unversioned Cascadelake-Server CPU model must not be static')
+- self.assertEquals(cpus['Cascadelake-Server'].get('alias-of'), 'Cascadelake-Server-v1',
+- 'Cascadelake-Server must be an alias of Cascadelake-Server-v1')
++ self.assertEqual(cpus['Cascadelake-Server'].get('alias-of'),
++ 'Cascadelake-Server-v1',
++ 'Cascadelake-Server must be an alias of Cascadelake-Server-v1')
+ self.assertNotIn('alias-of', cpus['Cascadelake-Server-v1'],
+ 'Cascadelake-Server-v1 must not be an alias')
+
+ self.assertFalse(cpus['qemu64']['static'],
+ 'unversioned qemu64 CPU model must not be static')
+- self.assertEquals(cpus['qemu64'].get('alias-of'), 'qemu64-v1',
+- 'qemu64 must be an alias of qemu64-v1')
++ self.assertEqual(cpus['qemu64'].get('alias-of'), 'qemu64-v1',
++ 'qemu64 must be an alias of qemu64-v1')
+ self.assertNotIn('alias-of', cpus['qemu64-v1'],
+ 'qemu64-v1 must not be an alias')
+
+ self.validate_variant_aliases(cpus)
+
+ # On pc-*-4.1, -noTSX and -IBRS models should be aliases:
+- self.assertEquals(cpus["Haswell"].get('alias-of'),
+- "Haswell-v1",
++ self.assertEqual(cpus["Haswell"].get('alias-of'),
++ "Haswell-v1",
+ "Haswell must be an alias")
+- self.assertEquals(cpus["Haswell-noTSX"].get('alias-of'),
+- "Haswell-v2",
++ self.assertEqual(cpus["Haswell-noTSX"].get('alias-of'),
++ "Haswell-v2",
+ "Haswell-noTSX must be an alias")
+- self.assertEquals(cpus["Haswell-IBRS"].get('alias-of'),
+- "Haswell-v3",
++ self.assertEqual(cpus["Haswell-IBRS"].get('alias-of'),
++ "Haswell-v3",
+ "Haswell-IBRS must be an alias")
+- self.assertEquals(cpus["Haswell-noTSX-IBRS"].get('alias-of'),
+- "Haswell-v4",
++ self.assertEqual(cpus["Haswell-noTSX-IBRS"].get('alias-of'),
++ "Haswell-v4",
+ "Haswell-noTSX-IBRS must be an alias")
+
+- self.assertEquals(cpus["Broadwell"].get('alias-of'),
+- "Broadwell-v1",
++ self.assertEqual(cpus["Broadwell"].get('alias-of'),
++ "Broadwell-v1",
+ "Broadwell must be an alias")
+- self.assertEquals(cpus["Broadwell-noTSX"].get('alias-of'),
+- "Broadwell-v2",
++ self.assertEqual(cpus["Broadwell-noTSX"].get('alias-of'),
++ "Broadwell-v2",
+ "Broadwell-noTSX must be an alias")
+- self.assertEquals(cpus["Broadwell-IBRS"].get('alias-of'),
+- "Broadwell-v3",
++ self.assertEqual(cpus["Broadwell-IBRS"].get('alias-of'),
++ "Broadwell-v3",
+ "Broadwell-IBRS must be an alias")
+- self.assertEquals(cpus["Broadwell-noTSX-IBRS"].get('alias-of'),
+- "Broadwell-v4",
++ self.assertEqual(cpus["Broadwell-noTSX-IBRS"].get('alias-of'),
++ "Broadwell-v4",
+ "Broadwell-noTSX-IBRS must be an alias")
+
+- self.assertEquals(cpus["Nehalem"].get('alias-of'),
+- "Nehalem-v1",
++ self.assertEqual(cpus["Nehalem"].get('alias-of'),
++ "Nehalem-v1",
+ "Nehalem must be an alias")
+- self.assertEquals(cpus["Nehalem-IBRS"].get('alias-of'),
+- "Nehalem-v2",
++ self.assertEqual(cpus["Nehalem-IBRS"].get('alias-of'),
++ "Nehalem-v2",
+ "Nehalem-IBRS must be an alias")
+
+- self.assertEquals(cpus["Westmere"].get('alias-of'),
+- "Westmere-v1",
++ self.assertEqual(cpus["Westmere"].get('alias-of'),
++ "Westmere-v1",
+ "Westmere must be an alias")
+- self.assertEquals(cpus["Westmere-IBRS"].get('alias-of'),
+- "Westmere-v2",
++ self.assertEqual(cpus["Westmere-IBRS"].get('alias-of'),
++ "Westmere-v2",
+ "Westmere-IBRS must be an alias")
+
+- self.assertEquals(cpus["SandyBridge"].get('alias-of'),
+- "SandyBridge-v1",
++ self.assertEqual(cpus["SandyBridge"].get('alias-of'),
++ "SandyBridge-v1",
+ "SandyBridge must be an alias")
+- self.assertEquals(cpus["SandyBridge-IBRS"].get('alias-of'),
+- "SandyBridge-v2",
++ self.assertEqual(cpus["SandyBridge-IBRS"].get('alias-of'),
++ "SandyBridge-v2",
+ "SandyBridge-IBRS must be an alias")
+
+- self.assertEquals(cpus["IvyBridge"].get('alias-of'),
+- "IvyBridge-v1",
++ self.assertEqual(cpus["IvyBridge"].get('alias-of'),
++ "IvyBridge-v1",
+ "IvyBridge must be an alias")
+- self.assertEquals(cpus["IvyBridge-IBRS"].get('alias-of'),
+- "IvyBridge-v2",
++ self.assertEqual(cpus["IvyBridge-IBRS"].get('alias-of'),
++ "IvyBridge-v2",
+ "IvyBridge-IBRS must be an alias")
+
+- self.assertEquals(cpus["Skylake-Client"].get('alias-of'),
+- "Skylake-Client-v1",
++ self.assertEqual(cpus["Skylake-Client"].get('alias-of'),
++ "Skylake-Client-v1",
+ "Skylake-Client must be an alias")
+- self.assertEquals(cpus["Skylake-Client-IBRS"].get('alias-of'),
+- "Skylake-Client-v2",
++ self.assertEqual(cpus["Skylake-Client-IBRS"].get('alias-of'),
++ "Skylake-Client-v2",
+ "Skylake-Client-IBRS must be an alias")
+
+- self.assertEquals(cpus["Skylake-Server"].get('alias-of'),
+- "Skylake-Server-v1",
++ self.assertEqual(cpus["Skylake-Server"].get('alias-of'),
++ "Skylake-Server-v1",
+ "Skylake-Server must be an alias")
+- self.assertEquals(cpus["Skylake-Server-IBRS"].get('alias-of'),
+- "Skylake-Server-v2",
++ self.assertEqual(cpus["Skylake-Server-IBRS"].get('alias-of'),
++ "Skylake-Server-v2",
+ "Skylake-Server-IBRS must be an alias")
+
+- self.assertEquals(cpus["EPYC"].get('alias-of'),
+- "EPYC-v1",
++ self.assertEqual(cpus["EPYC"].get('alias-of'),
++ "EPYC-v1",
+ "EPYC must be an alias")
+- self.assertEquals(cpus["EPYC-IBPB"].get('alias-of'),
+- "EPYC-v2",
++ self.assertEqual(cpus["EPYC-IBPB"].get('alias-of'),
++ "EPYC-v2",
+ "EPYC-IBPB must be an alias")
+
+ self.validate_aliases(cpus)
+diff --git a/tests/qemu-iotests/059 b/tests/qemu-iotests/059
+index e8be217e1f..9bcf1e7525 100755
+--- a/tests/qemu-iotests/059
++++ b/tests/qemu-iotests/059
+@@ -84,6 +84,8 @@ echo
+ echo "=== Testing big twoGbMaxExtentFlat ==="
+ _make_test_img -o "subformat=twoGbMaxExtentFlat" 1000G
+ _img_info --format-specific | _filter_img_info --format-specific
++$QEMU_IO -c "write 990G 512 -P 89" "$TEST_IMG" | _filter_qemu_io
++$QEMU_IO -c "read 990G 512 -P 89" "$TEST_IMG" | _filter_qemu_io
+ _cleanup_test_img
+
+ echo
+diff --git a/tests/qemu-iotests/059.out b/tests/qemu-iotests/059.out
+index 2b83c0c8b6..275ee7c778 100644
+--- a/tests/qemu-iotests/059.out
++++ b/tests/qemu-iotests/059.out
+@@ -2032,6 +2032,10 @@ Format specific information:
+ virtual size: 2147483648
+ filename: TEST_DIR/t-f500.IMGFMT
+ format: FLAT
++wrote 512/512 bytes at offset 1063004405760
++512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
++read 512/512 bytes at offset 1063004405760
++512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+ === Testing malformed VMFS extent description line ===
+ qemu-img: Could not open 'TEST_DIR/t.IMGFMT': Invalid extent line: RW 12582912 VMFS "dummy.IMGFMT" 1
+diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c
+index 52c6246a33..7ff9f1648c 100644
+--- a/ui/gtk-egl.c
++++ b/ui/gtk-egl.c
+@@ -234,6 +234,13 @@ void gd_egl_scanout_texture(DisplayChangeListener *dcl,
+ vc->gfx.h = h;
+ vc->gfx.y0_top = backing_y_0_top;
+
++ if (!vc->gfx.esurface) {
++ gd_egl_init(vc);
++ if (!vc->gfx.esurface) {
++ return;
++ }
++ }
++
+ eglMakeCurrent(qemu_egl_display, vc->gfx.esurface,
+ vc->gfx.esurface, vc->gfx.ectx);
+
+diff --git a/ui/vnc-clipboard.c b/ui/vnc-clipboard.c
+index c759be3438..124b6fbd9c 100644
+--- a/ui/vnc-clipboard.c
++++ b/ui/vnc-clipboard.c
+@@ -69,6 +69,11 @@ static uint8_t *inflate_buffer(uint8_t *in, uint32_t in_len, uint32_t *size)
+ }
+ }
+
++ *size = stream.total_out;
++ inflateEnd(&stream);
++
++ return out;
++
+ err_end:
+ inflateEnd(&stream);
+ err:
diff --git a/debian/patches/v7.2.9.diff b/debian/patches/v7.2.9.diff
new file mode 100644
index 00000000..57ed18b6
--- /dev/null
+++ b/debian/patches/v7.2.9.diff
@@ -0,0 +1,3566 @@
+Subject: v7.2.9
+Date: Mon Jan 29 12:49:21 2024 +0300
+Tagger: Michael Tokarev <mjt@tls.msk.ru>
+Forwarded: not-needed
+
+This is a difference between upstream qemu v7.2.9
+and upstream qemu v7.2.9.
+
+ .gitlab-ci.d/buildtest.yml | 5 +-
+ .readthedocs.yml | 19 +-
+ VERSION | 2 +-
+ accel/tcg/cpu-exec.c | 4 +-
+ accel/tcg/tb-maint.c | 6 +-
+ accel/tcg/translate-all.c | 2 -
+ block/blklogwrites.c | 35 ++-
+ block/io.c | 10 +
+ block/snapshot.c | 4 +-
+ chardev/char.c | 2 +-
+ docs/requirements.txt | 2 +
+ hw/block/pflash_cfi01.c | 171 ++++++------
+ hw/block/pflash_cfi02.c | 2 +-
+ hw/block/trace-events | 7 +-
+ hw/intc/arm_gicv3_cpuif.c | 17 +-
+ hw/net/virtio-net.c | 13 +-
+ hw/scsi/esp-pci.c | 61 ++--
+ include/exec/exec-all.h | 6 -
+ include/hw/elf_ops.h | 2 +-
+ monitor/qmp.c | 17 --
+ qapi/qmp-dispatch.c | 24 +-
+ softmmu/vl.c | 4 +
+ target/i386/cpu.h | 9 +-
+ target/i386/tcg/tcg-cpu.c | 25 +-
+ target/i386/tcg/translate.c | 22 +-
+ target/riscv/csr.c | 14 +-
+ target/s390x/tcg/translate.c | 3 +-
+ target/xtensa/mmu_helper.c | 47 +++-
+ tests/qemu-iotests/060.out | 4 +-
+ tests/qemu-iotests/071.out | 4 +-
+ tests/qemu-iotests/081.out | 16 +-
+ tests/qemu-iotests/087.out | 12 +-
+ tests/qemu-iotests/108.out | 2 +-
+ tests/qemu-iotests/109 | 4 +-
+ tests/qemu-iotests/109.out | 78 +++---
+ tests/qemu-iotests/117.out | 2 +-
+ tests/qemu-iotests/120.out | 2 +-
+ tests/qemu-iotests/127.out | 2 +-
+ tests/qemu-iotests/140.out | 2 +-
+ tests/qemu-iotests/141 | 307 +++++++++------------
+ tests/qemu-iotests/141.out | 200 +++-----------
+ tests/qemu-iotests/143.out | 2 +-
+ tests/qemu-iotests/156.out | 2 +-
+ tests/qemu-iotests/176.out | 16 +-
+ tests/qemu-iotests/182.out | 2 +-
+ tests/qemu-iotests/183.out | 4 +-
+ tests/qemu-iotests/184.out | 32 +--
+ tests/qemu-iotests/185 | 6 +-
+ tests/qemu-iotests/185.out | 45 ++-
+ tests/qemu-iotests/191.out | 16 +-
+ tests/qemu-iotests/195.out | 16 +-
+ tests/qemu-iotests/223.out | 12 +-
+ tests/qemu-iotests/227.out | 32 +--
+ tests/qemu-iotests/247.out | 2 +-
+ tests/qemu-iotests/273.out | 8 +-
+ tests/qemu-iotests/308 | 4 +-
+ tests/qemu-iotests/308.out | 2 +-
+ tests/qemu-iotests/iotests.py | 7 +
+ tests/qemu-iotests/tests/qcow2-internal-snapshots | 170 ++++++++++++
+ .../tests/qcow2-internal-snapshots.out | 107 +++++++
+ tests/qemu-iotests/tests/qsd-jobs.out | 4 +-
+ tests/qtest/meson.build | 1 +
+ 62 files changed, 979 insertions(+), 681 deletions(-)
+
+diff --git a/.gitlab-ci.d/buildtest.yml b/.gitlab-ci.d/buildtest.yml
+index 10886bb414..7243b8079b 100644
+--- a/.gitlab-ci.d/buildtest.yml
++++ b/.gitlab-ci.d/buildtest.yml
+@@ -637,7 +637,10 @@ pages:
+ - mkdir -p public
+ # HTML-ised source tree
+ - make gtags
+- - htags -anT --tree-view=filetree -m qemu_init
++ # We unset variables to work around a bug in some htags versions
++ # which causes it to fail when the environment is large
++ - CI_COMMIT_MESSAGE= CI_COMMIT_TAG_MESSAGE= htags
++ -anT --tree-view=filetree -m qemu_init
+ -t "Welcome to the QEMU sourcecode"
+ - mv HTML public/src
+ # Project documentation
+diff --git a/.readthedocs.yml b/.readthedocs.yml
+index 7fb7b8dd61..0b262469ce 100644
+--- a/.readthedocs.yml
++++ b/.readthedocs.yml
+@@ -5,16 +5,21 @@
+ # Required
+ version: 2
+
++# Set the version of Python and other tools you might need
++build:
++ os: ubuntu-22.04
++ tools:
++ python: "3.11"
++
+ # Build documentation in the docs/ directory with Sphinx
+ sphinx:
+ configuration: docs/conf.py
+
++# We recommend specifying your dependencies to enable reproducible builds:
++# https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html
++python:
++ install:
++ - requirements: docs/requirements.txt
++
+ # We want all the document formats
+ formats: all
+-
+-# For consistency, we require that QEMU's Sphinx extensions
+-# run with at least the same minimum version of Python that
+-# we require for other Python in our codebase (our conf.py
+-# enforces this, and some code needs it.)
+-python:
+- version: 3.6
+diff --git a/VERSION b/VERSION
+index 31554632ab..672f66a613 100644
+--- a/VERSION
++++ b/VERSION
+@@ -1 +1 @@
+-7.2.8
++7.2.9
+diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
+index 356fe348de..68fef3e01f 100644
+--- a/accel/tcg/cpu-exec.c
++++ b/accel/tcg/cpu-exec.c
+@@ -186,7 +186,7 @@ static bool tb_lookup_cmp(const void *p, const void *d)
+ const TranslationBlock *tb = p;
+ const struct tb_desc *desc = d;
+
+- if ((TARGET_TB_PCREL || tb_pc(tb) == desc->pc) &&
++ if (tb_pc(tb) == desc->pc &&
+ tb_page_addr0(tb) == desc->page_addr0 &&
+ tb->cs_base == desc->cs_base &&
+ tb->flags == desc->flags &&
+@@ -238,7 +238,7 @@ static TranslationBlock *tb_htable_lookup(CPUState *cpu, target_ulong pc,
+ return NULL;
+ }
+ desc.page_addr0 = phys_pc;
+- h = tb_hash_func(phys_pc, (TARGET_TB_PCREL ? 0 : pc),
++ h = tb_hash_func(phys_pc, pc,
+ flags, cflags, *cpu->trace_dstate);
+ return qht_lookup_custom(&tb_ctx.htable, &desc, h, tb_lookup_cmp);
+ }
+diff --git a/accel/tcg/tb-maint.c b/accel/tcg/tb-maint.c
+index 0cdb35548c..9d9f651c78 100644
+--- a/accel/tcg/tb-maint.c
++++ b/accel/tcg/tb-maint.c
+@@ -34,7 +34,7 @@ static bool tb_cmp(const void *ap, const void *bp)
+ const TranslationBlock *a = ap;
+ const TranslationBlock *b = bp;
+
+- return ((TARGET_TB_PCREL || tb_pc(a) == tb_pc(b)) &&
++ return (tb_pc(a) == tb_pc(b) &&
+ a->cs_base == b->cs_base &&
+ a->flags == b->flags &&
+ (tb_cflags(a) & ~CF_INVALID) == (tb_cflags(b) & ~CF_INVALID) &&
+@@ -269,7 +269,7 @@ static void do_tb_phys_invalidate(TranslationBlock *tb, bool rm_from_page_list)
+
+ /* remove the TB from the hash list */
+ phys_pc = tb_page_addr0(tb);
+- h = tb_hash_func(phys_pc, (TARGET_TB_PCREL ? 0 : tb_pc(tb)),
++ h = tb_hash_func(phys_pc, tb_pc(tb),
+ tb->flags, orig_cflags, tb->trace_vcpu_dstate);
+ if (!qht_remove(&tb_ctx.htable, tb, h)) {
+ return;
+@@ -459,7 +459,7 @@ TranslationBlock *tb_link_page(TranslationBlock *tb, tb_page_addr_t phys_pc,
+ }
+
+ /* add in the hash table */
+- h = tb_hash_func(phys_pc, (TARGET_TB_PCREL ? 0 : tb_pc(tb)),
++ h = tb_hash_func(phys_pc, tb_pc(tb),
+ tb->flags, tb->cflags, tb->trace_vcpu_dstate);
+ qht_insert(&tb_ctx.htable, tb, h, &existing_tb);
+
+diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
+index ac3ee3740c..ed8ddee6e8 100644
+--- a/accel/tcg/translate-all.c
++++ b/accel/tcg/translate-all.c
+@@ -818,9 +818,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
+
+ gen_code_buf = tcg_ctx->code_gen_ptr;
+ tb->tc.ptr = tcg_splitwx_to_rx(gen_code_buf);
+-#if !TARGET_TB_PCREL
+ tb->pc = pc;
+-#endif
+ tb->cs_base = cs_base;
+ tb->flags = flags;
+ tb->cflags = cflags;
+diff --git a/block/blklogwrites.c b/block/blklogwrites.c
+index cef9efe55d..ad589c4a2e 100644
+--- a/block/blklogwrites.c
++++ b/block/blklogwrites.c
+@@ -321,22 +321,39 @@ typedef struct {
+ static void coroutine_fn blk_log_writes_co_do_log(BlkLogWritesLogReq *lr)
+ {
+ BDRVBlkLogWritesState *s = lr->bs->opaque;
+- uint64_t cur_log_offset = s->cur_log_sector << s->sectorbits;
+
+- s->nr_entries++;
+- s->cur_log_sector +=
+- ROUND_UP(lr->qiov->size, s->sectorsize) >> s->sectorbits;
++ /*
++ * Determine the offsets and sizes of different parts of the entry, and
++ * update the state of the driver.
++ *
++ * This needs to be done in one go, before any actual I/O is done, as the
++ * log entry may have to be written in two parts, and the state of the
++ * driver may be modified by other driver operations while waiting for the
++ * I/O to complete.
++ */
++ const uint64_t entry_start_sector = s->cur_log_sector;
++ const uint64_t entry_offset = entry_start_sector << s->sectorbits;
++ const uint64_t qiov_aligned_size = ROUND_UP(lr->qiov->size, s->sectorsize);
++ const uint64_t entry_aligned_size = qiov_aligned_size +
++ ROUND_UP(lr->zero_size, s->sectorsize);
++ const uint64_t entry_nr_sectors = entry_aligned_size >> s->sectorbits;
+
+- lr->log_ret = bdrv_co_pwritev(s->log_file, cur_log_offset, lr->qiov->size,
++ s->nr_entries++;
++ s->cur_log_sector += entry_nr_sectors;
++
++ /*
++ * Write the log entry. Note that if this is a "write zeroes" operation,
++ * only the entry header is written here, with the zeroing being done
++ * separately below.
++ */
++ lr->log_ret = bdrv_co_pwritev(s->log_file, entry_offset, lr->qiov->size,
+ lr->qiov, 0);
+
+ /* Logging for the "write zeroes" operation */
+ if (lr->log_ret == 0 && lr->zero_size) {
+- cur_log_offset = s->cur_log_sector << s->sectorbits;
+- s->cur_log_sector +=
+- ROUND_UP(lr->zero_size, s->sectorsize) >> s->sectorbits;
++ const uint64_t zeroes_offset = entry_offset + qiov_aligned_size;
+
+- lr->log_ret = bdrv_co_pwrite_zeroes(s->log_file, cur_log_offset,
++ lr->log_ret = bdrv_co_pwrite_zeroes(s->log_file, zeroes_offset,
+ lr->zero_size, 0);
+ }
+
+diff --git a/block/io.c b/block/io.c
+index bbaa0d1b2d..4589a58917 100644
+--- a/block/io.c
++++ b/block/io.c
+@@ -2595,6 +2595,16 @@ static int coroutine_fn bdrv_co_block_status(BlockDriverState *bs,
+ ret |= (ret2 & BDRV_BLOCK_ZERO);
+ }
+ }
++
++ /*
++ * Now that the recursive search was done, clear the flag. Otherwise,
++ * with more complicated block graphs like snapshot-access ->
++ * copy-before-write -> qcow2, where the return value will be propagated
++ * further up to a parent bdrv_co_do_block_status() call, both the
++ * BDRV_BLOCK_RECURSE and BDRV_BLOCK_ZERO flags would be set, which is
++ * not allowed.
++ */
++ ret &= ~BDRV_BLOCK_RECURSE;
+ }
+
+ out:
+diff --git a/block/snapshot.c b/block/snapshot.c
+index e22ac3eac6..86e29ca59f 100644
+--- a/block/snapshot.c
++++ b/block/snapshot.c
+@@ -190,8 +190,10 @@ static BlockDriverState *bdrv_snapshot_fallback(BlockDriverState *bs)
+ int bdrv_can_snapshot(BlockDriverState *bs)
+ {
+ BlockDriver *drv = bs->drv;
++
+ GLOBAL_STATE_CODE();
+- if (!drv || !bdrv_is_inserted(bs) || bdrv_is_read_only(bs)) {
++
++ if (!drv || !bdrv_is_inserted(bs) || !bdrv_is_writable(bs)) {
+ return 0;
+ }
+
+diff --git a/chardev/char.c b/chardev/char.c
+index b005df3ccf..193bbac054 100644
+--- a/chardev/char.c
++++ b/chardev/char.c
+@@ -519,7 +519,7 @@ static const ChardevClass *char_get_class(const char *driver, Error **errp)
+
+ if (object_class_is_abstract(oc)) {
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "driver",
+- "an abstract device type");
++ "a non-abstract device type");
+ return NULL;
+ }
+
+diff --git a/docs/requirements.txt b/docs/requirements.txt
+new file mode 100644
+index 0000000000..691e5218ec
+--- /dev/null
++++ b/docs/requirements.txt
+@@ -0,0 +1,2 @@
++sphinx==5.3.0
++sphinx_rtd_theme==1.1.1
+diff --git a/hw/block/pflash_cfi01.c b/hw/block/pflash_cfi01.c
+index 0cbc2fb4cb..6bc00254cc 100644
+--- a/hw/block/pflash_cfi01.c
++++ b/hw/block/pflash_cfi01.c
+@@ -81,16 +81,39 @@ struct PFlashCFI01 {
+ uint16_t ident3;
+ uint8_t cfi_table[0x52];
+ uint64_t counter;
+- unsigned int writeblock_size;
++ uint32_t writeblock_size;
+ MemoryRegion mem;
+ char *name;
+ void *storage;
+ VMChangeStateEntry *vmstate;
+ bool old_multiple_chip_handling;
++
++ /* block update buffer */
++ unsigned char *blk_bytes;
++ uint32_t blk_offset;
+ };
+
+ static int pflash_post_load(void *opaque, int version_id);
+
++static bool pflash_blk_write_state_needed(void *opaque)
++{
++ PFlashCFI01 *pfl = opaque;
++
++ return (pfl->blk_offset != -1);
++}
++
++static const VMStateDescription vmstate_pflash_blk_write = {
++ .name = "pflash_cfi01_blk_write",
++ .version_id = 1,
++ .minimum_version_id = 1,
++ .needed = pflash_blk_write_state_needed,
++ .fields = (const VMStateField[]) {
++ VMSTATE_VBUFFER_UINT32(blk_bytes, PFlashCFI01, 0, NULL, writeblock_size),
++ VMSTATE_UINT32(blk_offset, PFlashCFI01),
++ VMSTATE_END_OF_LIST()
++ }
++};
++
+ static const VMStateDescription vmstate_pflash = {
+ .name = "pflash_cfi01",
+ .version_id = 1,
+@@ -102,6 +125,10 @@ static const VMStateDescription vmstate_pflash = {
+ VMSTATE_UINT8(status, PFlashCFI01),
+ VMSTATE_UINT64(counter, PFlashCFI01),
+ VMSTATE_END_OF_LIST()
++ },
++ .subsections = (const VMStateDescription * []) {
++ &vmstate_pflash_blk_write,
++ NULL
+ }
+ };
+
+@@ -226,34 +253,10 @@ static uint32_t pflash_data_read(PFlashCFI01 *pfl, hwaddr offset,
+ uint32_t ret;
+
+ p = pfl->storage;
+- switch (width) {
+- case 1:
+- ret = p[offset];
+- break;
+- case 2:
+- if (be) {
+- ret = p[offset] << 8;
+- ret |= p[offset + 1];
+- } else {
+- ret = p[offset];
+- ret |= p[offset + 1] << 8;
+- }
+- break;
+- case 4:
+- if (be) {
+- ret = p[offset] << 24;
+- ret |= p[offset + 1] << 16;
+- ret |= p[offset + 2] << 8;
+- ret |= p[offset + 3];
+- } else {
+- ret = p[offset];
+- ret |= p[offset + 1] << 8;
+- ret |= p[offset + 2] << 16;
+- ret |= p[offset + 3] << 24;
+- }
+- break;
+- default:
+- abort();
++ if (be) {
++ ret = ldn_be_p(p + offset, width);
++ } else {
++ ret = ldn_le_p(p + offset, width);
+ }
+ trace_pflash_data_read(pfl->name, offset, width, ret);
+ return ret;
+@@ -401,40 +404,61 @@ static void pflash_update(PFlashCFI01 *pfl, int offset,
+ }
+ }
+
++/* copy current flash content to block update buffer */
++static void pflash_blk_write_start(PFlashCFI01 *pfl, hwaddr offset)
++{
++ hwaddr mask = ~(pfl->writeblock_size - 1);
++
++ trace_pflash_write_block_start(pfl->name, pfl->counter);
++ pfl->blk_offset = offset & mask;
++ memcpy(pfl->blk_bytes, pfl->storage + pfl->blk_offset,
++ pfl->writeblock_size);
++}
++
++/* commit block update buffer changes */
++static void pflash_blk_write_flush(PFlashCFI01 *pfl)
++{
++ g_assert(pfl->blk_offset != -1);
++ trace_pflash_write_block_flush(pfl->name);
++ memcpy(pfl->storage + pfl->blk_offset, pfl->blk_bytes,
++ pfl->writeblock_size);
++ pflash_update(pfl, pfl->blk_offset, pfl->writeblock_size);
++ pfl->blk_offset = -1;
++}
++
++/* discard block update buffer changes */
++static void pflash_blk_write_abort(PFlashCFI01 *pfl)
++{
++ trace_pflash_write_block_abort(pfl->name);
++ pfl->blk_offset = -1;
++}
++
+ static inline void pflash_data_write(PFlashCFI01 *pfl, hwaddr offset,
+ uint32_t value, int width, int be)
+ {
+- uint8_t *p = pfl->storage;
++ uint8_t *p;
+
+- trace_pflash_data_write(pfl->name, offset, width, value, pfl->counter);
+- switch (width) {
+- case 1:
+- p[offset] = value;
+- break;
+- case 2:
+- if (be) {
+- p[offset] = value >> 8;
+- p[offset + 1] = value;
+- } else {
+- p[offset] = value;
+- p[offset + 1] = value >> 8;
+- }
+- break;
+- case 4:
+- if (be) {
+- p[offset] = value >> 24;
+- p[offset + 1] = value >> 16;
+- p[offset + 2] = value >> 8;
+- p[offset + 3] = value;
+- } else {
+- p[offset] = value;
+- p[offset + 1] = value >> 8;
+- p[offset + 2] = value >> 16;
+- p[offset + 3] = value >> 24;
++ if (pfl->blk_offset != -1) {
++ /* block write: redirect writes to block update buffer */
++ if ((offset < pfl->blk_offset) ||
++ (offset + width > pfl->blk_offset + pfl->writeblock_size)) {
++ pfl->status |= 0x10; /* Programming error */
++ return;
+ }
+- break;
++ trace_pflash_data_write_block(pfl->name, offset, width, value,
++ pfl->counter);
++ p = pfl->blk_bytes + (offset - pfl->blk_offset);
++ } else {
++ /* write directly to storage */
++ trace_pflash_data_write(pfl->name, offset, width, value);
++ p = pfl->storage + offset;
+ }
+
++ if (be) {
++ stn_be_p(p, width, value);
++ } else {
++ stn_le_p(p, width, value);
++ }
+ }
+
+ static void pflash_write(PFlashCFI01 *pfl, hwaddr offset,
+@@ -549,9 +573,9 @@ static void pflash_write(PFlashCFI01 *pfl, hwaddr offset,
+ } else {
+ value = extract32(value, 0, pfl->bank_width * 8);
+ }
+- trace_pflash_write_block(pfl->name, value);
+ pfl->counter = value;
+ pfl->wcycle++;
++ pflash_blk_write_start(pfl, offset);
+ break;
+ case 0x60:
+ if (cmd == 0xd0) {
+@@ -582,12 +606,7 @@ static void pflash_write(PFlashCFI01 *pfl, hwaddr offset,
+ switch (pfl->cmd) {
+ case 0xe8: /* Block write */
+ /* FIXME check @offset, @width */
+- if (!pfl->ro) {
+- /*
+- * FIXME writing straight to memory is *wrong*. We
+- * should write to a buffer, and flush it to memory
+- * only on confirm command (see below).
+- */
++ if (!pfl->ro && (pfl->blk_offset != -1)) {
+ pflash_data_write(pfl, offset, value, width, be);
+ } else {
+ pfl->status |= 0x10; /* Programming error */
+@@ -596,18 +615,8 @@ static void pflash_write(PFlashCFI01 *pfl, hwaddr offset,
+ pfl->status |= 0x80;
+
+ if (!pfl->counter) {
+- hwaddr mask = pfl->writeblock_size - 1;
+- mask = ~mask;
+-
+ trace_pflash_write(pfl->name, "block write finished");
+ pfl->wcycle++;
+- if (!pfl->ro) {
+- /* Flush the entire write buffer onto backing storage. */
+- /* FIXME premature! */
+- pflash_update(pfl, offset & mask, pfl->writeblock_size);
+- } else {
+- pfl->status |= 0x10; /* Programming error */
+- }
+ }
+
+ pfl->counter--;
+@@ -619,20 +628,17 @@ static void pflash_write(PFlashCFI01 *pfl, hwaddr offset,
+ case 3: /* Confirm mode */
+ switch (pfl->cmd) {
+ case 0xe8: /* Block write */
+- if (cmd == 0xd0) {
+- /* FIXME this is where we should write out the buffer */
++ if ((cmd == 0xd0) && !(pfl->status & 0x10)) {
++ pflash_blk_write_flush(pfl);
+ pfl->wcycle = 0;
+ pfl->status |= 0x80;
+ } else {
+- qemu_log_mask(LOG_UNIMP,
+- "%s: Aborting write to buffer not implemented,"
+- " the data is already written to storage!\n"
+- "Flash device reset into READ mode.\n",
+- __func__);
++ pflash_blk_write_abort(pfl);
+ goto mode_read_array;
+ }
+ break;
+ default:
++ pflash_blk_write_abort(pfl);
+ goto error_flash;
+ }
+ break;
+@@ -866,6 +872,9 @@ static void pflash_cfi01_realize(DeviceState *dev, Error **errp)
+ pfl->cmd = 0x00;
+ pfl->status = 0x80; /* WSM ready */
+ pflash_cfi01_fill_cfi_table(pfl);
++
++ pfl->blk_bytes = g_malloc(pfl->writeblock_size);
++ pfl->blk_offset = -1;
+ }
+
+ static void pflash_cfi01_system_reset(DeviceState *dev)
+@@ -885,6 +894,8 @@ static void pflash_cfi01_system_reset(DeviceState *dev)
+ * This model deliberately ignores this delay.
+ */
+ pfl->status = 0x80;
++
++ pfl->blk_offset = -1;
+ }
+
+ static Property pflash_cfi01_properties[] = {
+diff --git a/hw/block/pflash_cfi02.c b/hw/block/pflash_cfi02.c
+index 2a99b286b0..6fa56f14c0 100644
+--- a/hw/block/pflash_cfi02.c
++++ b/hw/block/pflash_cfi02.c
+@@ -546,7 +546,7 @@ static void pflash_write(void *opaque, hwaddr offset, uint64_t value,
+ }
+ goto reset_flash;
+ }
+- trace_pflash_data_write(pfl->name, offset, width, value, 0);
++ trace_pflash_data_write(pfl->name, offset, width, value);
+ if (!pfl->ro) {
+ p = (uint8_t *)pfl->storage + offset;
+ if (pfl->be) {
+diff --git a/hw/block/trace-events b/hw/block/trace-events
+index 2c45a62bd5..196493feae 100644
+--- a/hw/block/trace-events
++++ b/hw/block/trace-events
+@@ -12,7 +12,8 @@ fdctrl_tc_pulse(int level) "TC pulse: %u"
+ pflash_chip_erase_invalid(const char *name, uint64_t offset) "%s: chip erase: invalid address 0x%" PRIx64
+ pflash_chip_erase_start(const char *name) "%s: start chip erase"
+ pflash_data_read(const char *name, uint64_t offset, unsigned size, uint32_t value) "%s: data offset:0x%04"PRIx64" size:%u value:0x%04x"
+-pflash_data_write(const char *name, uint64_t offset, unsigned size, uint32_t value, uint64_t counter) "%s: data offset:0x%04"PRIx64" size:%u value:0x%04x counter:0x%016"PRIx64
++pflash_data_write(const char *name, uint64_t offset, unsigned size, uint32_t value) "%s: data offset:0x%04"PRIx64" size:%u value:0x%04x"
++pflash_data_write_block(const char *name, uint64_t offset, unsigned size, uint32_t value, uint64_t counter) "%s: data offset:0x%04"PRIx64" size:%u value:0x%04x counter:0x%016"PRIx64
+ pflash_device_id(const char *name, uint16_t id) "%s: read device ID: 0x%04x"
+ pflash_device_info(const char *name, uint64_t offset) "%s: read device information offset:0x%04" PRIx64
+ pflash_erase_complete(const char *name) "%s: sector erase complete"
+@@ -32,7 +33,9 @@ pflash_unlock0_failed(const char *name, uint64_t offset, uint8_t cmd, uint16_t a
+ pflash_unlock1_failed(const char *name, uint64_t offset, uint8_t cmd) "%s: unlock0 failed 0x%" PRIx64 " 0x%02x"
+ pflash_unsupported_device_configuration(const char *name, uint8_t width, uint8_t max) "%s: unsupported device configuration: device_width:%d max_device_width:%d"
+ pflash_write(const char *name, const char *str) "%s: %s"
+-pflash_write_block(const char *name, uint32_t value) "%s: block write: bytes:0x%x"
++pflash_write_block_start(const char *name, uint32_t value) "%s: block write start: bytes:0x%x"
++pflash_write_block_flush(const char *name) "%s: block write flush"
++pflash_write_block_abort(const char *name) "%s: block write abort"
+ pflash_write_block_erase(const char *name, uint64_t offset, uint64_t len) "%s: block erase offset:0x%" PRIx64 " bytes:0x%" PRIx64
+ pflash_write_failed(const char *name, uint64_t offset, uint8_t cmd) "%s: command failed 0x%" PRIx64 " 0x%02x"
+ pflash_write_invalid(const char *name, uint8_t cmd) "%s: invalid write for command 0x%02x"
+diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
+index b17b29288c..f71b3b07d8 100644
+--- a/hw/intc/arm_gicv3_cpuif.c
++++ b/hw/intc/arm_gicv3_cpuif.c
+@@ -1432,16 +1432,25 @@ static void icv_eoir_write(CPUARMState *env, const ARMCPRegInfo *ri,
+ idx = icv_find_active(cs, irq);
+
+ if (idx < 0) {
+- /* No valid list register corresponding to EOI ID */
+- icv_increment_eoicount(cs);
++ /*
++ * No valid list register corresponding to EOI ID; if this is a vLPI
++ * not in the list regs then do nothing; otherwise increment EOI count
++ */
++ if (irq < GICV3_LPI_INTID_START) {
++ icv_increment_eoicount(cs);
++ }
+ } else {
+ uint64_t lr = cs->ich_lr_el2[idx];
+ int thisgrp = (lr & ICH_LR_EL2_GROUP) ? GICV3_G1NS : GICV3_G0;
+ int lr_gprio = ich_lr_prio(lr) & icv_gprio_mask(cs, grp);
+
+ if (thisgrp == grp && lr_gprio == dropprio) {
+- if (!icv_eoi_split(env, cs)) {
+- /* Priority drop and deactivate not split: deactivate irq now */
++ if (!icv_eoi_split(env, cs) || irq >= GICV3_LPI_INTID_START) {
++ /*
++ * Priority drop and deactivate not split: deactivate irq now.
++ * LPIs always get their active state cleared immediately
++ * because no separate deactivate is expected.
++ */
+ icv_deactivate_irq(cs, idx);
+ }
+ }
+diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
+index 06f35ac2d8..412cba4927 100644
+--- a/hw/net/virtio-net.c
++++ b/hw/net/virtio-net.c
+@@ -664,6 +664,11 @@ static void virtio_net_set_mrg_rx_bufs(VirtIONet *n, int mergeable_rx_bufs,
+
+ n->mergeable_rx_bufs = mergeable_rx_bufs;
+
++ /*
++ * Note: when extending the vnet header, please make sure to
++ * change the vnet header copying logic in virtio_net_flush_tx()
++ * as well.
++ */
+ if (version_1) {
+ n->guest_hdr_len = hash_report ?
+ sizeof(struct virtio_net_hdr_v1_hash) :
+@@ -2630,7 +2635,7 @@ static int32_t virtio_net_flush_tx(VirtIONetQueue *q)
+ ssize_t ret;
+ unsigned int out_num;
+ struct iovec sg[VIRTQUEUE_MAX_SIZE], sg2[VIRTQUEUE_MAX_SIZE + 1], *out_sg;
+- struct virtio_net_hdr_mrg_rxbuf mhdr;
++ struct virtio_net_hdr_v1_hash vhdr;
+
+ elem = virtqueue_pop(q->tx_vq, sizeof(VirtQueueElement));
+ if (!elem) {
+@@ -2647,7 +2652,7 @@ static int32_t virtio_net_flush_tx(VirtIONetQueue *q)
+ }
+
+ if (n->has_vnet_hdr) {
+- if (iov_to_buf(out_sg, out_num, 0, &mhdr, n->guest_hdr_len) <
++ if (iov_to_buf(out_sg, out_num, 0, &vhdr, n->guest_hdr_len) <
+ n->guest_hdr_len) {
+ virtio_error(vdev, "virtio-net header incorrect");
+ virtqueue_detach_element(q->tx_vq, elem, 0);
+@@ -2655,8 +2660,8 @@ static int32_t virtio_net_flush_tx(VirtIONetQueue *q)
+ return -EINVAL;
+ }
+ if (n->needs_vnet_hdr_swap) {
+- virtio_net_hdr_swap(vdev, (void *) &mhdr);
+- sg2[0].iov_base = &mhdr;
++ virtio_net_hdr_swap(vdev, (void *) &vhdr);
++ sg2[0].iov_base = &vhdr;
+ sg2[0].iov_len = n->guest_hdr_len;
+ out_num = iov_copy(&sg2[1], ARRAY_SIZE(sg2) - 1,
+ out_sg, out_num,
+diff --git a/hw/scsi/esp-pci.c b/hw/scsi/esp-pci.c
+index 1792f84cea..6b7b963409 100644
+--- a/hw/scsi/esp-pci.c
++++ b/hw/scsi/esp-pci.c
+@@ -77,6 +77,41 @@ struct PCIESPState {
+ ESPState esp;
+ };
+
++static void esp_pci_update_irq(PCIESPState *pci)
++{
++ int scsi_level = !!(pci->dma_regs[DMA_STAT] & DMA_STAT_SCSIINT);
++ int dma_level = (pci->dma_regs[DMA_CMD] & DMA_CMD_INTE_D) ?
++ !!(pci->dma_regs[DMA_STAT] & DMA_STAT_DONE) : 0;
++ int level = scsi_level || dma_level;
++
++ pci_set_irq(PCI_DEVICE(pci), level);
++}
++
++static void esp_irq_handler(void *opaque, int irq_num, int level)
++{
++ PCIESPState *pci = PCI_ESP(opaque);
++
++ if (level) {
++ pci->dma_regs[DMA_STAT] |= DMA_STAT_SCSIINT;
++
++ /*
++ * If raising the ESP IRQ to indicate end of DMA transfer, set
++ * DMA_STAT_DONE at the same time. In theory this should be done in
++ * esp_pci_dma_memory_rw(), however there is a delay between setting
++ * DMA_STAT_DONE and the ESP IRQ arriving which is visible to the
++ * guest that can cause confusion e.g. Linux
++ */
++ if ((pci->dma_regs[DMA_CMD] & DMA_CMD_MASK) == 0x3 &&
++ pci->dma_regs[DMA_WBC] == 0) {
++ pci->dma_regs[DMA_STAT] |= DMA_STAT_DONE;
++ }
++ } else {
++ pci->dma_regs[DMA_STAT] &= ~DMA_STAT_SCSIINT;
++ }
++
++ esp_pci_update_irq(pci);
++}
++
+ static void esp_pci_handle_idle(PCIESPState *pci, uint32_t val)
+ {
+ ESPState *s = ESP(&pci->esp);
+@@ -89,6 +124,7 @@ static void esp_pci_handle_blast(PCIESPState *pci, uint32_t val)
+ {
+ trace_esp_pci_dma_blast(val);
+ qemu_log_mask(LOG_UNIMP, "am53c974: cmd BLAST not implemented\n");
++ pci->dma_regs[DMA_STAT] |= DMA_STAT_BCMBLT;
+ }
+
+ static void esp_pci_handle_abort(PCIESPState *pci, uint32_t val)
+@@ -151,6 +187,7 @@ static void esp_pci_dma_write(PCIESPState *pci, uint32_t saddr, uint32_t val)
+ /* clear some bits on write */
+ uint32_t mask = DMA_STAT_ERROR | DMA_STAT_ABORT | DMA_STAT_DONE;
+ pci->dma_regs[DMA_STAT] &= ~(val & mask);
++ esp_pci_update_irq(pci);
+ }
+ break;
+ default:
+@@ -161,17 +198,14 @@ static void esp_pci_dma_write(PCIESPState *pci, uint32_t saddr, uint32_t val)
+
+ static uint32_t esp_pci_dma_read(PCIESPState *pci, uint32_t saddr)
+ {
+- ESPState *s = ESP(&pci->esp);
+ uint32_t val;
+
+ val = pci->dma_regs[saddr];
+ if (saddr == DMA_STAT) {
+- if (s->rregs[ESP_RSTAT] & STAT_INT) {
+- val |= DMA_STAT_SCSIINT;
+- }
+ if (!(pci->sbac & SBAC_STATUS)) {
+ pci->dma_regs[DMA_STAT] &= ~(DMA_STAT_ERROR | DMA_STAT_ABORT |
+ DMA_STAT_DONE);
++ esp_pci_update_irq(pci);
+ }
+ }
+
+@@ -275,7 +309,7 @@ static void esp_pci_dma_memory_rw(PCIESPState *pci, uint8_t *buf, int len,
+ qemu_log_mask(LOG_UNIMP, "am53c974: MDL transfer not implemented\n");
+ }
+
+- addr = pci->dma_regs[DMA_SPA];
++ addr = pci->dma_regs[DMA_WAC];
+ if (pci->dma_regs[DMA_WBC] < len) {
+ len = pci->dma_regs[DMA_WBC];
+ }
+@@ -285,9 +319,6 @@ static void esp_pci_dma_memory_rw(PCIESPState *pci, uint8_t *buf, int len,
+ /* update status registers */
+ pci->dma_regs[DMA_WBC] -= len;
+ pci->dma_regs[DMA_WAC] += len;
+- if (pci->dma_regs[DMA_WBC] == 0) {
+- pci->dma_regs[DMA_STAT] |= DMA_STAT_DONE;
+- }
+ }
+
+ static void esp_pci_dma_memory_read(void *opaque, uint8_t *buf, int len)
+@@ -342,23 +373,13 @@ static const VMStateDescription vmstate_esp_pci_scsi = {
+ }
+ };
+
+-static void esp_pci_command_complete(SCSIRequest *req, size_t resid)
+-{
+- ESPState *s = req->hba_private;
+- PCIESPState *pci = container_of(s, PCIESPState, esp);
+-
+- esp_command_complete(req, resid);
+- pci->dma_regs[DMA_WBC] = 0;
+- pci->dma_regs[DMA_STAT] |= DMA_STAT_DONE;
+-}
+-
+ static const struct SCSIBusInfo esp_pci_scsi_info = {
+ .tcq = false,
+ .max_target = ESP_MAX_DEVS,
+ .max_lun = 7,
+
+ .transfer_data = esp_transfer_data,
+- .complete = esp_pci_command_complete,
++ .complete = esp_command_complete,
+ .cancel = esp_request_cancelled,
+ };
+
+@@ -386,7 +407,7 @@ static void esp_pci_scsi_realize(PCIDevice *dev, Error **errp)
+ "esp-io", 0x80);
+
+ pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &pci->io);
+- s->irq = pci_allocate_irq(dev);
++ s->irq = qemu_allocate_irq(esp_irq_handler, pci, 0);
+
+ scsi_bus_init(&s->bus, sizeof(s->bus), d, &esp_pci_scsi_info);
+ }
+diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
+index 9b7bfbf09a..db677c856b 100644
+--- a/include/exec/exec-all.h
++++ b/include/exec/exec-all.h
+@@ -503,7 +503,6 @@ struct tb_tc {
+ };
+
+ struct TranslationBlock {
+-#if !TARGET_TB_PCREL
+ /*
+ * Guest PC corresponding to this block. This must be the true
+ * virtual address. Therefore e.g. x86 stores EIP + CS_BASE, and
+@@ -518,7 +517,6 @@ struct TranslationBlock {
+ * deposited into the "current" PC.
+ */
+ target_ulong pc;
+-#endif
+
+ /*
+ * Target-specific data associated with the TranslationBlock, e.g.:
+@@ -604,11 +602,7 @@ struct TranslationBlock {
+ /* Hide the read to avoid ifdefs for TARGET_TB_PCREL. */
+ static inline target_ulong tb_pc(const TranslationBlock *tb)
+ {
+-#if TARGET_TB_PCREL
+- qemu_build_not_reached();
+-#else
+ return tb->pc;
+-#endif
+ }
+
+ /* Hide the qatomic_read to make code a little easier on the eyes */
+diff --git a/include/hw/elf_ops.h b/include/hw/elf_ops.h
+index fbe0b1e956..78f45c8115 100644
+--- a/include/hw/elf_ops.h
++++ b/include/hw/elf_ops.h
+@@ -499,7 +499,7 @@ static ssize_t glue(load_elf, SZ)(const char *name, int fd,
+ }
+
+ if (data_swab) {
+- int j;
++ elf_word j;
+ for (j = 0; j < file_size; j += (1 << data_swab)) {
+ uint8_t *dp = data + j;
+ switch (data_swab) {
+diff --git a/monitor/qmp.c b/monitor/qmp.c
+index 092c527b6f..acd0a350c2 100644
+--- a/monitor/qmp.c
++++ b/monitor/qmp.c
+@@ -296,14 +296,6 @@ void coroutine_fn monitor_qmp_dispatcher_co(void *data)
+ qemu_coroutine_yield();
+ }
+
+- /*
+- * Move the coroutine from iohandler_ctx to qemu_aio_context for
+- * executing the command handler so that it can make progress if it
+- * involves an AIO_WAIT_WHILE().
+- */
+- aio_co_schedule(qemu_get_aio_context(), qmp_dispatcher_co);
+- qemu_coroutine_yield();
+-
+ /* Process request */
+ if (req_obj->req) {
+ if (trace_event_get_state(TRACE_MONITOR_QMP_CMD_IN_BAND)) {
+@@ -330,15 +322,6 @@ void coroutine_fn monitor_qmp_dispatcher_co(void *data)
+ }
+
+ qmp_request_free(req_obj);
+-
+- /*
+- * Yield and reschedule so the main loop stays responsive.
+- *
+- * Move back to iohandler_ctx so that nested event loops for
+- * qemu_aio_context don't start new monitor commands.
+- */
+- aio_co_schedule(iohandler_get_aio_context(), qmp_dispatcher_co);
+- qemu_coroutine_yield();
+ }
+ }
+
+diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c
+index 0990873ec8..5d000fae87 100644
+--- a/qapi/qmp-dispatch.c
++++ b/qapi/qmp-dispatch.c
+@@ -206,9 +206,31 @@ QDict *qmp_dispatch(const QmpCommandList *cmds, QObject *request,
+ assert(!(oob && qemu_in_coroutine()));
+ assert(monitor_cur() == NULL);
+ if (!!(cmd->options & QCO_COROUTINE) == qemu_in_coroutine()) {
++ if (qemu_in_coroutine()) {
++ /*
++ * Move the coroutine from iohandler_ctx to qemu_aio_context for
++ * executing the command handler so that it can make progress if it
++ * involves an AIO_WAIT_WHILE().
++ */
++ aio_co_schedule(qemu_get_aio_context(), qemu_coroutine_self());
++ qemu_coroutine_yield();
++ }
++
+ monitor_set_cur(qemu_coroutine_self(), cur_mon);
+ cmd->fn(args, &ret, &err);
+ monitor_set_cur(qemu_coroutine_self(), NULL);
++
++ if (qemu_in_coroutine()) {
++ /*
++ * Yield and reschedule so the main loop stays responsive.
++ *
++ * Move back to iohandler_ctx so that nested event loops for
++ * qemu_aio_context don't start new monitor commands.
++ */
++ aio_co_schedule(iohandler_get_aio_context(),
++ qemu_coroutine_self());
++ qemu_coroutine_yield();
++ }
+ } else {
+ /*
+ * Actual context doesn't match the one the command needs.
+@@ -232,7 +254,7 @@ QDict *qmp_dispatch(const QmpCommandList *cmds, QObject *request,
+ .errp = &err,
+ .co = qemu_coroutine_self(),
+ };
+- aio_bh_schedule_oneshot(qemu_get_aio_context(), do_qmp_dispatch_bh,
++ aio_bh_schedule_oneshot(iohandler_get_aio_context(), do_qmp_dispatch_bh,
+ &data);
+ qemu_coroutine_yield();
+ }
+diff --git a/softmmu/vl.c b/softmmu/vl.c
+index 5115221efe..ce88869618 100644
+--- a/softmmu/vl.c
++++ b/softmmu/vl.c
+@@ -2321,6 +2321,10 @@ static void qemu_validate_options(const QDict *machine_opts)
+ }
+ }
+
++ if (loadvm && incoming) {
++ error_report("'incoming' and 'loadvm' options are mutually exclusive");
++ exit(EXIT_FAILURE);
++ }
+ if (loadvm && preconfig_requested) {
+ error_report("'preconfig' and 'loadvm' options are "
+ "mutually exclusive");
+diff --git a/target/i386/cpu.h b/target/i386/cpu.h
+index d4bc19577a..f67cee477a 100644
+--- a/target/i386/cpu.h
++++ b/target/i386/cpu.h
+@@ -2217,10 +2217,15 @@ static inline int cpu_mmu_index_kernel(CPUX86State *env)
+ static inline void cpu_get_tb_cpu_state(CPUX86State *env, target_ulong *pc,
+ target_ulong *cs_base, uint32_t *flags)
+ {
+- *cs_base = env->segs[R_CS].base;
+- *pc = *cs_base + env->eip;
+ *flags = env->hflags |
+ (env->eflags & (IOPL_MASK | TF_MASK | RF_MASK | VM_MASK | AC_MASK));
++ if (env->hflags & HF_CS64_MASK) {
++ *cs_base = 0;
++ *pc = env->eip;
++ } else {
++ *cs_base = env->segs[R_CS].base;
++ *pc = (uint32_t)(*cs_base + env->eip);
++ }
+ }
+
+ void do_cpu_init(X86CPU *cpu);
+diff --git a/target/i386/tcg/tcg-cpu.c b/target/i386/tcg/tcg-cpu.c
+index 79ac5908f7..cd49f86341 100644
+--- a/target/i386/tcg/tcg-cpu.c
++++ b/target/i386/tcg/tcg-cpu.c
+@@ -52,7 +52,12 @@ static void x86_cpu_synchronize_from_tb(CPUState *cs,
+ /* The instruction pointer is always up to date with TARGET_TB_PCREL. */
+ if (!TARGET_TB_PCREL) {
+ CPUX86State *env = cs->env_ptr;
+- env->eip = tb_pc(tb) - tb->cs_base;
++
++ if (tb->flags & HF_CS64_MASK) {
++ env->eip = tb_pc(tb);
++ } else {
++ env->eip = (uint32_t)(tb_pc(tb) - tb->cs_base);
++ }
+ }
+ }
+
+@@ -63,12 +68,26 @@ static void x86_restore_state_to_opc(CPUState *cs,
+ X86CPU *cpu = X86_CPU(cs);
+ CPUX86State *env = &cpu->env;
+ int cc_op = data[1];
++ uint64_t new_pc;
+
+ if (TARGET_TB_PCREL) {
+- env->eip = (env->eip & TARGET_PAGE_MASK) | data[0];
++ /*
++ * data[0] in PC-relative TBs is also a linear address, i.e. an address with
++ * the CS base added, because it is not guaranteed that EIP bits 12 and higher
++ * stay the same across the translation block. Add the CS base back before
++ * replacing the low bits, and subtract it below just like for !CF_PCREL.
++ */
++ uint64_t pc = env->eip + tb->cs_base;
++ new_pc = (pc & TARGET_PAGE_MASK) | data[0];
++ } else {
++ new_pc = data[0];
++ }
++ if (tb->flags & HF_CS64_MASK) {
++ env->eip = new_pc;
+ } else {
+- env->eip = data[0] - tb->cs_base;
++ env->eip = (uint32_t)(new_pc - tb->cs_base);
+ }
++
+ if (cc_op != CC_OP_DYNAMIC) {
+ env->cc_op = cc_op;
+ }
+diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
+index 7e0b2a709a..68c42fd9ff 100644
+--- a/target/i386/tcg/translate.c
++++ b/target/i386/tcg/translate.c
+@@ -547,8 +547,10 @@ static void gen_update_eip_cur(DisasContext *s)
+ assert(s->pc_save != -1);
+ if (TARGET_TB_PCREL) {
+ tcg_gen_addi_tl(cpu_eip, cpu_eip, s->base.pc_next - s->pc_save);
++ } else if (CODE64(s)) {
++ tcg_gen_movi_tl(cpu_eip, s->base.pc_next);
+ } else {
+- tcg_gen_movi_tl(cpu_eip, s->base.pc_next - s->cs_base);
++ tcg_gen_movi_tl(cpu_eip, (uint32_t)(s->base.pc_next - s->cs_base));
+ }
+ s->pc_save = s->base.pc_next;
+ }
+@@ -558,8 +560,10 @@ static void gen_update_eip_next(DisasContext *s)
+ assert(s->pc_save != -1);
+ if (TARGET_TB_PCREL) {
+ tcg_gen_addi_tl(cpu_eip, cpu_eip, s->pc - s->pc_save);
++ } else if (CODE64(s)) {
++ tcg_gen_movi_tl(cpu_eip, s->pc);
+ } else {
+- tcg_gen_movi_tl(cpu_eip, s->pc - s->cs_base);
++ tcg_gen_movi_tl(cpu_eip, (uint32_t)(s->pc - s->cs_base));
+ }
+ s->pc_save = s->pc;
+ }
+@@ -605,8 +609,10 @@ static TCGv eip_next_tl(DisasContext *s)
+ TCGv ret = tcg_temp_new();
+ tcg_gen_addi_tl(ret, cpu_eip, s->pc - s->pc_save);
+ return ret;
++ } else if (CODE64(s)) {
++ return tcg_constant_tl(s->pc);
+ } else {
+- return tcg_constant_tl(s->pc - s->cs_base);
++ return tcg_constant_tl((uint32_t)(s->pc - s->cs_base));
+ }
+ }
+
+@@ -617,8 +623,10 @@ static TCGv eip_cur_tl(DisasContext *s)
+ TCGv ret = tcg_temp_new();
+ tcg_gen_addi_tl(ret, cpu_eip, s->base.pc_next - s->pc_save);
+ return ret;
++ } else if (CODE64(s)) {
++ return tcg_constant_tl(s->base.pc_next);
+ } else {
+- return tcg_constant_tl(s->base.pc_next - s->cs_base);
++ return tcg_constant_tl((uint32_t)(s->base.pc_next - s->cs_base));
+ }
+ }
+
+@@ -2890,10 +2898,11 @@ static void gen_jmp_rel(DisasContext *s, MemOp ot, int diff, int tb_num)
+ tcg_gen_andi_tl(cpu_eip, cpu_eip, mask);
+ use_goto_tb = false;
+ }
++ } else if (!CODE64(s)) {
++ new_pc = (uint32_t)(new_eip + s->cs_base);
+ }
+
+- if (use_goto_tb &&
+- translator_use_goto_tb(&s->base, new_eip + s->cs_base)) {
++ if (use_goto_tb && translator_use_goto_tb(&s->base, new_pc)) {
+ /* jump to same page: we can use a direct jump */
+ tcg_gen_goto_tb(tb_num);
+ if (!TARGET_TB_PCREL) {
+@@ -6974,7 +6983,6 @@ static void i386_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
+
+ dc->prev_insn_end = tcg_last_op();
+ if (TARGET_TB_PCREL) {
+- pc_arg -= dc->cs_base;
+ pc_arg &= ~TARGET_PAGE_MASK;
+ }
+ tcg_gen_insn_start(pc_arg, dc->cc_op);
+diff --git a/target/riscv/csr.c b/target/riscv/csr.c
+index 5c9a7ee287..15dba5f653 100644
+--- a/target/riscv/csr.c
++++ b/target/riscv/csr.c
+@@ -697,11 +697,11 @@ static int write_mhpmcounterh(CPURISCVState *env, int csrno, target_ulong val)
+ static RISCVException riscv_pmu_read_ctr(CPURISCVState *env, target_ulong *val,
+ bool upper_half, uint32_t ctr_idx)
+ {
+- PMUCTRState counter = env->pmu_ctrs[ctr_idx];
+- target_ulong ctr_prev = upper_half ? counter.mhpmcounterh_prev :
+- counter.mhpmcounter_prev;
+- target_ulong ctr_val = upper_half ? counter.mhpmcounterh_val :
+- counter.mhpmcounter_val;
++ PMUCTRState *counter = &env->pmu_ctrs[ctr_idx];
++ target_ulong ctr_prev = upper_half ? counter->mhpmcounterh_prev :
++ counter->mhpmcounter_prev;
++ target_ulong ctr_val = upper_half ? counter->mhpmcounterh_val :
++ counter->mhpmcounter_val;
+
+ if (get_field(env->mcountinhibit, BIT(ctr_idx))) {
+ /**
+@@ -709,12 +709,12 @@ static RISCVException riscv_pmu_read_ctr(CPURISCVState *env, target_ulong *val,
+ * stop the icount counting. Just return the counter value written by
+ * the supervisor to indicate that counter was not incremented.
+ */
+- if (!counter.started) {
++ if (!counter->started) {
+ *val = ctr_val;
+ return RISCV_EXCP_NONE;
+ } else {
+ /* Mark that the counter has been stopped */
+- counter.started = false;
++ counter->started = false;
+ }
+ }
+
+diff --git a/target/s390x/tcg/translate.c b/target/s390x/tcg/translate.c
+index b0173e968e..a257c06838 100644
+--- a/target/s390x/tcg/translate.c
++++ b/target/s390x/tcg/translate.c
+@@ -3394,6 +3394,7 @@ static DisasJumpType op_mov2e(DisasContext *s, DisasOps *o)
+ {
+ int b2 = get_field(s, b2);
+ TCGv ar1 = tcg_temp_new_i64();
++ int r1 = get_field(s, r1);
+
+ o->out = o->in2;
+ o->g_out = o->g_in2;
+@@ -3419,7 +3420,7 @@ static DisasJumpType op_mov2e(DisasContext *s, DisasOps *o)
+ break;
+ }
+
+- tcg_gen_st32_i64(ar1, cpu_env, offsetof(CPUS390XState, aregs[1]));
++ tcg_gen_st32_i64(ar1, cpu_env, offsetof(CPUS390XState, aregs[r1]));
+ tcg_temp_free_i64(ar1);
+
+ return DISAS_NEXT;
+diff --git a/target/xtensa/mmu_helper.c b/target/xtensa/mmu_helper.c
+index fa66e8e867..c4b4df4d74 100644
+--- a/target/xtensa/mmu_helper.c
++++ b/target/xtensa/mmu_helper.c
+@@ -226,22 +226,31 @@ static void split_tlb_entry_spec_way(const CPUXtensaState *env, uint32_t v,
+ * Split TLB address into TLB way, entry index and VPN (with index).
+ * See ISA, 4.6.5.5 - 4.6.5.8 for the TLB addressing format
+ */
+-static void split_tlb_entry_spec(CPUXtensaState *env, uint32_t v, bool dtlb,
+- uint32_t *vpn, uint32_t *wi, uint32_t *ei)
++static bool split_tlb_entry_spec(CPUXtensaState *env, uint32_t v, bool dtlb,
++ uint32_t *vpn, uint32_t *wi, uint32_t *ei)
+ {
+ if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) {
+ *wi = v & (dtlb ? 0xf : 0x7);
+- split_tlb_entry_spec_way(env, v, dtlb, vpn, *wi, ei);
++ if (*wi < (dtlb ? env->config->dtlb.nways : env->config->itlb.nways)) {
++ split_tlb_entry_spec_way(env, v, dtlb, vpn, *wi, ei);
++ return true;
++ } else {
++ return false;
++ }
+ } else {
+ *vpn = v & REGION_PAGE_MASK;
+ *wi = 0;
+ *ei = (v >> 29) & 0x7;
++ return true;
+ }
+ }
+
+ static xtensa_tlb_entry *xtensa_tlb_get_entry(CPUXtensaState *env, bool dtlb,
+ unsigned wi, unsigned ei)
+ {
++ const xtensa_tlb *tlb = dtlb ? &env->config->dtlb : &env->config->itlb;
++
++ assert(wi < tlb->nways && ei < tlb->way_size[wi]);
+ return dtlb ?
+ env->dtlb[wi] + ei :
+ env->itlb[wi] + ei;
+@@ -254,11 +263,14 @@ static xtensa_tlb_entry *get_tlb_entry(CPUXtensaState *env,
+ uint32_t wi;
+ uint32_t ei;
+
+- split_tlb_entry_spec(env, v, dtlb, &vpn, &wi, &ei);
+- if (pwi) {
+- *pwi = wi;
++ if (split_tlb_entry_spec(env, v, dtlb, &vpn, &wi, &ei)) {
++ if (pwi) {
++ *pwi = wi;
++ }
++ return xtensa_tlb_get_entry(env, dtlb, wi, ei);
++ } else {
++ return NULL;
+ }
+- return xtensa_tlb_get_entry(env, dtlb, wi, ei);
+ }
+
+ static void xtensa_tlb_set_entry_mmu(const CPUXtensaState *env,
+@@ -484,7 +496,12 @@ uint32_t HELPER(rtlb0)(CPUXtensaState *env, uint32_t v, uint32_t dtlb)
+ if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) {
+ uint32_t wi;
+ const xtensa_tlb_entry *entry = get_tlb_entry(env, v, dtlb, &wi);
+- return (entry->vaddr & get_vpn_mask(env, dtlb, wi)) | entry->asid;
++
++ if (entry) {
++ return (entry->vaddr & get_vpn_mask(env, dtlb, wi)) | entry->asid;
++ } else {
++ return 0;
++ }
+ } else {
+ return v & REGION_PAGE_MASK;
+ }
+@@ -493,7 +510,12 @@ uint32_t HELPER(rtlb0)(CPUXtensaState *env, uint32_t v, uint32_t dtlb)
+ uint32_t HELPER(rtlb1)(CPUXtensaState *env, uint32_t v, uint32_t dtlb)
+ {
+ const xtensa_tlb_entry *entry = get_tlb_entry(env, v, dtlb, NULL);
+- return entry->paddr | entry->attr;
++
++ if (entry) {
++ return entry->paddr | entry->attr;
++ } else {
++ return 0;
++ }
+ }
+
+ void HELPER(itlb)(CPUXtensaState *env, uint32_t v, uint32_t dtlb)
+@@ -501,7 +523,7 @@ void HELPER(itlb)(CPUXtensaState *env, uint32_t v, uint32_t dtlb)
+ if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) {
+ uint32_t wi;
+ xtensa_tlb_entry *entry = get_tlb_entry(env, v, dtlb, &wi);
+- if (entry->variable && entry->asid) {
++ if (entry && entry->variable && entry->asid) {
+ tlb_flush_page(env_cpu(env), entry->vaddr);
+ entry->asid = 0;
+ }
+@@ -539,8 +561,9 @@ void HELPER(wtlb)(CPUXtensaState *env, uint32_t p, uint32_t v, uint32_t dtlb)
+ uint32_t vpn;
+ uint32_t wi;
+ uint32_t ei;
+- split_tlb_entry_spec(env, v, dtlb, &vpn, &wi, &ei);
+- xtensa_tlb_set_entry(env, dtlb, wi, ei, vpn, p);
++ if (split_tlb_entry_spec(env, v, dtlb, &vpn, &wi, &ei)) {
++ xtensa_tlb_set_entry(env, dtlb, wi, ei, vpn, p);
++ }
+ }
+
+ /*!
+diff --git a/tests/qemu-iotests/060.out b/tests/qemu-iotests/060.out
+index 329977d9b9..a37bf446e9 100644
+--- a/tests/qemu-iotests/060.out
++++ b/tests/qemu-iotests/060.out
+@@ -421,8 +421,8 @@ QMP_VERSION
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_IMAGE_CORRUPTED", "data": {"device": "none0", "msg": "Preventing invalid write on metadata (overlaps with refcount table)", "offset": 65536, "node-name": "drive", "fatal": true, "size": 65536}}
+ write failed: Input/output error
+ {"return": ""}
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
++{"return": {}}
+
+ === Testing incoming inactive corrupted image ===
+
+@@ -432,8 +432,8 @@ QMP_VERSION
+ qcow2: Image is corrupt: L2 table offset 0x2a2a2a00 unaligned (L1 index: 0); further non-fatal corruption events will be suppressed
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_IMAGE_CORRUPTED", "data": {"device": "", "msg": "L2 table offset 0x2a2a2a00 unaligned (L1 index: 0)", "node-name": "drive", "fatal": false}}
+ {"return": ""}
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
++{"return": {}}
+
+ corrupt: false
+ *** done
+diff --git a/tests/qemu-iotests/071.out b/tests/qemu-iotests/071.out
+index bca0c02f5c..a2923b05c2 100644
+--- a/tests/qemu-iotests/071.out
++++ b/tests/qemu-iotests/071.out
+@@ -45,8 +45,8 @@ QMP_VERSION
+ {"return": {}}
+ read failed: Input/output error
+ {"return": ""}
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
++{"return": {}}
+
+
+ === Testing blkverify on existing block device ===
+@@ -84,9 +84,9 @@ wrote 512/512 bytes at offset 0
+ {"return": ""}
+ read failed: Input/output error
+ {"return": ""}
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+ QEMU_PROG: Failed to flush the L2 table cache: Input/output error
+ QEMU_PROG: Failed to flush the refcount block cache: Input/output error
++{"return": {}}
+
+ *** done
+diff --git a/tests/qemu-iotests/081.out b/tests/qemu-iotests/081.out
+index 615c083549..aba85ea564 100644
+--- a/tests/qemu-iotests/081.out
++++ b/tests/qemu-iotests/081.out
+@@ -35,8 +35,8 @@ QMP_VERSION
+ read 10485760/10485760 bytes at offset 0
+ 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+ {"return": ""}
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
++{"return": {}}
+
+
+ == using quorum rewrite corrupted mode ==
+@@ -67,8 +67,8 @@ QMP_VERSION
+ read 10485760/10485760 bytes at offset 0
+ 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+ {"return": ""}
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
++{"return": {}}
+
+ -- checking that the image has been corrected --
+ read 10485760/10485760 bytes at offset 0
+@@ -106,8 +106,8 @@ QMP_VERSION
+ {"return": {}}
+ {"return": {}}
+ {"return": {}}
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
++{"return": {}}
+
+ Testing:
+ QMP_VERSION
+@@ -115,8 +115,8 @@ QMP_VERSION
+ {"return": {}}
+ {"return": {}}
+ {"error": {"class": "GenericError", "desc": "Cannot add a child to a quorum in blkverify mode"}}
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
++{"return": {}}
+
+
+ == dynamically removing a child from a quorum ==
+@@ -125,31 +125,31 @@ QMP_VERSION
+ {"return": {}}
+ {"return": {}}
+ {"return": {}}
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
++{"return": {}}
+
+ Testing:
+ QMP_VERSION
+ {"return": {}}
+ {"return": {}}
+ {"error": {"class": "GenericError", "desc": "The number of children cannot be lower than the vote threshold 2"}}
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
++{"return": {}}
+
+ Testing:
+ QMP_VERSION
+ {"return": {}}
+ {"error": {"class": "GenericError", "desc": "blkverify=on can only be set if there are exactly two files and vote-threshold is 2"}}
+ {"error": {"class": "GenericError", "desc": "Cannot find device='drive0-quorum' nor node-name='drive0-quorum'"}}
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
++{"return": {}}
+
+ Testing:
+ QMP_VERSION
+ {"return": {}}
+ {"return": {}}
+ {"error": {"class": "GenericError", "desc": "The number of children cannot be lower than the vote threshold 2"}}
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
++{"return": {}}
+
+ *** done
+diff --git a/tests/qemu-iotests/087.out b/tests/qemu-iotests/087.out
+index e1c23a6983..97b6d8036d 100644
+--- a/tests/qemu-iotests/087.out
++++ b/tests/qemu-iotests/087.out
+@@ -7,8 +7,8 @@ Testing:
+ QMP_VERSION
+ {"return": {}}
+ {"error": {"class": "GenericError", "desc": "'node-name' must be specified for the root node"}}
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
++{"return": {}}
+
+
+ === Duplicate ID ===
+@@ -18,8 +18,8 @@ QMP_VERSION
+ {"return": {}}
+ {"error": {"class": "GenericError", "desc": "node-name=disk is conflicting with a device id"}}
+ {"error": {"class": "GenericError", "desc": "Duplicate nodes with node-name='test-node'"}}
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
++{"return": {}}
+
+
+ === aio=native without O_DIRECT ===
+@@ -28,8 +28,8 @@ Testing:
+ QMP_VERSION
+ {"return": {}}
+ {"error": {"class": "GenericError", "desc": "aio=native was specified, but it requires cache.direct=on, which was not specified."}}
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
++{"return": {}}
+
+
+ === Encrypted image QCow ===
+@@ -40,8 +40,8 @@ QMP_VERSION
+ {"return": {}}
+ {"return": {}}
+ {"error": {"class": "GenericError", "desc": "Use of AES-CBC encrypted IMGFMT images is no longer supported in system emulators"}}
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
++{"return": {}}
+
+
+ === Encrypted image LUKS ===
+@@ -52,8 +52,8 @@ QMP_VERSION
+ {"return": {}}
+ {"return": {}}
+ {"return": {}}
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
++{"return": {}}
+
+
+ === Missing driver ===
+@@ -63,7 +63,7 @@ Testing: -S
+ QMP_VERSION
+ {"return": {}}
+ {"error": {"class": "GenericError", "desc": "Parameter 'driver' is missing"}}
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
++{"return": {}}
+
+ *** done
+diff --git a/tests/qemu-iotests/108.out b/tests/qemu-iotests/108.out
+index b5401d788d..b9c876b394 100644
+--- a/tests/qemu-iotests/108.out
++++ b/tests/qemu-iotests/108.out
+@@ -173,8 +173,8 @@ OK: Reftable is where we expect it
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "create"}}
+ {"return": {}}
+ { "execute": "quit" }
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
++{"return": {}}
+
+ wrote 65536/65536 bytes at offset 0
+ 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+diff --git a/tests/qemu-iotests/109 b/tests/qemu-iotests/109
+index e207a555f3..0fb580f9a5 100755
+--- a/tests/qemu-iotests/109
++++ b/tests/qemu-iotests/109
+@@ -57,13 +57,13 @@ run_qemu()
+ _launch_qemu -drive file="${source_img}",format=raw,cache=${CACHEMODE},aio=${AIOMODE},id=src
+ _send_qemu_cmd $QEMU_HANDLE "{ 'execute': 'qmp_capabilities' }" "return"
+
+- _send_qemu_cmd $QEMU_HANDLE \
++ capture_events="$qmp_event" _send_qemu_cmd $QEMU_HANDLE \
+ "{'execute':'drive-mirror', 'arguments':{
+ 'device': 'src', 'target': '$raw_img', $qmp_format
+ 'mode': 'existing', 'sync': 'full'}}" \
+ "return"
+
+- _send_qemu_cmd $QEMU_HANDLE '' "$qmp_event"
++ capture_events="$qmp_event JOB_STATUS_CHANGE" _wait_event $QEMU_HANDLE "$qmp_event"
+ if test "$qmp_event" = BLOCK_JOB_ERROR; then
+ _send_qemu_cmd $QEMU_HANDLE '' '"status": "null"'
+ fi
+diff --git a/tests/qemu-iotests/109.out b/tests/qemu-iotests/109.out
+index e29280015e..255b81fcdc 100644
+--- a/tests/qemu-iotests/109.out
++++ b/tests/qemu-iotests/109.out
+@@ -7,7 +7,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
+ { 'execute': 'qmp_capabilities' }
+ {"return": {}}
+ {'execute':'drive-mirror', 'arguments':{
+- 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
++ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
+ 'mode': 'existing', 'sync': 'full'}}
+ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw.
+ Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
+@@ -23,8 +23,8 @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed
+ {"execute":"query-block-jobs"}
+ {"return": []}
+ {"execute":"quit"}
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
++{"return": {}}
+ read 512/512 bytes at offset 0
+ 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+ { 'execute': 'qmp_capabilities' }
+@@ -35,12 +35,10 @@ read 512/512 bytes at offset 0
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}}
+ {"return": {}}
+-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 1024, "offset": 1024, "speed": 0, "type": "mirror"}}
+ {"execute":"query-block-jobs"}
+ {"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 1024, "offset": 1024, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
+ {"execute":"quit"}
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "standby", "id": "src"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
+@@ -48,6 +46,7 @@ read 512/512 bytes at offset 0
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "src", "len": 1024, "offset": 1024, "speed": 0, "type": "mirror"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
++{"return": {}}
+ Images are identical.
+
+ === Writing a qcow2 header into raw ===
+@@ -57,7 +56,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
+ { 'execute': 'qmp_capabilities' }
+ {"return": {}}
+ {'execute':'drive-mirror', 'arguments':{
+- 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
++ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
+ 'mode': 'existing', 'sync': 'full'}}
+ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw.
+ Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
+@@ -73,8 +72,8 @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed
+ {"execute":"query-block-jobs"}
+ {"return": []}
+ {"execute":"quit"}
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
++{"return": {}}
+ read 512/512 bytes at offset 0
+ 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+ { 'execute': 'qmp_capabilities' }
+@@ -85,12 +84,10 @@ read 512/512 bytes at offset 0
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}}
+ {"return": {}}
+-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 197120, "offset": 197120, "speed": 0, "type": "mirror"}}
+ {"execute":"query-block-jobs"}
+ {"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 197120, "offset": 197120, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
+ {"execute":"quit"}
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "standby", "id": "src"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
+@@ -98,6 +95,7 @@ read 512/512 bytes at offset 0
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "src", "len": 197120, "offset": 197120, "speed": 0, "type": "mirror"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
++{"return": {}}
+ Images are identical.
+
+ === Writing a qed header into raw ===
+@@ -107,7 +105,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
+ { 'execute': 'qmp_capabilities' }
+ {"return": {}}
+ {'execute':'drive-mirror', 'arguments':{
+- 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
++ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
+ 'mode': 'existing', 'sync': 'full'}}
+ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw.
+ Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
+@@ -123,8 +121,8 @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed
+ {"execute":"query-block-jobs"}
+ {"return": []}
+ {"execute":"quit"}
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
++{"return": {}}
+ read 512/512 bytes at offset 0
+ 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+ { 'execute': 'qmp_capabilities' }
+@@ -135,12 +133,10 @@ read 512/512 bytes at offset 0
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}}
+ {"return": {}}
+-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 327680, "offset": 327680, "speed": 0, "type": "mirror"}}
+ {"execute":"query-block-jobs"}
+ {"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 327680, "offset": 327680, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
+ {"execute":"quit"}
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "standby", "id": "src"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
+@@ -148,6 +144,7 @@ read 512/512 bytes at offset 0
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "src", "len": 327680, "offset": 327680, "speed": 0, "type": "mirror"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
++{"return": {}}
+ Images are identical.
+
+ === Writing a vdi header into raw ===
+@@ -157,7 +154,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
+ { 'execute': 'qmp_capabilities' }
+ {"return": {}}
+ {'execute':'drive-mirror', 'arguments':{
+- 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
++ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
+ 'mode': 'existing', 'sync': 'full'}}
+ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw.
+ Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
+@@ -173,8 +170,8 @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed
+ {"execute":"query-block-jobs"}
+ {"return": []}
+ {"execute":"quit"}
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
++{"return": {}}
+ read 512/512 bytes at offset 0
+ 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+ { 'execute': 'qmp_capabilities' }
+@@ -185,12 +182,10 @@ read 512/512 bytes at offset 0
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}}
+ {"return": {}}
+-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 1024, "offset": 1024, "speed": 0, "type": "mirror"}}
+ {"execute":"query-block-jobs"}
+ {"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 1024, "offset": 1024, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
+ {"execute":"quit"}
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "standby", "id": "src"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
+@@ -198,6 +193,7 @@ read 512/512 bytes at offset 0
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "src", "len": 1024, "offset": 1024, "speed": 0, "type": "mirror"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
++{"return": {}}
+ Images are identical.
+
+ === Writing a vmdk header into raw ===
+@@ -207,7 +203,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
+ { 'execute': 'qmp_capabilities' }
+ {"return": {}}
+ {'execute':'drive-mirror', 'arguments':{
+- 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
++ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
+ 'mode': 'existing', 'sync': 'full'}}
+ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw.
+ Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
+@@ -223,8 +219,8 @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed
+ {"execute":"query-block-jobs"}
+ {"return": []}
+ {"execute":"quit"}
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
++{"return": {}}
+ read 512/512 bytes at offset 0
+ 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+ { 'execute': 'qmp_capabilities' }
+@@ -235,12 +231,10 @@ read 512/512 bytes at offset 0
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}}
+ {"return": {}}
+-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 65536, "offset": 65536, "speed": 0, "type": "mirror"}}
+ {"execute":"query-block-jobs"}
+ {"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 65536, "offset": 65536, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
+ {"execute":"quit"}
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "standby", "id": "src"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
+@@ -248,6 +242,7 @@ read 512/512 bytes at offset 0
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "src", "len": 65536, "offset": 65536, "speed": 0, "type": "mirror"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
++{"return": {}}
+ Images are identical.
+
+ === Writing a vpc header into raw ===
+@@ -257,7 +252,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
+ { 'execute': 'qmp_capabilities' }
+ {"return": {}}
+ {'execute':'drive-mirror', 'arguments':{
+- 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
++ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
+ 'mode': 'existing', 'sync': 'full'}}
+ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw.
+ Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
+@@ -273,8 +268,8 @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed
+ {"execute":"query-block-jobs"}
+ {"return": []}
+ {"execute":"quit"}
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
++{"return": {}}
+ read 512/512 bytes at offset 0
+ 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+ { 'execute': 'qmp_capabilities' }
+@@ -285,12 +280,10 @@ read 512/512 bytes at offset 0
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}}
+ {"return": {}}
+-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 2560, "offset": 2560, "speed": 0, "type": "mirror"}}
+ {"execute":"query-block-jobs"}
+ {"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 2560, "offset": 2560, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
+ {"execute":"quit"}
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "standby", "id": "src"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
+@@ -298,6 +291,7 @@ read 512/512 bytes at offset 0
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "src", "len": 2560, "offset": 2560, "speed": 0, "type": "mirror"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
++{"return": {}}
+ Images are identical.
+
+ === Copying sample image empty.bochs into raw ===
+@@ -306,7 +300,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
+ { 'execute': 'qmp_capabilities' }
+ {"return": {}}
+ {'execute':'drive-mirror', 'arguments':{
+- 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
++ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
+ 'mode': 'existing', 'sync': 'full'}}
+ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw.
+ Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
+@@ -322,8 +316,8 @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed
+ {"execute":"query-block-jobs"}
+ {"return": []}
+ {"execute":"quit"}
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
++{"return": {}}
+ read 512/512 bytes at offset 0
+ 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+ { 'execute': 'qmp_capabilities' }
+@@ -334,12 +328,10 @@ read 512/512 bytes at offset 0
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}}
+ {"return": {}}
+-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 2560, "offset": 2560, "speed": 0, "type": "mirror"}}
+ {"execute":"query-block-jobs"}
+ {"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 2560, "offset": 2560, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
+ {"execute":"quit"}
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "standby", "id": "src"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
+@@ -347,6 +339,7 @@ read 512/512 bytes at offset 0
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "src", "len": 2560, "offset": 2560, "speed": 0, "type": "mirror"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
++{"return": {}}
+ Images are identical.
+
+ === Copying sample image iotest-dirtylog-10G-4M.vhdx into raw ===
+@@ -355,7 +348,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
+ { 'execute': 'qmp_capabilities' }
+ {"return": {}}
+ {'execute':'drive-mirror', 'arguments':{
+- 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
++ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
+ 'mode': 'existing', 'sync': 'full'}}
+ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw.
+ Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
+@@ -371,8 +364,8 @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed
+ {"execute":"query-block-jobs"}
+ {"return": []}
+ {"execute":"quit"}
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
++{"return": {}}
+ read 512/512 bytes at offset 0
+ 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+ { 'execute': 'qmp_capabilities' }
+@@ -383,12 +376,10 @@ read 512/512 bytes at offset 0
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}}
+ {"return": {}}
+-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 31457280, "offset": 31457280, "speed": 0, "type": "mirror"}}
+ {"execute":"query-block-jobs"}
+ {"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 31457280, "offset": 31457280, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
+ {"execute":"quit"}
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "standby", "id": "src"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
+@@ -396,6 +387,7 @@ read 512/512 bytes at offset 0
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "src", "len": 31457280, "offset": 31457280, "speed": 0, "type": "mirror"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
++{"return": {}}
+ Images are identical.
+
+ === Copying sample image parallels-v1 into raw ===
+@@ -404,7 +396,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
+ { 'execute': 'qmp_capabilities' }
+ {"return": {}}
+ {'execute':'drive-mirror', 'arguments':{
+- 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
++ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
+ 'mode': 'existing', 'sync': 'full'}}
+ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw.
+ Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
+@@ -420,8 +412,8 @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed
+ {"execute":"query-block-jobs"}
+ {"return": []}
+ {"execute":"quit"}
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
++{"return": {}}
+ read 512/512 bytes at offset 0
+ 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+ { 'execute': 'qmp_capabilities' }
+@@ -432,12 +424,10 @@ read 512/512 bytes at offset 0
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}}
+ {"return": {}}
+-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 327680, "offset": 327680, "speed": 0, "type": "mirror"}}
+ {"execute":"query-block-jobs"}
+ {"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 327680, "offset": 327680, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
+ {"execute":"quit"}
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "standby", "id": "src"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
+@@ -445,6 +435,7 @@ read 512/512 bytes at offset 0
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "src", "len": 327680, "offset": 327680, "speed": 0, "type": "mirror"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
++{"return": {}}
+ Images are identical.
+
+ === Copying sample image simple-pattern.cloop into raw ===
+@@ -453,7 +444,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
+ { 'execute': 'qmp_capabilities' }
+ {"return": {}}
+ {'execute':'drive-mirror', 'arguments':{
+- 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
++ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
+ 'mode': 'existing', 'sync': 'full'}}
+ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw.
+ Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
+@@ -469,8 +460,8 @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed
+ {"execute":"query-block-jobs"}
+ {"return": []}
+ {"execute":"quit"}
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
++{"return": {}}
+ read 512/512 bytes at offset 0
+ 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+ { 'execute': 'qmp_capabilities' }
+@@ -481,12 +472,10 @@ read 512/512 bytes at offset 0
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}}
+ {"return": {}}
+-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 2048, "offset": 2048, "speed": 0, "type": "mirror"}}
+ {"execute":"query-block-jobs"}
+ {"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 2048, "offset": 2048, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
+ {"execute":"quit"}
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "standby", "id": "src"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
+@@ -494,6 +483,7 @@ read 512/512 bytes at offset 0
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "src", "len": 2048, "offset": 2048, "speed": 0, "type": "mirror"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
++{"return": {}}
+ Images are identical.
+
+ === Write legitimate MBR into raw ===
+@@ -502,7 +492,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
+ { 'execute': 'qmp_capabilities' }
+ {"return": {}}
+ {'execute':'drive-mirror', 'arguments':{
+- 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
++ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
+ 'mode': 'existing', 'sync': 'full'}}
+ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw.
+ Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
+@@ -510,12 +500,10 @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}}
+ {"return": {}}
+-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 512, "offset": 512, "speed": 0, "type": "mirror"}}
+ {"execute":"query-block-jobs"}
+ {"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 512, "offset": 512, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
+ {"execute":"quit"}
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "standby", "id": "src"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
+@@ -523,6 +511,7 @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "src", "len": 512, "offset": 512, "speed": 0, "type": "mirror"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
++{"return": {}}
+ Images are identical.
+ { 'execute': 'qmp_capabilities' }
+ {"return": {}}
+@@ -532,12 +521,10 @@ Images are identical.
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}}
+ {"return": {}}
+-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 512, "offset": 512, "speed": 0, "type": "mirror"}}
+ {"execute":"query-block-jobs"}
+ {"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 512, "offset": 512, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
+ {"execute":"quit"}
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "standby", "id": "src"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
+@@ -545,5 +532,6 @@ Images are identical.
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "src", "len": 512, "offset": 512, "speed": 0, "type": "mirror"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
++{"return": {}}
+ Images are identical.
+ *** done
+diff --git a/tests/qemu-iotests/117.out b/tests/qemu-iotests/117.out
+index 735ffd25c6..1cea9e0217 100644
+--- a/tests/qemu-iotests/117.out
++++ b/tests/qemu-iotests/117.out
+@@ -18,8 +18,8 @@ wrote 65536/65536 bytes at offset 0
+ 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+ {"return": ""}
+ { 'execute': 'quit' }
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
++{"return": {}}
+ No errors were found on the image.
+ read 65536/65536 bytes at offset 0
+ 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+diff --git a/tests/qemu-iotests/120.out b/tests/qemu-iotests/120.out
+index 0744c1f136..35d84a5bc5 100644
+--- a/tests/qemu-iotests/120.out
++++ b/tests/qemu-iotests/120.out
+@@ -5,8 +5,8 @@ QMP_VERSION
+ wrote 65536/65536 bytes at offset 0
+ 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+ {"return": ""}
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
++{"return": {}}
+ read 65536/65536 bytes at offset 0
+ 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+ read 65536/65536 bytes at offset 0
+diff --git a/tests/qemu-iotests/127.out b/tests/qemu-iotests/127.out
+index 1685c4850a..dd8c4a8aa9 100644
+--- a/tests/qemu-iotests/127.out
++++ b/tests/qemu-iotests/127.out
+@@ -28,6 +28,6 @@ wrote 42/42 bytes at offset 0
+ { 'execute': 'quit' }
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "mirror"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "mirror"}}
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
++{"return": {}}
+ *** done
+diff --git a/tests/qemu-iotests/140.out b/tests/qemu-iotests/140.out
+index 312f76d5da..32866440ae 100644
+--- a/tests/qemu-iotests/140.out
++++ b/tests/qemu-iotests/140.out
+@@ -19,6 +19,6 @@ read 65536/65536 bytes at offset 0
+ qemu-io: can't open device nbd+unix:///drv?socket=SOCK_DIR/nbd: Requested export not available
+ server reported: export 'drv' not present
+ { 'execute': 'quit' }
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
++{"return": {}}
+ *** done
+diff --git a/tests/qemu-iotests/141 b/tests/qemu-iotests/141
+index a37030ee17..a7d3985a02 100755
+--- a/tests/qemu-iotests/141
++++ b/tests/qemu-iotests/141
+@@ -1,9 +1,12 @@
+-#!/usr/bin/env bash
++#!/usr/bin/env python3
+ # group: rw auto quick
+ #
+ # Test case for ejecting BDSs with block jobs still running on them
+ #
+-# Copyright (C) 2016 Red Hat, Inc.
++# Originally written in bash by Hanna Czenczek, ported to Python by Stefan
++# Hajnoczi.
++#
++# Copyright Red Hat
+ #
+ # This program is free software; you can redistribute it and/or modify
+ # it under the terms of the GNU General Public License as published by
+@@ -19,177 +22,129 @@
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
+ #
+
+-# creator
+-owner=hreitz@redhat.com
+-
+-seq="$(basename $0)"
+-echo "QA output created by $seq"
+-
+-status=1 # failure is the default!
+-
+-_cleanup()
+-{
+- _cleanup_qemu
+- _cleanup_test_img
+- for img in "$TEST_DIR"/{b,m,o}.$IMGFMT; do
+- _rm_test_img "$img"
+- done
+-}
+-trap "_cleanup; exit \$status" 0 1 2 3 15
+-
+-# get standard environment, filters and checks
+-. ./common.rc
+-. ./common.filter
+-. ./common.qemu
+-
+-# Needs backing file and backing format support
+-_supported_fmt qcow2 qed
+-_supported_proto file
+-_supported_os Linux
+-
+-
+-test_blockjob()
+-{
+- _send_qemu_cmd $QEMU_HANDLE \
+- "{'execute': 'blockdev-add',
+- 'arguments': {
+- 'node-name': 'drv0',
+- 'driver': '$IMGFMT',
+- 'file': {
+- 'driver': 'file',
+- 'filename': '$TEST_IMG'
+- }}}" \
+- 'return'
+-
+- # If "$2" is an event, we may or may not see it before the
+- # {"return": {}}. Therefore, filter the {"return": {}} out both
+- # here and in the next command. (Naturally, if we do not see it
+- # here, we will see it before the next command can be executed,
+- # so it will appear in the next _send_qemu_cmd's output.)
+- _send_qemu_cmd $QEMU_HANDLE \
+- "$1" \
+- "$2" \
+- | _filter_img_create | _filter_qmp_empty_return
+-
+- # We want this to return an error because the block job is still running
+- _send_qemu_cmd $QEMU_HANDLE \
+- "{'execute': 'blockdev-del',
+- 'arguments': {'node-name': 'drv0'}}" \
+- 'error' | _filter_generated_node_ids | _filter_qmp_empty_return
+-
+- _send_qemu_cmd $QEMU_HANDLE \
+- "{'execute': 'block-job-cancel',
+- 'arguments': {'device': 'job0'}}" \
+- "$3"
+-
+- _send_qemu_cmd $QEMU_HANDLE \
+- "{'execute': 'blockdev-del',
+- 'arguments': {'node-name': 'drv0'}}" \
+- 'return'
+-}
+-
+-
+-TEST_IMG="$TEST_DIR/b.$IMGFMT" _make_test_img 1M
+-TEST_IMG="$TEST_DIR/m.$IMGFMT" _make_test_img -b "$TEST_DIR/b.$IMGFMT" -F $IMGFMT 1M
+-_make_test_img -b "$TEST_DIR/m.$IMGFMT" 1M -F $IMGFMT
+-
+-_launch_qemu -nodefaults
+-
+-_send_qemu_cmd $QEMU_HANDLE \
+- "{'execute': 'qmp_capabilities'}" \
+- 'return'
+-
+-echo
+-echo '=== Testing drive-backup ==='
+-echo
+-
+-# drive-backup will not send BLOCK_JOB_READY by itself, and cancelling the job
+-# will consequently result in BLOCK_JOB_CANCELLED being emitted.
+-
+-test_blockjob \
+- "{'execute': 'drive-backup',
+- 'arguments': {'job-id': 'job0',
+- 'device': 'drv0',
+- 'target': '$TEST_DIR/o.$IMGFMT',
+- 'format': '$IMGFMT',
+- 'sync': 'none'}}" \
+- 'return' \
+- '"status": "null"'
+-
+-echo
+-echo '=== Testing drive-mirror ==='
+-echo
+-
+-# drive-mirror will send BLOCK_JOB_READY basically immediately, and cancelling
+-# the job will consequently result in BLOCK_JOB_COMPLETED being emitted.
+-
+-test_blockjob \
+- "{'execute': 'drive-mirror',
+- 'arguments': {'job-id': 'job0',
+- 'device': 'drv0',
+- 'target': '$TEST_DIR/o.$IMGFMT',
+- 'format': '$IMGFMT',
+- 'sync': 'none'}}" \
+- 'BLOCK_JOB_READY' \
+- '"status": "null"'
+-
+-echo
+-echo '=== Testing active block-commit ==='
+-echo
+-
+-# An active block-commit will send BLOCK_JOB_READY basically immediately, and
+-# cancelling the job will consequently result in BLOCK_JOB_COMPLETED being
+-# emitted.
+-
+-test_blockjob \
+- "{'execute': 'block-commit',
+- 'arguments': {'job-id': 'job0', 'device': 'drv0'}}" \
+- 'BLOCK_JOB_READY' \
+- '"status": "null"'
+-
+-echo
+-echo '=== Testing non-active block-commit ==='
+-echo
+-
+-# Give block-commit something to work on, otherwise it would be done
+-# immediately, send a BLOCK_JOB_COMPLETED and ejecting the BDS would work just
+-# fine without the block job still running.
+-
+-$QEMU_IO -c 'write 0 1M' "$TEST_DIR/m.$IMGFMT" | _filter_qemu_io
+-
+-test_blockjob \
+- "{'execute': 'block-commit',
+- 'arguments': {'job-id': 'job0',
+- 'device': 'drv0',
+- 'top': '$TEST_DIR/m.$IMGFMT',
+- 'speed': 1}}" \
+- 'return' \
+- '"status": "null"'
+-
+-echo
+-echo '=== Testing block-stream ==='
+-echo
+-
+-# Give block-stream something to work on, otherwise it would be done
+-# immediately, send a BLOCK_JOB_COMPLETED and ejecting the BDS would work just
+-# fine without the block job still running.
+-
+-$QEMU_IO -c 'write 0 1M' "$TEST_DIR/b.$IMGFMT" | _filter_qemu_io
+-
+-# With some data to stream (and @speed set to 1), block-stream will not complete
+-# until we send the block-job-cancel command.
+-
+-test_blockjob \
+- "{'execute': 'block-stream',
+- 'arguments': {'job-id': 'job0',
+- 'device': 'drv0',
+- 'speed': 1}}" \
+- 'return' \
+- '"status": "null"'
+-
+-_cleanup_qemu
+-
+-# success, all done
+-echo "*** done"
+-rm -f $seq.full
+-status=0
++import iotests
++
++# Common filters to mask values that vary in the test output
++QMP_FILTERS = [iotests.filter_qmp_testfiles, \
++ iotests.filter_qmp_imgfmt]
++
++
++class TestCase:
++ def __init__(self, name, vm, image_path, cancel_event):
++ self.name = name
++ self.vm = vm
++ self.image_path = image_path
++ self.cancel_event = cancel_event
++
++ def __enter__(self):
++ iotests.log(f'=== Testing {self.name} ===')
++ self.vm.qmp_log('blockdev-add', \
++ node_name='drv0', \
++ driver=iotests.imgfmt, \
++ file={'driver': 'file', 'filename': self.image_path}, \
++ filters=QMP_FILTERS)
++
++ def __exit__(self, *exc_details):
++ # This is expected to fail because the job still exists
++ self.vm.qmp_log('blockdev-del', node_name='drv0', \
++ filters=[iotests.filter_qmp_generated_node_ids])
++
++ self.vm.qmp_log('block-job-cancel', device='job0')
++ event = self.vm.event_wait(self.cancel_event)
++ iotests.log(event, filters=[iotests.filter_qmp_event])
++
++ # This time it succeeds
++ self.vm.qmp_log('blockdev-del', node_name='drv0')
++
++ # Separate test cases in output
++ iotests.log('')
++
++
++def main() -> None:
++ with iotests.FilePath('bottom', 'middle', 'top', 'target') as \
++ (bottom_path, middle_path, top_path, target_path), \
++ iotests.VM() as vm:
++
++ iotests.log('Creating bottom <- middle <- top backing file chain...')
++ IMAGE_SIZE='1M'
++ iotests.qemu_img_create('-f', iotests.imgfmt, bottom_path, IMAGE_SIZE)
++ iotests.qemu_img_create('-f', iotests.imgfmt, \
++ '-F', iotests.imgfmt, \
++ '-b', bottom_path, \
++ middle_path, \
++ IMAGE_SIZE)
++ iotests.qemu_img_create('-f', iotests.imgfmt, \
++ '-F', iotests.imgfmt, \
++ '-b', middle_path, \
++ top_path, \
++ IMAGE_SIZE)
++
++ iotests.log('Starting VM...')
++ vm.add_args('-nodefaults')
++ vm.launch()
++
++ # drive-backup will not send BLOCK_JOB_READY by itself, and cancelling
++ # the job will consequently result in BLOCK_JOB_CANCELLED being
++ # emitted.
++ with TestCase('drive-backup', vm, top_path, 'BLOCK_JOB_CANCELLED'):
++ vm.qmp_log('drive-backup', \
++ job_id='job0', \
++ device='drv0', \
++ target=target_path, \
++ format=iotests.imgfmt, \
++ sync='none', \
++ filters=QMP_FILTERS)
++
++ # drive-mirror will send BLOCK_JOB_READY basically immediately, and
++ # cancelling the job will consequently result in BLOCK_JOB_COMPLETED
++ # being emitted.
++ with TestCase('drive-mirror', vm, top_path, 'BLOCK_JOB_COMPLETED'):
++ vm.qmp_log('drive-mirror', \
++ job_id='job0', \
++ device='drv0', \
++ target=target_path, \
++ format=iotests.imgfmt, \
++ sync='none', \
++ filters=QMP_FILTERS)
++ event = vm.event_wait('BLOCK_JOB_READY')
++ assert event is not None # silence mypy
++ iotests.log(event, filters=[iotests.filter_qmp_event])
++
++ # An active block-commit will send BLOCK_JOB_READY basically
++ # immediately, and cancelling the job will consequently result in
++ # BLOCK_JOB_COMPLETED being emitted.
++ with TestCase('active block-commit', vm, top_path, \
++ 'BLOCK_JOB_COMPLETED'):
++ vm.qmp_log('block-commit', \
++ job_id='job0', \
++ device='drv0')
++ event = vm.event_wait('BLOCK_JOB_READY')
++ assert event is not None # silence mypy
++ iotests.log(event, filters=[iotests.filter_qmp_event])
++
++ # Give block-commit something to work on, otherwise it would be done
++ # immediately, send a BLOCK_JOB_COMPLETED and ejecting the BDS would
++ # work just fine without the block job still running.
++ iotests.qemu_io(middle_path, '-c', f'write 0 {IMAGE_SIZE}')
++ with TestCase('non-active block-commit', vm, top_path, \
++ 'BLOCK_JOB_CANCELLED'):
++ vm.qmp_log('block-commit', \
++ job_id='job0', \
++ device='drv0', \
++ top=middle_path, \
++ speed=1, \
++ filters=[iotests.filter_qmp_testfiles])
++
++ # Give block-stream something to work on, otherwise it would be done
++ # immediately, send a BLOCK_JOB_COMPLETED and ejecting the BDS would
++ # work just fine without the block job still running.
++ iotests.qemu_io(bottom_path, '-c', f'write 0 {IMAGE_SIZE}')
++ with TestCase('block-stream', vm, top_path, 'BLOCK_JOB_CANCELLED'):
++ vm.qmp_log('block-stream', \
++ job_id='job0', \
++ device='drv0', \
++ speed=1)
++
++if __name__ == '__main__':
++ iotests.script_main(main, supported_fmts=['qcow2', 'qed'],
++ supported_protocols=['file'])
+diff --git a/tests/qemu-iotests/141.out b/tests/qemu-iotests/141.out
+index 63203d9944..91b7ba50af 100644
+--- a/tests/qemu-iotests/141.out
++++ b/tests/qemu-iotests/141.out
+@@ -1,179 +1,69 @@
+-QA output created by 141
+-Formatting 'TEST_DIR/b.IMGFMT', fmt=IMGFMT size=1048576
+-Formatting 'TEST_DIR/m.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/b.IMGFMT backing_fmt=IMGFMT
+-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/m.IMGFMT backing_fmt=IMGFMT
+-{'execute': 'qmp_capabilities'}
+-{"return": {}}
+-
++Creating bottom <- middle <- top backing file chain...
++Starting VM...
+ === Testing drive-backup ===
+-
+-{'execute': 'blockdev-add',
+- 'arguments': {
+- 'node-name': 'drv0',
+- 'driver': 'IMGFMT',
+- 'file': {
+- 'driver': 'file',
+- 'filename': 'TEST_DIR/t.IMGFMT'
+- }}}
+-{"return": {}}
+-{'execute': 'drive-backup',
+-'arguments': {'job-id': 'job0',
+-'device': 'drv0',
+-'target': 'TEST_DIR/o.IMGFMT',
+-'format': 'IMGFMT',
+-'sync': 'none'}}
+-Formatting 'TEST_DIR/o.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT backing_fmt=IMGFMT
+-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}}
+-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}}
+-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "paused", "id": "job0"}}
+-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}}
+-{'execute': 'blockdev-del',
+- 'arguments': {'node-name': 'drv0'}}
++{"execute": "blockdev-add", "arguments": {"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top"}, "node-name": "drv0"}}
++{"return": {}}
++{"execute": "drive-backup", "arguments": {"device": "drv0", "format": "IMGFMT", "job-id": "job0", "sync": "none", "target": "TEST_DIR/PID-target"}}
++{"return": {}}
++{"execute": "blockdev-del", "arguments": {"node-name": "drv0"}}
+ {"error": {"class": "GenericError", "desc": "Node 'drv0' is busy: node is used as backing hd of 'NODE_NAME'"}}
+-{'execute': 'block-job-cancel',
+- 'arguments': {'device': 'job0'}}
++{"execute": "block-job-cancel", "arguments": {"device": "job0"}}
+ {"return": {}}
+-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "job0"}}
+-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "job0", "len": 1048576, "offset": 0, "speed": 0, "type": "backup"}}
+-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job0"}}
+-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job0"}}
+-{'execute': 'blockdev-del',
+- 'arguments': {'node-name': 'drv0'}}
++{"data": {"device": "job0", "len": 1048576, "offset": 0, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_CANCELLED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
++{"execute": "blockdev-del", "arguments": {"node-name": "drv0"}}
+ {"return": {}}
+
+ === Testing drive-mirror ===
+-
+-{'execute': 'blockdev-add',
+- 'arguments': {
+- 'node-name': 'drv0',
+- 'driver': 'IMGFMT',
+- 'file': {
+- 'driver': 'file',
+- 'filename': 'TEST_DIR/t.IMGFMT'
+- }}}
+-{"return": {}}
+-{'execute': 'drive-mirror',
+-'arguments': {'job-id': 'job0',
+-'device': 'drv0',
+-'target': 'TEST_DIR/o.IMGFMT',
+-'format': 'IMGFMT',
+-'sync': 'none'}}
+-Formatting 'TEST_DIR/o.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT backing_fmt=IMGFMT
+-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}}
+-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}}
+-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "job0"}}
+-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "mirror"}}
+-{'execute': 'blockdev-del',
+- 'arguments': {'node-name': 'drv0'}}
++{"execute": "blockdev-add", "arguments": {"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top"}, "node-name": "drv0"}}
++{"return": {}}
++{"execute": "drive-mirror", "arguments": {"device": "drv0", "format": "IMGFMT", "job-id": "job0", "sync": "none", "target": "TEST_DIR/PID-target"}}
++{"return": {}}
++{"data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "mirror"}, "event": "BLOCK_JOB_READY", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
++{"execute": "blockdev-del", "arguments": {"node-name": "drv0"}}
+ {"error": {"class": "GenericError", "desc": "Node 'drv0' is busy: block device is in use by block job: mirror"}}
+-{'execute': 'block-job-cancel',
+- 'arguments': {'device': 'job0'}}
++{"execute": "block-job-cancel", "arguments": {"device": "job0"}}
+ {"return": {}}
+-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "job0"}}
+-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "job0"}}
+-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "mirror"}}
+-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job0"}}
+-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job0"}}
+-{'execute': 'blockdev-del',
+- 'arguments': {'node-name': 'drv0'}}
++{"data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "mirror"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
++{"execute": "blockdev-del", "arguments": {"node-name": "drv0"}}
+ {"return": {}}
+
+ === Testing active block-commit ===
+-
+-{'execute': 'blockdev-add',
+- 'arguments': {
+- 'node-name': 'drv0',
+- 'driver': 'IMGFMT',
+- 'file': {
+- 'driver': 'file',
+- 'filename': 'TEST_DIR/t.IMGFMT'
+- }}}
+-{"return": {}}
+-{'execute': 'block-commit',
+-'arguments': {'job-id': 'job0', 'device': 'drv0'}}
+-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}}
+-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}}
+-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "job0"}}
+-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}}
+-{'execute': 'blockdev-del',
+- 'arguments': {'node-name': 'drv0'}}
++{"execute": "blockdev-add", "arguments": {"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top"}, "node-name": "drv0"}}
++{"return": {}}
++{"execute": "block-commit", "arguments": {"device": "drv0", "job-id": "job0"}}
++{"return": {}}
++{"data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}, "event": "BLOCK_JOB_READY", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
++{"execute": "blockdev-del", "arguments": {"node-name": "drv0"}}
+ {"error": {"class": "GenericError", "desc": "Node 'drv0' is busy: block device is in use by block job: commit"}}
+-{'execute': 'block-job-cancel',
+- 'arguments': {'device': 'job0'}}
++{"execute": "block-job-cancel", "arguments": {"device": "job0"}}
+ {"return": {}}
+-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "job0"}}
+-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "job0"}}
+-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}}
+-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job0"}}
+-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job0"}}
+-{'execute': 'blockdev-del',
+- 'arguments': {'node-name': 'drv0'}}
++{"data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
++{"execute": "blockdev-del", "arguments": {"node-name": "drv0"}}
+ {"return": {}}
+
+ === Testing non-active block-commit ===
+-
+-wrote 1048576/1048576 bytes at offset 0
+-1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+-{'execute': 'blockdev-add',
+- 'arguments': {
+- 'node-name': 'drv0',
+- 'driver': 'IMGFMT',
+- 'file': {
+- 'driver': 'file',
+- 'filename': 'TEST_DIR/t.IMGFMT'
+- }}}
+-{"return": {}}
+-{'execute': 'block-commit',
+-'arguments': {'job-id': 'job0',
+-'device': 'drv0',
+-'top': 'TEST_DIR/m.IMGFMT',
+-'speed': 1}}
+-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}}
+-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}}
+-{'execute': 'blockdev-del',
+- 'arguments': {'node-name': 'drv0'}}
++{"execute": "blockdev-add", "arguments": {"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top"}, "node-name": "drv0"}}
++{"return": {}}
++{"execute": "block-commit", "arguments": {"device": "drv0", "job-id": "job0", "speed": 1, "top": "TEST_DIR/PID-middle"}}
++{"return": {}}
++{"execute": "blockdev-del", "arguments": {"node-name": "drv0"}}
+ {"error": {"class": "GenericError", "desc": "Node 'drv0' is busy: block device is in use by block job: commit"}}
+-{'execute': 'block-job-cancel',
+- 'arguments': {'device': 'job0'}}
++{"execute": "block-job-cancel", "arguments": {"device": "job0"}}
+ {"return": {}}
+-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "job0"}}
+-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "job0", "len": 1048576, "offset": 524288, "speed": 1, "type": "commit"}}
+-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job0"}}
+-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job0"}}
+-{'execute': 'blockdev-del',
+- 'arguments': {'node-name': 'drv0'}}
++{"data": {"device": "job0", "len": 1048576, "offset": 524288, "speed": 1, "type": "commit"}, "event": "BLOCK_JOB_CANCELLED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
++{"execute": "blockdev-del", "arguments": {"node-name": "drv0"}}
+ {"return": {}}
+
+ === Testing block-stream ===
+-
+-wrote 1048576/1048576 bytes at offset 0
+-1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+-{'execute': 'blockdev-add',
+- 'arguments': {
+- 'node-name': 'drv0',
+- 'driver': 'IMGFMT',
+- 'file': {
+- 'driver': 'file',
+- 'filename': 'TEST_DIR/t.IMGFMT'
+- }}}
+-{"return": {}}
+-{'execute': 'block-stream',
+-'arguments': {'job-id': 'job0',
+-'device': 'drv0',
+-'speed': 1}}
+-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}}
+-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}}
+-{'execute': 'blockdev-del',
+- 'arguments': {'node-name': 'drv0'}}
++{"execute": "blockdev-add", "arguments": {"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top"}, "node-name": "drv0"}}
++{"return": {}}
++{"execute": "block-stream", "arguments": {"device": "drv0", "job-id": "job0", "speed": 1}}
++{"return": {}}
++{"execute": "blockdev-del", "arguments": {"node-name": "drv0"}}
+ {"error": {"class": "GenericError", "desc": "Node 'drv0' is busy: block device is in use by block job: stream"}}
+-{'execute': 'block-job-cancel',
+- 'arguments': {'device': 'job0'}}
++{"execute": "block-job-cancel", "arguments": {"device": "job0"}}
+ {"return": {}}
+-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "job0"}}
+-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "job0", "len": 1048576, "offset": 524288, "speed": 1, "type": "stream"}}
+-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job0"}}
+-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job0"}}
+-{'execute': 'blockdev-del',
+- 'arguments': {'node-name': 'drv0'}}
++{"data": {"device": "job0", "len": 1048576, "offset": 524288, "speed": 1, "type": "stream"}, "event": "BLOCK_JOB_CANCELLED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
++{"execute": "blockdev-del", "arguments": {"node-name": "drv0"}}
+ {"return": {}}
+-*** done
++
+diff --git a/tests/qemu-iotests/143.out b/tests/qemu-iotests/143.out
+index 9ec5888e0e..d6afa32abc 100644
+--- a/tests/qemu-iotests/143.out
++++ b/tests/qemu-iotests/143.out
+@@ -10,6 +10,6 @@ server reported: export 'no_such_export' not present
+ qemu-io: can't open device nbd+unix:///aa--aa1?socket=SOCK_DIR/nbd: Requested export not available
+ server reported: export 'aa--aa...' not present
+ { 'execute': 'quit' }
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
++{"return": {}}
+ *** done
+diff --git a/tests/qemu-iotests/156.out b/tests/qemu-iotests/156.out
+index 4a22f0c41a..07e5e83f5d 100644
+--- a/tests/qemu-iotests/156.out
++++ b/tests/qemu-iotests/156.out
+@@ -72,8 +72,8 @@ read 65536/65536 bytes at offset 196608
+ {"return": ""}
+
+ { 'execute': 'quit' }
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
++{"return": {}}
+
+ read 65536/65536 bytes at offset 0
+ 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+diff --git a/tests/qemu-iotests/176.out b/tests/qemu-iotests/176.out
+index 9d09b60452..45e9153ef3 100644
+--- a/tests/qemu-iotests/176.out
++++ b/tests/qemu-iotests/176.out
+@@ -169,8 +169,8 @@ QMP_VERSION
+ {"return": {}}
+ {"return": {}}
+ {"return": {}}
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
++{"return": {}}
+ wrote 196608/196608 bytes at offset 2147287040
+ 192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+ wrote 131072/131072 bytes at offset 2147352576
+@@ -206,8 +206,8 @@ QMP_VERSION
+ {"return": {}}
+ {"return": {}}
+ {"return": {"sha256": HASH}}
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
++{"return": {}}
+
+ === Test pass bitmap.1 ===
+
+@@ -218,8 +218,8 @@ QMP_VERSION
+ {"return": {}}
+ {"return": {}}
+ {"return": {}}
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
++{"return": {}}
+ wrote 196608/196608 bytes at offset 2147287040
+ 192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+ wrote 131072/131072 bytes at offset 2147352576
+@@ -256,8 +256,8 @@ QMP_VERSION
+ {"return": {}}
+ {"return": {}}
+ {"return": {"sha256": HASH}}
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
++{"return": {}}
+
+ === Test pass bitmap.2 ===
+
+@@ -268,8 +268,8 @@ QMP_VERSION
+ {"return": {}}
+ {"return": {}}
+ {"return": {}}
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
++{"return": {}}
+ wrote 196608/196608 bytes at offset 2147287040
+ 192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+ wrote 131072/131072 bytes at offset 2147352576
+@@ -306,8 +306,8 @@ QMP_VERSION
+ {"return": {}}
+ {"return": {}}
+ {"return": {"sha256": HASH}}
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
++{"return": {}}
+
+ === Test pass bitmap.3 ===
+
+@@ -318,8 +318,8 @@ QMP_VERSION
+ {"return": {}}
+ {"return": {}}
+ {"return": {}}
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
++{"return": {}}
+ wrote 196608/196608 bytes at offset 2147287040
+ 192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+ wrote 131072/131072 bytes at offset 2147352576
+@@ -353,6 +353,6 @@ QMP_VERSION
+ {"return": {}}
+ {"return": {}}
+ {"return": {"sha256": HASH}}
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
++{"return": {}}
+ *** done
+diff --git a/tests/qemu-iotests/182.out b/tests/qemu-iotests/182.out
+index 57f7265458..83fc1a4797 100644
+--- a/tests/qemu-iotests/182.out
++++ b/tests/qemu-iotests/182.out
+@@ -53,6 +53,6 @@ Formatting 'TEST_DIR/t.qcow2.overlay', fmt=qcow2 cluster_size=65536 extended_l2=
+ {'execute': 'qmp_capabilities'}
+ {"return": {}}
+ {'execute': 'quit'}
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
++{"return": {}}
+ *** done
+diff --git a/tests/qemu-iotests/183.out b/tests/qemu-iotests/183.out
+index fd9c2e52a5..51aa41c888 100644
+--- a/tests/qemu-iotests/183.out
++++ b/tests/qemu-iotests/183.out
+@@ -53,11 +53,11 @@ wrote 65536/65536 bytes at offset 1048576
+ === Shut down and check image ===
+
+ {"execute":"quit"}
++{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+ {"return": {}}
+ {"execute":"quit"}
+-{"return": {}}
+-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
++{"return": {}}
+ No errors were found on the image.
+ No errors were found on the image.
+ wrote 65536/65536 bytes at offset 1048576
+diff --git a/tests/qemu-iotests/184.out b/tests/qemu-iotests/184.out
+index 77e5489d65..e8f631f853 100644
+--- a/tests/qemu-iotests/184.out
++++ b/tests/qemu-iotests/184.out
+@@ -89,10 +89,6 @@ Testing:
+ "return": [
+ ]
+ }
+-{
+- "return": {
+- }
+-}
+ {
+ "timestamp": {
+ "seconds": TIMESTAMP,
+@@ -104,6 +100,10 @@ Testing:
+ "reason": "host-qmp-quit"
+ }
+ }
++{
++ "return": {
++ }
++}
+
+
+ == property changes in ThrottleGroup ==
+@@ -169,10 +169,6 @@ Testing:
+ "iops-total-max": 0
+ }
+ }
+-{
+- "return": {
+- }
+-}
+ {
+ "timestamp": {
+ "seconds": TIMESTAMP,
+@@ -184,6 +180,10 @@ Testing:
+ "reason": "host-qmp-quit"
+ }
+ }
++{
++ "return": {
++ }
++}
+
+
+ == object creation/set errors ==
+@@ -211,10 +211,6 @@ Testing:
+ "desc": "bps/iops/max total values and read/write values cannot be used at the same time"
+ }
+ }
+-{
+- "return": {
+- }
+-}
+ {
+ "timestamp": {
+ "seconds": TIMESTAMP,
+@@ -226,6 +222,10 @@ Testing:
+ "reason": "host-qmp-quit"
+ }
+ }
++{
++ "return": {
++ }
++}
+
+
+ == don't specify group ==
+@@ -247,10 +247,6 @@ Testing:
+ "desc": "Parameter 'throttle-group' is missing"
+ }
+ }
+-{
+- "return": {
+- }
+-}
+ {
+ "timestamp": {
+ "seconds": TIMESTAMP,
+@@ -262,6 +258,10 @@ Testing:
+ "reason": "host-qmp-quit"
+ }
+ }
++{
++ "return": {
++ }
++}
+
+
+ *** done
+diff --git a/tests/qemu-iotests/185 b/tests/qemu-iotests/185
+index 8b1143dc16..61f13d0460 100755
+--- a/tests/qemu-iotests/185
++++ b/tests/qemu-iotests/185
+@@ -344,14 +344,14 @@ wait_for_job_and_quit() {
+
+ sleep 1
+
++ # List of expected events
++ capture_events='BLOCK_JOB_CANCELLED JOB_STATUS_CHANGE SHUTDOWN'
++
+ _send_qemu_cmd $h \
+ '{"execute": "quit"}' \
+ 'return'
+
+- # List of expected events
+- capture_events='BLOCK_JOB_CANCELLED JOB_STATUS_CHANGE SHUTDOWN'
+ _wait_event $h 'SHUTDOWN'
+- QEMU_EVENTS= # Ignore all JOB_STATUS_CHANGE events that came before SHUTDOWN
+ _wait_event $h 'JOB_STATUS_CHANGE' # standby
+ _wait_event $h 'JOB_STATUS_CHANGE' # ready
+ _wait_event $h 'JOB_STATUS_CHANGE' # aborting
+diff --git a/tests/qemu-iotests/185.out b/tests/qemu-iotests/185.out
+index 70e8dd6c87..1cccccb1b6 100644
+--- a/tests/qemu-iotests/185.out
++++ b/tests/qemu-iotests/185.out
+@@ -40,9 +40,16 @@ Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off comp
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
+ {"return": {}}
+ { 'execute': 'quit' }
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
++{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "paused", "id": "disk"}}
++{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
++{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "paused", "id": "disk"}}
++{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
++{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "disk"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "disk", "len": 67108864, "offset": 524288, "speed": 65536, "type": "commit"}}
++{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "disk"}}
++{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "disk"}}
++{"return": {}}
+
+ === Start active commit job and exit qemu ===
+
+@@ -56,9 +63,16 @@ Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off comp
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
+ {"return": {}}
+ { 'execute': 'quit' }
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
++{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "paused", "id": "disk"}}
++{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
++{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "paused", "id": "disk"}}
++{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
++{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "disk"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "disk", "len": 4194304, "offset": 4194304, "speed": 65536, "type": "commit"}}
++{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "disk"}}
++{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "disk"}}
++{"return": {}}
+
+ === Start mirror job and exit qemu ===
+
+@@ -75,9 +89,16 @@ Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 cluster_size=65536 extended_l2=off
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
+ {"return": {}}
+ { 'execute': 'quit' }
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
++{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "paused", "id": "disk"}}
++{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
++{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "paused", "id": "disk"}}
++{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
++{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "disk"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "disk", "len": 4194304, "offset": 4194304, "speed": 65536, "type": "mirror"}}
++{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "disk"}}
++{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "disk"}}
++{"return": {}}
+
+ === Start backup job and exit qemu ===
+
+@@ -97,9 +118,16 @@ Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 cluster_size=65536 extended_l2=off
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
+ {"return": {}}
+ { 'execute': 'quit' }
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
++{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "paused", "id": "disk"}}
++{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
++{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "paused", "id": "disk"}}
++{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
++{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "disk"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "disk", "len": 67108864, "offset": 65536, "speed": 65536, "type": "backup"}}
++{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "disk"}}
++{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "disk"}}
++{"return": {}}
+
+ === Start streaming job and exit qemu ===
+
+@@ -112,9 +140,16 @@ Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 cluster_size=65536 extended_l2=off
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
+ {"return": {}}
+ { 'execute': 'quit' }
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
++{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "paused", "id": "disk"}}
++{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
++{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "paused", "id": "disk"}}
++{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
++{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "disk"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "disk", "len": 67108864, "offset": 524288, "speed": 65536, "type": "stream"}}
++{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "disk"}}
++{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "disk"}}
++{"return": {}}
+ No errors were found on the image.
+
+ === Start mirror to throttled QSD and exit qemu ===
+diff --git a/tests/qemu-iotests/191.out b/tests/qemu-iotests/191.out
+index ea88777374..c3309e4bc6 100644
+--- a/tests/qemu-iotests/191.out
++++ b/tests/qemu-iotests/191.out
+@@ -378,10 +378,6 @@ wrote 65536/65536 bytes at offset 1048576
+ ]
+ }
+ { 'execute': 'quit' }
+-{
+- "return": {
+- }
+-}
+ {
+ "timestamp": {
+ "seconds": TIMESTAMP,
+@@ -393,6 +389,10 @@ wrote 65536/65536 bytes at offset 1048576
+ "reason": "host-qmp-quit"
+ }
+ }
++{
++ "return": {
++ }
++}
+ image: TEST_DIR/t.IMGFMT
+ file format: IMGFMT
+ virtual size: 64 MiB (67108864 bytes)
+@@ -796,10 +796,6 @@ wrote 65536/65536 bytes at offset 1048576
+ ]
+ }
+ { 'execute': 'quit' }
+-{
+- "return": {
+- }
+-}
+ {
+ "timestamp": {
+ "seconds": TIMESTAMP,
+@@ -811,6 +807,10 @@ wrote 65536/65536 bytes at offset 1048576
+ "reason": "host-qmp-quit"
+ }
+ }
++{
++ "return": {
++ }
++}
+ image: TEST_DIR/t.IMGFMT
+ file format: IMGFMT
+ virtual size: 64 MiB (67108864 bytes)
+diff --git a/tests/qemu-iotests/195.out b/tests/qemu-iotests/195.out
+index ec84df5012..91717d302e 100644
+--- a/tests/qemu-iotests/195.out
++++ b/tests/qemu-iotests/195.out
+@@ -17,10 +17,6 @@ Testing: -drive if=none,file=TEST_DIR/t.IMGFMT,backing.node-name=mid
+ "return": {
+ }
+ }
+-{
+- "return": {
+- }
+-}
+ {
+ "timestamp": {
+ "seconds": TIMESTAMP,
+@@ -32,6 +28,10 @@ Testing: -drive if=none,file=TEST_DIR/t.IMGFMT,backing.node-name=mid
+ "reason": "host-qmp-quit"
+ }
+ }
++{
++ "return": {
++ }
++}
+
+ image: TEST_DIR/t.IMGFMT.mid
+ file format: IMGFMT
+@@ -55,10 +55,6 @@ Testing: -drive if=none,file=TEST_DIR/t.IMGFMT,node-name=top
+ "return": {
+ }
+ }
+-{
+- "return": {
+- }
+-}
+ {
+ "timestamp": {
+ "seconds": TIMESTAMP,
+@@ -70,6 +66,10 @@ Testing: -drive if=none,file=TEST_DIR/t.IMGFMT,node-name=top
+ "reason": "host-qmp-quit"
+ }
+ }
++{
++ "return": {
++ }
++}
+
+ image: TEST_DIR/t.IMGFMT
+ file format: IMGFMT
+diff --git a/tests/qemu-iotests/223.out b/tests/qemu-iotests/223.out
+index 26fb347c5d..65625c491e 100644
+--- a/tests/qemu-iotests/223.out
++++ b/tests/qemu-iotests/223.out
+@@ -11,8 +11,8 @@ QMP_VERSION
+ {"return": {}}
+ {"return": {}}
+ {"return": {}}
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
++{"return": {}}
+
+
+ === Write part of the file under active bitmap ===
+@@ -142,14 +142,14 @@ read 2097152/2097152 bytes at offset 2097152
+
+ {"execute":"nbd-server-remove",
+ "arguments":{"name":"n"}}
++{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "n"}}
+ {"return": {}}
+ {"execute":"nbd-server-remove",
+ "arguments":{"name":"n2"}}
+-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "n"}}
++{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "n2"}}
+ {"return": {}}
+ {"execute":"nbd-server-remove",
+ "arguments":{"name":"n2"}}
+-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "n2"}}
+ {"error": {"class": "GenericError", "desc": "Export 'n2' is not found"}}
+ {"execute":"nbd-server-stop"}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "n3"}}
+@@ -261,14 +261,14 @@ read 2097152/2097152 bytes at offset 2097152
+
+ {"execute":"nbd-server-remove",
+ "arguments":{"name":"n"}}
++{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "n"}}
+ {"return": {}}
+ {"execute":"nbd-server-remove",
+ "arguments":{"name":"n2"}}
+-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "n"}}
++{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "n2"}}
+ {"return": {}}
+ {"execute":"nbd-server-remove",
+ "arguments":{"name":"n2"}}
+-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "n2"}}
+ {"error": {"class": "GenericError", "desc": "Export 'n2' is not found"}}
+ {"execute":"nbd-server-stop"}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "n3"}}
+@@ -276,8 +276,8 @@ read 2097152/2097152 bytes at offset 2097152
+ {"execute":"nbd-server-stop"}
+ {"error": {"class": "GenericError", "desc": "NBD server not running"}}
+ {"execute":"quit"}
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
++{"return": {}}
+
+ === Use qemu-nbd as server ===
+
+diff --git a/tests/qemu-iotests/227.out b/tests/qemu-iotests/227.out
+index 378c1b8fb1..b6a56118b7 100644
+--- a/tests/qemu-iotests/227.out
++++ b/tests/qemu-iotests/227.out
+@@ -48,10 +48,6 @@ Testing: -drive driver=null-co,read-zeroes=on,if=virtio
+ }
+ ]
+ }
+-{
+- "return": {
+- }
+-}
+ {
+ "timestamp": {
+ "seconds": TIMESTAMP,
+@@ -63,6 +59,10 @@ Testing: -drive driver=null-co,read-zeroes=on,if=virtio
+ "reason": "host-qmp-quit"
+ }
+ }
++{
++ "return": {
++ }
++}
+
+
+ === blockstats with -drive if=none ===
+@@ -112,10 +112,6 @@ Testing: -drive driver=null-co,if=none
+ }
+ ]
+ }
+-{
+- "return": {
+- }
+-}
+ {
+ "timestamp": {
+ "seconds": TIMESTAMP,
+@@ -127,6 +123,10 @@ Testing: -drive driver=null-co,if=none
+ "reason": "host-qmp-quit"
+ }
+ }
++{
++ "return": {
++ }
++}
+
+
+ === blockstats with -blockdev ===
+@@ -143,10 +143,6 @@ Testing: -blockdev driver=null-co,node-name=null
+ "return": [
+ ]
+ }
+-{
+- "return": {
+- }
+-}
+ {
+ "timestamp": {
+ "seconds": TIMESTAMP,
+@@ -158,6 +154,10 @@ Testing: -blockdev driver=null-co,node-name=null
+ "reason": "host-qmp-quit"
+ }
+ }
++{
++ "return": {
++ }
++}
+
+
+ === blockstats with -blockdev and -device ===
+@@ -208,10 +208,6 @@ Testing: -blockdev driver=null-co,read-zeroes=on,node-name=null -device virtio-b
+ }
+ ]
+ }
+-{
+- "return": {
+- }
+-}
+ {
+ "timestamp": {
+ "seconds": TIMESTAMP,
+@@ -223,5 +219,9 @@ Testing: -blockdev driver=null-co,read-zeroes=on,node-name=null -device virtio-b
+ "reason": "host-qmp-quit"
+ }
+ }
++{
++ "return": {
++ }
++}
+
+ *** done
+diff --git a/tests/qemu-iotests/247.out b/tests/qemu-iotests/247.out
+index e909e83994..7d252e7fe4 100644
+--- a/tests/qemu-iotests/247.out
++++ b/tests/qemu-iotests/247.out
+@@ -17,6 +17,6 @@ QMP_VERSION
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "job0", "len": 134217728, "offset": 134217728, "speed": 0, "type": "commit"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job0"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job0"}}
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
++{"return": {}}
+ *** done
+diff --git a/tests/qemu-iotests/273.out b/tests/qemu-iotests/273.out
+index 6a74a8138b..71843f02de 100644
+--- a/tests/qemu-iotests/273.out
++++ b/tests/qemu-iotests/273.out
+@@ -282,10 +282,6 @@ Testing: -blockdev file,node-name=base,filename=TEST_DIR/t.IMGFMT.base -blockdev
+ ]
+ }
+ }
+-{
+- "return": {
+- }
+-}
+ {
+ "timestamp": {
+ "seconds": TIMESTAMP,
+@@ -297,5 +293,9 @@ Testing: -blockdev file,node-name=base,filename=TEST_DIR/t.IMGFMT.base -blockdev
+ "reason": "host-qmp-quit"
+ }
+ }
++{
++ "return": {
++ }
++}
+
+ *** done
+diff --git a/tests/qemu-iotests/308 b/tests/qemu-iotests/308
+index bde4aac2fa..d1bb49f1de 100755
+--- a/tests/qemu-iotests/308
++++ b/tests/qemu-iotests/308
+@@ -77,6 +77,7 @@ fuse_export_add()
+ # $1: Export ID
+ fuse_export_del()
+ {
++ capture_events="BLOCK_EXPORT_DELETED" \
+ _send_qemu_cmd $QEMU_HANDLE \
+ "{'execute': 'block-export-del',
+ 'arguments': {
+@@ -84,8 +85,7 @@ fuse_export_del()
+ } }" \
+ 'return'
+
+- _send_qemu_cmd $QEMU_HANDLE \
+- '' \
++ _wait_event $QEMU_HANDLE \
+ 'BLOCK_EXPORT_DELETED'
+ }
+
+diff --git a/tests/qemu-iotests/308.out b/tests/qemu-iotests/308.out
+index e4467a10cf..9fcf8844d4 100644
+--- a/tests/qemu-iotests/308.out
++++ b/tests/qemu-iotests/308.out
+@@ -165,9 +165,9 @@ OK: Post-truncate image size is as expected
+
+ === Tear down ===
+ {'execute': 'quit'}
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "export-mp"}}
++{"return": {}}
+
+ === Compare copy with original ===
+ Images are identical.
+diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
+index da7d6637e1..6f7c3c0e44 100644
+--- a/tests/qemu-iotests/iotests.py
++++ b/tests/qemu-iotests/iotests.py
+@@ -642,6 +642,13 @@ def _filter(_key, value):
+ def filter_generated_node_ids(msg):
+ return re.sub("#block[0-9]+", "NODE_NAME", msg)
+
++def filter_qmp_generated_node_ids(qmsg):
++ def _filter(_key, value):
++ if is_str(value):
++ return filter_generated_node_ids(value)
++ return value
++ return filter_qmp(qmsg, _filter)
++
+ def filter_img_info(output, filename):
+ lines = []
+ for line in output.split('\n'):
+diff --git a/tests/qemu-iotests/tests/qcow2-internal-snapshots b/tests/qemu-iotests/tests/qcow2-internal-snapshots
+new file mode 100755
+index 0000000000..36523aba06
+--- /dev/null
++++ b/tests/qemu-iotests/tests/qcow2-internal-snapshots
+@@ -0,0 +1,170 @@
++#!/usr/bin/env bash
++# group: rw quick
++#
++# Test case for internal snapshots in qcow2
++#
++# Copyright (C) 2023 Red Hat, Inc.
++#
++# This program is free software; you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation; either version 2 of the License, or
++# (at your option) any later version.
++#
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++# GNU General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program. If not, see <http://www.gnu.org/licenses/>.
++#
++
++# creator
++owner=kwolf@redhat.com
++
++seq="$(basename $0)"
++echo "QA output created by $seq"
++
++status=1 # failure is the default!
++
++_cleanup()
++{
++ _cleanup_test_img
++}
++trap "_cleanup; exit \$status" 0 1 2 3 15
++
++# get standard environment, filters and checks
++. ../common.rc
++. ../common.filter
++
++# This tests qcow2-specific low-level functionality
++_supported_fmt qcow2
++_supported_proto generic
++# Internal snapshots are (currently) impossible with refcount_bits=1,
++# and generally impossible with external data files
++_unsupported_imgopts 'compat=0.10' 'refcount_bits=1[^0-9]' data_file
++
++IMG_SIZE=64M
++
++_qemu()
++{
++ $QEMU -no-shutdown -nographic -monitor stdio -serial none \
++ -blockdev file,filename="$TEST_IMG",node-name=disk0-file \
++ -blockdev "$IMGFMT",file=disk0-file,node-name=disk0 \
++ -object iothread,id=iothread0 \
++ -device virtio-scsi,iothread=iothread0 \
++ -device scsi-hd,drive=disk0,share-rw=on \
++ "$@" 2>&1 |\
++ _filter_qemu | _filter_hmp | _filter_qemu_io
++}
++
++_make_test_img $IMG_SIZE
++
++echo
++echo "=== Write some data, take a snapshot and overwrite part of it ==="
++echo
++
++{
++ echo 'qemu-io disk0 "write -P0x11 0 1M"'
++ # Give qemu some time to boot before saving the VM state
++ sleep 0.5
++ echo "savevm snap0"
++ echo 'qemu-io disk0 "write -P0x22 0 512k"'
++ echo "quit"
++} | _qemu
++
++echo
++$QEMU_IMG snapshot -l "$TEST_IMG" | _filter_date | _filter_vmstate_size
++_check_test_img
++
++echo
++echo "=== Verify that loading the snapshot reverts to the old content ==="
++echo
++
++{
++ # -loadvm reverted the write from the previous QEMU instance
++ echo 'qemu-io disk0 "read -P0x11 0 1M"'
++
++ # Verify that it works without restarting QEMU, too
++ echo 'qemu-io disk0 "write -P0x33 512k 512k"'
++ echo "loadvm snap0"
++ echo 'qemu-io disk0 "read -P0x11 0 1M"'
++
++ # Verify COW by writing a partial cluster
++ echo 'qemu-io disk0 "write -P0x33 63k 2k"'
++ echo 'qemu-io disk0 "read -P0x11 0 63k"'
++ echo 'qemu-io disk0 "read -P0x33 63k 2k"'
++ echo 'qemu-io disk0 "read -P0x11 65k 63k"'
++
++ # Take a second snapshot
++ echo "savevm snap1"
++
++ echo "quit"
++} | _qemu -loadvm snap0
++
++echo
++$QEMU_IMG snapshot -l "$TEST_IMG" | _filter_date | _filter_vmstate_size
++_check_test_img
++
++echo
++echo "=== qemu-img snapshot can revert to snapshots ==="
++echo
++
++$QEMU_IMG snapshot -a snap0 "$TEST_IMG"
++$QEMU_IO -c "read -P0x11 0 1M" "$TEST_IMG" | _filter_qemu_io
++$QEMU_IMG snapshot -a snap1 "$TEST_IMG"
++$QEMU_IO \
++ -c "read -P0x11 0 63k" \
++ -c "read -P0x33 63k 2k" \
++ -c "read -P0x11 65k 63k" \
++ "$TEST_IMG" | _filter_qemu_io
++
++echo
++echo "=== Deleting snapshots ==="
++echo
++{
++ # The active layer stays unaffected by deleting the snapshot
++ echo "delvm snap1"
++ echo 'qemu-io disk0 "read -P0x11 0 63k"'
++ echo 'qemu-io disk0 "read -P0x33 63k 2k"'
++ echo 'qemu-io disk0 "read -P0x11 65k 63k"'
++
++ echo "quit"
++} | _qemu
++
++
++echo
++$QEMU_IMG snapshot -l "$TEST_IMG" | _filter_date | _filter_vmstate_size
++_check_test_img
++
++echo
++echo "=== Error cases ==="
++echo
++
++# snap1 should not exist any more
++_qemu -loadvm snap1
++
++echo
++{
++ echo "loadvm snap1"
++ echo "quit"
++} | _qemu
++
++# Snapshot operations and inactive images are incompatible
++echo
++_qemu -loadvm snap0 -incoming defer
++{
++ echo "loadvm snap0"
++ echo "delvm snap0"
++ echo "savevm snap1"
++ echo "quit"
++} | _qemu -incoming defer
++
++# -loadvm and -preconfig are incompatible
++echo
++_qemu -loadvm snap0 -preconfig
++
++# success, all done
++echo "*** done"
++rm -f $seq.full
++status=0
+diff --git a/tests/qemu-iotests/tests/qcow2-internal-snapshots.out b/tests/qemu-iotests/tests/qcow2-internal-snapshots.out
+new file mode 100644
+index 0000000000..438f535e6a
+--- /dev/null
++++ b/tests/qemu-iotests/tests/qcow2-internal-snapshots.out
+@@ -0,0 +1,107 @@
++QA output created by qcow2-internal-snapshots
++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
++
++=== Write some data, take a snapshot and overwrite part of it ===
++
++QEMU X.Y.Z monitor - type 'help' for more information
++(qemu) qemu-io disk0 "write -P0x11 0 1M"
++wrote 1048576/1048576 bytes at offset 0
++1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
++(qemu) savevm snap0
++(qemu) qemu-io disk0 "write -P0x22 0 512k"
++wrote 524288/524288 bytes at offset 0
++512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
++(qemu) quit
++
++Snapshot list:
++ID TAG VM SIZE DATE VM CLOCK ICOUNT
++1 snap0 SIZE yyyy-mm-dd hh:mm:ss 00:00:00.000
++No errors were found on the image.
++
++=== Verify that loading the snapshot reverts to the old content ===
++
++QEMU X.Y.Z monitor - type 'help' for more information
++(qemu) qemu-io disk0 "read -P0x11 0 1M"
++read 1048576/1048576 bytes at offset 0
++1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
++(qemu) qemu-io disk0 "write -P0x33 512k 512k"
++wrote 524288/524288 bytes at offset 524288
++512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
++(qemu) loadvm snap0
++(qemu) qemu-io disk0 "read -P0x11 0 1M"
++read 1048576/1048576 bytes at offset 0
++1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
++(qemu) qemu-io disk0 "write -P0x33 63k 2k"
++wrote 2048/2048 bytes at offset 64512
++2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
++(qemu) qemu-io disk0 "read -P0x11 0 63k"
++read 64512/64512 bytes at offset 0
++63 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
++(qemu) qemu-io disk0 "read -P0x33 63k 2k"
++read 2048/2048 bytes at offset 64512
++2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
++(qemu) qemu-io disk0 "read -P0x11 65k 63k"
++read 64512/64512 bytes at offset 66560
++63 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
++(qemu) savevm snap1
++(qemu) quit
++
++Snapshot list:
++ID TAG VM SIZE DATE VM CLOCK ICOUNT
++1 snap0 SIZE yyyy-mm-dd hh:mm:ss 00:00:00.000
++2 snap1 SIZE yyyy-mm-dd hh:mm:ss 00:00:00.000
++No errors were found on the image.
++
++=== qemu-img snapshot can revert to snapshots ===
++
++read 1048576/1048576 bytes at offset 0
++1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
++read 64512/64512 bytes at offset 0
++63 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
++read 2048/2048 bytes at offset 64512
++2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
++read 64512/64512 bytes at offset 66560
++63 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
++
++=== Deleting snapshots ===
++
++QEMU X.Y.Z monitor - type 'help' for more information
++(qemu) delvm snap1
++(qemu) qemu-io disk0 "read -P0x11 0 63k"
++read 64512/64512 bytes at offset 0
++63 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
++(qemu) qemu-io disk0 "read -P0x33 63k 2k"
++read 2048/2048 bytes at offset 64512
++2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
++(qemu) qemu-io disk0 "read -P0x11 65k 63k"
++read 64512/64512 bytes at offset 66560
++63 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
++(qemu) quit
++
++Snapshot list:
++ID TAG VM SIZE DATE VM CLOCK ICOUNT
++1 snap0 SIZE yyyy-mm-dd hh:mm:ss 00:00:00.000
++No errors were found on the image.
++
++=== Error cases ===
++
++QEMU X.Y.Z monitor - type 'help' for more information
++(qemu) QEMU_PROG: Snapshot 'snap1' does not exist in one or more devices
++
++QEMU X.Y.Z monitor - type 'help' for more information
++(qemu) loadvm snap1
++Error: Snapshot 'snap1' does not exist in one or more devices
++(qemu) quit
++
++QEMU_PROG: 'incoming' and 'loadvm' options are mutually exclusive
++QEMU X.Y.Z monitor - type 'help' for more information
++(qemu) loadvm snap0
++Error: Device 'disk0' is writable but does not support snapshots
++(qemu) delvm snap0
++Error: Device 'disk0' is writable but does not support snapshots
++(qemu) savevm snap1
++Error: Device 'disk0' is writable but does not support snapshots
++(qemu) quit
++
++QEMU_PROG: 'preconfig' and 'loadvm' options are mutually exclusive
++*** done
+diff --git a/tests/qemu-iotests/tests/qsd-jobs.out b/tests/qemu-iotests/tests/qsd-jobs.out
+index c1bc9b8356..aa6b6d1aef 100644
+--- a/tests/qemu-iotests/tests/qsd-jobs.out
++++ b/tests/qemu-iotests/tests/qsd-jobs.out
+@@ -7,8 +7,8 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/
+ QMP_VERSION
+ {"return": {}}
+ {"return": {}}
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}}
++{"return": {}}
+
+ === Streaming can't get permission on base node ===
+
+@@ -17,6 +17,6 @@ QMP_VERSION
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job0"}}
+ {"error": {"class": "GenericError", "desc": "Permission conflict on node 'fmt_base': permissions 'write' are both required by an unnamed block device (uses node 'fmt_base' as 'root' child) and unshared by stream job 'job0' (uses node 'fmt_base' as 'intermediate node' child)."}}
+-{"return": {}}
+ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "export1"}}
++{"return": {}}
+ *** done
+diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
+index c07a5b1a5f..c00b92b89a 100644
+--- a/tests/qtest/meson.build
++++ b/tests/qtest/meson.build
+@@ -6,6 +6,7 @@ endif
+
+ slow_qtests = {
+ 'ahci-test' : 60,
++ 'aspeed_smc-test': 360,
+ 'bios-tables-test' : 120,
+ 'boot-serial-test' : 60,
+ 'migration-test' : 150,
diff --git a/debian/qemu-block-extra.install b/debian/qemu-block-extra.install
new file mode 100644
index 00000000..ee45ae26
--- /dev/null
+++ b/debian/qemu-block-extra.install
@@ -0,0 +1 @@
+usr/lib/*/qemu/block-*.so
diff --git a/debian/qemu-debootstrap b/debian/qemu-debootstrap
new file mode 100755
index 00000000..399e736c
--- /dev/null
+++ b/debian/qemu-debootstrap
@@ -0,0 +1,15 @@
+#!/bin/sh
+# it was qemu-debootstrap - setup qemu syscall emulation in a debootstrap chroot
+# since kernel binfmt-misc support F flag for the interpreter and we use it,
+# there is no need to copy qemu-user binfmt interpreter binary to the chroot,
+# so regular debootstrap can be used just fine without --foreign, since all
+# commands inside the chroot will just run using qemu from binfmt-misc subsystem.
+
+if ! command -v debootstrap >/dev/null; then
+ echo "E: debootstrap isn't found in \$PATH, is debootstrap package installed?" >&2
+ exit 1
+fi
+
+echo "W: qemu-debootstrap is deprecated. Please use regular debootstrap directly" >&2
+echo "I: Running command: debootstrap $*" >&2
+exec debootstrap "$@"
diff --git a/debian/qemu-debootstrap.1 b/debian/qemu-debootstrap.1
new file mode 100644
index 00000000..8e76a1b4
--- /dev/null
+++ b/debian/qemu-debootstrap.1
@@ -0,0 +1,19 @@
+.TH qemu\-debootstrap 1 2011-07-02 "0.14.1+dfsg" Debian
+.SH NAME
+qemu\-debootstrap \- QEMU debootstrap wrapper
+.SH SYNOPSIS
+.B qemu\-debootstrap
+.RI [ options ]
+.SH DESCRIPTION
+The
+.B qemu\-debootstrap
+wrapper calls
+.BR debootstrap (8)
+making use of the \-\-foreign and \-\-second-stage options, and copies the appropriate
+.BR qemu\-user\-static (1)
+binary into place in order to install cross-architecture chroots. In order for it to work seamlessly, the binfmt-support package must be installed.
+.SH SEE ALSO
+.BR debootstrap (8),
+.BR qemu\-user\-static (1).
+.SH AUTHOR
+This manual page was written by Vagrant Cascadian <vagrant@debian.org>.
diff --git a/debian/qemu-guest-agent.dirs b/debian/qemu-guest-agent.dirs
new file mode 100644
index 00000000..47e91b18
--- /dev/null
+++ b/debian/qemu-guest-agent.dirs
@@ -0,0 +1 @@
+/etc/qemu/fsfreeze-hook.d
diff --git a/debian/qemu-guest-agent.init b/debian/qemu-guest-agent.init
new file mode 100644
index 00000000..e1424780
--- /dev/null
+++ b/debian/qemu-guest-agent.init
@@ -0,0 +1,131 @@
+#! /bin/sh
+### BEGIN INIT INFO
+# Provides: qemu-guest-agent
+# Required-Start: $remote_fs $syslog
+# Required-Stop: $remote_fs $syslog
+# Default-Start: 2 3 4 5
+# Default-Stop: 0 1 6
+# Short-Description: QEMU Guest Agent startup script
+# Description: Start the QEMU Guest Agent if we're running
+# in a QEMU virtual machine
+### END INIT INFO
+
+# Author: Michael Tokarev <mjt@tls.msk.ru>
+
+PATH=/sbin:/usr/sbin:/bin:/usr/bin
+DESC="QEMU Guest Agent"
+NAME=qemu-ga
+DAEMON=/usr/sbin/$NAME
+PIDFILE=/var/run/$NAME.pid
+
+# config
+DAEMON_ARGS=""
+# default transport
+TRANSPORT=virtio-serial:/dev/virtio-ports/org.qemu.guest_agent.0
+
+# Exit if the package is not installed
+[ -x "$DAEMON" ] || exit 0
+
+# Read configuration variable file if it is present
+[ -r /etc/default/qemu-guest-agent ] && . /etc/default/qemu-guest-agent
+
+# Load the VERBOSE setting and other rcS variables
+. /lib/init/vars.sh
+
+# Define LSB log_* functions.
+# Depend on lsb-base (>= 3.2-14) to ensure that this file is present
+# and status_of_proc is working.
+. /lib/lsb/init-functions
+
+#
+# Function that checks whenever system has necessary environment
+# It also splits $TRANSPORT into $method and $path
+#
+do_check_transport() {
+ method=${TRANSPORT%%:*}; path=${TRANSPORT#*:}
+ case "$method" in
+ virtio-serial | isa-serial)
+ if [ ! -e "$path" ]; then
+ log_warning_msg "$NAME: transport endpoint not found, not starting"
+ return 1
+ fi
+ ;;
+ esac
+}
+
+#
+# Function that starts the daemon/service
+#
+do_start()
+{
+ # Return
+ # 0 if daemon has been started
+ # 1 if daemon was already running
+ # 2 if daemon could not be started
+ start-stop-daemon -Sq -p $PIDFILE -x $DAEMON --test > /dev/null \
+ || return 1
+ start-stop-daemon -Sq -p $PIDFILE -x $DAEMON -- --daemonize \
+ $DAEMON_ARGS -m "$method" -p "$path" \
+ || return 2
+}
+
+#
+# Function that stops the daemon/service
+#
+do_stop()
+{
+ # Return
+ # 0 if daemon has been stopped
+ # 1 if daemon was already stopped
+ # 2 if daemon could not be stopped
+ # other if a failure occurred
+ start-stop-daemon -Kq --retry=TERM/30/KILL/5 -p $PIDFILE --name $NAME
+}
+
+case "$1" in
+ start)
+ do_check_transport || exit 0
+ [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" $NAME
+ do_start
+ case "$?" in
+ 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
+ 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
+ esac
+ ;;
+ stop)
+ [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" $NAME
+ do_stop
+ case "$?" in
+ 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
+ 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
+ esac
+ ;;
+ status)
+ status_of_proc "$DAEMON" $NAME && exit 0 || exit $?
+ ;;
+ restart|force-reload) # we do not support reload
+ do_check_transport || exit 0
+ log_daemon_msg "Restarting $DESC" $NAME
+ do_stop
+ case "$?" in
+ 0|1)
+ do_start
+ case "$?" in
+ 0) log_end_msg 0 ;;
+ 1) log_end_msg 1 ;; # Old process is still running
+ *) log_end_msg 1 ;; # Failed to start
+ esac
+ ;;
+ *)
+ # Failed to stop
+ log_end_msg 1
+ ;;
+ esac
+ ;;
+ *)
+ echo "Usage: /etc/init.d/qemu-guest-agent {start|stop|status|restart|force-reload}" >&2
+ exit 3
+ ;;
+esac
+
+:
diff --git a/debian/qemu-guest-agent.install b/debian/qemu-guest-agent.install
new file mode 100644
index 00000000..69f703d8
--- /dev/null
+++ b/debian/qemu-guest-agent.install
@@ -0,0 +1,5 @@
+debian/tmp/usr/bin/qemu-ga /usr/sbin
+debian/tmp/usr/share/man/man8/qemu-ga.8 /usr/share/man/man8
+debian/tmp/usr/share/man/man7/qemu-ga-ref.7 /usr/share/man/man7
+qga/qapi-schema.json /usr/share/doc/qemu-guest-agent
+scripts/qemu-guest-agent/fsfreeze-hook /etc/qemu/
diff --git a/debian/qemu-guest-agent.postinst b/debian/qemu-guest-agent.postinst
new file mode 100644
index 00000000..e479a0d2
--- /dev/null
+++ b/debian/qemu-guest-agent.postinst
@@ -0,0 +1,59 @@
+#!/bin/sh
+# postinst script for qemu-guest-agent
+#
+# see: dh_installdeb(1)
+
+set -e
+
+# summary of how this script can be called:
+# * <postinst> `configure' <most-recently-configured-version>
+# * <old-postinst> `abort-upgrade' <new version>
+# * <conflictor's-postinst> `abort-remove' `in-favour' <package>
+# <new-version>
+# * <postinst> `abort-remove'
+# * <deconfigured's-postinst> `abort-deconfigure' `in-favour'
+# <failed-install-package> <version> `removing'
+# <conflicting-package> <version>
+# for details, see https://www.debian.org/doc/debian-policy/ or
+# the debian-policy package
+
+
+case "$1" in
+ configure)
+ ;;
+
+ abort-upgrade|abort-remove|abort-deconfigure)
+ ;;
+
+ *)
+ echo "postinst called with unknown argument \`$1'" >&2
+ exit 1
+ ;;
+esac
+
+# dh_installdeb will replace this with shell code automatically
+# generated by other debhelper scripts.
+
+#DEBHELPER#
+
+# Normal mv_conffile alone would fail due to the new path being a DIR in the old package version (LP: 1820291)
+case "$1" in
+ configure)
+ # From /usr/bin/dpkg-maintscript-helper modified to be able to cope with this edge case
+ if [ -n "$2" ] && dpkg --compare-versions -- "$2" le-nl "1:3.1+dfsg-7~"; then
+ TMPCONFFILE="/etc/qemu/fsfreeze-hook.old"
+ NEWCONFFILE="/etc/qemu/fsfreeze-hook"
+ ORIGCONFFILE="/etc/qemu/fsfreeze-hook/fsfreeze-hook"
+ rm -f "$TMPCONFFILE.dpkg-remove"
+ if [ -e "$TMPCONFFILE" ]; then
+ echo "Preserving user changes to $NEWCONFFILE (renamed from $ORIGCONFFILE)..."
+ if [ -e "$NEWCONFFILE" ]; then
+ mv -f "$NEWCONFFILE" "$NEWCONFFILE.dpkg-new"
+ fi
+ mv -f "$TMPCONFFILE" "$NEWCONFFILE"
+ fi
+ fi
+ ;;
+esac
+
+exit 0
diff --git a/debian/qemu-guest-agent.postrm b/debian/qemu-guest-agent.postrm
new file mode 100644
index 00000000..525e3cbf
--- /dev/null
+++ b/debian/qemu-guest-agent.postrm
@@ -0,0 +1,56 @@
+#!/bin/sh
+# postrm script for qemu-guest-agent
+#
+# see: dh_installdeb(1)
+
+set -e
+
+# summary of how this script can be called:
+# * <postrm> `remove'
+# * <postrm> `purge'
+# * <old-postrm> `upgrade' <new-version>
+# * <new-postrm> `failed-upgrade' <old-version>
+# * <new-postrm> `abort-install'
+# * <new-postrm> `abort-install' <old-version>
+# * <new-postrm> `abort-upgrade' <old-version>
+# * <disappearer's-postrm> `disappear' <overwriter>
+# <overwriter-version>
+# for details, see https://www.debian.org/doc/debian-policy/ or
+# the debian-policy package
+
+
+case "$1" in
+ purge|remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear)
+ ;;
+
+ *)
+ echo "postrm called with unknown argument \`$1'" >&2
+ exit 1
+ ;;
+esac
+
+# dh_installdeb will replace this with shell code automatically
+# generated by other debhelper scripts.
+
+#DEBHELPER#
+
+# If needed revert the move we have made in preinst to compensate the new path being a DIR in the old package version (LP: 1820291)
+case "$1" in
+ abort-install|abort-upgrade)
+ # From /usr/bin/dpkg-maintscript-helper modified to be able to cope with this edge case
+ if [ -n "$2" ] && dpkg --compare-versions -- "$2" le-nl "1:3.1+dfsg-7~"; then
+ TMPCONFFILE="/etc/qemu/fsfreeze-hook.old"
+ NEWCONFFILE="/etc/qemu/fsfreeze-hook"
+ ORIGCONFFILE="/etc/qemu/fsfreeze-hook/fsfreeze-hook"
+ if [ -e "$TMPCONFFILE.dpkg-remove" ]; then
+ echo "Reinstalling $ORIGCONFFILE that was moved away"
+ if [ -f "$NEWCONFFILE" ]; then
+ rm -f "$NEWCONFFILE"
+ fi
+ mkdir -p "$NEWCONFFILE"
+ mv "$TMPCONFFILE.dpkg-remove" "$ORIGCONFFILE"
+ fi
+ fi
+esac
+
+exit 0
diff --git a/debian/qemu-guest-agent.preinst b/debian/qemu-guest-agent.preinst
new file mode 100644
index 00000000..f5b4cc7d
--- /dev/null
+++ b/debian/qemu-guest-agent.preinst
@@ -0,0 +1,62 @@
+#!/bin/sh
+# preinst script for qemu-guest-agent
+#
+# see: dh_installdeb(1)
+
+set -e
+
+# summary of how this script can be called:
+# * <new-preinst> `install'
+# * <new-preinst> `install' <old-version>
+# * <new-preinst> `upgrade' <old-version>
+# * <old-preinst> `abort-upgrade' <new-version>
+# for details, see https://www.debian.org/doc/debian-policy/ or
+# the debian-policy package
+
+
+case "$1" in
+ install|upgrade)
+ ;;
+
+ abort-upgrade)
+ ;;
+
+ *)
+ echo "preinst called with unknown argument \`$1'" >&2
+ exit 1
+ ;;
+esac
+
+# dh_installdeb will replace this with shell code automatically
+# generated by other debhelper scripts.
+
+# Normal mv_conffile alone would fail due to the new path being a DIR in the old package version (LP: 1820291)
+case "$1" in
+ install|upgrade)
+ # From /usr/bin/dpkg-maintscript-helper modified to be able to cope with this edge case
+ if [ -n "$2" ] && dpkg --compare-versions -- "$2" le-nl "1:3.1+dfsg-7~"; then
+ TMPCONFFILE="/etc/qemu/fsfreeze-hook.old"
+ NEWCONFFILE="/etc/qemu/fsfreeze-hook"
+ ORIGCONFFILE="/etc/qemu/fsfreeze-hook/fsfreeze-hook"
+ if [ -f "$ORIGCONFFILE" ]; then
+ disk_md5sum="$(md5sum "$ORIGCONFFILE" | sed -e 's/ .*//')"
+ pkg_md5sum="$(dpkg-query -W -f='${Conffiles}' "qemu-guest-agent" | \
+ sed -n -e "\'^ $ORIGCONFFILE ' { s/ obsolete$//; s/.* //; p }")"
+ if [ "$disk_md5sum" = "$pkg_md5sum" ]; then
+ # mark as having no custom content
+ mv -f "$ORIGCONFFILE" "${TMPCONFFILE}.dpkg-remove"
+ else
+ # keep the "old" name to reflect there is content to be preserved
+ mv -f "$ORIGCONFFILE" "$TMPCONFFILE"
+ fi
+ # In any case the old directory blocking the new conffile
+ # has to be removed before unpack happens
+ rmdir "$NEWCONFFILE" || echo "failed to remove $NEWCONFFILE"
+ fi
+ fi
+ ;;
+esac
+
+#DEBHELPER#
+
+exit 0
diff --git a/debian/qemu-guest-agent.service b/debian/qemu-guest-agent.service
new file mode 100644
index 00000000..88ef9c7e
--- /dev/null
+++ b/debian/qemu-guest-agent.service
@@ -0,0 +1,11 @@
+[Unit]
+Description=QEMU Guest Agent
+BindsTo=dev-virtio\x2dports-org.qemu.guest_agent.0.device
+After=dev-virtio\x2dports-org.qemu.guest_agent.0.device
+
+[Service]
+ExecStart=-/usr/sbin/qemu-ga
+Restart=always
+RestartSec=0
+
+[Install]
diff --git a/debian/qemu-guest-agent.udev b/debian/qemu-guest-agent.udev
new file mode 100644
index 00000000..47097057
--- /dev/null
+++ b/debian/qemu-guest-agent.udev
@@ -0,0 +1,2 @@
+SUBSYSTEM=="virtio-ports", ATTR{name}=="org.qemu.guest_agent.0", \
+ TAG+="systemd", ENV{SYSTEMD_WANTS}="qemu-guest-agent.service"
diff --git a/debian/qemu-ifdown b/debian/qemu-ifdown
new file mode 100755
index 00000000..b2dc471f
--- /dev/null
+++ b/debian/qemu-ifdown
@@ -0,0 +1,6 @@
+#! /bin/sh
+# Script to shut down a network (tap) device for qemu.
+# Initially this script is empty, but you can configure,
+# for example, accounting info here.
+
+:
diff --git a/debian/qemu-ifup.kfreebsd b/debian/qemu-ifup.kfreebsd
new file mode 100755
index 00000000..b7335b08
--- /dev/null
+++ b/debian/qemu-ifup.kfreebsd
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+/sbin/ifconfig $1 172.20.0.1
diff --git a/debian/qemu-ifup.linux b/debian/qemu-ifup.linux
new file mode 100755
index 00000000..76b68ea5
--- /dev/null
+++ b/debian/qemu-ifup.linux
@@ -0,0 +1,41 @@
+#! /bin/sh
+# Script to bring a network (tap) device for qemu up.
+# The idea is to add the tap device to the same bridge
+# as we have default routing to.
+
+# in order to be able to find brctl
+PATH=$PATH:/sbin:/usr/sbin
+ip=$(command -v ip)
+
+if [ -n "$ip" ]; then
+ ip link set "$1" up
+else
+ brctl=$(command -v brctl)
+ if [ -z "$ip$brctl" ]; then
+ echo "W: $0: not doing any bridge processing: neither ip nor brctl utility not found" >&2
+ exit 0
+ fi
+ ifconfig "$1" 0.0.0.0 up
+fi
+
+switch=$(ip route ls | \
+ awk '/^default / {
+ for(i=0;i<NF;i++) { if ($i == "dev") { print $(i+1); next; } }
+ }'
+ )
+
+# only add the interface to default-route bridge if we
+# have such interface (with default route) and if that
+# interface is actually a bridge.
+# It is possible to have several default routes too
+for br in $switch; do
+ if [ -d /sys/class/net/$br/bridge/. ]; then
+ if [ -n "$ip" ]; then
+ exec ip link set "$1" master "$br"
+ else
+ exec brctl addif $br "$1"
+ fi
+ fi
+done
+
+echo "W: $0: no bridge for guest interface found" >&2
diff --git a/debian/qemu-io.1 b/debian/qemu-io.1
new file mode 100644
index 00000000..cabd24e3
--- /dev/null
+++ b/debian/qemu-io.1
@@ -0,0 +1,43 @@
+.TH QEMU-IO 1 "December 18, 2011"
+.SH NAME
+qemu-io \- QEMU Disk exerciser
+.SH SYNOPSIS
+.B qemu-io [-h] [-V] [-rsnm] [-c cmd] ... [file]
+.SH DESCRIPTION
+qemu-io is a command line utility to exercise the QEMU I/O path.
+.SH OPTIONS
+.TP
+.B \-c,\ \-\-cmd\ <cmd>
+Command to execute
+.TP
+.B \-r,\ \-\-read-only
+Export read-only
+.TP
+.B \-s,\ \-\-snapshot
+Use snapshot file
+.TP
+.B \-n,\ \-\-nocache
+Disable host cache
+.TP
+.B \-g,\ \-\-growable
+Allow file to grow (only applies to protocols)
+.TP
+.B \-m,\ \-\-misalign
+Misalign allocations for O_DIRECT
+.TP
+.B \-k,\ \-\-native-aio
+Use kernel AIO implementation (on Linux only)
+.TP
+.B \-h,\ \-\-help
+Display help and exit
+.TP
+.B \-V,\ \-\-version
+Output version information and exit
+.SH SEE ALSO
+.BR qemu-img (1),
+.BR qemu-nbd (8)
+.SH AUTHOR
+QEMU project
+.PP
+This manual page was written by Asias He <asias.hejun@gmail.com>, for the Debian project (and may be used by others). Permission is granted to copy, distribute and/or modify this document under the terms of the Creative Commons Attribution-Share Alike 3.0 United States License. (See http://creativecommons.org/licenses/by-sa/3.0/us/legalcode)
+.
diff --git a/debian/qemu-system-common.NEWS b/debian/qemu-system-common.NEWS
new file mode 100644
index 00000000..474fe2ff
--- /dev/null
+++ b/debian/qemu-system-common.NEWS
@@ -0,0 +1,46 @@
+qemu (1:2.12+dfsg-2) unstable; urgency=medium
+
+ Since qemu 2.12, [G]UI display frontends can be built as modules.
+ Debian creates new package, qemu-system-gui, which currently
+ includes GTK3 support. This also switches display from SDL to GTK.
+ Qemu-system-* packages recommends installing qemu-system-gui, so
+ by default on upgrade you will have new package installed, and
+ local GUI will continue to work. However, if you choose to not
+ install recommended packages, you might consider installing
+ qemu-system-gui package separately, if you need local GUI support
+ as well. Without this package, qemu-system-* becomes "headless",
+ and can be used on servers to reduce amount of dependencies -
+ this way, no X11 stuff is needed by qemu-system anymore.
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Sun, 27 Apr 2018 09:18:32 +0300
+
+qemu (1:2.2+dfsg-6exp) unstable; urgency=medium
+
+ Since Debian release 2.2+dfsg-6exp, a new package named qemu-block-extra
+ has been created and some less frequently used block backends has been
+ split out of main qemu-system binaries and from qemu-img binary to
+ this new package. The backends which has been split are:
+ curl
+ iscsi
+ rbd (ceph/rados)
+ ssh
+ If you use any of these, please install qemu-block-extra package in
+ addition to qemu-system-* or qemu-utils package, because without it
+ these block backends won't work anymore.
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Mon, 27 Apr 2015 09:29:55 +0300
+
+qemu (2.0.0+dfsg-1) unstable; urgency=low
+
+ qemu-system-* packages does not provide /usr/bin/qemu alternative
+ anymore, and all various alternatives will be unregistered at new
+ individual qemu-system packages install. This is because different
+ architectures are not really alternatives, and never has been.
+ Historically, qemu emulated just one architecture, so the name "qemu"
+ was used for the binary. However when more architectures were added,
+ the old name "qemu" was used as an alternative, pointing to one of
+ the emulators. Upstream does not use the name "qemu" for binaries
+ for a long time. If you have scripts using the old name "qemu"
+ please update them to use the right qemu-system-* binary.
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Fri, 11 Apr 2014 19:57:22 +0400
diff --git a/debian/qemu-system-common.doc-base b/debian/qemu-system-common.doc-base
new file mode 100644
index 00000000..76cd04b3
--- /dev/null
+++ b/debian/qemu-system-common.doc-base
@@ -0,0 +1,12 @@
+Document: qemu-system-doc
+Title: QEMU User Manual
+Author: Fabrice Bellard
+Abstract: The QEMU user manual intends to make the user understand what
+ qemu is/does, and to guide them through the first steps of getting
+ the emulator to work, documenting parameters and commands, among other
+ useful things.
+Section: Emulators
+
+Format: HTML
+Index: /usr/share/doc/qemu-system-common/system/index.html
+Files: /usr/share/doc/qemu-system-common/system/index.html
diff --git a/debian/qemu-system-common.install b/debian/qemu-system-common.install
new file mode 100644
index 00000000..47ed9d9c
--- /dev/null
+++ b/debian/qemu-system-common.install
@@ -0,0 +1,18 @@
+debian/qemu-ifdown etc/
+debian/tmp/usr/share/man/man1/qemu-system.1
+debian/tmp/usr/share/qemu/trace-events-all
+debian/tmp/usr/bin/qemu-pr-helper
+debian/tmp/usr/share/man/man8/qemu-pr-helper.8
+debian/tmp/usr/share/man/man7/qemu-qmp-ref.7
+debian/tmp/usr/share/man/man7/qemu-block-drivers.7
+debian/tmp/usr/share/man/man7/qemu-cpu-models.7
+debian/tmp/usr/share/doc/qemu/system usr/share/doc/qemu-system-common
+debian/tmp/usr/bin/qemu-storage-daemon
+debian/tmp/usr/share/man/man1/qemu-storage-daemon.1
+debian/tmp/usr/share/man/man7/qemu-storage-daemon-qmp-ref.7
+# common modules. gui modules has been moved into place in d/rules.
+debian/tmp/usr/lib/*/qemu/accel-tcg-*.so
+debian/tmp/usr/lib/*/qemu/audio-*.so
+debian/tmp/usr/lib/*/qemu/chardev-*.so
+debian/tmp/usr/lib/*/qemu/hw-*.so
+debian/tmp/usr/lib/*/qemu/ui-*.so
diff --git a/debian/qemu-system-common.lintian-overrides b/debian/qemu-system-common.lintian-overrides
new file mode 100644
index 00000000..1e31856b
--- /dev/null
+++ b/debian/qemu-system-common.lintian-overrides
@@ -0,0 +1,5 @@
+# probably a false positive
+qemu-system-common: shared-library-lacks-prerequisites [usr/lib/*/qemu/*.so]
+qemu-system-common: spare-manual-page [usr/share/man/man1/qemu-system.1.gz]
+qemu-system-common: spare-manual-page [usr/share/man/man1/virtfs-proxy-helper.1.gz]
+qemu-system-common: spare-manual-page [usr/share/man/man1/virtiofsd.1.gz]
diff --git a/debian/qemu-system-data.docs b/debian/qemu-system-data.docs
new file mode 100644
index 00000000..3c68b468
--- /dev/null
+++ b/debian/qemu-system-data.docs
@@ -0,0 +1,5 @@
+docs/multiseat.txt
+docs/qdev-device-use.txt
+docs/qemupciserial.inf
+docs/config/
+docs/specs/
diff --git a/debian/qemu-system-data.lintian-overrides b/debian/qemu-system-data.lintian-overrides
new file mode 100644
index 00000000..d1be0c48
--- /dev/null
+++ b/debian/qemu-system-data.lintian-overrides
@@ -0,0 +1,5 @@
+# firmware files are arch-dependent binaries and can be statically linked
+qemu-system-data: arch-dependent-file-in-usr-share *usr/share/qemu/*
+qemu-system-data: arch-independent-package-contains-binary-or-object *usr/share/qemu/*
+qemu-system-data: statically-linked-binary *usr/share/qemu/*
+qemu-system-data: shared-library-lacks-prerequisites *usr/share/qemu/s390-*
diff --git a/debian/qemu-system-gui.install b/debian/qemu-system-gui.install
new file mode 100644
index 00000000..5d84e30a
--- /dev/null
+++ b/debian/qemu-system-gui.install
@@ -0,0 +1,3 @@
+usr/share/locale/*/LC_MESSAGES/qemu.mo
+debian/tmp/usr/share/qemu/vhost-user/50-qemu-gpu.json
+debian/tmp/usr/lib/qemu/vhost-user-gpu
diff --git a/debian/qemu-system-i386.xen-wrapper b/debian/qemu-system-i386.xen-wrapper
new file mode 100755
index 00000000..c9484938
--- /dev/null
+++ b/debian/qemu-system-i386.xen-wrapper
@@ -0,0 +1,29 @@
+#! /bin/sh
+# This is a temporarily wrapper for qemu-system-i386 to redirect xen-specific
+# invocations of qemu-system-i386 into xen-specific package if installed.
+#
+xenredir=/usr/libexec/xen-qemu-system-i386
+exe=/usr/libexec/qemu-system-i386
+
+for opt in "$@"; do
+ case "$opt" in
+ -xen-* | --xen-*)
+ if [ -x $xenredir ]; then
+ exe=$xenredir
+ cat <<EOF >&2
+W: $0 binary is not compiled with xen support anymore
+W: redirecting the call to $exe
+W: please update your configs
+EOF
+ else
+ cat <<EOF >&2
+E: $0 binary is not compiled with xen support anymore
+E: please install qemu-system-xen package and update your configs
+EOF
+ fi
+ break
+ ;;
+ esac
+done
+
+exec "$exe" "$@"
diff --git a/debian/qemu-system-misc.install b/debian/qemu-system-misc.install
new file mode 100644
index 00000000..abefed90
--- /dev/null
+++ b/debian/qemu-system-misc.install
@@ -0,0 +1,2 @@
+# microblaze firmware
+pc-bios/petalogix-*.dtb /usr/share/qemu/
diff --git a/debian/qemu-system-misc.lintian-overrides b/debian/qemu-system-misc.lintian-overrides
new file mode 100644
index 00000000..ec61d802
--- /dev/null
+++ b/debian/qemu-system-misc.lintian-overrides
@@ -0,0 +1,2 @@
+qemu-system-misc: spelling-error-in-binary addd add *usr/bin/qemu-*
+qemu-system-misc: spelling-error-in-binary nott not *usr/bin/qemu-*
diff --git a/debian/qemu-system-ppc.README.Debian b/debian/qemu-system-ppc.README.Debian
new file mode 100644
index 00000000..9fb5c5a2
--- /dev/null
+++ b/debian/qemu-system-ppc.README.Debian
@@ -0,0 +1,13 @@
+qemu-system for Debian
+----------------------
+
+The qemu-system-ppc package does not include the video.x file, which is
+needed by qemu-system-ppc for some systems. The file is available from
+the mac-on-linux project, and the sources are available on:
+ http://mac-on-linux.svn.sourceforge.net/viewvc/mac-on-linux/mac-drivers/video_driver/Makefile?revision=HEAD&view=markup
+
+They are not buildable on a Debian system though, hence video.x is not
+present in the package. The qemu-system-ppc binary is still useful for
+emulating a PReP platform, which does not need video.x.
+
+ -- Aurelien Jarno <aurel32@debian.org> Sun, 16 Mar 2008 19:17:39 +0100
diff --git a/debian/qemu-system-ppc.links b/debian/qemu-system-ppc.links
new file mode 100644
index 00000000..c2a5ee88
--- /dev/null
+++ b/debian/qemu-system-ppc.links
@@ -0,0 +1,2 @@
+usr/bin/qemu-system-ppc64 usr/bin/qemu-system-ppc64le
+usr/share/man/man1/qemu-system-ppc64.1 usr/share/man/man1/qemu-system-ppc64le.1
diff --git a/debian/qemu-system-ppc.lintian-overrides b/debian/qemu-system-ppc.lintian-overrides
new file mode 100644
index 00000000..b215e1b0
--- /dev/null
+++ b/debian/qemu-system-ppc.lintian-overrides
@@ -0,0 +1 @@
+qemu-system-ppc: spelling-error-in-binary buid build *usr/bin/qemu-system-ppc64*
diff --git a/debian/qemu-system-x86.NEWS b/debian/qemu-system-x86.NEWS
new file mode 100644
index 00000000..4efad6a5
--- /dev/null
+++ b/debian/qemu-system-x86.NEWS
@@ -0,0 +1,50 @@
+qemu (1:7.0+dfsg-7) unstable; urgency=medium
+
+ Starting with this version of qemu-system-x86 on x86 architecture, xen
+ support is moved out to a separate package named qemu-system-xen. Xen
+ release since 4.16.1-1 already uses qemu binary from this package. In
+ order to support transition from old xen and xen-supporting qemu-system-x86
+ to separate xen build of qemu, the qemu-system-i386 binary is temporarily
+ replaced by a shell wrapper which detects xen usage and if found, redirects
+ the call to xen-enabled qemu binary if found (with a warning), or suggests
+ to install qemu-system-xen package. If you used qemu-system-x86 (or
+ qemu-system-x86-xen on Ubuntu) to run xen, please install qemu-system-xen.
+ qemu-system-x86 is not used by xen anymore since 4.16.1-1.
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Sun, 15 May 2022 15:15:58 +0300
+
+qemu (1:5.0-9) unstable; urgency=medium
+
+ With this version, kvm wrapper (initially from the separate kvm
+ package, which were later renamed to qemu-kvm) is merged back
+ to qemu-system-x86 package, replacing old qemu-kvm package.
+ 'kvm' command name turned out to be very handy for manual
+ execution of qemu with kvm enabled, and we now rely on the
+ upstream behavor - when executable name ends with "kvm" it
+ enables the kvm mode by default if available, and falls back
+ to TCG if not.
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Fri, 17 Jul 2020 12:54:35 +0300
+
+qemu (1.7.0+dfsg-2) unstable; urgency=low
+
+ Since version 1.7.0+dfsg-2, qemu-system-x86 switched from vgabios for
+ plex/bochs project to implementation of vgabios provided by seabios.
+ The latter is written almost entirely in C language so it is much easier
+ to debugu/develop, but it lacks some 16bit protected mode functions which
+ are present in vgabios. This means that it is possible that, for eaxample,
+ some protected-mode games written for MS-DOS may not work since this
+ release.
+
+ This also means that vgabios package isn't used by qemu anymore, and might
+ be removed from the system if there are no other users of it left.
+
+
+ /usr/bin/kvm shell wrapper has been moved back to qemu-kvm package (it was
+ moved to qemu-system-x86 in version 1.3.0+dfsg-2exp). Please note that we
+ do not re-install qemu-kvm package if it has been removed as obsolete, so
+ if you need /usr/bin/kvm wrapper please install qemu-kvm package again.
+ This change allows qemu-system-x86 package to co-exist with the old qemu-kvm
+ binary (not shell-wrapper) package from wheezy.
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Thu, 28 Nov 2013 18:40:56 +0400
diff --git a/debian/qemu-system-x86_64-spice b/debian/qemu-system-x86_64-spice
new file mode 100755
index 00000000..a7bdb04e
--- /dev/null
+++ b/debian/qemu-system-x86_64-spice
@@ -0,0 +1,5 @@
+#! /bin/sh
+echo "$0: W: this is an old compat wrapper script for qemu-system-x86_64-spice" >&2
+echo "$0: W: please use qemu-system-x86_64 instead of $0" >&2
+
+exec qemu-system-x86_64 "$@"
diff --git a/debian/qemu-system.NEWS b/debian/qemu-system.NEWS
new file mode 100644
index 00000000..550670ba
--- /dev/null
+++ b/debian/qemu-system.NEWS
@@ -0,0 +1,47 @@
+qemu (1.3.0+dfsg-4exp) experimental; urgency=low
+
+ Starting from 1.3.0 release, qemu-system package, which provided
+ QEMU system emulation targets for many architectures, has been
+ split into several packages, each providing a related,
+ per-base-architecture, set of emulators, and qemu-system-misc
+ package which contains some "other" architectures. There are
+ also qemu-system-common package, which provides common files for
+ all other qemu-system-*, packages. Former qemu-system package
+ now become a meta-package which installs emulators for all
+ available targets as before.
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Tue, 22 Jan 2013 01:38:27 +0400
+
+qemu (0.12.3+dfsg-3) unstable; urgency=low
+
+ Starting with QEMU 0.12.0, KQEMU support has been removed from
+ upstream, as it has not seen active development for a few years now,
+ while causing regressions or limitations for non-KQEMU users.
+
+ -- Aurelien Jarno <aurel32@debian.org> Wed, 24 Mar 2010 23:14:35 +0100
+
+qemu (0.10.3-2) unstable; urgency=low
+
+ Starting with QEMU 0.10.0, it is possible to control how the host
+ cache is used to access block data, using the cache= suboption of the
+ -drive option. The following suboptions are available:
+ * none: The host page cache is entirely avoided.
+ * writeback (default in QEMU 0.9.x): Writeback caching reports data
+ writes as completed as soon as the data is present in the host page
+ cache. This is safe as long as you trust your host. If your host
+ crashes or loses power, then the guest may experience data
+ corruption.
+ * writethrough (default in QEMU 0.10.x): The host page cache is used
+ to read and write data but write notification is sent to the guest
+ only when the data has been reported as written by the storage
+ subsystem.
+
+ Note that depending on your configuration (filesystem, encryption,
+ kernel version, etc.), disk accesses can be very slow with the default
+ cache policy (writethrough). You can use the writeback cache policy
+ instead, but the data integrity is not assured anymore.
+
+ See qemu(1) for more details.
+
+ -- Aurelien Jarno <aurel32@debian.org> Sun, 03 May 2009 23:22:29 +0200
+
diff --git a/debian/qemu-user-static.1 b/debian/qemu-user-static.1
new file mode 100644
index 00000000..bac2d391
--- /dev/null
+++ b/debian/qemu-user-static.1
@@ -0,0 +1,37 @@
+.TH qemu\-user\-static 1 2007-02-08 "0.9.0" Debian
+.SH NAME
+qemu\-user\-static \- QEMU User Emulator (static version)
+.SH SYNOPSIS
+.B qemu\-user\-static
+.RI [ options ]
+.I program
+.RI [ program-arguments... ]
+.SH DESCRIPTION
+The
+.B qemu\-user\-static
+emulator can run binaries for other architectures but with the same operating
+system as the current one.
+.SH OPTIONS
+.TP
+.BR \-h
+Print this help.
+.TP
+.BR \-g " \fI<port>\fP"
+Wait gdb connection to port \fIport\fP.
+.TP
+.BR \-L " \fI<path>\fP"
+Set the elf interpreter prefix (default=\fI/etc/qemu\-binfmt/%M\fP).
+.TP
+.BR \-s " \fI<size>\fP"
+Set the stack size in bytes (default=\fI524288\fP).
+.TP
+.BR \-d " \fI<options>\fP"
+Activate log (logfile=\fI/tmp/qemu.log\fP)
+.TP
+.BR \-p " \fI<pagesize>\fP"
+Set the host page size to 'pagesize'.
+.SH SEE ALSO
+.BR qemu-system (1)
+(in qemu-system-common package).
+.SH AUTHOR
+This manual page was written by Guillem Jover <guillem@debian.org>.
diff --git a/debian/qemu-user-static.docs b/debian/qemu-user-static.docs
new file mode 100644
index 00000000..1c1b7d09
--- /dev/null
+++ b/debian/qemu-user-static.docs
@@ -0,0 +1 @@
+debian/tmp/usr/share/doc/qemu/user
diff --git a/debian/qemu-user-static.install b/debian/qemu-user-static.install
new file mode 100644
index 00000000..42e8bca7
--- /dev/null
+++ b/debian/qemu-user-static.install
@@ -0,0 +1,3 @@
+debian/qemu-user-static.1 usr/share/man/man1/
+debian/qemu-debootstrap usr/sbin
+debian/qemu-debootstrap.1 usr/share/man/man1/
diff --git a/debian/qemu-user-static.lintian-overrides b/debian/qemu-user-static.lintian-overrides
new file mode 100644
index 00000000..b9ed6553
--- /dev/null
+++ b/debian/qemu-user-static.lintian-overrides
@@ -0,0 +1,4 @@
+qemu-user-static: spelling-error-in-binary addd add *usr/bin/qemu-*-static*
+qemu-user-static: spelling-error-in-binary nott not *usr/bin/qemu-*-static*
+# these are static-pic executables, not shared executables:
+qemu-user-static: shared-library-lacks-prerequisites *usr/bin/qemu-*-static*
diff --git a/debian/qemu-user.docs b/debian/qemu-user.docs
new file mode 100644
index 00000000..1c1b7d09
--- /dev/null
+++ b/debian/qemu-user.docs
@@ -0,0 +1 @@
+debian/tmp/usr/share/doc/qemu/user
diff --git a/debian/qemu-user.install b/debian/qemu-user.install
new file mode 100644
index 00000000..2890ef27
--- /dev/null
+++ b/debian/qemu-user.install
@@ -0,0 +1 @@
+b/qemu-user.1 usr/share/man/man1/
diff --git a/debian/qemu-user.lintian-overrides b/debian/qemu-user.lintian-overrides
new file mode 100644
index 00000000..5ee86b85
--- /dev/null
+++ b/debian/qemu-user.lintian-overrides
@@ -0,0 +1,3 @@
+qemu-user: spelling-error-in-binary addd add *usr/bin/qemu-*
+qemu-user: spelling-error-in-binary nott not *usr/bin/qemu-*
+qemu-user: spare-manual-page [usr/share/man/man1/qemu-user.1.gz]
diff --git a/debian/qemu-utils.NEWS b/debian/qemu-utils.NEWS
new file mode 100644
index 00000000..406990ad
--- /dev/null
+++ b/debian/qemu-utils.NEWS
@@ -0,0 +1,15 @@
+qemu (1:2.2+dfsg-6exp) unstable; urgency=medium
+
+ Since Debian release 2.2+dfsg-6exp, a new package named qemu-block-extra
+ has been created and some less frequently used block backends has been
+ split out of main qemu-system binaries and from qemu-img binary to
+ this new package. The backends which has been split are:
+ curl
+ iscsi
+ rbd (ceph/rados)
+ ssh
+ If you use any of these, please install qemu-block-extra package in
+ addition to qemu-system-* or qemu-utils package, because without it
+ these block backends won't work anymore.
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Mon, 27 Apr 2015 09:29:55 +0300
diff --git a/debian/qemu-utils.install b/debian/qemu-utils.install
new file mode 100644
index 00000000..aabc5717
--- /dev/null
+++ b/debian/qemu-utils.install
@@ -0,0 +1,5 @@
+debian/tmp/usr/bin/qemu-img
+debian/tmp/usr/share/man/man1/qemu-img.1
+debian/tmp/usr/bin/qemu-nbd
+debian/tmp/usr/share/man/man8/qemu-nbd.8
+debian/tmp/usr/bin/qemu-io
diff --git a/debian/qemu-utils.manpages b/debian/qemu-utils.manpages
new file mode 100644
index 00000000..7cba2a0b
--- /dev/null
+++ b/debian/qemu-utils.manpages
@@ -0,0 +1 @@
+debian/qemu-io.1
diff --git a/debian/qemu.desktop b/debian/qemu.desktop
new file mode 100644
index 00000000..0203da13
--- /dev/null
+++ b/debian/qemu.desktop
@@ -0,0 +1,8 @@
+# Just for the icon under wayland.
+# qemu-system-foo sets application name to qemu
+[Desktop Entry]
+Name=qemu
+Comment=QEMU System Emulation
+Icon=qemu
+Type=Application
+NoDisplay=true
diff --git a/debian/rules b/debian/rules
new file mode 100755
index 00000000..dcc21904
--- /dev/null
+++ b/debian/rules
@@ -0,0 +1,653 @@
+#!/usr/bin/make -f
+SHELL = /bin/sh -e
+
+# in order to keep output non-intermixed together, disable parallel building
+# of different targets in this d/rules but allow running parallel submakes
+.NOTPARALLEL:
+
+# get DEB_VERSION
+include /usr/share/dpkg/pkg-info.mk
+# get CFLAGS LDFLAGS etc
+include /usr/share/dpkg/buildflags.mk
+# Fast version of dpkg/architecture.mk defining all vars in one go
+ifeq (${DEB_HOST_MULTIARCH},)
+ $(foreach d, $(shell dpkg-architecture | sed 's/=/?=/'), $(eval export $d))
+endif
+
+# Disable LTO on non-amd64 builds, see:
+# https://bugs.launchpad.net/ubuntu/+source/qemu/+bug/1921664
+# https://bugzilla.redhat.com/show_bug.cgi?id=1952483
+ifneq ($(DEB_HOST_ARCH),amd64)
+ export DEB_BUILD_MAINT_OPTIONS += optimize=-lto
+endif
+
+ifeq ($(shell dpkg-vendor --derives-from Ubuntu && echo yes),yes)
+VENDOR := UBUNTU
+DEB_BUILD_PARALLEL = yes
+else
+VENDOR := DEBIAN
+endif
+
+# DEB_BUILD_OPTIONS=parallel=N
+MAKEFLAGS += $(subst parallel=,-j,$(filter parallel=%,${DEB_BUILD_OPTIONS}))
+
+# verbose build
+V = $(if $(filter terse, ${DEB_BUILD_OPTIONS}),,1)
+
+# list of packages we're supposed to build
+BUILD_PACKAGES := $(shell dh_listpackages)
+
+enable_system = $(if $(filter qemu-system,${BUILD_PACKAGES}),enable,disable)
+enable_linux_user = $(if $(filter qemu-user,${BUILD_PACKAGES}),enable,disable)
+
+QEMU_XEN = /usr/libexec/xen-qemu-system-i386
+PKGVERSION = Debian ${DEB_VERSION}
+SAVEMODDIR = /run/qemu/$(shell echo -n "${PKGVERSION}" | tr --complement '[:alnum:]+-.~' '_')
+sysdataidir = debian/qemu-system-data/usr/share/qemu
+libdir = /usr/lib/${DEB_HOST_MULTIARCH}
+FIRMWAREPATH = /usr/share/qemu:/usr/share/seabios:/usr/lib/ipxe/qemu
+
+ALPHAEV67_CROSSPFX = alpha-linux-gnu-
+PPC64_CROSSPFX = powerpc64-linux-gnu-
+RISCV64_CROSSPFX = riscv64-linux-gnu-
+ARM_CROSSPFX = arm-none-eabi-
+
+extra-cflags = ${CFLAGS} ${CPPFLAGS}
+extra-ldflags = ${LDFLAGS} -Wl,--as-needed
+# we add another set of configure options from debian/control
+common_configure_opts = \
+ --with-pkgversion="$(PKGVERSION)" \
+ --extra-cflags="${extra-cflags}" \
+ --extra-ldflags="${extra-ldflags}" \
+ --prefix=/usr \
+ --sysconfdir=/etc \
+ --libdir=${libdir} \
+ --libexecdir=/usr/lib/qemu \
+ --firmwarepath=${FIRMWAREPATH} \
+ --localstatedir=/var \
+ --disable-install-blobs \
+ --disable-strip \
+ --interp-prefix=/etc/qemu-binfmt/%M \
+ --localstatedir=/var \
+ --with-git-submodules=ignore \
+
+# Cross compiling support
+ifneq ($(DEB_BUILD_GNU_TYPE), $(DEB_HOST_GNU_TYPE))
+common_configure_opts += --cross-prefix=$(DEB_HOST_GNU_TYPE)-
+endif
+
+ifneq ($(filter $(DEB_TARGET_ARCH), alpha ia64 hppa m68k sh4 sparc), )
+# allow configure to run on unsupported arches to build qemu-utils and the like
+common_configure_opts += --enable-tcg-interpreter --enable-tools
+endif
+
+ifeq (${enable_system},enable)
+
+# list of system (softmmu) targets, from ./configure
+system_targets = \
+ i386 x86_64 alpha aarch64 arm avr cris hppa m68k loongarch64 microblaze microblazeel \
+ mips mipsel mips64 mips64el nios2 or1k ppc ppc64 riscv32 riscv64 rx \
+ sh4 sh4eb sparc sparc64 s390x tricore xtensa xtensaeb
+
+# qemu-system subpackages, from d/control
+sys_systems = arm mips ppc sparc x86 $(if $(filter ${VENDOR},UBUNTU),s390x,)
+systems = ${sys_systems} misc
+sysarch_arm = $(filter aarch64 arm,${system_targets})
+sysarch_mips = $(filter mips mipsel mips64 mips64el,${system_targets})
+sysarch_ppc = $(filter ppc ppc64,${system_targets})
+sysarch_sparc = $(filter sparc sparc64,${system_targets})
+sysarch_x86 = $(filter i386 x86_64,${system_targets})
+sysarch_s390x = $(filter s390x,${system_targets})
+sysarch_misc = $(filter-out $(foreach s,${sys_systems},${sysarch_$s}),${system_targets})
+
+else
+
+systems =
+
+endif # enable_system
+
+ifeq (${enable_linux_user},enable)
+
+# list of linux-user targets, from ./configure
+user_targets = \
+ i386 x86_64 alpha aarch64 aarch64_be arm armeb cris hexagon hppa \
+ loongarch64 m68k microblaze microblazeel \
+ mips mipsel mips64 mips64el mipsn32 mipsn32el nios2 or1k \
+ ppc ppc64 ppc64le riscv32 riscv64 sh4 sh4eb sparc sparc64 sparc32plus \
+ s390x xtensa xtensaeb
+
+endif # enable_linux_user
+
+sysdata-components :=
+qemu-builds :=
+
+# several builds of qemu binary:
+
+##############################################
+# regular, main system/user and tools build
+configure-qemu: b/qemu/configured
+b/qemu/configured: configure
+ rm -rf b/qemu; mkdir -p b/qemu
+ cd b/qemu && \
+ ../../configure ${common_configure_opts} --disable-user \
+ --${enable_system}-system \
+ --${enable_linux_user}-linux-user \
+ --disable-xen \
+ --enable-modules \
+ --enable-module-upgrades \
+ $(shell sh debian/extract-config-opts \
+ $(DEB_HOST_ARCH_OS)-$(DEB_HOST_ARCH) debian/control) \
+ ${QEMU_CONFIGURE_OPTIONS}
+ touch $@
+
+build-qemu: b/qemu/built
+b/qemu/built: b/qemu/configured
+ $(MAKE) -C b/qemu V=${V}
+ touch $@
+
+define inst-system
+ mkdir -p debian/qemu-system-$1/usr/share/man/man1 debian/qemu-system-$1/usr/bin
+ for t in ${sysarch_$1}; do \
+ mv debian/tmp/usr/bin/qemu-system-$$t debian/qemu-system-$1/usr/bin/qemu-system-$$t; \
+ echo ".so man1/qemu-system.1" > debian/qemu-system-$1/usr/share/man/man1/qemu-system-$$t.1; \
+ done
+ echo sysarch:$1=\
+$(if $(wordlist 10,20,${sysarch_$1}),\
+$(wordlist 1,8,${sysarch_$1})\$${Newline} $(wordlist 9,20,${sysarch_$1}),\
+${sysarch_$1}) \
+> debian/qemu-system-$1.substvars
+ echo sysprovides:$1=${addprefix qemu-system-,${filter-out $1,${sysarch_$1}}} | \
+ sed -e 's/ /, /g' -e 'y/_/-/' >> debian/qemu-system-$1.substvars
+ dh_link -pqemu-system-$1 usr/share/doc/qemu-system-common usr/share/doc/qemu-system-$1/common
+
+endef
+# inst-kvm-link package binary-suffix
+define inst-kvm-link
+ dh_link -p $1 usr/bin/qemu-system-$2 usr/bin/kvm
+ mkdir -p debian/$1/usr/share/man/man1
+ sed 's/@ARCH@/$2/g' debian/kvm.1 > debian/$1/usr/share/man/man1/kvm.1
+ touch -r debian/kvm.1 debian/$1/usr/share/man/man1/kvm.1
+endef
+
+install-qemu: b/qemu/built
+ $(MAKE) -C b/qemu DESTDIR=${CURDIR}/debian/tmp install
+
+# remove qtest "accel" modules
+ rm -f debian/tmp${libdir}/qemu/accel-qtest-*.so
+
+# save block-extra loadable modules on upgrades
+# other module types for now (5.0) can't be loaded at runtime, only at startup
+ echo 'case $$1 in (upgrade|deconfigure) [ -d /run/qemu ] || exit 0; ! findmnt --noheadings --target /run/qemu/ | grep -q noexec || exit 0; mkdir -p ${SAVEMODDIR}; cp -p ${libdir}/qemu/block-*.so ${SAVEMODDIR}/;; esac' \
+ >> debian/qemu-block-extra.prerm.debhelper
+ echo 'case $$1 in (remove) rm -f ${SAVEMODDIR}/block-*.so;; esac' \
+ >> debian/qemu-block-extra.postrm.debhelper
+ echo 'case $$1 in (purge) if systemctl is-active -q run-qemu.mount; then systemctl stop run-qemu.mount || true; fi; rm -rf "/run/qemu";; esac' \
+ >> debian/qemu-block-extra.postrm.debhelper
+
+ifeq (${enable_system},enable)
+
+ # qemu-system subpackages
+ mv debian/tmp/usr/share/man/man1/qemu.1 debian/tmp/usr/share/man/man1/qemu-system.1
+ $(foreach s,${systems},$(call inst-system,$s))
+
+# gui modules. We move these here instead of using d/qemu-system-gui.install,
+# b/c we install "all other" modules in qemu-system-common.install
+# audio-pa.so pulls in X11 so we move it into -system-gui too
+# hw-display-virtio-gpu-gl also pulls in X11, move it to -gui
+ mkdir -p debian/qemu-system-gui${libdir}/qemu
+ mv -t debian/qemu-system-gui${libdir}/qemu/ \
+ debian/tmp${libdir}/qemu/ui-gtk.so \
+ debian/tmp${libdir}/qemu/ui-sdl.so \
+ debian/tmp${libdir}/qemu/audio-jack.so \
+ debian/tmp${libdir}/qemu/audio-sdl.so \
+ debian/tmp${libdir}/qemu/audio-pa.so \
+ debian/tmp${libdir}/qemu/hw-display-virtio-gpu-gl.so \
+
+ifeq ($(DEB_HOST_ARCH_OS),linux)
+
+# /usr/bin/kvm handy link multi-arch from old qemu-kvm package
+# on i386, should we link to qemu-system-i386? how about x32?
+ifneq ($(filter ${DEB_HOST_ARCH},amd64 i386),)
+ $(call inst-kvm-link,qemu-system-x86,x86_64)
+ifeq (${VENDOR},UBUNTU)
+# on ubuntu *-spice existed, may be used in libvirt xml and scripts - keep links for compatibility
+# The sunset for this will be when Ubuntu-Bionic goes out of support which is expected to happen in 2028
+ install -p -t debian/qemu-system-x86/usr/bin debian/kvm-spice debian/qemu-system-x86_64-spice
+ install -p -t debian/qemu-system-x86/usr/share/man/man1/ debian/kvm-spice.1
+ echo ".so man1/kvm-spice.1" > debian/qemu-system-x86/usr/share/man/man1/qemu-system-x86_64-spice.1
+endif
+endif
+ $(if $(filter ${DEB_HOST_ARCH},arm64), $(call inst-kvm-link,qemu-system-arm,aarch64))
+ $(if $(filter ${DEB_HOST_ARCH},armhf armel), $(call inst-kvm-link,qemu-system-arm,arm))
+ $(if $(filter ${DEB_HOST_ARCH},ppc64 ppc64el), $(call inst-kvm-link,qemu-system-ppc,ppc64))
+ $(if $(filter ${DEB_HOST_ARCH},s390x), $(call inst-kvm-link,qemu-system-$(if $(filter ${VENDOR},UBUNTU),s390x,misc),s390x))
+ifeq ($(VENDOR),UBUNTU)
+# apport hook is ubuntu-specific
+ install -p -D -t debian/qemu-system-common/usr/share/apport/package-hooks/ \
+ debian/source_qemu.py
+endif
+
+ifeq (DEBIAN-amd64,${VENDOR}-${DEB_HOST_ARCH})
+# do it for bookworm only, remove the wrapper for bookworm+
+ mkdir -p debian/qemu-system-x86/usr/libexec/
+ mv debian/qemu-system-x86/usr/bin/qemu-system-i386 \
+ debian/qemu-system-x86/usr/libexec/qemu-system-i386
+ install -pm0755 debian/qemu-system-i386.xen-wrapper \
+ debian/qemu-system-x86/usr/bin/qemu-system-i386
+endif
+
+# virtfs-proxy-helper and qemu-bridge-helper are linux-specific
+ for f in usr/lib/qemu/virtfs-proxy-helper \
+ usr/share/man/man1/virtfs-proxy-helper.1 \
+ usr/lib/qemu/qemu-bridge-helper \
+ ; do \
+ mkdir -p debian/qemu-system-common/$${f%/*} ; \
+ mv debian/tmp/$$f debian/qemu-system-common/$$f ; \
+ done
+
+ifneq (${DEB_HOST_ARCH},sparc64)
+# virtiofsd needs libseccomp which is not ported to sparc (not even the kernel part),
+# so install it only on non-sparc
+ for f in usr/lib/qemu/virtiofsd \
+ usr/share/man/man1/virtiofsd.1 \
+ usr/share/qemu/vhost-user/50-qemu-virtiofsd.json \
+ ; do \
+ mkdir -p debian/qemu-system-common/$${f%/*} ; \
+ mv debian/tmp/$$f debian/qemu-system-common/$$f ; \
+ done
+endif
+
+# for --enable-module-upgrades to work in more environments
+ install -D -m 0644 debian/run-qemu.mount debian/qemu-block-extra/lib/systemd/system/run-qemu.mount
+
+endif # linux
+
+endif # enable_system
+
+ifeq ($(enable_linux_user),enable)
+ mkdir -p debian/qemu-user/usr/bin
+ mv -t debian/qemu-user/usr/bin $(patsubst %,debian/tmp/usr/bin/qemu-%,${user_targets})
+ dh_link -p qemu-user $(patsubst %,usr/share/man/man1/qemu-user.1 usr/share/man/man1/qemu-%.1,${user_targets})
+
+ ./debian/binfmt-install qemu-user-binfmt
+endif # enable_linux_user
+
+ifeq (${enable_system},enable)
+# qemu-ifup is arch-specific
+ install -D debian/qemu-ifup.$(DEB_HOST_ARCH_OS) \
+ debian/qemu-system-common/etc/qemu-ifup
+endif
+
+qemu-builds += qemu
+
+##############################################
+# microvm build:
+configure-microvm: b/microvm/configured
+b/microvm/configured: configure debian/microvm-devices.mak
+ rm -rf b/microvm; mkdir -p b/microvm
+ cp -up debian/microvm-devices.mak configs/devices/x86_64-softmmu/microvm.mak
+ cd b/microvm && \
+ ../../configure ${common_configure_opts} \
+ --extra-cflags="${extra-cflags} -DCONFIG_MICROVM_DEFAULT=1" \
+ --disable-docs \
+ --without-default-features \
+ --disable-user \
+ --target-list=x86_64-softmmu --enable-kvm --disable-tcg \
+ --enable-vnc \
+ --enable-attr --enable-avx2 \
+ --enable-coroutine-pool \
+ --audio-drv-list="" \
+ --without-default-devices \
+ --with-devices-x86_64=microvm \
+ --enable-vhost-kernel --enable-vhost-net \
+ --enable-vhost-vdpa \
+ --enable-vhost-user --enable-vhost-user-blk-server \
+ --enable-vhost-crypto \
+ ${QEMU_MICROVM_CONFIGURE_OPTIONS}
+ touch $@
+build-microvm: b/microvm/qemu-system-x86_64
+b/microvm/qemu-system-x86_64: b/microvm/configured
+ $(MAKE) -C b/microvm V=${V} qemu-system-x86_64
+install-microvm: b/microvm/qemu-system-x86_64
+ cp b/microvm/x86_64-softmmu/qemu-system-x86_64 debian/qemu-system-x86/usr/bin/qemu-system-x86_64-microvm
+ echo ".so man1/qemu-system.1" > debian/qemu-system-x86/usr/share/man/man1/qemu-system-x86_64-microvm.1
+# build microvm on amd64 only if system build is enabled
+ifeq ($(filter-out $(DEB_HOST_ARCH),amd64)${enable_system},enable)
+qemu-builds += microvm
+endif
+
+##############################################
+# xen build (amd64 arch only, i386-softmmu target only)
+configure-xen: b/xen/configured
+b/xen/configured: configure
+ # system build for qemu-system-xen
+ rm -rf b/xen; mkdir -p b/xen
+ cd b/xen && \
+ ../../configure ${common_configure_opts} \
+ --disable-blobs --disable-docs --disable-tools \
+ --without-default-features \
+ --enable-avx2 --enable-avx512f \
+ --enable-xen --target-list=i386-softmmu \
+ --enable-xen-pci-passthrough \
+ --disable-tcg --disable-kvm \
+ --audio-drv-list= \
+ --enable-libusb \
+ --enable-vnc --enable-vnc-jpeg \
+ --enable-spice \
+ --enable-virtfs --enable-attr --enable-cap-ng \
+ ${QEMU_XEN_CONFIGURE_OPTIONS}
+ touch $@
+build-xen: b/xen/built
+b/xen/built: b/xen/configured
+ $(MAKE) -C b/xen V=${V} qemu-system-i386
+ touch $@
+install-xen: b/xen/built
+ install -D b/xen/qemu-system-i386 \
+ debian/qemu-system-xen${QEMU_XEN}
+ifeq (${DEB_HOST_ARCH}-${enable_system},amd64-enable)
+qemu-builds += xen
+endif
+
+##############################################
+# linux-user-static build
+configure-user-static: b/user-static/configured
+b/user-static/configured: configure
+# do not use debian/configure-opts here, all optional stuff will be enabled
+# See LP:#1908331 for --static-pie (the default in qemu) and #1053101
+# See https://sourceware.org/bugzilla/show_bug.cgi?id=29514
+# use --disable-pie on i386 for now due to #1056739
+ rm -rf b/user-static; mkdir b/user-static
+ cd b/user-static && \
+ ../../configure ${common_configure_opts} \
+ --static \
+ $(if $(filter i386,${DEB_HOST_ARCH}),--disable-pie) \
+ --disable-system --disable-xen \
+ --target-list="$(addsuffix -linux-user,${user_targets})"
+ touch $@
+build-user-static: b/user-static/built
+b/user-static/built: b/user-static/configured
+ # we use this invocation to build just the binaries
+ $(MAKE) -C b/user-static V=${V} $(addprefix qemu-,${user_targets})
+ sed -e 's/qemu\\-user\\-static/qemu\\-user/g' \
+ -e 's/ (static version)//' \
+ debian/qemu-user-static.1 > b/qemu-user.1
+ touch $@
+install-user-static: b/user-static/built
+ mkdir -p debian/qemu-user-static/usr/bin debian/qemu-user-static/usr/share/man/man1
+ for t in ${user_targets}; do \
+ cp -p b/user-static/$$t-linux-user/qemu-$$t \
+ debian/qemu-user-static/usr/bin/qemu-$$t-static ; \
+ ln -s qemu-user-static.1 \
+ debian/qemu-user-static/usr/share/man/man1/qemu-$$t-static.1 ; \
+ done
+ ./debian/binfmt-install qemu-user-static
+ifeq ($(enable_linux_user),enable)
+qemu-builds += user-static
+endif
+
+##############################################
+# common rules
+
+.PHONY: $(addprefix configure-, ${qemu-builds}) \
+ $(addprefix build-, ${qemu-builds}) \
+ $(addprefix install-, ${qemu-builds}) \
+ configure-arch build-arch
+configure-arch: $(addprefix configure-, ${qemu-builds})
+build-arch: $(addprefix build-, ${qemu-builds})
+
+override_dh_auto_install-arch: $(addprefix install-, ${qemu-builds})
+
+override_dh_installdocs:
+ dh_installdocs -Nqemu-user-binfmt
+ dh_installdocs -pqemu-user-binfmt --link-doc=qemu-user
+override_dh_installchangelogs:
+ dh_installchangelogs -Nqemu-user-binfmt
+override_dh_installinit:
+ dh_installinit -pqemu-guest-agent
+override_dh_installsystemd:
+ dh_installsystemd -pqemu-guest-agent --no-enable
+# default-enable /run/qemu mount only on ubuntu,
+# on debian let it be manually controlled and off by default
+ dh_installsystemd -pqemu-block-extra --no-restart-on-upgrade --name=run-qemu.mount \
+ $(if $(filter ${VENDOR},DEBIAN),--no-start --no-enable,)
+execute_after_dh_shlibdeps:
+ifeq ($(enable_linux_user),enable)
+# after shlibdeps finished, grab ${shlibs:Depends} from -user package
+# and transform it into Built-Using field for -user-static.
+# See also dpkg-query bug #588505
+ if [ -f debian/qemu-user.substvars ]; then \
+ pkgs=$$(sed -n -e's/([^)]*)//g' -e's/,//g' -e's/^shlibs:Depends=//p' debian/qemu-user.substvars); \
+ srcs=; for p in $$pkgs; do \
+ srcs="$$srcs $$(dpkg-query -f '$${source:Package} (= $${source:Version}),' -W $$p)"; \
+ done ; \
+ echo "built-using=$$srcs" >> debian/qemu-user-static.substvars ; \
+ fi
+endif
+
+# we do not need these (just a tiny build speedup):
+override_dh_makeshlibs:
+
+override_dh_dwz: #968670: skip dwz << 0.14 on these arches, remove in bookworm+1
+ifneq (,$(filter ${DEB_HOST_ARCH},arm64 ppc64el s390x))
+ v="$$(dwz --version 2>&1 | sed -n 's/^dwz version //p')"; case "$$v" in \
+ (0.1[0123]) echo "Skipping dwz version $$v on ${DEB_HOST_ARCH}: #968670" ;; \
+ (*) dh_dwz ;; \
+ esac
+else
+ dh_dwz
+endif
+
+##############################################
+### firmware, qemu-user-data package
+
+### openbios rules
+b/openbios/config-host.mak:
+ mkdir -p b/openbios
+ cd b/openbios && ../../roms/openbios/config/scripts/switch-arch builtin-ppc builtin-sparc32 builtin-sparc64
+build-openbios: $(addprefix b/openbios/obj-, $(addsuffix /.built, ppc sparc32 sparc64))
+b/openbios/obj-%/.built: b/openbios/config-host.mak
+ ${MAKE} -C ${@D} V=${V} EXTRACFLAGS="-ffreestanding -fno-pic -fno-stack-protector"
+ @touch $@
+install-openbios: build-openbios
+ install -m 0644 b/openbios/obj-ppc/openbios-qemu.elf ${sysdataidir}/openbios-ppc
+ install -m 0644 b/openbios/obj-sparc32/openbios-builtin.elf ${sysdataidir}/openbios-sparc32
+ install -m 0644 b/openbios/obj-sparc64/openbios-builtin.elf ${sysdataidir}/openbios-sparc64
+ install -m 0644 -t ${sysdataidir} \
+ b/openbios/obj-sparc32/QEMU,tcx.bin \
+ b/openbios/obj-sparc32/QEMU,cgthree.bin \
+ b/openbios/obj-sparc64/QEMU,VGA.bin
+sysdata-components += openbios
+
+### powernv firmware in roms/skiboot
+build-skiboot: b/skiboot/skiboot.lid
+b/skiboot/skiboot.lid: | roms/skiboot/.version
+ mkdir -p b/skiboot
+# skiboot makefiles makes it difficult to *add* an option to CFLAGS.
+# Abuse OPTS= for this, with the default being -Os.
+ grep -q '^OPTS=-Os$$' roms/skiboot/Makefile.main || \
+ { echo "review OPTS= in skiboot/Makefile.main"; false; }
+ ${MAKE} -C b/skiboot -f ${CURDIR}/roms/skiboot/Makefile \
+ SRC=${CURDIR}/roms/skiboot \
+ OPTS='-Os -ffile-prefix-map="${CURDIR}/roms/skiboot/"=' \
+ CROSS_COMPILE=${PPC64_CROSSPFX} V=${V}
+install-skiboot: b/skiboot/skiboot.lid
+ install -m 0644 -t ${sysdataidir} $<
+sysdata-components += skiboot
+
+build-vof: b/vof/vof.bin
+b/vof/vof.bin: | b
+ mkdir -p b/vof
+ printf 'CC=$${CROSS}gcc\nLD=$${CROSS}ld\nOBJCOPY=$${CROSS}objcopy\nEXTRA_CFLAGS=-m32 -mbig-endian' > b/vof/config.mak
+ ${MAKE} -C b/vof CROSS=${PPC64_CROSSPFX} SRC_DIR=../../pc-bios/vof -f../../pc-bios/vof/Makefile
+install-vof: b/vof/vof.bin
+ install -m 0644 -t ${sysdataidir} $<
+sysdata-components += vof
+
+### x86 optionrom
+build-x86-optionrom: b/optionrom/built
+b/optionrom/built:
+ mkdir -p b/optionrom
+ ${MAKE} -f ${CURDIR}/debian/optionrom.mak -C b/optionrom SRC_PATH="${CURDIR}" all
+ touch $@
+install-x86-optionrom: build-x86-optionrom | ${sysdataidir}
+ ${MAKE} -f ${CURDIR}/debian/optionrom.mak -C b/optionrom SRC_PATH="${CURDIR}" install DESTDIR="${CURDIR}/${sysdataidir}"
+sysdata-components += x86-optionrom
+
+### sgabios.
+# The Makefile is too complex and forces current date to be embedded to binary
+build-sgabios: b/sgabios/sgabios.bin
+b/sgabios/sgabios.bin:
+ mkdir -p b/sgabios
+ cc -c -o b/sgabios/sgabios.o roms/sgabios/sgabios.S -Wall -Os -m32 -nostdlib \
+ -DBUILD_DATE="\"$$(LC_ALL=C date -u -r roms/sgabios/sgabios.S)\"" \
+ -DBUILD_SHORT_DATE="\"$$(date -u +%D -r roms/sgabios/sgabios.S)\"" \
+ -DBUILD_HOST=\"debian\" -DBUILD_USER=\"build\"
+ ld -T roms/sgabios/rom16.ld -nostdlib b/sgabios/sgabios.o -o b/sgabios/sgabios.elf
+ objcopy -O binary b/sgabios/sgabios.elf b/sgabios/sgabios.bin
+ cc -Wall -O2 -o b/sgabios/csum8 roms/sgabios/csum8.c
+ b/sgabios/csum8 b/sgabios/sgabios.bin
+install-sgabios: b/sgabios/sgabios.bin
+ install -m 0644 $< ${sysdataidir}/sgabios.bin
+sysdata-components += sgabios
+
+### qboot, aka bios-microvm
+build-qboot: b/qboot/bios.bin
+b/qboot/bios.bin: | b
+ rm -rf b/qboot
+ meson setup roms/qboot b/qboot
+ ninja -C b/qboot
+install-qboot: b/qboot/bios.bin
+ install -m 0644 $< ${sysdataidir}/qboot.rom
+ # 5.0 & 5.1 compat symlink, can go for bullseye final
+ ln -s qboot.rom ${sysdataidir}/bios-microvm.bin
+sysdata-components += qboot
+
+### alpha firmware in roms/palcode-clipper
+build-palcode-clipper: b/qemu-palcode/palcode-clipper
+b/qemu-palcode/palcode-clipper: | b
+ cp -al roms/qemu-palcode b/
+#XXX #1019011 (remove OPT= alternative when fixed)
+ ${MAKE} -C b/qemu-palcode CROSS=${ALPHAEV67_CROSSPFX} -k || \
+ ${MAKE} -C b/qemu-palcode CROSS=${ALPHAEV67_CROSSPFX} OPT=-O1
+ ${ALPHAEV67_CROSSPFX}strip b/qemu-palcode/palcode-clipper
+install-palcode-clipper: b/qemu-palcode/palcode-clipper
+ install -m 0644 $< ${sysdataidir}/palcode-clipper
+sysdata-components += palcode-clipper
+
+### SLOF
+build-slof: b/SLOF/boot_rom.bin
+b/SLOF/boot_rom.bin: | b
+ cp -al roms/SLOF b/
+ env -u LDFLAGS -u CFLAGS $(MAKE) -C b/SLOF qemu CROSS=${PPC64_CROSSPFX} V=${V}
+install-slof: b/SLOF/boot_rom.bin
+ install -m 0644 $< ${sysdataidir}/slof.bin
+sysdata-components += slof
+
+### s390x firmware in pc-bios/s390-ccw
+build-s390x-fw: b/s390fw/built
+b/s390fw/built:
+ mkdir -p b/s390fw
+ ${MAKE} -f debian/s390fw.mak OUT=b/s390fw/
+ touch $@
+install-s390x-fw: build-s390x-fw
+ install -m 0644 -t ${sysdataidir} b/s390fw/s390*.img
+sysdata-components += s390x-fw
+
+### hppa-firmware (roms/seabios-hppa)
+build-hppa-fw: b/hppafw/hppa-firmware.img
+b/hppafw/hppa-firmware.img:
+ mkdir -p b/hppafw
+ echo CONFIG_PARISC=y > roms/seabios-hppa/.config
+ ${MAKE} -C roms/seabios-hppa olddefconfig
+ ${MAKE} -C roms/seabios-hppa OUT=../../b/hppafw/ PYTHON=python3 parisc
+ hppa-linux-gnu-strip -R.note -R.comment $@
+install-hppa-fw: b/hppafw/hppa-firmware.img
+ install -m 0644 $< ${sysdataidir}
+sysdata-components += hppa-fw
+
+### opensbi (riscv firmware)
+# we only build v64 variants, not v32
+build-opensbi: b/opensbi/.built
+b/opensbi/.built:
+ mkdir -p b/opensbi
+ ${MAKE} -C roms/opensbi O=../../b/opensbi CROSS_COMPILE=${RISCV64_CROSSPFX} V=${V} PLATFORM=generic
+ ${RISCV64_CROSSPFX}strip --strip-unneeded -R.comment -R.note b/opensbi/platform/generic/firmware/fw_dynamic.elf
+ touch $@
+install-opensbi: build-opensbi
+ install -m 0644 b/opensbi/platform/generic/firmware/fw_dynamic.bin ${sysdataidir}/opensbi-riscv64-generic-fw_dynamic.bin
+ install -m 0644 b/opensbi/platform/generic/firmware/fw_dynamic.elf ${sysdataidir}/opensbi-riscv64-generic-fw_dynamic.elf
+sysdata-components += opensbi
+
+### vbootrom (npcm7xx)
+build-vbootrom: b/vbootrom/.built
+b/vbootrom/.built: | b
+ cp -pa roms/vbootrom b/
+ ${MAKE} -C b/vbootrom CROSS_COMPILE=${ARM_CROSSPFX}
+ touch $@
+install-vbootrom: build-vbootrom
+ install -m 0644 b/vbootrom/npcm7xx_bootrom.bin ${sysdataidir}/
+sysdata-components += vbootrom
+
+### misc firmware
+build-misc: b/misc/.built
+b/misc/.built:
+ mkdir -p b/misc
+ dtc -o b/misc/bamboo.dtb pc-bios/bamboo.dts
+ dtc -o b/misc/canyonlands.dtb pc-bios/canyonlands.dts
+ touch $@
+install-misc: build-misc
+ install -m 0644 b/misc/bamboo.dtb b/misc/canyonlands.dtb \
+ ${sysdataidir}
+sysdata-components += misc
+
+${sysdataidir}:
+ mkdir -p -m 0755 $@
+b:
+ mkdir -p $@
+
+.PHONY: $(addprefix build- , ${sysdata-components}) \
+ $(addprefix install-, ${sysdata-components}) \
+ build-indep
+$(addprefix build- , ${sysdata-components}): | b
+$(addprefix install-, ${sysdata-components}): | ${sysdataidir}
+build-indep: $(addprefix build-, ${sysdata-components})
+
+override_dh_auto_install-indep: $(addprefix install-, ${sysdata-components})
+# qemu-system-data
+# icon for gtk ui
+ install -Dp -m0644 ui/icons/qemu.svg \
+ -t debian/qemu-system-data/usr/share/icons/hicolor/scalable/apps/
+ install -Dp -m0644 debian/qemu.desktop \
+ -t debian/qemu-system-data/usr/share/applications/
+# icon for sdl2 ui (non-sdl-image version)
+ install -Dp -m0644 ui/icons/qemu_32x32.png \
+ -t debian/qemu-system-data/usr/share/icons/hicolor/32x32/apps/
+ install -Dp -m0644 -t debian/qemu-system-data/usr/share/qemu/keymaps/ \
+ $$(ls -1 pc-bios/keymaps/* | fgrep -v /meson.build)
+
+binary-arch binary-indep binary \
+install-arch install-indep install \
+: %:
+ dh $@
+build: build-arch build-indep
+
+clean: debian/control
+ dh_clean \
+ b/ \
+ configs/devices/x86_64-softmmu/microvm.mak \
+
+.PHONY: build binary-arch binary-indep binary \
+ install-arch install-indep install \
+ clean get-orig-source
+
+get-orig-source:
+ ./debian/get-orig-source.sh ${DEB_VERSION}
+
+ifneq (,$(wildcard debian/control-in))
+# only include rules for debian/control if debian/control-in is present
+debian/control: debian/control-in debian/rules
+ echo '# autogenerated file, please edit debian/control-in' > $@.tmp
+ sed -e 's/^:$(shell echo ${VENDOR} | tr '[A-Z]' '[a-z]')://' \
+ -e '/^:[a-z]*:/D' $< >> $@.tmp
+ mv -f $@.tmp $@
+endif
diff --git a/debian/run-qemu.mount b/debian/run-qemu.mount
new file mode 100644
index 00000000..6ab120a8
--- /dev/null
+++ b/debian/run-qemu.mount
@@ -0,0 +1,14 @@
+[Unit]
+Description=Prepare /run/qemu to allow still running qemu binaries of former builds (after package upgrades) to fallback-load modules from there
+Before=libvirtd.service
+
+[Mount]
+What=tmpfs
+Where=/run/qemu
+Type=tmpfs
+Options=nosuid,nodev,mode=0755
+ReadWriteOnly=true
+LazyUnmount=yes
+
+[Install]
+WantedBy=multi-user.target
diff --git a/debian/s390fw.mak b/debian/s390fw.mak
new file mode 100644
index 00000000..64fab0f2
--- /dev/null
+++ b/debian/s390fw.mak
@@ -0,0 +1,49 @@
+# Makefile for s390x qemu firmware, building two files:
+# s390-ccw.img and s390-netboot.img
+# Uses SLOF sources for netboot.
+
+OUT =
+
+S390X_CROSSPFX=s390x-linux-gnu-
+
+LDFLAGS = -Wl,-pie -fPIE -nostdlib \
+ -std=gnu99 -fwrapv -fno-common \
+ -ffreestanding -fno-delete-null-pointer-checks -msoft-float \
+ -march=z900 -fPIE -fno-strict-aliasing -fno-stack-protector \
+ -fno-asynchronous-unwind-tables
+
+all: ${OUT}s390-ccw.img ${OUT}s390-netboot.img
+
+CCW_SRCS = start.S main.c bootmap.c jump2ipl.c sclp.c menu.c \
+ virtio.c virtio-scsi.c virtio-blkdev.c libc.c cio.c dasd-ipl.c
+CCW_FSRCS = $(addprefix pc-bios/s390-ccw/,${CCW_SRCS})
+
+${OUT}s390-ccw.img: $(CCW_FSRCS)
+ ${S390X_CROSSPFX}gcc -o $@ ${LDFLAGS} $^
+ ${S390X_CROSSPFX}strip --strip-unneeded $@
+ chmod -x $@
+
+NETBOOT_SRCS = start.S sclp.c cio.c virtio.c virtio-net.c jump2ipl.c netmain.c
+NETBOOT_FSRCS = $(addprefix pc-bios/s390-ccw/,${NETBOOT_SRCS})
+
+SLOF = roms/SLOF
+SLOFLIB = ${SLOF}/lib/libc/
+
+SLOF_LIBSRCS = \
+ $(addprefix ${SLOFLIB}ctype/,isdigit.c isxdigit.c toupper.c) \
+ $(addprefix ${SLOFLIB}string/,strcat.c strchr.c strrchr.c strcpy.c strlen.c strncpy.c \
+ strcmp.c strncmp.c strcasecmp.c strncasecmp.c strstr.c \
+ memset.c memcpy.c memmove.c memcmp.c) \
+ $(addprefix ${SLOFLIB}stdlib/,atoi.c atol.c strtoul.c strtol.c rand.c malloc.c free.c) \
+ $(addprefix ${SLOFLIB}stdio/,sprintf.c snprintf.c vfprintf.c vsnprintf.c vsprintf.c fprintf.c \
+ printf.c putc.c puts.c putchar.c stdchnls.c fileno.c) \
+ ${SLOF}/slof/sbrk.c \
+ $(addprefix ${SLOF}/lib/libnet/,args.c dhcp.c dns.c icmpv6.c ipv6.c tcp.c udp.c bootp.c \
+ dhcpv6.c ethernet.c ipv4.c ndp.c tftp.c pxelinux.c) \
+
+${OUT}s390-netboot.img: ${NETBOOT_FSRCS} ${SLOF_LIBSRCS}
+ ${S390X_CROSSPFX}gcc -o $@ ${LDFLAGS} -Ttext=0x7800000 \
+ -nostdinc -I${SLOFLIB}include -I${SLOF}/lib/libnet -DDHCPARCH=0x1F \
+ $^
+ ${S390X_CROSSPFX}strip --strip-unneeded $@
+ chmod -x $@
diff --git a/debian/source/format b/debian/source/format
new file mode 100644
index 00000000..163aaf8d
--- /dev/null
+++ b/debian/source/format
@@ -0,0 +1 @@
+3.0 (quilt)
diff --git a/debian/source/lintian-overrides b/debian/source/lintian-overrides
new file mode 100644
index 00000000..3d74f174
--- /dev/null
+++ b/debian/source/lintian-overrides
@@ -0,0 +1,6 @@
+# deliberate spacing to align Breaks:Replaces
+qemu source: debian-control-has-unusual-field-spacing Breaks *
+qemu source: debian-control-has-unusual-field-spacing Replaces *
+# we have a ton of files with long lines, just shut up this warning
+qemu source: very-long-line-length-in-source-file *
+qemu source: package-does-not-install-examples *roms/*/examples/*
diff --git a/debian/source/options b/debian/source/options
new file mode 100644
index 00000000..dcefc1b3
--- /dev/null
+++ b/debian/source/options
@@ -0,0 +1,2 @@
+# ignore sources which are in submodules in upstream git
+extend-diff-ignore ^capstone/|^dtc/|^meson/|^roms/.*/|^\.git-submodule-status$
diff --git a/debian/source_qemu.py b/debian/source_qemu.py
new file mode 100644
index 00000000..b86d6bd7
--- /dev/null
+++ b/debian/source_qemu.py
@@ -0,0 +1,25 @@
+'''apport package hook for qemu
+
+(c) 2009 Canonical Ltd.
+'''
+
+from apport.hookutils import *
+import subprocess
+
+def cmd_pipe(command1, command2, input = None, stderr = subprocess.STDOUT, stdin = None):
+ '''Try to pipe command1 into command2.'''
+ try:
+ sp1 = subprocess.Popen(command1, stdin=stdin, stdout=subprocess.PIPE, stderr=stderr, close_fds=True)
+ sp2 = subprocess.Popen(command2, stdin=sp1.stdout, stdout=subprocess.PIPE, stderr=stderr, close_fds=True)
+ except OSError as e:
+ return [127, str(e)]
+
+ out = sp2.communicate(input)[0]
+ return [sp2.returncode,out]
+
+def add_info(report):
+ attach_hardware(report)
+ attach_related_packages(report, ['kvm*', '*libvirt*', 'virt-manager', 'qemu*'])
+ rc,output = cmd_pipe(['ps', '-eo', 'comm,stat,euid,ruid,pid,ppid,pcpu,args'], ['egrep', '(^COMMAND|^qemu|^kvm)'])
+ if rc == 0:
+ report['KvmCmdLine'] = output
diff --git a/debian/tests/control b/debian/tests/control
new file mode 100644
index 00000000..9869a5f8
--- /dev/null
+++ b/debian/tests/control
@@ -0,0 +1,11 @@
+Tests: test-qemu-img.sh
+Depends: qemu-utils
+Restrictions: superficial
+
+Tests: test-qemu-system.sh
+Depends: qemu-system-x86
+Restrictions: superficial
+
+Tests: test-qemu-user.sh
+Depends: qemu-user, qemu-user-static
+Restrictions: superficial
diff --git a/debian/tests/test-qemu-img.sh b/debian/tests/test-qemu-img.sh
new file mode 100755
index 00000000..ed7475f2
--- /dev/null
+++ b/debian/tests/test-qemu-img.sh
@@ -0,0 +1,35 @@
+#!/bin/sh
+
+set -e
+
+cd "$AUTOPKGTEST_TMP"
+
+doit() {
+ echo "$1:"
+ shift
+ echo "$1"
+ if [ -n "$2" ]; then
+ out="$($1)"
+ eval "case \"\$out\" in ( $2 ) echo \"\$out\";; (*) echo \"unexpected output:\"; echo \" want $2\"; echo \" got \$out\"; return 1;; esac"
+ else
+ $1
+ fi
+ echo ok.
+}
+
+doit "Testing if qemu-img creates images" \
+ "qemu-img create q.raw 12G"
+
+doit "Testing for correct image size" \
+ "ls -l q.raw" '*\ 12884901888\ *'
+
+doit "Testing if file is sparse" \
+ 'ls -s q.raw' '[04]\ *'
+
+doit "Testing if conversion to a qcow2 image works" \
+ "qemu-img convert -f raw -O qcow2 q.raw q.qcow2"
+
+doit "Checking if image is qcow2" \
+ 'qemu-img info q.qcow2' "*'file format: qcow2'*'size: 12 GiB (12884901888 bytes)'*"
+
+rm -f q.raw q.qcow2
diff --git a/debian/tests/test-qemu-system.sh b/debian/tests/test-qemu-system.sh
new file mode 100755
index 00000000..eca40951
--- /dev/null
+++ b/debian/tests/test-qemu-system.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+set -e
+
+for ARCH in x86_64 i386; do
+ echo -n "Checking for pc in ${ARCH}..."
+ qemu-system-${ARCH} -M help | grep -qs "pc\s\+Standard PC"
+ echo "done."
+done
+
diff --git a/debian/tests/test-qemu-user.sh b/debian/tests/test-qemu-user.sh
new file mode 100755
index 00000000..da18b8af
--- /dev/null
+++ b/debian/tests/test-qemu-user.sh
@@ -0,0 +1,34 @@
+#!/bin/sh
+
+set -e
+
+arch=$(dpkg --print-architecture)
+echo "debian architecture: $arch"
+case $arch in
+ ( amd64 | x86_64 ) arch=x86_64 ;;
+ ( i[3456]86 ) arch=i386 ;;
+ ( arm64 | aarch64 ) arch=aarch64 ;;
+ ( arm | armel | armhf ) arch=arm ;;
+ ( ppc64el | powerpc64le ) arch=ppc64le ;;
+ ( s390x ) ;;
+ ( * ) echo "Warning: unmapped architecture $arch" ;;
+esac
+echo "qemu architecture: $arch"
+
+tested=
+for f in qemu-$arch qemu-$arch-static ; do
+ [ -x /usr/bin/$f ] || continue
+ echo "Checking if $f can run executables:"
+ echo "glob with sh: $f /bin/sh -c '$f /bin/ls -dCFl debian/*[t]*':"
+ ls="$($f /bin/sh -c "$f /bin/ls -dCFl debian/*[t]*")"
+ echo "$ls"
+ case "$ls" in
+ (*debian/control*) ;;
+ *) echo "Expected output not found" >&2; exit 1;;
+ esac
+ echo ok.
+ tested=y
+done
+if [ ! "$tested" ]; then
+ echo "Warning: qemu-$arch[-static] not found, not testing qemu-user"
+fi
diff --git a/debian/upstream/signing-key.asc b/debian/upstream/signing-key.asc
new file mode 100644
index 00000000..63904eaf
--- /dev/null
+++ b/debian/upstream/signing-key.asc
@@ -0,0 +1,44 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+mQENBFJhQQ8BCAChk4A3y0VfqeGfuhBZK4nvpZP/cSIQntWDheF3Tx7m9CxEGbc+
+5aHxfrvm45LSjwPCK020WjeqYX2UFQfcvcjoW6iMbth1BLydu11vx6Gk/CJuB7Ss
+8AbyvEXBcOfHbginUdqr4nwLD9e8qlVxRFbSHfbFRbuybZghke4y1pZzekkqbseT
+kahkWHxr6o1EGAjyIdjAq1IQxewW6yJ4rkHWsRvfv3sUQTqBU+wT180kdwC8AAv6
+q6TX4um0HGR46uJ+5SG8DYb00kRMckQtYpTuwuUmlAvNh/qLg2fVVMEiHBpcuIiV
+h7x8INuq94vc+tgxmr0bomIWIZljMQ7vp8ixABEBAAG0IE1pY2hhZWwgUm90aCA8
+bWRyb3RoQHV0ZXhhcy5lZHU+iQE4BBMBAgAiBQJSYUEPAhsDBgsJCAcDAgYVCAIJ
+CgsEFgIDAQIeAQIXgAAKCRAzU8nO8Qi1hAHFB/9XZo74FYIGrSY814qun2wWF1Ui
+wljt6pLrwJfpn5DQJmMRn6ZMAJxXb7S7NE1jVvo0E85m4tykjidWZvrFtTljDBiV
+WKA+xHT8ip5+cLIOr5ogwsR7ujC+Rk1u5nb8FIafo3G7V8raXYI6T7sfOCJ+wUUI
+s0A3Sw7P7GiAQLuafQ+jAUjg7S0REPNBvGamZ+tIAJxL7bAAACTWe4hZUGodXJuV
+Ofk7ic2p5SpeT0E6/Pd2JtAcQdsdpRB4x5M99neRtyEdZO/3SauoHzIoneRxml1Y
+rp4hr27Ggr8I9WMomU5E0IMz7HR3fRTQXVd5SsXKLsitUqeKHmTOLn1zuXtUtCFN
+aWNoYWVsIFJvdGggPGZsdWtzaHVuQGdtYWlsLmNvbT6JATgEEwECACIFAlJhQl4C
+GwMGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJEDNTyc7xCLWEj2cH/21MIyGv
+podSPX6e2y6sS0cvZ3rTNTm+qVq3VY2yJlHX8KVcvT6Su9s0yl9J5FdeIkQCqpo4
++U/ANDK4R7rcnHl/gEw21932lVESPMMKhxlLluAb054nrqdwpdjtxf+VZcTt4c4B
+zcF/K9po1LgZoOt6HJPxIC+tqYYQrsmrOZUtCJjgOXO6IkadrBmxoFNFxQ4qWB2u
+oZ+/HEtceOIb56qNfOj36MtEKVwpScYPAxaePd9lO7P4vlCOx6yIzO3MzEl+Aen7
+/NYKU8WwwRnshAlW4GTn2XbrEQeJx4HzSzI5r8xfMOH3JLh/ZVANBR7c5cw1MPe7
+1fAj5WzXrr/scJu0KE1pY2hhZWwgUm90aCA8bWRyb3RoQGxpbnV4LnZuZXQuaWJt
+LmNvbT6JATgEEwECACIFAlJhQjYCGwMGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheA
+AAoJEDNTyc7xCLWEltAH/37ADf0YFPrJd3gcZyGC/zvtPhYPZ/kxnqoahoBIRF/s
+ftGV5XqwwZOGm1Iws/VmTQ0PFBvU+Mw0vNT0HcreRT8PohtRlF+V8umHLVeL6x3C
+tmJfsfyYBxLoE5/DLyYqBvpCothLm40ND4O6lRdLF5CUScGhgD1IblvmYBs0Uz71
+tFnHmC+Ov3fNC8YkTNymaxnJGYlPtmwUZ7SWh1XRl8pMQzL+3B9Be6ecO3J5lbFm
+wL8XYawx0HtayvM5n9VbPy2eawAn++e7bLLywc39YyQ9/ckmSlZqtlUsEuij+h0T
+qmr9XY7K8WEHqBJXfl8txIm8DTOqq4dcx3j7k+qwQJC5AQ0EUmFBDwEIAJDxMtsu
+9ie8QN7eepcm+WuaY6Zbg3iDdPOOrQ4Ez+4oLaib5FHiZZjikdTsD7hlwcVuuhyE
+P2/bT9f29pbsrUVjHRgqJPdcuoOlUzAekgz17895Wh1gRarsbDIJDgs1878OSvIC
+/ek++qAWkzU4Sy8Psu9eJMTP6F0nPBOvet+iPwWDZO/dxrf+BnBb9wuBZnihpKMa
+v2gJox0iYrqpnFOFlK/XdSYnZNYpIyBin1e+K2CG+TzF2M+KmdZE7FMhnTz95est
+AG2kC37VIVkCq8yHNVZqsgyAfMqpB1ayQI2r3FUBM0Hxp6z2+8v/Ezp6zhYCI+Bi
+UC7VbrWSSuTlp4UAEQEAAYkBHwQYAQIACQUCUmFBDwIbDAAKCRAzU8nO8Qi1hKWY
+B/0R6ct3W2SEyoNuHTTKd5szIJigHYXrsqBa4XQGaVuFz7XZtcIbFFhEHjMrvTJp
+BWhuZ091Gp0AjV2ACNi2z+dSpXi16QxdFb1/4us6mFEm86UIu4tcNN1V3WPiODpW
+fFkEys/vmqQImLjfSsdxzhMdX7Yen1B3fxiKzwzsTlFbnNiBr2Mv7flDiUvMdbHm
+b/n0/B6a69SRYfVkJ3MZdl0gptJlXhJVdwjwVVl3bjvlQd0aZoLwJ7ntrWeMxOkb
+f8950vPVxemQ1frblB0zR98fuUNhX4cjrFTI9iJck7xLUwNZfgOz9PodfqUv4riM
+LczMmw3nwGZO/aJg0m6uWSWk
+=IvBA
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/debian/watch b/debian/watch
new file mode 100644
index 00000000..dd95c7d2
--- /dev/null
+++ b/debian/watch
@@ -0,0 +1,9 @@
+version=4
+
+opts=\
+dversionmangle=auto,\
+repacksuffix=+dfsg,\
+uversionmangle=s/-rc/~rc/;s/(\d+)\.(\d+)\.(\d+)/$1.$2/g,\
+pgpsigurlmangle=s/$/.sig/,\
+compression=xz \
+ https://download.qemu.org/ qemu-@ANY_VERSION@@ARCHIVE_EXT@