diff options
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, ¬ify); + + 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@ |