diff --git a/SOURCES/kvm-MAINTAINERS-split-out-s390x-sections.patch b/SOURCES/kvm-MAINTAINERS-split-out-s390x-sections.patch new file mode 100644 index 0000000..3d7381f --- /dev/null +++ b/SOURCES/kvm-MAINTAINERS-split-out-s390x-sections.patch @@ -0,0 +1,181 @@ +From 440ee491240f2f02f9a6082d8aad98d88c1039dd Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Mon, 15 Jan 2024 14:00:04 +0100 +Subject: [PATCH 1/5] MAINTAINERS: split out s390x sections +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Thomas Huth +RH-MergeRequest: 348: s390x: Provide some more useful information if decryption of a PV image fails +RH-Jira: RHEL-18214 +RH-Acked-by: Jon Maloy +RH-Acked-by: Cédric Le Goater +RH-Commit: [1/5] a71a3c11922481f97c36570e361088d17474e481 + +JIRA: https://issues.redhat.com/browse/RHEL-18214 + +commit 56e34834029c7c6862cb0095d95ad83c50485f88 +Author: Cornelia Huck +Date: Wed Dec 22 11:55:48 2021 +0100 + + MAINTAINERS: split out s390x sections + + Split out some more specialized devices etc., so that we can build + smarter lists of people to be put on cc: in the future. + + Signed-off-by: Cornelia Huck + Reviewed-by: Philippe Mathieu-Daudé + Acked-by: David Hildenbrand + Acked-by: Christian Borntraeger + Acked-by: Thomas Huth + Acked-by: Halil Pasic + Acked-by: Eric Farman + Message-Id: <20211222105548.356852-1-cohuck@redhat.com> + Signed-off-by: Thomas Huth + +Signed-off-by: Thomas Huth +--- + MAINTAINERS | 85 ++++++++++++++++++++++++++++++++++++++++++++++------- + 1 file changed, 74 insertions(+), 11 deletions(-) + +diff --git a/MAINTAINERS b/MAINTAINERS +index 7543eb4d59..b893206fc3 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -297,7 +297,6 @@ M: David Hildenbrand + S: Maintained + F: target/s390x/ + F: target/s390x/tcg +-F: target/s390x/cpu_models_*.[ch] + F: hw/s390x/ + F: disas/s390.c + F: tests/tcg/s390x/ +@@ -396,16 +395,10 @@ M: Halil Pasic + M: Christian Borntraeger + S: Supported + F: target/s390x/kvm/ +-F: target/s390x/ioinst.[ch] + F: target/s390x/machine.c + F: target/s390x/sigp.c +-F: target/s390x/cpu_features*.[ch] +-F: target/s390x/cpu_models.[ch] + F: hw/s390x/pv.c + F: include/hw/s390x/pv.h +-F: hw/intc/s390_flic.c +-F: hw/intc/s390_flic_kvm.c +-F: include/hw/s390x/s390_flic.h + F: gdb-xml/s390*.xml + T: git https://github.com/borntraeger/qemu.git s390-next + L: qemu-s390x@nongnu.org +@@ -1529,12 +1522,8 @@ S390 Virtio-ccw + M: Halil Pasic + M: Christian Borntraeger + S: Supported +-F: hw/char/sclp*.[hc] +-F: hw/char/terminal3270.c + F: hw/s390x/ + F: include/hw/s390x/ +-F: hw/watchdog/wdt_diag288.c +-F: include/hw/watchdog/wdt_diag288.h + F: configs/devices/s390x-softmmu/default.mak + F: tests/avocado/machine_s390_ccw_virtio.py + T: git https://github.com/borntraeger/qemu.git s390-next +@@ -1559,6 +1548,37 @@ F: hw/s390x/s390-pci* + F: include/hw/s390x/s390-pci* + L: qemu-s390x@nongnu.org + ++S390 channel subsystem ++M: Halil Pasic ++M: Christian Borntraeger ++S: Supported ++F: hw/s390x/ccw-device.[ch] ++F: hw/s390x/css.c ++F: hw/s390x/css-bridge.c ++F: include/hw/s390x/css.h ++F: include/hw/s390x/css-bridge.h ++F: include/hw/s390x/ioinst.h ++F: target/s390x/ioinst.c ++L: qemu-s390x@nongnu.org ++ ++S390 CPU models ++M: David Hildenbrand ++S: Maintained ++F: target/s390x/cpu_features*.[ch] ++F: target/s390x/cpu_models.[ch] ++L: qemu-s390x@nongnu.org ++ ++S390 SCLP-backed devices ++M: Halil Pasic ++M: Christian Borntraeger ++S: Supported ++F: include/hw/s390x/event-facility.h ++F: include/hw/s390x/sclp.h ++F: hw/char/sclp*.[hc] ++F: hw/s390x/event-facility.c ++F: hw/s390x/sclp*.c ++L: qemu-s390x@nongnu.org ++ + X86 Machines + ------------ + PC +@@ -1956,6 +1976,7 @@ M: Halil Pasic + S: Supported + F: hw/s390x/virtio-ccw*.[hc] + F: hw/s390x/vhost-vsock-ccw.c ++F: hw/s390x/vhost-user-fs-ccw.c + T: git https://gitlab.com/cohuck/qemu.git s390-next + T: git https://github.com/borntraeger/qemu.git s390-next + L: qemu-s390x@nongnu.org +@@ -2294,6 +2315,48 @@ F: hw/timer/mips_gictimer.c + F: include/hw/intc/mips_gic.h + F: include/hw/timer/mips_gictimer.h + ++S390 3270 device ++M: Halil Pasic ++M: Christian Borntraeger ++S: Odd fixes ++F: include/hw/s390x/3270-ccw.h ++F: hw/char/terminal3270.c ++F: hw/s390x/3270-ccw.c ++L: qemu-s390x@nongnu.org ++ ++S390 diag 288 watchdog ++M: Halil Pasic ++M: Christian Borntraeger ++S: Supported ++F: hw/watchdog/wdt_diag288.c ++F: include/hw/watchdog/wdt_diag288.h ++L: qemu-s390x@nongnu.org ++ ++S390 storage key device ++M: Halil Pasic ++M: Christian Borntraeger ++S: Supported ++F: hw/s390x/storage-keys.h ++F: hw/390x/s390-skeys*.c ++L: qemu-s390x@nongnu.org ++ ++S390 storage attribute device ++M: Halil Pasic ++M: Christian Borntraeger ++S: Supported ++F: hw/s390x/storage-attributes.h ++F: hw/s390/s390-stattrib*.c ++L: qemu-s390x@nongnu.org ++ ++S390 floating interrupt controller ++M: Halil Pasic ++M: Christian Borntraeger ++M: David Hildenbrand ++S: Supported ++F: hw/intc/s390_flic*.c ++F: include/hw/s390x/s390_flic.h ++L: qemu-s390x@nongnu.org ++ + Subsystems + ---------- + Overall Audio backends +-- +2.41.0 + diff --git a/SOURCES/kvm-RHEL-Enable-x-not-migrate-acpi-index-for-all-pre-RHE.patch b/SOURCES/kvm-RHEL-Enable-x-not-migrate-acpi-index-for-all-pre-RHE.patch new file mode 100644 index 0000000..77c08b6 --- /dev/null +++ b/SOURCES/kvm-RHEL-Enable-x-not-migrate-acpi-index-for-all-pre-RHE.patch @@ -0,0 +1,43 @@ +From f1480fe9a4054113ddacd218961e29f31c33d329 Mon Sep 17 00:00:00 2001 +From: Peter Xu +Date: Wed, 6 Sep 2023 16:29:23 -0400 +Subject: [PATCH 2/3] RHEL: Enable "x-not-migrate-acpi-index" for all pre-RHEL8 + guests +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Peter Xu +RH-MergeRequest: 343: acpi: fix acpi_index migration +RH-Jira: RHEL-20189 +RH-Acked-by: Leonardo Brás +RH-Acked-by: Igor Mammedov +RH-Acked-by: Prasad Pandit +RH-Commit: [2/2] 0a26a71236e68dd7feb5d2063254090e3852d6ba + +The acpi index migration is simply broken before for all pre-RHEL8 +branches. Don't migrate it for all of them. + +Signed-off-by: Peter Xu +--- + hw/core/machine.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/hw/core/machine.c b/hw/core/machine.c +index 2724f6848a..6650a3d7b7 100644 +--- a/hw/core/machine.c ++++ b/hw/core/machine.c +@@ -44,6 +44,10 @@ GlobalProperty hw_compat_rhel_8_6[] = { + * we need do disable it downstream on the latest hw_compat_rhel_8. + */ + { "vhost-vsock-device", "seqpacket", "off" }, ++ /* ++ * RHEL-2186: all rhel8 machines should not migrate acpi index. ++ */ ++ { "PIIX4_PM", "x-not-migrate-acpi-index", "on"}, + }; + const size_t hw_compat_rhel_8_6_len = G_N_ELEMENTS(hw_compat_rhel_8_6); + +-- +2.41.0 + diff --git a/SOURCES/kvm-acpi-fix-acpi_index-migration.patch b/SOURCES/kvm-acpi-fix-acpi_index-migration.patch new file mode 100644 index 0000000..6eb56ff --- /dev/null +++ b/SOURCES/kvm-acpi-fix-acpi_index-migration.patch @@ -0,0 +1,165 @@ +From 3deffc03c2e9b0053eec5aeb5b5d633dfe29f499 Mon Sep 17 00:00:00 2001 +From: "Dr. David Alan Gilbert" +Date: Wed, 6 Apr 2022 14:58:12 -0400 +Subject: [PATCH 1/3] acpi: fix acpi_index migration +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Peter Xu +RH-MergeRequest: 343: acpi: fix acpi_index migration +RH-Jira: RHEL-20189 +RH-Acked-by: Leonardo Brás +RH-Acked-by: Igor Mammedov +RH-Acked-by: Prasad Pandit +RH-Commit: [1/2] c5b9cdf5791cd856207b7df7e2ef5df360ec8de4 + +vmstate_acpi_pcihp_use_acpi_index() was expecting AcpiPciHpState +as state but it actually received PIIX4PMState, because +VMSTATE_PCI_HOTPLUG is a macro and not another struct. +So it ended up accessing random pointer, which resulted +in 'false' return value and acpi_index field wasn't ever +sent. + +However in 7.0 that pointer de-references to value > 0, and +destination QEMU starts to expect the field which isn't +sent in migratioon stream from older QEMU (6.2 and older). +As result migration fails with: + qemu-system-x86_64: Missing section footer for 0000:00:01.3/piix4_pm + qemu-system-x86_64: load of migration failed: Invalid argument + +In addition with QEMU-6.2, destination due to not expected +state, also never expects the acpi_index field in migration +stream. + +Q35 is not affected as it always sends/expects the field as +long as acpi based PCI hotplug is enabled. + +Fix issue by introducing compat knob to never send/expect +acpi_index in migration stream for 6.2 and older PC machine +types and always send it for 7.0 and newer PC machine types. + +Diagnosed-by: Dr. David Alan Gilbert +Fixes: b32bd76 ("pci: introduce acpi-index property for PCI device") +Resolves: https://gitlab.com/qemu-project/qemu/-/issues/932 +Signed-off-by: Igor Mammedov +Reviewed-by: Dr. David Alan Gilbert +Signed-off-by: Peter Maydell +(cherry picked from commit a83c2844903c45aa7d32cdd17305f23ce2c56ab9) +Signed-off-by: Peter Xu +--- + hw/acpi/acpi-pci-hotplug-stub.c | 4 ---- + hw/acpi/pcihp.c | 6 ------ + hw/acpi/piix4.c | 15 ++++++++++++++- + hw/core/machine.c | 5 +++++ + include/hw/acpi/pcihp.h | 2 -- + 5 files changed, 19 insertions(+), 13 deletions(-) + +diff --git a/hw/acpi/acpi-pci-hotplug-stub.c b/hw/acpi/acpi-pci-hotplug-stub.c +index 734e4c5986..a43f6dafc9 100644 +--- a/hw/acpi/acpi-pci-hotplug-stub.c ++++ b/hw/acpi/acpi-pci-hotplug-stub.c +@@ -41,7 +41,3 @@ void acpi_pcihp_reset(AcpiPciHpState *s, bool acpihp_root_off) + return; + } + +-bool vmstate_acpi_pcihp_use_acpi_index(void *opaque, int version_id) +-{ +- return false; +-} +diff --git a/hw/acpi/pcihp.c b/hw/acpi/pcihp.c +index be0e846b34..ec861661c3 100644 +--- a/hw/acpi/pcihp.c ++++ b/hw/acpi/pcihp.c +@@ -559,12 +559,6 @@ void acpi_pcihp_init(Object *owner, AcpiPciHpState *s, PCIBus *root_bus, + OBJ_PROP_FLAG_READ); + } + +-bool vmstate_acpi_pcihp_use_acpi_index(void *opaque, int version_id) +-{ +- AcpiPciHpState *s = opaque; +- return s->acpi_index; +-} +- + const VMStateDescription vmstate_acpi_pcihp_pci_status = { + .name = "acpi_pcihp_pci_status", + .version_id = 1, +diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c +index 8d6011c0a3..033e75ce5b 100644 +--- a/hw/acpi/piix4.c ++++ b/hw/acpi/piix4.c +@@ -82,6 +82,7 @@ struct PIIX4PMState { + AcpiPciHpState acpi_pci_hotplug; + bool use_acpi_hotplug_bridge; + bool use_acpi_root_pci_hotplug; ++ bool not_migrate_acpi_index; + + uint8_t disable_s3; + uint8_t disable_s4; +@@ -269,6 +270,16 @@ static bool piix4_vmstate_need_smbus(void *opaque, int version_id) + return pm_smbus_vmstate_needed(); + } + ++/* ++ * This is a fudge to turn off the acpi_index field, ++ * whose test was always broken on piix4 with 6.2 and older machine types. ++ */ ++static bool vmstate_test_migrate_acpi_index(void *opaque, int version_id) ++{ ++ PIIX4PMState *s = PIIX4_PM(opaque); ++ return s->use_acpi_hotplug_bridge && !s->not_migrate_acpi_index; ++} ++ + /* qemu-kvm 1.2 uses version 3 but advertised as 2 + * To support incoming qemu-kvm 1.2 migration, change version_id + * and minimum_version_id to 2 below (which breaks migration from +@@ -299,7 +310,7 @@ static const VMStateDescription vmstate_acpi = { + struct AcpiPciHpPciStatus), + VMSTATE_PCI_HOTPLUG(acpi_pci_hotplug, PIIX4PMState, + vmstate_test_use_acpi_hotplug_bridge, +- vmstate_acpi_pcihp_use_acpi_index), ++ vmstate_test_migrate_acpi_index), + VMSTATE_END_OF_LIST() + }, + .subsections = (const VMStateDescription*[]) { +@@ -654,6 +665,8 @@ static Property piix4_pm_properties[] = { + DEFINE_PROP_BOOL("memory-hotplug-support", PIIX4PMState, + acpi_memory_hotplug.is_enabled, true), + DEFINE_PROP_BOOL("smm-compat", PIIX4PMState, smm_compat, false), ++ DEFINE_PROP_BOOL("x-not-migrate-acpi-index", PIIX4PMState, ++ not_migrate_acpi_index, false), + DEFINE_PROP_END_OF_LIST(), + }; + +diff --git a/hw/core/machine.c b/hw/core/machine.c +index 76fcabec7a..2724f6848a 100644 +--- a/hw/core/machine.c ++++ b/hw/core/machine.c +@@ -331,6 +331,11 @@ GlobalProperty hw_compat_rhel_7_1[] = { + }; + const size_t hw_compat_rhel_7_1_len = G_N_ELEMENTS(hw_compat_rhel_7_1); + ++GlobalProperty hw_compat_6_2[] = { ++ { "PIIX4_PM", "x-not-migrate-acpi-index", "on"}, ++}; ++const size_t hw_compat_6_2_len = G_N_ELEMENTS(hw_compat_6_2); ++ + GlobalProperty hw_compat_6_1[] = { + { "vhost-user-vsock-device", "seqpacket", "off" }, + { "nvme-ns", "shared", "off" }, +diff --git a/include/hw/acpi/pcihp.h b/include/hw/acpi/pcihp.h +index af1a169fc3..7e268c2c9c 100644 +--- a/include/hw/acpi/pcihp.h ++++ b/include/hw/acpi/pcihp.h +@@ -73,8 +73,6 @@ void acpi_pcihp_reset(AcpiPciHpState *s, bool acpihp_root_off); + + extern const VMStateDescription vmstate_acpi_pcihp_pci_status; + +-bool vmstate_acpi_pcihp_use_acpi_index(void *opaque, int version_id); +- + #define VMSTATE_PCI_HOTPLUG(pcihp, state, test_pcihp, test_acpi_index) \ + VMSTATE_UINT32_TEST(pcihp.hotplug_select, state, \ + test_pcihp), \ +-- +2.41.0 + diff --git a/SOURCES/kvm-dump-Add-arch-cleanup-function.patch b/SOURCES/kvm-dump-Add-arch-cleanup-function.patch new file mode 100644 index 0000000..ace908b --- /dev/null +++ b/SOURCES/kvm-dump-Add-arch-cleanup-function.patch @@ -0,0 +1,69 @@ +From 837e09b1a8a38b53488f59aad090fbe6bb94e257 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 17 Nov 2023 11:32:37 +0100 +Subject: [PATCH 2/3] dump: Add arch cleanup function +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Thomas Huth +RH-MergeRequest: 323: Fix problem that secure execution guest might remain in "paused" state after failed dump +RH-Jira: RHEL-16696 +RH-Acked-by: Marc-André Lureau +RH-Acked-by: Cédric Le Goater +RH-Commit: [2/3] b70f406dec88ffd4877f3d5d580fc8f821bdb252 + +JIRA: https://issues.redhat.com/browse/RHEL-16696 + +commit e72629e5149aba6f44122ea6d2a803ef136a0c6b +Author: Janosch Frank +Date: Thu Nov 9 12:04:42 2023 +0000 + + dump: Add arch cleanup function + + Some architectures (s390x) need to cleanup after a failed dump to be + able to continue to run the vm. Add a cleanup function pointer and + call it if it's set. + + Signed-off-by: Janosch Frank + Reviewed-by: Thomas Huth + Reviewed-by: Marc-André Lureau + Message-ID: <20231109120443.185979-3-frankja@linux.ibm.com> + Signed-off-by: Thomas Huth + +Signed-off-by: Thomas Huth +--- + dump/dump.c | 4 ++++ + include/sysemu/dump-arch.h | 1 + + 2 files changed, 5 insertions(+) + +diff --git a/dump/dump.c b/dump/dump.c +index 5dee060b73..93edb89547 100644 +--- a/dump/dump.c ++++ b/dump/dump.c +@@ -100,6 +100,10 @@ uint64_t cpu_to_dump64(DumpState *s, uint64_t val) + + static int dump_cleanup(DumpState *s) + { ++ if (s->dump_info.arch_cleanup_fn) { ++ s->dump_info.arch_cleanup_fn(s); ++ } ++ + guest_phys_blocks_free(&s->guest_phys_blocks); + memory_mapping_list_free(&s->list); + close(s->fd); +diff --git a/include/sysemu/dump-arch.h b/include/sysemu/dump-arch.h +index 59bbc9be38..743916e46c 100644 +--- a/include/sysemu/dump-arch.h ++++ b/include/sysemu/dump-arch.h +@@ -24,6 +24,7 @@ typedef struct ArchDumpInfo { + void (*arch_sections_add_fn)(DumpState *s); + uint64_t (*arch_sections_write_hdr_fn)(DumpState *s, uint8_t *buff); + int (*arch_sections_write_fn)(DumpState *s, uint8_t *buff); ++ void (*arch_cleanup_fn)(DumpState *s); + } ArchDumpInfo; + + struct GuestPhysBlockList; /* memory_mapping.h */ +-- +2.39.3 + diff --git a/SOURCES/kvm-hw-arm-virt-Do-not-load-efi-virtio.rom-for-all-virti.patch b/SOURCES/kvm-hw-arm-virt-Do-not-load-efi-virtio.rom-for-all-virti.patch new file mode 100644 index 0000000..a57cf8d --- /dev/null +++ b/SOURCES/kvm-hw-arm-virt-Do-not-load-efi-virtio.rom-for-all-virti.patch @@ -0,0 +1,119 @@ +From 4f6f881de10e31cac4636d5fde4b7ed4c8affadb Mon Sep 17 00:00:00 2001 +From: Eric Auger +Date: Thu, 4 Jan 2024 12:02:31 +0100 +Subject: [PATCH 3/3] hw/arm/virt: Do not load efi-virtio.rom for all + virtio-net-pci variants + +RH-Author: Eric Auger +RH-MergeRequest: 344: hw/arm/virt: Do not load efi-virtio.rom for any virtio-net-pci variants +RH-Jira: RHEL-14870 +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Sebastian Ott +RH-Commit: [1/1] ffeaa78ad0a1cff5b49009dfb32d25e5cadc0e05 + +Upstream: RHEL-only +Brew: http://brewweb.engineering.redhat.com/brew/taskinfo?taskID=5785640 + +Currently arm_rhel_compat just sets the romfile to "" for +virtio-net-pci and not for transitional and non transitional +variants. However, on aarch64 RHEL, efi-virtio.rom is not +shipped so transitional and non-transitional variants cannot +be used and the following error is obeserved: + +"Could not open option rom 'efi-virtio.rom': No such file or directory" + +In practice, we do not need any rom file for those virtio-net-pci +variants either because edk2 already brings the full functionality. + +So let's change the applied compat to cover all the variants. While +at it also change the way arm_rhel_compat is applied. Instead of +applying it from the latest _virt_options(), which is error prone +when upgrading the machine type, let's apply it before calling +*virt_options in the non abstract machine class. That way the setting +will apply to any machine type without any need to add it in any +future machine types. + +We don't really care keeping non void romfiles for transitional and +non transitional devices on previous machine types because this +was not working anyway. + +Signed-off-by: Eric Auger +--- + hw/arm/virt.c | 42 ++++++++++++++++++++++++++++-------------- + 1 file changed, 28 insertions(+), 14 deletions(-) + +diff --git a/hw/arm/virt.c b/hw/arm/virt.c +index dbf0a6d62f..46c72a9611 100644 +--- a/hw/arm/virt.c ++++ b/hw/arm/virt.c +@@ -108,11 +108,39 @@ + DEFINE_VIRT_MACHINE_LATEST(major, minor, false) + #endif /* disabled for RHEL */ + ++/* ++ * This variable is for changes to properties that are RHEL specific, ++ * different to the current upstream and to be applied to the latest ++ * machine type. They may be overriden by older machine compats. ++ * ++ * virtio-net-pci variant romfiles are not needed because edk2 does ++ * fully support the pxe boot. Besides virtio romfiles are not shipped ++ * on rhel/aarch64. ++ */ ++GlobalProperty arm_rhel_compat[] = { ++ {"virtio-net-pci", "romfile", "" }, ++ {"virtio-net-pci-transitional", "romfile", "" }, ++ {"virtio-net-pci-non-transitional", "romfile", "" }, ++}; ++const size_t arm_rhel_compat_len = G_N_ELEMENTS(arm_rhel_compat); ++ ++/* ++ * This cannot be called from the rhel_virt_class_init() because ++ * TYPE_RHEL_MACHINE is abstract and mc->compat_props g_ptr_array_new() ++ * only is called on virt-rhelm.n.s non abstract class init. ++ */ ++static void arm_rhel_compat_set(MachineClass *mc) ++{ ++ compat_props_add(mc->compat_props, arm_rhel_compat, ++ arm_rhel_compat_len); ++} ++ + #define DEFINE_RHEL_MACHINE_LATEST(m, n, s, latest) \ + static void rhel##m##n##s##_virt_class_init(ObjectClass *oc, \ + void *data) \ + { \ + MachineClass *mc = MACHINE_CLASS(oc); \ ++ arm_rhel_compat_set(mc); \ + rhel##m##n##s##_virt_options(mc); \ + mc->desc = "RHEL " # m "." # n "." # s " ARM Virtual Machine"; \ + if (latest) { \ +@@ -136,19 +164,6 @@ + #define DEFINE_RHEL_MACHINE(major, minor, subminor) \ + DEFINE_RHEL_MACHINE_LATEST(major, minor, subminor, false) + +-/* This variable is for changes to properties that are RHEL specific, +- * different to the current upstream and to be applied to the latest +- * machine type. +- */ +-GlobalProperty arm_rhel_compat[] = { +- { +- .driver = "virtio-net-pci", +- .property = "romfile", +- .value = "", +- }, +-}; +-const size_t arm_rhel_compat_len = G_N_ELEMENTS(arm_rhel_compat); +- + /* Number of external interrupt lines to configure the GIC with */ + #define NUM_IRQS 256 + +@@ -3240,7 +3255,6 @@ type_init(rhel_machine_init); + + static void rhel860_virt_options(MachineClass *mc) + { +- compat_props_add(mc->compat_props, arm_rhel_compat, arm_rhel_compat_len); + } + DEFINE_RHEL_MACHINE_AS_LATEST(8, 6, 0) + +-- +2.41.0 + diff --git a/SOURCES/kvm-hw-ide-reset-cancel-async-DMA-operation-before-reset.patch b/SOURCES/kvm-hw-ide-reset-cancel-async-DMA-operation-before-reset.patch new file mode 100644 index 0000000..005d682 --- /dev/null +++ b/SOURCES/kvm-hw-ide-reset-cancel-async-DMA-operation-before-reset.patch @@ -0,0 +1,128 @@ +From 2308abf0c5da2fe35a0721318c31d22e077663c2 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Fri, 24 Nov 2023 12:17:11 -0500 +Subject: [PATCH 1/2] hw/ide: reset: cancel async DMA operation before + resetting state +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Jon Maloy +RH-MergeRequest: 335: hw/ide: reset: cancel async DMA operation before resetting state +RH-Jira: RHEL-15437 +RH-Acked-by: Hanna Czenczek +RH-Acked-by: Paolo Bonzini +RH-Commit: [1/2] b0f5f7f888559a210f1c6b3c545e337dbbc9cf22 (redhat/rhel/src/qemu-kvm/jons-qemu-kvm-2) + +JIRA: https://issues.redhat.com/browse/RHEL-15437 +CVE: CVE-2023-5088 +Upstream: Merged + +commit 7d7512019fc40c577e2bdd61f114f31a9eb84a8e +Author: Fiona Ebner +Date: Wed Sep 6 15:09:21 2023 +0200 + + hw/ide: reset: cancel async DMA operation before resetting state + + If there is a pending DMA operation during ide_bus_reset(), the fact + that the IDEState is already reset before the operation is canceled + can be problematic. In particular, ide_dma_cb() might be called and + then use the reset IDEState which contains the signature after the + reset. When used to construct the IO operation this leads to + ide_get_sector() returning 0 and nsector being 1. This is particularly + bad, because a write command will thus destroy the first sector which + often contains a partition table or similar. + + Traces showing the unsolicited write happening with IDEState + 0x5595af6949d0 being used after reset: + + > ahci_port_write ahci(0x5595af6923f0)[0]: port write [reg:PxSCTL] @ 0x2c: 0x00000300 + > ahci_reset_port ahci(0x5595af6923f0)[0]: reset port + > ide_reset IDEstate 0x5595af6949d0 + > ide_reset IDEstate 0x5595af694da8 + > ide_bus_reset_aio aio_cancel + > dma_aio_cancel dbs=0x7f64600089a0 + > dma_blk_cb dbs=0x7f64600089a0 ret=0 + > dma_complete dbs=0x7f64600089a0 ret=0 cb=0x5595acd40b30 + > ahci_populate_sglist ahci(0x5595af6923f0)[0] + > ahci_dma_prepare_buf ahci(0x5595af6923f0)[0]: prepare buf limit=512 prepared=512 + > ide_dma_cb IDEState 0x5595af6949d0; sector_num=0 n=1 cmd=DMA WRITE + > dma_blk_io dbs=0x7f6420802010 bs=0x5595ae2c6c30 offset=0 to_dev=1 + > dma_blk_cb dbs=0x7f6420802010 ret=0 + + > (gdb) p *qiov + > $11 = {iov = 0x7f647c76d840, niov = 1, {{nalloc = 1, local_iov = {iov_base = 0x0, + > iov_len = 512}}, {__pad = "\001\000\000\000\000\000\000\000\000\000\000", + > size = 512}}} + > (gdb) bt + > #0 blk_aio_pwritev (blk=0x5595ae2c6c30, offset=0, qiov=0x7f6420802070, flags=0, + > cb=0x5595ace6f0b0 , opaque=0x7f6420802010) + > at ../block/block-backend.c:1682 + > #1 0x00005595ace6f185 in dma_blk_cb (opaque=0x7f6420802010, ret=) + > at ../softmmu/dma-helpers.c:179 + > #2 0x00005595ace6f778 in dma_blk_io (ctx=0x5595ae0609f0, + > sg=sg@entry=0x5595af694d00, offset=offset@entry=0, align=align@entry=512, + > io_func=io_func@entry=0x5595ace6ee30 , + > io_func_opaque=io_func_opaque@entry=0x5595ae2c6c30, + > cb=0x5595acd40b30 , opaque=0x5595af6949d0, + > dir=DMA_DIRECTION_TO_DEVICE) at ../softmmu/dma-helpers.c:244 + > #3 0x00005595ace6f90a in dma_blk_write (blk=0x5595ae2c6c30, + > sg=sg@entry=0x5595af694d00, offset=offset@entry=0, align=align@entry=512, + > cb=cb@entry=0x5595acd40b30 , opaque=opaque@entry=0x5595af6949d0) + > at ../softmmu/dma-helpers.c:280 + > #4 0x00005595acd40e18 in ide_dma_cb (opaque=0x5595af6949d0, ret=) + > at ../hw/ide/core.c:953 + > #5 0x00005595ace6f319 in dma_complete (ret=0, dbs=0x7f64600089a0) + > at ../softmmu/dma-helpers.c:107 + > #6 dma_blk_cb (opaque=0x7f64600089a0, ret=0) at ../softmmu/dma-helpers.c:127 + > #7 0x00005595ad12227d in blk_aio_complete (acb=0x7f6460005b10) + > at ../block/block-backend.c:1527 + > #8 blk_aio_complete (acb=0x7f6460005b10) at ../block/block-backend.c:1524 + > #9 blk_aio_write_entry (opaque=0x7f6460005b10) at ../block/block-backend.c:1594 + > #10 0x00005595ad258cfb in coroutine_trampoline (i0=, + > i1=) at ../util/coroutine-ucontext.c:177 + + Signed-off-by: Fiona Ebner + Reviewed-by: Philippe Mathieu-Daudé + Tested-by: simon.rowe@nutanix.com + Message-ID: <20230906130922.142845-1-f.ebner@proxmox.com> + +Signed-off-by: Jon Maloy +--- + hw/ide/core.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/hw/ide/core.c b/hw/ide/core.c +index 05a32d0a99..fd50c123e8 100644 +--- a/hw/ide/core.c ++++ b/hw/ide/core.c +@@ -2456,19 +2456,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); +-- +2.41.0 + diff --git a/SOURCES/kvm-hw-s390x-Move-KVM-specific-PV-from-hw-to-target-s390.patch b/SOURCES/kvm-hw-s390x-Move-KVM-specific-PV-from-hw-to-target-s390.patch new file mode 100644 index 0000000..7d4135f --- /dev/null +++ b/SOURCES/kvm-hw-s390x-Move-KVM-specific-PV-from-hw-to-target-s390.patch @@ -0,0 +1,283 @@ +From 59f02a421ecdba6e856597367020926fc0cb5177 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Mon, 15 Jan 2024 18:52:30 +0100 +Subject: [PATCH 4/5] hw/s390x: Move KVM specific PV from hw/ to + target/s390x/kvm/ +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Thomas Huth +RH-MergeRequest: 348: s390x: Provide some more useful information if decryption of a PV image fails +RH-Jira: RHEL-18214 +RH-Acked-by: Jon Maloy +RH-Acked-by: Cédric Le Goater +RH-Commit: [4/5] f6095bfdb89268007a0741665284955db4752d46 + +JIRA: https://issues.redhat.com/browse/RHEL-18214 + +commit f5f9c6ea11bc807664fdeb9354915c2c9cdcbd89 +Author: Philippe Mathieu-Daudé +Date: Sat Jun 24 22:06:44 2023 +0200 + + hw/s390x: Move KVM specific PV from hw/ to target/s390x/kvm/ + + Protected Virtualization (PV) is not a real hardware device: + it is a feature of the firmware on s390x that is exposed to + userspace via the KVM interface. + + Move the pv.c/pv.h files to target/s390x/kvm/ to make this clearer. + + Suggested-by: Thomas Huth + Signed-off-by: Philippe Mathieu-Daudé + Message-Id: <20230624200644.23931-1-philmd@linaro.org> + Signed-off-by: Thomas Huth + +Conflicts: + hw/s390x/ipl.c + hw/s390x/s390-virtio-ccw.c + target/s390x/diag.c + (simple contextual conflict due to differce with #include statements) +Signed-off-by: Thomas Huth +--- + MAINTAINERS | 2 -- + hw/s390x/ipl.c | 2 +- + hw/s390x/meson.build | 1 - + hw/s390x/s390-pci-kvm.c | 2 +- + hw/s390x/s390-virtio-ccw.c | 2 +- + hw/s390x/tod-kvm.c | 2 +- + target/s390x/arch_dump.c | 2 +- + target/s390x/cpu-sysemu.c | 2 +- + target/s390x/cpu_features.c | 2 +- + target/s390x/cpu_models.c | 2 +- + target/s390x/diag.c | 2 +- + target/s390x/helper.c | 2 +- + target/s390x/ioinst.c | 2 +- + target/s390x/kvm/kvm.c | 2 +- + target/s390x/kvm/meson.build | 1 + + {hw/s390x => target/s390x/kvm}/pv.c | 2 +- + {include/hw/s390x => target/s390x/kvm}/pv.h | 0 + 17 files changed, 14 insertions(+), 16 deletions(-) + rename {hw/s390x => target/s390x/kvm}/pv.c (99%) + rename {include/hw/s390x => target/s390x/kvm}/pv.h (100%) + +diff --git a/MAINTAINERS b/MAINTAINERS +index b893206fc3..d74ca51154 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -397,8 +397,6 @@ S: Supported + F: target/s390x/kvm/ + F: target/s390x/machine.c + F: target/s390x/sigp.c +-F: hw/s390x/pv.c +-F: include/hw/s390x/pv.h + F: gdb-xml/s390*.xml + T: git https://github.com/borntraeger/qemu.git s390-next + L: qemu-s390x@nongnu.org +diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c +index 9051d8652d..c25e247426 100644 +--- a/hw/s390x/ipl.c ++++ b/hw/s390x/ipl.c +@@ -27,7 +27,7 @@ + #include "hw/s390x/vfio-ccw.h" + #include "hw/s390x/css.h" + #include "hw/s390x/ebcdic.h" +-#include "hw/s390x/pv.h" ++#include "target/s390x/kvm/pv.h" + #include "ipl.h" + #include "qemu/error-report.h" + #include "qemu/config-file.h" +diff --git a/hw/s390x/meson.build b/hw/s390x/meson.build +index 6e6e47fcda..bb3b42f613 100644 +--- a/hw/s390x/meson.build ++++ b/hw/s390x/meson.build +@@ -22,7 +22,6 @@ s390x_ss.add(when: 'CONFIG_KVM', if_true: files( + 'tod-kvm.c', + 's390-skeys-kvm.c', + 's390-stattrib-kvm.c', +- 'pv.c', + 's390-pci-kvm.c', + )) + s390x_ss.add(when: 'CONFIG_TCG', if_true: files( +diff --git a/hw/s390x/s390-pci-kvm.c b/hw/s390x/s390-pci-kvm.c +index 9134fe185f..ff41e4106d 100644 +--- a/hw/s390x/s390-pci-kvm.c ++++ b/hw/s390x/s390-pci-kvm.c +@@ -14,7 +14,7 @@ + #include + + #include "kvm/kvm_s390x.h" +-#include "hw/s390x/pv.h" ++#include "target/s390x/kvm/pv.h" + #include "hw/s390x/s390-pci-bus.h" + #include "hw/s390x/s390-pci-kvm.h" + #include "hw/s390x/s390-pci-inst.h" +diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c +index 17146469ee..7bfa5b4e8f 100644 +--- a/hw/s390x/s390-virtio-ccw.c ++++ b/hw/s390x/s390-virtio-ccw.c +@@ -40,7 +40,7 @@ + #include "hw/qdev-properties.h" + #include "hw/s390x/tod.h" + #include "sysemu/sysemu.h" +-#include "hw/s390x/pv.h" ++#include "target/s390x/kvm/pv.h" + #include "migration/blocker.h" + #include "qapi/visitor.h" + +diff --git a/hw/s390x/tod-kvm.c b/hw/s390x/tod-kvm.c +index c804c979b5..9776cda50a 100644 +--- a/hw/s390x/tod-kvm.c ++++ b/hw/s390x/tod-kvm.c +@@ -13,7 +13,7 @@ + #include "qemu/module.h" + #include "sysemu/runstate.h" + #include "hw/s390x/tod.h" +-#include "hw/s390x/pv.h" ++#include "target/s390x/kvm/pv.h" + #include "kvm/kvm_s390x.h" + + static void kvm_s390_get_tod_raw(S390TOD *tod, Error **errp) +diff --git a/target/s390x/arch_dump.c b/target/s390x/arch_dump.c +index 3b1f178dc3..2554238c16 100644 +--- a/target/s390x/arch_dump.c ++++ b/target/s390x/arch_dump.c +@@ -17,8 +17,8 @@ + #include "s390x-internal.h" + #include "elf.h" + #include "sysemu/dump.h" +-#include "hw/s390x/pv.h" + #include "kvm/kvm_s390x.h" ++#include "target/s390x/kvm/pv.h" + + struct S390xUserRegsStruct { + uint64_t psw[2]; +diff --git a/target/s390x/cpu-sysemu.c b/target/s390x/cpu-sysemu.c +index 5471e01ee8..547287a949 100644 +--- a/target/s390x/cpu-sysemu.c ++++ b/target/s390x/cpu-sysemu.c +@@ -32,7 +32,7 @@ + #include "qapi/qapi-visit-run-state.h" + #include "sysemu/hw_accel.h" + +-#include "hw/s390x/pv.h" ++#include "target/s390x/kvm/pv.h" + #include "hw/boards.h" + #include "sysemu/sysemu.h" + #include "sysemu/tcg.h" +diff --git a/target/s390x/cpu_features.c b/target/s390x/cpu_features.c +index 2e4e11d264..ebb155ce1c 100644 +--- a/target/s390x/cpu_features.c ++++ b/target/s390x/cpu_features.c +@@ -15,7 +15,7 @@ + #include "qemu/module.h" + #include "cpu_features.h" + #ifndef CONFIG_USER_ONLY +-#include "hw/s390x/pv.h" ++#include "target/s390x/kvm/pv.h" + #endif + + #define DEF_FEAT(_FEAT, _NAME, _TYPE, _BIT, _DESC) \ +diff --git a/target/s390x/cpu_models.c b/target/s390x/cpu_models.c +index e7c586c76e..100c5e7b3a 100644 +--- a/target/s390x/cpu_models.c ++++ b/target/s390x/cpu_models.c +@@ -22,7 +22,7 @@ + #include "qemu/qemu-print.h" + #ifndef CONFIG_USER_ONLY + #include "sysemu/sysemu.h" +-#include "hw/s390x/pv.h" ++#include "target/s390x/kvm/pv.h" + #endif + + #define CPUDEF_INIT(_type, _gen, _ec_ga, _mha_pow, _hmfai, _name, _desc) \ +diff --git a/target/s390x/diag.c b/target/s390x/diag.c +index 76b01dcd68..7c8714cc27 100644 +--- a/target/s390x/diag.c ++++ b/target/s390x/diag.c +@@ -19,9 +19,9 @@ + #include "sysemu/cpus.h" + #include "hw/s390x/ipl.h" + #include "hw/s390x/s390-virtio-ccw.h" +-#include "hw/s390x/pv.h" + #include "sysemu/kvm.h" + #include "kvm/kvm_s390x.h" ++#include "target/s390x/kvm/pv.h" + + int handle_diag_288(CPUS390XState *env, uint64_t r1, uint64_t r3) + { +diff --git a/target/s390x/helper.c b/target/s390x/helper.c +index 6e35473c7f..860977126a 100644 +--- a/target/s390x/helper.c ++++ b/target/s390x/helper.c +@@ -24,7 +24,7 @@ + #include "exec/gdbstub.h" + #include "qemu/timer.h" + #include "hw/s390x/ioinst.h" +-#include "hw/s390x/pv.h" ++#include "target/s390x/kvm/pv.h" + #include "sysemu/hw_accel.h" + #include "sysemu/runstate.h" + #include "sysemu/tcg.h" +diff --git a/target/s390x/ioinst.c b/target/s390x/ioinst.c +index bdae5090bc..409f3e3e63 100644 +--- a/target/s390x/ioinst.c ++++ b/target/s390x/ioinst.c +@@ -16,7 +16,7 @@ + #include "hw/s390x/ioinst.h" + #include "trace.h" + #include "hw/s390x/s390-pci-bus.h" +-#include "hw/s390x/pv.h" ++#include "target/s390x/kvm/pv.h" + + /* All I/O instructions but chsc use the s format */ + static uint64_t get_address_from_regs(CPUS390XState *env, uint32_t ipb, +diff --git a/target/s390x/kvm/kvm.c b/target/s390x/kvm/kvm.c +index a963866ef4..6d1a6324b9 100644 +--- a/target/s390x/kvm/kvm.c ++++ b/target/s390x/kvm/kvm.c +@@ -51,7 +51,7 @@ + #include "exec/memattrs.h" + #include "hw/s390x/s390-virtio-ccw.h" + #include "hw/s390x/s390-virtio-hcall.h" +-#include "hw/s390x/pv.h" ++#include "target/s390x/kvm/pv.h" + + #ifndef DEBUG_KVM + #define DEBUG_KVM 0 +diff --git a/target/s390x/kvm/meson.build b/target/s390x/kvm/meson.build +index aef52b6686..739d5b9f54 100644 +--- a/target/s390x/kvm/meson.build ++++ b/target/s390x/kvm/meson.build +@@ -1,5 +1,6 @@ + + s390x_ss.add(when: 'CONFIG_KVM', if_true: files( ++ 'pv.c', + 'kvm.c' + ), if_false: files( + 'stubs.c' +diff --git a/hw/s390x/pv.c b/target/s390x/kvm/pv.c +similarity index 99% +rename from hw/s390x/pv.c +rename to target/s390x/kvm/pv.c +index 8a1c71436b..e14db4f41a 100644 +--- a/hw/s390x/pv.c ++++ b/target/s390x/kvm/pv.c +@@ -19,9 +19,9 @@ + #include "qom/object_interfaces.h" + #include "exec/confidential-guest-support.h" + #include "hw/s390x/ipl.h" +-#include "hw/s390x/pv.h" + #include "hw/s390x/sclp.h" + #include "target/s390x/kvm/kvm_s390x.h" ++#include "target/s390x/kvm/pv.h" + + static bool info_valid; + static struct kvm_s390_pv_info_vm info_vm; +diff --git a/include/hw/s390x/pv.h b/target/s390x/kvm/pv.h +similarity index 100% +rename from include/hw/s390x/pv.h +rename to target/s390x/kvm/pv.h +-- +2.41.0 + diff --git a/SOURCES/kvm-hw-s390x-pv-Restrict-Protected-Virtualization-to-sys.patch b/SOURCES/kvm-hw-s390x-pv-Restrict-Protected-Virtualization-to-sys.patch new file mode 100644 index 0000000..f0f39fa --- /dev/null +++ b/SOURCES/kvm-hw-s390x-pv-Restrict-Protected-Virtualization-to-sys.patch @@ -0,0 +1,100 @@ +From 053faafcf523b0ea4d841c0af8e7e26a2cddd5e8 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Mon, 15 Jan 2024 14:00:04 +0100 +Subject: [PATCH 3/5] hw/s390x/pv: Restrict Protected Virtualization to sysemu +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Thomas Huth +RH-MergeRequest: 348: s390x: Provide some more useful information if decryption of a PV image fails +RH-Jira: RHEL-18214 +RH-Acked-by: Jon Maloy +RH-Acked-by: Cédric Le Goater +RH-Commit: [3/5] 17b11f9fd2b53c7d33c09a62f28cfca19b18e798 + +JIRA: https://issues.redhat.com/browse/RHEL-18214 + +commit 3ea7e312671686e616efa1b8caa5f5ce2d06543a +Author: Philippe Mathieu-Daudé +Date: Sat Dec 17 16:24:52 2022 +0100 + + hw/s390x/pv: Restrict Protected Virtualization to sysemu + + Protected Virtualization is irrelevant in user emulation. + + Signed-off-by: Philippe Mathieu-Daudé + Message-Id: <20221217152454.96388-4-philmd@linaro.org> + Reviewed-by: Thomas Huth + Reviewed-by: Richard Henderson + Signed-off-by: Thomas Huth + +Signed-off-by: Thomas Huth +--- + target/s390x/cpu_features.c | 4 ++++ + target/s390x/cpu_models.c | 4 +++- + 2 files changed, 7 insertions(+), 1 deletion(-) + +diff --git a/target/s390x/cpu_features.c b/target/s390x/cpu_features.c +index 5528acd082..2e4e11d264 100644 +--- a/target/s390x/cpu_features.c ++++ b/target/s390x/cpu_features.c +@@ -14,7 +14,9 @@ + #include "qemu/osdep.h" + #include "qemu/module.h" + #include "cpu_features.h" ++#ifndef CONFIG_USER_ONLY + #include "hw/s390x/pv.h" ++#endif + + #define DEF_FEAT(_FEAT, _NAME, _TYPE, _BIT, _DESC) \ + [S390_FEAT_##_FEAT] = { \ +@@ -107,6 +109,7 @@ void s390_fill_feat_block(const S390FeatBitmap features, S390FeatType type, + feat = find_next_bit(features, S390_FEAT_MAX, feat + 1); + } + ++#ifndef CONFIG_USER_ONLY + if (!s390_is_pv()) { + return; + } +@@ -147,6 +150,7 @@ void s390_fill_feat_block(const S390FeatBitmap features, S390FeatType type, + default: + return; + } ++#endif + } + + void s390_add_from_feat_block(S390FeatBitmap features, S390FeatType type, +diff --git a/target/s390x/cpu_models.c b/target/s390x/cpu_models.c +index 454485e706..e7c586c76e 100644 +--- a/target/s390x/cpu_models.c ++++ b/target/s390x/cpu_models.c +@@ -22,8 +22,8 @@ + #include "qemu/qemu-print.h" + #ifndef CONFIG_USER_ONLY + #include "sysemu/sysemu.h" +-#endif + #include "hw/s390x/pv.h" ++#endif + + #define CPUDEF_INIT(_type, _gen, _ec_ga, _mha_pow, _hmfai, _name, _desc) \ + { \ +@@ -236,6 +236,7 @@ bool s390_has_feat(S390Feat feat) + return 0; + } + ++#ifndef CONFIG_USER_ONLY + if (s390_is_pv()) { + switch (feat) { + case S390_FEAT_DIAG_318: +@@ -259,6 +260,7 @@ bool s390_has_feat(S390Feat feat) + break; + } + } ++#endif + return test_bit(feat, cpu->model->features); + } + +-- +2.41.0 + diff --git a/SOURCES/kvm-iotests-Make-144-deterministic-again.patch b/SOURCES/kvm-iotests-Make-144-deterministic-again.patch new file mode 100644 index 0000000..a7fef5a --- /dev/null +++ b/SOURCES/kvm-iotests-Make-144-deterministic-again.patch @@ -0,0 +1,82 @@ +From 9b5e69ce5f4ba9541e55d801af16ece4969379e9 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Fri, 9 Feb 2024 18:31:03 +0100 +Subject: [PATCH 4/4] iotests: Make 144 deterministic again + +RH-Author: Stefan Hajnoczi +RH-MergeRequest: 352: monitor: only run coroutine commands in qemu_aio_context +RH-Jira: RHEL-7353 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Hanna Czenczek +RH-Commit: [4/4] 4974a32174abefb509b7c46671a364b4b991449e + +Since commit effd60c8 changed how QMP commands are processed, the order +of the block-commit return value and job events in iotests 144 wasn't +fixed and more and caused the test to fail intermittently. + +Change the test to cache events first and then print them in a +predefined order. + +Waiting three times for JOB_STATUS_CHANGE is a bit uglier than just +waiting for the JOB_STATUS_CHANGE that has "status": "ready", but the +tooling we have doesn't seem to allow the latter easily. + +Fixes: effd60c878176bcaf97fa7ce2b12d04bb8ead6f7 +Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2126 +Signed-off-by: Kevin Wolf +Reviewed-by: Stefan Hajnoczi +Message-id: 20240209173103.239994-1-kwolf@redhat.com +Signed-off-by: Peter Maydell +(cherry picked from commit cc29c12ec629ba68a4a6cb7d165c94cc8502815a) +Signed-off-by: Stefan Hajnoczi +--- + tests/qemu-iotests/144 | 12 +++++++++++- + tests/qemu-iotests/144.out | 2 +- + 2 files changed, 12 insertions(+), 2 deletions(-) + +diff --git a/tests/qemu-iotests/144 b/tests/qemu-iotests/144 +index 60e9ddd75f..8c50d6487e 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', +-- +2.39.3 + diff --git a/SOURCES/kvm-iotests-add-filter_qmp_generated_node_ids.patch b/SOURCES/kvm-iotests-add-filter_qmp_generated_node_ids.patch new file mode 100644 index 0000000..d178cd4 --- /dev/null +++ b/SOURCES/kvm-iotests-add-filter_qmp_generated_node_ids.patch @@ -0,0 +1,49 @@ +From f164083416a9d09712b8cb8c654dd3b8988e6c5c Mon Sep 17 00:00:00 2001 +From: Stefan Hajnoczi +Date: Thu, 18 Jan 2024 09:48:21 -0500 +Subject: [PATCH 1/4] iotests: add filter_qmp_generated_node_ids() + +RH-Author: Stefan Hajnoczi +RH-MergeRequest: 352: monitor: only run coroutine commands in qemu_aio_context +RH-Jira: RHEL-7353 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Hanna Czenczek +RH-Commit: [1/4] cc276c8ef9e140203afc19fcd8b5b8e20577054d + +Add a filter function for QMP responses that contain QEMU's +automatically generated node ids. The ids change between runs and must +be masked in the reference output. + +The next commit will use this new function. + +Signed-off-by: Stefan Hajnoczi +Message-ID: <20240118144823.1497953-2-stefanha@redhat.com> +Reviewed-by: Kevin Wolf +Signed-off-by: Kevin Wolf +(cherry picked from commit da62b507a20510d819bcfbe8f5e573409b954006) +Signed-off-by: Stefan Hajnoczi +--- + tests/qemu-iotests/iotests.py | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py +index 2ef493755c..fd41f93421 100644 +--- a/tests/qemu-iotests/iotests.py ++++ b/tests/qemu-iotests/iotests.py +@@ -521,6 +521,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'): +-- +2.39.3 + diff --git a/SOURCES/kvm-iotests-port-141-to-Python-for-reliable-QMP-testing.patch b/SOURCES/kvm-iotests-port-141-to-Python-for-reliable-QMP-testing.patch new file mode 100644 index 0000000..21a5c8d --- /dev/null +++ b/SOURCES/kvm-iotests-port-141-to-Python-for-reliable-QMP-testing.patch @@ -0,0 +1,601 @@ +From 968c8ff7ea7d43bf29d8e5f6e9e17f84168c22c4 Mon Sep 17 00:00:00 2001 +From: Stefan Hajnoczi +Date: Thu, 18 Jan 2024 09:48:22 -0500 +Subject: [PATCH 2/4] iotests: port 141 to Python for reliable QMP testing + +RH-Author: Stefan Hajnoczi +RH-MergeRequest: 352: monitor: only run coroutine commands in qemu_aio_context +RH-Jira: RHEL-7353 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Hanna Czenczek +RH-Commit: [2/4] ff0899262544b1b61b4c7de2eb798b664fe5202e + +The common.qemu bash functions allow tests to interact with the QMP +monitor of a QEMU process. I spent two days trying to update 141 when +the order of the test output changed, but found it would still fail +occassionally because printf() and QMP events race with synchronous QMP +communication. + +I gave up and ported 141 to the existing Python API for QMP tests. The +Python API is less affected by the order in which QEMU prints output +because it does not print all QMP traffic by default. + +The next commit changes the order in which QMP messages are received. +Make 141 reliable first. + +Cc: Hanna Czenczek +Signed-off-by: Stefan Hajnoczi +Message-ID: <20240118144823.1497953-3-stefanha@redhat.com> +Reviewed-by: Kevin Wolf +Signed-off-by: Kevin Wolf +(cherry picked from commit 9ee2dd4c22a3639c5462b3fc20df60c005c3de64) +Signed-off-by: Stefan Hajnoczi + +Conflicts: + tests/qemu-iotests/141 + tests/qemu-iotests/141.out + + This commit replaces these files anyway, so apply our changes instead + of dragging in more dependencies to resolve context conflicts. +--- + tests/qemu-iotests/141 | 307 ++++++++++++++++--------------------- + tests/qemu-iotests/141.out | 204 ++++++------------------ + 2 files changed, 178 insertions(+), 333 deletions(-) + +diff --git a/tests/qemu-iotests/141 b/tests/qemu-iotests/141 +index 115cc1691e..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 . + # + +-# creator +-owner=mreitz@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 c4c15fb275..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'}} +-{"error": {"class": "GenericError", "desc": "Node drv0 is in use"}} +-{'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'}} ++{"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"}} ++{"return": {}} ++{"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 ++ +-- +2.39.3 + diff --git a/SOURCES/kvm-monitor-only-run-coroutine-commands-in-qemu_aio_cont.patch b/SOURCES/kvm-monitor-only-run-coroutine-commands-in-qemu_aio_cont.patch new file mode 100644 index 0000000..9fa5f32 --- /dev/null +++ b/SOURCES/kvm-monitor-only-run-coroutine-commands-in-qemu_aio_cont.patch @@ -0,0 +1,1569 @@ +From f3a0fa8579a22a180500162952cdc627818e085a Mon Sep 17 00:00:00 2001 +From: Stefan Hajnoczi +Date: Thu, 18 Jan 2024 09:48:23 -0500 +Subject: [PATCH 3/4] monitor: only run coroutine commands in qemu_aio_context + +RH-Author: Stefan Hajnoczi +RH-MergeRequest: 352: monitor: only run coroutine commands in qemu_aio_context +RH-Jira: RHEL-7353 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Hanna Czenczek +RH-Commit: [3/4] c79f7b4b6a677beb838fc428871e003ed8ee4e53 + +monitor_qmp_dispatcher_co() runs in the iohandler AioContext that is not +polled during nested event loops. The coroutine currently reschedules +itself in the main loop's qemu_aio_context AioContext, which is polled +during nested event loops. One known problem is that QMP device-add +calls drain_call_rcu(), which temporarily drops the BQL, leading to all +sorts of havoc like other vCPU threads re-entering device emulation code +while another vCPU thread is waiting in device emulation code with +aio_poll(). + +Paolo Bonzini suggested running non-coroutine QMP handlers in the +iohandler AioContext. This avoids trouble with nested event loops. His +original idea was to move coroutine rescheduling to +monitor_qmp_dispatch(), but I resorted to moving it to qmp_dispatch() +because we don't know if the QMP handler needs to run in coroutine +context in monitor_qmp_dispatch(). monitor_qmp_dispatch() would have +been nicer since it's associated with the monitor implementation and not +as general as qmp_dispatch(), which is also used by qemu-ga. + +A number of qemu-iotests need updated .out files because the order of +QMP events vs QMP responses has changed. + +Solves Issue #1933. + +Cc: qemu-stable@nongnu.org +Fixes: 7bed89958bfbf40df9ca681cefbdca63abdde39d ("device_core: use drain_call_rcu in in qmp_device_add") +Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=2215192 +Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=2214985 +Buglink: https://issues.redhat.com/browse/RHEL-17369 +Signed-off-by: Stefan Hajnoczi +Message-ID: <20240118144823.1497953-4-stefanha@redhat.com> +Reviewed-by: Kevin Wolf +Tested-by: Fiona Ebner +Signed-off-by: Kevin Wolf +(cherry picked from commit effd60c878176bcaf97fa7ce2b12d04bb8ead6f7) +Signed-off-by: Stefan Hajnoczi + +Conflicts: + tests/qemu-iotests/185 + tests/qemu-iotests/308.out + + These tests are different downstream. Shorten the upstream + changes to only cover portions that exist downstream. + + tests/qemu-iotests/tests/file-io-error + tests/qemu-iotests/tests/iothreads-resize.out + + These tests don't exist downstream. Ignore them. +--- + monitor/qmp.c | 17 ------ + qapi/qmp-dispatch.c | 24 ++++++++- + 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/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.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/tests/qsd-jobs.out | 4 +- + 29 files changed, 198 insertions(+), 170 deletions(-) + +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 d378bccac7..114e293476 100644 +--- a/qapi/qmp-dispatch.c ++++ b/qapi/qmp-dispatch.c +@@ -207,9 +207,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. +@@ -233,7 +255,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/tests/qemu-iotests/060.out b/tests/qemu-iotests/060.out +index b74540bafb..9c5fa875cf 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/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.out b/tests/qemu-iotests/185.out +index 754a641258..48aa465776 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,8 +140,15 @@ 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. + *** done +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 e58ea5abbd..5014a38173 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 === +@@ -118,14 +118,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"} + {"return": {}} +@@ -219,22 +219,22 @@ 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"} + {"return": {}} + {"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 9c09ee3917..26cb68c1ad 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 4e840b6730..2fd9d9f195 100644 +--- a/tests/qemu-iotests/273.out ++++ b/tests/qemu-iotests/273.out +@@ -286,10 +286,6 @@ Testing: -blockdev file,node-name=base,filename=TEST_DIR/t.IMGFMT.base -blockdev + ] + } + } +-{ +- "return": { +- } +-} + { + "timestamp": { + "seconds": TIMESTAMP, +@@ -301,5 +297,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 2e3f8f4282..cdb1507551 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 fc47bb11a2..0afbef2f8e 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/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 +-- +2.39.3 + diff --git a/SOURCES/kvm-net-Provide-MemReentrancyGuard-to-qemu_new_nic.patch b/SOURCES/kvm-net-Provide-MemReentrancyGuard-to-qemu_new_nic.patch new file mode 100644 index 0000000..55040d5 --- /dev/null +++ b/SOURCES/kvm-net-Provide-MemReentrancyGuard-to-qemu_new_nic.patch @@ -0,0 +1,611 @@ +From 2ae925a6d55a77627be8d1146f2b9ed139dbdb77 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Thu, 23 Nov 2023 11:30:46 -0500 +Subject: [PATCH 1/4] net: Provide MemReentrancyGuard * to qemu_new_nic() + +RH-Author: Jon Maloy +RH-MergeRequest: 331: net: Provide MemReentrancyGuard * to qemu_new_nic() +RH-Jira: RHEL-7309 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Laurent Vivier +RH-Acked-by: Jason Wang +RH-Commit: [1/2] bc963fb349b90288f547de97a5cbe9a74f856419 (redhat/rhel/src/qemu-kvm/jons-qemu-kvm-2) + +Jira: https://issues.redhat.com/browse/RHEL-7309 +CVE: CVE-2023-3019 +Upstream: Merged +Conflicts: hw/net/hw/net/xen_nic.c seems to have undergone significant changes upstream, + so the change had to be manually adapted to the old code. + +commit 7d0fefdf81f5973334c344f6b8e1896c309dff66 +Author: Akihiko Odaki +Date: Thu Jun 1 12:18:58 2023 +0900 + + net: Provide MemReentrancyGuard * to qemu_new_nic() + + Recently MemReentrancyGuard was added to DeviceState to record that the + device is engaging in I/O. The network device backend needs to update it + when delivering a packet to a device. + + In preparation for such a change, add MemReentrancyGuard * as a + parameter of qemu_new_nic(). + + Signed-off-by: Akihiko Odaki + Reviewed-by: Alexander Bulekov + Signed-off-by: Jason Wang + +Signed-off-by: Jon Maloy +--- + 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/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/usb/dev-network.c | 3 ++- + include/net/net.h | 1 + + net/net.c | 1 + + 38 files changed, 72 insertions(+), 38 deletions(-) + +diff --git a/hw/net/allwinner-sun8i-emac.c b/hw/net/allwinner-sun8i-emac.c +index ff611f18fb..9d0885ee15 100644 +--- a/hw/net/allwinner-sun8i-emac.c ++++ b/hw/net/allwinner-sun8i-emac.c +@@ -810,7 +810,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 282d01e374..86da1ae39e 100644 +--- a/hw/net/e1000.c ++++ b/hw/net/e1000.c +@@ -1733,7 +1733,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 d35bc1f0b0..c6096fa848 100644 +--- a/hw/net/e1000e.c ++++ b/hw/net/e1000e.c +@@ -340,7 +340,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 16e95ef9cc..16ca4dda04 100644 +--- a/hw/net/eepro100.c ++++ b/hw/net/eepro100.c +@@ -1865,7 +1865,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 bd9d62b559..f790613b52 100644 +--- a/hw/net/fsl_etsec/etsec.c ++++ b/hw/net/fsl_etsec/etsec.c +@@ -391,7 +391,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_DEFAULT); +diff --git a/hw/net/ftgmac100.c b/hw/net/ftgmac100.c +index 25685ba3a9..781e7f352e 100644 +--- a/hw/net/ftgmac100.c ++++ b/hw/net/ftgmac100.c +@@ -1111,7 +1111,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 9c7035bc94..ed19ee9350 100644 +--- a/hw/net/imx_fec.c ++++ b/hw/net/imx_fec.c +@@ -1310,7 +1310,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 6aff424cbe..942bce9ae6 100644 +--- a/hw/net/lan9118.c ++++ b/hw/net/lan9118.c +@@ -1354,7 +1354,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 25e3e453ab..a6be7bf413 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 9278fdce0b..1efa3dbf01 100644 +--- a/hw/net/msf2-emac.c ++++ b/hw/net/msf2-emac.c +@@ -527,7 +527,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/ne2000-isa.c b/hw/net/ne2000-isa.c +index dd6f6e34d3..30bd20c293 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 7c892f820f..dd1d0ad3bc 100644 +--- a/hw/net/npcm7xx_emc.c ++++ b/hw/net/npcm7xx_emc.c +@@ -802,7 +802,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 dcd3fc4948..da910a70bf 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 3ffb9dd22c..a3565c7159 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 ca69f7ea5e..985c4c14a4 100644 +--- a/hw/net/tulip.c ++++ b/hw/net/tulip.c +@@ -981,7 +981,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 ddaa8fa122..f5f07f8e63 100644 +--- a/hw/net/virtio-net.c ++++ b/hw/net/virtio-net.c +@@ -3512,10 +3512,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 f65af4e9ef..d4df039c55 100644 +--- a/hw/net/vmxnet3.c ++++ b/hw/net/vmxnet3.c +@@ -2078,7 +2078,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 5c815b4f0c..3d0b7820d3 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); + + snprintf(qemu_get_queue(netdev->nic)->info_str, + sizeof(qemu_get_queue(netdev->nic)->info_str), +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/usb/dev-network.c b/hw/usb/dev-network.c +index 6c49c16015..ae447a8bc3 100644 +--- a/hw/usb/dev-network.c ++++ b/hw/usb/dev-network.c +@@ -1362,7 +1362,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/include/net/net.h b/include/net/net.h +index 523136c7ac..1457b6c014 100644 +--- a/include/net/net.h ++++ b/include/net/net.h +@@ -145,6 +145,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/net/net.c b/net/net.c +index f0d14dbfc1..669e194c4b 100644 +--- a/net/net.c ++++ b/net/net.c +@@ -299,6 +299,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; +-- +2.41.0 + diff --git a/SOURCES/kvm-net-Update-MemReentrancyGuard-for-NIC.patch b/SOURCES/kvm-net-Update-MemReentrancyGuard-for-NIC.patch new file mode 100644 index 0000000..e01c03c --- /dev/null +++ b/SOURCES/kvm-net-Update-MemReentrancyGuard-for-NIC.patch @@ -0,0 +1,105 @@ +From d58671091daf8c325a6f1cd87737d94b5fb51d12 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Thu, 23 Nov 2023 11:30:46 -0500 +Subject: [PATCH 2/4] net: Update MemReentrancyGuard for NIC + +RH-Author: Jon Maloy +RH-MergeRequest: 331: net: Provide MemReentrancyGuard * to qemu_new_nic() +RH-Jira: RHEL-7309 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Laurent Vivier +RH-Acked-by: Jason Wang +RH-Commit: [2/2] b116efe725dd838c2cab9bd2240112f3c6c46d6a (redhat/rhel/src/qemu-kvm/jons-qemu-kvm-2) + +Jira: https://issues.redhat.com/browse/RHEL-7309 +CVE: CVE-2023-3019 +Upstream: Merged + +commit 9050f976e447444ea6ee2ba12c9f77e4b0dc54bc +Author: Akihiko Odaki +Date: Thu Jun 1 12:18:59 2023 +0900 + + net: Update MemReentrancyGuard for NIC + + Recently MemReentrancyGuard was added to DeviceState to record that the + device is engaging in I/O. The network device backend needs to update it + when delivering a packet to a device. + + This implementation follows what bottom half does, but it does not add + a tracepoint for the case that the network device backend started + delivering a packet to a device which is already engaging in I/O. This + is because such reentrancy frequently happens for + qemu_flush_queued_packets() and is insignificant. + + Fixes: CVE-2023-3019 + Reported-by: Alexander Bulekov + Signed-off-by: Akihiko Odaki + Acked-by: Alexander Bulekov + Signed-off-by: Jason Wang + +Signed-off-by: Jon Maloy +--- + include/net/net.h | 1 + + net/net.c | 14 ++++++++++++++ + 2 files changed, 15 insertions(+) + +diff --git a/include/net/net.h b/include/net/net.h +index 1457b6c014..11d4564ea1 100644 +--- a/include/net/net.h ++++ b/include/net/net.h +@@ -112,6 +112,7 @@ struct NetClientState { + typedef struct NICState { + NetClientState *ncs; + NICConf *conf; ++ MemReentrancyGuard *reentrancy_guard; + void *opaque; + bool peer_deleted; + } NICState; +diff --git a/net/net.c b/net/net.c +index 669e194c4b..b3008a52b7 100644 +--- a/net/net.c ++++ b/net/net.c +@@ -312,6 +312,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++) { +@@ -767,6 +768,7 @@ static ssize_t qemu_deliver_packet_iov(NetClientState *sender, + int iovcnt, + void *opaque) + { ++ MemReentrancyGuard *owned_reentrancy_guard; + NetClientState *nc = opaque; + int ret; + +@@ -779,12 +781,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; + } +-- +2.41.0 + diff --git a/SOURCES/kvm-redhat-Update-linux-headers-for-kvm_s390_vm_cpu_uv_f.patch b/SOURCES/kvm-redhat-Update-linux-headers-for-kvm_s390_vm_cpu_uv_f.patch new file mode 100644 index 0000000..2192023 --- /dev/null +++ b/SOURCES/kvm-redhat-Update-linux-headers-for-kvm_s390_vm_cpu_uv_f.patch @@ -0,0 +1,56 @@ +From 76e75a129e59a33103aa7d1d92074ddcef556980 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Tue, 12 Sep 2023 11:24:40 +0200 +Subject: [PATCH 3/5] redhat: Update linux-headers for kvm_s390_vm_cpu_uv_feat +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Thomas Huth +RH-MergeRequest: 321: Enable Secure Execution Crypto Passthrough for KVM on s390x +RH-Bugzilla: 2111390 +RH-Acked-by: Cédric Le Goater +RH-Commit: [3/5] f1329f5ce5f66033ead7777384dcc1613cad1226 + +Upstream Status: rhel-only + +This hunk is part of upstream commit da3c22c74a3c +("linux-headers: Update to Linux v6.6-rc1"), but since that +commit updates a lot of files and does not apply cleanly, +we only focus on the necessary change here. + +Signed-off-by: Thomas Huth +--- + linux-headers/asm-s390/kvm.h | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/linux-headers/asm-s390/kvm.h b/linux-headers/asm-s390/kvm.h +index f053b8304a..6706bdc5cc 100644 +--- a/linux-headers/asm-s390/kvm.h ++++ b/linux-headers/asm-s390/kvm.h +@@ -158,6 +158,22 @@ struct kvm_s390_vm_cpu_subfunc { + __u8 reserved[1728]; + }; + ++#define KVM_S390_VM_CPU_PROCESSOR_UV_FEAT_GUEST 6 ++#define KVM_S390_VM_CPU_MACHINE_UV_FEAT_GUEST 7 ++ ++#define KVM_S390_VM_CPU_UV_FEAT_NR_BITS 64 ++struct kvm_s390_vm_cpu_uv_feat { ++ union { ++ struct { ++ __u64 : 4; ++ __u64 ap : 1; /* bit 4 */ ++ __u64 ap_intr : 1; /* bit 5 */ ++ __u64 : 58; ++ }; ++ __u64 feat; ++ }; ++}; ++ + /* kvm attributes for crypto */ + #define KVM_S390_VM_CRYPTO_ENABLE_AES_KW 0 + #define KVM_S390_VM_CRYPTO_ENABLE_DEA_KW 1 +-- +2.41.0 + diff --git a/SOURCES/kvm-s390x-ap-fix-missing-subsystem-reset-registration.patch b/SOURCES/kvm-s390x-ap-fix-missing-subsystem-reset-registration.patch new file mode 100644 index 0000000..69f9cbf --- /dev/null +++ b/SOURCES/kvm-s390x-ap-fix-missing-subsystem-reset-registration.patch @@ -0,0 +1,44 @@ +From eb60b6cab9550a62f0b20a9e6d69547d651e3020 Mon Sep 17 00:00:00 2001 +From: Janosch Frank +Date: Wed, 23 Aug 2023 16:22:15 +0200 +Subject: [PATCH 1/5] s390x/ap: fix missing subsystem reset registration +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Thomas Huth +RH-MergeRequest: 321: Enable Secure Execution Crypto Passthrough for KVM on s390x +RH-Bugzilla: 2111390 +RH-Acked-by: Cédric Le Goater +RH-Commit: [1/5] 4ebe81bb6cc4fc137ca4ebc9c0cebdedc421cc91 + +A subsystem reset contains a reset of AP resources which has been +missing. Adding the AP bridge to the list of device types that need +reset fixes this issue. + +Reviewed-by: Jason J. Herne +Reviewed-by: Tony Krowiak +Signed-off-by: Janosch Frank +Fixes: a51b3153 ("s390x/ap: base Adjunct Processor (AP) object model") +Message-ID: <20230823142219.1046522-2-seiden@linux.ibm.com> +Signed-off-by: Thomas Huth +(cherry picked from commit 297ec01f0b9864ea8209ca0ddc6643b4c0574bdb) +--- + hw/s390x/s390-virtio-ccw.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c +index 4a7cd21cac..412d73715a 100644 +--- a/hw/s390x/s390-virtio-ccw.c ++++ b/hw/s390x/s390-virtio-ccw.c +@@ -100,6 +100,7 @@ static const char *const reset_dev_types[] = { + "s390-flic", + "diag288", + TYPE_S390_PCI_HOST_BRIDGE, ++ TYPE_AP_BRIDGE, + }; + + static void subsystem_reset(void) +-- +2.41.0 + diff --git a/SOURCES/kvm-s390x-do-a-subsystem-reset-before-the-unprotect-on-r.patch b/SOURCES/kvm-s390x-do-a-subsystem-reset-before-the-unprotect-on-r.patch new file mode 100644 index 0000000..2a23bc0 --- /dev/null +++ b/SOURCES/kvm-s390x-do-a-subsystem-reset-before-the-unprotect-on-r.patch @@ -0,0 +1,68 @@ +From 05b145a8d5b1c2f796069cdd81826c00cf7c983e Mon Sep 17 00:00:00 2001 +From: Janosch Frank +Date: Fri, 1 Sep 2023 11:48:51 +0000 +Subject: [PATCH 2/5] s390x: do a subsystem reset before the unprotect on + reboot +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Thomas Huth +RH-MergeRequest: 321: Enable Secure Execution Crypto Passthrough for KVM on s390x +RH-Bugzilla: 2111390 +RH-Acked-by: Cédric Le Goater +RH-Commit: [2/5] ea430d236e1a20ddad7095d2e6d10f741f9a1907 + +Bound APQNs have to be reset before tearing down the secure config via +s390_machine_unprotect(). Otherwise the Ultravisor will return a error +code. + +So let's do a subsystem_reset() which includes a AP reset before the +unprotect call. We'll do a full device_reset() afterwards which will +reset some devices twice. That's ok since we can't move the +device_reset() before the unprotect as it includes a CPU clear reset +which the Ultravisor does not expect at that point in time. + +Signed-off-by: Janosch Frank +Message-ID: <20230901114851.154357-1-frankja@linux.ibm.com> +Tested-by: Viktor Mihajlovski +Acked-by: Christian Borntraeger +Signed-off-by: Thomas Huth +(cherry picked from commit ef1535901a07f2e49fa25c8bcee7f0b73801d824) + +Conflicts: + hw/s390x/s390-virtio-ccw.c + (contextual conflict due to missing commit 7966d70f6f6b) +Signed-off-by: Thomas Huth +--- + hw/s390x/s390-virtio-ccw.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c +index 412d73715a..17146469ee 100644 +--- a/hw/s390x/s390-virtio-ccw.c ++++ b/hw/s390x/s390-virtio-ccw.c +@@ -430,10 +430,20 @@ static void s390_machine_reset(MachineState *machine) + switch (reset_type) { + case S390_RESET_EXTERNAL: + case S390_RESET_REIPL: ++ /* ++ * Reset the subsystem which includes a AP reset. If a PV ++ * guest had APQNs attached the AP reset is a prerequisite to ++ * unprotecting since the UV checks if all APQNs are reset. ++ */ ++ subsystem_reset(); + if (s390_is_pv()) { + s390_machine_unprotect(ms); + } + ++ /* ++ * Device reset includes CPU clear resets so this has to be ++ * done AFTER the unprotect call above. ++ */ + qemu_devices_reset(); + s390_crypto_reset(); + +-- +2.41.0 + diff --git a/SOURCES/kvm-s390x-pci-avoid-double-enable-disable-of-aif.patch b/SOURCES/kvm-s390x-pci-avoid-double-enable-disable-of-aif.patch new file mode 100644 index 0000000..8fd8d16 --- /dev/null +++ b/SOURCES/kvm-s390x-pci-avoid-double-enable-disable-of-aif.patch @@ -0,0 +1,106 @@ +From 52ad0cc8a82f7a4c3581146fb4d2046898163c4e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= +Date: Tue, 23 Jan 2024 13:59:24 +0100 +Subject: [PATCH 1/3] s390x/pci: avoid double enable/disable of aif +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Cédric Le Goater +RH-MergeRequest: 349: s390x: Fix reset ordering of passthrough ISM devices +RH-Jira: RHEL-22411 +RH-Acked-by: Thomas Huth +RH-Acked-by: Cornelia Huck +RH-Commit: [1/3] 450e4ca607d801bce93415994250374d70fb72f6 + +JIRA: https://issues.redhat.com/browse/RHEL-22411 + +commit 07b2c8e034d80ff92e202405c494d2ff80fcf848 +Author: Matthew Rosato +Date: Thu Jan 18 13:51:49 2024 -0500 + + s390x/pci: avoid double enable/disable of aif + + Use a flag to keep track of whether AIF is currently enabled. This can be + used to avoid enabling/disabling AIF multiple times as well as to determine + whether or not it should be disabled during reset processing. + + Fixes: d0bc7091c2 ("s390x/pci: enable adapter event notification for interpreted devices") + Reported-by: Cédric Le Goater + Reviewed-by: Eric Farman + Signed-off-by: Matthew Rosato + Message-ID: <20240118185151.265329-2-mjrosato@linux.ibm.com> + Reviewed-by: Cédric Le Goater + Signed-off-by: Thomas Huth + +Signed-off-by: Cédric Le Goater +--- + hw/s390x/s390-pci-kvm.c | 25 +++++++++++++++++++++++-- + include/hw/s390x/s390-pci-bus.h | 1 + + 2 files changed, 24 insertions(+), 2 deletions(-) + +diff --git a/hw/s390x/s390-pci-kvm.c b/hw/s390x/s390-pci-kvm.c +index ff41e4106d..1ee510436c 100644 +--- a/hw/s390x/s390-pci-kvm.c ++++ b/hw/s390x/s390-pci-kvm.c +@@ -27,6 +27,7 @@ bool s390_pci_kvm_interp_allowed(void) + + int s390_pci_kvm_aif_enable(S390PCIBusDevice *pbdev, ZpciFib *fib, bool assist) + { ++ int rc; + struct kvm_s390_zpci_op args = { + .fh = pbdev->fh, + .op = KVM_S390_ZPCIOP_REG_AEN, +@@ -38,15 +39,35 @@ int s390_pci_kvm_aif_enable(S390PCIBusDevice *pbdev, ZpciFib *fib, bool assist) + .u.reg_aen.flags = (assist) ? 0 : KVM_S390_ZPCIOP_REGAEN_HOST + }; + +- return kvm_vm_ioctl(kvm_state, KVM_S390_ZPCI_OP, &args); ++ if (pbdev->aif) { ++ return -EINVAL; ++ } ++ ++ rc = kvm_vm_ioctl(kvm_state, KVM_S390_ZPCI_OP, &args); ++ if (rc == 0) { ++ pbdev->aif = true; ++ } ++ ++ return rc; + } + + int s390_pci_kvm_aif_disable(S390PCIBusDevice *pbdev) + { ++ int rc; ++ + struct kvm_s390_zpci_op args = { + .fh = pbdev->fh, + .op = KVM_S390_ZPCIOP_DEREG_AEN + }; + +- return kvm_vm_ioctl(kvm_state, KVM_S390_ZPCI_OP, &args); ++ if (!pbdev->aif) { ++ return -EINVAL; ++ } ++ ++ rc = kvm_vm_ioctl(kvm_state, KVM_S390_ZPCI_OP, &args); ++ if (rc == 0) { ++ pbdev->aif = false; ++ } ++ ++ return rc; + } +diff --git a/include/hw/s390x/s390-pci-bus.h b/include/hw/s390x/s390-pci-bus.h +index e0a9f9385b..7a658f5e30 100644 +--- a/include/hw/s390x/s390-pci-bus.h ++++ b/include/hw/s390x/s390-pci-bus.h +@@ -361,6 +361,7 @@ struct S390PCIBusDevice { + bool unplug_requested; + bool interp; + bool forwarding_assist; ++ bool aif; + QTAILQ_ENTRY(S390PCIBusDevice) link; + }; + +-- +2.41.0 + diff --git a/SOURCES/kvm-s390x-pci-drive-ISM-reset-from-subsystem-reset.patch b/SOURCES/kvm-s390x-pci-drive-ISM-reset-from-subsystem-reset.patch new file mode 100644 index 0000000..a879176 --- /dev/null +++ b/SOURCES/kvm-s390x-pci-drive-ISM-reset-from-subsystem-reset.patch @@ -0,0 +1,137 @@ +From dda71c431be22772f3241af45b62737c988e85d4 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= +Date: Tue, 23 Jan 2024 13:59:24 +0100 +Subject: [PATCH 3/3] s390x/pci: drive ISM reset from subsystem reset +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Cédric Le Goater +RH-MergeRequest: 349: s390x: Fix reset ordering of passthrough ISM devices +RH-Jira: RHEL-22411 +RH-Acked-by: Thomas Huth +RH-Acked-by: Cornelia Huck +RH-Commit: [3/3] 42e89595dd5e24538a2d3f075391b4534497eece + +JIRA: https://issues.redhat.com/browse/RHEL-22411 + +commit 68c691ca99a2538d6a53a70ce8a9ce06ee307ff1 +Author: Matthew Rosato +Date: Thu Jan 18 13:51:51 2024 -0500 + + s390x/pci: drive ISM reset from subsystem reset + + ISM devices are sensitive to manipulation of the IOMMU, so the ISM device + needs to be reset before the vfio-pci device is reset (triggering a full + UNMAP). In order to ensure this occurs, trigger ISM device resets from + subsystem_reset before triggering the PCI bus reset (which will also + trigger vfio-pci reset). This only needs to be done for ISM devices + which were enabled for use by the guest. + Further, ensure that AIF is disabled as part of the reset event. + + Fixes: ef1535901a ("s390x: do a subsystem reset before the unprotect on reboot") + Fixes: 03451953c7 ("s390x/pci: reset ISM passthrough devices on shutdown and system reset") + Reported-by: Cédric Le Goater + Signed-off-by: Matthew Rosato + Message-ID: <20240118185151.265329-4-mjrosato@linux.ibm.com> + Reviewed-by: Eric Farman + Reviewed-by: Cédric Le Goater + Signed-off-by: Thomas Huth + +Signed-off-by: Cédric Le Goater +--- + hw/s390x/s390-pci-bus.c | 26 +++++++++++++++++--------- + hw/s390x/s390-virtio-ccw.c | 8 ++++++++ + include/hw/s390x/s390-pci-bus.h | 1 + + 3 files changed, 26 insertions(+), 9 deletions(-) + +diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c +index 2d92848b0f..a8953693b9 100644 +--- a/hw/s390x/s390-pci-bus.c ++++ b/hw/s390x/s390-pci-bus.c +@@ -160,20 +160,12 @@ static void s390_pci_shutdown_notifier(Notifier *n, void *opaque) + pci_device_reset(pbdev->pdev); + } + +-static void s390_pci_reset_cb(void *opaque) +-{ +- S390PCIBusDevice *pbdev = opaque; +- +- pci_device_reset(pbdev->pdev); +-} +- + static void s390_pci_perform_unplug(S390PCIBusDevice *pbdev) + { + HotplugHandler *hotplug_ctrl; + + if (pbdev->pft == ZPCI_PFT_ISM) { + notifier_remove(&pbdev->shutdown_notifier); +- qemu_unregister_reset(s390_pci_reset_cb, pbdev); + } + + /* Unplug the PCI device */ +@@ -1137,7 +1129,6 @@ static void s390_pcihost_plug(HotplugHandler *hotplug_dev, DeviceState *dev, + if (pbdev->pft == ZPCI_PFT_ISM) { + pbdev->shutdown_notifier.notify = s390_pci_shutdown_notifier; + qemu_register_shutdown_notifier(&pbdev->shutdown_notifier); +- qemu_register_reset(s390_pci_reset_cb, pbdev); + } + } else { + pbdev->fh |= FH_SHM_EMUL; +@@ -1284,6 +1275,23 @@ static void s390_pci_enumerate_bridge(PCIBus *bus, PCIDevice *pdev, + pci_default_write_config(pdev, PCI_SUBORDINATE_BUS, s->bus_no, 1); + } + ++void s390_pci_ism_reset(void) ++{ ++ S390pciState *s = s390_get_phb(); ++ ++ S390PCIBusDevice *pbdev, *next; ++ ++ /* Trigger reset event for each passthrough ISM device currently in-use */ ++ QTAILQ_FOREACH_SAFE(pbdev, &s->zpci_devs, link, next) { ++ if (pbdev->interp && pbdev->pft == ZPCI_PFT_ISM && ++ pbdev->fh & FH_MASK_ENABLE) { ++ s390_pci_kvm_aif_disable(pbdev); ++ ++ pci_device_reset(pbdev->pdev); ++ } ++ } ++} ++ + static void s390_pcihost_reset(DeviceState *dev) + { + S390pciState *s = S390_PCI_HOST_BRIDGE(dev); +diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c +index 94434c3bb1..51e5b39888 100644 +--- a/hw/s390x/s390-virtio-ccw.c ++++ b/hw/s390x/s390-virtio-ccw.c +@@ -108,6 +108,14 @@ static void subsystem_reset(void) + DeviceState *dev; + int i; + ++ /* ++ * ISM firmware is sensitive to unexpected changes to the IOMMU, which can ++ * occur during reset of the vfio-pci device (unmap of entire aperture). ++ * Ensure any passthrough ISM devices are reset now, while CPUs are paused ++ * but before vfio-pci cleanup occurs. ++ */ ++ s390_pci_ism_reset(); ++ + for (i = 0; i < ARRAY_SIZE(reset_dev_types); i++) { + dev = DEVICE(object_resolve_path_type("", reset_dev_types[i], NULL)); + if (dev) { +diff --git a/include/hw/s390x/s390-pci-bus.h b/include/hw/s390x/s390-pci-bus.h +index 7a658f5e30..2bfad5563a 100644 +--- a/include/hw/s390x/s390-pci-bus.h ++++ b/include/hw/s390x/s390-pci-bus.h +@@ -401,5 +401,6 @@ S390PCIBusDevice *s390_pci_find_dev_by_target(S390pciState *s, + const char *target); + S390PCIBusDevice *s390_pci_find_next_avail_dev(S390pciState *s, + S390PCIBusDevice *pbdev); ++void s390_pci_ism_reset(void); + + #endif +-- +2.41.0 + diff --git a/SOURCES/kvm-s390x-pci-refresh-fh-before-disabling-aif.patch b/SOURCES/kvm-s390x-pci-refresh-fh-before-disabling-aif.patch new file mode 100644 index 0000000..3072e01 --- /dev/null +++ b/SOURCES/kvm-s390x-pci-refresh-fh-before-disabling-aif.patch @@ -0,0 +1,71 @@ +From fe70e87ef8d2f7e538867052e06012051919083f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= +Date: Tue, 23 Jan 2024 13:59:24 +0100 +Subject: [PATCH 2/3] s390x/pci: refresh fh before disabling aif +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Cédric Le Goater +RH-MergeRequest: 349: s390x: Fix reset ordering of passthrough ISM devices +RH-Jira: RHEL-22411 +RH-Acked-by: Thomas Huth +RH-Acked-by: Cornelia Huck +RH-Commit: [2/3] 4a7d3fccdac508253bd7e5765973a08482022edb + +JIRA: https://issues.redhat.com/browse/RHEL-22411 + +commit 30e35258e25c75c9d799c34fd89afcafffb37084 +Author: Matthew Rosato +Date: Thu Jan 18 13:51:50 2024 -0500 + + s390x/pci: refresh fh before disabling aif + + Typically we refresh the host fh during CLP enable, however it's possible + that the device goes through multiple reset events before the guest + performs another CLP enable. Let's handle this for now by refreshing the + host handle from vfio before disabling aif. + + Fixes: 03451953c7 ("s390x/pci: reset ISM passthrough devices on shutdown and system reset") + Reported-by: Cédric Le Goater + Reviewed-by: Eric Farman + Signed-off-by: Matthew Rosato + Message-ID: <20240118185151.265329-3-mjrosato@linux.ibm.com> + Reviewed-by: Cédric Le Goater + Signed-off-by: Thomas Huth + +Signed-off-by: Cédric Le Goater +--- + hw/s390x/s390-pci-kvm.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/hw/s390x/s390-pci-kvm.c b/hw/s390x/s390-pci-kvm.c +index 1ee510436c..9eef4fc3ec 100644 +--- a/hw/s390x/s390-pci-kvm.c ++++ b/hw/s390x/s390-pci-kvm.c +@@ -18,6 +18,7 @@ + #include "hw/s390x/s390-pci-bus.h" + #include "hw/s390x/s390-pci-kvm.h" + #include "hw/s390x/s390-pci-inst.h" ++#include "hw/s390x/s390-pci-vfio.h" + #include "cpu_models.h" + + bool s390_pci_kvm_interp_allowed(void) +@@ -64,6 +65,14 @@ int s390_pci_kvm_aif_disable(S390PCIBusDevice *pbdev) + return -EINVAL; + } + ++ /* ++ * The device may have already been reset but we still want to relinquish ++ * the guest ISC, so always be sure to use an up-to-date host fh. ++ */ ++ if (!s390_pci_get_host_fh(pbdev, &args.fh)) { ++ return -EPERM; ++ } ++ + rc = kvm_vm_ioctl(kvm_state, KVM_S390_ZPCI_OP, &args); + if (rc == 0) { + pbdev->aif = false; +-- +2.41.0 + diff --git a/SOURCES/kvm-s390x-pv-remove-semicolon-from-macro-definition.patch b/SOURCES/kvm-s390x-pv-remove-semicolon-from-macro-definition.patch new file mode 100644 index 0000000..0c62189 --- /dev/null +++ b/SOURCES/kvm-s390x-pv-remove-semicolon-from-macro-definition.patch @@ -0,0 +1,51 @@ +From 52969f8a75ac7ba115e044cd94208984c18eee41 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Mon, 15 Jan 2024 14:00:04 +0100 +Subject: [PATCH 2/5] s390x/pv: remove semicolon from macro definition +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Thomas Huth +RH-MergeRequest: 348: s390x: Provide some more useful information if decryption of a PV image fails +RH-Jira: RHEL-18214 +RH-Acked-by: Jon Maloy +RH-Acked-by: Cédric Le Goater +RH-Commit: [2/5] 52a04c945a584746ff30bed516ad97bab75ac821 + +JIRA: https://issues.redhat.com/browse/RHEL-18214 + +commit 36c182bbe680d64f0868522bb9256b5b8eccf280 +Author: Claudio Imbrenda +Date: Mon Oct 10 17:10:41 2022 +0200 + + s390x/pv: remove semicolon from macro definition + + Remove spurious semicolon at the end of the macro s390_pv_cmd + + Signed-off-by: Claudio Imbrenda + Acked-by: Cornelia Huck + Message-Id: <20221010151041.89071-1-imbrenda@linux.ibm.com> + Signed-off-by: Thomas Huth + +Signed-off-by: Thomas Huth +--- + hw/s390x/pv.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/s390x/pv.c b/hw/s390x/pv.c +index 749e5db1ce..8a1c71436b 100644 +--- a/hw/s390x/pv.c ++++ b/hw/s390x/pv.c +@@ -51,7 +51,7 @@ static int __s390_pv_cmd(uint32_t cmd, const char *cmdname, void *data) + * This macro lets us pass the command as a string to the function so + * we can print it on an error. + */ +-#define s390_pv_cmd(cmd, data) __s390_pv_cmd(cmd, #cmd, data); ++#define s390_pv_cmd(cmd, data) __s390_pv_cmd(cmd, #cmd, data) + #define s390_pv_cmd_exit(cmd, data) \ + { \ + int rc; \ +-- +2.41.0 + diff --git a/SOURCES/kvm-target-s390x-AP-passthrough-for-PV-guests.patch b/SOURCES/kvm-target-s390x-AP-passthrough-for-PV-guests.patch new file mode 100644 index 0000000..f30722a --- /dev/null +++ b/SOURCES/kvm-target-s390x-AP-passthrough-for-PV-guests.patch @@ -0,0 +1,194 @@ +From 885d04faf5edb787341aab6917fd2de743e029ac Mon Sep 17 00:00:00 2001 +From: Steffen Eiden +Date: Wed, 23 Aug 2023 16:22:19 +0200 +Subject: [PATCH 5/5] target/s390x: AP-passthrough for PV guests +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Thomas Huth +RH-MergeRequest: 321: Enable Secure Execution Crypto Passthrough for KVM on s390x +RH-Bugzilla: 2111390 +RH-Acked-by: Cédric Le Goater +RH-Commit: [5/5] 9bf3dfd78fb030a22db7bb756a2cb7f54a0a8d82 + +Enabling AP-passthrough(AP-pt) for PV-guest by using the new CPU +features for PV-AP-pt of KVM. + +As usual QEMU first checks which CPU features are available and then +sets them if available and selected by user. An additional check is done +to verify that PV-AP can only be enabled if "regular" AP-pt is enabled +as well. Note that KVM itself does not enforce this restriction. + +Reviewed-by: Michael Mueller +Reviewed-by: Thomas Huth +Signed-off-by: Steffen Eiden +Message-ID: <20230823142219.1046522-6-seiden@linux.ibm.com> +Signed-off-by: Thomas Huth +(cherry picked from commit 5ac951519c23d9eaf7dc9e2dcbcbc7d9a745ffe7) + +Conflicts: + target/s390x/gen-features.c + (simple contextual conflict due to missing S390_FEAT_PAIE) +Signed-off-by: Thomas Huth +--- + target/s390x/cpu_features.h | 1 + + target/s390x/cpu_features_def.h.inc | 4 ++ + target/s390x/cpu_models.c | 2 + + target/s390x/gen-features.c | 2 + + target/s390x/kvm/kvm.c | 70 +++++++++++++++++++++++++++++ + 5 files changed, 79 insertions(+) + +diff --git a/target/s390x/cpu_features.h b/target/s390x/cpu_features.h +index 87463f064d..a9bd68a2e1 100644 +--- a/target/s390x/cpu_features.h ++++ b/target/s390x/cpu_features.h +@@ -43,6 +43,7 @@ typedef enum { + S390_FEAT_TYPE_KDSA, + S390_FEAT_TYPE_SORTL, + S390_FEAT_TYPE_DFLTCC, ++ S390_FEAT_TYPE_UV_FEAT_GUEST, + } S390FeatType; + + /* Definition of a CPU feature */ +diff --git a/target/s390x/cpu_features_def.h.inc b/target/s390x/cpu_features_def.h.inc +index e86662bb3b..aa1f51f2a8 100644 +--- a/target/s390x/cpu_features_def.h.inc ++++ b/target/s390x/cpu_features_def.h.inc +@@ -378,3 +378,7 @@ DEF_FEAT(DEFLATE_GHDT, "dfltcc-gdht", DFLTCC, 1, "DFLTCC GDHT") + DEF_FEAT(DEFLATE_CMPR, "dfltcc-cmpr", DFLTCC, 2, "DFLTCC CMPR") + DEF_FEAT(DEFLATE_XPND, "dfltcc-xpnd", DFLTCC, 4, "DFLTCC XPND") + DEF_FEAT(DEFLATE_F0, "dfltcc-f0", DFLTCC, 192, "DFLTCC format 0 parameter-block") ++ ++/* Features exposed via the UV-CALL instruction */ ++DEF_FEAT(UV_FEAT_AP, "appv", UV_FEAT_GUEST, 4, "AP instructions installed for secure guests") ++DEF_FEAT(UV_FEAT_AP_INTR, "appvi", UV_FEAT_GUEST, 5, "AP instructions interruption support for secure guests") +diff --git a/target/s390x/cpu_models.c b/target/s390x/cpu_models.c +index 11e06cc51f..454485e706 100644 +--- a/target/s390x/cpu_models.c ++++ b/target/s390x/cpu_models.c +@@ -467,6 +467,8 @@ static void check_consistency(const S390CPUModel *model) + { S390_FEAT_DIAG_318, S390_FEAT_EXTENDED_LENGTH_SCCB }, + { S390_FEAT_NNPA, S390_FEAT_VECTOR }, + { S390_FEAT_RDP, S390_FEAT_LOCAL_TLB_CLEARING }, ++ { S390_FEAT_UV_FEAT_AP, S390_FEAT_AP }, ++ { S390_FEAT_UV_FEAT_AP_INTR, S390_FEAT_UV_FEAT_AP }, + }; + int i; + +diff --git a/target/s390x/gen-features.c b/target/s390x/gen-features.c +index 7cb1a6ec10..b789288c82 100644 +--- a/target/s390x/gen-features.c ++++ b/target/s390x/gen-features.c +@@ -575,6 +575,8 @@ static uint16_t full_GEN16_GA1[] = { + S390_FEAT_BEAR_ENH, + S390_FEAT_RDP, + S390_FEAT_PAI, ++ S390_FEAT_UV_FEAT_AP, ++ S390_FEAT_UV_FEAT_AP_INTR, + }; + + +diff --git a/target/s390x/kvm/kvm.c b/target/s390x/kvm/kvm.c +index eb8ca4c780..a963866ef4 100644 +--- a/target/s390x/kvm/kvm.c ++++ b/target/s390x/kvm/kvm.c +@@ -2308,6 +2308,42 @@ static bool ap_enabled(const S390FeatBitmap features) + return test_bit(S390_FEAT_AP, features); + } + ++static bool uv_feat_supported(void) ++{ ++ return kvm_vm_check_attr(kvm_state, KVM_S390_VM_CPU_MODEL, ++ KVM_S390_VM_CPU_PROCESSOR_UV_FEAT_GUEST); ++} ++ ++static int query_uv_feat_guest(S390FeatBitmap features) ++{ ++ struct kvm_s390_vm_cpu_uv_feat prop = {}; ++ struct kvm_device_attr attr = { ++ .group = KVM_S390_VM_CPU_MODEL, ++ .attr = KVM_S390_VM_CPU_MACHINE_UV_FEAT_GUEST, ++ .addr = (uint64_t) &prop, ++ }; ++ int rc; ++ ++ /* AP support check is currently the only user of the UV feature test */ ++ if (!(uv_feat_supported() && ap_available())) { ++ return 0; ++ } ++ ++ rc = kvm_vm_ioctl(kvm_state, KVM_GET_DEVICE_ATTR, &attr); ++ if (rc) { ++ return rc; ++ } ++ ++ if (prop.ap) { ++ set_bit(S390_FEAT_UV_FEAT_AP, features); ++ } ++ if (prop.ap_intr) { ++ set_bit(S390_FEAT_UV_FEAT_AP_INTR, features); ++ } ++ ++ return 0; ++} ++ + static int kvm_to_feat[][2] = { + { KVM_S390_VM_CPU_FEAT_ESOP, S390_FEAT_ESOP }, + { KVM_S390_VM_CPU_FEAT_SIEF2, S390_FEAT_SIE_F2 }, +@@ -2502,11 +2538,38 @@ void kvm_s390_get_host_cpu_model(S390CPUModel *model, Error **errp) + set_bit(S390_FEAT_DIAG_318, model->features); + } + ++ /* Test for Ultravisor features that influence secure guest behavior */ ++ query_uv_feat_guest(model->features); ++ + /* strip of features that are not part of the maximum model */ + bitmap_and(model->features, model->features, model->def->full_feat, + S390_FEAT_MAX); + } + ++static int configure_uv_feat_guest(const S390FeatBitmap features) ++{ ++ struct kvm_s390_vm_cpu_uv_feat uv_feat = {}; ++ struct kvm_device_attr attribute = { ++ .group = KVM_S390_VM_CPU_MODEL, ++ .attr = KVM_S390_VM_CPU_PROCESSOR_UV_FEAT_GUEST, ++ .addr = (__u64) &uv_feat, ++ }; ++ ++ /* AP support check is currently the only user of the UV feature test */ ++ if (!(uv_feat_supported() && ap_enabled(features))) { ++ return 0; ++ } ++ ++ if (test_bit(S390_FEAT_UV_FEAT_AP, features)) { ++ uv_feat.ap = 1; ++ } ++ if (test_bit(S390_FEAT_UV_FEAT_AP_INTR, features)) { ++ uv_feat.ap_intr = 1; ++ } ++ ++ return kvm_vm_ioctl(kvm_state, KVM_SET_DEVICE_ATTR, &attribute); ++} ++ + static void kvm_s390_configure_apie(bool interpret) + { + uint64_t attr = interpret ? KVM_S390_VM_CRYPTO_ENABLE_APIE : +@@ -2578,6 +2641,13 @@ void kvm_s390_apply_cpu_model(const S390CPUModel *model, Error **errp) + if (ap_enabled(model->features)) { + kvm_s390_configure_apie(true); + } ++ ++ /* configure UV-features for the guest indicated via query / test_bit */ ++ rc = configure_uv_feat_guest(model->features); ++ if (rc) { ++ error_setg(errp, "KVM: Error configuring CPU UV features %d", rc); ++ return; ++ } + } + + void kvm_s390_restart_interrupt(S390CPU *cpu) +-- +2.41.0 + diff --git a/SOURCES/kvm-target-s390x-arch_dump-Add-arch-cleanup-function-for.patch b/SOURCES/kvm-target-s390x-arch_dump-Add-arch-cleanup-function-for.patch new file mode 100644 index 0000000..0bbfe01 --- /dev/null +++ b/SOURCES/kvm-target-s390x-arch_dump-Add-arch-cleanup-function-for.patch @@ -0,0 +1,84 @@ +From 4aa08999f8502e9d6869352db89081319c2d7119 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 17 Nov 2023 11:32:37 +0100 +Subject: [PATCH 3/3] target/s390x/arch_dump: Add arch cleanup function for PV + dumps +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Thomas Huth +RH-MergeRequest: 323: Fix problem that secure execution guest might remain in "paused" state after failed dump +RH-Jira: RHEL-16696 +RH-Acked-by: Marc-André Lureau +RH-Acked-by: Cédric Le Goater +RH-Commit: [3/3] 0bb389c9339b95f7ff6dc284526b0c8d5ef736b4 + +JIRA: https://issues.redhat.com/browse/RHEL-16696 + +commit d12a91e0baafce7b1cbacff7cf9339eeb0011732 +Author: Janosch Frank +Date: Thu Nov 9 12:04:43 2023 +0000 + + target/s390x/arch_dump: Add arch cleanup function for PV dumps + + PV dumps block vcpu runs until dump end is reached. If there's an + error between PV dump init and PV dump end the vm will never be able + to run again. One example of such an error is insufficient disk space + for the dump file. + + Let's add a cleanup function that tries to do a dump end. The dump + completion data is discarded but there's no point in writing it to a + file anyway if there's a possibility that other PV dump data is + missing. + + Signed-off-by: Janosch Frank + Reviewed-by: Thomas Huth + Reviewed-by: Claudio Imbrenda + Reviewed-by: Marc-André Lureau + Message-ID: <20231109120443.185979-4-frankja@linux.ibm.com> + Signed-off-by: Thomas Huth + +Signed-off-by: Thomas Huth +--- + target/s390x/arch_dump.c | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + +diff --git a/target/s390x/arch_dump.c b/target/s390x/arch_dump.c +index 7cdd4b7167..3b1f178dc3 100644 +--- a/target/s390x/arch_dump.c ++++ b/target/s390x/arch_dump.c +@@ -439,6 +439,22 @@ static int arch_sections_write(DumpState *s, uint8_t *buff) + return 0; + } + ++static void arch_cleanup(DumpState *s) ++{ ++ g_autofree uint8_t *buff = NULL; ++ int rc; ++ ++ if (!pv_dump_initialized) { ++ return; ++ } ++ ++ buff = g_malloc(kvm_s390_pv_dmp_get_size_completion_data()); ++ rc = kvm_s390_dump_completion_data(buff); ++ if (!rc) { ++ pv_dump_initialized = false; ++ } ++} ++ + int cpu_get_dump_info(ArchDumpInfo *info, + const struct GuestPhysBlockList *guest_phys_blocks) + { +@@ -454,6 +470,7 @@ int cpu_get_dump_info(ArchDumpInfo *info, + info->arch_sections_add_fn = *arch_sections_add; + info->arch_sections_write_hdr_fn = *arch_sections_write_hdr; + info->arch_sections_write_fn = *arch_sections_write; ++ info->arch_cleanup_fn = *arch_cleanup; + } + return 0; + } +-- +2.39.3 + diff --git a/SOURCES/kvm-target-s390x-dump-Remove-unneeded-dump-info-function.patch b/SOURCES/kvm-target-s390x-dump-Remove-unneeded-dump-info-function.patch new file mode 100644 index 0000000..dee0bfc --- /dev/null +++ b/SOURCES/kvm-target-s390x-dump-Remove-unneeded-dump-info-function.patch @@ -0,0 +1,56 @@ +From f647258696cbdce78316b2d9ae513f9ae6f4a0b5 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 17 Nov 2023 11:32:37 +0100 +Subject: [PATCH 1/3] target/s390x/dump: Remove unneeded dump info function + pointer init +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Thomas Huth +RH-MergeRequest: 323: Fix problem that secure execution guest might remain in "paused" state after failed dump +RH-Jira: RHEL-16696 +RH-Acked-by: Marc-André Lureau +RH-Acked-by: Cédric Le Goater +RH-Commit: [1/3] e3b0697ec76274f778fc523efb72f0cbca25cd77 + +JIRA: https://issues.redhat.com/browse/RHEL-16696 + +commit 816644b1219900875f47d7adf9bfb283f1b29aa0 +Author: Janosch Frank +Date: Thu Nov 9 12:04:41 2023 +0000 + + target/s390x/dump: Remove unneeded dump info function pointer init + + dump_state_prepare() now sets the function pointers to NULL so we only + need to touch them if we're going to use them. + + Signed-off-by: Janosch Frank + Reviewed-by: Marc-André Lureau + Reviewed-by: Thomas Huth + Message-ID: <20231109120443.185979-2-frankja@linux.ibm.com> + Signed-off-by: Thomas Huth + +Signed-off-by: Thomas Huth +--- + target/s390x/arch_dump.c | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/target/s390x/arch_dump.c b/target/s390x/arch_dump.c +index a7c44ba49d..7cdd4b7167 100644 +--- a/target/s390x/arch_dump.c ++++ b/target/s390x/arch_dump.c +@@ -454,10 +454,6 @@ int cpu_get_dump_info(ArchDumpInfo *info, + info->arch_sections_add_fn = *arch_sections_add; + info->arch_sections_write_hdr_fn = *arch_sections_write_hdr; + info->arch_sections_write_fn = *arch_sections_write; +- } else { +- info->arch_sections_add_fn = NULL; +- info->arch_sections_write_hdr_fn = NULL; +- info->arch_sections_write_fn = NULL; + } + return 0; + } +-- +2.39.3 + diff --git a/SOURCES/kvm-target-s390x-kvm-Refactor-AP-functionalities.patch b/SOURCES/kvm-target-s390x-kvm-Refactor-AP-functionalities.patch new file mode 100644 index 0000000..5aa8fcd --- /dev/null +++ b/SOURCES/kvm-target-s390x-kvm-Refactor-AP-functionalities.patch @@ -0,0 +1,111 @@ +From 57bcc768ac7d0614472e60cc2833b74a2a198d29 Mon Sep 17 00:00:00 2001 +From: Steffen Eiden +Date: Wed, 23 Aug 2023 16:22:18 +0200 +Subject: [PATCH 4/5] target/s390x/kvm: Refactor AP functionalities +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Thomas Huth +RH-MergeRequest: 321: Enable Secure Execution Crypto Passthrough for KVM on s390x +RH-Bugzilla: 2111390 +RH-Acked-by: Cédric Le Goater +RH-Commit: [4/5] 8ab2f8766931fb65a391aab590d0ccabd8ba8909 + +kvm_s390_set_attr() is a misleading name as it only sets attributes for +the KVM_S390_VM_CRYPTO group. Therefore, rename it to +kvm_s390_set_crypto_attr(). + +Add new functions ap_available() and ap_enabled() to avoid code +duplication later. + +Reviewed-by: Thomas Huth +Reviewed-by: Michael Mueller +Signed-off-by: Steffen Eiden +Message-ID: <20230823142219.1046522-5-seiden@linux.ibm.com> +Signed-off-by: Thomas Huth +(cherry picked from commit 354383c12294f2ee510204cfdc5aaed9f0c42171) +--- + target/s390x/kvm/kvm.c | 24 +++++++++++++++++------- + 1 file changed, 17 insertions(+), 7 deletions(-) + +diff --git a/target/s390x/kvm/kvm.c b/target/s390x/kvm/kvm.c +index 8d36c377b5..eb8ca4c780 100644 +--- a/target/s390x/kvm/kvm.c ++++ b/target/s390x/kvm/kvm.c +@@ -251,7 +251,7 @@ static void kvm_s390_enable_cmma(void) + trace_kvm_enable_cmma(rc); + } + +-static void kvm_s390_set_attr(uint64_t attr) ++static void kvm_s390_set_crypto_attr(uint64_t attr) + { + struct kvm_device_attr attribute = { + .group = KVM_S390_VM_CRYPTO, +@@ -276,7 +276,7 @@ static void kvm_s390_init_aes_kw(void) + } + + if (kvm_vm_check_attr(kvm_state, KVM_S390_VM_CRYPTO, attr)) { +- kvm_s390_set_attr(attr); ++ kvm_s390_set_crypto_attr(attr); + } + } + +@@ -290,7 +290,7 @@ static void kvm_s390_init_dea_kw(void) + } + + if (kvm_vm_check_attr(kvm_state, KVM_S390_VM_CRYPTO, attr)) { +- kvm_s390_set_attr(attr); ++ kvm_s390_set_crypto_attr(attr); + } + } + +@@ -2297,6 +2297,17 @@ static int configure_cpu_subfunc(const S390FeatBitmap features) + return kvm_vm_ioctl(kvm_state, KVM_SET_DEVICE_ATTR, &attr); + } + ++static bool ap_available(void) ++{ ++ return kvm_vm_check_attr(kvm_state, KVM_S390_VM_CRYPTO, ++ KVM_S390_VM_CRYPTO_ENABLE_APIE); ++} ++ ++static bool ap_enabled(const S390FeatBitmap features) ++{ ++ return test_bit(S390_FEAT_AP, features); ++} ++ + static int kvm_to_feat[][2] = { + { KVM_S390_VM_CPU_FEAT_ESOP, S390_FEAT_ESOP }, + { KVM_S390_VM_CPU_FEAT_SIEF2, S390_FEAT_SIE_F2 }, +@@ -2476,8 +2487,7 @@ void kvm_s390_get_host_cpu_model(S390CPUModel *model, Error **errp) + return; + } + /* for now, we can only provide the AP feature with HW support */ +- if (kvm_vm_check_attr(kvm_state, KVM_S390_VM_CRYPTO, +- KVM_S390_VM_CRYPTO_ENABLE_APIE)) { ++ if (ap_available()) { + set_bit(S390_FEAT_AP, model->features); + } + +@@ -2503,7 +2513,7 @@ static void kvm_s390_configure_apie(bool interpret) + KVM_S390_VM_CRYPTO_DISABLE_APIE; + + if (kvm_vm_check_attr(kvm_state, KVM_S390_VM_CRYPTO, attr)) { +- kvm_s390_set_attr(attr); ++ kvm_s390_set_crypto_attr(attr); + } + } + +@@ -2565,7 +2575,7 @@ void kvm_s390_apply_cpu_model(const S390CPUModel *model, Error **errp) + kvm_s390_enable_cmma(); + } + +- if (test_bit(S390_FEAT_AP, model->features)) { ++ if (ap_enabled(model->features)) { + kvm_s390_configure_apie(true); + } + } +-- +2.41.0 + diff --git a/SOURCES/kvm-target-s390x-kvm-pv-Provide-some-more-useful-informa.patch b/SOURCES/kvm-target-s390x-kvm-pv-Provide-some-more-useful-informa.patch new file mode 100644 index 0000000..dd05215 --- /dev/null +++ b/SOURCES/kvm-target-s390x-kvm-pv-Provide-some-more-useful-informa.patch @@ -0,0 +1,207 @@ +From c1273f9e38f81f912cd2bd1dd4a43f9652766f76 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Wed, 10 Jan 2024 15:29:16 +0100 +Subject: [PATCH 5/5] target/s390x/kvm/pv: Provide some more useful information + if decryption fails +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Thomas Huth +RH-MergeRequest: 348: s390x: Provide some more useful information if decryption of a PV image fails +RH-Jira: RHEL-18214 +RH-Acked-by: Jon Maloy +RH-Acked-by: Cédric Le Goater +RH-Commit: [5/5] 087acaecfaa5921b409beb212123214fa79fe50c + +JIRA: https://issues.redhat.com/browse/RHEL-18214 + +commit 7af51621b16ae86646cc2dc9dee30de8176ff761 +Author: Thomas Huth +Date: Wed Jan 10 15:29:16 2024 +0100 + + target/s390x/kvm/pv: Provide some more useful information if decryption fails + + It's a common scenario to copy guest images from one host to another + to run the guest on the other machine. This (of course) does not work + with "secure execution" guests since they are encrypted with one certain + host key. However, if you still (accidentally) do it, you only get a + very user-unfriendly error message that looks like this: + + qemu-system-s390x: KVM PV command 2 (KVM_PV_SET_SEC_PARMS) failed: + header rc 108 rrc 5 IOCTL rc: -22 + + Let's provide at least a somewhat nicer hint to the users so that they + are able to figure out what might have gone wrong. + + Message-ID: <20240110142916.850605-1-thuth@redhat.com> + Reviewed-by: Philippe Mathieu-Daudé + Reviewed-by: Cédric Le Goater + Reviewed-by: Claudio Imbrenda + Signed-off-by: Thomas Huth + +Conflicts: + target/s390x/kvm/pv.c + target/s390x/kvm/pv.h + (contextual conflict due to missing async-teardown in RHEL8) +Signed-off-by: Thomas Huth +--- + hw/s390x/ipl.c | 5 ++--- + hw/s390x/ipl.h | 2 +- + hw/s390x/s390-virtio-ccw.c | 5 ++++- + target/s390x/kvm/pv.c | 25 ++++++++++++++++++++----- + target/s390x/kvm/pv.h | 5 +++-- + 5 files changed, 30 insertions(+), 12 deletions(-) + +diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c +index c25e247426..c6cefdd3fe 100644 +--- a/hw/s390x/ipl.c ++++ b/hw/s390x/ipl.c +@@ -709,7 +709,7 @@ static void s390_ipl_prepare_qipl(S390CPU *cpu) + cpu_physical_memory_unmap(addr, len, 1, len); + } + +-int s390_ipl_prepare_pv_header(void) ++int s390_ipl_prepare_pv_header(Error **errp) + { + IplParameterBlock *ipib = s390_ipl_get_iplb_pv(); + IPLBlockPV *ipib_pv = &ipib->pv; +@@ -718,8 +718,7 @@ int s390_ipl_prepare_pv_header(void) + + cpu_physical_memory_read(ipib_pv->pv_header_addr, hdr, + ipib_pv->pv_header_len); +- rc = s390_pv_set_sec_parms((uintptr_t)hdr, +- ipib_pv->pv_header_len); ++ rc = s390_pv_set_sec_parms((uintptr_t)hdr, ipib_pv->pv_header_len, errp); + g_free(hdr); + return rc; + } +diff --git a/hw/s390x/ipl.h b/hw/s390x/ipl.h +index dfc6dfd89c..f9cce33330 100644 +--- a/hw/s390x/ipl.h ++++ b/hw/s390x/ipl.h +@@ -107,7 +107,7 @@ typedef union IplParameterBlock IplParameterBlock; + + int s390_ipl_set_loadparm(uint8_t *loadparm); + void s390_ipl_update_diag308(IplParameterBlock *iplb); +-int s390_ipl_prepare_pv_header(void); ++int s390_ipl_prepare_pv_header(Error **errp); + int s390_ipl_pv_unpack(void); + void s390_ipl_prepare_cpu(S390CPU *cpu); + IplParameterBlock *s390_ipl_get_iplb(void); +diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c +index 7bfa5b4e8f..94434c3bb1 100644 +--- a/hw/s390x/s390-virtio-ccw.c ++++ b/hw/s390x/s390-virtio-ccw.c +@@ -374,7 +374,7 @@ static int s390_machine_protect(S390CcwMachineState *ms) + } + + /* Set SE header and unpack */ +- rc = s390_ipl_prepare_pv_header(); ++ rc = s390_ipl_prepare_pv_header(&local_err); + if (rc) { + goto out_err; + } +@@ -393,6 +393,9 @@ static int s390_machine_protect(S390CcwMachineState *ms) + return rc; + + out_err: ++ if (local_err) { ++ error_report_err(local_err); ++ } + s390_machine_unprotect(ms); + return rc; + } +diff --git a/target/s390x/kvm/pv.c b/target/s390x/kvm/pv.c +index e14db4f41a..ae75063777 100644 +--- a/target/s390x/kvm/pv.c ++++ b/target/s390x/kvm/pv.c +@@ -27,7 +27,8 @@ static bool info_valid; + static struct kvm_s390_pv_info_vm info_vm; + static struct kvm_s390_pv_info_dump info_dump; + +-static int __s390_pv_cmd(uint32_t cmd, const char *cmdname, void *data) ++static int __s390_pv_cmd(uint32_t cmd, const char *cmdname, void *data, ++ int *pvrc) + { + struct kvm_pv_cmd pv_cmd = { + .cmd = cmd, +@@ -44,6 +45,9 @@ static int __s390_pv_cmd(uint32_t cmd, const char *cmdname, void *data) + "IOCTL rc: %d", cmd, cmdname, pv_cmd.rc, pv_cmd.rrc, + rc); + } ++ if (pvrc) { ++ *pvrc = pv_cmd.rc; ++ } + return rc; + } + +@@ -51,12 +55,13 @@ static int __s390_pv_cmd(uint32_t cmd, const char *cmdname, void *data) + * This macro lets us pass the command as a string to the function so + * we can print it on an error. + */ +-#define s390_pv_cmd(cmd, data) __s390_pv_cmd(cmd, #cmd, data) ++#define s390_pv_cmd(cmd, data) __s390_pv_cmd(cmd, #cmd, data, NULL) ++#define s390_pv_cmd_pvrc(cmd, data, pvrc) __s390_pv_cmd(cmd, #cmd, data, pvrc) + #define s390_pv_cmd_exit(cmd, data) \ + { \ + int rc; \ + \ +- rc = __s390_pv_cmd(cmd, #cmd, data);\ ++ rc = __s390_pv_cmd(cmd, #cmd, data, NULL); \ + if (rc) { \ + exit(1); \ + } \ +@@ -108,14 +113,24 @@ void s390_pv_vm_disable(void) + s390_pv_cmd_exit(KVM_PV_DISABLE, NULL); + } + +-int s390_pv_set_sec_parms(uint64_t origin, uint64_t length) ++int s390_pv_set_sec_parms(uint64_t origin, uint64_t length, Error **errp) + { ++ int ret, pvrc; + struct kvm_s390_pv_sec_parm args = { + .origin = origin, + .length = length, + }; + +- return s390_pv_cmd(KVM_PV_SET_SEC_PARMS, &args); ++ ret = s390_pv_cmd_pvrc(KVM_PV_SET_SEC_PARMS, &args, &pvrc); ++ if (ret) { ++ error_setg(errp, "Failed to set secure execution parameters"); ++ if (pvrc == 0x108) { ++ error_append_hint(errp, "Please check whether the image is " ++ "correctly encrypted for this host\n"); ++ } ++ } ++ ++ return ret; + } + + /* +diff --git a/target/s390x/kvm/pv.h b/target/s390x/kvm/pv.h +index 9360aa1091..6868c3f4ac 100644 +--- a/target/s390x/kvm/pv.h ++++ b/target/s390x/kvm/pv.h +@@ -41,7 +41,7 @@ static inline bool s390_is_pv(void) + int s390_pv_query_info(void); + int s390_pv_vm_enable(void); + void s390_pv_vm_disable(void); +-int s390_pv_set_sec_parms(uint64_t origin, uint64_t length); ++int s390_pv_set_sec_parms(uint64_t origin, uint64_t length, Error **errp); + int s390_pv_unpack(uint64_t addr, uint64_t size, uint64_t tweak); + void s390_pv_prep_reset(void); + int s390_pv_verify(void); +@@ -60,7 +60,8 @@ static inline bool s390_is_pv(void) { return false; } + static inline int s390_pv_query_info(void) { return 0; } + static inline int s390_pv_vm_enable(void) { return 0; } + static inline void s390_pv_vm_disable(void) {} +-static inline int s390_pv_set_sec_parms(uint64_t origin, uint64_t length) { return 0; } ++static inline int s390_pv_set_sec_parms(uint64_t origin, uint64_t length, ++ Error **errp) { return 0; } + static inline int s390_pv_unpack(uint64_t addr, uint64_t size, uint64_t tweak) { return 0; } + static inline void s390_pv_prep_reset(void) {} + static inline int s390_pv_verify(void) { return 0; } +-- +2.41.0 + diff --git a/SOURCES/kvm-tests-qtest-ahci-test-add-test-exposing-reset-issue-.patch b/SOURCES/kvm-tests-qtest-ahci-test-add-test-exposing-reset-issue-.patch new file mode 100644 index 0000000..964f459 --- /dev/null +++ b/SOURCES/kvm-tests-qtest-ahci-test-add-test-exposing-reset-issue-.patch @@ -0,0 +1,151 @@ +From b5a7e5e22a52d11034b997d2bd363c3f83f168e9 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Fri, 24 Nov 2023 12:17:53 -0500 +Subject: [PATCH 2/2] tests/qtest: ahci-test: add test exposing reset issue + with pending callback +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Jon Maloy +RH-MergeRequest: 335: hw/ide: reset: cancel async DMA operation before resetting state +RH-Jira: RHEL-15437 +RH-Acked-by: Hanna Czenczek +RH-Acked-by: Paolo Bonzini +RH-Commit: [2/2] 364e0703d22d69a4c1cfcff250ad0a3c81ada7b2 (redhat/rhel/src/qemu-kvm/jons-qemu-kvm-2) + +JIRA: https://issues.redhat.com/browse/RHEL-15437 +CVE: CVE-2023-5088 +Upstream: Merged + +commit cc610857bbd3551f4b86ae2299336b5d9aa0db2b +Author: Fiona Ebner +Date: Wed Sep 6 15:09:22 2023 +0200 + + tests/qtest: ahci-test: add test exposing reset issue with pending callback + + Before commit "hw/ide: reset: cancel async DMA operation before + resetting state", this test would fail, because a reset with a + pending write operation would lead to an unsolicited write to the + first sector of the disk. + + The test writes a pattern to the beginning of the disk and verifies + that it is still intact after a reset with a pending operation. It + also checks that the pending operation actually completes correctly. + + Signed-off-by: Fiona Ebner + Message-ID: <20230906130922.142845-2-f.ebner@proxmox.com> + Signed-off-by: Philippe Mathieu-Daudé + +Signed-off-by: Jon Maloy +--- + tests/qtest/ahci-test.c | 86 ++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 85 insertions(+), 1 deletion(-) + +diff --git a/tests/qtest/ahci-test.c b/tests/qtest/ahci-test.c +index 8073ccc205..b4d15566e1 100644 +--- a/tests/qtest/ahci-test.c ++++ b/tests/qtest/ahci-test.c +@@ -1425,6 +1425,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; +@@ -1929,7 +2012,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); +-- +2.41.0 + diff --git a/SOURCES/kvm-ui-fix-crash-when-there-are-no-active_console.patch b/SOURCES/kvm-ui-fix-crash-when-there-are-no-active_console.patch new file mode 100644 index 0000000..b115984 --- /dev/null +++ b/SOURCES/kvm-ui-fix-crash-when-there-are-no-active_console.patch @@ -0,0 +1,55 @@ +From 8a233fd50c4ab973ef4a3c4ac7daf83e5c90aabc Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= +Date: Mon, 11 Sep 2023 18:04:47 +0400 +Subject: [PATCH 4/4] ui: fix crash when there are no active_console +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Marc-André Lureau +RH-MergeRequest: 338: ui: fix crash when there are no active_console +RH-Jira: RHEL-2600 +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Vitaly Kuznetsov +RH-Commit: [1/1] c58d1d76558dbc7ee2a8193a1e7a9b87a79ac385 + +JIRA: https://issues.redhat.com/browse/RHEL-2600 + +Thread 1 "qemu-system-x86" received signal SIGSEGV, Segmentation fault. +0x0000555555888630 in dpy_ui_info_supported (con=0x0) at ../ui/console.c:812 +812 return con->hw_ops->ui_info != NULL; +(gdb) bt +#0 0x0000555555888630 in dpy_ui_info_supported (con=0x0) at ../ui/console.c:812 +#1 0x00005555558a44b1 in protocol_client_msg (vs=0x5555578c76c0, data=0x5555581e93f0 , len=24) at ../ui/vnc.c:2585 +#2 0x00005555558a19ac in vnc_client_read (vs=0x5555578c76c0) at ../ui/vnc.c:1607 +#3 0x00005555558a1ac2 in vnc_client_io (ioc=0x5555581eb0e0, condition=G_IO_IN, opaque=0x5555578c76c0) at ../ui/vnc.c:1635 + +Fixes: +https://issues.redhat.com/browse/RHEL-2600 + +Signed-off-by: Marc-André Lureau +Reviewed-by: Albert Esteve + +(cherry picked from commit 48a35e12faf90a896c5aa4755812201e00d60316) +Signed-off-by: Marc-André Lureau +--- + ui/console.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/ui/console.c b/ui/console.c +index 29a3e3f0f5..df3426bd8a 100644 +--- a/ui/console.c ++++ b/ui/console.c +@@ -1525,6 +1525,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; + } +-- +2.41.0 + diff --git a/SOURCES/kvm-ui-vnc-clipboard-fix-infinite-loop-in-inflate_buffer.patch b/SOURCES/kvm-ui-vnc-clipboard-fix-infinite-loop-in-inflate_buffer.patch new file mode 100644 index 0000000..08ecc15 --- /dev/null +++ b/SOURCES/kvm-ui-vnc-clipboard-fix-infinite-loop-in-inflate_buffer.patch @@ -0,0 +1,76 @@ +From efbf51a42b51665fd70ea49b9c583a208cfd2deb Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Tue, 4 Jul 2023 10:41:22 +0200 +Subject: [PATCH] ui/vnc-clipboard: fix infinite loop in inflate_buffer + (CVE-2023-3255) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Jon Maloy +RH-MergeRequest: 316: ui/vnc-clipboard: fix infinite loop in inflate_buffer (CVE-2023-3255) +RH-Bugzilla: 2218488 +RH-Acked-by: Mauro Matteo Cascella +RH-Commit: [1/1] f3cb05fb6e40261da5fe10f003fa3e57920469bb (redhat/rhel/src/qemu-kvm/jons-qemu-kvm-2) + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2218488 +CVE: CVE-2023-3255 +Upstream: Merged + +commit d921fea338c1059a27ce7b75309d7a2e485f710b +Author: Mauro Matteo Cascella +Date: Tue Jul 4 10:41:22 2023 +0200 + + ui/vnc-clipboard: fix infinite loop in inflate_buffer (CVE-2023-3255) + + A wrong exit condition may lead to an infinite loop when inflating a + valid zlib buffer containing some extra bytes in the `inflate_buffer` + function. The bug only occurs post-authentication. Return the buffer + immediately if the end of the compressed data has been reached + (Z_STREAM_END). + + Fixes: CVE-2023-3255 + Fixes: 0bf41cab ("ui/vnc: clipboard support") + Reported-by: Kevin Denis + Signed-off-by: Mauro Matteo Cascella + Reviewed-by: Marc-André Lureau + Tested-by: Marc-André Lureau + Message-ID: <20230704084210.101822-1-mcascell@redhat.com> + +Signed-off-by: Jon Maloy +--- + ui/vnc-clipboard.c | 10 ++++------ + 1 file changed, 4 insertions(+), 6 deletions(-) + +diff --git a/ui/vnc-clipboard.c b/ui/vnc-clipboard.c +index 67284b556c..c84599cfdb 100644 +--- a/ui/vnc-clipboard.c ++++ b/ui/vnc-clipboard.c +@@ -51,8 +51,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)) { +@@ -67,11 +70,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: +-- +2.41.0 + diff --git a/SOURCES/kvm-vhost-release-memory_listener-object-in-error-path.patch b/SOURCES/kvm-vhost-release-memory_listener-object-in-error-path.patch new file mode 100644 index 0000000..d804531 --- /dev/null +++ b/SOURCES/kvm-vhost-release-memory_listener-object-in-error-path.patch @@ -0,0 +1,69 @@ +From a728c0b522997e8e63bf6b64b202a7ae48693d02 Mon Sep 17 00:00:00 2001 +From: Prasad Pandit +Date: Fri, 18 Aug 2023 16:38:12 +0530 +Subject: [PATCH 3/4] vhost: release memory_listener object in error path + +RH-Author: Prasad Pandit +RH-MergeRequest: 337: vhost: release memory_listener object in error path +RH-Jira: RHEL-7567 +RH-Acked-by: Peter Xu +RH-Acked-by: Jon Maloy +RH-Commit: [1/1] 1e377a2f6f148e11a452d11107d839521354e2ca + +Jira: https://issues.redhat.com/browse/RHEL-7567 + +commit 1e3ffb34f764f8ac4c003b2b2e6a775b2b073a16 +Author: Prasad J Pandit +Date: Mon May 29 17:13:32 2023 +0530 + + vhost: release memory_listener object in error path + + vhost_dev_start function does not release memory_listener object + in case of an error. This may crash the guest when vhost is unable + to set memory table: + + stack trace of thread 125653: + Program terminated with signal SIGSEGV, Segmentation fault + #0 memory_listener_register (qemu-kvm + 0x6cda0f) + #1 vhost_dev_start (qemu-kvm + 0x699301) + #2 vhost_net_start (qemu-kvm + 0x45b03f) + #3 virtio_net_set_status (qemu-kvm + 0x665672) + #4 qmp_set_link (qemu-kvm + 0x548fd5) + #5 net_vhost_user_event (qemu-kvm + 0x552c45) + #6 tcp_chr_connect (qemu-kvm + 0x88d473) + #7 tcp_chr_new_client (qemu-kvm + 0x88cf83) + #8 tcp_chr_accept (qemu-kvm + 0x88b429) + #9 qio_net_listener_channel_func (qemu-kvm + 0x7ac07c) + #10 g_main_context_dispatch (libglib-2.0.so.0 + 0x54e2f) + + Release memory_listener objects in the error path. + + Signed-off-by: Prasad Pandit + Message-Id: <20230529114333.31686-2-ppandit@redhat.com> + Reviewed-by: Michael S. Tsirkin + Signed-off-by: Michael S. Tsirkin + Reviewed-by: Peter Xu + Fixes: c471ad0e9b ("vhost_net: device IOTLB support") + Cc: qemu-stable@nongnu.org + Acked-by: Jason Wang +--- + hw/virtio/vhost.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c +index 437347ad01..639029aa76 100644 +--- a/hw/virtio/vhost.c ++++ b/hw/virtio/vhost.c +@@ -1818,6 +1818,9 @@ fail_vq: + } + + fail_mem: ++ if (vhost_dev_has_iommu(hdev)) { ++ memory_listener_unregister(&hdev->iommu_listener); ++ } + fail_features: + + hdev->started = false; +-- +2.41.0 + diff --git a/SPECS/qemu-kvm.spec b/SPECS/qemu-kvm.spec index d5f12be..1aca466 100644 --- a/SPECS/qemu-kvm.spec +++ b/SPECS/qemu-kvm.spec @@ -83,7 +83,7 @@ Obsoletes: %1-rhev <= %{epoch}:%{version}-%{release} Summary: QEMU is a machine emulator and virtualizer Name: qemu-kvm Version: 6.2.0 -Release: 39%{?rcrel}%{?dist} +Release: 48%{?rcrel}%{?dist} # Epoch because we pushed a qemu-1.0 package. AIUI this can't ever be dropped Epoch: 15 License: GPLv2 and GPLv2+ and CC-BY @@ -781,6 +781,66 @@ Patch309: kvm-i386-cpu-Update-how-the-EBX-register-of-CPUID-0x8000.patch Patch310: kvm-target-i386-kvm-Fix-disabling-MPX-on-cpu-host-with-M.patch # For bz#2215786 - CVE-2023-3301 virt:rhel/qemu-kvm: QEMU: net: triggerable assertion due to race condition in hot-unplug [rhel-8] Patch311: kvm-vhost-vdpa-do-not-cleanup-the-vdpa-vhost-net-structu.patch +# For bz#2218488 - CVE-2023-3255 virt:rhel/qemu-kvm: QEMU: VNC: infinite loop in inflate_buffer() leads to denial of service [rhel-8] +Patch312: kvm-ui-vnc-clipboard-fix-infinite-loop-in-inflate_buffer.patch +# For bz#2111390 - [IBM 8.10 FEAT] KVM: Enable Secure Execution Crypto Passthrough - qemu part +Patch313: kvm-s390x-ap-fix-missing-subsystem-reset-registration.patch +# For bz#2111390 - [IBM 8.10 FEAT] KVM: Enable Secure Execution Crypto Passthrough - qemu part +Patch314: kvm-s390x-do-a-subsystem-reset-before-the-unprotect-on-r.patch +# For bz#2111390 - [IBM 8.10 FEAT] KVM: Enable Secure Execution Crypto Passthrough - qemu part +Patch315: kvm-redhat-Update-linux-headers-for-kvm_s390_vm_cpu_uv_f.patch +# For bz#2111390 - [IBM 8.10 FEAT] KVM: Enable Secure Execution Crypto Passthrough - qemu part +Patch316: kvm-target-s390x-kvm-Refactor-AP-functionalities.patch +# For bz#2111390 - [IBM 8.10 FEAT] KVM: Enable Secure Execution Crypto Passthrough - qemu part +Patch317: kvm-target-s390x-AP-passthrough-for-PV-guests.patch +# For RHEL-16696 - RHEL8 - KVM : Secure execution guest remains in "paused" state, post "virsh dump" failure (qemu-kvm) +Patch318: kvm-target-s390x-dump-Remove-unneeded-dump-info-function.patch +# For RHEL-16696 - RHEL8 - KVM : Secure execution guest remains in "paused" state, post "virsh dump" failure (qemu-kvm) +Patch319: kvm-dump-Add-arch-cleanup-function.patch +# For RHEL-16696 - RHEL8 - KVM : Secure execution guest remains in "paused" state, post "virsh dump" failure (qemu-kvm) +Patch320: kvm-target-s390x-arch_dump-Add-arch-cleanup-function-for.patch +# For RHEL-7309 - CVE-2023-3019 virt:rhel/qemu-kvm: QEMU: e1000e: heap use-after-free in e1000e_write_packet_to_guest() [rhel-8] +Patch321: kvm-net-Provide-MemReentrancyGuard-to-qemu_new_nic.patch +# For RHEL-7309 - CVE-2023-3019 virt:rhel/qemu-kvm: QEMU: e1000e: heap use-after-free in e1000e_write_packet_to_guest() [rhel-8] +Patch322: kvm-net-Update-MemReentrancyGuard-for-NIC.patch +# For RHEL-7567 - [RHEL8][clone]VM crash when guest running testpmd and delete created vhostuserclient port on host +Patch323: kvm-vhost-release-memory_listener-object-in-error-path.patch +# For RHEL-2600 - qemu core dump occurs when client connects to VNC server because qemu cmd only adds vnc but without graphics device +Patch324: kvm-ui-fix-crash-when-there-are-no-active_console.patch +# For RHEL-15437 - CVE-2023-5088 virt:rhel/qemu-kvm: QEMU: improper IDE controller reset can lead to MBR overwrite [rhel-8] +Patch325: kvm-hw-ide-reset-cancel-async-DMA-operation-before-reset.patch +# For RHEL-15437 - CVE-2023-5088 virt:rhel/qemu-kvm: QEMU: improper IDE controller reset can lead to MBR overwrite [rhel-8] +Patch326: kvm-tests-qtest-ahci-test-add-test-exposing-reset-issue-.patch +# For RHEL-20189 - [RHEL.8.10.0]Failed to migrate guest with pc (i440x) between RHELAV 8.4.0 and RHEL 8.10.0 +Patch327: kvm-acpi-fix-acpi_index-migration.patch +# For RHEL-20189 - [RHEL.8.10.0]Failed to migrate guest with pc (i440x) between RHELAV 8.4.0 and RHEL 8.10.0 +Patch328: kvm-RHEL-Enable-x-not-migrate-acpi-index-for-all-pre-RHE.patch +# For RHEL-14870 - [rhel8]ipxe-roms-qemu does not provide efi-virtio.rom +Patch329: kvm-hw-arm-virt-Do-not-load-efi-virtio.rom-for-all-virti.patch +# For RHEL-18214 - [RHEL8][Secure-execution][s390x] The error message is not clear when boot up a SE guest with wrong encryption +Patch330: kvm-MAINTAINERS-split-out-s390x-sections.patch +# For RHEL-18214 - [RHEL8][Secure-execution][s390x] The error message is not clear when boot up a SE guest with wrong encryption +Patch331: kvm-s390x-pv-remove-semicolon-from-macro-definition.patch +# For RHEL-18214 - [RHEL8][Secure-execution][s390x] The error message is not clear when boot up a SE guest with wrong encryption +Patch332: kvm-hw-s390x-pv-Restrict-Protected-Virtualization-to-sys.patch +# For RHEL-18214 - [RHEL8][Secure-execution][s390x] The error message is not clear when boot up a SE guest with wrong encryption +Patch333: kvm-hw-s390x-Move-KVM-specific-PV-from-hw-to-target-s390.patch +# For RHEL-18214 - [RHEL8][Secure-execution][s390x] The error message is not clear when boot up a SE guest with wrong encryption +Patch334: kvm-target-s390x-kvm-pv-Provide-some-more-useful-informa.patch +# For RHEL-22411 - [s390x] VM fails to start with ISM passed through +Patch335: kvm-s390x-pci-avoid-double-enable-disable-of-aif.patch +# For RHEL-22411 - [s390x] VM fails to start with ISM passed through +Patch336: kvm-s390x-pci-refresh-fh-before-disabling-aif.patch +# For RHEL-22411 - [s390x] VM fails to start with ISM passed through +Patch337: kvm-s390x-pci-drive-ISM-reset-from-subsystem-reset.patch +# For RHEL-7353 - [qemu-kvm] no response with QMP command device_add when repeatedly hotplug/unplug virtio disks [RHEL-8] +Patch338: kvm-iotests-add-filter_qmp_generated_node_ids.patch +# For RHEL-7353 - [qemu-kvm] no response with QMP command device_add when repeatedly hotplug/unplug virtio disks [RHEL-8] +Patch339: kvm-iotests-port-141-to-Python-for-reliable-QMP-testing.patch +# For RHEL-7353 - [qemu-kvm] no response with QMP command device_add when repeatedly hotplug/unplug virtio disks [RHEL-8] +Patch340: kvm-monitor-only-run-coroutine-commands-in-qemu_aio_cont.patch +# For RHEL-7353 - [qemu-kvm] no response with QMP command device_add when repeatedly hotplug/unplug virtio disks [RHEL-8] +Patch341: kvm-iotests-Make-144-deterministic-again.patch BuildRequires: wget BuildRequires: rpm-build @@ -1950,6 +2010,78 @@ sh %{_sysconfdir}/sysconfig/modules/kvm.modules &> /dev/null || : %changelog +* Mon Feb 26 2024 Miroslav Rezanina - 6.2.0-48 +- kvm-iotests-add-filter_qmp_generated_node_ids.patch [RHEL-7353] +- kvm-iotests-port-141-to-Python-for-reliable-QMP-testing.patch [RHEL-7353] +- kvm-monitor-only-run-coroutine-commands-in-qemu_aio_cont.patch [RHEL-7353] +- kvm-iotests-Make-144-deterministic-again.patch [RHEL-7353] +- Resolves: RHEL-7353 + ([qemu-kvm] no response with QMP command device_add when repeatedly hotplug/unplug virtio disks [RHEL-8]) + +* Sat Feb 03 2024 Jon Maloy - 6.2.0-47 +- kvm-s390x-pci-avoid-double-enable-disable-of-aif.patch [RHEL-22411] +- kvm-s390x-pci-refresh-fh-before-disabling-aif.patch [RHEL-22411] +- kvm-s390x-pci-drive-ISM-reset-from-subsystem-reset.patch [RHEL-22411] +- Resolves: RHEL-22411 + ([s390x] VM fails to start with ISM passed through) + +* Wed Jan 17 2024 Jon Maloy - 6.2.0-46 +- kvm-MAINTAINERS-split-out-s390x-sections.patch [RHEL-18214] +- kvm-s390x-pv-remove-semicolon-from-macro-definition.patch [RHEL-18214] +- kvm-hw-s390x-pv-Restrict-Protected-Virtualization-to-sys.patch [RHEL-18214] +- kvm-hw-s390x-Move-KVM-specific-PV-from-hw-to-target-s390.patch [RHEL-18214] +- kvm-target-s390x-kvm-pv-Provide-some-more-useful-informa.patch [RHEL-18214] +- Resolves: RHEL-18214 + ([RHEL8][Secure-execution][s390x] The error message is not clear when boot up a SE guest with wrong encryption) + +* Thu Jan 04 2024 Jon Maloy - 6.2.0-45 +- kvm-acpi-fix-acpi_index-migration.patch [RHEL-20189] +- kvm-RHEL-Enable-x-not-migrate-acpi-index-for-all-pre-RHE.patch [RHEL-20189] +- kvm-hw-arm-virt-Do-not-load-efi-virtio.rom-for-all-virti.patch [RHEL-14870] +- Resolves: RHEL-20189 + ([RHEL.8.10.0]Failed to migrate guest with pc (i440x) between RHELAV 8.4.0 and RHEL 8.10.0) +- Resolves: RHEL-14870 + ([rhel8]ipxe-roms-qemu does not provide efi-virtio.rom) + +* Wed Dec 13 2023 Jon Maloy - 6.2.0-44 +- kvm-hw-ide-reset-cancel-async-DMA-operation-before-reset.patch [RHEL-15437] +- kvm-tests-qtest-ahci-test-add-test-exposing-reset-issue-.patch [RHEL-15437] +- Resolves: RHEL-15437 + (CVE-2023-5088 virt:rhel/qemu-kvm: QEMU: improper IDE controller reset can lead to MBR overwrite [rhel-8]) + +* Wed Dec 06 2023 Jon Maloy - 6.2.0-43 +- kvm-net-Provide-MemReentrancyGuard-to-qemu_new_nic.patch [RHEL-7309] +- kvm-net-Update-MemReentrancyGuard-for-NIC.patch [RHEL-7309] +- kvm-vhost-release-memory_listener-object-in-error-path.patch [RHEL-7567] +- kvm-ui-fix-crash-when-there-are-no-active_console.patch [RHEL-2600] +- Resolves: RHEL-7309 + (CVE-2023-3019 virt:rhel/qemu-kvm: QEMU: e1000e: heap use-after-free in e1000e_write_packet_to_guest() [rhel-8]) +- Resolves: RHEL-7567 + ([RHEL8][clone]VM crash when guest running testpmd and delete created vhostuserclient port on host) +- Resolves: RHEL-2600 + (qemu core dump occurs when client connects to VNC server because qemu cmd only adds vnc but without graphics device) + +* Thu Nov 23 2023 Miroslav Rezanina - 6.2.0-42 +- kvm-target-s390x-dump-Remove-unneeded-dump-info-function.patch [RHEL-16696] +- kvm-dump-Add-arch-cleanup-function.patch [RHEL-16696] +- kvm-target-s390x-arch_dump-Add-arch-cleanup-function-for.patch [RHEL-16696] +- Resolves: RHEL-16696 + (RHEL8 - KVM : Secure execution guest remains in "paused" state, post "virsh dump" failure (qemu-kvm)) + +* Fri Sep 29 2023 Jon Maloy - 6.2.0-41 +- kvm-s390x-ap-fix-missing-subsystem-reset-registration.patch [bz#2111390] +- kvm-s390x-do-a-subsystem-reset-before-the-unprotect-on-r.patch [bz#2111390] +- kvm-redhat-Update-linux-headers-for-kvm_s390_vm_cpu_uv_f.patch [bz#2111390] +- kvm-target-s390x-kvm-Refactor-AP-functionalities.patch [bz#2111390] +- kvm-target-s390x-AP-passthrough-for-PV-guests.patch [bz#2111390] +- Resolves: bz#2111390 + ([IBM 8.10 FEAT] KVM: Enable Secure Execution Crypto Passthrough - qemu part) + +* Thu Sep 28 2023 Jon Maloy - 6.2.0-40 +- kvm-ui-vnc-clipboard-fix-infinite-loop-in-inflate_buffer.patch [bz#2218488] +- Resolves: bz#2218488 + (CVE-2023-3255 virt:rhel/qemu-kvm: QEMU: VNC: infinite loop in inflate_buffer() leads to denial of service [rhel-8]) + * Mon Aug 28 2023 Miroslav Rezanina - 6.2.0-39 - kvm-vhost-vdpa-do-not-cleanup-the-vdpa-vhost-net-structu.patch [bz#2215786] - Resolves: bz#2215786