diff --git a/SOURCES/kvm-Disable-CONFIG_I2C-and-CONFIG_IOH3420.patch b/SOURCES/kvm-Disable-CONFIG_I2C-and-CONFIG_IOH3420.patch new file mode 100644 index 0000000..a20255a --- /dev/null +++ b/SOURCES/kvm-Disable-CONFIG_I2C-and-CONFIG_IOH3420.patch @@ -0,0 +1,44 @@ +From 23400c3067fab729fd0584e16f6fa84e1bb3c4f8 Mon Sep 17 00:00:00 2001 +From: Auger Eric +Date: Fri, 20 Sep 2019 17:25:08 +0100 +Subject: [PATCH 02/21] Disable CONFIG_I2C and CONFIG_IOH3420 + +RH-Author: Auger Eric +Message-id: <20190920172508.16323-1-eric.auger@redhat.com> +Patchwork-id: 90825 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH] Disable CONFIG_I2C and CONFIG_IOH3420 +Bugzilla: 1693140 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Thomas Huth +RH-Acked-by: Andrew Jones + +BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1693140 +Branch: rhel-8.2.0 +Upstream: Downstream only +Brew: https://brewweb.engineering.redhat.com/brew/taskinfo?taskID=23613661 + +Remove the I2C config which is of no use on aarch64. Also remove the +IOH3420 to be consistent with AV content (See BZ 1627283). + +Signed-off-by: Eric Auger +Signed-off-by: Danilo C. L. de Paula +--- + default-configs/aarch64-softmmu.mak | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/default-configs/aarch64-softmmu.mak b/default-configs/aarch64-softmmu.mak +index 860140e..d718243 100644 +--- a/default-configs/aarch64-softmmu.mak ++++ b/default-configs/aarch64-softmmu.mak +@@ -23,8 +23,6 @@ CONFIG_GPIO_KEY=y + CONFIG_ARM_V7M=y + CONFIG_PCIE_PORT=y + CONFIG_XIO3130=y +-CONFIG_IOH3420=y + CONFIG_USB_XHCI=y + CONFIG_USB=y +-CONFIG_I2C=y + CONFIG_FW_CFG_DMA=y +-- +1.8.3.1 + diff --git a/SOURCES/kvm-Fix-heap-overflow-in-ip_reass-on-big-packet-input.patch b/SOURCES/kvm-Fix-heap-overflow-in-ip_reass-on-big-packet-input.patch new file mode 100644 index 0000000..bb26025 --- /dev/null +++ b/SOURCES/kvm-Fix-heap-overflow-in-ip_reass-on-big-packet-input.patch @@ -0,0 +1,56 @@ +From 486e74dd9b8515f478698fee494086b339015d51 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Wed, 31 Jul 2019 18:45:29 +0100 +Subject: [PATCH 14/14] Fix heap overflow in ip_reass on big packet input +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Philippe Mathieu-Daudé +Message-id: <20190731184529.21905-2-philmd@redhat.com> +Patchwork-id: 89820 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 1/1] Fix heap overflow in ip_reass on big packet input +Bugzilla: 1734751 +RH-Acked-by: Marc-André Lureau +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Thomas Huth + +From: Samuel Thibault + +When the first fragment does not fit in the preallocated buffer, q will +already be pointing to the ext buffer, so we mustn't try to update it. + +Signed-off-by: Samuel Thibault +(cherry picked from libslirp commit 126c04acbabd7ad32c2b018fe10dfac2a3bc1210) +Signed-off-by: Philippe Mathieu-Daudé + +Signed-off-by: Danilo C. L. de Paula +--- + slirp/ip_input.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/slirp/ip_input.c b/slirp/ip_input.c +index 348e1dc..07d8808 100644 +--- a/slirp/ip_input.c ++++ b/slirp/ip_input.c +@@ -334,6 +334,8 @@ insert: + q = fp->frag_link.next; + m = dtom(slirp, q); + ++ int was_ext = m->m_flags & M_EXT; ++ + q = (struct ipasfrag *) q->ipf_next; + while (q != (struct ipasfrag*)&fp->frag_link) { + struct mbuf *t = dtom(slirp, q); +@@ -356,7 +358,7 @@ insert: + * the old buffer (in the mbuf), so we must point ip + * into the new buffer. + */ +- if (m->m_flags & M_EXT) { ++ if (!was_ext && m->m_flags & M_EXT) { + int delta = (char *)q - m->m_dat; + q = (struct ipasfrag *)(m->m_ext + delta); + } +-- +1.8.3.1 + diff --git a/SOURCES/kvm-Introduce-kvm_arch_destroy_vcpu.patch b/SOURCES/kvm-Introduce-kvm_arch_destroy_vcpu.patch new file mode 100644 index 0000000..606b719 --- /dev/null +++ b/SOURCES/kvm-Introduce-kvm_arch_destroy_vcpu.patch @@ -0,0 +1,182 @@ +From e7dc49f6bf6fd242b5b7a83bc270664a1ca45879 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 22 Jul 2019 18:22:08 +0100 +Subject: [PATCH 27/39] KVM: Introduce kvm_arch_destroy_vcpu() + +RH-Author: Paolo Bonzini +Message-id: <20190722182220.19374-7-pbonzini@redhat.com> +Patchwork-id: 89623 +O-Subject: [RHEL-8.1.0 PATCH qemu-kvm v3 06/18] KVM: Introduce kvm_arch_destroy_vcpu() +Bugzilla: 1689269 +RH-Acked-by: Peter Xu +RH-Acked-by: Laurent Vivier +RH-Acked-by: Dr. David Alan Gilbert + +From: Liran Alon + +Simiar to how kvm_init_vcpu() calls kvm_arch_init_vcpu() to perform +arch-dependent initialisation, introduce kvm_arch_destroy_vcpu() +to be called from kvm_destroy_vcpu() to perform arch-dependent +destruction. + +This was added because some architectures (Such as i386) +currently do not free memory that it have allocated in +kvm_arch_init_vcpu(). + +Suggested-by: Maran Wilson +Reviewed-by: Maran Wilson +Signed-off-by: Liran Alon +Message-Id: <20190619162140.133674-3-liran.alon@oracle.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit b1115c99919cf158bb859865f14c3198a0e6f679) +Signed-off-by: Danilo C. L. de Paula +--- + accel/kvm/kvm-all.c | 5 +++++ + include/sysemu/kvm.h | 1 + + target/arm/kvm32.c | 5 +++++ + target/arm/kvm64.c | 5 +++++ + target/i386/kvm.c | 12 ++++++++++++ + target/mips/kvm.c | 5 +++++ + target/ppc/kvm.c | 5 +++++ + target/s390x/kvm.c | 10 ++++++++++ + 8 files changed, 48 insertions(+) + +diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c +index 3a7c8a3..a939b26 100644 +--- a/accel/kvm/kvm-all.c ++++ b/accel/kvm/kvm-all.c +@@ -290,6 +290,11 @@ int kvm_destroy_vcpu(CPUState *cpu) + + DPRINTF("kvm_destroy_vcpu\n"); + ++ ret = kvm_arch_destroy_vcpu(cpu); ++ if (ret < 0) { ++ goto err; ++ } ++ + mmap_size = kvm_ioctl(s, KVM_GET_VCPU_MMAP_SIZE, 0); + if (mmap_size < 0) { + ret = mmap_size; +diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h +index 3d8f294..a5a6dff 100644 +--- a/include/sysemu/kvm.h ++++ b/include/sysemu/kvm.h +@@ -372,6 +372,7 @@ int kvm_arch_put_registers(CPUState *cpu, int level); + int kvm_arch_init(MachineState *ms, KVMState *s); + + int kvm_arch_init_vcpu(CPUState *cpu); ++int kvm_arch_destroy_vcpu(CPUState *cpu); + + bool kvm_vcpu_id_is_valid(int vcpu_id); + +diff --git a/target/arm/kvm32.c b/target/arm/kvm32.c +index 1740cda..056f016 100644 +--- a/target/arm/kvm32.c ++++ b/target/arm/kvm32.c +@@ -237,6 +237,11 @@ int kvm_arch_init_vcpu(CPUState *cs) + return kvm_arm_init_cpreg_list(cpu); + } + ++int kvm_arch_destroy_vcpu(CPUState *cs) ++{ ++ return 0; ++} ++ + typedef struct Reg { + uint64_t id; + int offset; +diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c +index e0b8246..c9c761e 100644 +--- a/target/arm/kvm64.c ++++ b/target/arm/kvm64.c +@@ -549,6 +549,11 @@ int kvm_arch_init_vcpu(CPUState *cs) + return kvm_arm_init_cpreg_list(cpu); + } + ++int kvm_arch_destroy_vcpu(CPUState *cs) ++{ ++ return 0; ++} ++ + bool kvm_arm_reg_syncs_via_cpreg_list(uint64_t regidx) + { + /* Return true if the regidx is a register we should synchronize +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index 8e861a1..305809f 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -1196,6 +1196,18 @@ int kvm_arch_init_vcpu(CPUState *cs) + return r; + } + ++int kvm_arch_destroy_vcpu(CPUState *cs) ++{ ++ X86CPU *cpu = X86_CPU(cs); ++ ++ if (cpu->kvm_msr_buf) { ++ g_free(cpu->kvm_msr_buf); ++ cpu->kvm_msr_buf = NULL; ++ } ++ ++ return 0; ++} ++ + void kvm_arch_reset_vcpu(X86CPU *cpu) + { + CPUX86State *env = &cpu->env; +diff --git a/target/mips/kvm.c b/target/mips/kvm.c +index 8e72850..938f8f1 100644 +--- a/target/mips/kvm.c ++++ b/target/mips/kvm.c +@@ -91,6 +91,11 @@ int kvm_arch_init_vcpu(CPUState *cs) + return ret; + } + ++int kvm_arch_destroy_vcpu(CPUState *cs) ++{ ++ return 0; ++} ++ + void kvm_mips_reset_vcpu(MIPSCPU *cpu) + { + CPUMIPSState *env = &cpu->env; +diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c +index 058dcbe..b9858fa 100644 +--- a/target/ppc/kvm.c ++++ b/target/ppc/kvm.c +@@ -607,6 +607,11 @@ int kvm_arch_init_vcpu(CPUState *cs) + return ret; + } + ++int kvm_arch_destroy_vcpu(CPUState *cs) ++{ ++ return 0; ++} ++ + static void kvm_sw_tlb_put(PowerPCCPU *cpu) + { + CPUPPCState *env = &cpu->env; +diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c +index 1d6cc33..0814333 100644 +--- a/target/s390x/kvm.c ++++ b/target/s390x/kvm.c +@@ -370,6 +370,16 @@ int kvm_arch_init_vcpu(CPUState *cs) + return 0; + } + ++int kvm_arch_destroy_vcpu(CPUState *cs) ++{ ++ S390CPU *cpu = S390_CPU(cs); ++ ++ g_free(cpu->irqstate); ++ cpu->irqstate = NULL; ++ ++ return 0; ++} ++ + void kvm_s390_reset_vcpu(S390CPU *cpu) + { + CPUState *cs = CPU(cpu); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-RHEL-disable-hostmem-memfd.patch b/SOURCES/kvm-RHEL-disable-hostmem-memfd.patch new file mode 100644 index 0000000..5781a40 --- /dev/null +++ b/SOURCES/kvm-RHEL-disable-hostmem-memfd.patch @@ -0,0 +1,56 @@ +From bf545f4a8f40a4ac8f6d63d887a63d9f08329eb6 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= +Date: Wed, 14 Aug 2019 08:52:10 +0100 +Subject: [PATCH 10/10] RHEL: disable hostmem-memfd +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Marc-André Lureau +Message-id: <20190814085210.18462-1-marcandre.lureau@redhat.com> +Patchwork-id: 89974 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH] RHEL: disable hostmem-memfd +Bugzilla: 1740797 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: John Snow + +BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1740797 +BRANCH: rhel8/rhel-8.1.0 +UPSTREAM: n/a (downstream only) +BREW: 23060214 + +Signed-off-by: Marc-André Lureau +Signed-off-by: Danilo C. L. de Paula +--- + backends/Makefile.objs | 3 ++- + util/memfd.c | 2 +- + 2 files changed, 3 insertions(+), 2 deletions(-) + +diff --git a/backends/Makefile.objs b/backends/Makefile.objs +index ad7c032..673fc55 100644 +--- a/backends/Makefile.objs ++++ b/backends/Makefile.objs +@@ -15,4 +15,5 @@ common-obj-$(call land,$(CONFIG_VHOST_USER),$(CONFIG_LINUX)) += \ + cryptodev-vhost-user.o + endif + +-common-obj-$(CONFIG_LINUX) += hostmem-memfd.o ++# RHEL: disable memfd ++# common-obj-$(CONFIG_LINUX) += hostmem-memfd.o +diff --git a/util/memfd.c b/util/memfd.c +index b3ecbac..9312653 100644 +--- a/util/memfd.c ++++ b/util/memfd.c +@@ -202,7 +202,7 @@ bool qemu_memfd_alloc_check(void) + */ + bool qemu_memfd_check(void) + { +-#ifdef CONFIG_LINUX ++#if 0 /* RHEL: memfd support disabled */ + static int memfd_check = MEMFD_TODO; + + if (memfd_check == MEMFD_TODO) { +-- +1.8.3.1 + diff --git a/SOURCES/kvm-Using-ip_deq-after-m_free-might-read-pointers-from-a.patch b/SOURCES/kvm-Using-ip_deq-after-m_free-might-read-pointers-from-a.patch new file mode 100644 index 0000000..ce5cca1 --- /dev/null +++ b/SOURCES/kvm-Using-ip_deq-after-m_free-might-read-pointers-from-a.patch @@ -0,0 +1,61 @@ +From a4c22009a465ebe5fd0c09699e61ad0423b8849d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Fri, 6 Sep 2019 14:00:34 +0100 +Subject: [PATCH 07/22] Using ip_deq after m_free might read pointers from an + allocation reuse. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Philippe Mathieu-Daudé +Message-id: <20190906140034.19722-2-philmd@redhat.com> +Patchwork-id: 90306 +O-Subject: [RHEL-7.7 qemu-kvm-ma + RHEL-7.7 qemu-kvm-rhev + RHEL-8.1.0 qemu-kvm PATCH 1/1] Using ip_deq after m_free might read pointers from an allocation reuse. +Bugzilla: 1749724 +RH-Acked-by: Thomas Huth +RH-Acked-by: Stefano Garzarella +RH-Acked-by: Stefan Hajnoczi + +From: Samuel Thibault + +This would be difficult to exploit, but that is still related with +CVE-2019-14378 which generates fragmented IP packets that would trigger this +issue and at least produce a DoS. + +Signed-off-by: Samuel Thibault +(cherry picked from libslirp commit c59279437eda91841b9d26079c70b8a540d41204) +Signed-off-by: Philippe Mathieu-Daudé + +Signed-off-by: Danilo C. L. de Paula +--- + slirp/ip_input.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/slirp/ip_input.c b/slirp/ip_input.c +index 07d8808..7cf0133 100644 +--- a/slirp/ip_input.c ++++ b/slirp/ip_input.c +@@ -300,6 +300,7 @@ ip_reass(Slirp *slirp, struct ip *ip, struct ipq *fp) + */ + while (q != (struct ipasfrag*)&fp->frag_link && + ip->ip_off + ip->ip_len > q->ipf_off) { ++ struct ipasfrag *prev; + i = (ip->ip_off + ip->ip_len) - q->ipf_off; + if (i < q->ipf_len) { + q->ipf_len -= i; +@@ -307,9 +308,10 @@ ip_reass(Slirp *slirp, struct ip *ip, struct ipq *fp) + m_adj(dtom(slirp, q), i); + break; + } ++ prev = q; + q = q->ipf_next; +- m_free(dtom(slirp, q->ipf_prev)); +- ip_deq(q->ipf_prev); ++ ip_deq(prev); ++ m_free(dtom(slirp, prev)); + } + + insert: +-- +1.8.3.1 + diff --git a/SOURCES/kvm-accel-use-g_strsplit-for-parsing-accelerator-names.patch b/SOURCES/kvm-accel-use-g_strsplit-for-parsing-accelerator-names.patch new file mode 100644 index 0000000..f031582 --- /dev/null +++ b/SOURCES/kvm-accel-use-g_strsplit-for-parsing-accelerator-names.patch @@ -0,0 +1,113 @@ +From 28a766b8099f5e745dbfc18834277039643214a3 Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Thu, 12 Sep 2019 13:04:58 +0100 +Subject: [PATCH 01/22] accel: use g_strsplit for parsing accelerator names +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Laszlo Ersek +Message-id: <20190912130503.14094-2-lersek@redhat.com> +Patchwork-id: 90437 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH 1/6] accel: use g_strsplit for parsing accelerator names +Bugzilla: 1749022 +RH-Acked-by: Stefano Garzarella +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Eduardo Habkost + +From: Daniel P. Berrangé + +Instead of re-using the get_opt_name() method from QemuOpts to split a +string on ':', just use g_strsplit(). + +RHEL8 notes: + +- Fix up upstream's obviously garbled UTF8 sequences in Dan's name (Author + meta-datum, Signed-off-by tags). + +- Harmless context difference due to downstream-only commit 8b53513834e6 + ("Use kvm by default", 2018-04-24). + +Signed-off-by: Daniel P. Berrangé +Message-Id: <20180416111743.8473-2-berrange@redhat.com> +Signed-off-by: Paolo Bonzini +Signed-off-by: Daniel P. Berrangé +(cherry picked from commit 20efc49ed625585809401d8293ad9267927a6a4a) +Signed-off-by: Laszlo Ersek +Signed-off-by: Danilo C. L. de Paula +--- + accel/accel.c | 16 +++++++--------- + include/qemu/option.h | 1 - + util/qemu-option.c | 3 ++- + 3 files changed, 9 insertions(+), 11 deletions(-) + +diff --git a/accel/accel.c b/accel/accel.c +index 5f3d73f..57390e5 100644 +--- a/accel/accel.c ++++ b/accel/accel.c +@@ -70,8 +70,8 @@ static int accel_init_machine(AccelClass *acc, MachineState *ms) + + void configure_accelerator(MachineState *ms) + { +- const char *accel, *p; +- char buf[10]; ++ const char *accel; ++ char **accel_list, **tmp; + int ret; + bool accel_initialised = false; + bool init_failed = false; +@@ -83,13 +83,10 @@ void configure_accelerator(MachineState *ms) + accel = "kvm:tcg"; + } + +- p = accel; +- while (!accel_initialised && *p != '\0') { +- if (*p == ':') { +- p++; +- } +- p = get_opt_name(buf, sizeof(buf), p, ':'); +- acc = accel_find(buf); ++ accel_list = g_strsplit(accel, ":", 0); ++ ++ for (tmp = accel_list; !accel_initialised && tmp && *tmp; tmp++) { ++ acc = accel_find(*tmp); + if (!acc) { + continue; + } +@@ -107,6 +104,7 @@ void configure_accelerator(MachineState *ms) + accel_initialised = true; + } + } ++ g_strfreev(accel_list); + + if (!accel_initialised) { + if (!init_failed) { +diff --git a/include/qemu/option.h b/include/qemu/option.h +index 306fdb5..1cfe5cb 100644 +--- a/include/qemu/option.h ++++ b/include/qemu/option.h +@@ -28,7 +28,6 @@ + + #include "qemu/queue.h" + +-const char *get_opt_name(char *buf, int buf_size, const char *p, char delim); + const char *get_opt_value(char *buf, int buf_size, const char *p); + + void parse_option_size(const char *name, const char *value, +diff --git a/util/qemu-option.c b/util/qemu-option.c +index 95e6cf4..a8db173 100644 +--- a/util/qemu-option.c ++++ b/util/qemu-option.c +@@ -49,7 +49,8 @@ + * The return value is the position of the delimiter/zero byte after the option + * name in p. + */ +-const char *get_opt_name(char *buf, int buf_size, const char *p, char delim) ++static const char *get_opt_name(char *buf, int buf_size, const char *p, ++ char delim) + { + char *q; + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-add-call-to-qemu_add_opts-for-overcommit-option.patch b/SOURCES/kvm-add-call-to-qemu_add_opts-for-overcommit-option.patch new file mode 100644 index 0000000..a68e498 --- /dev/null +++ b/SOURCES/kvm-add-call-to-qemu_add_opts-for-overcommit-option.patch @@ -0,0 +1,45 @@ +From 490c0121b8cd1de62776c18a0843a256b7eed3e3 Mon Sep 17 00:00:00 2001 +From: "plai@redhat.com" +Date: Tue, 26 Nov 2019 19:36:51 +0000 +Subject: [PATCH 07/11] kvm: add call to qemu_add_opts() for -overcommit option + +RH-Author: plai@redhat.com +Message-id: <1574797015-32564-4-git-send-email-plai@redhat.com> +Patchwork-id: 92694 +O-Subject: [RHEL8.2 qemu-kvm PATCH 3/7] kvm: add call to qemu_add_opts() for -overcommit option +Bugzilla: 1634827 +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Michael S. Tsirkin +RH-Acked-by: Igor Mammedov + +From: Prasad Singamsetty + +qemu command fails to process -overcommit option. Add the missing +call to qemu_add_opts() in vl.c. + +Signed-off-by: Prasad Singamsetty +Message-Id: <20180815175704.105902-1-prasad.singamsetty@oracle.com> +Reviewed-by: Mark Kanda +Signed-off-by: Paolo Bonzini +(cherry picked from commit 1fdd4748711a62d863744f42b958472509a6f202) +Signed-off-by: Paul Lai +Signed-off-by: Danilo C. L. de Paula +--- + vl.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/vl.c b/vl.c +index 3cee95f..932c1cf 100644 +--- a/vl.c ++++ b/vl.c +@@ -3145,6 +3145,7 @@ int main(int argc, char **argv, char **envp) + qemu_add_opts(&qemu_object_opts); + qemu_add_opts(&qemu_tpmdev_opts); + qemu_add_opts(&qemu_realtime_opts); ++ qemu_add_opts(&qemu_overcommit_opts); + qemu_add_opts(&qemu_msg_opts); + qemu_add_opts(&qemu_name_opts); + qemu_add_opts(&qemu_numa_opts); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-block-Add-bdrv_get_request_alignment.patch b/SOURCES/kvm-block-Add-bdrv_get_request_alignment.patch new file mode 100644 index 0000000..42c08e1 --- /dev/null +++ b/SOURCES/kvm-block-Add-bdrv_get_request_alignment.patch @@ -0,0 +1,65 @@ +From f551451a4b9975121424cb0837df67d31d2528dc Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Tue, 23 Jul 2019 14:45:45 +0100 +Subject: [PATCH 07/14] block: Add bdrv_get_request_alignment() + +RH-Author: Max Reitz +Message-id: <20190723144546.23701-7-mreitz@redhat.com> +Patchwork-id: 89653 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 6/7] block: Add bdrv_get_request_alignment() +Bugzilla: 1678979 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Stefano Garzarella +RH-Acked-by: John Snow + +From: Eric Blake + +The next patch needs access to a device's minimum permitted +alignment, since NBD wants to advertise this to clients. Add +an accessor function, borrowing from blk_get_max_transfer() +for accessing a backend's block limits. + +Signed-off-by: Eric Blake +Reviewed-by: Vladimir Sementsov-Ogievskiy +Message-Id: <20190329042750.14704-6-eblake@redhat.com> +(cherry picked from commit 4841211e0d1628cd386b35835676d7f6f9a4fa9d) +Signed-off-by: Max Reitz +Signed-off-by: Danilo C. L. de Paula +--- + block/block-backend.c | 7 +++++++ + include/sysemu/block-backend.h | 1 + + 2 files changed, 8 insertions(+) + +diff --git a/block/block-backend.c b/block/block-backend.c +index 7ae5832..0d623e4 100644 +--- a/block/block-backend.c ++++ b/block/block-backend.c +@@ -1807,6 +1807,13 @@ int blk_get_flags(BlockBackend *blk) + } + } + ++/* Returns the minimum request alignment, in bytes; guaranteed nonzero */ ++uint32_t blk_get_request_alignment(BlockBackend *blk) ++{ ++ BlockDriverState *bs = blk_bs(blk); ++ return bs ? bs->bl.request_alignment : BDRV_SECTOR_SIZE; ++} ++ + /* Returns the maximum transfer length, in bytes; guaranteed nonzero */ + uint32_t blk_get_max_transfer(BlockBackend *blk) + { +diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h +index 830d873..20f8bbb 100644 +--- a/include/sysemu/block-backend.h ++++ b/include/sysemu/block-backend.h +@@ -176,6 +176,7 @@ bool blk_is_available(BlockBackend *blk); + void blk_lock_medium(BlockBackend *blk, bool locked); + void blk_eject(BlockBackend *blk, bool eject_flag); + int blk_get_flags(BlockBackend *blk); ++uint32_t blk_get_request_alignment(BlockBackend *blk); + uint32_t blk_get_max_transfer(BlockBackend *blk); + int blk_get_max_iov(BlockBackend *blk); + void blk_set_guest_block_size(BlockBackend *blk, int align); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-block-Fix-AioContext-switch-for-bs-drv-NULL.patch b/SOURCES/kvm-block-Fix-AioContext-switch-for-bs-drv-NULL.patch new file mode 100644 index 0000000..b7241e8 --- /dev/null +++ b/SOURCES/kvm-block-Fix-AioContext-switch-for-bs-drv-NULL.patch @@ -0,0 +1,118 @@ +From 808d2c94f53b9b29f44c2c5d9baea66d63ceddfc Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Wed, 14 Aug 2019 09:20:43 +0100 +Subject: [PATCH 07/10] block: Fix AioContext switch for bs->drv == NULL + +RH-Author: Kevin Wolf +Message-id: <20190814092043.15421-2-kwolf@redhat.com> +Patchwork-id: 89976 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 1/1] block: Fix AioContext switch for bs->drv == NULL +Bugzilla: 1716347 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Max Reitz +RH-Acked-by: John Snow + +Even for block nodes with bs->drv == NULL, we can't just ignore a +bdrv_set_aio_context() call. Leaving the node in its old context can +mean that it's still in an iothread context in bdrv_close_all() during +shutdown, resulting in an attempted unlock of the AioContext lock which +we don't hold. + +This is an example stack trace of a related crash: + + #0 0x00007ffff59da57f in raise () at /lib64/libc.so.6 + #1 0x00007ffff59c4895 in abort () at /lib64/libc.so.6 + #2 0x0000555555b97b1e in error_exit (err=, msg=msg@entry=0x555555d386d0 <__func__.19059> "qemu_mutex_unlock_impl") at util/qemu-thread-posix.c:36 + #3 0x0000555555b97f7f in qemu_mutex_unlock_impl (mutex=mutex@entry=0x5555568002f0, file=file@entry=0x555555d378df "util/async.c", line=line@entry=507) at util/qemu-thread-posix.c:97 + #4 0x0000555555b92f55 in aio_context_release (ctx=ctx@entry=0x555556800290) at util/async.c:507 + #5 0x0000555555b05cf8 in bdrv_prwv_co (child=child@entry=0x7fffc80012f0, offset=offset@entry=131072, qiov=qiov@entry=0x7fffffffd4f0, is_write=is_write@entry=true, flags=flags@entry=0) + at block/io.c:833 + #6 0x0000555555b060a9 in bdrv_pwritev (qiov=0x7fffffffd4f0, offset=131072, child=0x7fffc80012f0) at block/io.c:990 + #7 0x0000555555b060a9 in bdrv_pwrite (child=0x7fffc80012f0, offset=131072, buf=, bytes=) at block/io.c:990 + #8 0x0000555555ae172b in qcow2_cache_entry_flush (bs=bs@entry=0x555556810680, c=c@entry=0x5555568cc740, i=i@entry=0) at block/qcow2-cache.c:51 + #9 0x0000555555ae18dd in qcow2_cache_write (bs=bs@entry=0x555556810680, c=0x5555568cc740) at block/qcow2-cache.c:248 + #10 0x0000555555ae15de in qcow2_cache_flush (bs=0x555556810680, c=) at block/qcow2-cache.c:259 + #11 0x0000555555ae16b1 in qcow2_cache_flush_dependency (c=0x5555568a1700, c=0x5555568a1700, bs=0x555556810680) at block/qcow2-cache.c:194 + #12 0x0000555555ae16b1 in qcow2_cache_entry_flush (bs=bs@entry=0x555556810680, c=c@entry=0x5555568a1700, i=i@entry=0) at block/qcow2-cache.c:194 + #13 0x0000555555ae18dd in qcow2_cache_write (bs=bs@entry=0x555556810680, c=0x5555568a1700) at block/qcow2-cache.c:248 + #14 0x0000555555ae15de in qcow2_cache_flush (bs=bs@entry=0x555556810680, c=) at block/qcow2-cache.c:259 + #15 0x0000555555ad242c in qcow2_inactivate (bs=bs@entry=0x555556810680) at block/qcow2.c:2124 + #16 0x0000555555ad2590 in qcow2_close (bs=0x555556810680) at block/qcow2.c:2153 + #17 0x0000555555ab0c62 in bdrv_close (bs=0x555556810680) at block.c:3358 + #18 0x0000555555ab0c62 in bdrv_delete (bs=0x555556810680) at block.c:3542 + #19 0x0000555555ab0c62 in bdrv_unref (bs=0x555556810680) at block.c:4598 + #20 0x0000555555af4d72 in blk_remove_bs (blk=blk@entry=0x5555568103d0) at block/block-backend.c:785 + #21 0x0000555555af4dbb in blk_remove_all_bs () at block/block-backend.c:483 + #22 0x0000555555aae02f in bdrv_close_all () at block.c:3412 + #23 0x00005555557f9796 in main (argc=, argv=, envp=) at vl.c:4776 + +The reproducer I used is a qcow2 image on gluster volume, where the +virtual disk size (4 GB) is larger than the gluster volume size (64M), +so we can easily trigger an ENOSPC. This backend is assigned to a +virtio-blk device using an iothread, and then from the guest a +'dd if=/dev/zero of=/dev/vda bs=1G count=1' causes the VM to stop +because of an I/O error. qemu_gluster_co_flush_to_disk() sets +bs->drv = NULL on error, so when virtio-blk stops the dataplane, the +block nodes stay in the iothread AioContext. A 'quit' monitor command +issued from this paused state crashes the process. + +Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1631227 +Cc: qemu-stable@nongnu.org +Signed-off-by: Kevin Wolf +Reviewed-by: Eric Blake +Reviewed-by: Max Reitz +Reviewed-by: Stefano Garzarella +(cherry picked from commit 1bffe1ae7a7b707c3a14ea2ccd00d3609d3ce4d8) +Signed-off-by: Kevin Wolf +Signed-off-by: Danilo C. L. de Paula +--- + block.c | 12 ++---------- + 1 file changed, 2 insertions(+), 10 deletions(-) + +diff --git a/block.c b/block.c +index 8f3ceea..37af100 100644 +--- a/block.c ++++ b/block.c +@@ -4923,10 +4923,6 @@ void bdrv_detach_aio_context(BlockDriverState *bs) + BdrvAioNotifier *baf, *baf_tmp; + BdrvChild *child; + +- if (!bs->drv) { +- return; +- } +- + assert(!bs->walking_aio_notifiers); + bs->walking_aio_notifiers = true; + QLIST_FOREACH_SAFE(baf, &bs->aio_notifiers, list, baf_tmp) { +@@ -4941,7 +4937,7 @@ void bdrv_detach_aio_context(BlockDriverState *bs) + */ + bs->walking_aio_notifiers = false; + +- if (bs->drv->bdrv_detach_aio_context) { ++ if (bs->drv && bs->drv->bdrv_detach_aio_context) { + bs->drv->bdrv_detach_aio_context(bs); + } + QLIST_FOREACH(child, &bs->children, next) { +@@ -4960,10 +4956,6 @@ void bdrv_attach_aio_context(BlockDriverState *bs, + BdrvAioNotifier *ban, *ban_tmp; + BdrvChild *child; + +- if (!bs->drv) { +- return; +- } +- + if (bs->quiesce_counter) { + aio_disable_external(new_context); + } +@@ -4973,7 +4965,7 @@ void bdrv_attach_aio_context(BlockDriverState *bs, + QLIST_FOREACH(child, &bs->children, next) { + bdrv_attach_aio_context(child->bs, new_context); + } +- if (bs->drv->bdrv_attach_aio_context) { ++ if (bs->drv && bs->drv->bdrv_attach_aio_context) { + bs->drv->bdrv_attach_aio_context(bs, new_context); + } + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-block-Fix-AioContext-switch-for-drained-node.patch b/SOURCES/kvm-block-Fix-AioContext-switch-for-drained-node.patch new file mode 100644 index 0000000..4306d18 --- /dev/null +++ b/SOURCES/kvm-block-Fix-AioContext-switch-for-drained-node.patch @@ -0,0 +1,57 @@ +From ee7b9d7867634d052f2c695fcebf68f585fe59c0 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Wed, 14 Aug 2019 08:42:27 +0100 +Subject: [PATCH 04/10] block: Fix AioContext switch for drained node + +RH-Author: Kevin Wolf +Message-id: <20190814084229.6458-4-kwolf@redhat.com> +Patchwork-id: 89969 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 3/5] block: Fix AioContext switch for drained node +Bugzilla: 1716349 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Max Reitz +RH-Acked-by: Paolo Bonzini + +When a drained node changes its AioContext, we need to move its +aio_disable_external() to the new context, too. + +Without this fix, drain_end will try to reenable the new context, which +has never been disabled, so an assertion failure is triggered. + +Signed-off-by: Kevin Wolf +Reviewed-by: Eric Blake +(cherry picked from commit e64f25f30b80a71bd4e409ed518c39eeb5905166) +Signed-off-by: Kevin Wolf +Signed-off-by: Danilo C. L. de Paula +--- + block.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/block.c b/block.c +index 82b16df..9d9b8a9 100644 +--- a/block.c ++++ b/block.c +@@ -4948,6 +4948,9 @@ void bdrv_detach_aio_context(BlockDriverState *bs) + bdrv_detach_aio_context(child->bs); + } + ++ if (bs->quiesce_counter) { ++ aio_enable_external(bs->aio_context); ++ } + bs->aio_context = NULL; + } + +@@ -4961,6 +4964,10 @@ void bdrv_attach_aio_context(BlockDriverState *bs, + return; + } + ++ if (bs->quiesce_counter) { ++ aio_disable_external(new_context); ++ } ++ + bs->aio_context = new_context; + + QLIST_FOREACH(child, &bs->children, next) { +-- +1.8.3.1 + diff --git a/SOURCES/kvm-block-Use-normal-drain-for-bdrv_set_aio_context.patch b/SOURCES/kvm-block-Use-normal-drain-for-bdrv_set_aio_context.patch new file mode 100644 index 0000000..b8d168e --- /dev/null +++ b/SOURCES/kvm-block-Use-normal-drain-for-bdrv_set_aio_context.patch @@ -0,0 +1,76 @@ +From cf6bc30f7b525f0d646db62e49cbf02f3f28a1f2 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Wed, 14 Aug 2019 08:42:29 +0100 +Subject: [PATCH 06/10] block: Use normal drain for bdrv_set_aio_context() + +RH-Author: Kevin Wolf +Message-id: <20190814084229.6458-6-kwolf@redhat.com> +Patchwork-id: 89968 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 5/5] block: Use normal drain for bdrv_set_aio_context() +Bugzilla: 1716349 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Max Reitz +RH-Acked-by: Paolo Bonzini + +Now that bdrv_set_aio_context() works inside drained sections, it can +also use the real drain function instead of open coding something +similar. + +Signed-off-by: Kevin Wolf +(cherry picked from commit d70d595429ecd9ac4917e53453dd8979db8e5ffd) + +RHEL: This conflicts because we didn't backport the removal of the +polling loop. The conflict is resolved so that the polling loop moves to +above the drain and any requests a BH would spawn would still be +correctly drained afterwards. The changed order alone would have +compensated for the virtio-blk bug and it potentially compensates for +other bugs, too (we know of bugs in the NBD client at least), so leaving +the polling loop in, with the new ordering, feels like the safe way for +a downstream backport. + +Signed-off-by: Kevin Wolf +Signed-off-by: Danilo C. L. de Paula +--- + block.c | 11 +++++------ + 1 file changed, 5 insertions(+), 6 deletions(-) + +diff --git a/block.c b/block.c +index 9d9b8a9..8f3ceea 100644 +--- a/block.c ++++ b/block.c +@@ -4989,18 +4989,18 @@ void bdrv_attach_aio_context(BlockDriverState *bs, + bs->walking_aio_notifiers = false; + } + ++/* The caller must own the AioContext lock for the old AioContext of bs, but it ++ * must not own the AioContext lock for new_context (unless new_context is ++ * the same as the current context of bs). */ + void bdrv_set_aio_context(BlockDriverState *bs, AioContext *new_context) + { + AioContext *ctx = bdrv_get_aio_context(bs); + +- aio_disable_external(ctx); +- bdrv_parent_drained_begin(bs, NULL, false); +- bdrv_drain(bs); /* ensure there are no in-flight requests */ +- + while (aio_poll(ctx, false)) { + /* wait for all bottom halves to execute */ + } + ++ bdrv_drained_begin(bs); + bdrv_detach_aio_context(bs); + + /* This function executes in the old AioContext so acquire the new one in +@@ -5008,8 +5008,7 @@ void bdrv_set_aio_context(BlockDriverState *bs, AioContext *new_context) + */ + aio_context_acquire(new_context); + bdrv_attach_aio_context(bs, new_context); +- bdrv_parent_drained_end(bs, NULL, false); +- aio_enable_external(ctx); ++ bdrv_drained_end(bs); + aio_context_release(new_context); + } + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-block-backend-Make-blk_inc-dec_in_flight-public.patch b/SOURCES/kvm-block-backend-Make-blk_inc-dec_in_flight-public.patch new file mode 100644 index 0000000..2068d3f --- /dev/null +++ b/SOURCES/kvm-block-backend-Make-blk_inc-dec_in_flight-public.patch @@ -0,0 +1,62 @@ +From 0e5a55b3556fdd23bbeeaca40a151e7062d42c1e Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Wed, 14 Aug 2019 08:42:25 +0100 +Subject: [PATCH 02/10] block-backend: Make blk_inc/dec_in_flight public + +RH-Author: Kevin Wolf +Message-id: <20190814084229.6458-2-kwolf@redhat.com> +Patchwork-id: 89966 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 1/5] block-backend: Make blk_inc/dec_in_flight public +Bugzilla: 1716349 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Max Reitz +RH-Acked-by: Paolo Bonzini + +For some users of BlockBackends, just increasing the in_flight counter +is easier than implementing separate handlers in BlockDevOps. Make the +helper functions for this public. + +Signed-off-by: Kevin Wolf +(cherry picked from commit c90e2a9cfd94bd02d92c53b97f04fd595001de7e) +Signed-off-by: Kevin Wolf +Signed-off-by: Danilo C. L. de Paula +--- + block/block-backend.c | 4 ++-- + include/sysemu/block-backend.h | 2 ++ + 2 files changed, 4 insertions(+), 2 deletions(-) + +diff --git a/block/block-backend.c b/block/block-backend.c +index 0d623e4..e941520 100644 +--- a/block/block-backend.c ++++ b/block/block-backend.c +@@ -1294,12 +1294,12 @@ int blk_make_zero(BlockBackend *blk, BdrvRequestFlags flags) + return bdrv_make_zero(blk->root, flags); + } + +-static void blk_inc_in_flight(BlockBackend *blk) ++void blk_inc_in_flight(BlockBackend *blk) + { + atomic_inc(&blk->in_flight); + } + +-static void blk_dec_in_flight(BlockBackend *blk) ++void blk_dec_in_flight(BlockBackend *blk) + { + atomic_dec(&blk->in_flight); + aio_wait_kick(); +diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h +index 20f8bbb..815b6e5 100644 +--- a/include/sysemu/block-backend.h ++++ b/include/sysemu/block-backend.h +@@ -157,6 +157,8 @@ int blk_co_pdiscard(BlockBackend *blk, int64_t offset, int bytes); + int blk_co_flush(BlockBackend *blk); + int blk_flush(BlockBackend *blk); + int blk_commit_all(void); ++void blk_inc_in_flight(BlockBackend *blk); ++void blk_dec_in_flight(BlockBackend *blk); + void blk_drain(BlockBackend *blk); + void blk_drain_all(void); + void blk_set_on_error(BlockBackend *blk, BlockdevOnError on_read_error, +-- +1.8.3.1 + diff --git a/SOURCES/kvm-block-file-posix-Unaligned-O_DIRECT-block-status.patch b/SOURCES/kvm-block-file-posix-Unaligned-O_DIRECT-block-status.patch new file mode 100644 index 0000000..6ced895 --- /dev/null +++ b/SOURCES/kvm-block-file-posix-Unaligned-O_DIRECT-block-status.patch @@ -0,0 +1,98 @@ +From 29592218d57f1fe49c1254fffd9b0206cfe29ec7 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Tue, 23 Jul 2019 14:45:40 +0100 +Subject: [PATCH 02/14] block/file-posix: Unaligned O_DIRECT block-status + +RH-Author: Max Reitz +Message-id: <20190723144546.23701-2-mreitz@redhat.com> +Patchwork-id: 89647 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 1/7] block/file-posix: Unaligned O_DIRECT block-status +Bugzilla: 1678979 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Stefano Garzarella +RH-Acked-by: John Snow + +Currently, qemu crashes whenever someone queries the block status of an +unaligned image tail of an O_DIRECT image: +$ echo > foo +$ qemu-img map --image-opts driver=file,filename=foo,cache.direct=on +Offset Length Mapped to File +qemu-img: block/io.c:2093: bdrv_co_block_status: Assertion `*pnum && +QEMU_IS_ALIGNED(*pnum, align) && align > offset - aligned_offset' +failed. + +This is because bdrv_co_block_status() checks that the result returned +by the driver's implementation is aligned to the request_alignment, but +file-posix can fail to do so, which is actually mentioned in a comment +there: "[...] possibly including a partial sector at EOF". + +Fix this by rounding up those partial sectors. + +There are two possible alternative fixes: +(1) We could refuse to open unaligned image files with O_DIRECT + altogether. That sounds reasonable until you realize that qcow2 + does necessarily not fill up its metadata clusters, and that nobody + runs qemu-img create with O_DIRECT. Therefore, unpreallocated qcow2 + files usually have an unaligned image tail. + +(2) bdrv_co_block_status() could ignore unaligned tails. It actually + throws away everything past the EOF already, so that sounds + reasonable. + Unfortunately, the block layer knows file lengths only with a + granularity of BDRV_SECTOR_SIZE, so bdrv_co_block_status() usually + would have to guess whether its file length information is inexact + or whether the driver is broken. + +Fixing what raw_co_block_status() returns is the safest thing to do. + +There seems to be no other block driver that sets request_alignment and +does not make sure that it always returns aligned values. + +Cc: qemu-stable@nongnu.org +Signed-off-by: Max Reitz +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +(cherry picked from commit 9c3db310ff0b7473272ae8dce5e04e2f8a825390) +Signed-off-by: Max Reitz +Signed-off-by: Danilo C. L. de Paula +--- + block/file-posix.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/block/file-posix.c b/block/file-posix.c +index 5fb5a9a..4b404e4 100644 +--- a/block/file-posix.c ++++ b/block/file-posix.c +@@ -2413,6 +2413,8 @@ static int coroutine_fn raw_co_block_status(BlockDriverState *bs, + off_t data = 0, hole = 0; + int ret; + ++ assert(QEMU_IS_ALIGNED(offset | bytes, bs->bl.request_alignment)); ++ + ret = fd_open(bs); + if (ret < 0) { + return ret; +@@ -2438,6 +2440,20 @@ static int coroutine_fn raw_co_block_status(BlockDriverState *bs, + /* On a data extent, compute bytes to the end of the extent, + * possibly including a partial sector at EOF. */ + *pnum = MIN(bytes, hole - offset); ++ ++ /* ++ * We are not allowed to return partial sectors, though, so ++ * round up if necessary. ++ */ ++ if (!QEMU_IS_ALIGNED(*pnum, bs->bl.request_alignment)) { ++ int64_t file_length = raw_getlength(bs); ++ if (file_length > 0) { ++ /* Ignore errors, this is just a safeguard */ ++ assert(hole == file_length); ++ } ++ *pnum = ROUND_UP(*pnum, bs->bl.request_alignment); ++ } ++ + ret = BDRV_BLOCK_DATA; + } else { + /* On a hole, compute bytes to the beginning of the next extent. */ +-- +1.8.3.1 + diff --git a/SOURCES/kvm-block-gluster-limit-the-transfer-size-to-512-MiB.patch b/SOURCES/kvm-block-gluster-limit-the-transfer-size-to-512-MiB.patch new file mode 100644 index 0000000..d061535 --- /dev/null +++ b/SOURCES/kvm-block-gluster-limit-the-transfer-size-to-512-MiB.patch @@ -0,0 +1,101 @@ +From 1788135e55dd9e68e54ba32582702df09819a8fe Mon Sep 17 00:00:00 2001 +From: Stefano Garzarella +Date: Tue, 16 Jul 2019 08:13:10 +0100 +Subject: [PATCH 16/39] block/gluster: limit the transfer size to 512 MiB + +RH-Author: Stefano Garzarella +Message-id: <20190716081310.29528-2-sgarzare@redhat.com> +Patchwork-id: 89533 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 1/1] block/gluster: limit the transfer size to 512 MiB +Bugzilla: 1728657 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Kevin Wolf +RH-Acked-by: Max Reitz + +Several versions of GlusterFS (3.12? -> 6.0.1) fail when the +transfer size is greater or equal to 1024 MiB, so we are +limiting the transfer size to 512 MiB to avoid this rare issue. + +Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=1691320 +Signed-off-by: Stefano Garzarella +Reviewed-by: Niels de Vos +Signed-off-by: Kevin Wolf +(cherry picked from commit de23e72bb7515888fdea2a58c58a2e02370123bd) +Signed-off-by: Stefano Garzarella +Signed-off-by: Danilo C. L. de Paula +--- + block/gluster.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/block/gluster.c b/block/gluster.c +index a6ac2b1..9b29d96 100644 +--- a/block/gluster.c ++++ b/block/gluster.c +@@ -9,6 +9,7 @@ + */ + + #include "qemu/osdep.h" ++#include "qemu/units.h" + #include + #include "block/block_int.h" + #include "block/qdict.h" +@@ -41,6 +42,12 @@ + #define GLUSTER_DEBUG_MAX 9 + #define GLUSTER_OPT_LOGFILE "logfile" + #define GLUSTER_LOGFILE_DEFAULT "-" /* handled in libgfapi as /dev/stderr */ ++/* ++ * Several versions of GlusterFS (3.12? -> 6.0.1) fail when the transfer size ++ * is greater or equal to 1024 MiB, so we are limiting the transfer size to 512 ++ * MiB to avoid this rare issue. ++ */ ++#define GLUSTER_MAX_TRANSFER (512 * MiB) + + #define GERR_INDEX_HINT "hint: check in 'server' array index '%d'\n" + +@@ -887,6 +894,11 @@ out: + return ret; + } + ++static void qemu_gluster_refresh_limits(BlockDriverState *bs, Error **errp) ++{ ++ bs->bl.max_transfer = GLUSTER_MAX_TRANSFER; ++} ++ + static int qemu_gluster_reopen_prepare(BDRVReopenState *state, + BlockReopenQueue *queue, Error **errp) + { +@@ -1527,6 +1539,7 @@ static BlockDriver bdrv_gluster = { + .bdrv_co_pwrite_zeroes = qemu_gluster_co_pwrite_zeroes, + #endif + .bdrv_co_block_status = qemu_gluster_co_block_status, ++ .bdrv_refresh_limits = qemu_gluster_refresh_limits, + .create_opts = &qemu_gluster_create_opts, + }; + +@@ -1556,6 +1569,7 @@ static BlockDriver bdrv_gluster_tcp = { + .bdrv_co_pwrite_zeroes = qemu_gluster_co_pwrite_zeroes, + #endif + .bdrv_co_block_status = qemu_gluster_co_block_status, ++ .bdrv_refresh_limits = qemu_gluster_refresh_limits, + .create_opts = &qemu_gluster_create_opts, + }; + +@@ -1585,6 +1599,7 @@ static BlockDriver bdrv_gluster_unix = { + .bdrv_co_pwrite_zeroes = qemu_gluster_co_pwrite_zeroes, + #endif + .bdrv_co_block_status = qemu_gluster_co_block_status, ++ .bdrv_refresh_limits = qemu_gluster_refresh_limits, + .create_opts = &qemu_gluster_create_opts, + }; + +@@ -1620,6 +1635,7 @@ static BlockDriver bdrv_gluster_rdma = { + .bdrv_co_pwrite_zeroes = qemu_gluster_co_pwrite_zeroes, + #endif + .bdrv_co_block_status = qemu_gluster_co_block_status, ++ .bdrv_refresh_limits = qemu_gluster_refresh_limits, + .create_opts = &qemu_gluster_create_opts, + }; + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-block-posix-Always-allocate-the-first-block.patch b/SOURCES/kvm-block-posix-Always-allocate-the-first-block.patch new file mode 100644 index 0000000..08fbcba --- /dev/null +++ b/SOURCES/kvm-block-posix-Always-allocate-the-first-block.patch @@ -0,0 +1,392 @@ +From 273237507842493f78cd492cd54137e828a986ef Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 30 Aug 2019 12:56:27 +0100 +Subject: [PATCH 09/10] block: posix: Always allocate the first block + +RH-Author: Thomas Huth +Message-id: <20190830125628.23668-5-thuth@redhat.com> +Patchwork-id: 90210 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v2 4/5] block: posix: Always allocate the first block +Bugzilla: 1738839 +RH-Acked-by: Cornelia Huck +RH-Acked-by: Max Reitz +RH-Acked-by: David Hildenbrand + +From: Nir Soffer + +When creating an image with preallocation "off" or "falloc", the first +block of the image is typically not allocated. When using Gluster +storage backed by XFS filesystem, reading this block using direct I/O +succeeds regardless of request length, fooling alignment detection. + +In this case we fallback to a safe value (4096) instead of the optimal +value (512), which may lead to unneeded data copying when aligning +requests. Allocating the first block avoids the fallback. + +Since we allocate the first block even with preallocation=off, we no +longer create images with zero disk size: + + $ ./qemu-img create -f raw test.raw 1g + Formatting 'test.raw', fmt=raw size=1073741824 + + $ ls -lhs test.raw + 4.0K -rw-r--r--. 1 nsoffer nsoffer 1.0G Aug 16 23:48 test.raw + +And converting the image requires additional cluster: + + $ ./qemu-img measure -f raw -O qcow2 test.raw + required size: 458752 + fully allocated size: 1074135040 + +When using format like vmdk with multiple files per image, we allocate +one block per file: + + $ ./qemu-img create -f vmdk -o subformat=twoGbMaxExtentFlat test.vmdk 4g + Formatting 'test.vmdk', fmt=vmdk size=4294967296 compat6=off hwversion=undefined subformat=twoGbMaxExtentFlat + + $ ls -lhs test*.vmdk + 4.0K -rw-r--r--. 1 nsoffer nsoffer 2.0G Aug 27 03:23 test-f001.vmdk + 4.0K -rw-r--r--. 1 nsoffer nsoffer 2.0G Aug 27 03:23 test-f002.vmdk + 4.0K -rw-r--r--. 1 nsoffer nsoffer 353 Aug 27 03:23 test.vmdk + +I did quick performance test for copying disks with qemu-img convert to +new raw target image to Gluster storage with sector size of 512 bytes: + + for i in $(seq 10); do + rm -f dst.raw + sleep 10 + time ./qemu-img convert -f raw -O raw -t none -T none src.raw dst.raw + done + +Here is a table comparing the total time spent: + +Type Before(s) After(s) Diff(%) +--------------------------------------- +real 530.028 469.123 -11.4 +user 17.204 10.768 -37.4 +sys 17.881 7.011 -60.7 + +We can see very clear improvement in CPU usage. + +Signed-off-by: Nir Soffer +Message-id: 20190827010528.8818-2-nsoffer@redhat.com +Reviewed-by: Max Reitz +Signed-off-by: Max Reitz +(cherry picked from commit 3f900188502670a15f8915d5363533512ecd035f) +Signed-off-by: Danilo C. L. de Paula + +Conflicts: + block/file-posix.c (simple contextual conflict) + tests/qemu-iotests/059.out (Needed to adapt output a little bit) + +Signed-off-by: Thomas Huth +Signed-off-by: Danilo C. L. de Paula +--- + block/file-posix.c | 51 ++++++++++++++++++++++++++++++++++++++++ + tests/qemu-iotests/059.out | 2 +- + tests/qemu-iotests/150.out | 11 --------- + tests/qemu-iotests/150.out.qcow2 | 11 +++++++++ + tests/qemu-iotests/150.out.raw | 12 ++++++++++ + tests/qemu-iotests/175 | 19 ++++++++++----- + tests/qemu-iotests/175.out | 8 +++---- + tests/qemu-iotests/178.out.qcow2 | 4 ++-- + tests/qemu-iotests/221.out | 12 ++++++---- + tests/qemu-iotests/253.out | 12 ++++++---- + 10 files changed, 110 insertions(+), 32 deletions(-) + delete mode 100644 tests/qemu-iotests/150.out + create mode 100644 tests/qemu-iotests/150.out.qcow2 + create mode 100644 tests/qemu-iotests/150.out.raw + +diff --git a/block/file-posix.c b/block/file-posix.c +index 84c5a31..dfe0bca 100644 +--- a/block/file-posix.c ++++ b/block/file-posix.c +@@ -1605,6 +1605,43 @@ static ssize_t handle_aiocb_discard(RawPosixAIOData *aiocb) + return ret; + } + ++/* ++ * Help alignment probing by allocating the first block. ++ * ++ * When reading with direct I/O from unallocated area on Gluster backed by XFS, ++ * reading succeeds regardless of request length. In this case we fallback to ++ * safe alignment which is not optimal. Allocating the first block avoids this ++ * fallback. ++ * ++ * fd may be opened with O_DIRECT, but we don't know the buffer alignment or ++ * request alignment, so we use safe values. ++ * ++ * Returns: 0 on success, -errno on failure. Since this is an optimization, ++ * caller may ignore failures. ++ */ ++static int allocate_first_block(int fd, size_t max_size) ++{ ++ size_t write_size = (max_size < MAX_BLOCKSIZE) ++ ? BDRV_SECTOR_SIZE ++ : MAX_BLOCKSIZE; ++ size_t max_align = MAX(MAX_BLOCKSIZE, getpagesize()); ++ void *buf; ++ ssize_t n; ++ int ret; ++ ++ buf = qemu_memalign(max_align, write_size); ++ memset(buf, 0, write_size); ++ ++ do { ++ n = pwrite(fd, buf, write_size, 0); ++ } while (n == -1 && errno == EINTR); ++ ++ ret = (n == -1) ? -errno : 0; ++ ++ qemu_vfree(buf); ++ return ret; ++} ++ + static int handle_aiocb_truncate(RawPosixAIOData *aiocb) + { + int result = 0; +@@ -1642,6 +1679,17 @@ static int handle_aiocb_truncate(RawPosixAIOData *aiocb) + /* posix_fallocate() doesn't set errno. */ + error_setg_errno(errp, -result, + "Could not preallocate new data"); ++ } else if (current_length == 0) { ++ /* ++ * posix_fallocate() uses fallocate() if the filesystem ++ * supports it, or fallback to manually writing zeroes. If ++ * fallocate() was used, unaligned reads from the fallocated ++ * area in raw_probe_alignment() will succeed, hence we need to ++ * allocate the first block. ++ * ++ * Optimize future alignment probing; ignore failures. ++ */ ++ allocate_first_block(fd, offset); + } + } else { + result = 0; +@@ -1700,6 +1748,9 @@ static int handle_aiocb_truncate(RawPosixAIOData *aiocb) + if (ftruncate(fd, offset) != 0) { + result = -errno; + error_setg_errno(errp, -result, "Could not resize file"); ++ } else if (current_length == 0 && offset > current_length) { ++ /* Optimize future alignment probing; ignore failures. */ ++ allocate_first_block(fd, offset); + } + return result; + default: +diff --git a/tests/qemu-iotests/059.out b/tests/qemu-iotests/059.out +index f6dce79..19cd591 100644 +--- a/tests/qemu-iotests/059.out ++++ b/tests/qemu-iotests/059.out +@@ -27,7 +27,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824000 subformat=twoGbMax + image: TEST_DIR/t.vmdk + file format: vmdk + virtual size: 1.0T (1073741824000 bytes) +-disk size: 16K ++disk size: 2.0M + Format specific information: + cid: XXXXXXXX + parent cid: XXXXXXXX +diff --git a/tests/qemu-iotests/150.out b/tests/qemu-iotests/150.out +deleted file mode 100644 +index 2a54e8d..0000000 +--- a/tests/qemu-iotests/150.out ++++ /dev/null +@@ -1,11 +0,0 @@ +-QA output created by 150 +- +-=== Mapping sparse conversion === +- +-Offset Length File +- +-=== Mapping non-sparse conversion === +- +-Offset Length File +-0 0x100000 TEST_DIR/t.IMGFMT +-*** done +diff --git a/tests/qemu-iotests/150.out.qcow2 b/tests/qemu-iotests/150.out.qcow2 +new file mode 100644 +index 0000000..2a54e8d +--- /dev/null ++++ b/tests/qemu-iotests/150.out.qcow2 +@@ -0,0 +1,11 @@ ++QA output created by 150 ++ ++=== Mapping sparse conversion === ++ ++Offset Length File ++ ++=== Mapping non-sparse conversion === ++ ++Offset Length File ++0 0x100000 TEST_DIR/t.IMGFMT ++*** done +diff --git a/tests/qemu-iotests/150.out.raw b/tests/qemu-iotests/150.out.raw +new file mode 100644 +index 0000000..3cdc772 +--- /dev/null ++++ b/tests/qemu-iotests/150.out.raw +@@ -0,0 +1,12 @@ ++QA output created by 150 ++ ++=== Mapping sparse conversion === ++ ++Offset Length File ++0 0x1000 TEST_DIR/t.IMGFMT ++ ++=== Mapping non-sparse conversion === ++ ++Offset Length File ++0 0x100000 TEST_DIR/t.IMGFMT ++*** done +diff --git a/tests/qemu-iotests/175 b/tests/qemu-iotests/175 +index 2e37c9a..b3b7712 100755 +--- a/tests/qemu-iotests/175 ++++ b/tests/qemu-iotests/175 +@@ -38,14 +38,16 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 + # the file size. This function hides the resulting difference in the + # stat -c '%b' output. + # Parameter 1: Number of blocks an empty file occupies +-# Parameter 2: Image size in bytes ++# Parameter 2: Minimal number of blocks in an image ++# Parameter 3: Image size in bytes + _filter_blocks() + { + extra_blocks=$1 +- img_size=$2 ++ min_blocks=$2 ++ img_size=$3 + +- sed -e "s/blocks=$extra_blocks\\(\$\\|[^0-9]\\)/nothing allocated/" \ +- -e "s/blocks=$((extra_blocks + img_size / 512))\\(\$\\|[^0-9]\\)/everything allocated/" ++ sed -e "s/blocks=$min_blocks\\(\$\\|[^0-9]\\)/min allocation/" \ ++ -e "s/blocks=$((extra_blocks + img_size / 512))\\(\$\\|[^0-9]\\)/max allocation/" + } + + # get standard environment, filters and checks +@@ -61,16 +63,21 @@ size=$((1 * 1024 * 1024)) + touch "$TEST_DIR/empty" + extra_blocks=$(stat -c '%b' "$TEST_DIR/empty") + ++# We always write the first byte; check how many blocks this filesystem ++# allocates to match empty image alloation. ++printf "\0" > "$TEST_DIR/empty" ++min_blocks=$(stat -c '%b' "$TEST_DIR/empty") ++ + echo + echo "== creating image with default preallocation ==" + _make_test_img $size | _filter_imgfmt +-stat -c "size=%s, blocks=%b" $TEST_IMG | _filter_blocks $extra_blocks $size ++stat -c "size=%s, blocks=%b" $TEST_IMG | _filter_blocks $extra_blocks $min_blocks $size + + for mode in off full falloc; do + echo + echo "== creating image with preallocation $mode ==" + IMGOPTS=preallocation=$mode _make_test_img $size | _filter_imgfmt +- stat -c "size=%s, blocks=%b" $TEST_IMG | _filter_blocks $extra_blocks $size ++ stat -c "size=%s, blocks=%b" $TEST_IMG | _filter_blocks $extra_blocks $min_blocks $size + done + + # success, all done +diff --git a/tests/qemu-iotests/175.out b/tests/qemu-iotests/175.out +index 6d9a5ed..263e521 100644 +--- a/tests/qemu-iotests/175.out ++++ b/tests/qemu-iotests/175.out +@@ -2,17 +2,17 @@ QA output created by 175 + + == creating image with default preallocation == + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 +-size=1048576, nothing allocated ++size=1048576, min allocation + + == creating image with preallocation off == + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 preallocation=off +-size=1048576, nothing allocated ++size=1048576, min allocation + + == creating image with preallocation full == + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 preallocation=full +-size=1048576, everything allocated ++size=1048576, max allocation + + == creating image with preallocation falloc == + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 preallocation=falloc +-size=1048576, everything allocated ++size=1048576, max allocation + *** done +diff --git a/tests/qemu-iotests/178.out.qcow2 b/tests/qemu-iotests/178.out.qcow2 +index d42d4a4..12edc3d 100644 +--- a/tests/qemu-iotests/178.out.qcow2 ++++ b/tests/qemu-iotests/178.out.qcow2 +@@ -96,7 +96,7 @@ converted image file size in bytes: 196608 + == raw input image with data (human) == + + Formatting 'TEST_DIR/t.qcow2', fmt=IMGFMT size=1073741824 +-required size: 393216 ++required size: 458752 + fully allocated size: 1074135040 + wrote 512/512 bytes at offset 512 + 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +@@ -240,7 +240,7 @@ converted image file size in bytes: 196608 + + Formatting 'TEST_DIR/t.qcow2', fmt=IMGFMT size=1073741824 + { +- "required": 393216, ++ "required": 458752, + "fully-allocated": 1074135040 + } + wrote 512/512 bytes at offset 512 +diff --git a/tests/qemu-iotests/221.out b/tests/qemu-iotests/221.out +index 9f9dd52..dca024a 100644 +--- a/tests/qemu-iotests/221.out ++++ b/tests/qemu-iotests/221.out +@@ -3,14 +3,18 @@ QA output created by 221 + === Check mapping of unaligned raw image === + + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=65537 +-[{ "start": 0, "length": 66048, "depth": 0, "zero": true, "data": false, "offset": OFFSET}] +-[{ "start": 0, "length": 66048, "depth": 0, "zero": true, "data": false, "offset": OFFSET}] ++[{ "start": 0, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET}, ++{ "start": 4096, "length": 61952, "depth": 0, "zero": true, "data": false, "offset": OFFSET}] ++[{ "start": 0, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET}, ++{ "start": 4096, "length": 61952, "depth": 0, "zero": true, "data": false, "offset": OFFSET}] + wrote 1/1 bytes at offset 65536 + 1 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +-[{ "start": 0, "length": 65536, "depth": 0, "zero": true, "data": false, "offset": OFFSET}, ++[{ "start": 0, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET}, ++{ "start": 4096, "length": 61440, "depth": 0, "zero": true, "data": false, "offset": OFFSET}, + { "start": 65536, "length": 1, "depth": 0, "zero": false, "data": true, "offset": OFFSET}, + { "start": 65537, "length": 511, "depth": 0, "zero": true, "data": false, "offset": OFFSET}] +-[{ "start": 0, "length": 65536, "depth": 0, "zero": true, "data": false, "offset": OFFSET}, ++[{ "start": 0, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET}, ++{ "start": 4096, "length": 61440, "depth": 0, "zero": true, "data": false, "offset": OFFSET}, + { "start": 65536, "length": 1, "depth": 0, "zero": false, "data": true, "offset": OFFSET}, + { "start": 65537, "length": 511, "depth": 0, "zero": true, "data": false, "offset": OFFSET}] + *** done +diff --git a/tests/qemu-iotests/253.out b/tests/qemu-iotests/253.out +index 607c0ba..3d08b30 100644 +--- a/tests/qemu-iotests/253.out ++++ b/tests/qemu-iotests/253.out +@@ -3,12 +3,16 @@ QA output created by 253 + === Check mapping of unaligned raw image === + + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048575 +-[{ "start": 0, "length": 1048576, "depth": 0, "zero": true, "data": false, "offset": OFFSET}] +-[{ "start": 0, "length": 1048576, "depth": 0, "zero": true, "data": false, "offset": OFFSET}] ++[{ "start": 0, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET}, ++{ "start": 4096, "length": 1044480, "depth": 0, "zero": true, "data": false, "offset": OFFSET}] ++[{ "start": 0, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET}, ++{ "start": 4096, "length": 1044480, "depth": 0, "zero": true, "data": false, "offset": OFFSET}] + wrote 65535/65535 bytes at offset 983040 + 63.999 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +-[{ "start": 0, "length": 983040, "depth": 0, "zero": true, "data": false, "offset": OFFSET}, ++[{ "start": 0, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET}, ++{ "start": 4096, "length": 978944, "depth": 0, "zero": true, "data": false, "offset": OFFSET}, + { "start": 983040, "length": 65536, "depth": 0, "zero": false, "data": true, "offset": OFFSET}] +-[{ "start": 0, "length": 983040, "depth": 0, "zero": true, "data": false, "offset": OFFSET}, ++[{ "start": 0, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET}, ++{ "start": 4096, "length": 978944, "depth": 0, "zero": true, "data": false, "offset": OFFSET}, + { "start": 983040, "length": 65536, "depth": 0, "zero": false, "data": true, "offset": OFFSET}] + *** done +-- +1.8.3.1 + diff --git a/SOURCES/kvm-block-ssh-Convert-from-DPRINTF-macro-to-trace-events.patch b/SOURCES/kvm-block-ssh-Convert-from-DPRINTF-macro-to-trace-events.patch new file mode 100644 index 0000000..c12051d --- /dev/null +++ b/SOURCES/kvm-block-ssh-Convert-from-DPRINTF-macro-to-trace-events.patch @@ -0,0 +1,220 @@ +From f087aa3581b13254e4de34784631f1852a9ddbec Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Mon, 8 Jul 2019 15:25:52 +0100 +Subject: [PATCH 06/39] block/ssh: Convert from DPRINTF() macro to trace events +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Pino Toscano +Message-id: <20190708152601.21123-2-ptoscano@redhat.com> +Patchwork-id: 89415 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v3 01/10] block/ssh: Convert from DPRINTF() macro to trace events +Bugzilla: 1513367 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Max Reitz +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Markus Armbruster + +From: Laurent Vivier + +Signed-off-by: Laurent Vivier +Reviewed-by: Richard W.M. Jones +Reviewed-by: Philippe Mathieu-Daudé +Message-id: 20181213162727.17438-2-lvivier@redhat.com +[mreitz: Fixed type of ssh_{read,write}_return's parameter to be ssize_t + instead of size_t] +Signed-off-by: Max Reitz +(cherry picked from commit 023908a24de4f264dbcd22352e8a304424005bd4) +Signed-off-by: Pino Toscano + +Signed-off-by: Danilo C. L. de Paula +--- + block/ssh.c | 46 +++++++++++++++++----------------------------- + block/trace-events | 17 +++++++++++++++++ + 2 files changed, 34 insertions(+), 29 deletions(-) + +diff --git a/block/ssh.c b/block/ssh.c +index 6a55d82..dfb3e3c 100644 +--- a/block/ssh.c ++++ b/block/ssh.c +@@ -41,27 +41,17 @@ + #include "qapi/qmp/qstring.h" + #include "qapi/qobject-input-visitor.h" + #include "qapi/qobject-output-visitor.h" ++#include "trace.h" + +-/* DEBUG_SSH=1 enables the DPRINTF (debugging printf) statements in +- * this block driver code. +- * ++/* + * TRACE_LIBSSH2= enables tracing in libssh2 itself. Note + * that this requires that libssh2 was specially compiled with the + * `./configure --enable-debug' option, so most likely you will have + * to compile it yourself. The meaning of is described + * here: http://www.libssh2.org/libssh2_trace.html + */ +-#define DEBUG_SSH 0 + #define TRACE_LIBSSH2 0 /* or try: LIBSSH2_TRACE_SFTP */ + +-#define DPRINTF(fmt, ...) \ +- do { \ +- if (DEBUG_SSH) { \ +- fprintf(stderr, "ssh: %-15s " fmt "\n", \ +- __func__, ##__VA_ARGS__); \ +- } \ +- } while (0) +- + typedef struct BDRVSSHState { + /* Coroutine. */ + CoMutex lock; +@@ -336,7 +326,7 @@ static int check_host_key_knownhosts(BDRVSSHState *s, + switch (r) { + case LIBSSH2_KNOWNHOST_CHECK_MATCH: + /* OK */ +- DPRINTF("host key OK: %s", found->key); ++ trace_ssh_check_host_key_knownhosts(found->key); + break; + case LIBSSH2_KNOWNHOST_CHECK_MISMATCH: + ret = -EINVAL; +@@ -721,8 +711,7 @@ static int connect_to_ssh(BDRVSSHState *s, BlockdevOptionsSsh *opts, + } + + /* Open the remote file. */ +- DPRINTF("opening file %s flags=0x%x creat_mode=0%o", +- opts->path, ssh_flags, creat_mode); ++ trace_ssh_connect_to_ssh(opts->path, ssh_flags, creat_mode); + s->sftp_handle = libssh2_sftp_open(s->sftp, opts->path, ssh_flags, + creat_mode); + if (!s->sftp_handle) { +@@ -890,7 +879,7 @@ static int coroutine_fn ssh_co_create_opts(const char *filename, QemuOpts *opts, + /* Get desired file size. */ + ssh_opts->size = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0), + BDRV_SECTOR_SIZE); +- DPRINTF("total_size=%" PRIi64, ssh_opts->size); ++ trace_ssh_co_create_opts(ssh_opts->size); + + uri_options = qdict_new(); + ret = parse_uri(filename, uri_options, errp); +@@ -946,7 +935,7 @@ static void restart_coroutine(void *opaque) + BDRVSSHState *s = bs->opaque; + AioContext *ctx = bdrv_get_aio_context(bs); + +- DPRINTF("co=%p", restart->co); ++ trace_ssh_restart_coroutine(restart->co); + aio_set_fd_handler(ctx, s->sock, false, NULL, NULL, NULL, NULL); + + aio_co_wake(restart->co); +@@ -974,13 +963,12 @@ static coroutine_fn void co_yield(BDRVSSHState *s, BlockDriverState *bs) + wr_handler = restart_coroutine; + } + +- DPRINTF("s->sock=%d rd_handler=%p wr_handler=%p", s->sock, +- rd_handler, wr_handler); ++ trace_ssh_co_yield(s->sock, rd_handler, wr_handler); + + aio_set_fd_handler(bdrv_get_aio_context(bs), s->sock, + false, rd_handler, wr_handler, NULL, &restart); + qemu_coroutine_yield(); +- DPRINTF("s->sock=%d - back", s->sock); ++ trace_ssh_co_yield_back(s->sock); + } + + /* SFTP has a function `libssh2_sftp_seek64' which seeks to a position +@@ -1003,7 +991,7 @@ static void ssh_seek(BDRVSSHState *s, int64_t offset, int flags) + bool force = (flags & SSH_SEEK_FORCE) != 0; + + if (force || op_read != s->offset_op_read || offset != s->offset) { +- DPRINTF("seeking to offset=%" PRIi64, offset); ++ trace_ssh_seek(offset); + libssh2_sftp_seek64(s->sftp_handle, offset); + s->offset = offset; + s->offset_op_read = op_read; +@@ -1019,7 +1007,7 @@ static coroutine_fn int ssh_read(BDRVSSHState *s, BlockDriverState *bs, + char *buf, *end_of_vec; + struct iovec *i; + +- DPRINTF("offset=%" PRIi64 " size=%zu", offset, size); ++ trace_ssh_read(offset, size); + + ssh_seek(s, offset, SSH_SEEK_READ); + +@@ -1038,9 +1026,9 @@ static coroutine_fn int ssh_read(BDRVSSHState *s, BlockDriverState *bs, + */ + for (got = 0; got < size; ) { + again: +- DPRINTF("sftp_read buf=%p size=%zu", buf, end_of_vec - buf); ++ trace_ssh_read_buf(buf, end_of_vec - buf); + r = libssh2_sftp_read(s->sftp_handle, buf, end_of_vec - buf); +- DPRINTF("sftp_read returned %zd", r); ++ trace_ssh_read_return(r); + + if (r == LIBSSH2_ERROR_EAGAIN || r == LIBSSH2_ERROR_TIMEOUT) { + co_yield(s, bs); +@@ -1094,7 +1082,7 @@ static int ssh_write(BDRVSSHState *s, BlockDriverState *bs, + char *buf, *end_of_vec; + struct iovec *i; + +- DPRINTF("offset=%" PRIi64 " size=%zu", offset, size); ++ trace_ssh_write(offset, size); + + ssh_seek(s, offset, SSH_SEEK_WRITE); + +@@ -1108,9 +1096,9 @@ static int ssh_write(BDRVSSHState *s, BlockDriverState *bs, + + for (written = 0; written < size; ) { + again: +- DPRINTF("sftp_write buf=%p size=%zu", buf, end_of_vec - buf); ++ trace_ssh_write_buf(buf, end_of_vec - buf); + r = libssh2_sftp_write(s->sftp_handle, buf, end_of_vec - buf); +- DPRINTF("sftp_write returned %zd", r); ++ trace_ssh_write_return(r); + + if (r == LIBSSH2_ERROR_EAGAIN || r == LIBSSH2_ERROR_TIMEOUT) { + co_yield(s, bs); +@@ -1185,7 +1173,7 @@ static coroutine_fn int ssh_flush(BDRVSSHState *s, BlockDriverState *bs) + { + int r; + +- DPRINTF("fsync"); ++ trace_ssh_flush(); + again: + r = libssh2_sftp_fsync(s->sftp_handle); + if (r == LIBSSH2_ERROR_EAGAIN || r == LIBSSH2_ERROR_TIMEOUT) { +@@ -1236,7 +1224,7 @@ static int64_t ssh_getlength(BlockDriverState *bs) + + /* Note we cannot make a libssh2 call here. */ + length = (int64_t) s->attrs.filesize; +- DPRINTF("length=%" PRIi64, length); ++ trace_ssh_getlength(length); + + return length; + } +diff --git a/block/trace-events b/block/trace-events +index c35287b..4c69548 100644 +--- a/block/trace-events ++++ b/block/trace-events +@@ -150,3 +150,20 @@ nvme_free_req_queue_wait(void *q) "q %p" + nvme_cmd_map_qiov(void *s, void *cmd, void *req, void *qiov, int entries) "s %p cmd %p req %p qiov %p entries %d" + nvme_cmd_map_qiov_pages(void *s, int i, uint64_t page) "s %p page[%d] 0x%"PRIx64 + nvme_cmd_map_qiov_iov(void *s, int i, void *page, int pages) "s %p iov[%d] %p pages %d" ++ ++# block/ssh.c ++ssh_restart_coroutine(void *co) "co=%p" ++ssh_flush(void) "fsync" ++ssh_check_host_key_knownhosts(const char *key) "host key OK: %s" ++ssh_connect_to_ssh(char *path, int flags, int mode) "opening file %s flags=0x%x creat_mode=0%o" ++ssh_co_yield(int sock, void *rd_handler, void *wr_handler) "s->sock=%d rd_handler=%p wr_handler=%p" ++ssh_co_yield_back(int sock) "s->sock=%d - back" ++ssh_getlength(int64_t length) "length=%" PRIi64 ++ssh_co_create_opts(uint64_t size) "total_size=%" PRIu64 ++ssh_read(int64_t offset, size_t size) "offset=%" PRIi64 " size=%zu" ++ssh_read_buf(void *buf, size_t size) "sftp_read buf=%p size=%zu" ++ssh_read_return(ssize_t ret) "sftp_read returned %zd" ++ssh_write(int64_t offset, size_t size) "offset=%" PRIi64 " size=%zu" ++ssh_write_buf(void *buf, size_t size) "sftp_write buf=%p size=%zu" ++ssh_write_return(ssize_t ret) "sftp_write returned %zd" ++ssh_seek(int64_t offset) "seeking to offset=%" PRIi64 +-- +1.8.3.1 + diff --git a/SOURCES/kvm-block-ssh-Do-not-report-read-write-flush-errors-to-t.patch b/SOURCES/kvm-block-ssh-Do-not-report-read-write-flush-errors-to-t.patch new file mode 100644 index 0000000..51dc4f5 --- /dev/null +++ b/SOURCES/kvm-block-ssh-Do-not-report-read-write-flush-errors-to-t.patch @@ -0,0 +1,132 @@ +From 2deb556f99ae439125674fa3c6d77424048fd30c Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Mon, 8 Jul 2019 15:25:53 +0100 +Subject: [PATCH 07/39] block/ssh: Do not report read/write/flush errors to the + user +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Pino Toscano +Message-id: <20190708152601.21123-3-ptoscano@redhat.com> +Patchwork-id: 89418 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v3 02/10] block/ssh: Do not report read/write/flush errors to the user +Bugzilla: 1513367 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Max Reitz +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Markus Armbruster + +From: Markus Armbruster + +Callbacks ssh_co_readv(), ssh_co_writev(), ssh_co_flush() report +errors to the user with error_printf(). They shouldn't, it's their +caller's job. Replace by a suitable trace point. While there, drop +the unreachable !s->sftp case. + +Perhaps we should convert this part of the block driver interface to +Error, so block drivers can pass more detail to their callers. Not +today. + +Cc: "Richard W.M. Jones" +Cc: Kevin Wolf +Cc: Max Reitz +Cc: qemu-block@nongnu.org +Signed-off-by: Markus Armbruster +Reviewed-by: Eric Blake +Message-Id: <20190417190641.26814-3-armbru@redhat.com> +(cherry picked from commit 6b3048cee0e0eccd27b62954ecc57c4a1bceb976) +Signed-off-by: Philippe Mathieu-Daudé +Signed-off-by: Danilo C. L. de Paula +--- + block/ssh.c | 38 +++++++++++++------------------------- + block/trace-events | 3 +++ + 2 files changed, 16 insertions(+), 25 deletions(-) + +diff --git a/block/ssh.c b/block/ssh.c +index dfb3e3c..89abce0 100644 +--- a/block/ssh.c ++++ b/block/ssh.c +@@ -159,31 +159,19 @@ sftp_error_setg(Error **errp, BDRVSSHState *s, const char *fs, ...) + g_free(msg); + } + +-static void GCC_FMT_ATTR(2, 3) +-sftp_error_report(BDRVSSHState *s, const char *fs, ...) ++static void sftp_error_trace(BDRVSSHState *s, const char *op) + { +- va_list args; +- +- va_start(args, fs); +- error_vprintf(fs, args); ++ char *ssh_err; ++ int ssh_err_code; ++ unsigned long sftp_err_code; + +- if ((s)->sftp) { +- char *ssh_err; +- int ssh_err_code; +- unsigned long sftp_err_code; ++ /* This is not an errno. See . */ ++ ssh_err_code = libssh2_session_last_error(s->session, ++ &ssh_err, NULL, 0); ++ /* See . */ ++ sftp_err_code = libssh2_sftp_last_error((s)->sftp); + +- /* This is not an errno. See . */ +- ssh_err_code = libssh2_session_last_error(s->session, +- &ssh_err, NULL, 0); +- /* See . */ +- sftp_err_code = libssh2_sftp_last_error((s)->sftp); +- +- error_printf(": %s (libssh2 error code: %d, sftp error code: %lu)", +- ssh_err, ssh_err_code, sftp_err_code); +- } +- +- va_end(args); +- error_printf("\n"); ++ trace_sftp_error(op, ssh_err, ssh_err_code, sftp_err_code); + } + + static int parse_uri(const char *filename, QDict *options, Error **errp) +@@ -1035,7 +1023,7 @@ static coroutine_fn int ssh_read(BDRVSSHState *s, BlockDriverState *bs, + goto again; + } + if (r < 0) { +- sftp_error_report(s, "read failed"); ++ sftp_error_trace(s, "read"); + s->offset = -1; + return -EIO; + } +@@ -1105,7 +1093,7 @@ static int ssh_write(BDRVSSHState *s, BlockDriverState *bs, + goto again; + } + if (r < 0) { +- sftp_error_report(s, "write failed"); ++ sftp_error_trace(s, "write"); + s->offset = -1; + return -EIO; + } +@@ -1186,7 +1174,7 @@ static coroutine_fn int ssh_flush(BDRVSSHState *s, BlockDriverState *bs) + return 0; + } + if (r < 0) { +- sftp_error_report(s, "fsync failed"); ++ sftp_error_trace(s, "fsync"); + return -EIO; + } + +diff --git a/block/trace-events b/block/trace-events +index 4c69548..23c9963 100644 +--- a/block/trace-events ++++ b/block/trace-events +@@ -167,3 +167,6 @@ ssh_write(int64_t offset, size_t size) "offset=%" PRIi64 " size=%zu" + ssh_write_buf(void *buf, size_t size) "sftp_write buf=%p size=%zu" + ssh_write_return(ssize_t ret) "sftp_write returned %zd" + ssh_seek(int64_t offset) "seeking to offset=%" PRIi64 ++ ++# ssh.c ++sftp_error(const char *op, const char *ssh_err, int ssh_err_code, unsigned long sftp_err_code) "%s failed: %s (libssh2 error code: %d, sftp error code: %lu)" +-- +1.8.3.1 + diff --git a/SOURCES/kvm-block-ssh-Implement-.bdrv_refresh_filename.patch b/SOURCES/kvm-block-ssh-Implement-.bdrv_refresh_filename.patch new file mode 100644 index 0000000..ec1b7fb --- /dev/null +++ b/SOURCES/kvm-block-ssh-Implement-.bdrv_refresh_filename.patch @@ -0,0 +1,291 @@ +From cd8ddc9c29115f6f8428fc17fbded67f0ce99004 Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Mon, 8 Jul 2019 15:25:57 +0100 +Subject: [PATCH 11/39] block/ssh: Implement .bdrv_refresh_filename() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Pino Toscano +Message-id: <20190708152601.21123-7-ptoscano@redhat.com> +Patchwork-id: 89417 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v3 06/10] block/ssh: Implement .bdrv_refresh_filename() +Bugzilla: 1513367 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Max Reitz +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Markus Armbruster + +From: Max Reitz + +This requires some changes to keep iotests 104 and 207 working. + +qemu-img info in 104 will now return a filename including the user name +and the port, which need to be filtered by adjusting REMOTE_TEST_DIR in +common.rc. This additional information has to be marked optional, +however (which is simple as REMOTE_TEST_DIR is a regex), because +otherwise 197 and 215 would fail: They use it (indirectly) to filter +qemu-img create output which contains a backing filename they have +passed to it -- which probably does not contain a user name or port +number. + +The problem in 207 is a nice one to have: qemu-img info used to return +json:{} filenames, but with this patch it returns nice plain ones. We +now need to adjust the filtering to hide the user name (and port number +while we are at it). The simplest way to do this is to include both in +iotests.remote_filename() so that bdrv_refresh_filename() will not +change it, and then iotests.img_info_log() will filter it correctly +automatically. + +Signed-off-by: Max Reitz +Tested-by: Richard W.M. Jones +Message-id: 20190225190828.17726-2-mreitz@redhat.com +Signed-off-by: Max Reitz +(cherry picked from commit b8c1f90118ee81090ff9093790f88bf335132814) +This patch was modified for the lack of 998b3a1e5a2dd23bf89a853e15fab, +by adding the 'QDict *options' parameter to ssh_refresh_filename(), +matching the requested prototype, and setting bs->full_open_options to +the specified option (following the hint of Max Reitz). +Signed-off-by: Pino Toscano + +Signed-off-by: Danilo C. L. de Paula +--- + block/ssh.c | 55 +++++++++++++++++++++++++++++++++++++++---- + tests/qemu-iotests/207 | 10 ++++---- + tests/qemu-iotests/207.out | 10 ++++---- + tests/qemu-iotests/common.rc | 2 +- + tests/qemu-iotests/iotests.py | 2 +- + 5 files changed, 62 insertions(+), 17 deletions(-) + +diff --git a/block/ssh.c b/block/ssh.c +index 89abce0..f0ef874 100644 +--- a/block/ssh.c ++++ b/block/ssh.c +@@ -75,6 +75,14 @@ typedef struct BDRVSSHState { + + /* Used to warn if 'flush' is not supported. */ + bool unsafe_flush_warning; ++ ++ /* ++ * Store the user name for ssh_refresh_filename() because the ++ * default depends on the system you are on -- therefore, when we ++ * generate a filename, it should always contain the user name we ++ * are actually using. ++ */ ++ char *user; + } BDRVSSHState; + + static void ssh_state_init(BDRVSSHState *s) +@@ -87,6 +95,8 @@ static void ssh_state_init(BDRVSSHState *s) + + static void ssh_state_free(BDRVSSHState *s) + { ++ g_free(s->user); ++ + if (s->sftp_handle) { + libssh2_sftp_close(s->sftp_handle); + } +@@ -628,14 +638,13 @@ static int connect_to_ssh(BDRVSSHState *s, BlockdevOptionsSsh *opts, + int ssh_flags, int creat_mode, Error **errp) + { + int r, ret; +- const char *user; + long port = 0; + + if (opts->has_user) { +- user = opts->user; ++ s->user = g_strdup(opts->user); + } else { +- user = g_get_user_name(); +- if (!user) { ++ s->user = g_strdup(g_get_user_name()); ++ if (!s->user) { + error_setg_errno(errp, errno, "Can't get user name"); + ret = -errno; + goto err; +@@ -685,7 +694,7 @@ static int connect_to_ssh(BDRVSSHState *s, BlockdevOptionsSsh *opts, + } + + /* Authenticate. */ +- ret = authenticate(s, user, errp); ++ ret = authenticate(s, s->user, errp); + if (ret < 0) { + goto err; + } +@@ -1240,6 +1249,41 @@ static int coroutine_fn ssh_co_truncate(BlockDriverState *bs, int64_t offset, + return ssh_grow_file(s, offset, errp); + } + ++static void ssh_refresh_filename(BlockDriverState *bs, QDict *options) ++{ ++ BDRVSSHState *s = bs->opaque; ++ const char *path, *host_key_check; ++ int ret; ++ ++ qdict_put_str(options, "driver", "ssh"); ++ bs->full_open_options = qobject_ref(options); ++ ++ /* ++ * None of these options can be represented in a plain "host:port" ++ * format, so if any was given, we have to abort. ++ */ ++ if (s->inet->has_ipv4 || s->inet->has_ipv6 || s->inet->has_to || ++ s->inet->has_numeric) ++ { ++ return; ++ } ++ ++ path = qdict_get_try_str(bs->full_open_options, "path"); ++ assert(path); /* mandatory option */ ++ ++ host_key_check = qdict_get_try_str(bs->full_open_options, "host_key_check"); ++ ++ ret = snprintf(bs->exact_filename, sizeof(bs->exact_filename), ++ "ssh://%s@%s:%s%s%s%s", ++ s->user, s->inet->host, s->inet->port, path, ++ host_key_check ? "?host_key_check=" : "", ++ host_key_check ?: ""); ++ if (ret >= sizeof(bs->exact_filename)) { ++ /* An overflow makes the filename unusable, so do not report any */ ++ bs->exact_filename[0] = '\0'; ++ } ++} ++ + static BlockDriver bdrv_ssh = { + .format_name = "ssh", + .protocol_name = "ssh", +@@ -1255,6 +1299,7 @@ static BlockDriver bdrv_ssh = { + .bdrv_getlength = ssh_getlength, + .bdrv_co_truncate = ssh_co_truncate, + .bdrv_co_flush_to_disk = ssh_co_flush, ++ .bdrv_refresh_filename = ssh_refresh_filename, + .create_opts = &ssh_create_opts, + }; + +diff --git a/tests/qemu-iotests/207 b/tests/qemu-iotests/207 +index 444ae23..8202bd1 100755 +--- a/tests/qemu-iotests/207 ++++ b/tests/qemu-iotests/207 +@@ -62,7 +62,7 @@ with iotests.FilePath('t.img') as disk_path, \ + 'size': 4194304 }) + vm.shutdown() + +- iotests.img_info_log(remote_path, filter_path=disk_path) ++ iotests.img_info_log(remote_path) + iotests.log("") + iotests.img_info_log(disk_path) + +@@ -87,7 +87,7 @@ with iotests.FilePath('t.img') as disk_path, \ + 'size': 8388608 }) + vm.shutdown() + +- iotests.img_info_log(remote_path, filter_path=disk_path) ++ iotests.img_info_log(remote_path) + + vm.launch() + blockdev_create(vm, { 'driver': 'ssh', +@@ -104,7 +104,7 @@ with iotests.FilePath('t.img') as disk_path, \ + 'size': 4194304 }) + vm.shutdown() + +- iotests.img_info_log(remote_path, filter_path=disk_path) ++ iotests.img_info_log(remote_path) + + md5_key = subprocess.check_output( + 'ssh-keyscan -t rsa 127.0.0.1 2>/dev/null | grep -v "\\^#" | ' + +@@ -142,7 +142,7 @@ with iotests.FilePath('t.img') as disk_path, \ + 'size': 8388608 }) + vm.shutdown() + +- iotests.img_info_log(remote_path, filter_path=disk_path) ++ iotests.img_info_log(remote_path) + + sha1_key = subprocess.check_output( + 'ssh-keyscan -t rsa 127.0.0.1 2>/dev/null | grep -v "\\^#" | ' + +@@ -180,7 +180,7 @@ with iotests.FilePath('t.img') as disk_path, \ + 'size': 4194304 }) + vm.shutdown() + +- iotests.img_info_log(remote_path, filter_path=disk_path) ++ iotests.img_info_log(remote_path) + + # + # Invalid path and user +diff --git a/tests/qemu-iotests/207.out b/tests/qemu-iotests/207.out +index 078b7e6..fc131a6 100644 +--- a/tests/qemu-iotests/207.out ++++ b/tests/qemu-iotests/207.out +@@ -5,7 +5,7 @@ + {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} + {u'return': {}} + +-image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.port": "22", "driver": "ssh", "path": "TEST_IMG"}} ++image: TEST_IMG + file format: IMGFMT + virtual size: 4.0M (4194304 bytes) + +@@ -21,7 +21,7 @@ virtual size: 4.0M (4194304 bytes) + {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} + {u'return': {}} + +-image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.port": "22", "driver": "ssh", "path": "TEST_IMG"}} ++image: TEST_IMG + file format: IMGFMT + virtual size: 8.0M (8388608 bytes) + +@@ -30,7 +30,7 @@ virtual size: 8.0M (8388608 bytes) + {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} + {u'return': {}} + +-image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.port": "22", "driver": "ssh", "path": "TEST_IMG"}} ++image: TEST_IMG + file format: IMGFMT + virtual size: 4.0M (4194304 bytes) + +@@ -45,7 +45,7 @@ Job failed: remote host key does not match host_key_check 'wrong' + {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} + {u'return': {}} + +-image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.port": "22", "driver": "ssh", "path": "TEST_IMG"}} ++image: TEST_IMG + file format: IMGFMT + virtual size: 8.0M (8388608 bytes) + +@@ -60,7 +60,7 @@ Job failed: remote host key does not match host_key_check 'wrong' + {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} + {u'return': {}} + +-image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.port": "22", "driver": "ssh", "path": "TEST_IMG"}} ++image: TEST_IMG + file format: IMGFMT + virtual size: 4.0M (4194304 bytes) + +diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc +index 6490c8d..9ff8fa1 100644 +--- a/tests/qemu-iotests/common.rc ++++ b/tests/qemu-iotests/common.rc +@@ -145,7 +145,7 @@ else + TEST_IMG="nbd:127.0.0.1:10810" + elif [ "$IMGPROTO" = "ssh" ]; then + TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT +- REMOTE_TEST_DIR="ssh://127.0.0.1$TEST_DIR" ++ REMOTE_TEST_DIR="ssh://\\($USER@\\)\\?127.0.0.1\\(:[0-9]\\+\\)\\?$TEST_DIR" + TEST_IMG="ssh://127.0.0.1$TEST_IMG_FILE" + elif [ "$IMGPROTO" = "nfs" ]; then + TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT +diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py +index 4e67fbb..0f6980a 100644 +--- a/tests/qemu-iotests/iotests.py ++++ b/tests/qemu-iotests/iotests.py +@@ -325,7 +325,7 @@ def remote_filename(path): + if imgproto == 'file': + return path + elif imgproto == 'ssh': +- return "ssh://127.0.0.1%s" % (path) ++ return "ssh://%s@127.0.0.1:22%s" % (os.environ.get('USER'), path) + else: + raise Exception("Protocol %s not supported" % (imgproto)) + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-ccid-Fix-dwProtocols-advertisement-of-T-0.patch b/SOURCES/kvm-ccid-Fix-dwProtocols-advertisement-of-T-0.patch new file mode 100644 index 0000000..5af3ea1 --- /dev/null +++ b/SOURCES/kvm-ccid-Fix-dwProtocols-advertisement-of-T-0.patch @@ -0,0 +1,67 @@ +From e541592f0c98696276261a7c36afe074a3bdd956 Mon Sep 17 00:00:00 2001 +From: Maxim Levitsky +Date: Wed, 18 Sep 2019 18:45:52 +0100 +Subject: [PATCH 11/22] ccid: Fix dwProtocols advertisement of T=0 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Maxim Levitsky +Message-id: <20190918184552.10820-2-mlevitsk@redhat.com> +Patchwork-id: 90769 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH 1/1] ccid: Fix dwProtocols advertisement of T=0 +Bugzilla: 1746361 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Stefano Garzarella +RH-Acked-by: John Snow + +From: Jason Andryuk + +Commit d7d218ef02d87c637d20d64da8f575d434ff6f78 attempted to change +dwProtocols to only advertise support for T=0 and not T=1. The change +was incorrect as it changed 0x00000003 to 0x00010000. + +lsusb -v in a linux guest shows: +"dwProtocols 65536 (Invalid values detected)", though the +smart card could still be accessed. Windows 7 does not detect inserted +smart cards and logs the the following Error in the Event Logs: + + Source: Smart Card Service + Event ID: 610 + Smart Card Reader 'QEMU QEMU USB CCID 0' rejected IOCTL SET_PROTOCOL: + Incorrect function. If this error persists, your smart card or reader + may not be functioning correctly + + Command Header: 03 00 00 00 + +Setting to 0x00000001 fixes the Windows issue. + +Signed-off-by: Jason Andryuk +Message-id: 20180420183219.20722-1-jandryuk@gmail.com +Cc: qemu-stable@nongnu.org +Signed-off-by: Gerd Hoffmann +(cherry picked from commit 0ee86bb6c5beb6498488850104f7557c376d0bef) +Signed-off-by: Maxim Levitsky +Signed-off-by: Danilo C. L. de Paula +--- + hw/usb/dev-smartcard-reader.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c +index e646805..cabb564 100644 +--- a/hw/usb/dev-smartcard-reader.c ++++ b/hw/usb/dev-smartcard-reader.c +@@ -329,8 +329,8 @@ static const uint8_t qemu_ccid_descriptor[] = { + */ + 0x07, /* u8 bVoltageSupport; 01h - 5.0v, 02h - 3.0, 03 - 1.8 */ + +- 0x00, 0x00, /* u32 dwProtocols; RRRR PPPP. RRRR = 0000h.*/ +- 0x01, 0x00, /* PPPP: 0001h = Protocol T=0, 0002h = Protocol T=1 */ ++ 0x01, 0x00, /* u32 dwProtocols; RRRR PPPP. RRRR = 0000h.*/ ++ 0x00, 0x00, /* PPPP: 0001h = Protocol T=0, 0002h = Protocol T=1 */ + /* u32 dwDefaultClock; in kHZ (0x0fa0 is 4 MHz) */ + 0xa0, 0x0f, 0x00, 0x00, + /* u32 dwMaximumClock; */ +-- +1.8.3.1 + diff --git a/SOURCES/kvm-console-Avoid-segfault-in-screendump.patch b/SOURCES/kvm-console-Avoid-segfault-in-screendump.patch new file mode 100644 index 0000000..9c1c18e --- /dev/null +++ b/SOURCES/kvm-console-Avoid-segfault-in-screendump.patch @@ -0,0 +1,69 @@ +From 60df0d1b59e02c4ef2964473f84b707153ccad58 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Tue, 13 Aug 2019 12:21:56 +0100 +Subject: [PATCH 1/3] console: Avoid segfault in screendump +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Gerd Hoffmann +Message-id: <20190813122156.5609-2-kraxel@redhat.com> +Patchwork-id: 89958 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 1/1] console: Avoid segfault in screendump +Bugzilla: 1684383 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: John Snow + +From: Michal Privoznik + +After f771c5440e04626f1 it is possible to select device and +head which to take screendump from. And even though we check if +provided head number falls within range, it may still happen that +the console has no surface yet leading to SIGSEGV: + + qemu.git $ ./x86_64-softmmu/qemu-system-x86_64 \ + -qmp stdio \ + -device virtio-vga,id=video0,max_outputs=4 + + {"execute":"qmp_capabilities"} + {"execute":"screendump", "arguments":{"filename":"/tmp/screen.ppm", "device":"video0", "head":1}} + Segmentation fault + + #0 0x00005628249dda88 in ppm_save (filename=0x56282826cbc0 "/tmp/screen.ppm", ds=0x0, errp=0x7fff52a6fae0) at ui/console.c:304 + #1 0x00005628249ddd9b in qmp_screendump (filename=0x56282826cbc0 "/tmp/screen.ppm", has_device=true, device=0x5628276902d0 "video0", has_head=true, head=1, errp=0x7fff52a6fae0) at ui/console.c:375 + #2 0x00005628247740df in qmp_marshal_screendump (args=0x562828265e00, ret=0x7fff52a6fb68, errp=0x7fff52a6fb60) at qapi/qapi-commands-ui.c:110 + +Here, @ds from frame #0 (or @surface from frame #1) is +dereferenced at the very beginning of ppm_save(). And because +it's NULL crash happens. + +Signed-off-by: Michal Privoznik +Reviewed-by: Thomas Huth +Message-id: cb05bb1909daa6ba62145c0194aafa05a14ed3d1.1526569138.git.mprivozn@redhat.com +Signed-off-by: Gerd Hoffmann +(cherry picked from commit 08d9864fa4e0c616e076ca8b225d39a7ecb189af) +Signed-off-by: Danilo C. L. de Paula +--- + ui/console.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/ui/console.c b/ui/console.c +index 594ec63..4e4052f 100644 +--- a/ui/console.c ++++ b/ui/console.c +@@ -370,6 +370,11 @@ void qmp_screendump(const char *filename, bool has_device, const char *device, + + graphic_hw_update(con); + surface = qemu_console_surface(con); ++ if (!surface) { ++ error_setg(errp, "no surface"); ++ return; ++ } ++ + ppm_save(filename, surface, errp); + } + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-curl-Check-completion-in-curl_multi_do.patch b/SOURCES/kvm-curl-Check-completion-in-curl_multi_do.patch new file mode 100644 index 0000000..95ac20c --- /dev/null +++ b/SOURCES/kvm-curl-Check-completion-in-curl_multi_do.patch @@ -0,0 +1,87 @@ +From a09766bbc8a4208fc0f62904cebec4022beba6b0 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Tue, 19 Nov 2019 15:29:56 +0000 +Subject: [PATCH 4/8] curl: Check completion in curl_multi_do() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Max Reitz +Message-id: <20191119153000.101646-4-mreitz@redhat.com> +Patchwork-id: 92516 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH 3/7] curl: Check completion in curl_multi_do() +Bugzilla: 1744602 +RH-Acked-by: Maxim Levitsky +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Stefano Garzarella + +While it is more likely that transfers complete after some file +descriptor has data ready to read, we probably should not rely on it. +Better be safe than sorry and call curl_multi_check_completion() in +curl_multi_do(), too, just like it is done in curl_multi_read(). + +With this change, curl_multi_do() and curl_multi_read() are actually the +same, so drop curl_multi_read() and use curl_multi_do() as the sole FD +handler. + +Signed-off-by: Max Reitz +Message-id: 20190910124136.10565-4-mreitz@redhat.com +Reviewed-by: Maxim Levitsky +Reviewed-by: John Snow +Signed-off-by: Max Reitz +(cherry picked from commit 948403bcb1c7e71dcbe8ab8479cf3934a0efcbb5) +Signed-off-by: Max Reitz +Signed-off-by: Danilo C. L. de Paula +--- + block/curl.c | 14 ++------------ + 1 file changed, 2 insertions(+), 12 deletions(-) + +diff --git a/block/curl.c b/block/curl.c +index b3fe09f..8f31594 100644 +--- a/block/curl.c ++++ b/block/curl.c +@@ -148,7 +148,6 @@ typedef struct BDRVCURLState { + + static void curl_clean_state(CURLState *s); + static void curl_multi_do(void *arg); +-static void curl_multi_read(void *arg); + + #ifdef NEED_CURL_TIMER_CALLBACK + /* Called from curl_multi_do_locked, with s->mutex held. */ +@@ -195,7 +194,7 @@ static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action, + switch (action) { + case CURL_POLL_IN: + aio_set_fd_handler(s->aio_context, fd, false, +- curl_multi_read, NULL, NULL, state); ++ curl_multi_do, NULL, NULL, state); + break; + case CURL_POLL_OUT: + aio_set_fd_handler(s->aio_context, fd, false, +@@ -203,7 +202,7 @@ static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action, + break; + case CURL_POLL_INOUT: + aio_set_fd_handler(s->aio_context, fd, false, +- curl_multi_read, curl_multi_do, NULL, state); ++ curl_multi_do, curl_multi_do, NULL, state); + break; + case CURL_POLL_REMOVE: + aio_set_fd_handler(s->aio_context, fd, false, +@@ -427,15 +426,6 @@ static void curl_multi_do(void *arg) + + qemu_mutex_lock(&s->s->mutex); + curl_multi_do_locked(s); +- qemu_mutex_unlock(&s->s->mutex); +-} +- +-static void curl_multi_read(void *arg) +-{ +- CURLState *s = (CURLState *)arg; +- +- qemu_mutex_lock(&s->s->mutex); +- curl_multi_do_locked(s); + curl_multi_check_completion(s->s); + qemu_mutex_unlock(&s->s->mutex); + } +-- +1.8.3.1 + diff --git a/SOURCES/kvm-curl-Check-curl_multi_add_handle-s-return-code.patch b/SOURCES/kvm-curl-Check-curl_multi_add_handle-s-return-code.patch new file mode 100644 index 0000000..859023c --- /dev/null +++ b/SOURCES/kvm-curl-Check-curl_multi_add_handle-s-return-code.patch @@ -0,0 +1,54 @@ +From d8de6fc3530b5cfa05485f24e14af4ce44a8b72d Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Tue, 19 Nov 2019 15:30:00 +0000 +Subject: [PATCH 8/8] curl: Check curl_multi_add_handle()'s return code +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Max Reitz +Message-id: <20191119153000.101646-8-mreitz@redhat.com> +Patchwork-id: 92521 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH 7/7] curl: Check curl_multi_add_handle()'s return code +Bugzilla: 1744602 +RH-Acked-by: Maxim Levitsky +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Stefano Garzarella + +If we had done that all along, debugging would have been much simpler. +(Also, I/O errors are better than hangs.) + +Signed-off-by: Max Reitz +Message-id: 20190910124136.10565-8-mreitz@redhat.com +Reviewed-by: Maxim Levitsky +Reviewed-by: John Snow +Signed-off-by: Max Reitz +(cherry picked from commit c34dc07f9f01cf686e512f939aece744723072cd) +Signed-off-by: Max Reitz +Signed-off-by: Danilo C. L. de Paula +--- + block/curl.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/block/curl.c b/block/curl.c +index b5899e1..5d05d30 100644 +--- a/block/curl.c ++++ b/block/curl.c +@@ -891,7 +891,13 @@ static void curl_setup_preadv(BlockDriverState *bs, CURLAIOCB *acb) + acb->bytes, start, state->range); + curl_easy_setopt(state->curl, CURLOPT_RANGE, state->range); + +- curl_multi_add_handle(s->multi, state->curl); ++ if (curl_multi_add_handle(s->multi, state->curl) != CURLM_OK) { ++ state->acb[0] = NULL; ++ acb->ret = -EIO; ++ ++ curl_clean_state(state); ++ goto out; ++ } + + /* Tell curl it needs to kick things off */ + curl_multi_socket_action(s->multi, CURL_SOCKET_TIMEOUT, 0, &running); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-curl-Handle-success-in-multi_check_completion.patch b/SOURCES/kvm-curl-Handle-success-in-multi_check_completion.patch new file mode 100644 index 0000000..9fe667e --- /dev/null +++ b/SOURCES/kvm-curl-Handle-success-in-multi_check_completion.patch @@ -0,0 +1,162 @@ +From 23f5a846f6702c456cf7cc9490e50cfd23368910 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Tue, 19 Nov 2019 15:29:59 +0000 +Subject: [PATCH 7/8] curl: Handle success in multi_check_completion +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Max Reitz +Message-id: <20191119153000.101646-7-mreitz@redhat.com> +Patchwork-id: 92520 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH 6/7] curl: Handle success in multi_check_completion +Bugzilla: 1744602 +RH-Acked-by: Maxim Levitsky +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Stefano Garzarella + +Background: As of cURL 7.59.0, it verifies that several functions are +not called from within a callback. Among these functions is +curl_multi_add_handle(). + +curl_read_cb() is a callback from cURL and not a coroutine. Waking up +acb->co will lead to entering it then and there, which means the current +request will settle and the caller (if it runs in the same coroutine) +may then issue the next request. In such a case, we will enter +curl_setup_preadv() effectively from within curl_read_cb(). + +Calling curl_multi_add_handle() will then fail and the new request will +not be processed. + +Fix this by not letting curl_read_cb() wake up acb->co. Instead, leave +the whole business of settling the AIOCB objects to +curl_multi_check_completion() (which is called from our timer callback +and our FD handler, so not from any cURL callbacks). + +Reported-by: Natalie Gavrielov +Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=1740193 +Cc: qemu-stable@nongnu.org +Signed-off-by: Max Reitz +Message-id: 20190910124136.10565-7-mreitz@redhat.com +Reviewed-by: John Snow +Reviewed-by: Maxim Levitsky +Signed-off-by: Max Reitz +(cherry picked from commit bfb23b480a49114315877aacf700b49453e0f9d9) +Signed-off-by: Max Reitz +Signed-off-by: Danilo C. L. de Paula +--- + block/curl.c | 69 +++++++++++++++++++++++++----------------------------------- + 1 file changed, 29 insertions(+), 40 deletions(-) + +diff --git a/block/curl.c b/block/curl.c +index f776615..b5899e1 100644 +--- a/block/curl.c ++++ b/block/curl.c +@@ -238,7 +238,6 @@ static size_t curl_read_cb(void *ptr, size_t size, size_t nmemb, void *opaque) + { + CURLState *s = ((CURLState*)opaque); + size_t realsize = size * nmemb; +- int i; + + DPRINTF("CURL: Just reading %zd bytes\n", realsize); + +@@ -254,32 +253,6 @@ static size_t curl_read_cb(void *ptr, size_t size, size_t nmemb, void *opaque) + memcpy(s->orig_buf + s->buf_off, ptr, realsize); + s->buf_off += realsize; + +- for(i=0; iacb[i]; +- +- if (!acb) +- continue; +- +- if ((s->buf_off >= acb->end)) { +- size_t request_length = acb->bytes; +- +- qemu_iovec_from_buf(acb->qiov, 0, s->orig_buf + acb->start, +- acb->end - acb->start); +- +- if (acb->end - acb->start < request_length) { +- size_t offset = acb->end - acb->start; +- qemu_iovec_memset(acb->qiov, offset, 0, +- request_length - offset); +- } +- +- acb->ret = 0; +- s->acb[i] = NULL; +- qemu_mutex_unlock(&s->s->mutex); +- aio_co_wake(acb->co); +- qemu_mutex_lock(&s->s->mutex); +- } +- } +- + read_end: + /* curl will error out if we do not return this value */ + return size * nmemb; +@@ -360,13 +333,14 @@ static void curl_multi_check_completion(BDRVCURLState *s) + break; + + if (msg->msg == CURLMSG_DONE) { ++ int i; + CURLState *state = NULL; ++ bool error = msg->data.result != CURLE_OK; ++ + curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE, + (char **)&state); + +- /* ACBs for successful messages get completed in curl_read_cb */ +- if (msg->data.result != CURLE_OK) { +- int i; ++ if (error) { + static int errcount = 100; + + /* Don't lose the original error message from curl, since +@@ -378,20 +352,35 @@ static void curl_multi_check_completion(BDRVCURLState *s) + error_report("curl: further errors suppressed"); + } + } ++ } + +- for (i = 0; i < CURL_NUM_ACB; i++) { +- CURLAIOCB *acb = state->acb[i]; ++ for (i = 0; i < CURL_NUM_ACB; i++) { ++ CURLAIOCB *acb = state->acb[i]; + +- if (acb == NULL) { +- continue; +- } ++ if (acb == NULL) { ++ continue; ++ } ++ ++ if (!error) { ++ /* Assert that we have read all data */ ++ assert(state->buf_off >= acb->end); ++ ++ qemu_iovec_from_buf(acb->qiov, 0, ++ state->orig_buf + acb->start, ++ acb->end - acb->start); + +- acb->ret = -EIO; +- state->acb[i] = NULL; +- qemu_mutex_unlock(&s->mutex); +- aio_co_wake(acb->co); +- qemu_mutex_lock(&s->mutex); ++ if (acb->end - acb->start < acb->bytes) { ++ size_t offset = acb->end - acb->start; ++ qemu_iovec_memset(acb->qiov, offset, 0, ++ acb->bytes - offset); ++ } + } ++ ++ acb->ret = error ? -EIO : 0; ++ state->acb[i] = NULL; ++ qemu_mutex_unlock(&s->mutex); ++ aio_co_wake(acb->co); ++ qemu_mutex_lock(&s->mutex); + } + + curl_clean_state(state); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-curl-Keep-pointer-to-the-CURLState-in-CURLSocket.patch b/SOURCES/kvm-curl-Keep-pointer-to-the-CURLState-in-CURLSocket.patch new file mode 100644 index 0000000..65742ed --- /dev/null +++ b/SOURCES/kvm-curl-Keep-pointer-to-the-CURLState-in-CURLSocket.patch @@ -0,0 +1,65 @@ +From 21dbedae8100710d284b79f7ce21a6b095a4c6e0 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Tue, 19 Nov 2019 15:29:54 +0000 +Subject: [PATCH 2/8] curl: Keep pointer to the CURLState in CURLSocket +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Max Reitz +Message-id: <20191119153000.101646-2-mreitz@redhat.com> +Patchwork-id: 92515 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH 1/7] curl: Keep pointer to the CURLState in CURLSocket +Bugzilla: 1744602 +RH-Acked-by: Maxim Levitsky +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Stefano Garzarella + +A follow-up patch will make curl_multi_do() and curl_multi_read() take a +CURLSocket instead of the CURLState. They still need the latter, +though, so add a pointer to it to the former. + +Cc: qemu-stable@nongnu.org +Signed-off-by: Max Reitz +Reviewed-by: John Snow +Message-id: 20190910124136.10565-2-mreitz@redhat.com +Reviewed-by: Maxim Levitsky +Signed-off-by: Max Reitz +(cherry picked from commit 0487861685294660b23bc146e1ebd5304aa8bbe0) +Signed-off-by: Max Reitz +Signed-off-by: Danilo C. L. de Paula +--- + block/curl.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/block/curl.c b/block/curl.c +index f0df33a..fa602d1 100644 +--- a/block/curl.c ++++ b/block/curl.c +@@ -89,6 +89,7 @@ static CURLMcode __curl_multi_socket_action(CURLM *multi_handle, + #define CURL_BLOCK_OPT_PROXY_PASSWORD_SECRET "proxy-password-secret" + + struct BDRVCURLState; ++struct CURLState; + + static bool libcurl_initialized; + +@@ -106,6 +107,7 @@ typedef struct CURLAIOCB { + + typedef struct CURLSocket { + int fd; ++ struct CURLState *state; + QLIST_ENTRY(CURLSocket) next; + } CURLSocket; + +@@ -189,6 +191,7 @@ static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action, + if (!socket) { + socket = g_new0(CURLSocket, 1); + socket->fd = fd; ++ socket->state = state; + QLIST_INSERT_HEAD(&state->sockets, socket, next); + } + socket = NULL; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-curl-Keep-socket-until-the-end-of-curl_sock_cb.patch b/SOURCES/kvm-curl-Keep-socket-until-the-end-of-curl_sock_cb.patch new file mode 100644 index 0000000..1ed321a --- /dev/null +++ b/SOURCES/kvm-curl-Keep-socket-until-the-end-of-curl_sock_cb.patch @@ -0,0 +1,72 @@ +From 46598620c18de69d9565e662a47d2615984cc49b Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Tue, 19 Nov 2019 15:29:55 +0000 +Subject: [PATCH 3/8] curl: Keep *socket until the end of curl_sock_cb() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Max Reitz +Message-id: <20191119153000.101646-3-mreitz@redhat.com> +Patchwork-id: 92517 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH 2/7] curl: Keep *socket until the end of curl_sock_cb() +Bugzilla: 1744602 +RH-Acked-by: Maxim Levitsky +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Stefano Garzarella + +This does not really change anything, but it makes the code a bit easier +to follow once we use @socket as the opaque pointer for +aio_set_fd_handler(). + +Cc: qemu-stable@nongnu.org +Signed-off-by: Max Reitz +Message-id: 20190910124136.10565-3-mreitz@redhat.com +Reviewed-by: Maxim Levitsky +Reviewed-by: John Snow +Signed-off-by: Max Reitz +(cherry picked from commit 007f339b1099af46a008dac438ca0943e31dba72) +Signed-off-by: Max Reitz +Signed-off-by: Danilo C. L. de Paula +--- + block/curl.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/block/curl.c b/block/curl.c +index fa602d1..b3fe09f 100644 +--- a/block/curl.c ++++ b/block/curl.c +@@ -181,10 +181,6 @@ static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action, + + QLIST_FOREACH(socket, &state->sockets, next) { + if (socket->fd == fd) { +- if (action == CURL_POLL_REMOVE) { +- QLIST_REMOVE(socket, next); +- g_free(socket); +- } + break; + } + } +@@ -194,7 +190,6 @@ static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action, + socket->state = state; + QLIST_INSERT_HEAD(&state->sockets, socket, next); + } +- socket = NULL; + + DPRINTF("CURL (AIO): Sock action %d on fd %d\n", action, (int)fd); + switch (action) { +@@ -216,6 +211,11 @@ static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action, + break; + } + ++ if (action == CURL_POLL_REMOVE) { ++ QLIST_REMOVE(socket, next); ++ g_free(socket); ++ } ++ + return 0; + } + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-curl-Pass-CURLSocket-to-curl_multi_do.patch b/SOURCES/kvm-curl-Pass-CURLSocket-to-curl_multi_do.patch new file mode 100644 index 0000000..6879fb2 --- /dev/null +++ b/SOURCES/kvm-curl-Pass-CURLSocket-to-curl_multi_do.patch @@ -0,0 +1,93 @@ +From 37acfe84ccbc4cc050e7be0ba9c8c4134a7b004e Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Tue, 19 Nov 2019 15:29:57 +0000 +Subject: [PATCH 5/8] curl: Pass CURLSocket to curl_multi_do() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Max Reitz +Message-id: <20191119153000.101646-5-mreitz@redhat.com> +Patchwork-id: 92518 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH 4/7] curl: Pass CURLSocket to curl_multi_do() +Bugzilla: 1744602 +RH-Acked-by: Maxim Levitsky +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Stefano Garzarella + +curl_multi_do_locked() currently marks all sockets as ready. That is +not only inefficient, but in fact unsafe (the loop is). A follow-up +patch will change that, but to do so, curl_multi_do_locked() needs to +know exactly which socket is ready; and that is accomplished by this +patch here. + +Cc: qemu-stable@nongnu.org +Signed-off-by: Max Reitz +Message-id: 20190910124136.10565-5-mreitz@redhat.com +Reviewed-by: Maxim Levitsky +Reviewed-by: John Snow +Signed-off-by: Max Reitz +(cherry picked from commit 9dbad87d25587ff640ef878f7b6159fc368ff541) +Signed-off-by: Max Reitz +Signed-off-by: Danilo C. L. de Paula +--- + block/curl.c | 20 +++++++++++--------- + 1 file changed, 11 insertions(+), 9 deletions(-) + +diff --git a/block/curl.c b/block/curl.c +index 8f31594..de00ec8 100644 +--- a/block/curl.c ++++ b/block/curl.c +@@ -194,15 +194,15 @@ static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action, + switch (action) { + case CURL_POLL_IN: + aio_set_fd_handler(s->aio_context, fd, false, +- curl_multi_do, NULL, NULL, state); ++ curl_multi_do, NULL, NULL, socket); + break; + case CURL_POLL_OUT: + aio_set_fd_handler(s->aio_context, fd, false, +- NULL, curl_multi_do, NULL, state); ++ NULL, curl_multi_do, NULL, socket); + break; + case CURL_POLL_INOUT: + aio_set_fd_handler(s->aio_context, fd, false, +- curl_multi_do, curl_multi_do, NULL, state); ++ curl_multi_do, curl_multi_do, NULL, socket); + break; + case CURL_POLL_REMOVE: + aio_set_fd_handler(s->aio_context, fd, false, +@@ -401,9 +401,10 @@ static void curl_multi_check_completion(BDRVCURLState *s) + } + + /* Called with s->mutex held. */ +-static void curl_multi_do_locked(CURLState *s) ++static void curl_multi_do_locked(CURLSocket *ready_socket) + { + CURLSocket *socket, *next_socket; ++ CURLState *s = ready_socket->state; + int running; + int r; + +@@ -422,12 +423,13 @@ static void curl_multi_do_locked(CURLState *s) + + static void curl_multi_do(void *arg) + { +- CURLState *s = (CURLState *)arg; ++ CURLSocket *socket = arg; ++ BDRVCURLState *s = socket->state->s; + +- qemu_mutex_lock(&s->s->mutex); +- curl_multi_do_locked(s); +- curl_multi_check_completion(s->s); +- qemu_mutex_unlock(&s->s->mutex); ++ qemu_mutex_lock(&s->mutex); ++ curl_multi_do_locked(socket); ++ curl_multi_check_completion(s); ++ qemu_mutex_unlock(&s->mutex); + } + + static void curl_multi_timeout_do(void *arg) +-- +1.8.3.1 + diff --git a/SOURCES/kvm-curl-Report-only-ready-sockets.patch b/SOURCES/kvm-curl-Report-only-ready-sockets.patch new file mode 100644 index 0000000..06db6e3 --- /dev/null +++ b/SOURCES/kvm-curl-Report-only-ready-sockets.patch @@ -0,0 +1,77 @@ +From 70c7a568e3c1384704228622990d6aaa2350e44e Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Tue, 19 Nov 2019 15:29:58 +0000 +Subject: [PATCH 6/8] curl: Report only ready sockets +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Max Reitz +Message-id: <20191119153000.101646-6-mreitz@redhat.com> +Patchwork-id: 92519 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH 5/7] curl: Report only ready sockets +Bugzilla: 1744602 +RH-Acked-by: Maxim Levitsky +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Stefano Garzarella + +Instead of reporting all sockets to cURL, only report the one that has +caused curl_multi_do_locked() to be called. This lets us get rid of the +QLIST_FOREACH_SAFE() list, which was actually wrong: SAFE foreaches are +only safe when the current element is removed in each iteration. If it +possible for the list to be concurrently modified, we cannot guarantee +that only the current element will be removed. Therefore, we must not +use QLIST_FOREACH_SAFE() here. + +Fixes: ff5ca1664af85b24a4180d595ea6873fd3deac57 +Cc: qemu-stable@nongnu.org +Signed-off-by: Max Reitz +Message-id: 20190910124136.10565-6-mreitz@redhat.com +Reviewed-by: Maxim Levitsky +Reviewed-by: John Snow +Signed-off-by: Max Reitz +(cherry picked from commit 9abaf9fc474c3dd53e8e119326abc774c977c331) +Signed-off-by: Max Reitz +Signed-off-by: Danilo C. L. de Paula +--- + block/curl.c | 17 ++++++----------- + 1 file changed, 6 insertions(+), 11 deletions(-) + +diff --git a/block/curl.c b/block/curl.c +index de00ec8..f776615 100644 +--- a/block/curl.c ++++ b/block/curl.c +@@ -401,24 +401,19 @@ static void curl_multi_check_completion(BDRVCURLState *s) + } + + /* Called with s->mutex held. */ +-static void curl_multi_do_locked(CURLSocket *ready_socket) ++static void curl_multi_do_locked(CURLSocket *socket) + { +- CURLSocket *socket, *next_socket; +- CURLState *s = ready_socket->state; ++ BDRVCURLState *s = socket->state->s; + int running; + int r; + +- if (!s->s->multi) { ++ if (!s->multi) { + return; + } + +- /* Need to use _SAFE because curl_multi_socket_action() may trigger +- * curl_sock_cb() which might modify this list */ +- QLIST_FOREACH_SAFE(socket, &s->sockets, next, next_socket) { +- do { +- r = curl_multi_socket_action(s->s->multi, socket->fd, 0, &running); +- } while (r == CURLM_CALL_MULTI_PERFORM); +- } ++ do { ++ r = curl_multi_socket_action(s->multi, socket->fd, 0, &running); ++ } while (r == CURLM_CALL_MULTI_PERFORM); + } + + static void curl_multi_do(void *arg) +-- +1.8.3.1 + diff --git a/SOURCES/kvm-file-posix-Handle-undetectable-alignment.patch b/SOURCES/kvm-file-posix-Handle-undetectable-alignment.patch new file mode 100644 index 0000000..b4a7bad --- /dev/null +++ b/SOURCES/kvm-file-posix-Handle-undetectable-alignment.patch @@ -0,0 +1,127 @@ +From 5935958fc4eb9934b1493486a69f0f571e7da112 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 30 Aug 2019 12:56:24 +0100 +Subject: [PATCH 06/10] file-posix: Handle undetectable alignment + +RH-Author: Thomas Huth +Message-id: <20190830125628.23668-2-thuth@redhat.com> +Patchwork-id: 90209 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v2 1/5] file-posix: Handle undetectable alignment +Bugzilla: 1738839 +RH-Acked-by: Cornelia Huck +RH-Acked-by: Max Reitz +RH-Acked-by: David Hildenbrand + +In some cases buf_align or request_alignment cannot be detected: + +1. With Gluster, buf_align cannot be detected since the actual I/O is + done on Gluster server, and qemu buffer alignment does not matter. + Since we don't have alignment requirement, buf_align=1 is the best + value. + +2. With local XFS filesystem, buf_align cannot be detected if reading + from unallocated area. In this we must align the buffer, but we don't + know what is the correct size. Using the wrong alignment results in + I/O error. + +3. With Gluster backed by XFS, request_alignment cannot be detected if + reading from unallocated area. In this case we need to use the + correct alignment, and failing to do so results in I/O errors. + +4. With NFS, the server does not use direct I/O, so both buf_align cannot + be detected. In this case we don't need any alignment so we can use + buf_align=1 and request_alignment=1. + +These cases seems to work when storage sector size is 512 bytes, because +the current code starts checking align=512. If the check succeeds +because alignment cannot be detected we use 512. But this does not work +for storage with 4k sector size. + +To determine if we can detect the alignment, we probe first with +align=1. If probing succeeds, maybe there are no alignment requirement +(cases 1, 4) or we are probing unallocated area (cases 2, 3). Since we +don't have any way to tell, we treat this as undetectable alignment. If +probing with align=1 fails with EINVAL, but probing with one of the +expected alignments succeeds, we know that we found a working alignment. + +Practically the alignment requirements are the same for buffer +alignment, buffer length, and offset in file. So in case we cannot +detect buf_align, we can use request alignment. If we cannot detect +request alignment, we can fallback to a safe value. To use this logic, +we probe first request alignment instead of buf_align. + +Here is a table showing the behaviour with current code (the value in +parenthesis is the optimal value). + +Case Sector buf_align (opt) request_alignment (opt) result + +Signed-off-by: Danilo C. L. de Paula +--- + block/file-posix.c | 36 +++++++++++++++++++++++++----------- + 1 file changed, 25 insertions(+), 11 deletions(-) + +diff --git a/block/file-posix.c b/block/file-posix.c +index 4b404e4..84c5a31 100644 +--- a/block/file-posix.c ++++ b/block/file-posix.c +@@ -324,6 +324,7 @@ static void raw_probe_alignment(BlockDriverState *bs, int fd, Error **errp) + BDRVRawState *s = bs->opaque; + char *buf; + size_t max_align = MAX(MAX_BLOCKSIZE, getpagesize()); ++ size_t alignments[] = {1, 512, 1024, 2048, 4096}; + + /* For SCSI generic devices the alignment is not really used. + With buffered I/O, we don't have any restrictions. */ +@@ -350,25 +351,38 @@ static void raw_probe_alignment(BlockDriverState *bs, int fd, Error **errp) + } + #endif + +- /* If we could not get the sizes so far, we can only guess them */ +- if (!s->buf_align) { ++ /* ++ * If we could not get the sizes so far, we can only guess them. First try ++ * to detect request alignment, since it is more likely to succeed. Then ++ * try to detect buf_align, which cannot be detected in some cases (e.g. ++ * Gluster). If buf_align cannot be detected, we fallback to the value of ++ * request_alignment. ++ */ ++ ++ if (!bs->bl.request_alignment) { ++ int i; + size_t align; +- buf = qemu_memalign(max_align, 2 * max_align); +- for (align = 512; align <= max_align; align <<= 1) { +- if (raw_is_io_aligned(fd, buf + align, max_align)) { +- s->buf_align = align; ++ buf = qemu_memalign(max_align, max_align); ++ for (i = 0; i < ARRAY_SIZE(alignments); i++) { ++ align = alignments[i]; ++ if (raw_is_io_aligned(fd, buf, align)) { ++ /* Fallback to safe value. */ ++ bs->bl.request_alignment = (align != 1) ? align : max_align; + break; + } + } + qemu_vfree(buf); + } + +- if (!bs->bl.request_alignment) { ++ if (!s->buf_align) { ++ int i; + size_t align; +- buf = qemu_memalign(s->buf_align, max_align); +- for (align = 512; align <= max_align; align <<= 1) { +- if (raw_is_io_aligned(fd, buf, align)) { +- bs->bl.request_alignment = align; ++ buf = qemu_memalign(max_align, 2 * max_align); ++ for (i = 0; i < ARRAY_SIZE(alignments); i++) { ++ align = alignments[i]; ++ if (raw_is_io_aligned(fd, buf + align, max_align)) { ++ /* Fallback to request_aligment. */ ++ s->buf_align = (align != 1) ? align : bs->bl.request_alignment; + break; + } + } +-- +1.8.3.1 + diff --git a/SOURCES/kvm-fw_cfg-Fix-boot-bootsplash-error-checking.patch b/SOURCES/kvm-fw_cfg-Fix-boot-bootsplash-error-checking.patch new file mode 100644 index 0000000..c838f38 --- /dev/null +++ b/SOURCES/kvm-fw_cfg-Fix-boot-bootsplash-error-checking.patch @@ -0,0 +1,122 @@ +From f798645d16957453ee49a5a2945ed80eeb87cd15 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Mon, 7 Oct 2019 07:35:07 +0100 +Subject: [PATCH 14/22] fw_cfg: Fix -boot bootsplash error checking +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Markus Armbruster +Message-id: <20191007073509.5887-3-armbru@redhat.com> +Patchwork-id: 90980 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH v2 2/4] fw_cfg: Fix -boot bootsplash error checking +Bugzilla: 1607367 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Laszlo Ersek + +From: Li Qiang + +fw_cfg_bootsplash() gets option parameter "splash-time" +with qemu_opt_get(), then converts it to an integer by hand. +It neglects to check that conversion for errors. This is +needlessly complicated and error-prone. But as "splash-time +not specified" is not the same as "splash-time=T" for any T, +we need use qemu_opt_get() to check if splash time exists. +This patch also make the qemu exit when finding or loading +splash file failed. + +Signed-off-by: Li Qiang +Reviewed-by: Markus Armbruster +Reviewed-by: Gerd Hoffmann +Reviewed-by: Philippe Mathieu-Daudé +Message-Id: <1542777026-2788-2-git-send-email-liq3ea@gmail.com> +Signed-off-by: Philippe Mathieu-Daudé +(cherry picked from commit 6912bb0b3d3b140c70d8cdfd2dff77f9890d7f12) +Signed-off-by: Danilo C. L. de Paula +--- + hw/nvram/fw_cfg.c | 35 +++++++++++++---------------------- + vl.c | 2 +- + 2 files changed, 14 insertions(+), 23 deletions(-) + +diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c +index d35ac7b..d7185ea 100644 +--- a/hw/nvram/fw_cfg.c ++++ b/hw/nvram/fw_cfg.c +@@ -117,47 +117,38 @@ error: + + static void fw_cfg_bootsplash(FWCfgState *s) + { +- int boot_splash_time = -1; + const char *boot_splash_filename = NULL; +- char *p; ++ const char *boot_splash_time = NULL; + char *filename, *file_data; + gsize file_size; + int file_type; +- const char *temp; + + /* get user configuration */ + QemuOptsList *plist = qemu_find_opts("boot-opts"); + QemuOpts *opts = QTAILQ_FIRST(&plist->head); +- if (opts != NULL) { +- temp = qemu_opt_get(opts, "splash"); +- if (temp != NULL) { +- boot_splash_filename = temp; +- } +- temp = qemu_opt_get(opts, "splash-time"); +- if (temp != NULL) { +- p = (char *)temp; +- boot_splash_time = strtol(p, &p, 10); +- } +- } ++ boot_splash_filename = qemu_opt_get(opts, "splash"); ++ boot_splash_time = qemu_opt_get(opts, "splash-time"); + + /* insert splash time if user configurated */ +- if (boot_splash_time >= 0) { ++ if (boot_splash_time) { ++ int64_t bst_val = qemu_opt_get_number(opts, "splash-time", -1); + /* validate the input */ +- if (boot_splash_time > 0xffff) { +- error_report("splash time is big than 65535, force it to 65535."); +- boot_splash_time = 0xffff; ++ if (bst_val < 0 || bst_val > 0xffff) { ++ error_report("splash-time is invalid," ++ "it should be a value between 0 and 65535"); ++ exit(1); + } + /* use little endian format */ +- qemu_extra_params_fw[0] = (uint8_t)(boot_splash_time & 0xff); +- qemu_extra_params_fw[1] = (uint8_t)((boot_splash_time >> 8) & 0xff); ++ qemu_extra_params_fw[0] = (uint8_t)(bst_val & 0xff); ++ qemu_extra_params_fw[1] = (uint8_t)((bst_val >> 8) & 0xff); + fw_cfg_add_file(s, "etc/boot-menu-wait", qemu_extra_params_fw, 2); + } + + /* insert splash file if user configurated */ +- if (boot_splash_filename != NULL) { ++ if (boot_splash_filename) { + filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, boot_splash_filename); + if (filename == NULL) { +- error_report("failed to find file '%s'.", boot_splash_filename); ++ error_report("failed to find file '%s'", boot_splash_filename); + return; + } + +diff --git a/vl.c b/vl.c +index c778594..e2212f5 100644 +--- a/vl.c ++++ b/vl.c +@@ -364,7 +364,7 @@ static QemuOptsList qemu_boot_opts = { + .type = QEMU_OPT_STRING, + }, { + .name = "splash-time", +- .type = QEMU_OPT_STRING, ++ .type = QEMU_OPT_NUMBER, + }, { + .name = "reboot-timeout", + .type = QEMU_OPT_STRING, +-- +1.8.3.1 + diff --git a/SOURCES/kvm-fw_cfg-Fix-boot-reboot-timeout-error-checking.patch b/SOURCES/kvm-fw_cfg-Fix-boot-reboot-timeout-error-checking.patch new file mode 100644 index 0000000..188ceb4 --- /dev/null +++ b/SOURCES/kvm-fw_cfg-Fix-boot-reboot-timeout-error-checking.patch @@ -0,0 +1,99 @@ +From 07c499baed0c800e43cd6ec867fc465dea43567d Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Mon, 7 Oct 2019 07:35:08 +0100 +Subject: [PATCH 15/22] fw_cfg: Fix -boot reboot-timeout error checking +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Markus Armbruster +Message-id: <20191007073509.5887-4-armbru@redhat.com> +Patchwork-id: 90979 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH v2 3/4] fw_cfg: Fix -boot reboot-timeout error checking +Bugzilla: 1607367 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Laszlo Ersek + +From: Li Qiang + +fw_cfg_reboot() gets option parameter "reboot-timeout" with +qemu_opt_get(), then converts it to an integer by hand. It neglects to +check that conversion for errors, and fails to reject negative values. +Positive values above the limit get reported and replaced by the limit. +This patch checks for conversion errors properly, and reject all values +outside 0...0xffff. + +Signed-off-by: Li Qiang +Reviewed-by: Markus Armbruster +Reviewed-by: Gerd Hoffmann +Reviewed-by: Philippe Mathieu-Daudé +Message-Id: <1542777026-2788-3-git-send-email-liq3ea@gmail.com> +Signed-off-by: Philippe Mathieu-Daudé +(cherry picked from commit ee5d0f89de3e53cdb0dcf51acc1502b310ed3bd2) +Signed-off-by: Danilo C. L. de Paula +--- + hw/nvram/fw_cfg.c | 27 +++++++++++++-------------- + vl.c | 2 +- + 2 files changed, 14 insertions(+), 15 deletions(-) + +diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c +index d7185ea..02ab458 100644 +--- a/hw/nvram/fw_cfg.c ++++ b/hw/nvram/fw_cfg.c +@@ -176,26 +176,25 @@ static void fw_cfg_bootsplash(FWCfgState *s) + + static void fw_cfg_reboot(FWCfgState *s) + { +- int reboot_timeout = -1; +- char *p; +- const char *temp; ++ const char *reboot_timeout = NULL; ++ int64_t rt_val = -1; + + /* get user configuration */ + QemuOptsList *plist = qemu_find_opts("boot-opts"); + QemuOpts *opts = QTAILQ_FIRST(&plist->head); +- if (opts != NULL) { +- temp = qemu_opt_get(opts, "reboot-timeout"); +- if (temp != NULL) { +- p = (char *)temp; +- reboot_timeout = strtol(p, &p, 10); ++ reboot_timeout = qemu_opt_get(opts, "reboot-timeout"); ++ ++ if (reboot_timeout) { ++ rt_val = qemu_opt_get_number(opts, "reboot-timeout", -1); ++ /* validate the input */ ++ if (rt_val < 0 || rt_val > 0xffff) { ++ error_report("reboot timeout is invalid," ++ "it should be a value between 0 and 65535"); ++ exit(1); + } + } +- /* validate the input */ +- if (reboot_timeout > 0xffff) { +- error_report("reboot timeout is larger than 65535, force it to 65535."); +- reboot_timeout = 0xffff; +- } +- fw_cfg_add_file(s, "etc/boot-fail-wait", g_memdup(&reboot_timeout, 4), 4); ++ ++ fw_cfg_add_file(s, "etc/boot-fail-wait", g_memdup(&rt_val, 4), 4); + } + + static void fw_cfg_write(FWCfgState *s, uint8_t value) +diff --git a/vl.c b/vl.c +index e2212f5..3cee95f 100644 +--- a/vl.c ++++ b/vl.c +@@ -367,7 +367,7 @@ static QemuOptsList qemu_boot_opts = { + .type = QEMU_OPT_NUMBER, + }, { + .name = "reboot-timeout", +- .type = QEMU_OPT_STRING, ++ .type = QEMU_OPT_NUMBER, + }, { + .name = "strict", + .type = QEMU_OPT_BOOL, +-- +1.8.3.1 + diff --git a/SOURCES/kvm-fw_cfg-Improve-error-message-when-can-t-load-splash-.patch b/SOURCES/kvm-fw_cfg-Improve-error-message-when-can-t-load-splash-.patch new file mode 100644 index 0000000..f9ca4b2 --- /dev/null +++ b/SOURCES/kvm-fw_cfg-Improve-error-message-when-can-t-load-splash-.patch @@ -0,0 +1,62 @@ +From f11136998ed22e121b0a9df26f83e252bd5918fa Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Mon, 7 Oct 2019 07:35:06 +0100 +Subject: [PATCH 13/22] fw_cfg: Improve error message when can't load splash + file +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Markus Armbruster +Message-id: <20191007073509.5887-2-armbru@redhat.com> +Patchwork-id: 90978 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH v2 1/4] fw_cfg: Improve error message when can't load splash file +Bugzilla: 1607367 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Laszlo Ersek + +From: Li Qiang + +read_splashfile() reports "failed to read splash file" without +further details. Get the details from g_file_get_contents(), and +include them in the error message. Also remove unnecessary 'res' +variable. + +Signed-off-by: Li Qiang +Reviewed-by: Markus Armbruster +Reviewed-by: Philippe Mathieu-Daudé +Message-Id: <1541052148-28752-1-git-send-email-liq3ea@gmail.com> +Signed-off-by: Philippe Mathieu-Daudé +(cherry picked from commit bed66336771ecdcb788d394bdd081a78b843e509) +Signed-off-by: Danilo C. L. de Paula +--- + hw/nvram/fw_cfg.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c +index 2a0739d..d35ac7b 100644 +--- a/hw/nvram/fw_cfg.c ++++ b/hw/nvram/fw_cfg.c +@@ -68,15 +68,14 @@ static char *read_splashfile(char *filename, gsize *file_sizep, + int *file_typep) + { + GError *err = NULL; +- gboolean res; + gchar *content; + int file_type; + unsigned int filehead; + int bmp_bpp; + +- res = g_file_get_contents(filename, &content, file_sizep, &err); +- if (res == FALSE) { +- error_report("failed to read splash file '%s'", filename); ++ if (!g_file_get_contents(filename, &content, file_sizep, &err)) { ++ error_report("failed to read splash file '%s': %s", ++ filename, err->message); + g_error_free(err); + return NULL; + } +-- +1.8.3.1 + diff --git a/SOURCES/kvm-gluster-Handle-changed-glfs_ftruncate-signature.patch b/SOURCES/kvm-gluster-Handle-changed-glfs_ftruncate-signature.patch new file mode 100644 index 0000000..711e67c --- /dev/null +++ b/SOURCES/kvm-gluster-Handle-changed-glfs_ftruncate-signature.patch @@ -0,0 +1,97 @@ +From a30344defca0e948400587280f67d4e6bcc5834f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Wed, 19 Jun 2019 17:15:07 +0200 +Subject: [PATCH 1/2] gluster: Handle changed glfs_ftruncate signature +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Philippe Mathieu-Daudé +Message-id: <20190619171508.31981-2-philmd@redhat.com> +Patchwork-id: 88737 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 1/2] gluster: Handle changed glfs_ftruncate signature +Bugzilla: 1721983 +RH-Acked-by: Max Reitz +RH-Acked-by: Niels de Vos +RH-Acked-by: Miroslav Rezanina + +From: Prasanna Kumar Kalever + +New versions of Glusters libgfapi.so have an updated glfs_ftruncate() +function that returns additional 'struct stat' structures to enable +advanced caching of attributes. This is useful for file servers, not so +much for QEMU. Nevertheless, the API has changed and needs to be +adopted. + +Signed-off-by: Prasanna Kumar Kalever +Signed-off-by: Niels de Vos +Signed-off-by: Kevin Wolf +(cherry picked from commit e014dbe74e0484188164c61ff6843f8a04a8cb9d) +Signed-off-by: Philippe Mathieu-Daudé +Signed-off-by: Miroslav Rezanina +--- + block/gluster.c | 4 ++++ + configure | 18 ++++++++++++++++++ + 2 files changed, 22 insertions(+) + +diff --git a/block/gluster.c b/block/gluster.c +index 8c13002..e3ffa61 100644 +--- a/block/gluster.c ++++ b/block/gluster.c +@@ -20,6 +20,10 @@ + #include "qemu/option.h" + #include "qemu/cutils.h" + ++#ifdef CONFIG_GLUSTERFS_FTRUNCATE_HAS_STAT ++# define glfs_ftruncate(fd, offset) glfs_ftruncate(fd, offset, NULL, NULL) ++#endif ++ + #define GLUSTER_OPT_FILENAME "filename" + #define GLUSTER_OPT_VOLUME "volume" + #define GLUSTER_OPT_PATH "path" +diff --git a/configure b/configure +index 6d61b14..b3d337b 100755 +--- a/configure ++++ b/configure +@@ -429,6 +429,7 @@ glusterfs_xlator_opt="no" + glusterfs_discard="no" + glusterfs_fallocate="no" + glusterfs_zerofill="no" ++glusterfs_ftruncate_has_stat="no" + gtk="" + gtkabi="" + gtk_gl="no" +@@ -3919,6 +3920,19 @@ if test "$glusterfs" != "no" ; then + glusterfs_fallocate="yes" + glusterfs_zerofill="yes" + fi ++ cat > $TMPC << EOF ++#include ++ ++int ++main(void) ++{ ++ /* new glfs_ftruncate() passes two additional args */ ++ return glfs_ftruncate(NULL, 0, NULL, NULL); ++} ++EOF ++ if compile_prog "$glusterfs_cflags" "$glusterfs_libs" ; then ++ glusterfs_ftruncate_has_stat="yes" ++ fi + else + if test "$glusterfs" = "yes" ; then + feature_not_found "GlusterFS backend support" \ +@@ -6622,6 +6636,10 @@ if test "$glusterfs_zerofill" = "yes" ; then + echo "CONFIG_GLUSTERFS_ZEROFILL=y" >> $config_host_mak + fi + ++if test "$glusterfs_ftruncate_has_stat" = "yes" ; then ++ echo "CONFIG_GLUSTERFS_FTRUNCATE_HAS_STAT=y" >> $config_host_mak ++fi ++ + if test "$libssh2" = "yes" ; then + echo "CONFIG_LIBSSH2=m" >> $config_host_mak + echo "LIBSSH2_CFLAGS=$libssh2_cflags" >> $config_host_mak +-- +1.8.3.1 + diff --git a/SOURCES/kvm-gluster-the-glfs_io_cbk-callback-function-pointer-ad.patch b/SOURCES/kvm-gluster-the-glfs_io_cbk-callback-function-pointer-ad.patch new file mode 100644 index 0000000..c822f7c --- /dev/null +++ b/SOURCES/kvm-gluster-the-glfs_io_cbk-callback-function-pointer-ad.patch @@ -0,0 +1,108 @@ +From 41e53f27ba80b6479c5b7fdb34eb67ceb801c65b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Wed, 19 Jun 2019 17:15:08 +0200 +Subject: [PATCH 2/2] gluster: the glfs_io_cbk callback function pointer adds + pre/post stat args +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Philippe Mathieu-Daudé +Message-id: <20190619171508.31981-3-philmd@redhat.com> +Patchwork-id: 88738 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 2/2] gluster: the glfs_io_cbk callback function pointer adds pre/post stat args +Bugzilla: 1721983 +RH-Acked-by: Max Reitz +RH-Acked-by: Niels de Vos +RH-Acked-by: Miroslav Rezanina + +From: Niels de Vos + +The glfs_*_async() functions do a callback once finished. This callback +has changed its arguments, pre- and post-stat structures have been +added. This makes it possible to improve caching, which is useful for +Samba and NFS-Ganesha, but not so much for QEMU. Gluster 6 is the first +release that includes these new arguments. + +With an additional detection in ./configure, the new arguments can +conditionally get included in the glfs_io_cbk handler. + +Signed-off-by: Niels de Vos +Signed-off-by: Kevin Wolf +(cherry picked from commit 0e3b891fefacc0e49f3c8ffa3a753b69eb7214d2) +Signed-off-by: Philippe Mathieu-Daudé +Signed-off-by: Miroslav Rezanina +--- + block/gluster.c | 6 +++++- + configure | 24 ++++++++++++++++++++++++ + 2 files changed, 29 insertions(+), 1 deletion(-) + +diff --git a/block/gluster.c b/block/gluster.c +index e3ffa61..a6ac2b1 100644 +--- a/block/gluster.c ++++ b/block/gluster.c +@@ -729,7 +729,11 @@ static struct glfs *qemu_gluster_init(BlockdevOptionsGluster *gconf, + /* + * AIO callback routine called from GlusterFS thread. + */ +-static void gluster_finish_aiocb(struct glfs_fd *fd, ssize_t ret, void *arg) ++static void gluster_finish_aiocb(struct glfs_fd *fd, ssize_t ret, ++#ifdef CONFIG_GLUSTERFS_IOCB_HAS_STAT ++ struct glfs_stat *pre, struct glfs_stat *post, ++#endif ++ void *arg) + { + GlusterAIOCB *acb = (GlusterAIOCB *)arg; + +diff --git a/configure b/configure +index b3d337b..c9a1034 100755 +--- a/configure ++++ b/configure +@@ -430,6 +430,7 @@ glusterfs_discard="no" + glusterfs_fallocate="no" + glusterfs_zerofill="no" + glusterfs_ftruncate_has_stat="no" ++glusterfs_iocb_has_stat="no" + gtk="" + gtkabi="" + gtk_gl="no" +@@ -3933,6 +3934,25 @@ EOF + if compile_prog "$glusterfs_cflags" "$glusterfs_libs" ; then + glusterfs_ftruncate_has_stat="yes" + fi ++ cat > $TMPC << EOF ++#include ++ ++/* new glfs_io_cbk() passes two additional glfs_stat structs */ ++static void ++glusterfs_iocb(glfs_fd_t *fd, ssize_t ret, struct glfs_stat *prestat, struct glfs_stat *poststat, void *data) ++{} ++ ++int ++main(void) ++{ ++ glfs_io_cbk iocb = &glusterfs_iocb; ++ iocb(NULL, 0 , NULL, NULL, NULL); ++ return 0; ++} ++EOF ++ if compile_prog "$glusterfs_cflags" "$glusterfs_libs" ; then ++ glusterfs_iocb_has_stat="yes" ++ fi + else + if test "$glusterfs" = "yes" ; then + feature_not_found "GlusterFS backend support" \ +@@ -6640,6 +6660,10 @@ if test "$glusterfs_ftruncate_has_stat" = "yes" ; then + echo "CONFIG_GLUSTERFS_FTRUNCATE_HAS_STAT=y" >> $config_host_mak + fi + ++if test "$glusterfs_iocb_has_stat" = "yes" ; then ++ echo "CONFIG_GLUSTERFS_IOCB_HAS_STAT=y" >> $config_host_mak ++fi ++ + if test "$libssh2" = "yes" ; then + echo "CONFIG_LIBSSH2=m" >> $config_host_mak + echo "LIBSSH2_CFLAGS=$libssh2_cflags" >> $config_host_mak +-- +1.8.3.1 + diff --git a/SOURCES/kvm-hw-block-pflash_cfi01-Add-missing-DeviceReset-handle.patch b/SOURCES/kvm-hw-block-pflash_cfi01-Add-missing-DeviceReset-handle.patch new file mode 100644 index 0000000..de0b450 --- /dev/null +++ b/SOURCES/kvm-hw-block-pflash_cfi01-Add-missing-DeviceReset-handle.patch @@ -0,0 +1,86 @@ +From 707a777c2992e840d2c3dd4e1fbed5b0d6c682ec Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Tue, 23 Jul 2019 11:51:05 +0100 +Subject: [PATCH 01/14] hw/block/pflash_cfi01: Add missing DeviceReset() + handler +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Philippe Mathieu-Daudé +Message-id: <20190723115105.31305-2-philmd@redhat.com> +Patchwork-id: 89645 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 1/1] hw/block/pflash_cfi01: Add missing DeviceReset() handler +Bugzilla: 1707192 +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: John Snow + +To avoid incoherent states when the machine resets (see bug report +below), add the device reset callback. + +A "system reset" sets the device state machine in READ_ARRAY mode +and, after some delay, set the SR.7 READY bit. + +Since we do not model timings, we set the SR.7 bit directly. + +Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1678713 +Reported-by: Laszlo Ersek +Reviewed-by: John Snow +Reviewed-by: Alistair Francis +Reviewed-by: Laszlo Ersek +Tested-by: Laszlo Ersek +[Laszlo Ersek: Regression tested EDK2 OVMF IA32X64, ArmVirtQemu Aarch64 + https://lists.gnu.org/archive/html/qemu-devel/2019-07/msg04373.html] +Message-Id: <20190718104837.13905-2-philmd@redhat.com> +Signed-off-by: Philippe Mathieu-Daudé +(cherry picked from commit 3a283507c03474d285196620fca506bd1a89b198) +[PMD: upstream commit e7b6274197c changed PFLASH_CFI01 <- CFI_PFLASH01, + and upstream commit 1643406520f changed PFlashCFI01 <- pflash_t] +Signed-off-by: Philippe Mathieu-Daudé + +Signed-off-by: Danilo C. L. de Paula +--- + hw/block/pflash_cfi01.c | 19 +++++++++++++++++++ + 1 file changed, 19 insertions(+) + +diff --git a/hw/block/pflash_cfi01.c b/hw/block/pflash_cfi01.c +index 2e82840..1be351e 100644 +--- a/hw/block/pflash_cfi01.c ++++ b/hw/block/pflash_cfi01.c +@@ -876,6 +876,24 @@ static void pflash_cfi01_realize(DeviceState *dev, Error **errp) + pfl->cfi_table[0x3f] = 0x01; /* Number of protection fields */ + } + ++static void pflash_cfi01_system_reset(DeviceState *dev) ++{ ++ pflash_t *pfl = CFI_PFLASH01(dev); ++ ++ /* ++ * The command 0x00 is not assigned by the CFI open standard, ++ * but QEMU historically uses it for the READ_ARRAY command (0xff). ++ */ ++ pfl->cmd = 0x00; ++ pfl->wcycle = 0; ++ memory_region_rom_device_set_romd(&pfl->mem, true); ++ /* ++ * The WSM ready timer occurs at most 150ns after system reset. ++ * This model deliberately ignores this delay. ++ */ ++ pfl->status = 0x80; ++} ++ + static Property pflash_cfi01_properties[] = { + DEFINE_PROP_DRIVE("drive", struct pflash_t, blk), + /* num-blocks is the number of blocks actually visible to the guest, +@@ -920,6 +938,7 @@ static void pflash_cfi01_class_init(ObjectClass *klass, void *data) + { + DeviceClass *dc = DEVICE_CLASS(klass); + ++ dc->reset = pflash_cfi01_system_reset; + dc->realize = pflash_cfi01_realize; + dc->props = pflash_cfi01_properties; + dc->vmsd = &vmstate_pflash; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-hw-nvram-fw_cfg-Store-reboot-timeout-as-little-endia.patch b/SOURCES/kvm-hw-nvram-fw_cfg-Store-reboot-timeout-as-little-endia.patch new file mode 100644 index 0000000..058f595 --- /dev/null +++ b/SOURCES/kvm-hw-nvram-fw_cfg-Store-reboot-timeout-as-little-endia.patch @@ -0,0 +1,80 @@ +From 5bb1365ea92b83615937e3082a9c250728384989 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Mon, 7 Oct 2019 07:35:09 +0100 +Subject: [PATCH 16/22] hw/nvram/fw_cfg: Store 'reboot-timeout' as little + endian +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Markus Armbruster +Message-id: <20191007073509.5887-5-armbru@redhat.com> +Patchwork-id: 90976 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH v2 4/4] hw/nvram/fw_cfg: Store 'reboot-timeout' as little endian +Bugzilla: 1607367 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Laszlo Ersek + +From: Li Qiang + +The current codebase is not specific about the endianess of the +fw_cfg 'file' entry 'reboot-timeout'. + +Per docs/specs/fw_cfg.txt: + + === All Other Data Items === + + Please consult the QEMU source for the most up-to-date + and authoritative list of selector keys and their respective + items' purpose, format and writeability. + +Checking the git history, this code was introduced in commit +ac05f3492421, very similar to commit 3d3b8303c6f8 for the +'boot-menu-wait' entry, which explicitely use little-endian. + +OVMF consumes 'boot-menu-wait' as little-endian, however it does +not consume 'reboot-timeout'. + +Regarding the git history and OVMF use, we choose to explicit +'reboot-timeout' endianess as little-endian. + +Signed-off-by: Li Qiang +Tested-by: Thomas Huth +Reviewed-by: Philippe Mathieu-Daudé +Tested-by: Philippe Mathieu-Daudé +Message-Id: <20190424140643.62457-4-liq3ea@163.com> +[PMD: Reword commit description based on review comments] +Signed-off-by: Philippe Mathieu-Daudé +(cherry picked from commit 04da973501b591525ce68c2925c61c8886badd4d) + +Signed-off-by: Danilo C. L. de Paula +--- + hw/nvram/fw_cfg.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c +index 02ab458..954de33 100644 +--- a/hw/nvram/fw_cfg.c ++++ b/hw/nvram/fw_cfg.c +@@ -178,6 +178,7 @@ static void fw_cfg_reboot(FWCfgState *s) + { + const char *reboot_timeout = NULL; + int64_t rt_val = -1; ++ uint32_t rt_le32; + + /* get user configuration */ + QemuOptsList *plist = qemu_find_opts("boot-opts"); +@@ -194,7 +195,8 @@ static void fw_cfg_reboot(FWCfgState *s) + } + } + +- fw_cfg_add_file(s, "etc/boot-fail-wait", g_memdup(&rt_val, 4), 4); ++ rt_le32 = cpu_to_le32(rt_val); ++ fw_cfg_add_file(s, "etc/boot-fail-wait", g_memdup(&rt_le32, 4), 4); + } + + static void fw_cfg_write(FWCfgState *s, uint8_t value) +-- +1.8.3.1 + diff --git a/SOURCES/kvm-i386-Add-new-model-of-Cascadelake-Server.patch b/SOURCES/kvm-i386-Add-new-model-of-Cascadelake-Server.patch new file mode 100644 index 0000000..8b96ddd --- /dev/null +++ b/SOURCES/kvm-i386-Add-new-model-of-Cascadelake-Server.patch @@ -0,0 +1,107 @@ +From 2d44f02611fcb0eddad08d2c5d4361d568fcfd67 Mon Sep 17 00:00:00 2001 +From: "plai@redhat.com" +Date: Mon, 1 Jul 2019 16:17:30 +0100 +Subject: [PATCH 01/39] i386: Add new model of Cascadelake-Server + +RH-Author: plai@redhat.com +Message-id: <1561997854-9646-2-git-send-email-plai@redhat.com> +Patchwork-id: 89331 +O-Subject: [RHEL8.1 qemu-kvm PATCH v6 1/5] i386: Add new model of Cascadelake-Server +Bugzilla: 1629906 +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Bandan Das + +From: Tao Xu + +New CPU models mostly inherit features from ancestor Skylake-Server, +while addin new features: AVX512_VNNI, Intel PT. +SSBD support for speculative execution +side channel mitigations. + +Note: + +On Cascadelake, some capabilities (RDCL_NO, IBRS_ALL, RSBA, +SKIP_L1DFL_VMENTRY and SSB_NO) are enumerated by MSR. +These features rely on MSR based feature support patch. +Will be added later after that patch's in. +http://lists.nongnu.org/archive/html/qemu-devel/2018-09/msg00074.html + +Signed-off-by: Tao Xu +Message-Id: <20180919031122.28487-2-tao3.xu@intel.com> +Signed-off-by: Eduardo Habkost +(cherry picked from commit c7a88b52f62b30c04158eeb07f73e3f72221b6a8) +Signed-off-by: Paul Lai +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 54 insertions(+) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 5c10093..9ba5288 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -2483,6 +2483,60 @@ static X86CPUDefinition builtin_x86_defs[] = { + .model_id = "Intel Xeon Processor (Skylake, IBRS)", + }, + { ++ .name = "Cascadelake-Server", ++ .level = 0xd, ++ .vendor = CPUID_VENDOR_INTEL, ++ .family = 6, ++ .model = 85, ++ .stepping = 5, ++ .features[FEAT_1_EDX] = ++ CPUID_VME | CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | ++ CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | ++ CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 | ++ CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE | ++ CPUID_DE | CPUID_FP87, ++ .features[FEAT_1_ECX] = ++ CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES | ++ CPUID_EXT_POPCNT | CPUID_EXT_X2APIC | CPUID_EXT_SSE42 | ++ CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | ++ CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3 | ++ CPUID_EXT_TSC_DEADLINE_TIMER | CPUID_EXT_FMA | CPUID_EXT_MOVBE | ++ CPUID_EXT_PCID | CPUID_EXT_F16C | CPUID_EXT_RDRAND, ++ .features[FEAT_8000_0001_EDX] = ++ CPUID_EXT2_LM | CPUID_EXT2_PDPE1GB | CPUID_EXT2_RDTSCP | ++ CPUID_EXT2_NX | CPUID_EXT2_SYSCALL, ++ .features[FEAT_8000_0001_ECX] = ++ CPUID_EXT3_ABM | CPUID_EXT3_LAHF_LM | CPUID_EXT3_3DNOWPREFETCH, ++ .features[FEAT_7_0_EBX] = ++ CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 | ++ CPUID_7_0_EBX_HLE | CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP | ++ CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_INVPCID | ++ CPUID_7_0_EBX_RTM | CPUID_7_0_EBX_RDSEED | CPUID_7_0_EBX_ADX | ++ CPUID_7_0_EBX_SMAP | CPUID_7_0_EBX_MPX | CPUID_7_0_EBX_CLWB | ++ CPUID_7_0_EBX_AVX512F | CPUID_7_0_EBX_AVX512DQ | ++ CPUID_7_0_EBX_AVX512BW | CPUID_7_0_EBX_AVX512CD | ++ CPUID_7_0_EBX_AVX512VL | CPUID_7_0_EBX_CLFLUSHOPT | ++ CPUID_7_0_EBX_INTEL_PT, ++ .features[FEAT_7_0_ECX] = ++ CPUID_7_0_ECX_PKU | CPUID_7_0_ECX_OSPKE | ++ CPUID_7_0_ECX_AVX512VNNI, ++ .features[FEAT_7_0_EDX] = ++ CPUID_7_0_EDX_SPEC_CTRL | CPUID_7_0_EDX_SPEC_CTRL_SSBD, ++ /* Missing: XSAVES (not supported by some Linux versions, ++ * including v4.1 to v4.12). ++ * KVM doesn't yet expose any XSAVES state save component, ++ * and the only one defined in Skylake (processor tracing) ++ * probably will block migration anyway. ++ */ ++ .features[FEAT_XSAVE] = ++ CPUID_XSAVE_XSAVEOPT | CPUID_XSAVE_XSAVEC | ++ CPUID_XSAVE_XGETBV1, ++ .features[FEAT_6_EAX] = ++ CPUID_6_EAX_ARAT, ++ .xlevel = 0x80000008, ++ .model_id = "Intel Xeon Processor (Cascadelake)", ++ }, ++ { + .name = "Icelake-Client", + .level = 0xd, + .vendor = CPUID_VENDOR_INTEL, +-- +1.8.3.1 + diff --git a/SOURCES/kvm-i386-Add-x-force-features-option-for-testing.patch b/SOURCES/kvm-i386-Add-x-force-features-option-for-testing.patch new file mode 100644 index 0000000..3281581 --- /dev/null +++ b/SOURCES/kvm-i386-Add-x-force-features-option-for-testing.patch @@ -0,0 +1,80 @@ +From d5526e43ccf3532aa3a0f592e6df5740983a94e2 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Fri, 22 Nov 2019 11:53:35 +0000 +Subject: [PATCH 02/16] i386: Add x-force-features option for testing +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Paolo Bonzini +Message-id: <20191122115348.25000-3-pbonzini@redhat.com> +Patchwork-id: 92602 +O-Subject: [RHEL8.2/rhel qemu-kvm PATCH 02/15] i386: Add x-force-features option for testing +Bugzilla: 1689270 +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Maxim Levitsky + +From: Eduardo Habkost + +Add a new option that can be used to disable feature flag +filtering. This will allow CPU model compatibility test cases to +work without host hardware dependencies. + +Signed-off-by: Eduardo Habkost +Message-Id: <20190628002844.24894-3-ehabkost@redhat.com> +Reviewed-by: Daniel P. Berrangé +Signed-off-by: Eduardo Habkost +(cherry picked from commit dac1deae658539e39966e12b12378a28e3dc8441) +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 8 ++++++-- + target/i386/cpu.h | 6 ++++++ + 2 files changed, 12 insertions(+), 2 deletions(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index c69116c..8c1338f 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -5019,8 +5019,11 @@ static int x86_cpu_filter_features(X86CPU *cpu) + uint32_t host_feat = + x86_cpu_get_supported_feature_word(w, false); + uint32_t requested_features = env->features[w]; +- env->features[w] &= host_feat; +- cpu->filtered_features[w] = requested_features & ~env->features[w]; ++ uint32_t available_features = requested_features & host_feat; ++ if (!cpu->force_features) { ++ env->features[w] = available_features; ++ } ++ cpu->filtered_features[w] = requested_features & ~available_features; + if (cpu->filtered_features[w]) { + rv = 1; + } +@@ -5680,6 +5683,7 @@ static Property x86_cpu_properties[] = { + DEFINE_PROP_BOOL("hv-frequencies", X86CPU, hyperv_frequencies, false), + DEFINE_PROP_BOOL("check", X86CPU, check_cpuid, true), + DEFINE_PROP_BOOL("enforce", X86CPU, enforce_cpuid, false), ++ DEFINE_PROP_BOOL("x-force-features", X86CPU, force_features, false), + DEFINE_PROP_BOOL("kvm", X86CPU, expose_kvm, true), + DEFINE_PROP_UINT32("phys-bits", X86CPU, phys_bits, 0), + DEFINE_PROP_BOOL("host-phys-bits", X86CPU, host_phys_bits, false), +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index add8b60..1ad54bd 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -1394,6 +1394,12 @@ struct X86CPU { + bool hyperv_frequencies; + bool check_cpuid; + bool enforce_cpuid; ++ /* ++ * Force features to be enabled even if the host doesn't support them. ++ * This is dangerous and should be done only for testing CPUID ++ * compatibility. ++ */ ++ bool force_features; + bool expose_kvm; + bool expose_tcg; + bool migratable; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-i386-Disable-OSPKE-on-CPU-model-definitions-NEW.patch b/SOURCES/kvm-i386-Disable-OSPKE-on-CPU-model-definitions-NEW.patch new file mode 100644 index 0000000..c78b32a --- /dev/null +++ b/SOURCES/kvm-i386-Disable-OSPKE-on-CPU-model-definitions-NEW.patch @@ -0,0 +1,72 @@ +From 04f34e7c0b0fada186ca7012f5f4168f46483c5f Mon Sep 17 00:00:00 2001 +From: "plai@redhat.com" +Date: Mon, 1 Jul 2019 16:17:34 +0100 +Subject: [PATCH 05/39] i386: Disable OSPKE on CPU model definitions + +RH-Author: plai@redhat.com +Message-id: <1561997854-9646-6-git-send-email-plai@redhat.com> +Patchwork-id: 89334 +O-Subject: [RHEL8.1 qemu-kvm PATCH v6 5/5] i386: Disable OSPKE on CPU model definitions +Bugzilla: 1629906 +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Bandan Das + +From: Eduardo Habkost + +Currently, the Cascadelake-Server, Icelake-Client, and +Icelake-Server are always generating the following warning: + + qemu-system-x86_64: warning: \ + host doesn't support requested feature: CPUID.07H:ECX [bit 4] + +This happens because OSPKE was never returned by +GET_SUPPORTED_CPUID or x86_cpu_get_supported_feature_word(). +OSPKE is a runtime flag automatically set by the KVM module or by +TCG code, was always cleared by x86_cpu_filter_features(), and +was not supposed to appear on the CPU model table. + +Remove the OSPKE flag from the CPU model table entries, to avoid +the bogus warning and avoid returning invalid feature data on +query-cpu-* QMP commands. As OSPKE was always cleared by +x86_cpu_filter_features(), this won't have any guest-visible +impact. + +Include a test case that should detect the problem if we introduce +a similar bug again. + +Fixes: c7a88b52f62b ("i386: Add new model of Cascadelake-Server") +Fixes: 8a11c62da914 ("i386: Add new CPU model Icelake-{Server,Client}") +Cc: Tao Xu +Cc: Robert Hoo +Signed-off-by: Eduardo Habkost +Message-Id: <20190319200515.14999-1-ehabkost@redhat.com> +Signed-off-by: Eduardo Habkost +(cherry picked from commit bb4928c7cafe50ab2137a0034e350ef1bfa044d9) +Signed-off-by: Paul Lai +Signed-off-by: Danilo C. L. de Paula + +Conflicts: + target/i386/cpu.c + +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 2538d82..af62281 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -2517,7 +2517,7 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_7_0_EBX_AVX512BW | CPUID_7_0_EBX_AVX512CD | + CPUID_7_0_EBX_AVX512VL | CPUID_7_0_EBX_CLFLUSHOPT, + .features[FEAT_7_0_ECX] = +- CPUID_7_0_ECX_PKU | CPUID_7_0_ECX_OSPKE | ++ CPUID_7_0_ECX_PKU | + CPUID_7_0_ECX_AVX512VNNI, + .features[FEAT_7_0_EDX] = + CPUID_7_0_EDX_SPEC_CTRL | CPUID_7_0_EDX_SPEC_CTRL_SSBD, +-- +1.8.3.1 + diff --git a/SOURCES/kvm-i386-Don-t-print-warning-if-phys-bits-was-set-automa.patch b/SOURCES/kvm-i386-Don-t-print-warning-if-phys-bits-was-set-automa.patch new file mode 100644 index 0000000..d64dbc9 --- /dev/null +++ b/SOURCES/kvm-i386-Don-t-print-warning-if-phys-bits-was-set-automa.patch @@ -0,0 +1,79 @@ +From 7e78c8e8b5a9cab9ef4604dc29eab4b4323e9b9b Mon Sep 17 00:00:00 2001 +From: Eduardo Habkost +Date: Tue, 13 Aug 2019 01:53:55 +0100 +Subject: [PATCH 01/21] i386: Don't print warning if phys-bits was set + automatically + +RH-Author: Eduardo Habkost +Message-id: <20190813015355.17556-1-ehabkost@redhat.com> +Patchwork-id: 89946 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH] i386: Don't print warning if phys-bits was set automatically +Bugzilla: 1719127 +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Igor Mammedov +RH-Acked-by: John Snow + +BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1719127 +BRANCH: rhel-8.1.0 +UPSTREAM: fea306520ea4b2f189dd23c70a6afd2fc4ffafdc +BREW: https://brewweb.engineering.redhat.com/brew/taskinfo?taskID=23026463 + +If cpu->host_phys_bits_limit is set, QEMU will make +cpu->phys_bits be lower than host_phys_bits on some cases. This +triggers a warning that was supposed to be printed only if +phys-bits was explicitly set in the command-line. + +Reorder the code so the value of cpu->phys_bits is validated +before the cpu->host_phys_bits handling. This will avoid +unexpected warnings when cpu->host_phys_bits_limit is set. + +Signed-off-by: Eduardo Habkost +Message-Id: <20190611205420.20286-1-ehabkost@redhat.com> +Reviewed-by: Dr. David Alan Gilbert +Signed-off-by: Eduardo Habkost +(cherry picked from commit fea306520ea4b2f189dd23c70a6afd2fc4ffafdc) +Signed-off-by: Eduardo Habkost +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 18 +++++++++--------- + 1 file changed, 9 insertions(+), 9 deletions(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index c8f50a7..c69116c 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -5116,15 +5116,6 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp) + uint32_t host_phys_bits = x86_host_phys_bits(); + static bool warned; + +- if (cpu->host_phys_bits) { +- /* The user asked for us to use the host physical bits */ +- cpu->phys_bits = host_phys_bits; +- if (cpu->host_phys_bits_limit && +- cpu->phys_bits > cpu->host_phys_bits_limit) { +- cpu->phys_bits = cpu->host_phys_bits_limit; +- } +- } +- + /* Print a warning if the user set it to a value that's not the + * host value. + */ +@@ -5136,6 +5127,15 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp) + warned = true; + } + ++ if (cpu->host_phys_bits) { ++ /* The user asked for us to use the host physical bits */ ++ cpu->phys_bits = host_phys_bits; ++ if (cpu->host_phys_bits_limit && ++ cpu->phys_bits > cpu->host_phys_bits_limit) { ++ cpu->phys_bits = cpu->host_phys_bits_limit; ++ } ++ } ++ + if (cpu->phys_bits && + (cpu->phys_bits > TARGET_PHYS_ADDR_SPACE_BITS || + cpu->phys_bits < 32)) { +-- +1.8.3.1 + diff --git a/SOURCES/kvm-i386-Save-EFER-for-32-bit-targets.patch b/SOURCES/kvm-i386-Save-EFER-for-32-bit-targets.patch new file mode 100644 index 0000000..fe1a7b3 --- /dev/null +++ b/SOURCES/kvm-i386-Save-EFER-for-32-bit-targets.patch @@ -0,0 +1,80 @@ +From 1e8e3c4fe380a2a0ed88f7a92f5bcb8600ab1258 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 22 Jul 2019 18:22:03 +0100 +Subject: [PATCH 22/39] i386: Save EFER for 32-bit targets + +RH-Author: Paolo Bonzini +Message-id: <20190722182220.19374-2-pbonzini@redhat.com> +Patchwork-id: 89619 +O-Subject: [RHEL-8.1.0 PATCH qemu-kvm v3 01/18] i386: Save EFER for 32-bit targets +Bugzilla: 1689269 +RH-Acked-by: Peter Xu +RH-Acked-by: Laurent Vivier +RH-Acked-by: Dr. David Alan Gilbert + +From: Pavel Dovgalyuk + +i386 (32 bit) emulation uses EFER in wrmsr and in MMU fault +processing. +But it does not included in VMState, because "efer" field is disabled with + +This patch adds a section for 32-bit targets which saves EFER when +it's value is non-zero. + +Signed-off-by: Pavel Dovgalyuk +Message-Id: <155913371654.8429.1659082639780315242.stgit@pasha-Precision-3630-Tower> +Reviewed-by: Peter Xu +[ehabkost: indentation fix] +Signed-off-by: Eduardo Habkost +(cherry picked from commit 89a44a103315267122119b4311218d00d2561ebe) + +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/machine.c | 24 ++++++++++++++++++++++++ + 1 file changed, 24 insertions(+) + +diff --git a/target/i386/machine.c b/target/i386/machine.c +index 2a85c91..561d4a5 100644 +--- a/target/i386/machine.c ++++ b/target/i386/machine.c +@@ -932,6 +932,27 @@ static const VMStateDescription vmstate_msr_virt_ssbd = { + } + }; + ++#ifndef TARGET_X86_64 ++static bool intel_efer32_needed(void *opaque) ++{ ++ X86CPU *cpu = opaque; ++ CPUX86State *env = &cpu->env; ++ ++ return env->efer != 0; ++} ++ ++static const VMStateDescription vmstate_efer32 = { ++ .name = "cpu/efer32", ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .needed = intel_efer32_needed, ++ .fields = (VMStateField[]) { ++ VMSTATE_UINT64(env.efer, X86CPU), ++ VMSTATE_END_OF_LIST() ++ } ++}; ++#endif ++ + VMStateDescription vmstate_x86_cpu = { + .name = "cpu", + .version_id = 12, +@@ -1056,6 +1077,9 @@ VMStateDescription vmstate_x86_cpu = { + &vmstate_msr_intel_pt, + &vmstate_xsave, + &vmstate_msr_virt_ssbd, ++#ifndef TARGET_X86_64 ++ &vmstate_efer32, ++#endif + NULL + } + }; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-i386-Update-stepping-of-Cascadelake-Server.patch b/SOURCES/kvm-i386-Update-stepping-of-Cascadelake-Server.patch new file mode 100644 index 0000000..328d271 --- /dev/null +++ b/SOURCES/kvm-i386-Update-stepping-of-Cascadelake-Server.patch @@ -0,0 +1,66 @@ +From 839e9376bc82933ccacb26b660f1d3adf62aaf05 Mon Sep 17 00:00:00 2001 +From: "plai@redhat.com" +Date: Mon, 1 Jul 2019 16:17:31 +0100 +Subject: [PATCH 02/39] i386: Update stepping of Cascadelake-Server + +RH-Author: plai@redhat.com +Message-id: <1561997854-9646-3-git-send-email-plai@redhat.com> +Patchwork-id: 89329 +O-Subject: [RHEL8.1 qemu-kvm PATCH v6 2/5] i386: Update stepping of Cascadelake-Server +Bugzilla: 1629906 +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Bandan Das + +From: Tao Xu + +Update the stepping from 5 to 6, in order that +the Cascadelake-Server CPU model can support AVX512VNNI +and MSR based features exposed by ARCH_CAPABILITIES. + +Signed-off-by: Tao Xu +Message-Id: <20181227024304.12182-2-tao3.xu@intel.com> +Signed-off-by: Eduardo Habkost +(cherry picked from commit b0a1980384fc265d91de7e09aa5fe531a69e6288) +Signed-off-by: Paul Lai + +Resolved Conflicts: + hw/i386/pc.c changes to include/hw/i386/pc.h + +Signed-off-by: Danilo C. L. de Paula +--- + include/hw/i386/pc.h | 4 ++++ + target/i386/cpu.c | 2 +- + 2 files changed, 5 insertions(+), 1 deletion(-) + +diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h +index 244d7b5..88ffd40 100644 +--- a/include/hw/i386/pc.h ++++ b/include/hw/i386/pc.h +@@ -318,6 +318,10 @@ bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *); + .driver = "Skylake-Server" "-" TYPE_X86_CPU,\ + .property = "clflushopt",\ + .value = "off",\ ++ },{\ ++ .driver = "Cascadelake-Server" "-" TYPE_X86_CPU,\ ++ .property = "stepping",\ ++ .value = "5",\ + }, + + #define PC_COMPAT_2_10 \ +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 9ba5288..c4b31eb 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -2488,7 +2488,7 @@ static X86CPUDefinition builtin_x86_defs[] = { + .vendor = CPUID_VENDOR_INTEL, + .family = 6, + .model = 85, +- .stepping = 5, ++ .stepping = 6, + .features[FEAT_1_EDX] = + CPUID_VME | CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | + CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | +-- +1.8.3.1 + diff --git a/SOURCES/kvm-i386-cpu-make-cpu-host-support-monitor-mwait.patch b/SOURCES/kvm-i386-cpu-make-cpu-host-support-monitor-mwait.patch new file mode 100644 index 0000000..19f6d86 --- /dev/null +++ b/SOURCES/kvm-i386-cpu-make-cpu-host-support-monitor-mwait.patch @@ -0,0 +1,132 @@ +From 91ac1f511b0414292d07688c3cb3012bed6e3649 Mon Sep 17 00:00:00 2001 +From: "Michael S. Tsirkin" +Date: Fri, 22 Jun 2018 22:22:05 +0300 +Subject: [PATCH 09/11] i386/cpu: make -cpu host support monitor/mwait + +When guest CPU PM is enabled, and with -cpu host, expose the host CPU +MWAIT leaf in the CPUID so guest can make good PM decisions. + +Note: the result is 100% CPU utilization reported by host as host +no longer knows that the CPU is halted. + +Signed-off-by: Michael S. Tsirkin +Reviewed-by: Eduardo Habkost +Message-Id: <20180622192148.178309-3-mst@redhat.com> +Signed-off-by: Paolo Bonzini +Signed-off-by: Danilo C. L. de Paula +--- + accel/tcg/user-exec-stub.c | 3 +++ + target/i386/cpu.c | 32 ++++++++++++++++++++++---------- + target/i386/cpu.h | 9 +++++++++ + target/i386/kvm.c | 9 +++++++++ + 4 files changed, 43 insertions(+), 10 deletions(-) + +diff --git a/accel/tcg/user-exec-stub.c b/accel/tcg/user-exec-stub.c +index dbcf1ad..a32b449 100644 +--- a/accel/tcg/user-exec-stub.c ++++ b/accel/tcg/user-exec-stub.c +@@ -2,6 +2,9 @@ + #include "qemu-common.h" + #include "qom/cpu.h" + #include "sysemu/replay.h" ++#include "sysemu/sysemu.h" ++ ++bool enable_cpu_pm = false; + + void cpu_resume(CPUState *cpu) + { +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 307b629..87b0502 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -5662,11 +5662,11 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, + } + break; + case 5: +- /* mwait info: needed for Core compatibility */ +- *eax = 0; /* Smallest monitor-line size in bytes */ +- *ebx = 0; /* Largest monitor-line size in bytes */ +- *ecx = CPUID_MWAIT_EMX | CPUID_MWAIT_IBE; +- *edx = 0; ++ /* MONITOR/MWAIT Leaf */ ++ *eax = cpu->mwait.eax; /* Smallest monitor-line size in bytes */ ++ *ebx = cpu->mwait.ebx; /* Largest monitor-line size in bytes */ ++ *ecx = cpu->mwait.ecx; /* flags */ ++ *edx = cpu->mwait.edx; /* mwait substates */ + break; + case 6: + /* Thermal and Power Leaf */ +@@ -6521,13 +6521,25 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp) + Error *local_err = NULL; + static bool ht_warned; + +- if (xcc->host_cpuid_required && !accel_uses_host_cpuid()) { +- char *name = x86_cpu_class_get_model_name(xcc); +- error_setg(&local_err, "CPU model '%s' requires KVM", name); +- g_free(name); +- goto out; ++ if (xcc->host_cpuid_required) { ++ if (!accel_uses_host_cpuid()) { ++ char *name = x86_cpu_class_get_model_name(xcc); ++ error_setg(&local_err, "CPU model '%s' requires KVM", name); ++ g_free(name); ++ goto out; ++ } ++ ++ if (enable_cpu_pm) { ++ host_cpuid(5, 0, &cpu->mwait.eax, &cpu->mwait.ebx, ++ &cpu->mwait.ecx, &cpu->mwait.edx); ++ env->features[FEAT_1_ECX] |= CPUID_EXT_MONITOR; ++ } + } + ++ /* mwait extended info: needed for Core compatibility */ ++ /* We always wake on interrupt even if host does not have the capability */ ++ cpu->mwait.ecx |= CPUID_MWAIT_EMX | CPUID_MWAIT_IBE; ++ + if (cpu->apic_id == UNASSIGNED_APIC_ID) { + error_setg(errp, "apic-id property was not initialized properly"); + return; +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index d33fa8d..7ab8ee9 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -1564,6 +1564,15 @@ struct X86CPU { + /* if true the CPUID code directly forward host cache leaves to the guest */ + bool cache_info_passthrough; + ++ /* if true the CPUID code directly forwards ++ * host monitor/mwait leaves to the guest */ ++ struct { ++ uint32_t eax; ++ uint32_t ebx; ++ uint32_t ecx; ++ uint32_t edx; ++ } mwait; ++ + /* Features that were filtered out because of missing host capabilities */ + FeatureWordArray filtered_features; + +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index 879c3e0..ffd01f0 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -377,6 +377,15 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function, + if (!kvm_irqchip_in_kernel()) { + ret &= ~CPUID_EXT_X2APIC; + } ++ ++ if (enable_cpu_pm) { ++ int disable_exits = kvm_check_extension(s, ++ KVM_CAP_X86_DISABLE_EXITS); ++ ++ if (disable_exits & KVM_X86_DISABLE_EXITS_MWAIT) { ++ ret |= CPUID_EXT_MONITOR; ++ } ++ } + } else if (function == 6 && reg == R_EAX) { + ret |= CPUID_6_EAX_ARAT; /* safe to allow because of emulated APIC */ + } else if (function == 7 && index == 0 && reg == R_EBX) { +-- +1.8.3.1 + diff --git a/SOURCES/kvm-i386-display-known-CPUID-features-linewrapped-in-alp.patch b/SOURCES/kvm-i386-display-known-CPUID-features-linewrapped-in-alp.patch new file mode 100644 index 0000000..50e63b4 --- /dev/null +++ b/SOURCES/kvm-i386-display-known-CPUID-features-linewrapped-in-alp.patch @@ -0,0 +1,119 @@ +From e7f11d39d1ef78f47ed6d45ecd278d51c502f131 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Fri, 22 Nov 2019 11:53:37 +0000 +Subject: [PATCH 04/16] i386: display known CPUID features linewrapped, in + alphabetical order +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Paolo Bonzini +Message-id: <20191122115348.25000-5-pbonzini@redhat.com> +Patchwork-id: 92605 +O-Subject: [RHEL8.2/rhel qemu-kvm PATCH 04/15] i386: display known CPUID features linewrapped, in alphabetical order +Bugzilla: 1689270 +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Maxim Levitsky + +From: Daniel P. Berrangé + +When using '-cpu help' the list of CPUID features is grouped according +to the internal low level CPUID grouping. The data printed results in +very long lines too. + +This combines to make it hard for users to read the output and identify +if QEMU knows about the feature they wish to use. + +This change gets rid of the grouping of features and treats all flags as +single list. The list is sorted into alphabetical order and the printing +with line wrapping at the 77th column. + +Signed-off-by: Daniel P. Berrangé +Message-Id: <20180606165527.17365-4-berrange@redhat.com> +Signed-off-by: Eduardo Habkost +(cherry picked from commit cc643b1e7898414b56f551bbd42d4ed8c2ae127a) +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 41 +++++++++++++++++++++++++++-------------- + 1 file changed, 27 insertions(+), 14 deletions(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 52f1f33..d0c48c2 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -3651,17 +3651,21 @@ static void x86_cpu_class_check_missing_features(X86CPUClass *xcc, + + /* Print all cpuid feature names in featureset + */ +-static void listflags(FILE *f, fprintf_function print, const char **featureset) ++static void listflags(FILE *f, fprintf_function print, GList *features) + { +- int bit; +- bool first = true; +- +- for (bit = 0; bit < 32; bit++) { +- if (featureset[bit]) { +- print(f, "%s%s", first ? "" : " ", featureset[bit]); +- first = false; ++ size_t len = 0; ++ GList *tmp; ++ ++ for (tmp = features; tmp; tmp = tmp->next) { ++ const char *name = tmp->data; ++ if ((len + strlen(name) + 1) >= 75) { ++ print(f, "\n"); ++ len = 0; + } ++ print(f, "%s%s", len == 0 ? " " : " ", name); ++ len += strlen(name) + 1; + } ++ print(f, "\n"); + } + + /* Sort alphabetically by type name, respecting X86CPUClass::ordering. */ +@@ -3708,26 +3712,35 @@ static void x86_cpu_list_entry(gpointer data, gpointer user_data) + /* list available CPU models and flags */ + void x86_cpu_list(FILE *f, fprintf_function cpu_fprintf) + { +- int i; ++ int i, j; + CPUListState s = { + .file = f, + .cpu_fprintf = cpu_fprintf, + }; + GSList *list; ++ GList *names = NULL; + + (*cpu_fprintf)(f, "Available CPUs:\n"); + list = get_sorted_cpu_model_list(); + g_slist_foreach(list, x86_cpu_list_entry, &s); + g_slist_free(list); + +- (*cpu_fprintf)(f, "\nRecognized CPUID flags:\n"); ++ names = NULL; + for (i = 0; i < ARRAY_SIZE(feature_word_info); i++) { + FeatureWordInfo *fw = &feature_word_info[i]; +- +- (*cpu_fprintf)(f, " "); +- listflags(f, cpu_fprintf, fw->feat_names); +- (*cpu_fprintf)(f, "\n"); ++ for (j = 0; j < 32; j++) { ++ if (fw->feat_names[j]) { ++ names = g_list_append(names, (gpointer)fw->feat_names[j]); ++ } ++ } + } ++ ++ names = g_list_sort(names, (GCompareFunc)strcmp); ++ ++ (*cpu_fprintf)(f, "\nRecognized CPUID flags:\n"); ++ listflags(f, cpu_fprintf, names); ++ (*cpu_fprintf)(f, "\n"); ++ g_list_free(names); + } + + static void x86_cpu_definition_entry(gpointer data, gpointer user_data) +-- +1.8.3.1 + diff --git a/SOURCES/kvm-i386-fix-regression-parsing-multiboot-initrd-modules.patch b/SOURCES/kvm-i386-fix-regression-parsing-multiboot-initrd-modules.patch new file mode 100644 index 0000000..0f80206 --- /dev/null +++ b/SOURCES/kvm-i386-fix-regression-parsing-multiboot-initrd-modules.patch @@ -0,0 +1,83 @@ +From dc98e8dd5c4aad2f3c480a9513ffba89540dcf3f Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Thu, 12 Sep 2019 13:05:01 +0100 +Subject: [PATCH 04/22] i386: fix regression parsing multiboot initrd modules +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Laszlo Ersek +Message-id: <20190912130503.14094-5-lersek@redhat.com> +Patchwork-id: 90434 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH 4/6] i386: fix regression parsing multiboot initrd modules +Bugzilla: 1749022 +RH-Acked-by: Stefano Garzarella +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Eduardo Habkost + +From: Daniel P. Berrangé + +The logic for parsing the multiboot initrd modules was messed up in + + commit 950c4e6c94b15cd0d8b63891dddd7a8dbf458e6a + Author: Daniel P. Berrangé + Date: Mon Apr 16 12:17:43 2018 +0100 + + opts: don't silently truncate long option values + +Causing the length to be undercounter, and the number of modules over +counted. It also passes NULL to get_opt_value() which was not robust +at accepting a NULL value. + +RHEL8 notes: + +- Context difference in "util/qemu-option.c", function get_opt_value(); + upstream has commit 5c99fa375da1 ("cutils: Provide strchrnul", + 2018-06-29), part of v3.0.0, but downstream lacks it. Harmless, because + said upstream commit only refactors get_opt_value(). + +Signed-off-by: Daniel P. Berrangé +Message-Id: <20180514171913.17664-2-berrange@redhat.com> +Reviewed-by: Eduardo Habkost +Tested-by: Roman Kagan +Signed-off-by: Paolo Bonzini +(cherry picked from commit 6e3ad3f0e31b8e31c6c0769d0f474bcd9673e0e5) +Signed-off-by: Laszlo Ersek +Signed-off-by: Danilo C. L. de Paula +--- + hw/i386/multiboot.c | 3 +-- + util/qemu-option.c | 4 +++- + 2 files changed, 4 insertions(+), 3 deletions(-) + +diff --git a/hw/i386/multiboot.c b/hw/i386/multiboot.c +index 7a2953e..8e26545 100644 +--- a/hw/i386/multiboot.c ++++ b/hw/i386/multiboot.c +@@ -292,8 +292,7 @@ int load_multiboot(FWCfgState *fw_cfg, + cmdline_len += strlen(kernel_cmdline) + 1; + if (initrd_filename) { + const char *r = get_opt_value(initrd_filename, NULL); +- cmdline_len += strlen(r) + 1; +- mbs.mb_mods_avail = 1; ++ cmdline_len += strlen(initrd_filename) + 1; + while (1) { + mbs.mb_mods_avail++; + r = get_opt_value(r, NULL); +diff --git a/util/qemu-option.c b/util/qemu-option.c +index ba44a08..a396d60 100644 +--- a/util/qemu-option.c ++++ b/util/qemu-option.c +@@ -75,7 +75,9 @@ const char *get_opt_value(const char *p, char **value) + size_t capacity = 0, length; + const char *offset; + +- *value = NULL; ++ if (value) { ++ *value = NULL; ++ } + while (1) { + offset = strchr(p, ','); + if (!offset) { +-- +1.8.3.1 + diff --git a/SOURCES/kvm-i386-kvm-Do-not-sync-nested-state-during-runtime.patch b/SOURCES/kvm-i386-kvm-Do-not-sync-nested-state-during-runtime.patch new file mode 100644 index 0000000..f0d83c7 --- /dev/null +++ b/SOURCES/kvm-i386-kvm-Do-not-sync-nested-state-during-runtime.patch @@ -0,0 +1,55 @@ +From aaf60450da6b0bc4723028aeab9ced75ee03111b Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 22 Jul 2019 18:22:20 +0100 +Subject: [PATCH 39/39] i386/kvm: Do not sync nested state during runtime + +RH-Author: Paolo Bonzini +Message-id: <20190722182220.19374-19-pbonzini@redhat.com> +Patchwork-id: 89635 +O-Subject: [RHEL-8.1.0 PATCH qemu-kvm v3 18/18] i386/kvm: Do not sync nested state during runtime +Bugzilla: 1689269 +RH-Acked-by: Peter Xu +RH-Acked-by: Laurent Vivier +RH-Acked-by: Dr. David Alan Gilbert + +From: Jan Kiszka + +Writing the nested state e.g. after a vmport access can invalidate +important parts of the kernel-internal state, and it is not needed as +well. So leave this out from KVM_PUT_RUNTIME_STATE. + +Suggested-by: Paolo Bonzini +Signed-off-by: Jan Kiszka +Message-Id: +Signed-off-by: Paolo Bonzini +(cherry picked from commit 20b25d239ab7a94bb8bff3d0f13a9527ee75cf10) +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/kvm.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index 8648f1f..da5f07e 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -3014,12 +3014,12 @@ int kvm_arch_put_registers(CPUState *cpu, int level) + + assert(cpu_is_stopped(cpu) || qemu_cpu_is_self(cpu)); + +- ret = kvm_put_nested_state(x86_cpu); +- if (ret < 0) { +- return ret; +- } +- + if (level >= KVM_PUT_RESET_STATE) { ++ ret = kvm_put_nested_state(x86_cpu); ++ if (ret < 0) { ++ return ret; ++ } ++ + ret = kvm_put_msr_feature_control(x86_cpu); + if (ret < 0) { + return ret; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-i386-only-parse-the-initrd_filename-once-for-multibo.patch b/SOURCES/kvm-i386-only-parse-the-initrd_filename-once-for-multibo.patch new file mode 100644 index 0000000..204cb8d --- /dev/null +++ b/SOURCES/kvm-i386-only-parse-the-initrd_filename-once-for-multibo.patch @@ -0,0 +1,115 @@ +From b9d1e72a0910c3a0d11cb0a3c863938de344e0f5 Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Thu, 12 Sep 2019 13:05:02 +0100 +Subject: [PATCH 05/22] i386: only parse the initrd_filename once for multiboot + modules +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Laszlo Ersek +Message-id: <20190912130503.14094-6-lersek@redhat.com> +Patchwork-id: 90438 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH 5/6] i386: only parse the initrd_filename once for multiboot modules +Bugzilla: 1749022 +RH-Acked-by: Stefano Garzarella +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Eduardo Habkost + +From: Daniel P. Berrangé + +The multiboot code parses the initrd_filename twice, first to count how +many entries there are, and second to process each entry. This changes +the first loop to store the parse module names in a list, and the second +loop can now use these names. This avoids having to pass NULL to the +get_opt_value() method which means it can safely assume a non-NULL param. + +Signed-off-by: Daniel P. Berrangé +Message-Id: <20180514171913.17664-3-berrange@redhat.com> +Reviewed-by: Eduardo Habkost +Tested-by: Roman Kagan +Signed-off-by: Paolo Bonzini +(cherry picked from commit f8da93a0ffa09268815c1942732cbc616a7db847) +Signed-off-by: Laszlo Ersek +Signed-off-by: Danilo C. L. de Paula +--- + hw/i386/multiboot.c | 32 +++++++++++++++----------------- + 1 file changed, 15 insertions(+), 17 deletions(-) + +diff --git a/hw/i386/multiboot.c b/hw/i386/multiboot.c +index 8e26545..d519e20 100644 +--- a/hw/i386/multiboot.c ++++ b/hw/i386/multiboot.c +@@ -161,6 +161,7 @@ int load_multiboot(FWCfgState *fw_cfg, + uint8_t bootinfo[MBI_SIZE]; + uint8_t *mb_bootinfo_data; + uint32_t cmdline_len; ++ GList *mods = NULL; + + /* Ok, let's see if it is a multiboot image. + The header is 12x32bit long, so the latest entry may be 8192 - 48. */ +@@ -291,15 +292,16 @@ int load_multiboot(FWCfgState *fw_cfg, + cmdline_len = strlen(kernel_filename) + 1; + cmdline_len += strlen(kernel_cmdline) + 1; + if (initrd_filename) { +- const char *r = get_opt_value(initrd_filename, NULL); ++ const char *r = initrd_filename; + cmdline_len += strlen(initrd_filename) + 1; +- while (1) { ++ while (*r) { ++ char *value; ++ r = get_opt_value(r, &value); + mbs.mb_mods_avail++; +- r = get_opt_value(r, NULL); +- if (!*r) { +- break; ++ mods = g_list_append(mods, value); ++ if (*r) { ++ r++; + } +- r++; + } + } + +@@ -314,20 +316,16 @@ int load_multiboot(FWCfgState *fw_cfg, + mbs.offset_cmdlines = mbs.offset_mbinfo + mbs.mb_mods_avail * MB_MOD_SIZE; + mbs.offset_bootloader = mbs.offset_cmdlines + cmdline_len; + +- if (initrd_filename) { +- const char *next_initrd; +- char not_last; +- char *one_file = NULL; +- ++ if (mods) { ++ GList *tmpl = mods; + mbs.offset_mods = mbs.mb_buf_size; + +- do { ++ while (tmpl) { + char *next_space; + int mb_mod_length; + uint32_t offs = mbs.mb_buf_size; ++ char *one_file = tmpl->data; + +- next_initrd = get_opt_value(initrd_filename, &one_file); +- not_last = *next_initrd; + /* if a space comes after the module filename, treat everything + after that as parameters */ + hwaddr c = mb_add_cmdline(&mbs, one_file); +@@ -352,10 +350,10 @@ int load_multiboot(FWCfgState *fw_cfg, + mb_debug("mod_start: %p\nmod_end: %p\n cmdline: "TARGET_FMT_plx, + (char *)mbs.mb_buf + offs, + (char *)mbs.mb_buf + offs + mb_mod_length, c); +- initrd_filename = next_initrd+1; + g_free(one_file); +- one_file = NULL; +- } while (not_last); ++ tmpl = tmpl->next; ++ } ++ g_list_free(mods); + } + + /* Commandline support */ +-- +1.8.3.1 + diff --git a/SOURCES/kvm-i386-remove-the-INTEL_PT-CPUID-bit-from-named-CPU-NEW.patch b/SOURCES/kvm-i386-remove-the-INTEL_PT-CPUID-bit-from-named-CPU-NEW.patch new file mode 100644 index 0000000..9e36c94 --- /dev/null +++ b/SOURCES/kvm-i386-remove-the-INTEL_PT-CPUID-bit-from-named-CPU-NEW.patch @@ -0,0 +1,52 @@ +From 6131491c7a5494c1c034973ae23fc842b1ee733e Mon Sep 17 00:00:00 2001 +From: "plai@redhat.com" +Date: Mon, 1 Jul 2019 16:17:33 +0100 +Subject: [PATCH 04/39] i386: remove the 'INTEL_PT' CPUID bit from named CPU + models + +RH-Author: plai@redhat.com +Message-id: <1561997854-9646-5-git-send-email-plai@redhat.com> +Patchwork-id: 89332 +O-Subject: [RHEL8.1 qemu-kvm PATCH v6 4/5] i386: remove the 'INTEL_PT' CPUID bit from named CPU models +Bugzilla: 1629906 +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Bandan Das + +From: Paolo Bonzini + +Processor tracing is not yet implemented for KVM and it will be an +opt in feature requiring a special module parameter. +Disable it, because it is wrong to enable it by default and +it is impossible that no one has ever used it. + +Cc: qemu-stable@nongnu.org +Signed-off-by: Paolo Bonzini +(cherry picked from commit 4c257911dcc7c4189768e9651755c849ce9db4e8) +Signed-off-by: Paul Lai + +Resolved Conflicts: + target/i386/cpu.c + +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 094f8a1..2538d82 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -2515,8 +2515,7 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_7_0_EBX_SMAP | CPUID_7_0_EBX_CLWB | + CPUID_7_0_EBX_AVX512F | CPUID_7_0_EBX_AVX512DQ | + CPUID_7_0_EBX_AVX512BW | CPUID_7_0_EBX_AVX512CD | +- CPUID_7_0_EBX_AVX512VL | CPUID_7_0_EBX_CLFLUSHOPT | +- CPUID_7_0_EBX_INTEL_PT, ++ CPUID_7_0_EBX_AVX512VL | CPUID_7_0_EBX_CLFLUSHOPT, + .features[FEAT_7_0_ECX] = + CPUID_7_0_ECX_PKU | CPUID_7_0_ECX_OSPKE | + CPUID_7_0_ECX_AVX512VNNI, +-- +1.8.3.1 + diff --git a/SOURCES/kvm-i386-unavailable-features-QOM-property.patch b/SOURCES/kvm-i386-unavailable-features-QOM-property.patch new file mode 100644 index 0000000..6f16eb8 --- /dev/null +++ b/SOURCES/kvm-i386-unavailable-features-QOM-property.patch @@ -0,0 +1,71 @@ +From 2adf144c57ddef54f5c42cdbc539d0249ce1b0ba Mon Sep 17 00:00:00 2001 +From: Eduardo Habkost +Date: Thu, 29 Aug 2019 20:55:32 +0100 +Subject: [PATCH 05/10] i386: "unavailable-features" QOM property + +RH-Author: Eduardo Habkost +Message-id: <20190829205532.8302-3-ehabkost@redhat.com> +Patchwork-id: 90201 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 2/2] i386: "unavailable-features" QOM property +Bugzilla: 1747185 +RH-Acked-by: Thomas Huth +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Michael S. Tsirkin + +Add a "unavailable-features" QOM property to X86CPU objects that +have the same semantics of "unavailable-features" on +query-cpu-definitions. The new property has the same goal of +"filtered-features", but is generic enough to let any kind of CPU +feature to be listed there without relying on low level details +like CPUID leaves or MSR numbers. + +Message-Id: <20190422234742.15780-3-ehabkost@redhat.com> +Signed-off-by: Eduardo Habkost +(cherry picked from commit 506174bf8219dc6d56d2b1f7e66e8cf39157466f) +Signed-off-by: Eduardo Habkost +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 934f11b..c8f50a7 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -3580,6 +3580,17 @@ static void x86_cpu_list_feature_names(FeatureWordArray features, + } + } + ++static void x86_cpu_get_unavailable_features(Object *obj, Visitor *v, ++ const char *name, void *opaque, ++ Error **errp) ++{ ++ X86CPU *xc = X86_CPU(obj); ++ strList *result = NULL; ++ ++ x86_cpu_list_feature_names(xc->filtered_features, &result); ++ visit_type_strList(v, "unavailable-features", &result, errp); ++} ++ + /* Check for missing features that may prevent the CPU class from + * running using the current machine and accelerator. + */ +@@ -5479,6 +5490,15 @@ static void x86_cpu_initfn(Object *obj) + object_property_add(obj, "filtered-features", "X86CPUFeatureWordInfo", + x86_cpu_get_feature_words, + NULL, NULL, (void *)cpu->filtered_features, NULL); ++ /* ++ * The "unavailable-features" property has the same semantics as ++ * CpuDefinitionInfo.unavailable-features on the "query-cpu-definitions" ++ * QMP command: they list the features that would have prevented the ++ * CPU from running if the "enforce" flag was set. ++ */ ++ object_property_add(obj, "unavailable-features", "strList", ++ x86_cpu_get_unavailable_features, ++ NULL, NULL, NULL, &error_abort); + + object_property_add(obj, "crash-information", "GuestPanicInformation", + x86_cpu_get_crash_info_qom, NULL, NULL, NULL, NULL); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-i386-x86_cpu_list_feature_names-function.patch b/SOURCES/kvm-i386-x86_cpu_list_feature_names-function.patch new file mode 100644 index 0000000..e1e9895 --- /dev/null +++ b/SOURCES/kvm-i386-x86_cpu_list_feature_names-function.patch @@ -0,0 +1,90 @@ +From 61aa52146679fb00f976bc1eb7884f1ddcf7342c Mon Sep 17 00:00:00 2001 +From: Eduardo Habkost +Date: Thu, 29 Aug 2019 20:55:31 +0100 +Subject: [PATCH 04/10] i386: x86_cpu_list_feature_names() function + +RH-Author: Eduardo Habkost +Message-id: <20190829205532.8302-2-ehabkost@redhat.com> +Patchwork-id: 90200 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 1/2] i386: x86_cpu_list_feature_names() function +Bugzilla: 1747185 +RH-Acked-by: Thomas Huth +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Michael S. Tsirkin + +Extract feature name listing code from +x86_cpu_class_check_missing_features(). It will be reused to +return information about CPU filtered features at runtime. + +Message-Id: <20190422234742.15780-2-ehabkost@redhat.com> +Signed-off-by: Eduardo Habkost +(cherry picked from commit 5a853fc57a0860da4a55d1448a77845f97e7a9be) +Signed-off-by: Eduardo Habkost +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 35 ++++++++++++++++++++++------------- + 1 file changed, 22 insertions(+), 13 deletions(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index f71b044..934f11b 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -3559,6 +3559,27 @@ static void x86_cpu_parse_featurestr(const char *typename, char *features, + static void x86_cpu_expand_features(X86CPU *cpu, Error **errp); + static int x86_cpu_filter_features(X86CPU *cpu); + ++/* Build a list with the name of all features on a feature word array */ ++static void x86_cpu_list_feature_names(FeatureWordArray features, ++ strList **feat_names) ++{ ++ FeatureWord w; ++ strList **next = feat_names; ++ ++ for (w = 0; w < FEATURE_WORDS; w++) { ++ uint32_t filtered = features[w]; ++ int i; ++ for (i = 0; i < 32; i++) { ++ if (filtered & (1UL << i)) { ++ strList *new = g_new0(strList, 1); ++ new->value = g_strdup(x86_cpu_feature_name(w, i)); ++ *next = new; ++ next = &new->next; ++ } ++ } ++ } ++} ++ + /* Check for missing features that may prevent the CPU class from + * running using the current machine and accelerator. + */ +@@ -3566,7 +3587,6 @@ static void x86_cpu_class_check_missing_features(X86CPUClass *xcc, + strList **missing_feats) + { + X86CPU *xc; +- FeatureWord w; + Error *err = NULL; + strList **next = missing_feats; + +@@ -3593,18 +3613,7 @@ static void x86_cpu_class_check_missing_features(X86CPUClass *xcc, + + x86_cpu_filter_features(xc); + +- for (w = 0; w < FEATURE_WORDS; w++) { +- uint32_t filtered = xc->filtered_features[w]; +- int i; +- for (i = 0; i < 32; i++) { +- if (filtered & (1UL << i)) { +- strList *new = g_new0(strList, 1); +- new->value = g_strdup(x86_cpu_feature_name(w, i)); +- *next = new; +- next = &new->next; +- } +- } +- } ++ x86_cpu_list_feature_names(xc->filtered_features, next); + + object_unref(OBJECT(xc)); + } +-- +1.8.3.1 + diff --git a/SOURCES/kvm-intel_iommu-Correct-caching-mode-error-message.patch b/SOURCES/kvm-intel_iommu-Correct-caching-mode-error-message.patch new file mode 100644 index 0000000..02b5255 --- /dev/null +++ b/SOURCES/kvm-intel_iommu-Correct-caching-mode-error-message.patch @@ -0,0 +1,59 @@ +From 8954b0306e2179987cd097d203057e780808b0ba Mon Sep 17 00:00:00 2001 +From: Peter Xu +Date: Wed, 9 Oct 2019 12:39:43 +0100 +Subject: [PATCH 17/22] intel_iommu: Correct caching-mode error message +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Peter Xu +Message-id: <20191009123947.21505-2-peterx@redhat.com> +Patchwork-id: 91350 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH 1/5] intel_iommu: Correct caching-mode error message +Bugzilla: 1738440 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Auger Eric +RH-Acked-by: Alex Williamson + +From: Alex Williamson + +If we try to use the intel-iommu device with vfio-pci devices without +caching mode enabled, we're told: + + qemu-system-x86_64: We need to set caching-mode=1 for intel-iommu to enable + device assignment with IOMMU protection. + +But to enable caching mode, the option is actually "caching-mode=on". + +Signed-off-by: Alex Williamson +Message-Id: <155364147432.16467.15898335025013220939.stgit@gimli.home> +Reviewed-by: Peter Xu +Reviewed-by: Laurent Vivier +Reviewed-by: Philippe Mathieu-Daudé +Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
+Reviewed-by: Eric Auger +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +(cherry picked from commit 75c5626c88a9675010018849ca9abc8d56045425) +Signed-off-by: Peter Xu +Signed-off-by: Danilo C. L. de Paula +--- + hw/i386/intel_iommu.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c +index e827c5a..22d2e52 100644 +--- a/hw/i386/intel_iommu.c ++++ b/hw/i386/intel_iommu.c +@@ -2554,7 +2554,7 @@ static void vtd_iommu_notify_flag_changed(IOMMUMemoryRegion *iommu, + IntelIOMMUState *s = vtd_as->iommu_state; + + if (!s->caching_mode && new & IOMMU_NOTIFIER_MAP) { +- error_report("We need to set caching-mode=1 for intel-iommu to enable " ++ error_report("We need to set caching-mode=on for intel-iommu to enable " + "device assignment with IOMMU protection."); + exit(1); + } +-- +1.8.3.1 + diff --git a/SOURCES/kvm-intel_iommu-Remove-the-caching-mode-check-during-fla.patch b/SOURCES/kvm-intel_iommu-Remove-the-caching-mode-check-during-fla.patch new file mode 100644 index 0000000..1f45fc0 --- /dev/null +++ b/SOURCES/kvm-intel_iommu-Remove-the-caching-mode-check-during-fla.patch @@ -0,0 +1,49 @@ +From 01ab894f9d19a03aee876b0d1b468f7314765539 Mon Sep 17 00:00:00 2001 +From: Peter Xu +Date: Wed, 9 Oct 2019 12:39:47 +0100 +Subject: [PATCH 21/22] intel_iommu: Remove the caching-mode check during flag + change + +RH-Author: Peter Xu +Message-id: <20191009123947.21505-6-peterx@redhat.com> +Patchwork-id: 91349 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH 5/5] intel_iommu: Remove the caching-mode check during flag change +Bugzilla: 1738440 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Auger Eric +RH-Acked-by: Alex Williamson + +That's never a good place to stop QEMU process... Since now we have +both the machine done sanity check and also the hotplug handler, we +can safely remove this to avoid that. + +Reviewed-by: Eric Auger +Signed-off-by: Peter Xu +Message-Id: <20190916080718.3299-5-peterx@redhat.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +(cherry picked from commit e7df189e19e86bf9f4d7aea4c6cf50ac0ebfce46) +Signed-off-by: Peter Xu +Signed-off-by: Danilo C. L. de Paula +--- + hw/i386/intel_iommu.c | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c +index 44d19cc..a4190bf 100644 +--- a/hw/i386/intel_iommu.c ++++ b/hw/i386/intel_iommu.c +@@ -2561,10 +2561,6 @@ static void vtd_iommu_notify_flag_changed(IOMMUMemoryRegion *iommu, + VTDAddressSpace *vtd_as = container_of(iommu, VTDAddressSpace, iommu); + IntelIOMMUState *s = vtd_as->iommu_state; + +- if (!s->caching_mode && new & IOMMU_NOTIFIER_MAP) { +- vtd_panic_require_caching_mode(); +- } +- + /* Update per-address-space notifier flags */ + vtd_as->notifier_flags = new; + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-intel_iommu-Sanity-check-vfio-pci-config-on-machine-.patch b/SOURCES/kvm-intel_iommu-Sanity-check-vfio-pci-config-on-machine-.patch new file mode 100644 index 0000000..ed7753f --- /dev/null +++ b/SOURCES/kvm-intel_iommu-Sanity-check-vfio-pci-config-on-machine-.patch @@ -0,0 +1,131 @@ +From 3a528a458d4a2ba4236e98ef3f4efe5482323972 Mon Sep 17 00:00:00 2001 +From: Peter Xu +Date: Wed, 9 Oct 2019 12:39:44 +0100 +Subject: [PATCH 18/22] intel_iommu: Sanity check vfio-pci config on machine + init done + +RH-Author: Peter Xu +Message-id: <20191009123947.21505-3-peterx@redhat.com> +Patchwork-id: 91347 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH 2/5] intel_iommu: Sanity check vfio-pci config on machine init done +Bugzilla: 1738440 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Auger Eric +RH-Acked-by: Alex Williamson + +This check was previously only happened when the IOMMU is enabled in +the guest. It was always too late because the enabling of IOMMU +normally only happens during the boot of guest OS. It means that we +can bail out and exit directly during the guest OS boots if the +configuration of devices are not supported. Or, if the guest didn't +enable vIOMMU at all, then the user can use the guest normally but as +long as it reconfigure the guest OS to enable the vIOMMU then reboot, +the user will see the panic right after the reset when the next boot +starts. + +Let's make this failure even earlier so that we force the user to use +caching-mode for vfio-pci devices when with the vIOMMU. So the user +won't get surprise at least during execution of the guest, which seems +a bit nicer. + +This will affect some user who didn't enable vIOMMU in the guest OS +but was using vfio-pci and the vtd device in the past. However I hope +it's not a majority because not enabling vIOMMU with the device +attached is actually meaningless. + +We still keep the old assertion for safety so far because the hotplug +path could still reach it, so far. + +Reviewed-by: Eric Auger +Signed-off-by: Peter Xu +Message-Id: <20190916080718.3299-2-peterx@redhat.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +(cherry picked from commit 28cf553afeb29b0c4f339c600171552a72a68cb7) +Signed-off-by: Peter Xu +Signed-off-by: Danilo C. L. de Paula +--- + hw/i386/intel_iommu.c | 39 ++++++++++++++++++++++++++++++++++++--- + 1 file changed, 36 insertions(+), 3 deletions(-) + +diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c +index 22d2e52..44d19cc 100644 +--- a/hw/i386/intel_iommu.c ++++ b/hw/i386/intel_iommu.c +@@ -33,6 +33,7 @@ + #include "hw/i386/x86-iommu.h" + #include "hw/pci-host/q35.h" + #include "sysemu/kvm.h" ++#include "sysemu/sysemu.h" + #include "hw/i386/apic_internal.h" + #include "kvm_i386.h" + #include "trace.h" +@@ -40,6 +41,13 @@ + static void vtd_address_space_refresh_all(IntelIOMMUState *s); + static void vtd_address_space_unmap(VTDAddressSpace *as, IOMMUNotifier *n); + ++static void vtd_panic_require_caching_mode(void) ++{ ++ error_report("We need to set caching-mode=on for intel-iommu to enable " ++ "device assignment with IOMMU protection."); ++ exit(1); ++} ++ + static void vtd_define_quad(IntelIOMMUState *s, hwaddr addr, uint64_t val, + uint64_t wmask, uint64_t w1cmask) + { +@@ -2554,9 +2562,7 @@ static void vtd_iommu_notify_flag_changed(IOMMUMemoryRegion *iommu, + IntelIOMMUState *s = vtd_as->iommu_state; + + if (!s->caching_mode && new & IOMMU_NOTIFIER_MAP) { +- error_report("We need to set caching-mode=on for intel-iommu to enable " +- "device assignment with IOMMU protection."); +- exit(1); ++ vtd_panic_require_caching_mode(); + } + + /* Update per-address-space notifier flags */ +@@ -3303,6 +3309,32 @@ static bool vtd_decide_config(IntelIOMMUState *s, Error **errp) + return true; + } + ++static int vtd_machine_done_notify_one(Object *child, void *unused) ++{ ++ IntelIOMMUState *iommu = INTEL_IOMMU_DEVICE(x86_iommu_get_default()); ++ ++ /* ++ * We hard-coded here because vfio-pci is the only special case ++ * here. Let's be more elegant in the future when we can, but so ++ * far there seems to be no better way. ++ */ ++ if (object_dynamic_cast(child, "vfio-pci") && !iommu->caching_mode) { ++ vtd_panic_require_caching_mode(); ++ } ++ ++ return 0; ++} ++ ++static void vtd_machine_done_hook(Notifier *notifier, void *unused) ++{ ++ object_child_foreach_recursive(object_get_root(), ++ vtd_machine_done_notify_one, NULL); ++} ++ ++static Notifier vtd_machine_done_notify = { ++ .notify = vtd_machine_done_hook, ++}; ++ + static void vtd_realize(DeviceState *dev, Error **errp) + { + MachineState *ms = MACHINE(qdev_get_machine()); +@@ -3333,6 +3365,7 @@ static void vtd_realize(DeviceState *dev, Error **errp) + pci_setup_iommu(bus, vtd_host_dma_iommu, dev); + /* Pseudo address space under root PCI bus. */ + pcms->ioapic_as = vtd_host_dma_iommu(bus, s, Q35_PSEUDO_DEVFN_IOAPIC); ++ qemu_add_machine_init_done_notifier(&vtd_machine_done_notify); + } + + static void vtd_class_init(ObjectClass *klass, void *data) +-- +1.8.3.1 + diff --git a/SOURCES/kvm-iotests-Filter-175-s-allocation-information.patch b/SOURCES/kvm-iotests-Filter-175-s-allocation-information.patch new file mode 100644 index 0000000..8c91799 --- /dev/null +++ b/SOURCES/kvm-iotests-Filter-175-s-allocation-information.patch @@ -0,0 +1,138 @@ +From b897ede11c7b47cc9db8334ca44dd960d3001309 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 30 Aug 2019 12:56:26 +0100 +Subject: [PATCH 08/10] iotests: Filter 175's allocation information + +RH-Author: Thomas Huth +Message-id: <20190830125628.23668-4-thuth@redhat.com> +Patchwork-id: 90211 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v2 3/5] iotests: Filter 175's allocation information +Bugzilla: 1738839 +RH-Acked-by: Cornelia Huck +RH-Acked-by: Max Reitz +RH-Acked-by: David Hildenbrand + +From: Max Reitz + +It is possible for an empty file to take up blocks on a filesystem, for +example: + +$ qemu-img create -f raw test.img 1G +Formatting 'test.img', fmt=raw size=1073741824 +$ mkfs.ext4 -I 128 -q test.img +$ mkdir test-mount +$ sudo mount -o loop test.img test-mount +$ sudo touch test-mount/test-file +$ stat -c 'blocks=%b' test-mount/test-file +blocks=8 + +These extra blocks (one cluster) are apparently used for metadata, +because they are always there, on top of blocks used for data: + +$ sudo dd if=/dev/zero of=test-mount/test-file bs=1M count=1 +1+0 records in +1+0 records out +1048576 bytes (1.0 MB, 1.0 MiB) copied, 0.00135339 s, 775 MB/s +$ stat -c 'blocks=%b' test-mount/test-file +blocks=2056 + +Make iotest 175 take this into account. + +Reported-by: Thomas Huth +Signed-off-by: Max Reitz +Reviewed-by: Eric Blake +Reviewed-by: Nir Soffer +Message-id: 20190516144319.12570-1-mreitz@redhat.com +Signed-off-by: Max Reitz +(cherry picked from commit a3bd71b5773a3664692601e6e181f108e1e4aa41) +Signed-off-by: Danilo C. L. de Paula +--- + tests/qemu-iotests/175 | 26 ++++++++++++++++++++++---- + tests/qemu-iotests/175.out | 8 ++++---- + 2 files changed, 26 insertions(+), 8 deletions(-) + +diff --git a/tests/qemu-iotests/175 b/tests/qemu-iotests/175 +index ca56e82..2e37c9a 100755 +--- a/tests/qemu-iotests/175 ++++ b/tests/qemu-iotests/175 +@@ -29,10 +29,25 @@ status=1 # failure is the default! + + _cleanup() + { +- _cleanup_test_img ++ _cleanup_test_img ++ rm -f "$TEST_DIR/empty" + } + trap "_cleanup; exit \$status" 0 1 2 3 15 + ++# Some file systems sometimes allocate extra blocks independently of ++# the file size. This function hides the resulting difference in the ++# stat -c '%b' output. ++# Parameter 1: Number of blocks an empty file occupies ++# Parameter 2: Image size in bytes ++_filter_blocks() ++{ ++ extra_blocks=$1 ++ img_size=$2 ++ ++ sed -e "s/blocks=$extra_blocks\\(\$\\|[^0-9]\\)/nothing allocated/" \ ++ -e "s/blocks=$((extra_blocks + img_size / 512))\\(\$\\|[^0-9]\\)/everything allocated/" ++} ++ + # get standard environment, filters and checks + . ./common.rc + . ./common.filter +@@ -41,18 +56,21 @@ _supported_fmt raw + _supported_proto file + _supported_os Linux + +-size=1m ++size=$((1 * 1024 * 1024)) ++ ++touch "$TEST_DIR/empty" ++extra_blocks=$(stat -c '%b' "$TEST_DIR/empty") + + echo + echo "== creating image with default preallocation ==" + _make_test_img $size | _filter_imgfmt +-stat -c "size=%s, blocks=%b" $TEST_IMG ++stat -c "size=%s, blocks=%b" $TEST_IMG | _filter_blocks $extra_blocks $size + + for mode in off full falloc; do + echo + echo "== creating image with preallocation $mode ==" + IMGOPTS=preallocation=$mode _make_test_img $size | _filter_imgfmt +- stat -c "size=%s, blocks=%b" $TEST_IMG ++ stat -c "size=%s, blocks=%b" $TEST_IMG | _filter_blocks $extra_blocks $size + done + + # success, all done +diff --git a/tests/qemu-iotests/175.out b/tests/qemu-iotests/175.out +index 76c02c6..6d9a5ed 100644 +--- a/tests/qemu-iotests/175.out ++++ b/tests/qemu-iotests/175.out +@@ -2,17 +2,17 @@ QA output created by 175 + + == creating image with default preallocation == + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 +-size=1048576, blocks=0 ++size=1048576, nothing allocated + + == creating image with preallocation off == + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 preallocation=off +-size=1048576, blocks=0 ++size=1048576, nothing allocated + + == creating image with preallocation full == + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 preallocation=full +-size=1048576, blocks=2048 ++size=1048576, everything allocated + + == creating image with preallocation falloc == + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 preallocation=falloc +-size=1048576, blocks=2048 ++size=1048576, everything allocated + *** done +-- +1.8.3.1 + diff --git a/SOURCES/kvm-iotests-Filter-SSH-paths.patch b/SOURCES/kvm-iotests-Filter-SSH-paths.patch new file mode 100644 index 0000000..07e69e8 --- /dev/null +++ b/SOURCES/kvm-iotests-Filter-SSH-paths.patch @@ -0,0 +1,49 @@ +From 1d8ba61938b06c54749b96af34acf3fee751bc93 Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Mon, 8 Jul 2019 15:25:56 +0100 +Subject: [PATCH 10/39] iotests: Filter SSH paths +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Pino Toscano +Message-id: <20190708152601.21123-6-ptoscano@redhat.com> +Patchwork-id: 89416 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v3 05/10] iotests: Filter SSH paths +Bugzilla: 1513367 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Max Reitz +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Markus Armbruster + +From: Max Reitz + +8908b253c4ad5f8874c8d13abec169c696a5cd32 has implemented filtering of +remote paths for NFS, but forgot SSH. This patch takes care of that. + +Signed-off-by: Max Reitz +Reviewed-by: John Snow +Message-id: 20190210145736.1486-9-mreitz@redhat.com +Signed-off-by: Max Reitz +(cherry picked from commit ac3589dc463c18e6726be2831196c7755bec39d5) +Signed-off-by: Pino Toscano +Signed-off-by: Danilo C. L. de Paula +--- + tests/qemu-iotests/common.rc | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc +index d054cb9..6490c8d 100644 +--- a/tests/qemu-iotests/common.rc ++++ b/tests/qemu-iotests/common.rc +@@ -145,6 +145,7 @@ else + TEST_IMG="nbd:127.0.0.1:10810" + elif [ "$IMGPROTO" = "ssh" ]; then + TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT ++ REMOTE_TEST_DIR="ssh://127.0.0.1$TEST_DIR" + TEST_IMG="ssh://127.0.0.1$TEST_IMG_FILE" + elif [ "$IMGPROTO" = "nfs" ]; then + TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT +-- +1.8.3.1 + diff --git a/SOURCES/kvm-iotests-Make-182-do-without-device_add.patch b/SOURCES/kvm-iotests-Make-182-do-without-device_add.patch new file mode 100644 index 0000000..5d4e5e6 --- /dev/null +++ b/SOURCES/kvm-iotests-Make-182-do-without-device_add.patch @@ -0,0 +1,95 @@ +From 58bf58e416a89ea5166865664887cfe4562b1fc0 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 26 Jun 2019 16:24:01 +0100 +Subject: [PATCH 2/2] iotests: Make 182 do without device_add +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Max Reitz +Message-id: <20190626162401.11112-2-mreitz@redhat.com> +Patchwork-id: 88951 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 1/1] iotests: Make 182 do without device_add +Bugzilla: 1707598 +RH-Acked-by: Kevin Wolf +RH-Acked-by: John Snow +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Stefan Hajnoczi + +182 fails if qemu has no support for hotplugging of a virtio-blk device. +Using an NBD server instead works just as well for the test, even on +qemus without hotplugging support. + +Fixes: 6d0a4a0fb5c8f10c8eb68b52cfda0082b00ae963 +Reported-by: Danilo C. L. de Paula +Signed-off-by: Max Reitz +Message-Id: <20190417153005.30096-1-mreitz@redhat.com> +Tested-by: Eric Blake +Reviewed-by: Eric Blake +Acked-by: Alberto Garcia +Signed-off-by: Eric Blake +(cherry picked from commit 8fabb8be37775ebb32b0d78bc7be815a29b8a107) +Signed-off-by: Max Reitz +Signed-off-by: Danilo C. L. de Paula +--- + tests/qemu-iotests/182 | 22 +++++++++++++++++----- + tests/qemu-iotests/182.out | 1 + + 2 files changed, 18 insertions(+), 5 deletions(-) + +diff --git a/tests/qemu-iotests/182 b/tests/qemu-iotests/182 +index 3b7689c..c1520ed 100755 +--- a/tests/qemu-iotests/182 ++++ b/tests/qemu-iotests/182 +@@ -32,6 +32,7 @@ _cleanup() + { + _cleanup_test_img + rm -f "$TEST_IMG.overlay" ++ rm -f "$TEST_DIR/nbd.socket" + } + trap "_cleanup; exit \$status" 0 1 2 3 15 + +@@ -127,15 +128,26 @@ success_or_failure=y _send_qemu_cmd $QEMU_HANDLE \ + 'return' \ + 'error' + +-# Now we attach the image to a virtio-blk device. This device does +-# require some permissions (at least WRITE and READ_CONSISTENT), so if ++# Start an NBD server to which we can attach node1 ++success_or_failure=y _send_qemu_cmd $QEMU_HANDLE \ ++ "{'execute': 'nbd-server-start', ++ 'arguments': { ++ 'addr': { ++ 'type': 'unix', ++ 'data': { ++ 'path': '$TEST_DIR/nbd.socket' ++ } } } }" \ ++ 'return' \ ++ 'error' ++ ++# Now we attach the image to the NBD server. This server does require ++# some permissions (at least WRITE and READ_CONSISTENT), so if + # reopening node0 unshared any (which it should not have), this will + # fail (but it should not). + success_or_failure=y _send_qemu_cmd $QEMU_HANDLE \ +- "{'execute': 'device_add', ++ "{'execute': 'nbd-server-add', + 'arguments': { +- 'driver': 'virtio-blk', +- 'drive': 'node1' ++ 'device': 'node1' + } }" \ + 'return' \ + 'error' +diff --git a/tests/qemu-iotests/182.out b/tests/qemu-iotests/182.out +index af501ca..33d41ee 100644 +--- a/tests/qemu-iotests/182.out ++++ b/tests/qemu-iotests/182.out +@@ -14,4 +14,5 @@ Formatting 'TEST_DIR/t.qcow2.overlay', fmt=qcow2 size=197120 backing_file=TEST_D + {"return": {}} + {"return": {}} + {"return": {}} ++{"return": {}} + *** done +-- +1.8.3.1 + diff --git a/SOURCES/kvm-iotests-Test-allocate_first_block-with-O_DIRECT.patch b/SOURCES/kvm-iotests-Test-allocate_first_block-with-O_DIRECT.patch new file mode 100644 index 0000000..b02cbbb --- /dev/null +++ b/SOURCES/kvm-iotests-Test-allocate_first_block-with-O_DIRECT.patch @@ -0,0 +1,108 @@ +From b4841fd40fefcffc99c4b52c8a06720edb4ef9ef Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 30 Aug 2019 12:56:28 +0100 +Subject: [PATCH 10/10] iotests: Test allocate_first_block() with O_DIRECT + +RH-Author: Thomas Huth +Message-id: <20190830125628.23668-6-thuth@redhat.com> +Patchwork-id: 90212 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v2 5/5] iotests: Test allocate_first_block() with O_DIRECT +Bugzilla: 1738839 +RH-Acked-by: Cornelia Huck +RH-Acked-by: Max Reitz +RH-Acked-by: David Hildenbrand + +From: Nir Soffer + +Using block_resize we can test allocate_first_block() with file +descriptor opened with O_DIRECT, ensuring that it works for any size +larger than 4096 bytes. + +Testing smaller sizes is tricky as the result depends on the filesystem +used for testing. For example on NFS any size will work since O_DIRECT +does not require any alignment. + +Signed-off-by: Nir Soffer +Reviewed-by: Max Reitz +Message-id: 20190827010528.8818-3-nsoffer@redhat.com +Signed-off-by: Max Reitz +(cherry picked from commit 4656fb5ebbece8c7bbca0bef56bea882c94b9132) +Signed-off-by: Danilo C. L. de Paula +--- + tests/qemu-iotests/175 | 28 ++++++++++++++++++++++++++++ + tests/qemu-iotests/175.out | 8 ++++++++ + 2 files changed, 36 insertions(+) + +diff --git a/tests/qemu-iotests/175 b/tests/qemu-iotests/175 +index b3b7712..74ca49d 100755 +--- a/tests/qemu-iotests/175 ++++ b/tests/qemu-iotests/175 +@@ -50,6 +50,23 @@ _filter_blocks() + -e "s/blocks=$((extra_blocks + img_size / 512))\\(\$\\|[^0-9]\\)/max allocation/" + } + ++# Resize image using block_resize. ++# Parameter 1: image path ++# Parameter 2: new size ++_block_resize() ++{ ++ local path=$1 ++ local size=$2 ++ ++ $QEMU -qmp stdio -nographic -nodefaults \ ++ -blockdev file,node-name=file,filename=$path,cache.direct=on \ ++ </dev/null ++ stat -c "size=%s, blocks=%b" $TEST_IMG | _filter_blocks $extra_blocks $min_blocks $new_size ++done ++ + # success, all done + echo "*** done" + rm -f $seq.full +diff --git a/tests/qemu-iotests/175.out b/tests/qemu-iotests/175.out +index 263e521..39c2ee0 100644 +--- a/tests/qemu-iotests/175.out ++++ b/tests/qemu-iotests/175.out +@@ -15,4 +15,12 @@ size=1048576, max allocation + == creating image with preallocation falloc == + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 preallocation=falloc + size=1048576, max allocation ++ ++== resize empty image with block_resize == ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=0 ++size=4096, min allocation ++ ++== resize empty image with block_resize == ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=0 ++size=1048576, min allocation + *** done +-- +1.8.3.1 + diff --git a/SOURCES/kvm-iotests-Test-unaligned-raw-images-with-O_DIRECT.patch b/SOURCES/kvm-iotests-Test-unaligned-raw-images-with-O_DIRECT.patch new file mode 100644 index 0000000..3aefe6f --- /dev/null +++ b/SOURCES/kvm-iotests-Test-unaligned-raw-images-with-O_DIRECT.patch @@ -0,0 +1,182 @@ +From d193f7ee2bf7822408fa9a92b7e170330b7f6ec4 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Tue, 23 Jul 2019 14:45:41 +0100 +Subject: [PATCH 03/14] iotests: Test unaligned raw images with O_DIRECT + +RH-Author: Max Reitz +Message-id: <20190723144546.23701-3-mreitz@redhat.com> +Patchwork-id: 89648 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 2/7] iotests: Test unaligned raw images with O_DIRECT +Bugzilla: 1678979 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Stefano Garzarella +RH-Acked-by: John Snow + +We already have 221 for accesses through the page cache, but it is +better to create a new file for O_DIRECT instead of integrating those +test cases into 221. This way, we can make use of +_supported_cache_modes (and _default_cache_mode) so the test is +automatically skipped on filesystems that do not support O_DIRECT. + +As part of the split, add _supported_cache_modes to 221. With that, it +no longer fails when run with -c none or -c directsync. + +Signed-off-by: Max Reitz +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +(cherry picked from commit 2fab30c80b33cdc6157c7efe6207e54b6835cf92) +Signed-off-by: Max Reitz +Signed-off-by: Danilo C. L. de Paula +--- + tests/qemu-iotests/221 | 4 +++ + tests/qemu-iotests/253 | 84 ++++++++++++++++++++++++++++++++++++++++++++++ + tests/qemu-iotests/253.out | 14 ++++++++ + tests/qemu-iotests/group | 1 + + 4 files changed, 103 insertions(+) + create mode 100755 tests/qemu-iotests/253 + create mode 100644 tests/qemu-iotests/253.out + +diff --git a/tests/qemu-iotests/221 b/tests/qemu-iotests/221 +index 41c4e4b..2cc29ba 100755 +--- a/tests/qemu-iotests/221 ++++ b/tests/qemu-iotests/221 +@@ -1,6 +1,7 @@ + #!/bin/bash + # + # Test qemu-img vs. unaligned images ++# (See also 253, which is the O_DIRECT version) + # + # Copyright (C) 2018 Red Hat, Inc. + # +@@ -38,6 +39,9 @@ _supported_fmt raw + _supported_proto file + _supported_os Linux + ++_default_cache_mode writeback ++_supported_cache_modes writeback writethrough unsafe ++ + echo + echo "=== Check mapping of unaligned raw image ===" + echo +diff --git a/tests/qemu-iotests/253 b/tests/qemu-iotests/253 +new file mode 100755 +index 0000000..d88d5af +--- /dev/null ++++ b/tests/qemu-iotests/253 +@@ -0,0 +1,84 @@ ++#!/usr/bin/env bash ++# ++# Test qemu-img vs. unaligned images; O_DIRECT version ++# (Originates from 221) ++# ++# Copyright (C) 2019 Red Hat, Inc. ++# ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 2 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program. If not, see . ++# ++ ++seq="$(basename $0)" ++echo "QA output created by $seq" ++ ++status=1 # failure is the default! ++ ++_cleanup() ++{ ++ _cleanup_test_img ++} ++trap "_cleanup; exit \$status" 0 1 2 3 15 ++ ++# get standard environment, filters and checks ++. ./common.rc ++. ./common.filter ++ ++_supported_fmt raw ++_supported_proto file ++_supported_os Linux ++ ++_default_cache_mode none ++_supported_cache_modes none directsync ++ ++echo ++echo "=== Check mapping of unaligned raw image ===" ++echo ++ ++# We do not know how large a physical sector is, but it is certainly ++# going to be a factor of 1 MB ++size=$((1 * 1024 * 1024 - 1)) ++ ++# qemu-img create rounds size up to BDRV_SECTOR_SIZE ++_make_test_img $size ++$QEMU_IMG map --output=json --image-opts \ ++ "driver=$IMGFMT,file.driver=file,file.filename=$TEST_IMG,cache.direct=on" \ ++ | _filter_qemu_img_map ++ ++# so we resize it and check again ++truncate --size=$size "$TEST_IMG" ++$QEMU_IMG map --output=json --image-opts \ ++ "driver=$IMGFMT,file.driver=file,file.filename=$TEST_IMG,cache.direct=on" \ ++ | _filter_qemu_img_map ++ ++# qemu-io with O_DIRECT always writes whole physical sectors. Again, ++# we do not know how large a physical sector is, so we just start ++# writing from a 64 kB boundary, which should always be aligned. ++offset=$((1 * 1024 * 1024 - 64 * 1024)) ++$QEMU_IO -c "w $offset $((size - offset))" "$TEST_IMG" | _filter_qemu_io ++$QEMU_IMG map --output=json --image-opts \ ++ "driver=$IMGFMT,file.driver=file,file.filename=$TEST_IMG,cache.direct=on" \ ++ | _filter_qemu_img_map ++ ++# Resize it and check again -- contrary to 221, we may not get partial ++# sectors here, so there should be only two areas (one zero, one ++# data). ++truncate --size=$size "$TEST_IMG" ++$QEMU_IMG map --output=json --image-opts \ ++ "driver=$IMGFMT,file.driver=file,file.filename=$TEST_IMG,cache.direct=on" \ ++ | _filter_qemu_img_map ++ ++# success, all done ++echo '*** done' ++rm -f $seq.full ++status=0 +diff --git a/tests/qemu-iotests/253.out b/tests/qemu-iotests/253.out +new file mode 100644 +index 0000000..607c0ba +--- /dev/null ++++ b/tests/qemu-iotests/253.out +@@ -0,0 +1,14 @@ ++QA output created by 253 ++ ++=== Check mapping of unaligned raw image === ++ ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048575 ++[{ "start": 0, "length": 1048576, "depth": 0, "zero": true, "data": false, "offset": OFFSET}] ++[{ "start": 0, "length": 1048576, "depth": 0, "zero": true, "data": false, "offset": OFFSET}] ++wrote 65535/65535 bytes at offset 983040 ++63.999 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++[{ "start": 0, "length": 983040, "depth": 0, "zero": true, "data": false, "offset": OFFSET}, ++{ "start": 983040, "length": 65536, "depth": 0, "zero": false, "data": true, "offset": OFFSET}] ++[{ "start": 0, "length": 983040, "depth": 0, "zero": true, "data": false, "offset": OFFSET}, ++{ "start": 983040, "length": 65536, "depth": 0, "zero": false, "data": true, "offset": OFFSET}] ++*** done +diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group +index 5cbdc24..b356d82 100644 +--- a/tests/qemu-iotests/group ++++ b/tests/qemu-iotests/group +@@ -227,3 +227,4 @@ + 232 auto quick + 234 auto quick migration + 240 auto quick ++253 rw auto quick +-- +1.8.3.1 + diff --git a/SOURCES/kvm-iotests-Tweak-221-sizing-for-different-hole-granular.patch b/SOURCES/kvm-iotests-Tweak-221-sizing-for-different-hole-granular.patch new file mode 100644 index 0000000..228841b --- /dev/null +++ b/SOURCES/kvm-iotests-Tweak-221-sizing-for-different-hole-granular.patch @@ -0,0 +1,101 @@ +From 6f5c54a54c05143cf9f69a626b398886d1c51358 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 30 Aug 2019 12:56:25 +0100 +Subject: [PATCH 07/10] iotests: Tweak 221 sizing for different hole + granularities + +RH-Author: Thomas Huth +Message-id: <20190830125628.23668-3-thuth@redhat.com> +Patchwork-id: 90213 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v2 2/5] iotests: Tweak 221 sizing for different hole granularities +Bugzilla: 1738839 +RH-Acked-by: Cornelia Huck +RH-Acked-by: Max Reitz +RH-Acked-by: David Hildenbrand + +From: Eric Blake + +For some particular configurations of ext4, sizing an image to 84 +sectors + 1 byte causes test failures when the size of the hole is +rounded to a 4k alignment. Let's instead size things to 128 sectors + +1 byte, as the 64k boundary is more likely to work with various hole +granularities. + +Reported-by: Thomas Huth +Signed-off-by: Eric Blake +Message-Id: <20190506172111.31594-1-eblake@redhat.com> +Tested-by: Thomas Huth +(cherry picked from commit d3192de752cd6d383d38e50341b39d9550d21fa8) +Signed-off-by: Danilo C. L. de Paula +--- + tests/qemu-iotests/221 | 10 +++++----- + tests/qemu-iotests/221.out | 20 ++++++++++---------- + 2 files changed, 15 insertions(+), 15 deletions(-) + +diff --git a/tests/qemu-iotests/221 b/tests/qemu-iotests/221 +index 2cc29ba..75aa192 100755 +--- a/tests/qemu-iotests/221 ++++ b/tests/qemu-iotests/221 +@@ -3,7 +3,7 @@ + # Test qemu-img vs. unaligned images + # (See also 253, which is the O_DIRECT version) + # +-# Copyright (C) 2018 Red Hat, Inc. ++# Copyright (C) 2018-2019 Red Hat, Inc. + # + # This program is free software; you can redistribute it and/or modify + # it under the terms of the GNU General Public License as published by +@@ -46,16 +46,16 @@ echo + echo "=== Check mapping of unaligned raw image ===" + echo + +-_make_test_img 43009 # qemu-img create rounds size up ++_make_test_img 65537 # qemu-img create rounds size up + $QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map + +-truncate --size=43009 "$TEST_IMG" # so we resize it and check again ++truncate --size=65537 "$TEST_IMG" # so we resize it and check again + $QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map + +-$QEMU_IO -c 'w 43008 1' "$TEST_IMG" | _filter_qemu_io # writing also rounds up ++$QEMU_IO -c 'w 65536 1' "$TEST_IMG" | _filter_qemu_io # writing also rounds up + $QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map + +-truncate --size=43009 "$TEST_IMG" # so we resize it and check again ++truncate --size=65537 "$TEST_IMG" # so we resize it and check again + $QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map + + # success, all done +diff --git a/tests/qemu-iotests/221.out b/tests/qemu-iotests/221.out +index a9c0190..9f9dd52 100644 +--- a/tests/qemu-iotests/221.out ++++ b/tests/qemu-iotests/221.out +@@ -2,15 +2,15 @@ QA output created by 221 + + === Check mapping of unaligned raw image === + +-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=43009 +-[{ "start": 0, "length": 43520, "depth": 0, "zero": true, "data": false, "offset": OFFSET}] +-[{ "start": 0, "length": 43520, "depth": 0, "zero": true, "data": false, "offset": OFFSET}] +-wrote 1/1 bytes at offset 43008 ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=65537 ++[{ "start": 0, "length": 66048, "depth": 0, "zero": true, "data": false, "offset": OFFSET}] ++[{ "start": 0, "length": 66048, "depth": 0, "zero": true, "data": false, "offset": OFFSET}] ++wrote 1/1 bytes at offset 65536 + 1 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +-[{ "start": 0, "length": 40960, "depth": 0, "zero": true, "data": false, "offset": OFFSET}, +-{ "start": 40960, "length": 2049, "depth": 0, "zero": false, "data": true, "offset": OFFSET}, +-{ "start": 43009, "length": 511, "depth": 0, "zero": true, "data": false, "offset": OFFSET}] +-[{ "start": 0, "length": 40960, "depth": 0, "zero": true, "data": false, "offset": OFFSET}, +-{ "start": 40960, "length": 2049, "depth": 0, "zero": false, "data": true, "offset": OFFSET}, +-{ "start": 43009, "length": 511, "depth": 0, "zero": true, "data": false, "offset": OFFSET}] ++[{ "start": 0, "length": 65536, "depth": 0, "zero": true, "data": false, "offset": OFFSET}, ++{ "start": 65536, "length": 1, "depth": 0, "zero": false, "data": true, "offset": OFFSET}, ++{ "start": 65537, "length": 511, "depth": 0, "zero": true, "data": false, "offset": OFFSET}] ++[{ "start": 0, "length": 65536, "depth": 0, "zero": true, "data": false, "offset": OFFSET}, ++{ "start": 65536, "length": 1, "depth": 0, "zero": false, "data": true, "offset": OFFSET}, ++{ "start": 65537, "length": 511, "depth": 0, "zero": true, "data": false, "offset": OFFSET}] + *** done +-- +1.8.3.1 + diff --git a/SOURCES/kvm-iotests-Unify-log-outputs-between-Python-2-and-3.patch b/SOURCES/kvm-iotests-Unify-log-outputs-between-Python-2-and-3.patch new file mode 100644 index 0000000..d53070c --- /dev/null +++ b/SOURCES/kvm-iotests-Unify-log-outputs-between-Python-2-and-3.patch @@ -0,0 +1,2136 @@ +From f58a88cc157331a911eb2cf1faee6d494b0c9333 Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Mon, 8 Jul 2019 15:25:59 +0100 +Subject: [PATCH 13/39] iotests: Unify log outputs between Python 2 and 3 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Pino Toscano +Message-id: <20190708152601.21123-9-ptoscano@redhat.com> +Patchwork-id: 89420 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v3 08/10] iotests: Unify log outputs between Python 2 and 3 +Bugzilla: 1513367 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Max Reitz +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Markus Armbruster + +From: Max Reitz + +When dumping an object into the log, there are differences between +Python 2 and 3. First, unicode strings are prefixed by 'u' in Python 2 +(they are no longer in 3, because unicode strings are the default +there). Second, the order of keys in dicts may differ. Third, +especially long numbers are longs in Python 2 and thus get an 'L' +suffix, which does not happen in Python 3. + +We can get around all of these differences by dumping objects (lists and +dicts) in a language-independent format, namely JSON. The JSON +generator even allows emitting dicts with their keys sorted +alphabetically. + +This changes the output of all tests that use these logging functions +(dict keys are ordered now, strings in dicts are now enclosed in double +quotes instead of single quotes, the 'L' suffix of large integers is +dropped, and "true" and "false" are now in lower case). +The quote change necessitates a small change to a filter used in test +207. + +Suggested-by: Eduardo Habkost +Signed-off-by: Max Reitz +Reviewed-by: Cleber Rosa +Message-Id: <20181022135307.14398-10-mreitz@redhat.com> +Signed-off-by: Eduardo Habkost +(cherry picked from commit e21b5f34d669b82087597273f3783626947291a0) +Signed-off-by: Pino Toscano +Signed-off-by: Danilo C. L. de Paula +--- + tests/qemu-iotests/194.out | 22 +- + tests/qemu-iotests/202.out | 12 +- + tests/qemu-iotests/203.out | 14 +- + tests/qemu-iotests/206.out | 218 ++++++++--------- + tests/qemu-iotests/207 | 2 +- + tests/qemu-iotests/207.out | 72 +++--- + tests/qemu-iotests/208.out | 8 +- + tests/qemu-iotests/210.out | 94 ++++---- + tests/qemu-iotests/211.out | 102 ++++---- + tests/qemu-iotests/212.out | 174 +++++++------- + tests/qemu-iotests/213.out | 182 +++++++-------- + tests/qemu-iotests/216.out | 4 +- + tests/qemu-iotests/218.out | 20 +- + tests/qemu-iotests/219.out | 526 +++++++++++++++++++++--------------------- + tests/qemu-iotests/222.out | 24 +- + tests/qemu-iotests/iotests.py | 10 +- + 16 files changed, 744 insertions(+), 740 deletions(-) + +diff --git a/tests/qemu-iotests/194.out b/tests/qemu-iotests/194.out +index 50ac50d..7185785 100644 +--- a/tests/qemu-iotests/194.out ++++ b/tests/qemu-iotests/194.out +@@ -1,18 +1,18 @@ + Launching VMs... + Launching NBD server on destination... +-{u'return': {}} +-{u'return': {}} ++{"return": {}} ++{"return": {}} + Starting `drive-mirror` on source... +-{u'return': {}} ++{"return": {}} + Waiting for `drive-mirror` to complete... +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'device': u'mirror-job0', u'type': u'mirror', u'speed': 0, u'len': 1073741824, u'offset': 1073741824}, u'event': u'BLOCK_JOB_READY'} ++{"data": {"device": "mirror-job0", "len": 1073741824, "offset": 1073741824, "speed": 0, "type": "mirror"}, "event": "BLOCK_JOB_READY", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} + Starting migration... +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'setup'}, u'event': u'MIGRATION'} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'active'}, u'event': u'MIGRATION'} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'completed'}, u'event': u'MIGRATION'} ++{"return": {}} ++{"data": {"status": "setup"}, "event": "MIGRATION", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"data": {"status": "active"}, "event": "MIGRATION", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"data": {"status": "completed"}, "event": "MIGRATION", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} + Gracefully ending the `drive-mirror` job on source... +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'device': u'mirror-job0', u'type': u'mirror', u'speed': 0, u'len': 1073741824, u'offset': 1073741824}, u'event': u'BLOCK_JOB_COMPLETED'} ++{"return": {}} ++{"data": {"device": "mirror-job0", "len": 1073741824, "offset": 1073741824, "speed": 0, "type": "mirror"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} + Stopping the NBD server on destination... +-{u'return': {}} ++{"return": {}} +diff --git a/tests/qemu-iotests/202.out b/tests/qemu-iotests/202.out +index d5ea374..9a8619e 100644 +--- a/tests/qemu-iotests/202.out ++++ b/tests/qemu-iotests/202.out +@@ -1,11 +1,11 @@ + Launching VM... + Adding IOThread... +-{u'return': {}} ++{"return": {}} + Adding blockdevs... +-{u'return': {}} +-{u'return': {}} ++{"return": {}} ++{"return": {}} + Setting iothread... +-{u'return': {}} +-{u'return': {}} ++{"return": {}} ++{"return": {}} + Creating external snapshots... +-{u'return': {}} ++{"return": {}} +diff --git a/tests/qemu-iotests/203.out b/tests/qemu-iotests/203.out +index 1a11f09..9d4abba 100644 +--- a/tests/qemu-iotests/203.out ++++ b/tests/qemu-iotests/203.out +@@ -1,11 +1,11 @@ + Launching VM... + Setting IOThreads... +-{u'return': {}} +-{u'return': {}} ++{"return": {}} ++{"return": {}} + Enabling migration QMP events... +-{u'return': {}} ++{"return": {}} + Starting migration... +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'setup'}, u'event': u'MIGRATION'} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'active'}, u'event': u'MIGRATION'} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'completed'}, u'event': u'MIGRATION'} ++{"return": {}} ++{"data": {"status": "setup"}, "event": "MIGRATION", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"data": {"status": "active"}, "event": "MIGRATION", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"data": {"status": "completed"}, "event": "MIGRATION", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +diff --git a/tests/qemu-iotests/206.out b/tests/qemu-iotests/206.out +index 789eebe..91f4db5 100644 +--- a/tests/qemu-iotests/206.out ++++ b/tests/qemu-iotests/206.out +@@ -1,16 +1,16 @@ + === Successful image creation (defaults) === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.qcow2'}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} +- +-{'execute': 'blockdev-add', 'arguments': {'node_name': 'imgfile', 'driver': 'file', 'filename': 'TEST_DIR/PID-t.qcow2'}} +-{u'return': {}} +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'qcow2', 'file': 'imgfile', 'size': 134217728}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "size": 0}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} ++ ++{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "node_name": "imgfile"}} ++{"return": {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "imgfile", "size": 134217728}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + image: TEST_IMG + file format: IMGFMT +@@ -24,15 +24,15 @@ Format specific information: + + === Successful image creation (inline blockdev-add, explicit defaults) === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'nocow': False, 'preallocation': 'off', 'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.qcow2'}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "nocow": false, "preallocation": "off", "size": 0}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 65536, 'refcount-bits': 16, 'version': 'v3', 'preallocation': 'off', 'file': {'driver': 'file', 'filename': 'TEST_DIR/PID-t.qcow2'}, 'lazy-refcounts': False, 'driver': 'qcow2', 'size': 67108864}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 65536, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2"}, "lazy-refcounts": false, "preallocation": "off", "refcount-bits": 16, "size": 67108864, "version": "v3"}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + image: TEST_IMG + file format: IMGFMT +@@ -46,15 +46,15 @@ Format specific information: + + === Successful image creation (v3 non-default options) === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'nocow': True, 'preallocation': 'falloc', 'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.qcow2'}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "nocow": true, "preallocation": "falloc", "size": 0}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 2097152, 'refcount-bits': 1, 'version': 'v3', 'preallocation': 'metadata', 'file': {'driver': 'file', 'filename': 'TEST_DIR/PID-t.qcow2'}, 'lazy-refcounts': True, 'driver': 'qcow2', 'size': 33554432}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 2097152, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2"}, "lazy-refcounts": true, "preallocation": "metadata", "refcount-bits": 1, "size": 33554432, "version": "v3"}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + image: TEST_IMG + file format: IMGFMT +@@ -68,15 +68,15 @@ Format specific information: + + === Successful image creation (v2 non-default options) === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.qcow2'}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "size": 0}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 512, 'backing-fmt': 'qcow2', 'driver': 'qcow2', 'version': 'v2', 'file': {'driver': 'file', 'filename': 'TEST_DIR/PID-t.qcow2'}, 'backing-file': 'TEST_DIR/PID-t.qcow2.base', 'size': 33554432}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"backing-file": "TEST_DIR/PID-t.qcow2.base", "backing-fmt": "qcow2", "cluster-size": 512, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2"}, "size": 33554432, "version": "v2"}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + image: TEST_IMG + file format: IMGFMT +@@ -90,10 +90,10 @@ Format specific information: + + === Successful image creation (encrypted) === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'encrypt': {'key-secret': 'keysec0', 'iter-time': 10, 'cipher-mode': 'ctr', 'ivgen-hash-alg': 'md5', 'cipher-alg': 'twofish-128', 'format': 'luks', 'ivgen-alg': 'plain64', 'hash-alg': 'sha1'}, 'driver': 'qcow2', 'file': {'driver': 'file', 'filename': 'TEST_DIR/PID-t.qcow2'}, 'size': 33554432}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "encrypt": {"cipher-alg": "twofish-128", "cipher-mode": "ctr", "format": "luks", "hash-alg": "sha1", "iter-time": 10, "ivgen-alg": "plain64", "ivgen-hash-alg": "md5", "key-secret": "keysec0"}, "file": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2"}, "size": 33554432}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + image: TEST_IMG + file format: IMGFMT +@@ -144,113 +144,113 @@ Format specific information: + + === Invalid BlockdevRef === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'qcow2', 'file': "this doesn't exist", 'size': 33554432}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "this doesn't exist", "size": 33554432}}} ++{"return": {}} + Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exist +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + === Invalid sizes === +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'qcow2', 'file': 'node0', 'size': 1234}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 1234}}} ++{"return": {}} + Job failed: Image size must be a multiple of 512 bytes +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'qcow2', 'file': 'node0', 'size': 18446744073709551104L}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 18446744073709551104}}} ++{"return": {}} + Job failed: Could not resize image: Image size cannot be negative +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'qcow2', 'file': 'node0', 'size': 9223372036854775808L}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 9223372036854775808}}} ++{"return": {}} + Job failed: Could not resize image: Image size cannot be negative +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'qcow2', 'file': 'node0', 'size': 9223372036854775296}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 9223372036854775296}}} ++{"return": {}} + Job failed: Could not resize image: Failed to grow the L1 table: File too large +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + === Invalid version === +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'version': 'v1', 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}} +-{u'error': {u'class': u'GenericError', u'desc': u"Invalid parameter 'v1'"}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 67108864, "version": "v1"}}} ++{"error": {"class": "GenericError", "desc": "Invalid parameter 'v1'"}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'lazy-refcounts': True, 'version': 'v2', 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "lazy-refcounts": true, "size": 67108864, "version": "v2"}}} ++{"return": {}} + Job failed: Lazy refcounts only supported with compatibility level 1.1 and above (use version=v3 or greater) +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'refcount-bits': 8, 'version': 'v2', 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "refcount-bits": 8, "size": 67108864, "version": "v2"}}} ++{"return": {}} + Job failed: Different refcount widths than 16 bits require compatibility level 1.1 or above (use version=v3 or greater) +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + === Invalid backing file options === +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'preallocation': 'full', 'driver': 'qcow2', 'backing-file': '/dev/null', 'file': 'node0', 'size': 67108864}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"backing-file": "/dev/null", "driver": "qcow2", "file": "node0", "preallocation": "full", "size": 67108864}}} ++{"return": {}} + Job failed: Backing file and preallocation cannot be used at the same time +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'backing-fmt': 'qcow2', 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"backing-fmt": "qcow2", "driver": "qcow2", "file": "node0", "size": 67108864}}} ++{"return": {}} + Job failed: Backing format cannot be used without backing file +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + === Invalid cluster size === +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 1234, 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 1234, "driver": "qcow2", "file": "node0", "size": 67108864}}} ++{"return": {}} + Job failed: Cluster size must be a power of two between 512 and 2048k +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 128, 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 128, "driver": "qcow2", "file": "node0", "size": 67108864}}} ++{"return": {}} + Job failed: Cluster size must be a power of two between 512 and 2048k +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 4194304, 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 4194304, "driver": "qcow2", "file": "node0", "size": 67108864}}} ++{"return": {}} + Job failed: Cluster size must be a power of two between 512 and 2048k +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 0, 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 0, "driver": "qcow2", "file": "node0", "size": 67108864}}} ++{"return": {}} + Job failed: Cluster size must be a power of two between 512 and 2048k +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 512, 'driver': 'qcow2', 'file': 'node0', 'size': 281474976710656}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 512, "driver": "qcow2", "file": "node0", "size": 281474976710656}}} ++{"return": {}} + Job failed: Could not resize image: Failed to grow the L1 table: File too large +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + === Invalid refcount width === +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'refcount-bits': 128, 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "refcount-bits": 128, "size": 67108864}}} ++{"return": {}} + Job failed: Refcount width must be a power of two and may not exceed 64 bits +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'refcount-bits': 0, 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "refcount-bits": 0, "size": 67108864}}} ++{"return": {}} + Job failed: Refcount width must be a power of two and may not exceed 64 bits +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'refcount-bits': 7, 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "refcount-bits": 7, "size": 67108864}}} ++{"return": {}} + Job failed: Refcount width must be a power of two and may not exceed 64 bits +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +diff --git a/tests/qemu-iotests/207 b/tests/qemu-iotests/207 +index d45bf72..aaad656 100755 +--- a/tests/qemu-iotests/207 ++++ b/tests/qemu-iotests/207 +@@ -28,7 +28,7 @@ iotests.verify_image_format(supported_fmts=['raw']) + iotests.verify_protocol(supported=['ssh']) + + def filter_hash(msg): +- return re.sub("'hash': '[0-9a-f]+'", "'hash': HASH", msg) ++ return re.sub('"hash": "[0-9a-f]+"', '"hash": HASH', msg) + + def blockdev_create(vm, options): + result = vm.qmp_log('blockdev-create', job_id='job0', options=options, +diff --git a/tests/qemu-iotests/207.out b/tests/qemu-iotests/207.out +index fc131a6..789b465 100644 +--- a/tests/qemu-iotests/207.out ++++ b/tests/qemu-iotests/207.out +@@ -1,9 +1,9 @@ + === Successful image creation (defaults) === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/PID-t.img', 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 4194304}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 4194304}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + image: TEST_IMG + file format: IMGFMT +@@ -16,49 +16,49 @@ virtual size: 4.0M (4194304 bytes) + + === Test host-key-check options === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/PID-t.img', 'host-key-check': {'mode': 'none'}, 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 8388608}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"mode": "none"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 8388608}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + image: TEST_IMG + file format: IMGFMT + virtual size: 8.0M (8388608 bytes) + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/PID-t.img', 'host-key-check': {'mode': 'known_hosts'}, 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 4194304}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"mode": "known_hosts"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 4194304}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + image: TEST_IMG + file format: IMGFMT + virtual size: 4.0M (4194304 bytes) + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/PID-t.img', 'host-key-check': {'hash': 'wrong', 'type': 'md5', 'mode': 'hash'}, 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 2097152}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"hash": "wrong", "mode": "hash", "type": "md5"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 2097152}}} ++{"return": {}} + Job failed: remote host key does not match host_key_check 'wrong' +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/PID-t.img', 'host-key-check': {'hash': HASH, 'type': 'md5', 'mode': 'hash'}, 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 8388608}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"hash": HASH, "mode": "hash", "type": "md5"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 8388608}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + image: TEST_IMG + file format: IMGFMT + virtual size: 8.0M (8388608 bytes) + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/PID-t.img', 'host-key-check': {'hash': 'wrong', 'type': 'sha1', 'mode': 'hash'}, 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 2097152}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"hash": "wrong", "mode": "hash", "type": "sha1"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 2097152}}} ++{"return": {}} + Job failed: remote host key does not match host_key_check 'wrong' +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/PID-t.img', 'host-key-check': {'hash': HASH, 'type': 'sha1', 'mode': 'hash'}, 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 4194304}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"hash": HASH, "mode": "hash", "type": "sha1"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 4194304}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + image: TEST_IMG + file format: IMGFMT +@@ -66,15 +66,15 @@ virtual size: 4.0M (4194304 bytes) + + === Invalid path and user === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': '/this/is/not/an/existing/path', 'host-key-check': {'mode': 'none'}, 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 4194304}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"mode": "none"}, "path": "/this/is/not/an/existing/path", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 4194304}}} ++{"return": {}} + Job failed: failed to open remote file '/this/is/not/an/existing/path': Failed opening remote file (libssh2 error code: -31) +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/PID-t.img', 'host-key-check': {'mode': 'none'}, 'user': 'invalid user', 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 4194304}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"mode": "none"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}, "user": "invalid user"}, "size": 4194304}}} ++{"return": {}} + Job failed: failed to authenticate using publickey authentication and the identities held by your ssh-agent +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +diff --git a/tests/qemu-iotests/208.out b/tests/qemu-iotests/208.out +index 3687e9d..9ff2582 100644 +--- a/tests/qemu-iotests/208.out ++++ b/tests/qemu-iotests/208.out +@@ -1,9 +1,9 @@ + Launching VM... + Starting NBD server... +-{u'return': {}} ++{"return": {}} + Adding NBD export... +-{u'return': {}} ++{"return": {}} + Creating external snapshot... +-{u'return': {}} ++{"return": {}} + Stopping NBD server... +-{u'return': {}} ++{"return": {}} +diff --git a/tests/qemu-iotests/210.out b/tests/qemu-iotests/210.out +index 078ba54..923cb05 100644 +--- a/tests/qemu-iotests/210.out ++++ b/tests/qemu-iotests/210.out +@@ -1,16 +1,16 @@ + === Successful image creation (defaults) === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.luks'}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} +- +-{'execute': 'blockdev-add', 'arguments': {'node_name': 'imgfile', 'driver': 'file', 'filename': 'TEST_DIR/PID-t.luks'}} +-{u'return': {}} +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'key-secret': 'keysec0', 'iter-time': 10, 'driver': 'luks', 'file': 'imgfile', 'size': 134217728}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.luks", "size": 0}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} ++ ++{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.luks", "node_name": "imgfile"}} ++{"return": {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "luks", "file": "imgfile", "iter-time": 10, "key-secret": "keysec0", "size": 134217728}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + image: json:{"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_IMG"}, "key-secret": "keysec0"} + file format: IMGFMT +@@ -54,15 +54,15 @@ Format specific information: + + === Successful image creation (with non-default options) === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.luks'}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.luks", "size": 0}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'key-secret': 'keysec0', 'hash-alg': 'sha1', 'cipher-mode': 'ctr', 'cipher-alg': 'twofish-128', 'file': {'driver': 'file', 'filename': 'TEST_DIR/PID-t.luks'}, 'iter-time': 10, 'ivgen-alg': 'plain64', 'ivgen-hash-alg': 'md5', 'driver': 'luks', 'size': 67108864}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cipher-alg": "twofish-128", "cipher-mode": "ctr", "driver": "luks", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.luks"}, "hash-alg": "sha1", "iter-time": 10, "ivgen-alg": "plain64", "ivgen-hash-alg": "md5", "key-secret": "keysec0", "size": 67108864}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + image: json:{"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_IMG"}, "key-secret": "keysec0"} + file format: IMGFMT +@@ -106,18 +106,18 @@ Format specific information: + + === Invalid BlockdevRef === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'luks', 'file': "this doesn't exist", 'size': 67108864}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "luks", "file": "this doesn't exist", "size": 67108864}}} ++{"return": {}} + Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exist +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + === Zero size === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'key-secret': 'keysec0', 'iter-time': 10, 'driver': 'luks', 'file': 'node0', 'size': 0}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "luks", "file": "node0", "iter-time": 10, "key-secret": "keysec0", "size": 0}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + image: json:{"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_IMG"}, "key-secret": "keysec0"} + file format: IMGFMT +@@ -161,34 +161,34 @@ Format specific information: + + === Invalid sizes === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'key-secret': 'keysec0', 'driver': 'luks', 'file': 'node0', 'size': 18446744073709551104L}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "luks", "file": "node0", "key-secret": "keysec0", "size": 18446744073709551104}}} ++{"return": {}} + Job failed: The requested file size is too large +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'key-secret': 'keysec0', 'driver': 'luks', 'file': 'node0', 'size': 9223372036854775808L}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "luks", "file": "node0", "key-secret": "keysec0", "size": 9223372036854775808}}} ++{"return": {}} + Job failed: The requested file size is too large +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'key-secret': 'keysec0', 'driver': 'luks', 'file': 'node0', 'size': 9223372036854775296}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "luks", "file": "node0", "key-secret": "keysec0", "size": 9223372036854775296}}} ++{"return": {}} + Job failed: The requested file size is too large +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + === Resize image with invalid sizes === + +-{'execute': 'block_resize', 'arguments': {'size': 9223372036854775296, 'node_name': 'node1'}} +-{u'error': {u'class': u'GenericError', u'desc': u'The requested file size is too large'}} +-{'execute': 'block_resize', 'arguments': {'size': 9223372036854775808L, 'node_name': 'node1'}} +-{u'error': {u'class': u'GenericError', u'desc': u"Invalid parameter type for 'size', expected: integer"}} +-{'execute': 'block_resize', 'arguments': {'size': 18446744073709551104L, 'node_name': 'node1'}} +-{u'error': {u'class': u'GenericError', u'desc': u"Invalid parameter type for 'size', expected: integer"}} +-{'execute': 'block_resize', 'arguments': {'size': -9223372036854775808, 'node_name': 'node1'}} +-{u'error': {u'class': u'GenericError', u'desc': u"Parameter 'size' expects a >0 size"}} ++{"execute": "block_resize", "arguments": {"node_name": "node1", "size": 9223372036854775296}} ++{"error": {"class": "GenericError", "desc": "The requested file size is too large"}} ++{"execute": "block_resize", "arguments": {"node_name": "node1", "size": 9223372036854775808}} ++{"error": {"class": "GenericError", "desc": "Invalid parameter type for 'size', expected: integer"}} ++{"execute": "block_resize", "arguments": {"node_name": "node1", "size": 18446744073709551104}} ++{"error": {"class": "GenericError", "desc": "Invalid parameter type for 'size', expected: integer"}} ++{"execute": "block_resize", "arguments": {"node_name": "node1", "size": -9223372036854775808}} ++{"error": {"class": "GenericError", "desc": "Parameter 'size' expects a >0 size"}} + image: json:{"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_IMG"}, "key-secret": "keysec0"} + file format: IMGFMT + virtual size: 0 (0 bytes) +diff --git a/tests/qemu-iotests/211.out b/tests/qemu-iotests/211.out +index 6feaea3..eebb0ea 100644 +--- a/tests/qemu-iotests/211.out ++++ b/tests/qemu-iotests/211.out +@@ -1,16 +1,16 @@ + === Successful image creation (defaults) === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.vdi'}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} +- +-{'execute': 'blockdev-add', 'arguments': {'node_name': 'imgfile', 'driver': 'file', 'filename': 'TEST_DIR/PID-t.vdi'}} +-{u'return': {}} +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vdi', 'file': 'imgfile', 'size': 134217728}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi", "size": 0}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} ++ ++{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi", "node_name": "imgfile"}} ++{"return": {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": "imgfile", "size": 134217728}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + image: TEST_IMG + file format: IMGFMT +@@ -21,15 +21,15 @@ cluster_size: 1048576 + + === Successful image creation (explicit defaults) === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.vdi'}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi", "size": 0}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'preallocation': 'off', 'driver': 'vdi', 'file': {'driver': 'file', 'filename': 'TEST_DIR/PID-t.vdi'}, 'size': 67108864}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi"}, "preallocation": "off", "size": 67108864}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + image: TEST_IMG + file format: IMGFMT +@@ -40,15 +40,15 @@ cluster_size: 1048576 + + === Successful image creation (with non-default options) === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.vdi'}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi", "size": 0}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'preallocation': 'metadata', 'driver': 'vdi', 'file': {'driver': 'file', 'filename': 'TEST_DIR/PID-t.vdi'}, 'size': 33554432}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi"}, "preallocation": "metadata", "size": 33554432}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + image: TEST_IMG + file format: IMGFMT +@@ -60,18 +60,18 @@ cluster_size: 1048576 + + === Invalid BlockdevRef === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vdi', 'file': "this doesn't exist", 'size': 33554432}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": "this doesn't exist", "size": 33554432}}} ++{"return": {}} + Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exist +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + === Zero size === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vdi', 'file': 'node0', 'size': 0}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": "node0", "size": 0}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + image: TEST_IMG + file format: IMGFMT +@@ -80,10 +80,10 @@ cluster_size: 1048576 + + === Maximum size === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vdi', 'file': 'node0', 'size': 562949819203584}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": "node0", "size": 562949819203584}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + image: TEST_IMG + file format: IMGFMT +@@ -92,21 +92,21 @@ cluster_size: 1048576 + + === Invalid sizes === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vdi', 'file': 'node0', 'size': 18446744073709551104L}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": "node0", "size": 18446744073709551104}}} ++{"return": {}} + Job failed: Unsupported VDI image size (size is 0xfffffffffffffe00, max supported is 0x1fffff8000000) +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vdi', 'file': 'node0', 'size': 9223372036854775808L}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": "node0", "size": 9223372036854775808}}} ++{"return": {}} + Job failed: Unsupported VDI image size (size is 0x8000000000000000, max supported is 0x1fffff8000000) +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vdi', 'file': 'node0', 'size': 562949819203585}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": "node0", "size": 562949819203585}}} ++{"return": {}} + Job failed: Unsupported VDI image size (size is 0x1fffff8000001, max supported is 0x1fffff8000000) +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +diff --git a/tests/qemu-iotests/212.out b/tests/qemu-iotests/212.out +index 9150da7..01da467 100644 +--- a/tests/qemu-iotests/212.out ++++ b/tests/qemu-iotests/212.out +@@ -1,16 +1,16 @@ + === Successful image creation (defaults) === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.parallels'}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} +- +-{'execute': 'blockdev-add', 'arguments': {'node_name': 'imgfile', 'driver': 'file', 'filename': 'TEST_DIR/PID-t.parallels'}} +-{u'return': {}} +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': 'imgfile', 'size': 134217728}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels", "size": 0}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} ++ ++{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels", "node_name": "imgfile"}} ++{"return": {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "imgfile", "size": 134217728}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + image: TEST_IMG + file format: IMGFMT +@@ -18,15 +18,15 @@ virtual size: 128M (134217728 bytes) + + === Successful image creation (explicit defaults) === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.parallels'}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels", "size": 0}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 1048576, 'driver': 'parallels', 'file': {'driver': 'file', 'filename': 'TEST_DIR/PID-t.parallels'}, 'size': 67108864}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 1048576, "driver": "parallels", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels"}, "size": 67108864}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + image: TEST_IMG + file format: IMGFMT +@@ -34,15 +34,15 @@ virtual size: 64M (67108864 bytes) + + === Successful image creation (with non-default options) === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.parallels'}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels", "size": 0}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 65536, 'driver': 'parallels', 'file': {'driver': 'file', 'filename': 'TEST_DIR/PID-t.parallels'}, 'size': 33554432}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 65536, "driver": "parallels", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels"}, "size": 33554432}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + image: TEST_IMG + file format: IMGFMT +@@ -50,18 +50,18 @@ virtual size: 32M (33554432 bytes) + + === Invalid BlockdevRef === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': "this doesn't exist", 'size': 33554432}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "this doesn't exist", "size": 33554432}}} ++{"return": {}} + Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exist +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + === Zero size === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': 'node0', 'size': 0}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 0}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + image: TEST_IMG + file format: IMGFMT +@@ -69,10 +69,10 @@ virtual size: 0 (0 bytes) + + === Maximum size === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': 'node0', 'size': 4503599627369984}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 4503599627369984}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + image: TEST_IMG + file format: IMGFMT +@@ -80,77 +80,77 @@ virtual size: 4096T (4503599627369984 bytes) + + === Invalid sizes === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': 'node0', 'size': 1234}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 1234}}} ++{"return": {}} + Job failed: Image size must be a multiple of 512 bytes +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': 'node0', 'size': 18446744073709551104L}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 18446744073709551104}}} ++{"return": {}} + Job failed: Image size is too large for this cluster size +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': 'node0', 'size': 9223372036854775808L}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 9223372036854775808}}} ++{"return": {}} + Job failed: Image size is too large for this cluster size +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': 'node0', 'size': 9223372036854775296}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 9223372036854775296}}} ++{"return": {}} + Job failed: Image size is too large for this cluster size +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': 'node0', 'size': 4503599627370497}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 4503599627370497}}} ++{"return": {}} + Job failed: Image size is too large for this cluster size +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + === Invalid cluster size === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 1234, 'driver': 'parallels', 'file': 'node0', 'size': 67108864}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 1234, "driver": "parallels", "file": "node0", "size": 67108864}}} ++{"return": {}} + Job failed: Cluster size must be a multiple of 512 bytes +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 128, 'driver': 'parallels', 'file': 'node0', 'size': 67108864}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 128, "driver": "parallels", "file": "node0", "size": 67108864}}} ++{"return": {}} + Job failed: Cluster size must be a multiple of 512 bytes +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 4294967296, 'driver': 'parallels', 'file': 'node0', 'size': 67108864}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 4294967296, "driver": "parallels", "file": "node0", "size": 67108864}}} ++{"return": {}} + Job failed: Cluster size is too large +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 9223372036854775808L, 'driver': 'parallels', 'file': 'node0', 'size': 67108864}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 9223372036854775808, "driver": "parallels", "file": "node0", "size": 67108864}}} ++{"return": {}} + Job failed: Cluster size is too large +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 18446744073709551104L, 'driver': 'parallels', 'file': 'node0', 'size': 67108864}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 18446744073709551104, "driver": "parallels", "file": "node0", "size": 67108864}}} ++{"return": {}} + Job failed: Cluster size is too large +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 0, 'driver': 'parallels', 'file': 'node0', 'size': 67108864}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 0, "driver": "parallels", "file": "node0", "size": 67108864}}} ++{"return": {}} + Job failed: Image size is too large for this cluster size +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 512, 'driver': 'parallels', 'file': 'node0', 'size': 281474976710656}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 512, "driver": "parallels", "file": "node0", "size": 281474976710656}}} ++{"return": {}} + Job failed: Image size is too large for this cluster size +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +diff --git a/tests/qemu-iotests/213.out b/tests/qemu-iotests/213.out +index e1dcd47..0c9d65b 100644 +--- a/tests/qemu-iotests/213.out ++++ b/tests/qemu-iotests/213.out +@@ -1,16 +1,16 @@ + === Successful image creation (defaults) === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.vhdx'}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} +- +-{'execute': 'blockdev-add', 'arguments': {'node_name': 'imgfile', 'driver': 'file', 'filename': 'TEST_DIR/PID-t.vhdx'}} +-{u'return': {}} +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': 'imgfile', 'size': 134217728}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx", "size": 0}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} ++ ++{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx", "node_name": "imgfile"}} ++{"return": {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "imgfile", "size": 134217728}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + image: TEST_IMG + file format: IMGFMT +@@ -19,15 +19,15 @@ cluster_size: 8388608 + + === Successful image creation (explicit defaults) === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.vhdx'}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx", "size": 0}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'block-size': 8388608, 'driver': 'vhdx', 'subformat': 'dynamic', 'log-size': 1048576, 'file': {'driver': 'file', 'filename': 'TEST_DIR/PID-t.vhdx'}, 'block-state-zero': True, 'size': 67108864}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"block-size": 8388608, "block-state-zero": true, "driver": "vhdx", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx"}, "log-size": 1048576, "size": 67108864, "subformat": "dynamic"}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + image: TEST_IMG + file format: IMGFMT +@@ -36,15 +36,15 @@ cluster_size: 8388608 + + === Successful image creation (with non-default options) === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.vhdx'}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx", "size": 0}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'block-size': 268435456, 'driver': 'vhdx', 'subformat': 'fixed', 'log-size': 8388608, 'file': {'driver': 'file', 'filename': 'TEST_DIR/PID-t.vhdx'}, 'block-state-zero': False, 'size': 33554432}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"block-size": 268435456, "block-state-zero": false, "driver": "vhdx", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx"}, "log-size": 8388608, "size": 33554432, "subformat": "fixed"}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + image: TEST_IMG + file format: IMGFMT +@@ -53,18 +53,18 @@ cluster_size: 268435456 + + === Invalid BlockdevRef === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': "this doesn't exist", 'size': 33554432}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "this doesn't exist", "size": 33554432}}} ++{"return": {}} + Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exist +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + === Zero size === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': 'node0', 'size': 0}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 0}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + image: TEST_IMG + file format: IMGFMT +@@ -73,10 +73,10 @@ cluster_size: 8388608 + + === Maximum size === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': 'node0', 'size': 70368744177664}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 70368744177664}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + image: TEST_IMG + file format: IMGFMT +@@ -85,85 +85,85 @@ cluster_size: 67108864 + + === Invalid sizes === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': 'node0', 'size': 18446744073709551104L}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 18446744073709551104}}} ++{"return": {}} + Job failed: Image size too large; max of 64TB +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': 'node0', 'size': 9223372036854775808L}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 9223372036854775808}}} ++{"return": {}} + Job failed: Image size too large; max of 64TB +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': 'node0', 'size': 9223372036854775296}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 9223372036854775296}}} ++{"return": {}} + Job failed: Image size too large; max of 64TB +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': 'node0', 'size': 70368744177665}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 70368744177665}}} ++{"return": {}} + Job failed: Image size too large; max of 64TB +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + === Invalid block size === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'block-size': 1234567, 'file': 'node0', 'size': 67108864}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"block-size": 1234567, "driver": "vhdx", "file": "node0", "size": 67108864}}} ++{"return": {}} + Job failed: Block size must be a multiple of 1 MB +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'block-size': 128, 'file': 'node0', 'size': 67108864}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"block-size": 128, "driver": "vhdx", "file": "node0", "size": 67108864}}} ++{"return": {}} + Job failed: Block size must be a multiple of 1 MB +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'block-size': 3145728, 'file': 'node0', 'size': 67108864}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"block-size": 3145728, "driver": "vhdx", "file": "node0", "size": 67108864}}} ++{"return": {}} + Job failed: Block size must be a power of two +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'block-size': 536870912, 'file': 'node0', 'size': 67108864}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"block-size": 536870912, "driver": "vhdx", "file": "node0", "size": 67108864}}} ++{"return": {}} + Job failed: Block size must not exceed 268435456 +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'block-size': 0, 'file': 'node0', 'size': 67108864}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"block-size": 0, "driver": "vhdx", "file": "node0", "size": 67108864}}} ++{"return": {}} + Job failed: Block size must be a multiple of 1 MB +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + === Invalid log size === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'log-size': 1234567, 'driver': 'vhdx', 'file': 'node0', 'size': 67108864}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "log-size": 1234567, "size": 67108864}}} ++{"return": {}} + Job failed: Log size must be a multiple of 1 MB +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'log-size': 128, 'driver': 'vhdx', 'file': 'node0', 'size': 67108864}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "log-size": 128, "size": 67108864}}} ++{"return": {}} + Job failed: Log size must be a multiple of 1 MB +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'log-size': 4294967296, 'driver': 'vhdx', 'file': 'node0', 'size': 67108864}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "log-size": 4294967296, "size": 67108864}}} ++{"return": {}} + Job failed: Log size must be smaller than 4 GB +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'log-size': 0, 'driver': 'vhdx', 'file': 'node0', 'size': 67108864}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "log-size": 0, "size": 67108864}}} ++{"return": {}} + Job failed: Log size must be a multiple of 1 MB +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +diff --git a/tests/qemu-iotests/216.out b/tests/qemu-iotests/216.out +index 45ea857..a70aa5c 100644 +--- a/tests/qemu-iotests/216.out ++++ b/tests/qemu-iotests/216.out +@@ -7,8 +7,8 @@ Done + + --- Doing COR --- + +-{u'return': {}} +-{u'return': u''} ++{"return": {}} ++{"return": ""} + + --- Checking COR result --- + +diff --git a/tests/qemu-iotests/218.out b/tests/qemu-iotests/218.out +index 7dbf78e..825a657 100644 +--- a/tests/qemu-iotests/218.out ++++ b/tests/qemu-iotests/218.out +@@ -4,27 +4,27 @@ + --- force=false --- + + Cancelling job +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'device': u'mirror', u'type': u'mirror', u'speed': 65536, u'len': 1048576, u'offset': 65536}, u'event': u'BLOCK_JOB_CANCELLED'} ++{"return": {}} ++{"data": {"device": "mirror", "len": 1048576, "offset": 65536, "speed": 65536, "type": "mirror"}, "event": "BLOCK_JOB_CANCELLED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} + + --- force=true --- + + Cancelling job +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'device': u'mirror', u'type': u'mirror', u'speed': 65536, u'len': 1048576, u'offset': 65536}, u'event': u'BLOCK_JOB_CANCELLED'} ++{"return": {}} ++{"data": {"device": "mirror", "len": 1048576, "offset": 65536, "speed": 65536, "type": "mirror"}, "event": "BLOCK_JOB_CANCELLED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} + + === Cancel mirror job after convergence === + + --- force=false --- + +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'device': u'mirror', u'type': u'mirror', u'speed': 0, u'len': 1048576, u'offset': 1048576}, u'event': u'BLOCK_JOB_READY'} ++{"data": {"device": "mirror", "len": 1048576, "offset": 1048576, "speed": 0, "type": "mirror"}, "event": "BLOCK_JOB_READY", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} + Cancelling job +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'device': u'mirror', u'type': u'mirror', u'speed': 0, u'len': 1048576, u'offset': 1048576}, u'event': u'BLOCK_JOB_COMPLETED'} ++{"return": {}} ++{"data": {"device": "mirror", "len": 1048576, "offset": 1048576, "speed": 0, "type": "mirror"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} + + --- force=true --- + +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'device': u'mirror', u'type': u'mirror', u'speed': 0, u'len': 1048576, u'offset': 1048576}, u'event': u'BLOCK_JOB_READY'} ++{"data": {"device": "mirror", "len": 1048576, "offset": 1048576, "speed": 0, "type": "mirror"}, "event": "BLOCK_JOB_READY", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} + Cancelling job +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'device': u'mirror', u'type': u'mirror', u'speed': 0, u'len': 1048576, u'offset': 1048576}, u'event': u'BLOCK_JOB_CANCELLED'} ++{"return": {}} ++{"data": {"device": "mirror", "len": 1048576, "offset": 1048576, "speed": 0, "type": "mirror"}, "event": "BLOCK_JOB_CANCELLED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +diff --git a/tests/qemu-iotests/219.out b/tests/qemu-iotests/219.out +index 6dc07bc..8ebd3fe 100644 +--- a/tests/qemu-iotests/219.out ++++ b/tests/qemu-iotests/219.out +@@ -2,326 +2,326 @@ Launching VM... + + + Starting block job: drive-mirror (auto-finalize: True; auto-dismiss: True) +-{u'return': {}} +-{u'return': [{u'status': u'running', u'current-progress': 'FILTERED', u'total-progress': 'FILTERED', u'id': u'job0', u'type': u'mirror'}]} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'created', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} ++{"return": {}} ++{"return": [{"current-progress": "FILTERED", "id": "job0", "status": "running", "total-progress": "FILTERED", "type": "mirror"}]} ++{"data": {"id": "job0", "status": "created"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} + + Pause/resume in RUNNING + === Testing block-job-pause/block-job-resume === +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'paused', u'current-progress': 65536, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'running', u'current-progress': 131072, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 65536, "id": "job0", "status": "paused", "total-progress": 4194304, "type": "mirror"}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 131072, "id": "job0", "status": "running", "total-progress": 4194304, "type": "mirror"}]} + === Testing block-job-pause/job-resume === +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'paused', u'current-progress': 131072, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'running', u'current-progress': 196608, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 131072, "id": "job0", "status": "paused", "total-progress": 4194304, "type": "mirror"}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 196608, "id": "job0", "status": "running", "total-progress": 4194304, "type": "mirror"}]} + === Testing job-pause/block-job-resume === +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'paused', u'current-progress': 196608, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'running', u'current-progress': 262144, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 196608, "id": "job0", "status": "paused", "total-progress": 4194304, "type": "mirror"}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 262144, "id": "job0", "status": "running", "total-progress": 4194304, "type": "mirror"}]} + === Testing job-pause/job-resume === +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'paused', u'current-progress': 262144, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'running', u'current-progress': 327680, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'complete'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'complete'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} +-{u'return': {}} ++{"return": {}} ++{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 262144, "id": "job0", "status": "paused", "total-progress": 4194304, "type": "mirror"}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 327680, "id": "job0", "status": "running", "total-progress": 4194304, "type": "mirror"}]} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'complete'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'complete'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} ++{"return": {}} + + Waiting for READY state... +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'ready', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'ready', u'current-progress': 4194304, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} ++{"data": {"id": "job0", "status": "ready"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 4194304, "id": "job0", "status": "ready", "total-progress": 4194304, "type": "mirror"}]} + + Pause/resume in READY + === Testing block-job-pause/block-job-resume === +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'standby', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'standby', u'current-progress': 4194304, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'ready', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'ready', u'current-progress': 4194304, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "standby"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 4194304, "id": "job0", "status": "standby", "total-progress": 4194304, "type": "mirror"}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "ready"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 4194304, "id": "job0", "status": "ready", "total-progress": 4194304, "type": "mirror"}]} + === Testing block-job-pause/job-resume === +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'standby', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'standby', u'current-progress': 4194304, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'ready', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'ready', u'current-progress': 4194304, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "standby"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 4194304, "id": "job0", "status": "standby", "total-progress": 4194304, "type": "mirror"}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "ready"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 4194304, "id": "job0", "status": "ready", "total-progress": 4194304, "type": "mirror"}]} + === Testing job-pause/block-job-resume === +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'standby', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'standby', u'current-progress': 4194304, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'ready', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'ready', u'current-progress': 4194304, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "standby"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 4194304, "id": "job0", "status": "standby", "total-progress": 4194304, "type": "mirror"}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "ready"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 4194304, "id": "job0", "status": "ready", "total-progress": 4194304, "type": "mirror"}]} + === Testing job-pause/job-resume === +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'standby', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'standby', u'current-progress': 4194304, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'ready', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'ready', u'current-progress': 4194304, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'ready' cannot accept command verb 'finalize'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'ready' cannot accept command verb 'dismiss'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'ready' cannot accept command verb 'finalize'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'ready' cannot accept command verb 'dismiss'"}} +-{u'return': {}} ++{"return": {}} ++{"data": {"id": "job0", "status": "standby"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 4194304, "id": "job0", "status": "standby", "total-progress": 4194304, "type": "mirror"}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "ready"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 4194304, "id": "job0", "status": "ready", "total-progress": 4194304, "type": "mirror"}]} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'ready' cannot accept command verb 'finalize'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'ready' cannot accept command verb 'dismiss'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'ready' cannot accept command verb 'finalize'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'ready' cannot accept command verb 'dismiss'"}} ++{"return": {}} + + Waiting for PENDING state... +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'waiting', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'pending', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'concluded', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'null', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': []} ++{"data": {"id": "job0", "status": "waiting"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"data": {"id": "job0", "status": "pending"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"data": {"id": "job0", "status": "concluded"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"data": {"id": "job0", "status": "null"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": []} + + + Starting block job: drive-backup (auto-finalize: True; auto-dismiss: True) +-{u'return': {}} +-{u'return': [{u'status': u'running', u'current-progress': 'FILTERED', u'total-progress': 'FILTERED', u'id': u'job0', u'type': u'backup'}]} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'created', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} ++{"return": {}} ++{"return": [{"current-progress": "FILTERED", "id": "job0", "status": "running", "total-progress": "FILTERED", "type": "backup"}]} ++{"data": {"id": "job0", "status": "created"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} + + Pause/resume in RUNNING + === Testing block-job-pause/block-job-resume === +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'paused', u'current-progress': 65536, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'running', u'current-progress': 131072, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 65536, "id": "job0", "status": "paused", "total-progress": 4194304, "type": "backup"}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 131072, "id": "job0", "status": "running", "total-progress": 4194304, "type": "backup"}]} + === Testing block-job-pause/job-resume === +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'paused', u'current-progress': 131072, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'running', u'current-progress': 196608, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 131072, "id": "job0", "status": "paused", "total-progress": 4194304, "type": "backup"}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 196608, "id": "job0", "status": "running", "total-progress": 4194304, "type": "backup"}]} + === Testing job-pause/block-job-resume === +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'paused', u'current-progress': 196608, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'running', u'current-progress': 262144, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 196608, "id": "job0", "status": "paused", "total-progress": 4194304, "type": "backup"}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 262144, "id": "job0", "status": "running", "total-progress": 4194304, "type": "backup"}]} + === Testing job-pause/job-resume === +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'paused', u'current-progress': 262144, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'running', u'current-progress': 327680, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'complete'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'complete'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} +-{u'return': {}} ++{"return": {}} ++{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 262144, "id": "job0", "status": "paused", "total-progress": 4194304, "type": "backup"}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 327680, "id": "job0", "status": "running", "total-progress": 4194304, "type": "backup"}]} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'complete'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'complete'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} ++{"return": {}} + + Waiting for PENDING state... +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'waiting', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'pending', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'concluded', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'null', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': []} ++{"data": {"id": "job0", "status": "waiting"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"data": {"id": "job0", "status": "pending"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"data": {"id": "job0", "status": "concluded"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"data": {"id": "job0", "status": "null"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": []} + + + Starting block job: drive-backup (auto-finalize: True; auto-dismiss: False) +-{u'return': {}} +-{u'return': [{u'status': u'running', u'current-progress': 'FILTERED', u'total-progress': 'FILTERED', u'id': u'job0', u'type': u'backup'}]} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'created', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} ++{"return": {}} ++{"return": [{"current-progress": "FILTERED", "id": "job0", "status": "running", "total-progress": "FILTERED", "type": "backup"}]} ++{"data": {"id": "job0", "status": "created"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} + + Pause/resume in RUNNING + === Testing block-job-pause/block-job-resume === +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'paused', u'current-progress': 65536, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'running', u'current-progress': 131072, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 65536, "id": "job0", "status": "paused", "total-progress": 4194304, "type": "backup"}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 131072, "id": "job0", "status": "running", "total-progress": 4194304, "type": "backup"}]} + === Testing block-job-pause/job-resume === +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'paused', u'current-progress': 131072, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'running', u'current-progress': 196608, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 131072, "id": "job0", "status": "paused", "total-progress": 4194304, "type": "backup"}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 196608, "id": "job0", "status": "running", "total-progress": 4194304, "type": "backup"}]} + === Testing job-pause/block-job-resume === +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'paused', u'current-progress': 196608, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'running', u'current-progress': 262144, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 196608, "id": "job0", "status": "paused", "total-progress": 4194304, "type": "backup"}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 262144, "id": "job0", "status": "running", "total-progress": 4194304, "type": "backup"}]} + === Testing job-pause/job-resume === +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'paused', u'current-progress': 262144, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'running', u'current-progress': 327680, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'complete'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'complete'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} +-{u'return': {}} ++{"return": {}} ++{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 262144, "id": "job0", "status": "paused", "total-progress": 4194304, "type": "backup"}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 327680, "id": "job0", "status": "running", "total-progress": 4194304, "type": "backup"}]} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'complete'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'complete'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} ++{"return": {}} + + Waiting for PENDING state... +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'waiting', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'pending', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'concluded', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'concluded', u'current-progress': 4194304, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'concluded' cannot accept command verb 'pause'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'concluded' cannot accept command verb 'complete'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'concluded' cannot accept command verb 'finalize'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'concluded' cannot accept command verb 'pause'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'concluded' cannot accept command verb 'complete'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'concluded' cannot accept command verb 'finalize'"}} +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'null', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': []} ++{"data": {"id": "job0", "status": "waiting"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"data": {"id": "job0", "status": "pending"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"data": {"id": "job0", "status": "concluded"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 4194304, "id": "job0", "status": "concluded", "total-progress": 4194304, "type": "backup"}]} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'concluded' cannot accept command verb 'pause'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'concluded' cannot accept command verb 'complete'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'concluded' cannot accept command verb 'finalize'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'concluded' cannot accept command verb 'pause'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'concluded' cannot accept command verb 'complete'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'concluded' cannot accept command verb 'finalize'"}} ++{"return": {}} ++{"data": {"id": "job0", "status": "null"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": []} + + + Starting block job: drive-backup (auto-finalize: False; auto-dismiss: True) +-{u'return': {}} +-{u'return': [{u'status': u'running', u'current-progress': 'FILTERED', u'total-progress': 'FILTERED', u'id': u'job0', u'type': u'backup'}]} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'created', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} ++{"return": {}} ++{"return": [{"current-progress": "FILTERED", "id": "job0", "status": "running", "total-progress": "FILTERED", "type": "backup"}]} ++{"data": {"id": "job0", "status": "created"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} + + Pause/resume in RUNNING + === Testing block-job-pause/block-job-resume === +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'paused', u'current-progress': 65536, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'running', u'current-progress': 131072, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 65536, "id": "job0", "status": "paused", "total-progress": 4194304, "type": "backup"}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 131072, "id": "job0", "status": "running", "total-progress": 4194304, "type": "backup"}]} + === Testing block-job-pause/job-resume === +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'paused', u'current-progress': 131072, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'running', u'current-progress': 196608, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 131072, "id": "job0", "status": "paused", "total-progress": 4194304, "type": "backup"}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 196608, "id": "job0", "status": "running", "total-progress": 4194304, "type": "backup"}]} + === Testing job-pause/block-job-resume === +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'paused', u'current-progress': 196608, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'running', u'current-progress': 262144, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 196608, "id": "job0", "status": "paused", "total-progress": 4194304, "type": "backup"}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 262144, "id": "job0", "status": "running", "total-progress": 4194304, "type": "backup"}]} + === Testing job-pause/job-resume === +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'paused', u'current-progress': 262144, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'running', u'current-progress': 327680, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'complete'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'complete'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} +-{u'return': {}} ++{"return": {}} ++{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 262144, "id": "job0", "status": "paused", "total-progress": 4194304, "type": "backup"}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 327680, "id": "job0", "status": "running", "total-progress": 4194304, "type": "backup"}]} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'complete'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'complete'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} ++{"return": {}} + + Waiting for PENDING state... +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'waiting', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'pending', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'pending', u'current-progress': 4194304, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'pending' cannot accept command verb 'pause'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'pending' cannot accept command verb 'complete'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'pending' cannot accept command verb 'dismiss'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'pending' cannot accept command verb 'pause'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'pending' cannot accept command verb 'complete'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'pending' cannot accept command verb 'dismiss'"}} +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'concluded', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'null', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': []} ++{"data": {"id": "job0", "status": "waiting"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"data": {"id": "job0", "status": "pending"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 4194304, "id": "job0", "status": "pending", "total-progress": 4194304, "type": "backup"}]} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'pending' cannot accept command verb 'pause'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'pending' cannot accept command verb 'complete'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'pending' cannot accept command verb 'dismiss'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'pending' cannot accept command verb 'pause'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'pending' cannot accept command verb 'complete'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'pending' cannot accept command verb 'dismiss'"}} ++{"return": {}} ++{"data": {"id": "job0", "status": "concluded"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"data": {"id": "job0", "status": "null"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": []} + + + Starting block job: drive-backup (auto-finalize: False; auto-dismiss: False) +-{u'return': {}} +-{u'return': [{u'status': u'running', u'current-progress': 'FILTERED', u'total-progress': 'FILTERED', u'id': u'job0', u'type': u'backup'}]} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'created', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} ++{"return": {}} ++{"return": [{"current-progress": "FILTERED", "id": "job0", "status": "running", "total-progress": "FILTERED", "type": "backup"}]} ++{"data": {"id": "job0", "status": "created"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} + + Pause/resume in RUNNING + === Testing block-job-pause/block-job-resume === +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'paused', u'current-progress': 65536, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'running', u'current-progress': 131072, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 65536, "id": "job0", "status": "paused", "total-progress": 4194304, "type": "backup"}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 131072, "id": "job0", "status": "running", "total-progress": 4194304, "type": "backup"}]} + === Testing block-job-pause/job-resume === +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'paused', u'current-progress': 131072, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'running', u'current-progress': 196608, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 131072, "id": "job0", "status": "paused", "total-progress": 4194304, "type": "backup"}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 196608, "id": "job0", "status": "running", "total-progress": 4194304, "type": "backup"}]} + === Testing job-pause/block-job-resume === +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'paused', u'current-progress': 196608, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'running', u'current-progress': 262144, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 196608, "id": "job0", "status": "paused", "total-progress": 4194304, "type": "backup"}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 262144, "id": "job0", "status": "running", "total-progress": 4194304, "type": "backup"}]} + === Testing job-pause/job-resume === +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'paused', u'current-progress': 262144, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'running', u'current-progress': 327680, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'complete'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'complete'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} +-{u'return': {}} ++{"return": {}} ++{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 262144, "id": "job0", "status": "paused", "total-progress": 4194304, "type": "backup"}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 327680, "id": "job0", "status": "running", "total-progress": 4194304, "type": "backup"}]} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'complete'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'complete'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} ++{"return": {}} + + Waiting for PENDING state... +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'waiting', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'pending', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'pending', u'current-progress': 4194304, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'pending' cannot accept command verb 'pause'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'pending' cannot accept command verb 'complete'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'pending' cannot accept command verb 'dismiss'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'pending' cannot accept command verb 'pause'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'pending' cannot accept command verb 'complete'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'pending' cannot accept command verb 'dismiss'"}} +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'concluded', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'concluded', u'current-progress': 4194304, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'concluded' cannot accept command verb 'pause'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'concluded' cannot accept command verb 'complete'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'concluded' cannot accept command verb 'finalize'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'concluded' cannot accept command verb 'pause'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'concluded' cannot accept command verb 'complete'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'concluded' cannot accept command verb 'finalize'"}} +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'null', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': []} ++{"data": {"id": "job0", "status": "waiting"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"data": {"id": "job0", "status": "pending"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 4194304, "id": "job0", "status": "pending", "total-progress": 4194304, "type": "backup"}]} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'pending' cannot accept command verb 'pause'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'pending' cannot accept command verb 'complete'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'pending' cannot accept command verb 'dismiss'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'pending' cannot accept command verb 'pause'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'pending' cannot accept command verb 'complete'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'pending' cannot accept command verb 'dismiss'"}} ++{"return": {}} ++{"data": {"id": "job0", "status": "concluded"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 4194304, "id": "job0", "status": "concluded", "total-progress": 4194304, "type": "backup"}]} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'concluded' cannot accept command verb 'pause'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'concluded' cannot accept command verb 'complete'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'concluded' cannot accept command verb 'finalize'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'concluded' cannot accept command verb 'pause'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'concluded' cannot accept command verb 'complete'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'concluded' cannot accept command verb 'finalize'"}} ++{"return": {}} ++{"data": {"id": "job0", "status": "null"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": []} +diff --git a/tests/qemu-iotests/222.out b/tests/qemu-iotests/222.out +index 48f336a..16643dd 100644 +--- a/tests/qemu-iotests/222.out ++++ b/tests/qemu-iotests/222.out +@@ -8,13 +8,13 @@ Done + + --- Setting up Fleecing Graph --- + +-{u'return': {}} +-{u'return': {}} ++{"return": {}} ++{"return": {}} + + --- Setting up NBD Export --- + +-{u'return': {}} +-{u'return': {}} ++{"return": {}} ++{"return": {}} + + --- Sanity Check --- + +@@ -29,13 +29,13 @@ read -P0 0x3fe0000 64k + --- Testing COW --- + + write -P0xab 0 64k +-{u'return': u''} ++{"return": ""} + write -P0xad 0x00f8000 64k +-{u'return': u''} ++{"return": ""} + write -P0x1d 0x2008000 64k +-{u'return': u''} ++{"return": ""} + write -P0xea 0x3fe0000 64k +-{u'return': u''} ++{"return": ""} + + --- Verifying Data --- + +@@ -49,10 +49,10 @@ read -P0 0x3fe0000 64k + + --- Cleanup --- + +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'device': u'drive0', u'type': u'backup', u'speed': 0, u'len': 67108864, u'offset': 393216}, u'event': u'BLOCK_JOB_CANCELLED'} +-{u'return': {}} +-{u'return': {}} ++{"return": {}} ++{"data": {"device": "drive0", "len": 67108864, "offset": 393216, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_CANCELLED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": {}} ++{"return": {}} + + --- Confirming writes --- + +diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py +index 3d41ff0..b548e2f 100644 +--- a/tests/qemu-iotests/iotests.py ++++ b/tests/qemu-iotests/iotests.py +@@ -252,7 +252,10 @@ def filter_img_info(output, filename): + def log(msg, filters=[]): + for flt in filters: + msg = flt(msg) +- print(msg) ++ if type(msg) is dict or type(msg) is list: ++ print(json.dumps(msg, sort_keys=True)) ++ else: ++ print(msg) + + class Timeout: + def __init__(self, seconds, errmsg = "Timeout"): +@@ -440,10 +443,11 @@ class VM(qtest.QEMUQtestMachine): + return result + + def qmp_log(self, cmd, filters=[filter_testfiles], **kwargs): +- logmsg = "{'execute': '%s', 'arguments': %s}" % (cmd, kwargs) ++ logmsg = '{"execute": "%s", "arguments": %s}' % \ ++ (cmd, json.dumps(kwargs, sort_keys=True)) + log(logmsg, filters) + result = self.qmp(cmd, **kwargs) +- log(str(result), filters) ++ log(json.dumps(result, sort_keys=True), filters) + return result + + def run_job(self, job, auto_finalize=True, auto_dismiss=False): +-- +1.8.3.1 + diff --git a/SOURCES/kvm-iotests-Use-Python-byte-strings-where-appropriate.patch b/SOURCES/kvm-iotests-Use-Python-byte-strings-where-appropriate.patch new file mode 100644 index 0000000..c633b51 --- /dev/null +++ b/SOURCES/kvm-iotests-Use-Python-byte-strings-where-appropriate.patch @@ -0,0 +1,267 @@ +From 3b36d09996dbcbfc15cb83b2287940243022fd6a Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Mon, 8 Jul 2019 15:25:58 +0100 +Subject: [PATCH 12/39] iotests: Use Python byte strings where appropriate +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Pino Toscano +Message-id: <20190708152601.21123-8-ptoscano@redhat.com> +Patchwork-id: 89424 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v3 07/10] iotests: Use Python byte strings where appropriate +Bugzilla: 1513367 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Max Reitz +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Markus Armbruster + +From: Max Reitz + +Since byte strings are no longer the default in Python 3, we have to +explicitly use them where we need to, which is mostly when working with +structures. It also means that we need to open a file in binary mode +when we want to use structures. + +On the other hand, we have to accomodate for the fact that some +functions (still) work with byte strings but we want to use unicode +strings (in Python 3 at least, and it does not matter in Python 2). +This includes base64 encoding, but it is most notable when working with +the subprocess module: Either we set universal_newlines to True so that +the default streams are opened in text mode (hence this parameter is +aliased as "text" as of 3.7), or, if that is not possible, we have to +decode the output to a normal string. + +Signed-off-by: Max Reitz +Reviewed-by: Eduardo Habkost +Message-Id: <20181022135307.14398-4-mreitz@redhat.com> +Signed-off-by: Eduardo Habkost +(cherry picked from commit 8eb5e6746feaf9e021b69ea2521899f8dc889033) +Signed-off-by: Pino Toscano +Signed-off-by: Danilo C. L. de Paula +--- + scripts/qtest.py | 2 +- + tests/qemu-iotests/044 | 8 ++++---- + tests/qemu-iotests/149 | 8 +++++--- + tests/qemu-iotests/207 | 4 ++-- + tests/qemu-iotests/iotests.py | 11 +++++++---- + tests/qemu-iotests/nbd-fault-injector.py | 4 ++-- + tests/qemu-iotests/qcow2.py | 10 +++++----- + 7 files changed, 26 insertions(+), 21 deletions(-) + +diff --git a/scripts/qtest.py b/scripts/qtest.py +index df0daf2..adf1fe3 100644 +--- a/scripts/qtest.py ++++ b/scripts/qtest.py +@@ -64,7 +64,7 @@ class QEMUQtestProtocol(object): + + @param qtest_cmd: qtest command text to be sent + """ +- self._sock.sendall(qtest_cmd + "\n") ++ self._sock.sendall((qtest_cmd + "\n").encode('utf-8')) + + def close(self): + self._sock.close() +diff --git a/tests/qemu-iotests/044 b/tests/qemu-iotests/044 +index 11ea0f4..69e736f 100755 +--- a/tests/qemu-iotests/044 ++++ b/tests/qemu-iotests/044 +@@ -53,21 +53,21 @@ class TestRefcountTableGrowth(iotests.QMPTestCase): + fd.seek(off_reftable) + + for i in xrange(0, h.refcount_table_clusters): +- sector = ''.join(struct.pack('>Q', ++ sector = b''.join(struct.pack('>Q', + off_refblock + i * 64 * 512 + j * 512) + for j in xrange(0, 64)) + fd.write(sector) + + # Write the refcount blocks + assert(fd.tell() == off_refblock) +- sector = ''.join(struct.pack('>H', 1) for j in xrange(0, 64 * 256)) ++ sector = b''.join(struct.pack('>H', 1) for j in range(0, 64 * 256)) + for block in xrange(0, h.refcount_table_clusters): + fd.write(sector) + + # Write the L1 table + assert(fd.tell() == off_l1) + assert(off_l2 + 512 * h.l1_size == off_data) +- table = ''.join(struct.pack('>Q', (1 << 63) | off_l2 + 512 * j) ++ table = b''.join(struct.pack('>Q', (1 << 63) | off_l2 + 512 * j) + for j in xrange(0, h.l1_size)) + fd.write(table) + +@@ -85,7 +85,7 @@ class TestRefcountTableGrowth(iotests.QMPTestCase): + remaining = remaining - 1024 * 512 + off = off + 1024 * 512 + +- table = ''.join(struct.pack('>Q', (1 << 63) | off + 512 * j) ++ table = b''.join(struct.pack('>Q', (1 << 63) | off + 512 * j) + for j in xrange(0, remaining / 512)) + fd.write(table) + +diff --git a/tests/qemu-iotests/149 b/tests/qemu-iotests/149 +index d3ffa25..87174b1 100755 +--- a/tests/qemu-iotests/149 ++++ b/tests/qemu-iotests/149 +@@ -79,7 +79,7 @@ class LUKSConfig(object): + + def first_password_base64(self): + (pw, slot) = self.first_password() +- return base64.b64encode(pw) ++ return base64.b64encode(pw.encode('ascii')).decode('ascii') + + def active_slots(self): + slots = [] +@@ -98,7 +98,8 @@ def verify_passwordless_sudo(): + proc = subprocess.Popen(args, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, +- stderr=subprocess.STDOUT) ++ stderr=subprocess.STDOUT, ++ universal_newlines=True) + + msg = proc.communicate()[0] + +@@ -116,7 +117,8 @@ def cryptsetup(args, password=None): + proc = subprocess.Popen(fullargs, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, +- stderr=subprocess.STDOUT) ++ stderr=subprocess.STDOUT, ++ universal_newlines=True) + + msg = proc.communicate(password)[0] + +diff --git a/tests/qemu-iotests/207 b/tests/qemu-iotests/207 +index 8202bd1..d45bf72 100755 +--- a/tests/qemu-iotests/207 ++++ b/tests/qemu-iotests/207 +@@ -109,7 +109,7 @@ with iotests.FilePath('t.img') as disk_path, \ + md5_key = subprocess.check_output( + 'ssh-keyscan -t rsa 127.0.0.1 2>/dev/null | grep -v "\\^#" | ' + + 'cut -d" " -f3 | base64 -d | md5sum -b | cut -d" " -f1', +- shell=True).rstrip() ++ shell=True).rstrip().decode('ascii') + + vm.launch() + blockdev_create(vm, { 'driver': 'ssh', +@@ -147,7 +147,7 @@ with iotests.FilePath('t.img') as disk_path, \ + sha1_key = subprocess.check_output( + 'ssh-keyscan -t rsa 127.0.0.1 2>/dev/null | grep -v "\\^#" | ' + + 'cut -d" " -f3 | base64 -d | sha1sum -b | cut -d" " -f1', +- shell=True).rstrip() ++ shell=True).rstrip().decode('ascii') + + vm.launch() + blockdev_create(vm, { 'driver': 'ssh', +diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py +index 0f6980a..3d41ff0 100644 +--- a/tests/qemu-iotests/iotests.py ++++ b/tests/qemu-iotests/iotests.py +@@ -104,7 +104,8 @@ def qemu_img_pipe(*args): + '''Run qemu-img and return its output''' + subp = subprocess.Popen(qemu_img_args + list(args), + stdout=subprocess.PIPE, +- stderr=subprocess.STDOUT) ++ stderr=subprocess.STDOUT, ++ universal_newlines=True) + exitcode = subp.wait() + if exitcode < 0: + sys.stderr.write('qemu-img received signal %i: %s\n' % (-exitcode, ' '.join(qemu_img_args + list(args)))) +@@ -128,7 +129,8 @@ def qemu_io(*args): + '''Run qemu-io and return the stdout data''' + args = qemu_io_args + list(args) + subp = subprocess.Popen(args, stdout=subprocess.PIPE, +- stderr=subprocess.STDOUT) ++ stderr=subprocess.STDOUT, ++ universal_newlines=True) + exitcode = subp.wait() + if exitcode < 0: + sys.stderr.write('qemu-io received signal %i: %s\n' % (-exitcode, ' '.join(args))) +@@ -149,7 +151,8 @@ class QemuIoInteractive: + self.args = qemu_io_args + list(args) + self._p = subprocess.Popen(self.args, stdin=subprocess.PIPE, + stdout=subprocess.PIPE, +- stderr=subprocess.STDOUT) ++ stderr=subprocess.STDOUT, ++ universal_newlines=True) + assert self._p.stdout.read(9) == 'qemu-io> ' + + def close(self): +@@ -192,7 +195,7 @@ def compare_images(img1, img2, fmt1=imgfmt, fmt2=imgfmt): + + def create_image(name, size): + '''Create a fully-allocated raw image with sector markers''' +- file = open(name, 'w') ++ file = open(name, 'wb') + i = 0 + while i < size: + sector = struct.pack('>l504xl', i / 512, i / 512) +diff --git a/tests/qemu-iotests/nbd-fault-injector.py b/tests/qemu-iotests/nbd-fault-injector.py +index f9193c0..09668f6 100755 +--- a/tests/qemu-iotests/nbd-fault-injector.py ++++ b/tests/qemu-iotests/nbd-fault-injector.py +@@ -86,7 +86,7 @@ def recvall(sock, bufsize): + raise Exception('unexpected disconnect') + chunks.append(chunk) + received += len(chunk) +- return ''.join(chunks) ++ return b''.join(chunks) + + class Rule(object): + def __init__(self, name, event, io, when): +@@ -176,7 +176,7 @@ def handle_connection(conn, use_export): + req = read_request(conn) + if req.type == NBD_CMD_READ: + write_reply(conn, 0, req.handle) +- conn.send('\0' * req.len, event='data') ++ conn.send(b'\0' * req.len, event='data') + elif req.type == NBD_CMD_WRITE: + _ = conn.recv(req.len, event='data') + write_reply(conn, 0, req.handle) +diff --git a/tests/qemu-iotests/qcow2.py b/tests/qemu-iotests/qcow2.py +index b95a837..b392972 100755 +--- a/tests/qemu-iotests/qcow2.py ++++ b/tests/qemu-iotests/qcow2.py +@@ -10,7 +10,7 @@ class QcowHeaderExtension: + def __init__(self, magic, length, data): + if length % 8 != 0: + padding = 8 - (length % 8) +- data += "\0" * padding ++ data += b"\0" * padding + + self.magic = magic + self.length = length +@@ -103,7 +103,7 @@ class QcowHeader: + + fd.seek(self.header_length) + extensions = self.extensions +- extensions.append(QcowHeaderExtension(0, 0, "")) ++ extensions.append(QcowHeaderExtension(0, 0, b"")) + for ex in extensions: + buf = struct.pack('>II', ex.magic, ex.length) + fd.write(buf) +@@ -137,8 +137,8 @@ class QcowHeader: + for ex in self.extensions: + + data = ex.data[:ex.length] +- if all(c in string.printable for c in data): +- data = "'%s'" % data ++ if all(c in string.printable.encode('ascii') for c in data): ++ data = "'%s'" % data.decode('ascii') + else: + data = "" + +@@ -178,7 +178,7 @@ def cmd_add_header_ext(fd, magic, data): + sys.exit(1) + + h = QcowHeader(fd) +- h.extensions.append(QcowHeaderExtension.create(magic, data)) ++ h.extensions.append(QcowHeaderExtension.create(magic, data.encode('ascii'))) + h.update(fd) + + def cmd_add_header_ext_stdio(fd, magic): +-- +1.8.3.1 + diff --git a/SOURCES/kvm-iothread-fix-crash-with-invalid-properties.patch b/SOURCES/kvm-iothread-fix-crash-with-invalid-properties.patch new file mode 100644 index 0000000..1ae1c2c --- /dev/null +++ b/SOURCES/kvm-iothread-fix-crash-with-invalid-properties.patch @@ -0,0 +1,81 @@ +From 287d819f015a624f321d34491e30b62a05912298 Mon Sep 17 00:00:00 2001 +From: Stefan Hajnoczi +Date: Thu, 15 Aug 2019 13:23:10 +0100 +Subject: [PATCH 08/10] iothread: fix crash with invalid properties +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Stefan Hajnoczi +Message-id: <20190815132311.22027-2-stefanha@redhat.com> +Patchwork-id: 89995 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v2 1/2] iothread: fix crash with invalid properties +Bugzilla: 1687541 +RH-Acked-by: Peter Xu +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: John Snow +RH-Acked-by: Markus Armbruster + +From: Marc-André Lureau + +-object iothread,id=foo,? will crash qemu: + +qemu-system-x86_64:qemu-thread-posix.c:128: qemu_cond_destroy: Assertion `cond->initialized' failed. + +Use thread_id != -1 to check if iothread_complete() finished +successfully and the mutex/cond have been initialized. + +Signed-off-by: Marc-André Lureau +Message-Id: <20180821100716.13803-1-marcandre.lureau@redhat.com> +Signed-off-by: Fam Zheng +(cherry picked from commit 14a2d11825ddc37d6547a80704ae6450e9e376c7) +Signed-off-by: Stefan Hajnoczi +Signed-off-by: Danilo C. L. de Paula +--- + iothread.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/iothread.c b/iothread.c +index aff1281..2fb1cdf 100644 +--- a/iothread.c ++++ b/iothread.c +@@ -110,6 +110,7 @@ static void iothread_instance_init(Object *obj) + IOThread *iothread = IOTHREAD(obj); + + iothread->poll_max_ns = IOTHREAD_POLL_MAX_NS_DEFAULT; ++ iothread->thread_id = -1; + } + + static void iothread_instance_finalize(Object *obj) +@@ -117,6 +118,11 @@ static void iothread_instance_finalize(Object *obj) + IOThread *iothread = IOTHREAD(obj); + + iothread_stop(iothread); ++ ++ if (iothread->thread_id != -1) { ++ qemu_cond_destroy(&iothread->init_done_cond); ++ qemu_mutex_destroy(&iothread->init_done_lock); ++ } + /* + * Before glib2 2.33.10, there is a glib2 bug that GSource context + * pointer may not be cleared even if the context has already been +@@ -135,8 +141,6 @@ static void iothread_instance_finalize(Object *obj) + g_main_context_unref(iothread->worker_context); + iothread->worker_context = NULL; + } +- qemu_cond_destroy(&iothread->init_done_cond); +- qemu_mutex_destroy(&iothread->init_done_lock); + } + + static void iothread_complete(UserCreatable *obj, Error **errp) +@@ -147,7 +151,6 @@ static void iothread_complete(UserCreatable *obj, Error **errp) + + iothread->stopping = false; + iothread->running = true; +- iothread->thread_id = -1; + iothread->ctx = aio_context_new(&local_error); + if (!iothread->ctx) { + error_propagate(errp, local_error); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-iothread-replace-init_done_cond-with-a-semaphore.patch b/SOURCES/kvm-iothread-replace-init_done_cond-with-a-semaphore.patch new file mode 100644 index 0000000..aac68ac --- /dev/null +++ b/SOURCES/kvm-iothread-replace-init_done_cond-with-a-semaphore.patch @@ -0,0 +1,117 @@ +From 9db6f24509ee8a28818693d6a15257b873d9422a Mon Sep 17 00:00:00 2001 +From: Stefan Hajnoczi +Date: Thu, 15 Aug 2019 13:23:11 +0100 +Subject: [PATCH 09/10] iothread: replace init_done_cond with a semaphore + +RH-Author: Stefan Hajnoczi +Message-id: <20190815132311.22027-3-stefanha@redhat.com> +Patchwork-id: 89996 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v2 2/2] iothread: replace init_done_cond with a semaphore +Bugzilla: 1687541 +RH-Acked-by: Peter Xu +RH-Acked-by: John Snow +RH-Acked-by: Markus Armbruster + +From: Peter Xu + +Only sending an init-done message using lock+cond seems an overkill to +me. Replacing it with a simpler semaphore. + +Meanwhile, init the semaphore unconditionally, then we can destroy it +unconditionally too in finalize which seems cleaner. + +Signed-off-by: Peter Xu +Message-id: 20190306115532.23025-2-peterx@redhat.com +Message-Id: <20190306115532.23025-2-peterx@redhat.com> +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit 21c4d15b4708b7d30c450041a560df670f36cac8) +Signed-off-by: Stefan Hajnoczi +Signed-off-by: Danilo C. L. de Paula +--- + include/sysemu/iothread.h | 3 +-- + iothread.c | 17 ++++------------- + 2 files changed, 5 insertions(+), 15 deletions(-) + +diff --git a/include/sysemu/iothread.h b/include/sysemu/iothread.h +index 8a7ac2c..50411ba 100644 +--- a/include/sysemu/iothread.h ++++ b/include/sysemu/iothread.h +@@ -27,8 +27,7 @@ typedef struct { + GMainContext *worker_context; + GMainLoop *main_loop; + GOnce once; +- QemuMutex init_done_lock; +- QemuCond init_done_cond; /* is thread initialization done? */ ++ QemuSemaphore init_done_sem; /* is thread init done? */ + bool stopping; /* has iothread_stop() been called? */ + bool running; /* should iothread_run() continue? */ + int thread_id; +diff --git a/iothread.c b/iothread.c +index 2fb1cdf..b92232f 100644 +--- a/iothread.c ++++ b/iothread.c +@@ -55,10 +55,8 @@ static void *iothread_run(void *opaque) + rcu_register_thread(); + + my_iothread = iothread; +- qemu_mutex_lock(&iothread->init_done_lock); + iothread->thread_id = qemu_get_thread_id(); +- qemu_cond_signal(&iothread->init_done_cond); +- qemu_mutex_unlock(&iothread->init_done_lock); ++ qemu_sem_post(&iothread->init_done_sem); + + while (iothread->running) { + aio_poll(iothread->ctx, true); +@@ -111,6 +109,7 @@ static void iothread_instance_init(Object *obj) + + iothread->poll_max_ns = IOTHREAD_POLL_MAX_NS_DEFAULT; + iothread->thread_id = -1; ++ qemu_sem_init(&iothread->init_done_sem, 0); + } + + static void iothread_instance_finalize(Object *obj) +@@ -119,10 +118,6 @@ static void iothread_instance_finalize(Object *obj) + + iothread_stop(iothread); + +- if (iothread->thread_id != -1) { +- qemu_cond_destroy(&iothread->init_done_cond); +- qemu_mutex_destroy(&iothread->init_done_lock); +- } + /* + * Before glib2 2.33.10, there is a glib2 bug that GSource context + * pointer may not be cleared even if the context has already been +@@ -141,6 +136,7 @@ static void iothread_instance_finalize(Object *obj) + g_main_context_unref(iothread->worker_context); + iothread->worker_context = NULL; + } ++ qemu_sem_destroy(&iothread->init_done_sem); + } + + static void iothread_complete(UserCreatable *obj, Error **errp) +@@ -169,8 +165,6 @@ static void iothread_complete(UserCreatable *obj, Error **errp) + return; + } + +- qemu_mutex_init(&iothread->init_done_lock); +- qemu_cond_init(&iothread->init_done_cond); + iothread->once = (GOnce) G_ONCE_INIT; + + /* This assumes we are called from a thread with useful CPU affinity for us +@@ -184,12 +178,9 @@ static void iothread_complete(UserCreatable *obj, Error **errp) + g_free(name); + + /* Wait for initialization to complete */ +- qemu_mutex_lock(&iothread->init_done_lock); + while (iothread->thread_id == -1) { +- qemu_cond_wait(&iothread->init_done_cond, +- &iothread->init_done_lock); ++ qemu_sem_wait(&iothread->init_done_sem); + } +- qemu_mutex_unlock(&iothread->init_done_lock); + } + + typedef struct { +-- +1.8.3.1 + diff --git a/SOURCES/kvm-linux-headers-synchronize-generic-and-x86-KVM-header.patch b/SOURCES/kvm-linux-headers-synchronize-generic-and-x86-KVM-header.patch new file mode 100644 index 0000000..e6380a7 --- /dev/null +++ b/SOURCES/kvm-linux-headers-synchronize-generic-and-x86-KVM-header.patch @@ -0,0 +1,334 @@ +From 4a8e202ddd9bde207a5a9caaee6e0f06399a3052 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 22 Jul 2019 18:22:13 +0100 +Subject: [PATCH 32/39] linux-headers: synchronize generic and x86 KVM headers + with upstream [rhel-only] + +RH-Author: Paolo Bonzini +Message-id: <20190722182220.19374-12-pbonzini@redhat.com> +Patchwork-id: 89628 +O-Subject: [RHEL-8.1.0 PATCH qemu-kvm v3 11/18] linux-headers: synchronize generic and x86 KVM headers with upstream [rhel-only] +Bugzilla: 1689269 +RH-Acked-by: Peter Xu +RH-Acked-by: Laurent Vivier +RH-Acked-by: Dr. David Alan Gilbert + +From: Liran Alon + +Relevant files copied from upstream QEMU at commit +1d33bea4d013104f01d1c4badc4c670e55c16cca. + +Signed-off-by: Danilo C. L. de Paula +--- + linux-headers/asm-x86/kvm.h | 76 ++++++++++++++++++++++++++++++++++++-- + linux-headers/linux/kvm.h | 89 +++++++++++++++++++++++++++++++++++++++++++-- + 2 files changed, 158 insertions(+), 7 deletions(-) + +diff --git a/linux-headers/asm-x86/kvm.h b/linux-headers/asm-x86/kvm.h +index dcf4dc9..6e7dd79 100644 +--- a/linux-headers/asm-x86/kvm.h ++++ b/linux-headers/asm-x86/kvm.h +@@ -288,6 +288,7 @@ struct kvm_reinject_control { + #define KVM_VCPUEVENT_VALID_SIPI_VECTOR 0x00000002 + #define KVM_VCPUEVENT_VALID_SHADOW 0x00000004 + #define KVM_VCPUEVENT_VALID_SMM 0x00000008 ++#define KVM_VCPUEVENT_VALID_PAYLOAD 0x00000010 + + /* Interrupt shadow states */ + #define KVM_X86_SHADOW_INT_MOV_SS 0x01 +@@ -299,7 +300,7 @@ struct kvm_vcpu_events { + __u8 injected; + __u8 nr; + __u8 has_error_code; +- __u8 pad; ++ __u8 pending; + __u32 error_code; + } exception; + struct { +@@ -322,7 +323,9 @@ struct kvm_vcpu_events { + __u8 smm_inside_nmi; + __u8 latched_init; + } smi; +- __u32 reserved[9]; ++ __u8 reserved[27]; ++ __u8 exception_has_payload; ++ __u64 exception_payload; + }; + + /* for KVM_GET/SET_DEBUGREGS */ +@@ -354,12 +357,79 @@ struct kvm_xcrs { + __u64 padding[16]; + }; + +-/* definition of registers in kvm_run */ ++#define KVM_SYNC_X86_REGS (1UL << 0) ++#define KVM_SYNC_X86_SREGS (1UL << 1) ++#define KVM_SYNC_X86_EVENTS (1UL << 2) ++ ++#define KVM_SYNC_X86_VALID_FIELDS \ ++ (KVM_SYNC_X86_REGS| \ ++ KVM_SYNC_X86_SREGS| \ ++ KVM_SYNC_X86_EVENTS) ++ ++/* kvm_sync_regs struct included by kvm_run struct */ + struct kvm_sync_regs { ++ /* Members of this structure are potentially malicious. ++ * Care must be taken by code reading, esp. interpreting, ++ * data fields from them inside KVM to prevent TOCTOU and ++ * double-fetch types of vulnerabilities. ++ */ ++ struct kvm_regs regs; ++ struct kvm_sregs sregs; ++ struct kvm_vcpu_events events; + }; + + #define KVM_X86_QUIRK_LINT0_REENABLED (1 << 0) + #define KVM_X86_QUIRK_CD_NW_CLEARED (1 << 1) + #define KVM_X86_QUIRK_LAPIC_MMIO_HOLE (1 << 2) ++#define KVM_X86_QUIRK_OUT_7E_INC_RIP (1 << 3) ++ ++#define KVM_STATE_NESTED_FORMAT_VMX 0 ++#define KVM_STATE_NESTED_FORMAT_SVM 1 ++ ++#define KVM_STATE_NESTED_GUEST_MODE 0x00000001 ++#define KVM_STATE_NESTED_RUN_PENDING 0x00000002 ++#define KVM_STATE_NESTED_EVMCS 0x00000004 ++ ++#define KVM_STATE_NESTED_VMX_VMCS_SIZE 0x1000 ++ ++#define KVM_STATE_NESTED_SMM_GUEST_MODE 0x00000001 ++#define KVM_STATE_NESTED_SMM_VMXON 0x00000002 ++ ++struct kvm_vmx_nested_state_data { ++ __u8 vmcs12[KVM_STATE_NESTED_VMX_VMCS_SIZE]; ++ __u8 shadow_vmcs12[KVM_STATE_NESTED_VMX_VMCS_SIZE]; ++}; ++ ++struct kvm_vmx_nested_state_hdr { ++ __u64 vmxon_pa; ++ __u64 vmcs12_pa; ++ ++ struct { ++ __u16 flags; ++ } smm; ++}; ++ ++/* for KVM_CAP_NESTED_STATE */ ++struct kvm_nested_state { ++ __u16 flags; ++ __u16 format; ++ __u32 size; ++ ++ union { ++ struct kvm_vmx_nested_state_hdr vmx; ++ ++ /* Pad the header to 128 bytes. */ ++ __u8 pad[120]; ++ } hdr; ++ ++ /* ++ * Define data region as 0 bytes to preserve backwards-compatability ++ * to old definition of kvm_nested_state in order to avoid changing ++ * KVM_{GET,PUT}_NESTED_STATE ioctl values. ++ */ ++ union { ++ struct kvm_vmx_nested_state_data vmx[0]; ++ } data; ++}; + + #endif /* _ASM_X86_KVM_H */ +diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h +index 8be1232..c8423e7 100644 +--- a/linux-headers/linux/kvm.h ++++ b/linux-headers/linux/kvm.h +@@ -396,6 +396,10 @@ struct kvm_run { + char padding[256]; + }; + ++ /* 2048 is the size of the char array used to bound/pad the size ++ * of the union that holds sync regs. ++ */ ++ #define SYNC_REGS_SIZE_BYTES 2048 + /* + * shared registers between kvm and userspace. + * kvm_valid_regs specifies the register classes set by the host +@@ -407,7 +411,7 @@ struct kvm_run { + __u64 kvm_dirty_regs; + union { + struct kvm_sync_regs regs; +- char padding[2048]; ++ char padding[SYNC_REGS_SIZE_BYTES]; + } s; + }; + +@@ -416,13 +420,19 @@ struct kvm_run { + struct kvm_coalesced_mmio_zone { + __u64 addr; + __u32 size; +- __u32 pad; ++ union { ++ __u32 pad; ++ __u32 pio; ++ }; + }; + + struct kvm_coalesced_mmio { + __u64 phys_addr; + __u32 len; +- __u32 pad; ++ union { ++ __u32 pad; ++ __u32 pio; ++ }; + __u8 data[8]; + }; + +@@ -482,6 +492,17 @@ struct kvm_dirty_log { + }; + }; + ++/* for KVM_CLEAR_DIRTY_LOG */ ++struct kvm_clear_dirty_log { ++ __u32 slot; ++ __u32 num_pages; ++ __u64 first_page; ++ union { ++ void *dirty_bitmap; /* one bit per page */ ++ __u64 padding2; ++ }; ++}; ++ + /* for KVM_SET_SIGNAL_MASK */ + struct kvm_signal_mask { + __u32 len; +@@ -672,6 +693,13 @@ struct kvm_ioeventfd { + __u8 pad[36]; + }; + ++#define KVM_X86_DISABLE_EXITS_MWAIT (1 << 0) ++#define KVM_X86_DISABLE_EXITS_HLT (1 << 1) ++#define KVM_X86_DISABLE_EXITS_PAUSE (1 << 2) ++#define KVM_X86_DISABLE_VALID_EXITS (KVM_X86_DISABLE_EXITS_MWAIT | \ ++ KVM_X86_DISABLE_EXITS_HLT | \ ++ KVM_X86_DISABLE_EXITS_PAUSE) ++ + /* for KVM_ENABLE_CAP */ + struct kvm_enable_cap { + /* in */ +@@ -708,6 +736,7 @@ struct kvm_ppc_one_seg_page_size { + + #define KVM_PPC_PAGE_SIZES_REAL 0x00000001 + #define KVM_PPC_1T_SEGMENTS 0x00000002 ++#define KVM_PPC_NO_HASH 0x00000004 + + struct kvm_ppc_smmu_info { + __u64 flags; +@@ -740,6 +769,15 @@ struct kvm_ppc_resize_hpt { + #define KVM_S390_SIE_PAGE_OFFSET 1 + + /* ++ * On arm64, machine type can be used to request the physical ++ * address size for the VM. Bits[7-0] are reserved for the guest ++ * PA size shift (i.e, log2(PA_Size)). For backward compatibility, ++ * value 0 implies the default IPA size, 40bits. ++ */ ++#define KVM_VM_TYPE_ARM_IPA_SIZE_MASK 0xffULL ++#define KVM_VM_TYPE_ARM_IPA_SIZE(x) \ ++ ((x) & KVM_VM_TYPE_ARM_IPA_SIZE_MASK) ++/* + * ioctls for /dev/kvm fds: + */ + #define KVM_GET_API_VERSION _IO(KVMIO, 0x00) +@@ -925,7 +963,7 @@ struct kvm_ppc_resize_hpt { + #define KVM_CAP_S390_GS 140 + #define KVM_CAP_S390_AIS 141 + #define KVM_CAP_SPAPR_TCE_VFIO 142 +-#define KVM_CAP_X86_GUEST_MWAIT 143 ++#define KVM_CAP_X86_DISABLE_EXITS 143 + #define KVM_CAP_ARM_USER_IRQ 144 + #define KVM_CAP_S390_CMMA_MIGRATION 145 + #define KVM_CAP_PPC_FWNMI 146 +@@ -936,11 +974,25 @@ struct kvm_ppc_resize_hpt { + #define KVM_CAP_PPC_GET_CPU_CHAR 151 + #define KVM_CAP_S390_BPB 152 + #define KVM_CAP_GET_MSR_FEATURES 153 ++#define KVM_CAP_HYPERV_EVENTFD 154 ++#define KVM_CAP_HYPERV_TLBFLUSH 155 + #define KVM_CAP_S390_HPAGE_1M 156 + #define KVM_CAP_NESTED_STATE 157 + #define KVM_CAP_ARM_INJECT_SERROR_ESR 158 + #define KVM_CAP_MSR_PLATFORM_INFO 159 + #define KVM_CAP_PPC_NESTED_HV 160 ++#define KVM_CAP_HYPERV_SEND_IPI 161 ++#define KVM_CAP_COALESCED_PIO 162 ++#define KVM_CAP_HYPERV_ENLIGHTENED_VMCS 163 ++#define KVM_CAP_EXCEPTION_PAYLOAD 164 ++#define KVM_CAP_ARM_VM_IPA_SIZE 165 ++#define KVM_CAP_MANUAL_DIRTY_LOG_PROTECT 166 /* Obsolete */ ++#define KVM_CAP_HYPERV_CPUID 167 ++#define KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2 168 ++#define KVM_CAP_PPC_IRQ_XIVE 169 ++#define KVM_CAP_ARM_SVE 170 ++#define KVM_CAP_ARM_PTRAUTH_ADDRESS 171 ++#define KVM_CAP_ARM_PTRAUTH_GENERIC 172 + + #ifdef KVM_CAP_IRQ_ROUTING + +@@ -1098,6 +1150,7 @@ struct kvm_dirty_tlb { + #define KVM_REG_SIZE_U256 0x0050000000000000ULL + #define KVM_REG_SIZE_U512 0x0060000000000000ULL + #define KVM_REG_SIZE_U1024 0x0070000000000000ULL ++#define KVM_REG_SIZE_U2048 0x0080000000000000ULL + + struct kvm_reg_list { + __u64 n; /* number of regs */ +@@ -1164,6 +1217,8 @@ enum kvm_device_type { + #define KVM_DEV_TYPE_ARM_VGIC_V3 KVM_DEV_TYPE_ARM_VGIC_V3 + KVM_DEV_TYPE_ARM_VGIC_ITS, + #define KVM_DEV_TYPE_ARM_VGIC_ITS KVM_DEV_TYPE_ARM_VGIC_ITS ++ KVM_DEV_TYPE_XIVE, ++#define KVM_DEV_TYPE_XIVE KVM_DEV_TYPE_XIVE + KVM_DEV_TYPE_MAX, + }; + +@@ -1380,6 +1435,22 @@ struct kvm_enc_region { + #define KVM_MEMORY_ENCRYPT_REG_REGION _IOR(KVMIO, 0xbb, struct kvm_enc_region) + #define KVM_MEMORY_ENCRYPT_UNREG_REGION _IOR(KVMIO, 0xbc, struct kvm_enc_region) + ++/* Available with KVM_CAP_HYPERV_EVENTFD */ ++#define KVM_HYPERV_EVENTFD _IOW(KVMIO, 0xbd, struct kvm_hyperv_eventfd) ++ ++/* Available with KVM_CAP_NESTED_STATE */ ++#define KVM_GET_NESTED_STATE _IOWR(KVMIO, 0xbe, struct kvm_nested_state) ++#define KVM_SET_NESTED_STATE _IOW(KVMIO, 0xbf, struct kvm_nested_state) ++ ++/* Available with KVM_CAP_MANUAL_DIRTY_LOG_PROTECT_2 */ ++#define KVM_CLEAR_DIRTY_LOG _IOWR(KVMIO, 0xc0, struct kvm_clear_dirty_log) ++ ++/* Available with KVM_CAP_HYPERV_CPUID */ ++#define KVM_GET_SUPPORTED_HV_CPUID _IOWR(KVMIO, 0xc1, struct kvm_cpuid2) ++ ++/* Available with KVM_CAP_ARM_SVE */ ++#define KVM_ARM_VCPU_FINALIZE _IOW(KVMIO, 0xc2, int) ++ + /* Secure Encrypted Virtualization command */ + enum sev_cmd_id { + /* Guest initialization commands */ +@@ -1520,4 +1591,14 @@ struct kvm_assigned_msix_entry { + #define KVM_ARM_DEV_EL1_PTIMER (1 << 1) + #define KVM_ARM_DEV_PMU (1 << 2) + ++struct kvm_hyperv_eventfd { ++ __u32 conn_id; ++ __s32 fd; ++ __u32 flags; ++ __u32 padding[3]; ++}; ++ ++#define KVM_HYPERV_CONN_ID_MASK 0x00ffffff ++#define KVM_HYPERV_EVENTFD_DEASSIGN (1 << 0) ++ + #endif /* __LINUX_KVM_H */ +-- +1.8.3.1 + diff --git a/SOURCES/kvm-mmap-alloc-fix-hugetlbfs-misaligned-length-in-ppc64.patch b/SOURCES/kvm-mmap-alloc-fix-hugetlbfs-misaligned-length-in-ppc64.patch new file mode 100644 index 0000000..c3f4fa9 --- /dev/null +++ b/SOURCES/kvm-mmap-alloc-fix-hugetlbfs-misaligned-length-in-ppc64.patch @@ -0,0 +1,174 @@ +From e69f257e657473ba59f48692d387e292a24892bb Mon Sep 17 00:00:00 2001 +From: "plai@redhat.com" +Date: Tue, 20 Aug 2019 16:12:50 +0100 +Subject: [PATCH 03/11] mmap-alloc: fix hugetlbfs misaligned length in ppc64 + +RH-Author: plai@redhat.com +Message-id: <1566317571-5697-4-git-send-email-plai@redhat.com> +Patchwork-id: 90082 +O-Subject: [RHEL8.2 qemu-kvm PATCH 3/4] mmap-alloc: fix hugetlbfs misaligned length in ppc64 +Bugzilla: 1539282 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Pankaj Gupta +RH-Acked-by: Eduardo Habkost + +From: Murilo Opsfelder Araujo + +The commit 7197fb4058bcb68986bae2bb2c04d6370f3e7218 ("util/mmap-alloc: +fix hugetlb support on ppc64") fixed Huge TLB mappings on ppc64. + +However, we still need to consider the underlying huge page size +during munmap() because it requires that both address and length be a +multiple of the underlying huge page size for Huge TLB mappings. +Quote from "Huge page (Huge TLB) mappings" paragraph under NOTES +section of the munmap(2) manual: + + "For munmap(), addr and length must both be a multiple of the + underlying huge page size." + +On ppc64, the munmap() in qemu_ram_munmap() does not work for Huge TLB +mappings because the mapped segment can be aligned with the underlying +huge page size, not aligned with the native system page size, as +returned by getpagesize(). + +This has the side effect of not releasing huge pages back to the pool +after a hugetlbfs file-backed memory device is hot-unplugged. + +This patch fixes the situation in qemu_ram_mmap() and +qemu_ram_munmap() by considering the underlying page size on ppc64. + +After this patch, memory hot-unplug releases huge pages back to the +pool. + +Fixes: 7197fb4058bcb68986bae2bb2c04d6370f3e7218 +Signed-off-by: Murilo Opsfelder Araujo +Reviewed-by: Greg Kurz +Signed-off-by: David Gibson +(cherry picked from commit 53adb9d43e1abba187387a51f238e878e934c647) +Signed-off-by: Paul Lai +Signed-off-by: Danilo C. L. de Paula +--- + exec.c | 4 ++-- + include/qemu/mmap-alloc.h | 2 +- + util/mmap-alloc.c | 22 ++++++++++++++++------ + util/oslib-posix.c | 2 +- + 4 files changed, 20 insertions(+), 10 deletions(-) + +diff --git a/exec.c b/exec.c +index a79eaa3..9112d8b 100644 +--- a/exec.c ++++ b/exec.c +@@ -1679,7 +1679,7 @@ static void *file_ram_alloc(RAMBlock *block, + if (mem_prealloc) { + os_mem_prealloc(fd, area, memory, smp_cpus, errp); + if (errp && *errp) { +- qemu_ram_munmap(area, memory); ++ qemu_ram_munmap(fd, area, memory); + return NULL; + } + } +@@ -2200,7 +2200,7 @@ static void reclaim_ramblock(RAMBlock *block) + xen_invalidate_map_cache_entry(block->host); + #ifndef _WIN32 + } else if (block->fd >= 0) { +- qemu_ram_munmap(block->host, block->max_length); ++ qemu_ram_munmap(block->fd, block->host, block->max_length); + close(block->fd); + #endif + } else { +diff --git a/include/qemu/mmap-alloc.h b/include/qemu/mmap-alloc.h +index 190688a..eec98d8 100644 +--- a/include/qemu/mmap-alloc.h ++++ b/include/qemu/mmap-alloc.h +@@ -28,6 +28,6 @@ void *qemu_ram_mmap(int fd, + bool shared, + bool is_pmem); + +-void qemu_ram_munmap(void *ptr, size_t size); ++void qemu_ram_munmap(int fd, void *ptr, size_t size); + + #endif +diff --git a/util/mmap-alloc.c b/util/mmap-alloc.c +index b29fcee..bbd9077 100644 +--- a/util/mmap-alloc.c ++++ b/util/mmap-alloc.c +@@ -82,6 +82,7 @@ void *qemu_ram_mmap(int fd, + int flags; + int guardfd; + size_t offset; ++ size_t pagesize; + size_t total; + void *guardptr; + void *ptr; +@@ -102,7 +103,8 @@ void *qemu_ram_mmap(int fd, + * anonymous memory is OK. + */ + flags = MAP_PRIVATE; +- if (fd == -1 || qemu_fd_getpagesize(fd) == getpagesize()) { ++ pagesize = qemu_fd_getpagesize(fd); ++ if (fd == -1 || pagesize == getpagesize()) { + guardfd = -1; + flags |= MAP_ANONYMOUS; + } else { +@@ -111,6 +113,7 @@ void *qemu_ram_mmap(int fd, + } + #else + guardfd = -1; ++ pagesize = getpagesize(); + flags = MAP_PRIVATE | MAP_ANONYMOUS; + #endif + +@@ -122,7 +125,7 @@ void *qemu_ram_mmap(int fd, + + assert(is_power_of_2(align)); + /* Always align to host page size */ +- assert(align >= getpagesize()); ++ assert(align >= pagesize); + + flags = MAP_FIXED; + flags |= fd == -1 ? MAP_ANONYMOUS : 0; +@@ -145,17 +148,24 @@ void *qemu_ram_mmap(int fd, + * a guard page guarding against potential buffer overflows. + */ + total -= offset; +- if (total > size + getpagesize()) { +- munmap(ptr + size + getpagesize(), total - size - getpagesize()); ++ if (total > size + pagesize) { ++ munmap(ptr + size + pagesize, total - size - pagesize); + } + + return ptr; + } + +-void qemu_ram_munmap(void *ptr, size_t size) ++void qemu_ram_munmap(int fd, void *ptr, size_t size) + { ++ size_t pagesize; ++ + if (ptr) { + /* Unmap both the RAM block and the guard page */ +- munmap(ptr, size + getpagesize()); ++#if defined(__powerpc64__) && defined(__linux__) ++ pagesize = qemu_fd_getpagesize(fd); ++#else ++ pagesize = getpagesize(); ++#endif ++ munmap(ptr, size + pagesize); + } + } +diff --git a/util/oslib-posix.c b/util/oslib-posix.c +index c36b2bb..7b6db04 100644 +--- a/util/oslib-posix.c ++++ b/util/oslib-posix.c +@@ -153,7 +153,7 @@ void qemu_vfree(void *ptr) + void qemu_anon_ram_free(void *ptr, size_t size) + { + trace_qemu_anon_ram_free(ptr, size); +- qemu_ram_munmap(ptr, size); ++ qemu_ram_munmap(-1, ptr, size); + } + + void qemu_set_block(int fd) +-- +1.8.3.1 + diff --git a/SOURCES/kvm-mmap-alloc-unfold-qemu_ram_mmap.patch b/SOURCES/kvm-mmap-alloc-unfold-qemu_ram_mmap.patch new file mode 100644 index 0000000..fdc21ec --- /dev/null +++ b/SOURCES/kvm-mmap-alloc-unfold-qemu_ram_mmap.patch @@ -0,0 +1,139 @@ +From 6b3478bb8b5718d86cb04f41043a8e0cce4df24c Mon Sep 17 00:00:00 2001 +From: "plai@redhat.com" +Date: Tue, 20 Aug 2019 16:12:49 +0100 +Subject: [PATCH 02/11] mmap-alloc: unfold qemu_ram_mmap() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: plai@redhat.com +Message-id: <1566317571-5697-3-git-send-email-plai@redhat.com> +Patchwork-id: 90083 +O-Subject: [RHEL8.2 qemu-kvm PATCH 2/4] mmap-alloc: unfold qemu_ram_mmap() +Bugzilla: 1539282 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Pankaj Gupta +RH-Acked-by: Eduardo Habkost + +From: Murilo Opsfelder Araujo + +Unfold parts of qemu_ram_mmap() for the sake of understanding, moving +declarations to the top, and keeping architecture-specifics in the +ifdef-else blocks. No changes in the function behaviour. + +Give ptr and ptr1 meaningful names: + ptr -> guardptr : pointer to the PROT_NONE guard region + ptr1 -> ptr : pointer to the mapped memory returned to caller + +Signed-off-by: Murilo Opsfelder Araujo +Reviewed-by: Greg Kurz +Signed-off-by: David Gibson +(cherry picked from commit 2044c3e7116eeac0449dcb4a4130cc8f8b9310da) +Signed-off-by: Paul Lai +Signed-off-by: Danilo C. L. de Paula +--- + util/mmap-alloc.c | 53 ++++++++++++++++++++++++++++++++++------------------- + 1 file changed, 34 insertions(+), 19 deletions(-) + +diff --git a/util/mmap-alloc.c b/util/mmap-alloc.c +index 55d1890..b29fcee 100644 +--- a/util/mmap-alloc.c ++++ b/util/mmap-alloc.c +@@ -79,11 +79,19 @@ void *qemu_ram_mmap(int fd, + bool shared, + bool is_pmem) + { ++ int flags; ++ int guardfd; ++ size_t offset; ++ size_t total; ++ void *guardptr; ++ void *ptr; ++ + /* + * Note: this always allocates at least one extra page of virtual address + * space, even if size is already aligned. + */ +- size_t total = size + align; ++ total = size + align; ++ + #if defined(__powerpc64__) && defined(__linux__) + /* On ppc64 mappings in the same segment (aka slice) must share the same + * page size. Since we will be re-allocating part of this segment +@@ -93,16 +101,22 @@ void *qemu_ram_mmap(int fd, + * We do this unless we are using the system page size, in which case + * anonymous memory is OK. + */ +- int anonfd = fd == -1 || qemu_fd_getpagesize(fd) == getpagesize() ? -1 : fd; +- int flags = anonfd == -1 ? MAP_ANONYMOUS : MAP_NORESERVE; +- void *ptr = mmap(0, total, PROT_NONE, flags | MAP_PRIVATE, anonfd, 0); ++ flags = MAP_PRIVATE; ++ if (fd == -1 || qemu_fd_getpagesize(fd) == getpagesize()) { ++ guardfd = -1; ++ flags |= MAP_ANONYMOUS; ++ } else { ++ guardfd = fd; ++ flags |= MAP_NORESERVE; ++ } + #else +- void *ptr = mmap(0, total, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); ++ guardfd = -1; ++ flags = MAP_PRIVATE | MAP_ANONYMOUS; + #endif +- size_t offset; +- void *ptr1; + +- if (ptr == MAP_FAILED) { ++ guardptr = mmap(0, total, PROT_NONE, flags, guardfd, 0); ++ ++ if (guardptr == MAP_FAILED) { + return MAP_FAILED; + } + +@@ -110,19 +124,20 @@ void *qemu_ram_mmap(int fd, + /* Always align to host page size */ + assert(align >= getpagesize()); + +- offset = QEMU_ALIGN_UP((uintptr_t)ptr, align) - (uintptr_t)ptr; +- ptr1 = mmap(ptr + offset, size, PROT_READ | PROT_WRITE, +- MAP_FIXED | +- (fd == -1 ? MAP_ANONYMOUS : 0) | +- (shared ? MAP_SHARED : MAP_PRIVATE), +- fd, 0); +- if (ptr1 == MAP_FAILED) { +- munmap(ptr, total); ++ flags = MAP_FIXED; ++ flags |= fd == -1 ? MAP_ANONYMOUS : 0; ++ flags |= shared ? MAP_SHARED : MAP_PRIVATE; ++ offset = QEMU_ALIGN_UP((uintptr_t)guardptr, align) - (uintptr_t)guardptr; ++ ++ ptr = mmap(guardptr + offset, size, PROT_READ | PROT_WRITE, flags, fd, 0); ++ ++ if (ptr == MAP_FAILED) { ++ munmap(guardptr, total); + return MAP_FAILED; + } + + if (offset > 0) { +- munmap(ptr, offset); ++ munmap(guardptr, offset); + } + + /* +@@ -131,10 +146,10 @@ void *qemu_ram_mmap(int fd, + */ + total -= offset; + if (total > size + getpagesize()) { +- munmap(ptr1 + size + getpagesize(), total - size - getpagesize()); ++ munmap(ptr + size + getpagesize(), total - size - getpagesize()); + } + +- return ptr1; ++ return ptr; + } + + void qemu_ram_munmap(void *ptr, size_t size) +-- +1.8.3.1 + diff --git a/SOURCES/kvm-nbd-client-Lower-min_block-for-block-status-unaligne.patch b/SOURCES/kvm-nbd-client-Lower-min_block-for-block-status-unaligne.patch new file mode 100644 index 0000000..1573c0f --- /dev/null +++ b/SOURCES/kvm-nbd-client-Lower-min_block-for-block-status-unaligne.patch @@ -0,0 +1,119 @@ +From 569674a3b855f516a8bec22ca365fc7614639ce6 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Tue, 23 Jul 2019 14:45:42 +0100 +Subject: [PATCH 04/14] nbd/client: Lower min_block for block-status, unaligned + size + +RH-Author: Max Reitz +Message-id: <20190723144546.23701-4-mreitz@redhat.com> +Patchwork-id: 89650 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 3/7] nbd/client: Lower min_block for block-status, unaligned size +Bugzilla: 1678979 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Stefano Garzarella +RH-Acked-by: John Snow + +From: Eric Blake + +We have a latent bug in our NBD client code, tickled by the brand new +nbdkit 1.11.10 block status support: + +$ nbdkit --filter=log --filter=truncate -U - \ + data data="1" size=511 truncate=64K logfile=/dev/stdout \ + --run 'qemu-img convert $nbd /var/tmp/out' +... +qemu-img: block/io.c:2122: bdrv_co_block_status: Assertion `*pnum && QEMU_IS_ALIGNED(*pnum, align) && align > offset - aligned_offset' failed. + +The culprit? Our implementation of .bdrv_co_block_status can return +unaligned block status for any server that operates with a lower +actual alignment than what we tell the block layer in +request_alignment, in violation of the block layer's constraints. To +date, we've been unable to trip the bug, because qemu as NBD server +always advertises block sizing (at which point it is a server bug if +the server sends unaligned status - although qemu 3.1 is such a server +and I've sent separate patches for 4.0 both to get the server to obey +the spec, and to let the client to tolerate server oddities at EOF). + +But nbdkit does not (yet) advertise block sizing, and therefore is not +in violation of the spec for returning block status at whatever +boundaries it wants, and those unaligned results can occur anywhere +rather than just at EOF. While we are still wise to avoid sending +sub-sector read/write requests to a server of unknown origin, we MUST +consider that a server telling us block status without an advertised +block size is correct. So, we either have to munge unaligned answers +from the server into aligned ones that we hand back to the block +layer, or we have to tell the block layer about a smaller alignment. + +Similarly, if the server advertises an image size that is not +sector-aligned, we might as well assume that the server intends to let +us access those tail bytes, and therefore supports a minimum block +size of 1, regardless of whether the server supports block status +(although we still need more patches to fix the problem that with an +unaligned image, we can send read or block status requests that exceed +EOF to the server). Again, qemu as server cannot trip this problem +(because it rounds images to sector alignment), but nbdkit advertised +unaligned size even before it gained block status support. + +Solve both alignment problems at once by using better heuristics on +what alignment to report to the block layer when the server did not +give us something to work with. Note that very few NBD servers +implement block status (to date, only qemu and nbdkit are known to do +so); and as the NBD spec mentioned block sizing constraints prior to +documenting block status, it can be assumed that any future +implementations of block status are aware that they must advertise +block size if they want a minimum size other than 1. + +We've had a long history of struggles with picking the right alignment +to use in the block layer, as evidenced by the commit message of +fd8d372d (v2.12) that introduced the current choice of forced 512-byte +alignment. + +There is no iotest coverage for this fix, because qemu can't provoke +it, and I didn't want to make test 241 dependent on nbdkit. + +Fixes: fd8d372d +Reported-by: Richard W.M. Jones +Signed-off-by: Eric Blake +Message-Id: <20190329042750.14704-3-eblake@redhat.com> +Reviewed-by: Vladimir Sementsov-Ogievskiy +Tested-by: Richard W.M. Jones +(cherry picked from commit 7da537f70d929800ba9c657b8a47a7b827695ccc) +Signed-off-by: Max Reitz +Signed-off-by: Danilo C. L. de Paula +--- + block/nbd.c | 19 ++++++++++++++++++- + 1 file changed, 18 insertions(+), 1 deletion(-) + +diff --git a/block/nbd.c b/block/nbd.c +index f29c10f..3d642cd 100644 +--- a/block/nbd.c ++++ b/block/nbd.c +@@ -473,7 +473,24 @@ static void nbd_refresh_limits(BlockDriverState *bs, Error **errp) + uint32_t min = s->info.min_block; + uint32_t max = MIN_NON_ZERO(NBD_MAX_BUFFER_SIZE, s->info.max_block); + +- bs->bl.request_alignment = min ? min : BDRV_SECTOR_SIZE; ++ /* ++ * If the server did not advertise an alignment: ++ * - a size that is not sector-aligned implies that an alignment ++ * of 1 can be used to access those tail bytes ++ * - advertisement of block status requires an alignment of 1, so ++ * that we don't violate block layer constraints that block ++ * status is always aligned (as we can't control whether the ++ * server will report sub-sector extents, such as a hole at EOF ++ * on an unaligned POSIX file) ++ * - otherwise, assume the server is so old that we are safer avoiding ++ * sub-sector requests ++ */ ++ if (!min) { ++ min = (!QEMU_IS_ALIGNED(s->info.size, BDRV_SECTOR_SIZE) || ++ s->info.base_allocation) ? 1 : BDRV_SECTOR_SIZE; ++ } ++ ++ bs->bl.request_alignment = min; + bs->bl.max_pdiscard = max; + bs->bl.max_pwrite_zeroes = max; + bs->bl.max_transfer = max; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-nbd-client-Reject-inaccessible-tail-of-inconsistent-.patch b/SOURCES/kvm-nbd-client-Reject-inaccessible-tail-of-inconsistent-.patch new file mode 100644 index 0000000..9061a46 --- /dev/null +++ b/SOURCES/kvm-nbd-client-Reject-inaccessible-tail-of-inconsistent-.patch @@ -0,0 +1,64 @@ +From e49b010d5f866b3ee7efbf40398f0a0832ce8801 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Tue, 23 Jul 2019 14:45:43 +0100 +Subject: [PATCH 05/14] nbd/client: Reject inaccessible tail of inconsistent + server + +RH-Author: Max Reitz +Message-id: <20190723144546.23701-5-mreitz@redhat.com> +Patchwork-id: 89649 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 4/7] nbd/client: Reject inaccessible tail of inconsistent server +Bugzilla: 1678979 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Stefano Garzarella +RH-Acked-by: John Snow + +From: Eric Blake + +The NBD spec suggests that a server should never advertise a size +inconsistent with its minimum block alignment, as that tail is +effectively inaccessible to a compliant client obeying those block +constraints. Since we have a habit of rounding up rather than +truncating, to avoid losing the last few bytes of user input, and we +cannot access the tail when the server advertises bogus block sizing, +abort the connection to alert the server to fix their bug. And +rejecting such servers matches what we already did for a min_block +that was not a power of 2 or which was larger than max_block. + +Does not impact either qemu (which always sends properly aligned +sizes) or nbdkit (which does not send minimum block requirements yet); +so this is mostly aimed at new NBD server implementations, and ensures +that the rest of our code can assume the size is aligned. + +Signed-off-by: Eric Blake +Message-Id: <20190330155704.24191-1-eblake@redhat.com> +Reviewed-by: Vladimir Sementsov-Ogievskiy +(cherry picked from commit 3add3ab78247fd347fd6f377a4b951022ac35d35) +Signed-off-by: Max Reitz +Signed-off-by: Danilo C. L. de Paula +--- + nbd/client.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/nbd/client.c b/nbd/client.c +index 25603f2..c828faf 100644 +--- a/nbd/client.c ++++ b/nbd/client.c +@@ -416,6 +416,14 @@ static int nbd_opt_go(QIOChannel *ioc, const char *wantname, + nbd_send_opt_abort(ioc); + return -1; + } ++ if (info->min_block && ++ !QEMU_IS_ALIGNED(info->size, info->min_block)) { ++ error_setg(errp, "export size %" PRIu64 "is not multiple of " ++ "minimum block size %" PRIu32, info->size, ++ info->min_block); ++ nbd_send_opt_abort(ioc); ++ return -1; ++ } + be16_to_cpus(&info->flags); + trace_nbd_receive_negotiate_size_flags(info->size, info->flags); + break; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-nbd-client-Support-qemu-img-convert-from-unaligned-s.patch b/SOURCES/kvm-nbd-client-Support-qemu-img-convert-from-unaligned-s.patch new file mode 100644 index 0000000..fe47c31 --- /dev/null +++ b/SOURCES/kvm-nbd-client-Support-qemu-img-convert-from-unaligned-s.patch @@ -0,0 +1,132 @@ +From 25bfe4a95b02b6fefafdfa1651c50a4d0c5bc87b Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Tue, 23 Jul 2019 14:45:44 +0100 +Subject: [PATCH 06/14] nbd/client: Support qemu-img convert from unaligned + size + +RH-Author: Max Reitz +Message-id: <20190723144546.23701-6-mreitz@redhat.com> +Patchwork-id: 89651 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 5/7] nbd/client: Support qemu-img convert from unaligned size +Bugzilla: 1678979 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Stefano Garzarella +RH-Acked-by: John Snow + +From: Eric Blake + +If an NBD server advertises a size that is not a multiple of a sector, +the block layer rounds up that size, even though we set info.size to +the exact byte value sent by the server. The block layer then proceeds +to let us read or query block status on the hole that it added past +EOF, which the NBD server is unlikely to be happy with. Fortunately, +qemu as a server never advertizes an unaligned size, so we generally +don't run into this problem; but the nbdkit server makes it easy to +test: + +$ printf %1000d 1 > f1 +$ ~/nbdkit/nbdkit -fv file f1 & pid=$! +$ qemu-img convert -f raw nbd://localhost:10809 f2 +$ kill $pid +$ qemu-img compare f1 f2 + +Pre-patch, the server attempts a 1024-byte read, which nbdkit +rightfully rejects as going beyond its advertised 1000 byte size; the +conversion fails and the output files differ (not even the first +sector is copied, because qemu-img does not follow ddrescue's habit of +trying smaller reads to get as much information as possible in spite +of errors). Post-patch, the client's attempts to read (and query block +status, for new enough nbdkit) are properly truncated to the server's +length, with sane handling of the hole the block layer forced on +us. Although f2 ends up as a larger file (1024 bytes instead of 1000), +qemu-img compare shows the two images to have identical contents for +display to the guest. + +I didn't add iotests coverage since I didn't want to add a dependency +on nbdkit in iotests. I also did NOT patch write, trim, or write +zeroes - these commands continue to fail (usually with ENOSPC, but +whatever the server chose), because we really can't write to the end +of the file, and because 'qemu-img convert' is the most common case +where we care about being tolerant (which is read-only). Perhaps we +could truncate the request if the client is writing zeros to the tail, +but that seems like more work, especially if the block layer is fixed +in 4.1 to track byte-accurate sizing (in which case this patch would +be reverted as unnecessary). + +Signed-off-by: Eric Blake +Message-Id: <20190329042750.14704-5-eblake@redhat.com> +Tested-by: Richard W.M. Jones +(cherry picked from commit 9cf638508c0090b33ada4155c7cbb684e08e5ee9) +Signed-off-by: Max Reitz +Signed-off-by: Danilo C. L. de Paula +--- + block/nbd-client.c | 39 ++++++++++++++++++++++++++++++++++++++- + 1 file changed, 38 insertions(+), 1 deletion(-) + +diff --git a/block/nbd-client.c b/block/nbd-client.c +index 80d3625..6b33fe3 100644 +--- a/block/nbd-client.c ++++ b/block/nbd-client.c +@@ -790,6 +790,25 @@ int nbd_client_co_preadv(BlockDriverState *bs, uint64_t offset, + if (!bytes) { + return 0; + } ++ /* ++ * Work around the fact that the block layer doesn't do ++ * byte-accurate sizing yet - if the read exceeds the server's ++ * advertised size because the block layer rounded size up, then ++ * truncate the request to the server and tail-pad with zero. ++ */ ++ if (offset >= client->info.size) { ++ assert(bytes < BDRV_SECTOR_SIZE); ++ qemu_iovec_memset(qiov, 0, 0, bytes); ++ return 0; ++ } ++ if (offset + bytes > client->info.size) { ++ uint64_t slop = offset + bytes - client->info.size; ++ ++ assert(slop < BDRV_SECTOR_SIZE); ++ qemu_iovec_memset(qiov, bytes - slop, 0, slop); ++ request.len -= slop; ++ } ++ + ret = nbd_co_send_request(bs, &request, NULL); + if (ret < 0) { + return ret; +@@ -904,7 +923,8 @@ int coroutine_fn nbd_client_co_block_status(BlockDriverState *bs, + .from = offset, + .len = MIN(MIN_NON_ZERO(QEMU_ALIGN_DOWN(INT_MAX, + bs->bl.request_alignment), +- client->info.max_block), bytes), ++ client->info.max_block), ++ MIN(bytes, client->info.size - offset)), + .flags = NBD_CMD_FLAG_REQ_ONE, + }; + +@@ -913,6 +933,23 @@ int coroutine_fn nbd_client_co_block_status(BlockDriverState *bs, + return BDRV_BLOCK_DATA; + } + ++ /* ++ * Work around the fact that the block layer doesn't do ++ * byte-accurate sizing yet - if the status request exceeds the ++ * server's advertised size because the block layer rounded size ++ * up, we truncated the request to the server (above), or are ++ * called on just the hole. ++ */ ++ if (offset >= client->info.size) { ++ *pnum = bytes; ++ assert(bytes < BDRV_SECTOR_SIZE); ++ /* Intentionally don't report offset_valid for the hole */ ++ return BDRV_BLOCK_ZERO; ++ } ++ ++ if (client->info.min_block) { ++ assert(QEMU_IS_ALIGNED(request.len, client->info.min_block)); ++ } + ret = nbd_co_send_request(bs, &request, NULL); + if (ret < 0) { + return ret; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-nbd-server-Advertise-actual-minimum-block-size.patch b/SOURCES/kvm-nbd-server-Advertise-actual-minimum-block-size.patch new file mode 100644 index 0000000..b9312c3 --- /dev/null +++ b/SOURCES/kvm-nbd-server-Advertise-actual-minimum-block-size.patch @@ -0,0 +1,120 @@ +From 1832a90928232cb91a8542613b754079fd1f0f0e Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Tue, 23 Jul 2019 14:45:46 +0100 +Subject: [PATCH 08/14] nbd/server: Advertise actual minimum block size + +RH-Author: Max Reitz +Message-id: <20190723144546.23701-8-mreitz@redhat.com> +Patchwork-id: 89652 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 7/7] nbd/server: Advertise actual minimum block size +Bugzilla: 1678979 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Stefano Garzarella +RH-Acked-by: John Snow + +From: Eric Blake + +Both NBD_CMD_BLOCK_STATUS and structured NBD_CMD_READ will split their +reply according to bdrv_block_status() boundaries. If the block device +has a request_alignment smaller than 512, but we advertise a block +alignment of 512 to the client, then this can result in the server +reply violating client expectations by reporting a smaller region of +the export than what the client is permitted to address (although this +is less of an issue for qemu 4.0 clients, given recent client patches +to overlook our non-compliance at EOF). Since it's always better to +be strict in what we send, it is worth advertising the actual minimum +block limit rather than blindly rounding it up to 512. + +Note that this patch is not foolproof - it is still possible to +provoke non-compliant server behavior using: + +$ qemu-nbd --image-opts driver=blkdebug,align=512,image.driver=file,image.filename=/path/to/non-aligned-file + +That is arguably a bug in the blkdebug driver (it should never pass +back block status smaller than its alignment, even if it has to make +multiple bdrv_get_status calls and determine the +least-common-denominator status among the group to return). It may +also be possible to observe issues with a backing layer with smaller +alignment than the active layer, although so far I have been unable to +write a reliable iotest for that scenario (but again, an issue like +that could be argued to be a bug in the block layer, or something +where we need a flag to bdrv_block_status() to state whether the +result must be aligned to the current layer's limits or can be +subdivided for accuracy when chasing backing files). + +Anyways, as blkdebug is not normally used, and as this patch makes our +server more interoperable with qemu 3.1 clients, it is worth applying +now, even while we still work on a larger patch series for the 4.1 +timeframe to have byte-accurate file lengths. + +Note that the iotests output changes - for 223 and 233, we can see the +server's better granularity advertisement; and for 241, the three test +cases have the following effects: +- natural alignment: the server's smaller alignment is now advertised, +and the hole reported at EOF is now the right result; we've gotten rid +of the server's non-compliance +- forced server alignment: the server still advertises 512 bytes, but +still sends a mid-sector hole. This is still a server compliance bug, +which needs to be fixed in the block layer in a later patch; output +does not change because the client is already being tolerant of the +non-compliance +- forced client alignment: the server's smaller alignment means that +the client now sees the server's status change mid-sector without any +protocol violations, but the fact that the map shows an unaligned +mid-sector hole is evidence of the block layer problems with aligned +block status, to be fixed in a later patch + +Signed-off-by: Eric Blake +Message-Id: <20190329042750.14704-7-eblake@redhat.com> +Reviewed-by: Vladimir Sementsov-Ogievskiy +[eblake: rebase to enhanced iotest 241 coverage] +(cherry picked from commit b0245d6478ea5906e3d7a542244d5c015fd47bc7) + +Signed-off-by: Danilo C. L. de Paula + +Conflicts: +- tests/qemu-iotests/223.out: We are missing + ddd09448fd833d646952c769ae9ce3d39bee989f downstream, which adds + qemu-nbd --list tests to 223. (qemu-nbd --list does not exist + downstream.) + +- tests/qemu-iotests/233.out: Does not exist downstream. + +- tests/qemu-iotests/241.out: Does not exist downstream, because it + would require qemu-nbd --list. + +Signed-off-by: Max Reitz +Signed-off-by: Danilo C. L. de Paula +--- + nbd/server.c | 13 ++++++++----- + 1 file changed, 8 insertions(+), 5 deletions(-) + +diff --git a/nbd/server.c b/nbd/server.c +index e094300..96b6631 100644 +--- a/nbd/server.c ++++ b/nbd/server.c +@@ -608,13 +608,16 @@ static int nbd_negotiate_handle_info(NBDClient *client, uint16_t myflags, + /* Send NBD_INFO_BLOCK_SIZE always, but tweak the minimum size + * according to whether the client requested it, and according to + * whether this is OPT_INFO or OPT_GO. */ +- /* minimum - 1 for back-compat, or 512 if client is new enough. +- * TODO: consult blk_bs(blk)->bl.request_alignment? */ +- sizes[0] = +- (client->opt == NBD_OPT_INFO || blocksize) ? BDRV_SECTOR_SIZE : 1; ++ /* minimum - 1 for back-compat, or actual if client will obey it. */ ++ if (client->opt == NBD_OPT_INFO || blocksize) { ++ sizes[0] = blk_get_request_alignment(exp->blk); ++ } else { ++ sizes[0] = 1; ++ } ++ assert(sizes[0] <= NBD_MAX_BUFFER_SIZE); + /* preferred - Hard-code to 4096 for now. + * TODO: is blk_bs(blk)->bl.opt_transfer appropriate? */ +- sizes[1] = 4096; ++ sizes[1] = MAX(4096, sizes[0]); + /* maximum - At most 32M, but smaller as appropriate. */ + sizes[2] = MIN(blk_get_max_transfer(exp->blk), NBD_MAX_BUFFER_SIZE); + trace_nbd_negotiate_handle_info_block_size(sizes[0], sizes[1], sizes[2]); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-opts-don-t-silently-truncate-long-option-values.patch b/SOURCES/kvm-opts-don-t-silently-truncate-long-option-values.patch new file mode 100644 index 0000000..f338282 --- /dev/null +++ b/SOURCES/kvm-opts-don-t-silently-truncate-long-option-values.patch @@ -0,0 +1,398 @@ +From 6abc65aaa666bf41070fa772293982cb0d1ae835 Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Thu, 12 Sep 2019 13:05:00 +0100 +Subject: [PATCH 03/22] opts: don't silently truncate long option values +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Laszlo Ersek +Message-id: <20190912130503.14094-4-lersek@redhat.com> +Patchwork-id: 90436 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH 3/6] opts: don't silently truncate long option values +Bugzilla: 1749022 +RH-Acked-by: Stefano Garzarella +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Eduardo Habkost + +From: Daniel P. Berrangé + +The existing QemuOpts parsing code uses a fixed size 1024 byte buffer +for storing the option values. If a value exceeded this size it was +silently truncated and no error reported to the user. Long option values +is not a common scenario, but it is conceivable that they will happen. +eg if the user has a very deeply nested filesystem it would be possible +to come up with a disk path that was > 1024 bytes. Most of the time if +such data was silently truncated, the user would get an error about +opening a non-existant disk. If they're unlucky though, QEMU might use a +completely different disk image from another VM, which could be +considered a security issue. Another example program was in using the +-smbios command line arg with very large data blobs. In this case the +silent truncation will be providing semantically incorrect data to the +guest OS for SMBIOS tables. + +If the operating system didn't limit the user's argv when spawning QEMU, +the code should honour whatever length arguments were given without +imposing its own length restrictions. This patch thus changes the code +to use a heap allocated buffer for storing the values during parsing, +lifting the arbitrary length restriction. + +RHEL8 notes: + +- Fix up upstream's obviously garbled UTF8 sequences in Dan's name (Author + meta-datum, Signed-off-by tags). + +Signed-off-by: Daniel P. Berrangé +Message-Id: <20180416111743.8473-4-berrange@redhat.com> +Signed-off-by: Paolo Bonzini +Signed-off-by: Daniel P. Berrangé +(cherry picked from commit 950c4e6c94b15cd0d8b63891dddd7a8dbf458e6a) +Signed-off-by: Laszlo Ersek +Signed-off-by: Danilo C. L. de Paula +--- + hw/i386/multiboot.c | 33 +++++++++------ + include/qemu/option.h | 2 +- + util/qemu-option.c | 111 +++++++++++++++++++++++++++----------------------- + 3 files changed, 81 insertions(+), 65 deletions(-) + +diff --git a/hw/i386/multiboot.c b/hw/i386/multiboot.c +index 5bc0a2c..7a2953e 100644 +--- a/hw/i386/multiboot.c ++++ b/hw/i386/multiboot.c +@@ -291,12 +291,16 @@ int load_multiboot(FWCfgState *fw_cfg, + cmdline_len = strlen(kernel_filename) + 1; + cmdline_len += strlen(kernel_cmdline) + 1; + if (initrd_filename) { +- const char *r = initrd_filename; ++ const char *r = get_opt_value(initrd_filename, NULL); + cmdline_len += strlen(r) + 1; + mbs.mb_mods_avail = 1; +- while (*(r = get_opt_value(NULL, 0, r))) { +- mbs.mb_mods_avail++; +- r++; ++ while (1) { ++ mbs.mb_mods_avail++; ++ r = get_opt_value(r, NULL); ++ if (!*r) { ++ break; ++ } ++ r++; + } + } + +@@ -313,7 +317,8 @@ int load_multiboot(FWCfgState *fw_cfg, + + if (initrd_filename) { + const char *next_initrd; +- char not_last, tmpbuf[strlen(initrd_filename) + 1]; ++ char not_last; ++ char *one_file = NULL; + + mbs.offset_mods = mbs.mb_buf_size; + +@@ -322,24 +327,26 @@ int load_multiboot(FWCfgState *fw_cfg, + int mb_mod_length; + uint32_t offs = mbs.mb_buf_size; + +- next_initrd = get_opt_value(tmpbuf, sizeof(tmpbuf), initrd_filename); ++ next_initrd = get_opt_value(initrd_filename, &one_file); + not_last = *next_initrd; + /* if a space comes after the module filename, treat everything + after that as parameters */ +- hwaddr c = mb_add_cmdline(&mbs, tmpbuf); +- if ((next_space = strchr(tmpbuf, ' '))) ++ hwaddr c = mb_add_cmdline(&mbs, one_file); ++ next_space = strchr(one_file, ' '); ++ if (next_space) { + *next_space = '\0'; +- mb_debug("multiboot loading module: %s", tmpbuf); +- mb_mod_length = get_image_size(tmpbuf); ++ } ++ mb_debug("multiboot loading module: %s", one_file); ++ mb_mod_length = get_image_size(one_file); + if (mb_mod_length < 0) { +- error_report("Failed to open file '%s'", tmpbuf); ++ error_report("Failed to open file '%s'", one_file); + exit(1); + } + + mbs.mb_buf_size = TARGET_PAGE_ALIGN(mb_mod_length + mbs.mb_buf_size); + mbs.mb_buf = g_realloc(mbs.mb_buf, mbs.mb_buf_size); + +- load_image(tmpbuf, (unsigned char *)mbs.mb_buf + offs); ++ load_image(one_file, (unsigned char *)mbs.mb_buf + offs); + mb_add_mod(&mbs, mbs.mb_buf_phys + offs, + mbs.mb_buf_phys + offs + mb_mod_length, c); + +@@ -347,6 +354,8 @@ int load_multiboot(FWCfgState *fw_cfg, + (char *)mbs.mb_buf + offs, + (char *)mbs.mb_buf + offs + mb_mod_length, c); + initrd_filename = next_initrd+1; ++ g_free(one_file); ++ one_file = NULL; + } while (not_last); + } + +diff --git a/include/qemu/option.h b/include/qemu/option.h +index 1cfe5cb..3dfb449 100644 +--- a/include/qemu/option.h ++++ b/include/qemu/option.h +@@ -28,7 +28,7 @@ + + #include "qemu/queue.h" + +-const char *get_opt_value(char *buf, int buf_size, const char *p); ++const char *get_opt_value(const char *p, char **value); + + void parse_option_size(const char *name, const char *value, + uint64_t *ret, Error **errp); +diff --git a/util/qemu-option.c b/util/qemu-option.c +index b99568f..ba44a08 100644 +--- a/util/qemu-option.c ++++ b/util/qemu-option.c +@@ -70,25 +70,37 @@ static const char *get_opt_name(const char *p, char **option, char delim) + * delimiter is fixed to be comma which starts a new option. To specify an + * option value that contains commas, double each comma. + */ +-const char *get_opt_value(char *buf, int buf_size, const char *p) ++const char *get_opt_value(const char *p, char **value) + { +- char *q; ++ size_t capacity = 0, length; ++ const char *offset; ++ ++ *value = NULL; ++ while (1) { ++ offset = strchr(p, ','); ++ if (!offset) { ++ offset = p + strlen(p); ++ } + +- q = buf; +- while (*p != '\0') { +- if (*p == ',') { +- if (*(p + 1) != ',') +- break; +- p++; ++ length = offset - p; ++ if (*offset != '\0' && *(offset + 1) == ',') { ++ length++; ++ } ++ if (value) { ++ *value = g_renew(char, *value, capacity + length + 1); ++ strncpy(*value + capacity, p, length); ++ (*value)[capacity + length] = '\0'; ++ } ++ capacity += length; ++ if (*offset == '\0' || ++ *(offset + 1) != ',') { ++ break; + } +- if (q && (q - buf) < buf_size - 1) +- *q++ = *p; +- p++; ++ ++ p += (offset - p) + 2; + } +- if (q) +- *q = '\0'; + +- return p; ++ return offset; + } + + static void parse_option_bool(const char *name, const char *value, bool *ret, +@@ -162,50 +174,43 @@ void parse_option_size(const char *name, const char *value, + + bool has_help_option(const char *param) + { +- size_t buflen = strlen(param) + 1; +- char *buf = g_malloc(buflen); + const char *p = param; + bool result = false; + +- while (*p) { +- p = get_opt_value(buf, buflen, p); ++ while (*p && !result) { ++ char *value; ++ ++ p = get_opt_value(p, &value); + if (*p) { + p++; + } + +- if (is_help_option(buf)) { +- result = true; +- goto out; +- } ++ result = is_help_option(value); ++ g_free(value); + } + +-out: +- g_free(buf); + return result; + } + +-bool is_valid_option_list(const char *param) ++bool is_valid_option_list(const char *p) + { +- size_t buflen = strlen(param) + 1; +- char *buf = g_malloc(buflen); +- const char *p = param; +- bool result = true; ++ char *value = NULL; ++ bool result = false; + + while (*p) { +- p = get_opt_value(buf, buflen, p); +- if (*p && !*++p) { +- result = false; ++ p = get_opt_value(p, &value); ++ if ((*p && !*++p) || ++ (!*value || *value == ',')) { + goto out; + } + +- if (!*buf || *buf == ',') { +- result = false; +- goto out; +- } ++ g_free(value); ++ value = NULL; + } + ++ result = true; + out: +- g_free(buf); ++ g_free(value); + return result; + } + +@@ -486,7 +491,7 @@ int qemu_opt_unset(QemuOpts *opts, const char *name) + } + } + +-static void opt_set(QemuOpts *opts, const char *name, const char *value, ++static void opt_set(QemuOpts *opts, const char *name, char *value, + bool prepend, Error **errp) + { + QemuOpt *opt; +@@ -495,6 +500,7 @@ static void opt_set(QemuOpts *opts, const char *name, const char *value, + + desc = find_desc_by_name(opts->list->desc, name); + if (!desc && !opts_accepts_any(opts)) { ++ g_free(value); + error_setg(errp, QERR_INVALID_PARAMETER, name); + return; + } +@@ -508,8 +514,7 @@ static void opt_set(QemuOpts *opts, const char *name, const char *value, + QTAILQ_INSERT_TAIL(&opts->head, opt, next); + } + opt->desc = desc; +- opt->str = g_strdup(value); +- assert(opt->str); ++ opt->str = value; + qemu_opt_parse(opt, &local_err); + if (local_err) { + error_propagate(errp, local_err); +@@ -520,7 +525,7 @@ static void opt_set(QemuOpts *opts, const char *name, const char *value, + void qemu_opt_set(QemuOpts *opts, const char *name, const char *value, + Error **errp) + { +- opt_set(opts, name, value, false, errp); ++ opt_set(opts, name, g_strdup(value), false, errp); + } + + void qemu_opt_set_bool(QemuOpts *opts, const char *name, bool val, +@@ -754,7 +759,7 @@ static void opts_do_parse(QemuOpts *opts, const char *params, + const char *firstname, bool prepend, Error **errp) + { + char *option = NULL; +- char value[1024]; ++ char *value = NULL; + const char *p,*pe,*pc; + Error *local_err = NULL; + +@@ -766,15 +771,15 @@ static void opts_do_parse(QemuOpts *opts, const char *params, + if (p == params && firstname) { + /* implicitly named first option */ + option = g_strdup(firstname); +- p = get_opt_value(value, sizeof(value), p); ++ p = get_opt_value(p, &value); + } else { + /* option without value, probably a flag */ + p = get_opt_name(p, &option, ','); + if (strncmp(option, "no", 2) == 0) { + memmove(option, option+2, strlen(option+2)+1); +- pstrcpy(value, sizeof(value), "off"); ++ value = g_strdup("off"); + } else { +- pstrcpy(value, sizeof(value), "on"); ++ value = g_strdup("on"); + } + } + } else { +@@ -782,11 +787,12 @@ static void opts_do_parse(QemuOpts *opts, const char *params, + p = get_opt_name(p, &option, '='); + assert(*p == '='); + p++; +- p = get_opt_value(value, sizeof(value), p); ++ p = get_opt_value(p, &value); + } + if (strcmp(option, "id") != 0) { + /* store and parse */ + opt_set(opts, option, value, prepend, &local_err); ++ value = NULL; + if (local_err) { + error_propagate(errp, local_err); + goto cleanup; +@@ -796,11 +802,13 @@ static void opts_do_parse(QemuOpts *opts, const char *params, + break; + } + g_free(option); +- option = NULL; ++ g_free(value); ++ option = value = NULL; + } + + cleanup: + g_free(option); ++ g_free(value); + } + + /** +@@ -819,7 +827,7 @@ static QemuOpts *opts_parse(QemuOptsList *list, const char *params, + bool permit_abbrev, bool defaults, Error **errp) + { + const char *firstname; +- char value[1024], *id = NULL; ++ char *id = NULL; + const char *p; + QemuOpts *opts; + Error *local_err = NULL; +@@ -828,11 +836,9 @@ static QemuOpts *opts_parse(QemuOptsList *list, const char *params, + firstname = permit_abbrev ? list->implied_opt_name : NULL; + + if (strncmp(params, "id=", 3) == 0) { +- get_opt_value(value, sizeof(value), params+3); +- id = value; ++ get_opt_value(params + 3, &id); + } else if ((p = strstr(params, ",id=")) != NULL) { +- get_opt_value(value, sizeof(value), p+4); +- id = value; ++ get_opt_value(p + 4, &id); + } + + /* +@@ -844,6 +850,7 @@ static QemuOpts *opts_parse(QemuOptsList *list, const char *params, + */ + assert(!defaults || list->merge_lists); + opts = qemu_opts_create(list, id, !defaults, &local_err); ++ g_free(id); + if (opts == NULL) { + error_propagate(errp, local_err); + return NULL; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-opts-don-t-silently-truncate-long-parameter-keys.patch b/SOURCES/kvm-opts-don-t-silently-truncate-long-parameter-keys.patch new file mode 100644 index 0000000..00cd2ae --- /dev/null +++ b/SOURCES/kvm-opts-don-t-silently-truncate-long-parameter-keys.patch @@ -0,0 +1,198 @@ +From 5fe3c58c3a57a04254b3083b070fdf99fba82c93 Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Thu, 12 Sep 2019 13:04:59 +0100 +Subject: [PATCH 02/22] opts: don't silently truncate long parameter keys +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Laszlo Ersek +Message-id: <20190912130503.14094-3-lersek@redhat.com> +Patchwork-id: 90435 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH 2/6] opts: don't silently truncate long parameter keys +Bugzilla: 1749022 +RH-Acked-by: Stefano Garzarella +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Eduardo Habkost + +From: Daniel P. Berrangé + +The existing QemuOpts parsing code uses a fixed size 128 byte buffer +for storing the parameter keys. If a key exceeded this size it was +silently truncate and no error reported to the user. This behaviour was +reasonable & harmless because traditionally the key names are all +statically declared, and it was known that no code was declaring a key +longer than 127 bytes. This assumption, however, ceased to be valid once +the block layer added support for dot-separate compound keys. This +syntax allows for keys that can be arbitrarily long, limited only by the +number of block drivers you can stack up. With this usage, silently +truncating the key name can never lead to correct behaviour. + +Hopefully such truncation would turn into an error, when the block code +then tried to extract options later, but there's no guarantee that will +happen. It is conceivable that an option specified by the user may be +truncated and then ignored. This could have serious consequences, +possibly even leading to security problems if the ignored option set a +security relevant parameter. + +If the operating system didn't limit the user's argv when spawning QEMU, +the code should honour whatever length arguments were given without +imposing its own length restrictions. This patch thus changes the code +to use a heap allocated buffer for storing the keys during parsing, +lifting the arbitrary length restriction. + +RHEL8 notes: + +- Fix up upstream's obviously garbled UTF8 sequences in Dan's name (Author + meta-datum, Signed-off-by tags). + +Signed-off-by: Daniel P. Berrangé +Message-Id: <20180416111743.8473-3-berrange@redhat.com> +Signed-off-by: Paolo Bonzini +Signed-off-by: Daniel P. Berrangé +(cherry picked from commit e652714f98f22e8882e88e3d563b025c5b00feec) +Signed-off-by: Laszlo Ersek +Signed-off-by: Danilo C. L. de Paula +--- + tests/test-qemu-opts.c | 18 ------------------ + util/qemu-option.c | 44 ++++++++++++++++++++++---------------------- + 2 files changed, 22 insertions(+), 40 deletions(-) + +diff --git a/tests/test-qemu-opts.c b/tests/test-qemu-opts.c +index 77dd72b..7092e21 100644 +--- a/tests/test-qemu-opts.c ++++ b/tests/test-qemu-opts.c +@@ -459,8 +459,6 @@ static void test_opts_parse(void) + { + Error *err = NULL; + QemuOpts *opts; +- char long_key[129]; +- char *params; + + /* Nothing */ + opts = qemu_opts_parse(&opts_list_03, "", false, &error_abort); +@@ -471,22 +469,6 @@ static void test_opts_parse(void) + g_assert_cmpuint(opts_count(opts), ==, 1); + g_assert_cmpstr(qemu_opt_get(opts, ""), ==, "val"); + +- /* Long key */ +- memset(long_key, 'a', 127); +- long_key[127] = 'z'; +- long_key[128] = 0; +- params = g_strdup_printf("%s=v", long_key); +- opts = qemu_opts_parse(&opts_list_03, params + 1, NULL, &error_abort); +- g_assert_cmpuint(opts_count(opts), ==, 1); +- g_assert_cmpstr(qemu_opt_get(opts, long_key + 1), ==, "v"); +- +- /* Overlong key gets truncated */ +- opts = qemu_opts_parse(&opts_list_03, params, NULL, &error_abort); +- g_assert(opts_count(opts) == 1); +- long_key[127] = 0; +- g_assert_cmpstr(qemu_opt_get(opts, long_key), ==, "v"); +- g_free(params); +- + /* Multiple keys, last one wins */ + opts = qemu_opts_parse(&opts_list_03, "a=1,b=2,,x,a=3", + false, &error_abort); +diff --git a/util/qemu-option.c b/util/qemu-option.c +index a8db173..b99568f 100644 +--- a/util/qemu-option.c ++++ b/util/qemu-option.c +@@ -43,27 +43,23 @@ + * first byte of the option name) + * + * The option name is delimited by delim (usually , or =) or the string end +- * and is copied into buf. If the option name is longer than buf_size, it is +- * truncated. buf is always zero terminated. ++ * and is copied into option. The caller is responsible for free'ing option ++ * when no longer required. + * + * The return value is the position of the delimiter/zero byte after the option + * name in p. + */ +-static const char *get_opt_name(char *buf, int buf_size, const char *p, +- char delim) ++static const char *get_opt_name(const char *p, char **option, char delim) + { +- char *q; ++ char *offset = strchr(p, delim); + +- q = buf; +- while (*p != '\0' && *p != delim) { +- if (q && (q - buf) < buf_size - 1) +- *q++ = *p; +- p++; ++ if (offset) { ++ *option = g_strndup(p, offset - p); ++ return offset; ++ } else { ++ *option = g_strdup(p); ++ return p + strlen(p); + } +- if (q) +- *q = '\0'; +- +- return p; + } + + /* +@@ -757,7 +753,8 @@ void qemu_opts_print(QemuOpts *opts, const char *separator) + static void opts_do_parse(QemuOpts *opts, const char *params, + const char *firstname, bool prepend, Error **errp) + { +- char option[128], value[1024]; ++ char *option = NULL; ++ char value[1024]; + const char *p,*pe,*pc; + Error *local_err = NULL; + +@@ -768,11 +765,11 @@ static void opts_do_parse(QemuOpts *opts, const char *params, + /* found "foo,more" */ + if (p == params && firstname) { + /* implicitly named first option */ +- pstrcpy(option, sizeof(option), firstname); ++ option = g_strdup(firstname); + p = get_opt_value(value, sizeof(value), p); + } else { + /* option without value, probably a flag */ +- p = get_opt_name(option, sizeof(option), p, ','); ++ p = get_opt_name(p, &option, ','); + if (strncmp(option, "no", 2) == 0) { + memmove(option, option+2, strlen(option+2)+1); + pstrcpy(value, sizeof(value), "off"); +@@ -782,10 +779,8 @@ static void opts_do_parse(QemuOpts *opts, const char *params, + } + } else { + /* found "foo=bar,more" */ +- p = get_opt_name(option, sizeof(option), p, '='); +- if (*p != '=') { +- break; +- } ++ p = get_opt_name(p, &option, '='); ++ assert(*p == '='); + p++; + p = get_opt_value(value, sizeof(value), p); + } +@@ -794,13 +789,18 @@ static void opts_do_parse(QemuOpts *opts, const char *params, + opt_set(opts, option, value, prepend, &local_err); + if (local_err) { + error_propagate(errp, local_err); +- return; ++ goto cleanup; + } + } + if (*p != ',') { + break; + } ++ g_free(option); ++ option = NULL; + } ++ ++ cleanup: ++ g_free(option); + } + + /** +-- +1.8.3.1 + diff --git a/SOURCES/kvm-opts-remove-redundant-check-for-NULL-parameter.patch b/SOURCES/kvm-opts-remove-redundant-check-for-NULL-parameter.patch new file mode 100644 index 0000000..7130abe --- /dev/null +++ b/SOURCES/kvm-opts-remove-redundant-check-for-NULL-parameter.patch @@ -0,0 +1,74 @@ +From 1906ff6940bb9f84f0f6a66980354e66b5124558 Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Thu, 12 Sep 2019 13:05:03 +0100 +Subject: [PATCH 06/22] opts: remove redundant check for NULL parameter +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Laszlo Ersek +Message-id: <20190912130503.14094-7-lersek@redhat.com> +Patchwork-id: 90432 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH 6/6] opts: remove redundant check for NULL parameter +Bugzilla: 1749022 +RH-Acked-by: Stefano Garzarella +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Eduardo Habkost + +From: Daniel P. Berrangé + +No callers of get_opt_value() pass in a NULL for the "value" parameter, +so the check is redundant. + +RHEL8 notes: + +- Context difference in "util/qemu-option.c", function get_opt_value(); + upstream has commit 5c99fa375da1 ("cutils: Provide strchrnul", + 2018-06-29), part of v3.0.0, but downstream lacks it. Harmless, because + said upstream commit only refactors get_opt_value(). + +Signed-off-by: Daniel P. Berrangé +Message-Id: <20180514171913.17664-4-berrange@redhat.com> +Reviewed-by: Eduardo Habkost +Tested-by: Roman Kagan +Signed-off-by: Paolo Bonzini +(cherry picked from commit 0c2f6e7ee99517449b4ed6cf333c2d9456d8fe35) +Signed-off-by: Laszlo Ersek +Signed-off-by: Danilo C. L. de Paula +--- + util/qemu-option.c | 12 ++++-------- + 1 file changed, 4 insertions(+), 8 deletions(-) + +diff --git a/util/qemu-option.c b/util/qemu-option.c +index a396d60..940f7a3 100644 +--- a/util/qemu-option.c ++++ b/util/qemu-option.c +@@ -75,9 +75,7 @@ const char *get_opt_value(const char *p, char **value) + size_t capacity = 0, length; + const char *offset; + +- if (value) { +- *value = NULL; +- } ++ *value = NULL; + while (1) { + offset = strchr(p, ','); + if (!offset) { +@@ -88,11 +86,9 @@ const char *get_opt_value(const char *p, char **value) + if (*offset != '\0' && *(offset + 1) == ',') { + length++; + } +- if (value) { +- *value = g_renew(char, *value, capacity + length + 1); +- strncpy(*value + capacity, p, length); +- (*value)[capacity + length] = '\0'; +- } ++ *value = g_renew(char, *value, capacity + length + 1); ++ strncpy(*value + capacity, p, length); ++ (*value)[capacity + length] = '\0'; + capacity += length; + if (*offset == '\0' || + *(offset + 1) != ',') { +-- +1.8.3.1 + diff --git a/SOURCES/kvm-pc-bios-s390-ccw-define-loadparm-length.patch b/SOURCES/kvm-pc-bios-s390-ccw-define-loadparm-length.patch new file mode 100644 index 0000000..3f12d5a --- /dev/null +++ b/SOURCES/kvm-pc-bios-s390-ccw-define-loadparm-length.patch @@ -0,0 +1,122 @@ +From ad3b92699ba5e2280950fa9866f79673cecdb695 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Mon, 14 Oct 2019 10:06:29 +0100 +Subject: [PATCH 04/21] pc-bios/s390-ccw: define loadparm length + +RH-Author: Thomas Huth +Message-id: <20191014100645.22862-2-thuth@redhat.com> +Patchwork-id: 91780 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH v2 01/17] pc-bios/s390-ccw: define loadparm length +Bugzilla: 1664376 +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand +RH-Acked-by: Jens Freimann + +From: Collin Walling + +Loadparm is defined by the s390 architecture to be 8 bytes +in length. Let's define this size in the s390-ccw bios. + +Suggested-by: Laszlo Ersek +Signed-off-by: Collin Walling +Reviewed-by: Laszlo Ersek +Reviewed-by: Thomas Huth +Signed-off-by: Thomas Huth +(cherry picked from commit a0e11b617b9ef41cefe8739dff4d6a7b01ca967f) +Signed-off-by: Danilo C. L. de Paula +--- + pc-bios/s390-ccw/iplb.h | 4 +++- + pc-bios/s390-ccw/main.c | 8 ++++---- + pc-bios/s390-ccw/sclp.c | 2 +- + pc-bios/s390-ccw/sclp.h | 2 +- + 4 files changed, 9 insertions(+), 7 deletions(-) + +diff --git a/pc-bios/s390-ccw/iplb.h b/pc-bios/s390-ccw/iplb.h +index ded20c8..772d5c5 100644 +--- a/pc-bios/s390-ccw/iplb.h ++++ b/pc-bios/s390-ccw/iplb.h +@@ -12,6 +12,8 @@ + #ifndef IPLB_H + #define IPLB_H + ++#define LOADPARM_LEN 8 ++ + struct IplBlockCcw { + uint8_t reserved0[85]; + uint8_t ssid; +@@ -61,7 +63,7 @@ struct IplParameterBlock { + uint8_t pbt; + uint8_t flags; + uint16_t reserved01; +- uint8_t loadparm[8]; ++ uint8_t loadparm[LOADPARM_LEN]; + union { + IplBlockCcw ccw; + IplBlockFcp fcp; +diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c +index 26f9adf..544851d 100644 +--- a/pc-bios/s390-ccw/main.c ++++ b/pc-bios/s390-ccw/main.c +@@ -15,7 +15,7 @@ + char stack[PAGE_SIZE * 8] __attribute__((__aligned__(PAGE_SIZE))); + static SubChannelId blk_schid = { .one = 1 }; + IplParameterBlock iplb __attribute__((__aligned__(PAGE_SIZE))); +-static char loadparm_str[9] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; ++static char loadparm_str[LOADPARM_LEN + 1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + QemuIplParameters qipl; + + #define LOADPARM_PROMPT "PROMPT " +@@ -80,13 +80,13 @@ static bool find_dev(Schib *schib, int dev_no) + + static void menu_setup(void) + { +- if (memcmp(loadparm_str, LOADPARM_PROMPT, 8) == 0) { ++ if (memcmp(loadparm_str, LOADPARM_PROMPT, LOADPARM_LEN) == 0) { + menu_set_parms(QIPL_FLAG_BM_OPTS_CMD, 0); + return; + } + + /* If loadparm was set to any other value, then do not enable menu */ +- if (memcmp(loadparm_str, LOADPARM_EMPTY, 8) != 0) { ++ if (memcmp(loadparm_str, LOADPARM_EMPTY, LOADPARM_LEN) != 0) { + return; + } + +@@ -117,7 +117,7 @@ static void virtio_setup(void) + enable_mss_facility(); + + sclp_get_loadparm_ascii(loadparm_str); +- memcpy(ldp + 10, loadparm_str, 8); ++ memcpy(ldp + 10, loadparm_str, LOADPARM_LEN); + sclp_print(ldp); + + memcpy(&qipl, early_qipl, sizeof(QemuIplParameters)); +diff --git a/pc-bios/s390-ccw/sclp.c b/pc-bios/s390-ccw/sclp.c +index 3836cb4..c0223fa 100644 +--- a/pc-bios/s390-ccw/sclp.c ++++ b/pc-bios/s390-ccw/sclp.c +@@ -114,7 +114,7 @@ void sclp_get_loadparm_ascii(char *loadparm) + memset((char *)_sccb, 0, sizeof(ReadInfo)); + sccb->h.length = sizeof(ReadInfo); + if (!sclp_service_call(SCLP_CMDW_READ_SCP_INFO, sccb)) { +- ebcdic_to_ascii((char *) sccb->loadparm, loadparm, 8); ++ ebcdic_to_ascii((char *) sccb->loadparm, loadparm, LOADPARM_LEN); + } + } + +diff --git a/pc-bios/s390-ccw/sclp.h b/pc-bios/s390-ccw/sclp.h +index 0dd987f..8450161 100644 +--- a/pc-bios/s390-ccw/sclp.h ++++ b/pc-bios/s390-ccw/sclp.h +@@ -56,7 +56,7 @@ typedef struct ReadInfo { + uint16_t rnmax; + uint8_t rnsize; + uint8_t reserved[13]; +- uint8_t loadparm[8]; ++ uint8_t loadparm[LOADPARM_LEN]; + } __attribute__((packed)) ReadInfo; + + typedef struct SCCB { +-- +1.8.3.1 + diff --git a/SOURCES/kvm-pc-bios-s390-ccw-net-Use-diag308-to-reset-machine-be.patch b/SOURCES/kvm-pc-bios-s390-ccw-net-Use-diag308-to-reset-machine-be.patch new file mode 100644 index 0000000..54d102d --- /dev/null +++ b/SOURCES/kvm-pc-bios-s390-ccw-net-Use-diag308-to-reset-machine-be.patch @@ -0,0 +1,328 @@ +From 2f0454ccd0dd12429e8c204933cafe71a248d4eb Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Mon, 14 Oct 2019 10:06:30 +0100 +Subject: [PATCH 05/21] pc-bios/s390-ccw/net: Use diag308 to reset machine + before jumping to the OS + +RH-Author: Thomas Huth +Message-id: <20191014100645.22862-3-thuth@redhat.com> +Patchwork-id: 91777 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH v2 02/17] pc-bios/s390-ccw/net: Use diag308 to reset machine before jumping to the OS +Bugzilla: 1664376 +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand +RH-Acked-by: Jens Freimann + +The netboot firmware so far simply jumped directly into the OS kernel +after the download has been completed. This, however, bears the risk +that the virtio-net device still might be active in the background and +incoming packets are still placed into the buffers - which could destroy +memory of the now-running Linux kernel in case it did not take over the +device fast enough. Also the SCLP console is not put into a well-defined +state here. We should hand over the system in a clean state when jumping +into the kernel, so let's use the same mechanism as it's done in the +main s390-ccw firmware and reset the machine with diag308 into a clean +state before jumping into the OS kernel code. To be able to share the +code with the main s390-ccw firmware, the related functions are now +extracted from bootmap.c into a new file called jump2ipl.c. + +Since we now also set the boot device schid at address 184 for the network +boot device, this patch also slightly changes the way how we detect the +entry points for non-ELF binary images: The code now looks for the "S390EP" +magic first and then jumps to 0x10000 in case it has been found. This is +necessary for booting from network devices, since the normal kernel code +(where the PSW at ddress 0 points to) tries to do a block load from the +boot device. This of course fails for a virtio-net device and causes the +kernel to abort with a panic-PSW silently. + +Acked-by: Christian Borntraeger +Signed-off-by: Thomas Huth +(cherry picked from commit 9a848adf45d6732e62551decb3c0255173090767) +Signed-off-by: Danilo C. L. de Paula +--- + pc-bios/s390-ccw/Makefile | 4 +- + pc-bios/s390-ccw/bootmap.c | 63 +----------------------------- + pc-bios/s390-ccw/bootmap.h | 4 -- + pc-bios/s390-ccw/jump2ipl.c | 91 ++++++++++++++++++++++++++++++++++++++++++++ + pc-bios/s390-ccw/netboot.mak | 3 +- + pc-bios/s390-ccw/netmain.c | 11 +++++- + pc-bios/s390-ccw/s390-ccw.h | 4 ++ + 7 files changed, 111 insertions(+), 69 deletions(-) + create mode 100644 pc-bios/s390-ccw/jump2ipl.c + +diff --git a/pc-bios/s390-ccw/Makefile b/pc-bios/s390-ccw/Makefile +index 1712c2d..439e3cc 100644 +--- a/pc-bios/s390-ccw/Makefile ++++ b/pc-bios/s390-ccw/Makefile +@@ -9,7 +9,9 @@ $(call set-vpath, $(SRC_PATH)/pc-bios/s390-ccw) + + .PHONY : all clean build-all + +-OBJECTS = start.o main.o bootmap.o sclp.o virtio.o virtio-scsi.o virtio-blkdev.o libc.o menu.o ++OBJECTS = start.o main.o bootmap.o jump2ipl.o sclp.o menu.o \ ++ virtio.o virtio-scsi.o virtio-blkdev.o libc.o ++ + QEMU_CFLAGS := $(filter -W%, $(QEMU_CFLAGS)) + QEMU_CFLAGS += -ffreestanding -fno-delete-null-pointer-checks -msoft-float + QEMU_CFLAGS += -march=z900 -fPIE -fno-strict-aliasing +diff --git a/pc-bios/s390-ccw/bootmap.c b/pc-bios/s390-ccw/bootmap.c +index ffbf671..d13b7cb 100644 +--- a/pc-bios/s390-ccw/bootmap.c ++++ b/pc-bios/s390-ccw/bootmap.c +@@ -29,14 +29,6 @@ + /* Scratch space */ + static uint8_t sec[MAX_SECTOR_SIZE*4] __attribute__((__aligned__(PAGE_SIZE))); + +-typedef struct ResetInfo { +- uint32_t ipl_mask; +- uint32_t ipl_addr; +- uint32_t ipl_continue; +-} ResetInfo; +- +-static ResetInfo save; +- + const uint8_t el_torito_magic[] = "EL TORITO SPECIFICATION" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; + +@@ -57,53 +49,6 @@ static inline bool is_iso_vd_valid(IsoVolDesc *vd) + vd->type <= VOL_DESC_TYPE_PARTITION; + } + +-static void jump_to_IPL_2(void) +-{ +- ResetInfo *current = 0; +- +- void (*ipl)(void) = (void *) (uint64_t) current->ipl_continue; +- *current = save; +- ipl(); /* should not return */ +-} +- +-static void jump_to_IPL_code(uint64_t address) +-{ +- /* store the subsystem information _after_ the bootmap was loaded */ +- write_subsystem_identification(); +- +- /* prevent unknown IPL types in the guest */ +- if (iplb.pbt == S390_IPL_TYPE_QEMU_SCSI) { +- iplb.pbt = S390_IPL_TYPE_CCW; +- set_iplb(&iplb); +- } +- +- /* +- * The IPL PSW is at address 0. We also must not overwrite the +- * content of non-BIOS memory after we loaded the guest, so we +- * save the original content and restore it in jump_to_IPL_2. +- */ +- ResetInfo *current = 0; +- +- save = *current; +- current->ipl_addr = (uint32_t) (uint64_t) &jump_to_IPL_2; +- current->ipl_continue = address & 0x7fffffff; +- +- debug_print_int("set IPL addr to", current->ipl_continue); +- +- /* Ensure the guest output starts fresh */ +- sclp_print("\n"); +- +- /* +- * HACK ALERT. +- * We use the load normal reset to keep r15 unchanged. jump_to_IPL_2 +- * can then use r15 as its stack pointer. +- */ +- asm volatile("lghi 1,1\n\t" +- "diag 1,1,0x308\n\t" +- : : : "1", "memory"); +- panic("\n! IPL returns !\n"); +-} +- + /*********************************************************************** + * IPL an ECKD DASD (CDL or LDL/CMS format) + */ +@@ -744,13 +689,7 @@ static void load_iso_bc_entry(IsoBcSection *load) + (void *)((uint64_t)bswap16(s.load_segment)), + blks_to_load); + +- /* Trying to get PSW at zero address */ +- if (*((uint64_t *)0) & IPL_PSW_MASK) { +- jump_to_IPL_code((*((uint64_t *)0)) & 0x7fffffff); +- } +- +- /* Try default linux start address */ +- jump_to_IPL_code(KERN_IMAGE_START); ++ jump_to_low_kernel(); + } + + static uint32_t find_iso_bc(void) +diff --git a/pc-bios/s390-ccw/bootmap.h b/pc-bios/s390-ccw/bootmap.h +index f1ce423..94f53a5 100644 +--- a/pc-bios/s390-ccw/bootmap.h ++++ b/pc-bios/s390-ccw/bootmap.h +@@ -355,10 +355,6 @@ static inline uint32_t iso_733_to_u32(uint64_t x) + #define ISO_SECTOR_SIZE 2048 + /* El Torito specifies boot image size in 512 byte blocks */ + #define ET_SECTOR_SHIFT 2 +-#define KERN_IMAGE_START 0x010000UL +-#define PSW_MASK_64 0x0000000100000000ULL +-#define PSW_MASK_32 0x0000000080000000ULL +-#define IPL_PSW_MASK (PSW_MASK_32 | PSW_MASK_64) + + #define ISO_PRIMARY_VD_SECTOR 16 + +diff --git a/pc-bios/s390-ccw/jump2ipl.c b/pc-bios/s390-ccw/jump2ipl.c +new file mode 100644 +index 0000000..266f150 +--- /dev/null ++++ b/pc-bios/s390-ccw/jump2ipl.c +@@ -0,0 +1,91 @@ ++/* ++ * QEMU s390-ccw firmware - jump to IPL code ++ * ++ * This work is licensed under the terms of the GNU GPL, version 2 or (at ++ * your option) any later version. See the COPYING file in the top-level ++ * directory. ++ */ ++ ++#include "libc.h" ++#include "s390-ccw.h" ++ ++#define KERN_IMAGE_START 0x010000UL ++#define PSW_MASK_64 0x0000000100000000ULL ++#define PSW_MASK_32 0x0000000080000000ULL ++#define IPL_PSW_MASK (PSW_MASK_32 | PSW_MASK_64) ++ ++typedef struct ResetInfo { ++ uint32_t ipl_mask; ++ uint32_t ipl_addr; ++ uint32_t ipl_continue; ++} ResetInfo; ++ ++static ResetInfo save; ++ ++static void jump_to_IPL_2(void) ++{ ++ ResetInfo *current = 0; ++ ++ void (*ipl)(void) = (void *) (uint64_t) current->ipl_continue; ++ *current = save; ++ ipl(); /* should not return */ ++} ++ ++void jump_to_IPL_code(uint64_t address) ++{ ++ /* store the subsystem information _after_ the bootmap was loaded */ ++ write_subsystem_identification(); ++ ++ /* prevent unknown IPL types in the guest */ ++ if (iplb.pbt == S390_IPL_TYPE_QEMU_SCSI) { ++ iplb.pbt = S390_IPL_TYPE_CCW; ++ set_iplb(&iplb); ++ } ++ ++ /* ++ * The IPL PSW is at address 0. We also must not overwrite the ++ * content of non-BIOS memory after we loaded the guest, so we ++ * save the original content and restore it in jump_to_IPL_2. ++ */ ++ ResetInfo *current = 0; ++ ++ save = *current; ++ current->ipl_addr = (uint32_t) (uint64_t) &jump_to_IPL_2; ++ current->ipl_continue = address & 0x7fffffff; ++ ++ debug_print_int("set IPL addr to", current->ipl_continue); ++ ++ /* Ensure the guest output starts fresh */ ++ sclp_print("\n"); ++ ++ /* ++ * HACK ALERT. ++ * We use the load normal reset to keep r15 unchanged. jump_to_IPL_2 ++ * can then use r15 as its stack pointer. ++ */ ++ asm volatile("lghi 1,1\n\t" ++ "diag 1,1,0x308\n\t" ++ : : : "1", "memory"); ++ panic("\n! IPL returns !\n"); ++} ++ ++void jump_to_low_kernel(void) ++{ ++ /* ++ * If it looks like a Linux binary, i.e. there is the "S390EP" magic from ++ * arch/s390/kernel/head.S here, then let's jump to the well-known Linux ++ * kernel start address (when jumping to the PSW-at-zero address instead, ++ * the kernel startup code fails when we booted from a network device). ++ */ ++ if (!memcmp((char *)0x10008, "S390EP", 6)) { ++ jump_to_IPL_code(KERN_IMAGE_START); ++ } ++ ++ /* Trying to get PSW at zero address */ ++ if (*((uint64_t *)0) & IPL_PSW_MASK) { ++ jump_to_IPL_code((*((uint64_t *)0)) & 0x7fffffff); ++ } ++ ++ /* No other option left, so use the Linux kernel start address */ ++ jump_to_IPL_code(KERN_IMAGE_START); ++} +diff --git a/pc-bios/s390-ccw/netboot.mak b/pc-bios/s390-ccw/netboot.mak +index a25d238..4f64128 100644 +--- a/pc-bios/s390-ccw/netboot.mak ++++ b/pc-bios/s390-ccw/netboot.mak +@@ -1,7 +1,8 @@ + + SLOF_DIR := $(SRC_PATH)/roms/SLOF + +-NETOBJS := start.o sclp.o virtio.o virtio-net.o netmain.o libnet.a libc.a ++NETOBJS := start.o sclp.o virtio.o virtio-net.o jump2ipl.o netmain.o \ ++ libnet.a libc.a + + LIBC_INC := -nostdinc -I$(SLOF_DIR)/lib/libc/include + LIBNET_INC := -I$(SLOF_DIR)/lib/libnet +diff --git a/pc-bios/s390-ccw/netmain.c b/pc-bios/s390-ccw/netmain.c +index d86d46b..d60e84f 100644 +--- a/pc-bios/s390-ccw/netmain.c ++++ b/pc-bios/s390-ccw/netmain.c +@@ -281,6 +281,15 @@ void panic(const char *string) + } + } + ++void write_subsystem_identification(void) ++{ ++ SubChannelId *schid = (SubChannelId *) 184; ++ uint32_t *zeroes = (uint32_t *) 188; ++ ++ *schid = net_schid; ++ *zeroes = 0; ++} ++ + static bool find_net_dev(Schib *schib, int dev_no) + { + int i, r; +@@ -354,7 +363,7 @@ void main(void) + rc = net_load(NULL, (long)_start); + if (rc > 0) { + sclp_print("Network loading done, starting kernel...\n"); +- asm volatile (" lpsw 0(%0) " : : "r"(0) : "memory"); ++ jump_to_low_kernel(); + } + + panic("Failed to load OS from network\n"); +diff --git a/pc-bios/s390-ccw/s390-ccw.h b/pc-bios/s390-ccw/s390-ccw.h +index a1bdb4c..9828aa2 100644 +--- a/pc-bios/s390-ccw/s390-ccw.h ++++ b/pc-bios/s390-ccw/s390-ccw.h +@@ -87,6 +87,10 @@ ulong get_second(void); + /* bootmap.c */ + void zipl_load(void); + ++/* jump2ipl.c */ ++void jump_to_IPL_code(uint64_t address); ++void jump_to_low_kernel(void); ++ + /* menu.c */ + void menu_set_parms(uint8_t boot_menu_flag, uint32_t boot_menu_timeout); + int menu_get_zipl_boot_index(const char *menu_data); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-pc-q35-Disallow-vfio-pci-hotplug-without-VT-d-cachin.patch b/SOURCES/kvm-pc-q35-Disallow-vfio-pci-hotplug-without-VT-d-cachin.patch new file mode 100644 index 0000000..adcf327 --- /dev/null +++ b/SOURCES/kvm-pc-q35-Disallow-vfio-pci-hotplug-without-VT-d-cachin.patch @@ -0,0 +1,87 @@ +From f117f5fb216e45796a32579c03673c1d79164037 Mon Sep 17 00:00:00 2001 +From: Peter Xu +Date: Wed, 9 Oct 2019 12:39:46 +0100 +Subject: [PATCH 20/22] pc/q35: Disallow vfio-pci hotplug without VT-d caching + mode + +RH-Author: Peter Xu +Message-id: <20191009123947.21505-5-peterx@redhat.com> +Patchwork-id: 91352 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH 4/5] pc/q35: Disallow vfio-pci hotplug without VT-d caching mode +Bugzilla: 1738440 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Auger Eric +RH-Acked-by: Alex Williamson +Signed-off-by: Danilo C. L. de Paula + +Conflicts: + + hw/i386/pc.c: context differs on quite a few places in + pc_machine_class_init(), but none of them is really relevant to + current change. + +Instead of bailing out when trying to hotplug a vfio-pci device with +below configuration: + + -device intel-iommu,caching-mode=off + +With this we can return a warning message to the user via QMP/HMP and +the VM will continue to work after failing the hotplug: + + (qemu) device_add vfio-pci,bus=root.3,host=05:00.0,id=vfio1 + Error: Device assignment is not allowed without enabling caching-mode=on for Intel IOMMU. + +Reviewed-by: Eric Auger +Signed-off-by: Peter Xu +Message-Id: <20190916080718.3299-4-peterx@redhat.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +(cherry picked from commit c6cbc29d36fe8df078776ed715c37cebac582238) +Signed-off-by: Peter Xu +Signed-off-by: Danilo C. L. de Paula +--- + hw/i386/pc.c | 21 +++++++++++++++++++++ + 1 file changed, 21 insertions(+) + +diff --git a/hw/i386/pc.c b/hw/i386/pc.c +index 9e1e6ae..d6c4050 100644 +--- a/hw/i386/pc.c ++++ b/hw/i386/pc.c +@@ -2340,6 +2340,26 @@ static void x86_nmi(NMIState *n, int cpu_index, Error **errp) + } + } + ++ ++static bool pc_hotplug_allowed(MachineState *ms, DeviceState *dev, Error **errp) ++{ ++ X86IOMMUState *iommu = x86_iommu_get_default(); ++ IntelIOMMUState *intel_iommu; ++ ++ if (iommu && ++ object_dynamic_cast((Object *)iommu, TYPE_INTEL_IOMMU_DEVICE) && ++ object_dynamic_cast((Object *)dev, "vfio-pci")) { ++ intel_iommu = INTEL_IOMMU_DEVICE(iommu); ++ if (!intel_iommu->caching_mode) { ++ error_setg(errp, "Device assignment is not allowed without " ++ "enabling caching-mode=on for Intel IOMMU."); ++ return false; ++ } ++ } ++ ++ return true; ++} ++ + static void pc_machine_class_init(ObjectClass *oc, void *data) + { + MachineClass *mc = MACHINE_CLASS(oc); +@@ -2369,6 +2389,7 @@ static void pc_machine_class_init(ObjectClass *oc, void *data) + */ + mc->async_pf_vmexit_disable = true; + mc->get_hotplug_handler = pc_get_hotpug_handler; ++ mc->hotplug_allowed = pc_hotplug_allowed; + mc->cpu_index_to_instance_props = pc_cpu_index_to_props; + mc->get_default_cpu_node_id = pc_get_default_cpu_node_id; + mc->possible_cpu_arch_ids = pc_possible_cpu_arch_ids; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-pseries-do-not-allow-memory-less-cpu-less-NUMA-node.patch b/SOURCES/kvm-pseries-do-not-allow-memory-less-cpu-less-NUMA-node.patch new file mode 100644 index 0000000..93fa9f7 --- /dev/null +++ b/SOURCES/kvm-pseries-do-not-allow-memory-less-cpu-less-NUMA-node.patch @@ -0,0 +1,108 @@ +From 7ab2261eebf90ea8a3cf5701fa177d181fe665d1 Mon Sep 17 00:00:00 2001 +From: Laurent Vivier +Date: Thu, 10 Oct 2019 07:34:38 +0100 +Subject: [PATCH 22/22] pseries: do not allow memory-less/cpu-less NUMA node +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Laurent Vivier +Message-id: <20191010073438.16478-1-lvivier@redhat.com> +Patchwork-id: 91379 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH] pseries: do not allow memory-less/cpu-less NUMA node +Bugzilla: 1651474 +RH-Acked-by: David Gibson +RH-Acked-by: Thomas Huth +RH-Acked-by: Philippe Mathieu-Daudé + +When we hotplug a CPU on memory-less/cpu-less node, the linux kernel +crashes. + +This happens because linux kernel needs to know the NUMA topology at +start to be able to initialize the distance lookup table. + +On pseries, the topology is provided by the firmware via the existing +CPUs and memory information. Thus a node without memory and CPU cannot be +discovered by the kernel. + +To avoid the kernel crash, do not allow to start pseries with empty +nodes. + +Signed-off-by: Laurent Vivier +Message-Id: <20190830161345.22436-1-lvivier@redhat.com> +[dwg: Rework to cope with movement of numa state from globals to MachineState] +Signed-off-by: David Gibson +(cherry picked from commit 58c46efa451caa3935224223f950216872e2eee3) +Signed-off-by: Laurent Vivier + +Conflicts in the context: + hw/ppc/spapr.c +because of missing downstream commits: + 0550b1206a91 ("spapr: don't advertise radix GTSE if max-compat-cpu < power9") + ad99d04c76de ("target/ppc: Allow cpu compatiblity checks based on type, not instance") + +because of missing donwtream commit: + + 7e721e7b10e1 ("numa: move numa global variable numa_info into MachineState") + +replaced numa_state by numa_info (revert dwg rework), back to original +patch I sent: + + https://patchew.org/QEMU/20190830161345.22436-1-lvivier@redhat.com/ + +BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1651474 +BRANCH: rhel-8.2.0 +UPSTREAM: merged +BREW: https://brewweb.engineering.redhat.com/brew/taskinfo?taskID=23924908 +Signed-off-by: Danilo C. L. de Paula +--- + hw/ppc/spapr.c | 33 +++++++++++++++++++++++++++++++++ + 1 file changed, 33 insertions(+) + +diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c +index 1a2f0d9..b4c9993 100644 +--- a/hw/ppc/spapr.c ++++ b/hw/ppc/spapr.c +@@ -2527,6 +2527,39 @@ static void spapr_machine_init(MachineState *machine) + /* init CPUs */ + spapr_init_cpus(spapr); + ++ /* ++ * check we don't have a memory-less/cpu-less NUMA node ++ * Firmware relies on the existing memory/cpu topology to provide the ++ * NUMA topology to the kernel. ++ * And the linux kernel needs to know the NUMA topology at start ++ * to be able to hotplug CPUs later. ++ */ ++ if (nb_numa_nodes) { ++ for (i = 0; i < nb_numa_nodes; ++i) { ++ /* check for memory-less node */ ++ if (numa_info[i].node_mem == 0) { ++ CPUState *cs; ++ int found = 0; ++ /* check for cpu-less node */ ++ CPU_FOREACH(cs) { ++ PowerPCCPU *cpu = POWERPC_CPU(cs); ++ if (cpu->node_id == i) { ++ found = 1; ++ break; ++ } ++ } ++ /* memory-less and cpu-less node */ ++ if (!found) { ++ error_report( ++ "Memory-less/cpu-less nodes are not supported (node %d)", ++ i); ++ exit(1); ++ } ++ } ++ } ++ ++ } ++ + if (kvm_enabled()) { + /* Enable H_LOGICAL_CI_* so SLOF can talk to in-kernel devices */ + kvmppc_enable_logical_ci_hcalls(); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-qapi-fill-in-CpuInfoFast.arch-in-query-cpus-fast.patch b/SOURCES/kvm-qapi-fill-in-CpuInfoFast.arch-in-query-cpus-fast.patch new file mode 100644 index 0000000..b506221 --- /dev/null +++ b/SOURCES/kvm-qapi-fill-in-CpuInfoFast.arch-in-query-cpus-fast.patch @@ -0,0 +1,116 @@ +From 9000286ea20abb4e03c76ab8f873a6e9eb708377 Mon Sep 17 00:00:00 2001 +From: Maxim Levitsky +Date: Thu, 14 Nov 2019 08:20:41 +0000 +Subject: [PATCH 1/8] qapi: fill in CpuInfoFast.arch in query-cpus-fast + +RH-Author: Maxim Levitsky +Message-id: <20191114082041.20840-2-mlevitsk@redhat.com> +Patchwork-id: 92245 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH v2 1/1] qapi: fill in CpuInfoFast.arch in query-cpus-fast +Bugzilla: 1730969 +RH-Acked-by: Cornelia Huck +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Markus Armbruster + +From: Laszlo Ersek + +* Commit ca230ff33f89 added the @arch field to @CpuInfoFast, but it failed + to set the new field in qmp_query_cpus_fast(), when TARGET_S390X was not + defined. The updated @query-cpus-fast example in "qapi-schema.json" + showed "arch":"x86" only because qmp_query_cpus_fast() calls g_malloc0() + to allocate @CpuInfoFast, and the CPU_INFO_ARCH_X86 enum constant is + generated with value 0. + + All @arch values other than @s390 implied the @CpuInfoOther sub-struct + for @CpuInfoFast -- at the time of writing the patch --, thus no fields + other than @arch needed to be set when TARGET_S390X was not defined. Set + @arch now, by copying the corresponding assignments from + qmp_query_cpus(). + +* Commit 25fa194b7b11 added the @riscv enum constant to @CpuInfoArch (used + in both @CpuInfo and @CpuInfoFast -- the return types of the @query-cpus + and @query-cpus-fast commands, respectively), and assigned, in both + return structures, the @CpuInfoRISCV sub-structure to the new enum + value. + + However, qmp_query_cpus_fast() would not populate either the @arch field + or the @CpuInfoRISCV sub-structure, when TARGET_RISCV was defined; only + qmp_query_cpus() would. + + Assign @CpuInfoOther to the @riscv enum constant in @CpuInfoFast, and + populate only the @arch field in qmp_query_cpus_fast(). Getting CPU + state without interrupting KVM is an exceptional thing that only S390X + does currently. Quoting Cornelia Huck , "s390x is + exceptional in that it has state in QEMU that is actually interesting + for upper layers and can be retrieved without performance penalty". See + also + . + +Cc: Cornelia Huck +Cc: Eric Blake +Cc: Markus Armbruster +Cc: Viktor VM Mihajlovski +Cc: qemu-stable@nongnu.org +Fixes: ca230ff33f89bf7102cbfbc2328716da6750aaed +Fixes: 25fa194b7b11901561532e435beb83d046899f7a +Signed-off-by: Laszlo Ersek +Reviewed-by: Eric Blake +Reviewed-by: Cornelia Huck +Reviewed-by: Markus Armbruster +Message-Id: <20180427192852.15013-2-lersek@redhat.com> +Signed-off-by: Markus Armbruster +(cherry picked from commit 96054f56396eaa0b9b5c681fc3e42a0004b17ade) +Signed-off-by: Maxim Levitsky +Signed-off-by: Danilo C. L. de Paula +--- + cpus.c | 16 +++++++++++++++- + qapi/misc.json | 2 +- + 2 files changed, 16 insertions(+), 2 deletions(-) + +diff --git a/cpus.c b/cpus.c +index 6100089..cea42f9 100644 +--- a/cpus.c ++++ b/cpus.c +@@ -2218,11 +2218,25 @@ CpuInfoFastList *qmp_query_cpus_fast(Error **errp) + info->value->props = props; + } + +-#if defined(TARGET_S390X) ++#if defined(TARGET_I386) ++ info->value->arch = CPU_INFO_ARCH_X86; ++#elif defined(TARGET_PPC) ++ info->value->arch = CPU_INFO_ARCH_PPC; ++#elif defined(TARGET_SPARC) ++ info->value->arch = CPU_INFO_ARCH_SPARC; ++#elif defined(TARGET_MIPS) ++ info->value->arch = CPU_INFO_ARCH_MIPS; ++#elif defined(TARGET_TRICORE) ++ info->value->arch = CPU_INFO_ARCH_TRICORE; ++#elif defined(TARGET_S390X) + s390_cpu = S390_CPU(cpu); + env = &s390_cpu->env; + info->value->arch = CPU_INFO_ARCH_S390; + info->value->u.s390.cpu_state = env->cpu_state; ++#elif defined(TARGET_RISCV) ++ info->value->arch = CPU_INFO_ARCH_RISCV; ++#else ++ info->value->arch = CPU_INFO_ARCH_OTHER; + #endif + if (!cur_item) { + head = cur_item = info; +diff --git a/qapi/misc.json b/qapi/misc.json +index 5636f4a..104d013 100644 +--- a/qapi/misc.json ++++ b/qapi/misc.json +@@ -573,7 +573,7 @@ + 'mips': 'CpuInfoOther', + 'tricore': 'CpuInfoOther', + 's390': 'CpuInfoS390', +- 'riscv': 'CpuInfoRISCV', ++ 'riscv': 'CpuInfoOther', + 'other': 'CpuInfoOther' } } + + ## +-- +1.8.3.1 + diff --git a/SOURCES/kvm-qdev-machine-Introduce-hotplug_allowed-hook.patch b/SOURCES/kvm-qdev-machine-Introduce-hotplug_allowed-hook.patch new file mode 100644 index 0000000..22575fe --- /dev/null +++ b/SOURCES/kvm-qdev-machine-Introduce-hotplug_allowed-hook.patch @@ -0,0 +1,135 @@ +From 6a2ee1fd8d36ed8407b403a7307de1633462759c Mon Sep 17 00:00:00 2001 +From: Peter Xu +Date: Wed, 9 Oct 2019 12:39:45 +0100 +Subject: [PATCH 19/22] qdev/machine: Introduce hotplug_allowed hook + +RH-Author: Peter Xu +Message-id: <20191009123947.21505-4-peterx@redhat.com> +Patchwork-id: 91351 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH 3/5] qdev/machine: Introduce hotplug_allowed hook +Bugzilla: 1738440 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Auger Eric +RH-Acked-by: Alex Williamson +Signed-off-by: Danilo C. L. de Paula + +Conflicts: + + hw/core/qdev.c: don't have 14405c274e86e ("qdev: Provide + qdev_get_bus_hotplug_handler()") + + include/hw/boards: plenty of new things missing in + MachineClass (kvm_type, numa_mem_supported, smp_parse) + + include/hw/qdev-core.h: don't have 17cc0128da3 ("qdev: Let machine + hotplug handler to override bus hotplug handler") + +Introduce this new per-machine hook to give any machine class a chance +to do a sanity check on the to-be-hotplugged device as a sanity test. +This will be used for x86 to try to detect some illegal configuration +of devices, e.g., possible conflictions between vfio-pci and x86 +vIOMMU. + +Reviewed-by: Eric Auger +Signed-off-by: Peter Xu +Message-Id: <20190916080718.3299-3-peterx@redhat.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +(cherry picked from commit d2321d31ff98b75b652c2b1594f00a4cfd48102a) +Signed-off-by: Peter Xu +Signed-off-by: Danilo C. L. de Paula +--- + hw/core/qdev.c | 17 +++++++++++++++++ + include/hw/boards.h | 9 +++++++++ + include/hw/qdev-core.h | 1 + + qdev-monitor.c | 7 +++++++ + 4 files changed, 34 insertions(+) + +diff --git a/hw/core/qdev.c b/hw/core/qdev.c +index 24f1ae7..5971242 100644 +--- a/hw/core/qdev.c ++++ b/hw/core/qdev.c +@@ -259,6 +259,23 @@ HotplugHandler *qdev_get_machine_hotplug_handler(DeviceState *dev) + return NULL; + } + ++bool qdev_hotplug_allowed(DeviceState *dev, Error **errp) ++{ ++ MachineState *machine; ++ MachineClass *mc; ++ Object *m_obj = qdev_get_machine(); ++ ++ if (object_dynamic_cast(m_obj, TYPE_MACHINE)) { ++ machine = MACHINE(m_obj); ++ mc = MACHINE_GET_CLASS(machine); ++ if (mc->hotplug_allowed) { ++ return mc->hotplug_allowed(machine, dev, errp); ++ } ++ } ++ ++ return true; ++} ++ + HotplugHandler *qdev_get_hotplug_handler(DeviceState *dev) + { + HotplugHandler *hotplug_ctrl; +diff --git a/include/hw/boards.h b/include/hw/boards.h +index 9b4a69b..e568a3c 100644 +--- a/include/hw/boards.h ++++ b/include/hw/boards.h +@@ -156,6 +156,13 @@ typedef struct { + * should instead use "unimplemented-device" for all memory ranges where + * the guest will attempt to probe for a device that QEMU doesn't + * implement and a stub device is required. ++ * @hotplug_allowed: ++ * If the hook is provided, then it'll be called for each device ++ * hotplug to check whether the device hotplug is allowed. Return ++ * true to grant allowance or false to reject the hotplug. When ++ * false is returned, an error must be set to show the reason of ++ * the rejection. If the hook is not provided, all hotplug will be ++ * allowed. + */ + struct MachineClass { + /*< private >*/ +@@ -210,6 +217,8 @@ struct MachineClass { + + HotplugHandler *(*get_hotplug_handler)(MachineState *machine, + DeviceState *dev); ++ bool (*hotplug_allowed)(MachineState *state, DeviceState *dev, ++ Error **errp); + CpuInstanceProperties (*cpu_index_to_instance_props)(MachineState *machine, + unsigned cpu_index); + const CPUArchIdList *(*possible_cpu_arch_ids)(MachineState *machine); +diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h +index 9453588..b8d1cac 100644 +--- a/include/hw/qdev-core.h ++++ b/include/hw/qdev-core.h +@@ -286,6 +286,7 @@ void qdev_init_nofail(DeviceState *dev); + void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id, + int required_for_version); + HotplugHandler *qdev_get_machine_hotplug_handler(DeviceState *dev); ++bool qdev_hotplug_allowed(DeviceState *dev, Error **errp); + HotplugHandler *qdev_get_hotplug_handler(DeviceState *dev); + void qdev_unplug(DeviceState *dev, Error **errp); + void qdev_simple_device_unplug_cb(HotplugHandler *hotplug_dev, +diff --git a/qdev-monitor.c b/qdev-monitor.c +index f439b83..70bce8f 100644 +--- a/qdev-monitor.c ++++ b/qdev-monitor.c +@@ -606,6 +606,13 @@ DeviceState *qdev_device_add(QemuOpts *opts, Error **errp) + /* create device */ + dev = DEVICE(object_new(driver)); + ++ /* Check whether the hotplug is allowed by the machine */ ++ if (qdev_hotplug && !qdev_hotplug_allowed(dev, &err)) { ++ /* Error must be set in the machine hook */ ++ assert(err); ++ goto err_del_dev; ++ } ++ + if (bus) { + qdev_set_parent_bus(dev, bus); + } else if (qdev_hotplug && !qdev_get_machine_hotplug_handler(dev)) { +-- +1.8.3.1 + diff --git a/SOURCES/kvm-qemu-img-fix-regression-copying-secrets-during-conve.patch b/SOURCES/kvm-qemu-img-fix-regression-copying-secrets-during-conve.patch new file mode 100644 index 0000000..ead5090 --- /dev/null +++ b/SOURCES/kvm-qemu-img-fix-regression-copying-secrets-during-conve.patch @@ -0,0 +1,124 @@ +From 14768fe9b44d6c89c066ebf597b9be79f7d43f30 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Wed, 14 Aug 2019 11:28:11 +0100 +Subject: [PATCH 3/3] qemu-img: fix regression copying secrets during convert +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Kevin Wolf +Message-id: <20190814112811.28642-2-kwolf@redhat.com> +Patchwork-id: 89987 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 1/1] qemu-img: fix regression copying secrets during convert +Bugzilla: 1727821 +RH-Acked-by: Max Reitz +RH-Acked-by: John Snow +RH-Acked-by: Thomas Huth + +From: Daniel P. Berrangé + +When the convert command is creating an output file that needs +secrets, we need to ensure those secrets are passed to both the +blk_new_open and bdrv_create API calls. + +This is done by qemu-img extracting all opts matching the name +suffix "key-secret". Unfortunately the code doing this was run after the +call to bdrv_create(), which meant the QemuOpts it was extracting +secrets from was now empty. + +Previously this worked by luks as a bug meant the "key-secret" +parameters were not purged from the QemuOpts. This bug was fixed in + + commit b76b4f604521e59f857d6177bc55f6f2e41fd392 + Author: Kevin Wolf + Date: Thu Jan 11 16:18:08 2018 +0100 + + qcow2: Use visitor for options in qcow2_create() + +Exposing the latent bug in qemu-img. This fix simply moves the copying +of secrets to before the bdrv_create() call. + +Cc: qemu-stable@nongnu.org +Signed-off-by: Daniel P. Berrangé +Signed-off-by: Kevin Wolf +(cherry picked from commit 8d65a3ccfd5db7f0436e095cd952f5d0c3a873ba) +Signed-off-by: Kevin Wolf +Signed-off-by: Danilo C. L. de Paula +--- + qemu-img.c | 32 +++++++++++++++----------------- + 1 file changed, 15 insertions(+), 17 deletions(-) + +diff --git a/qemu-img.c b/qemu-img.c +index f42750a..fa0cbd7 100644 +--- a/qemu-img.c ++++ b/qemu-img.c +@@ -348,21 +348,6 @@ static int img_add_key_secrets(void *opaque, + return 0; + } + +-static BlockBackend *img_open_new_file(const char *filename, +- QemuOpts *create_opts, +- const char *fmt, int flags, +- bool writethrough, bool quiet, +- bool force_share) +-{ +- QDict *options = NULL; +- +- options = qdict_new(); +- qemu_opt_foreach(create_opts, img_add_key_secrets, options, &error_abort); +- +- return img_open_file(filename, options, fmt, flags, writethrough, quiet, +- force_share); +-} +- + + static BlockBackend *img_open(bool image_opts, + const char *filename, +@@ -1994,6 +1979,7 @@ static int img_convert(int argc, char **argv) + BlockDriverState *out_bs; + QemuOpts *opts = NULL, *sn_opts = NULL; + QemuOptsList *create_opts = NULL; ++ QDict *open_opts = NULL; + char *options = NULL; + Error *local_err = NULL; + bool writethrough, src_writethrough, quiet = false, image_opts = false, +@@ -2342,6 +2328,16 @@ static int img_convert(int argc, char **argv) + } + } + ++ /* ++ * The later open call will need any decryption secrets, and ++ * bdrv_create() will purge "opts", so extract them now before ++ * they are lost. ++ */ ++ if (!skip_create) { ++ open_opts = qdict_new(); ++ qemu_opt_foreach(opts, img_add_key_secrets, open_opts, &error_abort); ++ } ++ + if (!skip_create) { + /* Create the new image */ + ret = bdrv_create(drv, out_filename, opts, &local_err); +@@ -2368,8 +2364,9 @@ static int img_convert(int argc, char **argv) + * That has to wait for bdrv_create to be improved + * to allow filenames in option syntax + */ +- s.target = img_open_new_file(out_filename, opts, out_fmt, +- flags, writethrough, quiet, false); ++ s.target = img_open_file(out_filename, open_opts, out_fmt, ++ flags, writethrough, quiet, false); ++ open_opts = NULL; /* blk_new_open will have freed it */ + } + if (!s.target) { + ret = -1; +@@ -2437,6 +2434,7 @@ out: + qemu_opts_del(opts); + qemu_opts_free(create_opts); + qemu_opts_del(sn_opts); ++ qobject_unref(open_opts); + blk_unref(s.target); + if (s.src) { + for (bs_i = 0; bs_i < s.src_num; bs_i++) { +-- +1.8.3.1 + diff --git a/SOURCES/kvm-qemu-iotests-Filter-NFS-paths.patch b/SOURCES/kvm-qemu-iotests-Filter-NFS-paths.patch new file mode 100644 index 0000000..a891d98 --- /dev/null +++ b/SOURCES/kvm-qemu-iotests-Filter-NFS-paths.patch @@ -0,0 +1,110 @@ +From 065df0fad17065597ffb3baf5b697c82c95c2ed0 Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Mon, 8 Jul 2019 15:25:55 +0100 +Subject: [PATCH 09/39] qemu-iotests: Filter NFS paths +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Pino Toscano +Message-id: <20190708152601.21123-5-ptoscano@redhat.com> +Patchwork-id: 89419 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v3 04/10] qemu-iotests: Filter NFS paths +Bugzilla: 1513367 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Max Reitz +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Markus Armbruster + +From: Kevin Wolf + +NFS paths were only partially filtered in _filter_img_create, _img_info +and _filter_img_info, resulting in "nfs://127.0.0.1TEST_DIR/t.IMGFMT". +This adds another replacement to the sed calls that matches the test +directory not as a host path, but as an NFS URL (the prefix as used for +$TEST_IMG). + +Signed-off-by: Kevin Wolf +Reviewed-by: Fam Zheng +(cherry picked from commit 8908b253c4ad5f8874c8d13abec169c696a5cd32) +Signed-off-by: Pino Toscano +Signed-off-by: Danilo C. L. de Paula +--- + tests/qemu-iotests/126.out | 2 +- + tests/qemu-iotests/common.filter | 6 ++++-- + tests/qemu-iotests/common.rc | 8 +++++++- + 3 files changed, 12 insertions(+), 4 deletions(-) + +diff --git a/tests/qemu-iotests/126.out b/tests/qemu-iotests/126.out +index 50d7308..17d03d5 100644 +--- a/tests/qemu-iotests/126.out ++++ b/tests/qemu-iotests/126.out +@@ -3,7 +3,7 @@ QA output created by 126 + === Testing plain files === + + Formatting 'TEST_DIR/a:b.IMGFMT', fmt=IMGFMT size=67108864 +-Formatting 'TEST_DIR/a:b.IMGFMT', fmt=IMGFMT size=67108864 ++Formatting 'file:TEST_DIR/a:b.IMGFMT', fmt=IMGFMT size=67108864 + + === Testing relative backing filename resolution === + +diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter +index 7acb454..2031e35 100644 +--- a/tests/qemu-iotests/common.filter ++++ b/tests/qemu-iotests/common.filter +@@ -118,7 +118,8 @@ _filter_actual_image_size() + # replace driver-specific options in the "Formatting..." line + _filter_img_create() + { +- sed -e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \ ++ sed -e "s#$REMOTE_TEST_DIR#TEST_DIR#g" \ ++ -e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \ + -e "s#$TEST_DIR#TEST_DIR#g" \ + -e "s#$IMGFMT#IMGFMT#g" \ + -e 's#nbd:127.0.0.1:10810#TEST_DIR/t.IMGFMT#g' \ +@@ -153,7 +154,8 @@ _filter_img_info() + + discard=0 + regex_json_spec_start='^ *"format-specific": \{' +- sed -e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \ ++ sed -e "s#$REMOTE_TEST_DIR#TEST_DIR#g" \ ++ -e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \ + -e "s#$TEST_DIR#TEST_DIR#g" \ + -e "s#$IMGFMT#IMGFMT#g" \ + -e 's#nbd://127.0.0.1:10810$#TEST_DIR/t.IMGFMT#g' \ +diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc +index cb5fa14..d054cb9 100644 +--- a/tests/qemu-iotests/common.rc ++++ b/tests/qemu-iotests/common.rc +@@ -148,6 +148,7 @@ else + TEST_IMG="ssh://127.0.0.1$TEST_IMG_FILE" + elif [ "$IMGPROTO" = "nfs" ]; then + TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT ++ REMOTE_TEST_DIR="nfs://127.0.0.1$TEST_DIR" + TEST_IMG="nfs://127.0.0.1$TEST_IMG_FILE" + elif [ "$IMGPROTO" = "vxhs" ]; then + TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT +@@ -173,6 +174,10 @@ if [ ! -d "$TEST_DIR" ]; then + exit 1 + fi + ++if [ -z "$REMOTE_TEST_DIR" ]; then ++ REMOTE_TEST_DIR="$TEST_DIR" ++fi ++ + if [ ! -d "$SAMPLE_IMG_DIR" ]; then + echo "common.config: Error: \$SAMPLE_IMG_DIR ($SAMPLE_IMG_DIR) is not a directory" + exit 1 +@@ -333,7 +338,8 @@ _img_info() + discard=0 + regex_json_spec_start='^ *"format-specific": \{' + $QEMU_IMG info $QEMU_IMG_EXTRA_ARGS "$@" "$TEST_IMG" 2>&1 | \ +- sed -e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \ ++ sed -e "s#$REMOTE_TEST_DIR#TEST_DIR#g" \ ++ -e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \ + -e "s#$TEST_DIR#TEST_DIR#g" \ + -e "s#$IMGFMT#IMGFMT#g" \ + -e "/^disk size:/ D" \ +-- +1.8.3.1 + diff --git a/SOURCES/kvm-qemu-iotests-Fix-paths-for-NFS.patch b/SOURCES/kvm-qemu-iotests-Fix-paths-for-NFS.patch new file mode 100644 index 0000000..c475e51 --- /dev/null +++ b/SOURCES/kvm-qemu-iotests-Fix-paths-for-NFS.patch @@ -0,0 +1,51 @@ +From 5e41ecd75bc95d1390328218676c72ac1cf4562b Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Mon, 8 Jul 2019 15:25:54 +0100 +Subject: [PATCH 08/39] qemu-iotests: Fix paths for NFS +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Pino Toscano +Message-id: <20190708152601.21123-4-ptoscano@redhat.com> +Patchwork-id: 89423 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v3 03/10] qemu-iotests: Fix paths for NFS +Bugzilla: 1513367 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Max Reitz +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Markus Armbruster + +From: Kevin Wolf + +Test cases were trying to use nfs:// URLs as local filenames, which made +every test fail for NFS. With TEST_IMG and TEST_IMG_FILE set like for +the other protocols, NFS tests can pass again. + +Signed-off-by: Kevin Wolf +Reviewed-by: Fam Zheng +(cherry picked from commit 655ae6bb91998a01964759406cb38ef215a6ba5b) +Signed-off-by: Pino Toscano +Signed-off-by: Danilo C. L. de Paula +--- + tests/qemu-iotests/common.rc | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc +index 9a65a11..cb5fa14 100644 +--- a/tests/qemu-iotests/common.rc ++++ b/tests/qemu-iotests/common.rc +@@ -147,8 +147,8 @@ else + TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT + TEST_IMG="ssh://127.0.0.1$TEST_IMG_FILE" + elif [ "$IMGPROTO" = "nfs" ]; then +- TEST_DIR="nfs://127.0.0.1/$TEST_DIR" +- TEST_IMG=$TEST_DIR/t.$IMGFMT ++ TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT ++ TEST_IMG="nfs://127.0.0.1$TEST_IMG_FILE" + elif [ "$IMGPROTO" = "vxhs" ]; then + TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT + TEST_IMG="vxhs://127.0.0.1:9999/t.$IMGFMT" +-- +1.8.3.1 + diff --git a/SOURCES/kvm-qxl-check-release-info-object.patch b/SOURCES/kvm-qxl-check-release-info-object.patch new file mode 100644 index 0000000..5f14dc6 --- /dev/null +++ b/SOURCES/kvm-qxl-check-release-info-object.patch @@ -0,0 +1,50 @@ +From 56a21c3a967a6cbf99e2ecb2dff30d4dca759532 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Thu, 20 Jun 2019 13:07:31 +0100 +Subject: [PATCH 1/2] qxl: check release info object +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Philippe Mathieu-Daudé +Message-id: <20190620130731.18034-2-philmd@redhat.com> +Patchwork-id: 88745 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 1/1] qxl: check release info object +Bugzilla: 1712705 +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Stefan Hajnoczi + +From: Prasad J Pandit + +When releasing spice resources in release_resource() routine, +if release info object 'ext.info' is null, it leads to null +pointer dereference. Add check to avoid it. + +Reported-by: Bugs SysSec +Signed-off-by: Prasad J Pandit +Message-id: 20190425063534.32747-1-ppandit@redhat.com +Signed-off-by: Gerd Hoffmann +(cherry picked from commit d52680fc932efb8a2f334cc6993e705ed1e31e99) +Signed-off-by: Danilo C. L. de Paula +--- + hw/display/qxl.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/hw/display/qxl.c b/hw/display/qxl.c +index b373c50..a8c953b 100644 +--- a/hw/display/qxl.c ++++ b/hw/display/qxl.c +@@ -776,6 +776,9 @@ static void interface_release_resource(QXLInstance *sin, + QXLReleaseRing *ring; + uint64_t *item, id; + ++ if (!ext.info) { ++ return; ++ } + if (ext.group_id == MEMSLOT_GROUP_HOST) { + /* host group -> vga mode update request */ + QXLCommandExt *cmdext = (void *)(intptr_t)(ext.info->id); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390-PCI-fix-IOMMU-region-init.patch b/SOURCES/kvm-s390-PCI-fix-IOMMU-region-init.patch new file mode 100644 index 0000000..d6822b8 --- /dev/null +++ b/SOURCES/kvm-s390-PCI-fix-IOMMU-region-init.patch @@ -0,0 +1,61 @@ +From 324a0ffc5140c4ece5b720708da2c673a8d1b9cc Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Tue, 1 Oct 2019 06:02:58 +0100 +Subject: [PATCH 12/22] s390: PCI: fix IOMMU region init + +RH-Author: Thomas Huth +Message-id: <20191001060258.28206-2-thuth@redhat.com> +Patchwork-id: 90929 +O-Subject: [RHEL-8.2.0/RHEL-8.1.z qemu-kvm PATCH 1/1] s390: PCI: fix IOMMU region init +Bugzilla: 1754643 +RH-Acked-by: Jens Freimann +RH-Acked-by: David Hildenbrand +RH-Acked-by: Maxim Levitsky + +From: Matthew Rosato + +The fix in dbe9cf606c shrinks the IOMMU memory region to a size +that seems reasonable on the surface, however is actually too +small as it is based against a 0-mapped address space. This +causes breakage with small guests as they can overrun the IOMMU window. + +Let's go back to the prior method of initializing iommu for now. + +Fixes: dbe9cf606c ("s390x/pci: Set the iommu region size mpcifc request") +Reviewed-by: Pierre Morel +Reported-by: Boris Fiuczynski +Tested-by: Boris Fiuczynski +Reported-by: Stefan Zimmerman +Signed-off-by: Matthew Rosato +Message-Id: <1569507036-15314-1-git-send-email-mjrosato@linux.ibm.com> +Signed-off-by: Christian Borntraeger +(cherry picked from commit 7df1dac5f1c85312474df9cb3a8fcae72303da62) +Signed-off-by: Danilo C. L. de Paula +--- + hw/s390x/s390-pci-bus.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c +index 383b3e7..069e152 100644 +--- a/hw/s390x/s390-pci-bus.c ++++ b/hw/s390x/s390-pci-bus.c +@@ -691,10 +691,15 @@ static const MemoryRegionOps s390_msi_ctrl_ops = { + + void s390_pci_iommu_enable(S390PCIIOMMU *iommu) + { ++ /* ++ * The iommu region is initialized against a 0-mapped address space, ++ * so the smallest IOMMU region we can define runs from 0 to the end ++ * of the PCI address space. ++ */ + char *name = g_strdup_printf("iommu-s390-%04x", iommu->pbdev->uid); + memory_region_init_iommu(&iommu->iommu_mr, sizeof(iommu->iommu_mr), + TYPE_S390_IOMMU_MEMORY_REGION, OBJECT(&iommu->mr), +- name, iommu->pal - iommu->pba + 1); ++ name, iommu->pal + 1); + iommu->enabled = true; + memory_region_add_subregion(&iommu->mr, 0, MEMORY_REGION(&iommu->iommu_mr)); + g_free(name); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390-bios-Add-channel-command-codes-structs-needed-f.patch b/SOURCES/kvm-s390-bios-Add-channel-command-codes-structs-needed-f.patch new file mode 100644 index 0000000..9c02f2d --- /dev/null +++ b/SOURCES/kvm-s390-bios-Add-channel-command-codes-structs-needed-f.patch @@ -0,0 +1,88 @@ +From 81d722eaf6284d55e2da0ba6cc4874bfd262a7e2 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Mon, 14 Oct 2019 10:06:43 +0100 +Subject: [PATCH 18/21] s390-bios: Add channel command codes/structs needed for + dasd-ipl + +RH-Author: Thomas Huth +Message-id: <20191014100645.22862-16-thuth@redhat.com> +Patchwork-id: 91792 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH v2 15/17] s390-bios: Add channel command codes/structs needed for dasd-ipl +Bugzilla: 1664376 +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand +RH-Acked-by: Jens Freimann + +From: "Jason J. Herne" + +The dasd IPL procedure needs to execute a few previously unused +channel commands. Let's define them and their associated data +structures. + +Signed-off-by: Jason J. Herne +Acked-by: Cornelia Huck +Acked-by: Thomas Huth +Message-Id: <1554388475-18329-15-git-send-email-jjherne@linux.ibm.com> +Signed-off-by: Thomas Huth +(cherry picked from commit 69333c36dc85b84b021766747cffc2b53df93ae8) +Signed-off-by: Danilo C. L. de Paula +--- + pc-bios/s390-ccw/cio.h | 23 +++++++++++++++++++++++ + 1 file changed, 23 insertions(+) + +diff --git a/pc-bios/s390-ccw/cio.h b/pc-bios/s390-ccw/cio.h +index 1637e32..aaa432d 100644 +--- a/pc-bios/s390-ccw/cio.h ++++ b/pc-bios/s390-ccw/cio.h +@@ -200,11 +200,14 @@ typedef struct ccw1 { + #define CCW_FLAG_IDA 0x04 + #define CCW_FLAG_SUSPEND 0x02 + ++/* Common CCW commands */ ++#define CCW_CMD_READ_IPL 0x02 + #define CCW_CMD_NOOP 0x03 + #define CCW_CMD_BASIC_SENSE 0x04 + #define CCW_CMD_TIC 0x08 + #define CCW_CMD_SENSE_ID 0xe4 + ++/* Virtio CCW commands */ + #define CCW_CMD_SET_VQ 0x13 + #define CCW_CMD_VDEV_RESET 0x33 + #define CCW_CMD_READ_FEAT 0x12 +@@ -216,6 +219,12 @@ typedef struct ccw1 { + #define CCW_CMD_SET_CONF_IND 0x53 + #define CCW_CMD_READ_VQ_CONF 0x32 + ++/* DASD CCW commands */ ++#define CCW_CMD_DASD_READ 0x06 ++#define CCW_CMD_DASD_SEEK 0x07 ++#define CCW_CMD_DASD_SEARCH_ID_EQ 0x31 ++#define CCW_CMD_DASD_READ_MT 0x86 ++ + /* + * Command-mode operation request block + */ +@@ -333,6 +342,20 @@ typedef struct irb { + __u32 emw[8]; + } __attribute__ ((packed, aligned(4))) Irb; + ++/* Used for SEEK ccw commands */ ++typedef struct CcwSeekData { ++ uint16_t reserved; ++ uint16_t cyl; ++ uint16_t head; ++} __attribute__((packed)) CcwSeekData; ++ ++/* Used for SEARCH ID ccw commands */ ++typedef struct CcwSearchIdData { ++ uint16_t cyl; ++ uint16_t head; ++ uint8_t record; ++} __attribute__((packed)) CcwSearchIdData; ++ + int enable_mss_facility(void); + void enable_subchannel(SubChannelId schid); + uint16_t cu_type(SubChannelId schid); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390-bios-Clean-up-cio.h.patch b/SOURCES/kvm-s390-bios-Clean-up-cio.h.patch new file mode 100644 index 0000000..7dd990a --- /dev/null +++ b/SOURCES/kvm-s390-bios-Clean-up-cio.h.patch @@ -0,0 +1,251 @@ +From fc07c126ddd0796c1996b2e527e69486c9c848b9 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Mon, 14 Oct 2019 10:06:33 +0100 +Subject: [PATCH 08/21] s390-bios: Clean up cio.h + +RH-Author: Thomas Huth +Message-id: <20191014100645.22862-6-thuth@redhat.com> +Patchwork-id: 91782 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH v2 05/17] s390-bios: Clean up cio.h +Bugzilla: 1664376 +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand +RH-Acked-by: Jens Freimann + +From: "Jason J. Herne" + +Add proper typedefs to all structs and modify all bit fields to use consistent +formatting. + +Signed-off-by: Jason J. Herne +Reviewed-by: Collin Walling +Reviewed-by: Farhan Ali +Acked-by: Cornelia Huck +Reviewed-by: Thomas Huth +Message-Id: <1554388475-18329-5-git-send-email-jjherne@linux.ibm.com> +Signed-off-by: Thomas Huth +(cherry picked from commit d96c5db77f1058ee9509554f43b945c66b3aa7c9) +Signed-off-by: Danilo C. L. de Paula +--- + pc-bios/s390-ccw/cio.h | 114 ++++++++++++++++++++++---------------------- + pc-bios/s390-ccw/s390-ccw.h | 8 ---- + 2 files changed, 57 insertions(+), 65 deletions(-) + +diff --git a/pc-bios/s390-ccw/cio.h b/pc-bios/s390-ccw/cio.h +index 1a0795f..ed5b2cb 100644 +--- a/pc-bios/s390-ccw/cio.h ++++ b/pc-bios/s390-ccw/cio.h +@@ -17,35 +17,35 @@ + * path management control word + */ + struct pmcw { +- __u32 intparm; /* interruption parameter */ +- __u32 qf : 1; /* qdio facility */ +- __u32 w : 1; +- __u32 isc : 3; /* interruption sublass */ +- __u32 res5 : 3; /* reserved zeros */ +- __u32 ena : 1; /* enabled */ +- __u32 lm : 2; /* limit mode */ +- __u32 mme : 2; /* measurement-mode enable */ +- __u32 mp : 1; /* multipath mode */ +- __u32 tf : 1; /* timing facility */ +- __u32 dnv : 1; /* device number valid */ +- __u32 dev : 16; /* device number */ +- __u8 lpm; /* logical path mask */ +- __u8 pnom; /* path not operational mask */ +- __u8 lpum; /* last path used mask */ +- __u8 pim; /* path installed mask */ +- __u16 mbi; /* measurement-block index */ +- __u8 pom; /* path operational mask */ +- __u8 pam; /* path available mask */ +- __u8 chpid[8]; /* CHPID 0-7 (if available) */ +- __u32 unused1 : 8; /* reserved zeros */ +- __u32 st : 3; /* subchannel type */ +- __u32 unused2 : 18; /* reserved zeros */ +- __u32 mbfc : 1; /* measurement block format control */ +- __u32 xmwme : 1; /* extended measurement word mode enable */ +- __u32 csense : 1; /* concurrent sense; can be enabled ...*/ +- /* ... per MSCH, however, if facility */ +- /* ... is not installed, this results */ +- /* ... in an operand exception. */ ++ __u32 intparm; /* interruption parameter */ ++ __u32 qf:1; /* qdio facility */ ++ __u32 w:1; ++ __u32 isc:3; /* interruption sublass */ ++ __u32 res5:3; /* reserved zeros */ ++ __u32 ena:1; /* enabled */ ++ __u32 lm:2; /* limit mode */ ++ __u32 mme:2; /* measurement-mode enable */ ++ __u32 mp:1; /* multipath mode */ ++ __u32 tf:1; /* timing facility */ ++ __u32 dnv:1; /* device number valid */ ++ __u32 dev:16; /* device number */ ++ __u8 lpm; /* logical path mask */ ++ __u8 pnom; /* path not operational mask */ ++ __u8 lpum; /* last path used mask */ ++ __u8 pim; /* path installed mask */ ++ __u16 mbi; /* measurement-block index */ ++ __u8 pom; /* path operational mask */ ++ __u8 pam; /* path available mask */ ++ __u8 chpid[8]; /* CHPID 0-7 (if available) */ ++ __u32 unused1:8; /* reserved zeros */ ++ __u32 st:3; /* subchannel type */ ++ __u32 unused2:18; /* reserved zeros */ ++ __u32 mbfc:1; /* measurement block format control */ ++ __u32 xmwme:1; /* extended measurement word mode enable */ ++ __u32 csense:1; /* concurrent sense; can be enabled ...*/ ++ /* ... per MSCH, however, if facility */ ++ /* ... is not installed, this results */ ++ /* ... in an operand exception. */ + } __attribute__ ((packed)); + + /* Target SCHIB configuration. */ +@@ -77,28 +77,28 @@ struct scsw { + /* + * subchannel information block + */ +-struct schib { ++typedef struct schib { + struct pmcw pmcw; /* path management control word */ + struct scsw scsw; /* subchannel status word */ + __u64 mba; /* measurement block address */ + __u8 mda[4]; /* model dependent area */ +-} __attribute__ ((packed,aligned(4))); +- +-struct subchannel_id { +- __u32 cssid : 8; +- __u32 : 4; +- __u32 m : 1; +- __u32 ssid : 2; +- __u32 one : 1; +- __u32 sch_no : 16; +-} __attribute__ ((packed, aligned(4))); ++} __attribute__ ((packed, aligned(4))) Schib; ++ ++typedef struct subchannel_id { ++ __u32 cssid:8; ++ __u32:4; ++ __u32 m:1; ++ __u32 ssid:2; ++ __u32 one:1; ++ __u32 sch_no:16; ++} __attribute__ ((packed, aligned(4))) SubChannelId; + + struct chsc_header { + __u16 length; + __u16 code; + } __attribute__((packed)); + +-struct chsc_area_sda { ++typedef struct chsc_area_sda { + struct chsc_header request; + __u8 reserved1:4; + __u8 format:4; +@@ -111,29 +111,29 @@ struct chsc_area_sda { + __u32 reserved5:4; + __u32 format2:4; + __u32 reserved6:24; +-} __attribute__((packed)); ++} __attribute__((packed)) ChscAreaSda; + + /* + * TPI info structure + */ + struct tpi_info { + struct subchannel_id schid; +- __u32 intparm; /* interruption parameter */ +- __u32 adapter_IO : 1; +- __u32 reserved2 : 1; +- __u32 isc : 3; +- __u32 reserved3 : 12; +- __u32 int_type : 3; +- __u32 reserved4 : 12; ++ __u32 intparm; /* interruption parameter */ ++ __u32 adapter_IO:1; ++ __u32 reserved2:1; ++ __u32 isc:3; ++ __u32 reserved3:12; ++ __u32 int_type:3; ++ __u32 reserved4:12; + } __attribute__ ((packed, aligned(4))); + + /* channel command word (type 1) */ +-struct ccw1 { ++typedef struct ccw1 { + __u8 cmd_code; + __u8 flags; + __u16 count; + __u32 cda; +-} __attribute__ ((packed, aligned(8))); ++} __attribute__ ((packed, aligned(8))) Ccw1; + + #define CCW_FLAG_DC 0x80 + #define CCW_FLAG_CC 0x40 +@@ -162,7 +162,7 @@ struct ccw1 { + /* + * Command-mode operation request block + */ +-struct cmd_orb { ++typedef struct cmd_orb { + __u32 intparm; /* interruption parameter */ + __u32 key:4; /* flags, like key, suspend control, etc. */ + __u32 spnd:1; /* suspend control */ +@@ -182,7 +182,7 @@ struct cmd_orb { + __u32 zero:6; /* reserved zeros */ + __u32 orbx:1; /* ORB extension control */ + __u32 cpa; /* channel program address */ +-} __attribute__ ((packed, aligned(4))); ++} __attribute__ ((packed, aligned(4))) CmdOrb; + + struct ciw { + __u8 type; +@@ -193,7 +193,7 @@ struct ciw { + /* + * sense-id response buffer layout + */ +-struct senseid { ++typedef struct senseid { + /* common part */ + __u8 reserved; /* always 0x'FF' */ + __u16 cu_type; /* control unit type */ +@@ -203,15 +203,15 @@ struct senseid { + __u8 unused; /* padding byte */ + /* extended part */ + struct ciw ciw[62]; +-} __attribute__ ((packed, aligned(4))); ++} __attribute__ ((packed, aligned(4))) SenseId; + + /* interruption response block */ +-struct irb { ++typedef struct irb { + struct scsw scsw; + __u32 esw[5]; + __u32 ecw[8]; + __u32 emw[8]; +-} __attribute__ ((packed, aligned(4))); ++} __attribute__ ((packed, aligned(4))) Irb; + + /* + * Some S390 specific IO instructions as inline +diff --git a/pc-bios/s390-ccw/s390-ccw.h b/pc-bios/s390-ccw/s390-ccw.h +index 9828aa2..241c6d0 100644 +--- a/pc-bios/s390-ccw/s390-ccw.h ++++ b/pc-bios/s390-ccw/s390-ccw.h +@@ -49,14 +49,6 @@ typedef unsigned long long __u64; + #include "cio.h" + #include "iplb.h" + +-typedef struct irb Irb; +-typedef struct ccw1 Ccw1; +-typedef struct cmd_orb CmdOrb; +-typedef struct schib Schib; +-typedef struct chsc_area_sda ChscAreaSda; +-typedef struct senseid SenseId; +-typedef struct subchannel_id SubChannelId; +- + /* start.s */ + void disabled_wait(void); + void consume_sclp_int(void); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390-bios-Decouple-channel-i-o-logic-from-virtio.patch b/SOURCES/kvm-s390-bios-Decouple-channel-i-o-logic-from-virtio.patch new file mode 100644 index 0000000..4e8b917 --- /dev/null +++ b/SOURCES/kvm-s390-bios-Decouple-channel-i-o-logic-from-virtio.patch @@ -0,0 +1,226 @@ +From 9fa5a139c303dd7cedabafda03bcd79807b01086 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Mon, 14 Oct 2019 10:06:34 +0100 +Subject: [PATCH 09/21] s390-bios: Decouple channel i/o logic from virtio + +RH-Author: Thomas Huth +Message-id: <20191014100645.22862-7-thuth@redhat.com> +Patchwork-id: 91779 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH v2 06/17] s390-bios: Decouple channel i/o logic from virtio +Bugzilla: 1664376 +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand +RH-Acked-by: Jens Freimann + +From: "Jason J. Herne" + +Create a separate library for channel i/o related code. This decouples +channel i/o operations from virtio and allows us to make use of them for +the real dasd boot path. + +Signed-off-by: Jason J. Herne +Reviewed-by: Cornelia Huck +Reviewed-by: Thomas Huth +Message-Id: <1554388475-18329-6-git-send-email-jjherne@linux.ibm.com> +Signed-off-by: Thomas Huth +(cherry picked from commit 120d04103e3f870d0fcd2a23c2ada0a4a4f036cc) +Signed-off-by: Danilo C. L. de Paula +--- + pc-bios/s390-ccw/Makefile | 2 +- + pc-bios/s390-ccw/cio.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ + pc-bios/s390-ccw/cio.h | 3 +++ + pc-bios/s390-ccw/main.c | 1 + + pc-bios/s390-ccw/netboot.mak | 2 +- + pc-bios/s390-ccw/netmain.c | 1 + + pc-bios/s390-ccw/s390-ccw.h | 1 - + pc-bios/s390-ccw/virtio.c | 27 ++------------------------- + 8 files changed, 53 insertions(+), 28 deletions(-) + create mode 100644 pc-bios/s390-ccw/cio.c + +diff --git a/pc-bios/s390-ccw/Makefile b/pc-bios/s390-ccw/Makefile +index 439e3cc..acca961 100644 +--- a/pc-bios/s390-ccw/Makefile ++++ b/pc-bios/s390-ccw/Makefile +@@ -10,7 +10,7 @@ $(call set-vpath, $(SRC_PATH)/pc-bios/s390-ccw) + .PHONY : all clean build-all + + OBJECTS = start.o main.o bootmap.o jump2ipl.o sclp.o menu.o \ +- virtio.o virtio-scsi.o virtio-blkdev.o libc.o ++ virtio.o virtio-scsi.o virtio-blkdev.o libc.o cio.o + + QEMU_CFLAGS := $(filter -W%, $(QEMU_CFLAGS)) + QEMU_CFLAGS += -ffreestanding -fno-delete-null-pointer-checks -msoft-float +diff --git a/pc-bios/s390-ccw/cio.c b/pc-bios/s390-ccw/cio.c +new file mode 100644 +index 0000000..87c6b34 +--- /dev/null ++++ b/pc-bios/s390-ccw/cio.c +@@ -0,0 +1,44 @@ ++/* ++ * S390 Channel I/O ++ * ++ * Copyright (c) 2013 Alexander Graf ++ * Copyright (c) 2019 IBM Corp. ++ * ++ * Author(s): Jason J. Herne ++ * ++ * This work is licensed under the terms of the GNU GPL, version 2 or (at ++ * your option) any later version. See the COPYING file in the top-level ++ * directory. ++ */ ++ ++#include "libc.h" ++#include "s390-ccw.h" ++#include "cio.h" ++ ++static char chsc_page[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE))); ++ ++int enable_mss_facility(void) ++{ ++ int ret; ++ ChscAreaSda *sda_area = (ChscAreaSda *) chsc_page; ++ ++ memset(sda_area, 0, PAGE_SIZE); ++ sda_area->request.length = 0x0400; ++ sda_area->request.code = 0x0031; ++ sda_area->operation_code = 0x2; ++ ++ ret = chsc(sda_area); ++ if ((ret == 0) && (sda_area->response.code == 0x0001)) { ++ return 0; ++ } ++ return -EIO; ++} ++ ++void enable_subchannel(SubChannelId schid) ++{ ++ Schib schib; ++ ++ stsch_err(schid, &schib); ++ schib.pmcw.ena = 1; ++ msch(schid, &schib); ++} +diff --git a/pc-bios/s390-ccw/cio.h b/pc-bios/s390-ccw/cio.h +index ed5b2cb..218fd96 100644 +--- a/pc-bios/s390-ccw/cio.h ++++ b/pc-bios/s390-ccw/cio.h +@@ -213,6 +213,9 @@ typedef struct irb { + __u32 emw[8]; + } __attribute__ ((packed, aligned(4))) Irb; + ++int enable_mss_facility(void); ++void enable_subchannel(SubChannelId schid); ++ + /* + * Some S390 specific IO instructions as inline + */ +diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c +index 67df421..10f04c6 100644 +--- a/pc-bios/s390-ccw/main.c ++++ b/pc-bios/s390-ccw/main.c +@@ -10,6 +10,7 @@ + + #include "libc.h" + #include "s390-ccw.h" ++#include "cio.h" + #include "virtio.h" + + char stack[PAGE_SIZE * 8] __attribute__((__aligned__(PAGE_SIZE))); +diff --git a/pc-bios/s390-ccw/netboot.mak b/pc-bios/s390-ccw/netboot.mak +index 4f64128..d17b424 100644 +--- a/pc-bios/s390-ccw/netboot.mak ++++ b/pc-bios/s390-ccw/netboot.mak +@@ -1,7 +1,7 @@ + + SLOF_DIR := $(SRC_PATH)/roms/SLOF + +-NETOBJS := start.o sclp.o virtio.o virtio-net.o jump2ipl.o netmain.o \ ++NETOBJS := start.o sclp.o cio.o virtio.o virtio-net.o jump2ipl.o netmain.o \ + libnet.a libc.a + + LIBC_INC := -nostdinc -I$(SLOF_DIR)/lib/libc/include +diff --git a/pc-bios/s390-ccw/netmain.c b/pc-bios/s390-ccw/netmain.c +index d60e84f..4e1b8cf 100644 +--- a/pc-bios/s390-ccw/netmain.c ++++ b/pc-bios/s390-ccw/netmain.c +@@ -32,6 +32,7 @@ + #include + + #include "s390-ccw.h" ++#include "cio.h" + #include "virtio.h" + + #define DEFAULT_BOOT_RETRIES 10 +diff --git a/pc-bios/s390-ccw/s390-ccw.h b/pc-bios/s390-ccw/s390-ccw.h +index 241c6d0..b39ee5d 100644 +--- a/pc-bios/s390-ccw/s390-ccw.h ++++ b/pc-bios/s390-ccw/s390-ccw.h +@@ -72,7 +72,6 @@ unsigned long virtio_load_direct(ulong rec_list1, ulong rec_list2, + bool virtio_is_supported(SubChannelId schid); + void virtio_blk_setup_device(SubChannelId schid); + int virtio_read(ulong sector, void *load_addr); +-int enable_mss_facility(void); + u64 get_clock(void); + ulong get_second(void); + +diff --git a/pc-bios/s390-ccw/virtio.c b/pc-bios/s390-ccw/virtio.c +index cdb66f4..aa9da72 100644 +--- a/pc-bios/s390-ccw/virtio.c ++++ b/pc-bios/s390-ccw/virtio.c +@@ -10,6 +10,7 @@ + + #include "libc.h" + #include "s390-ccw.h" ++#include "cio.h" + #include "virtio.h" + #include "virtio-scsi.h" + #include "bswap.h" +@@ -20,8 +21,6 @@ static VRing block[VIRTIO_MAX_VQS]; + static char ring_area[VIRTIO_RING_SIZE * VIRTIO_MAX_VQS] + __attribute__((__aligned__(PAGE_SIZE))); + +-static char chsc_page[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE))); +- + static VDev vdev = { + .nr_vqs = 1, + .vrings = block, +@@ -94,14 +93,9 @@ static int run_ccw(VDev *vdev, int cmd, void *ptr, int len) + { + Ccw1 ccw = {}; + CmdOrb orb = {}; +- Schib schib; + int r; + +- /* start command processing */ +- stsch_err(vdev->schid, &schib); +- /* enable the subchannel for IPL device */ +- schib.pmcw.ena = 1; +- msch(vdev->schid, &schib); ++ enable_subchannel(vdev->schid); + + /* start subchannel command */ + orb.fmt = 1; +@@ -343,20 +337,3 @@ bool virtio_is_supported(SubChannelId schid) + } + return false; + } +- +-int enable_mss_facility(void) +-{ +- int ret; +- ChscAreaSda *sda_area = (ChscAreaSda *) chsc_page; +- +- memset(sda_area, 0, PAGE_SIZE); +- sda_area->request.length = 0x0400; +- sda_area->request.code = 0x0031; +- sda_area->operation_code = 0x2; +- +- ret = chsc(sda_area); +- if ((ret == 0) && (sda_area->response.code == 0x0001)) { +- return 0; +- } +- return -EIO; +-} +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390-bios-Extend-find_dev-for-non-virtio-devices.patch b/SOURCES/kvm-s390-bios-Extend-find_dev-for-non-virtio-devices.patch new file mode 100644 index 0000000..eb8c504 --- /dev/null +++ b/SOURCES/kvm-s390-bios-Extend-find_dev-for-non-virtio-devices.patch @@ -0,0 +1,72 @@ +From edf2dd4c4eda49957b845ea90a084dde0951f92a Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Mon, 14 Oct 2019 10:06:39 +0100 +Subject: [PATCH 14/21] s390-bios: Extend find_dev() for non-virtio devices + +RH-Author: Thomas Huth +Message-id: <20191014100645.22862-12-thuth@redhat.com> +Patchwork-id: 91784 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH v2 11/17] s390-bios: Extend find_dev() for non-virtio devices +Bugzilla: 1664376 +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand +RH-Acked-by: Jens Freimann + +From: "Jason J. Herne" + +We need a method for finding the subchannel of a dasd device. Let's +modify find_dev to handle this since it mostly does what we need. Up to +this point find_dev has been specific to only virtio devices. + +Signed-off-by: Jason J. Herne +Acked-by: Halil Pasic +Reviewed-by: Cornelia Huck +Message-Id: <1554388475-18329-11-git-send-email-jjherne@linux.ibm.com> +Signed-off-by: Thomas Huth +(cherry picked from commit 930072d2bf30986e57dac5c5945a32492f288944) +Signed-off-by: Danilo C. L. de Paula +--- + pc-bios/s390-ccw/main.c | 16 +++++++++++----- + 1 file changed, 11 insertions(+), 5 deletions(-) + +diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c +index e403b5f..d04ea89 100644 +--- a/pc-bios/s390-ccw/main.c ++++ b/pc-bios/s390-ccw/main.c +@@ -52,6 +52,12 @@ unsigned int get_loadparm_index(void) + return atoui(loadparm_str); + } + ++/* ++ * Find the subchannel connected to the given device (dev_no) and fill in the ++ * subchannel information block (schib) with the connected subchannel's info. ++ * NOTE: The global variable blk_schid is updated to contain the subchannel ++ * information. ++ */ + static bool find_dev(Schib *schib, int dev_no) + { + int i, r; +@@ -65,15 +71,15 @@ static bool find_dev(Schib *schib, int dev_no) + if (!schib->pmcw.dnv) { + continue; + } +- if (!virtio_is_supported(blk_schid)) { +- continue; +- } ++ + /* Skip net devices since no IPLB is created and therefore no +- * no network bootloader has been loaded ++ * network bootloader has been loaded + */ +- if (virtio_get_device_type() == VIRTIO_ID_NET && dev_no < 0) { ++ if (virtio_is_supported(blk_schid) && ++ virtio_get_device_type() == VIRTIO_ID_NET && dev_no < 0) { + continue; + } ++ + if ((dev_no < 0) || (schib->pmcw.dev == dev_no)) { + return true; + } +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390-bios-Factor-finding-boot-device-out-of-virtio-c.patch b/SOURCES/kvm-s390-bios-Factor-finding-boot-device-out-of-virtio-c.patch new file mode 100644 index 0000000..3d82337 --- /dev/null +++ b/SOURCES/kvm-s390-bios-Factor-finding-boot-device-out-of-virtio-c.patch @@ -0,0 +1,201 @@ +From e9b154b1297ac5aff8737dde61b6793fcd7c0a69 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Mon, 14 Oct 2019 10:06:40 +0100 +Subject: [PATCH 15/21] s390-bios: Factor finding boot device out of virtio + code path + +RH-Author: Thomas Huth +Message-id: <20191014100645.22862-13-thuth@redhat.com> +Patchwork-id: 91789 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH v2 12/17] s390-bios: Factor finding boot device out of virtio code path +Bugzilla: 1664376 +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand +RH-Acked-by: Jens Freimann + +From: "Jason J. Herne" + +Make a new routine find_boot_device to locate the boot device for all +cases, not just virtio. + +The error message for the case where no boot device has been specified +and a suitable boot device cannot be auto detected was specific to +virtio devices. We update this message to remove virtio specific wording. + +Signed-off-by: Jason J. Herne +Reviewed-by: Farhan Ali +Reviewed-by: Cornelia Huck +Message-Id: <1554388475-18329-12-git-send-email-jjherne@linux.ibm.com> +Signed-off-by: Thomas Huth +(cherry picked from commit 7b361db37b18a75860decc0a85e0194936401d66) +Signed-off-by: Danilo C. L. de Paula + +Conflicts: + tests/boot-serial-test.c + (we're missing commit 052888f043ba in downstream) +Signed-off-by: Thomas Huth + +Signed-off-by: Danilo C. L. de Paula +--- + pc-bios/s390-ccw/main.c | 85 ++++++++++++++++++++++++++---------------------- + tests/boot-serial-test.c | 2 +- + 2 files changed, 47 insertions(+), 40 deletions(-) + +diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c +index d04ea89..d3a161c 100644 +--- a/pc-bios/s390-ccw/main.c ++++ b/pc-bios/s390-ccw/main.c +@@ -58,17 +58,18 @@ unsigned int get_loadparm_index(void) + * NOTE: The global variable blk_schid is updated to contain the subchannel + * information. + */ +-static bool find_dev(Schib *schib, int dev_no) ++static bool find_subch(int dev_no) + { ++ Schib schib; + int i, r; + + for (i = 0; i < 0x10000; i++) { + blk_schid.sch_no = i; +- r = stsch_err(blk_schid, schib); ++ r = stsch_err(blk_schid, &schib); + if ((r == 3) || (r == -EIO)) { + break; + } +- if (!schib->pmcw.dnv) { ++ if (!schib.pmcw.dnv) { + continue; + } + +@@ -80,7 +81,7 @@ static bool find_dev(Schib *schib, int dev_no) + continue; + } + +- if ((dev_no < 0) || (schib->pmcw.dev == dev_no)) { ++ if ((dev_no < 0) || (schib.pmcw.dev == dev_no)) { + return true; + } + } +@@ -136,56 +137,61 @@ static void boot_setup(void) + have_iplb = store_iplb(&iplb); + } + +-static void virtio_setup(void) ++static void find_boot_device(void) + { +- Schib schib; +- int ssid; +- bool found = false; +- uint16_t dev_no; + VDev *vdev = virtio_get_device(); +- QemuIplParameters *early_qipl = (QemuIplParameters *)QIPL_ADDRESS; +- +- memcpy(&qipl, early_qipl, sizeof(QemuIplParameters)); ++ int ssid; ++ bool found; + +- if (have_iplb) { +- switch (iplb.pbt) { +- case S390_IPL_TYPE_CCW: +- dev_no = iplb.ccw.devno; +- debug_print_int("device no. ", dev_no); +- blk_schid.ssid = iplb.ccw.ssid & 0x3; +- debug_print_int("ssid ", blk_schid.ssid); +- found = find_dev(&schib, dev_no); +- break; +- case S390_IPL_TYPE_QEMU_SCSI: +- vdev->scsi_device_selected = true; +- vdev->selected_scsi_device.channel = iplb.scsi.channel; +- vdev->selected_scsi_device.target = iplb.scsi.target; +- vdev->selected_scsi_device.lun = iplb.scsi.lun; +- blk_schid.ssid = iplb.scsi.ssid & 0x3; +- found = find_dev(&schib, iplb.scsi.devno); +- break; +- default: +- panic("List-directed IPL not supported yet!\n"); +- } +- menu_setup(); +- } else { ++ if (!have_iplb) { + for (ssid = 0; ssid < 0x3; ssid++) { + blk_schid.ssid = ssid; +- found = find_dev(&schib, -1); ++ found = find_subch(-1); + if (found) { +- break; ++ return; + } + } ++ panic("Could not find a suitable boot device (none specified)\n"); ++ } ++ ++ switch (iplb.pbt) { ++ case S390_IPL_TYPE_CCW: ++ debug_print_int("device no. ", iplb.ccw.devno); ++ blk_schid.ssid = iplb.ccw.ssid & 0x3; ++ debug_print_int("ssid ", blk_schid.ssid); ++ found = find_subch(iplb.ccw.devno); ++ break; ++ case S390_IPL_TYPE_QEMU_SCSI: ++ vdev->scsi_device_selected = true; ++ vdev->selected_scsi_device.channel = iplb.scsi.channel; ++ vdev->selected_scsi_device.target = iplb.scsi.target; ++ vdev->selected_scsi_device.lun = iplb.scsi.lun; ++ blk_schid.ssid = iplb.scsi.ssid & 0x3; ++ found = find_subch(iplb.scsi.devno); ++ break; ++ default: ++ panic("List-directed IPL not supported yet!\n"); + } + +- IPL_assert(found, "No virtio device found"); ++ IPL_assert(found, "Boot device not found\n"); ++} ++ ++static void virtio_setup(void) ++{ ++ VDev *vdev = virtio_get_device(); ++ QemuIplParameters *early_qipl = (QemuIplParameters *)QIPL_ADDRESS; ++ ++ memcpy(&qipl, early_qipl, sizeof(QemuIplParameters)); ++ ++ if (have_iplb) { ++ menu_setup(); ++ } + + if (virtio_get_device_type() == VIRTIO_ID_NET) { + sclp_print("Network boot device detected\n"); + vdev->netboot_start_addr = qipl.netboot_start_addr; + } else { + virtio_blk_setup_device(blk_schid); +- + IPL_assert(virtio_ipl_disk_is_valid(), "No valid IPL device detected"); + } + } +@@ -195,8 +201,9 @@ int main(void) + sclp_setup(); + css_setup(); + boot_setup(); +- virtio_setup(); ++ find_boot_device(); + ++ virtio_setup(); + zipl_load(); /* no return */ + + panic("Failed to load OS from hard disk\n"); +diff --git a/tests/boot-serial-test.c b/tests/boot-serial-test.c +index dc682c1..fe52668 100644 +--- a/tests/boot-serial-test.c ++++ b/tests/boot-serial-test.c +@@ -97,7 +97,7 @@ static testdef_t tests[] = { + { "sparc", "SS-600MP", "", "TMS390Z55" }, + { "sparc64", "sun4u", "", "UltraSPARC" }, + { "s390x", "s390-ccw-virtio", +- "-nodefaults -device sclpconsole,chardev=serial0", "virtio device" }, ++ "-nodefaults -device sclpconsole,chardev=serial0", "device" }, + { "m68k", "mcf5208evb", "", "TT", sizeof(kernel_mcf5208), kernel_mcf5208 }, + { "microblaze", "petalogix-s3adsp1800", "", "TT", + sizeof(kernel_pls3adsp1800), kernel_pls3adsp1800 }, +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390-bios-Map-low-core-memory.patch b/SOURCES/kvm-s390-bios-Map-low-core-memory.patch new file mode 100644 index 0000000..51cf633 --- /dev/null +++ b/SOURCES/kvm-s390-bios-Map-low-core-memory.patch @@ -0,0 +1,152 @@ +From 256d99ee0acedd9ca8f21c9ebec83eee5e905c9d Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Mon, 14 Oct 2019 10:06:35 +0100 +Subject: [PATCH 10/21] s390-bios: Map low core memory + +RH-Author: Thomas Huth +Message-id: <20191014100645.22862-8-thuth@redhat.com> +Patchwork-id: 91786 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH v2 07/17] s390-bios: Map low core memory +Bugzilla: 1664376 +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand +RH-Acked-by: Jens Freimann + +From: "Jason J. Herne" + +Create a new header for basic architecture specific definitions and add a +mapping of low core memory. This mapping will be used by the real dasd boot +process. + +Signed-off-by: Jason J. Herne +Acked-by: Cornelia Huck +Reviewed-by: Thomas Huth +Message-Id: <1554388475-18329-7-git-send-email-jjherne@linux.ibm.com> +Signed-off-by: Thomas Huth +(cherry picked from commit c95df3d108028ff5a709ee3aefdb14401b07cb39) +Signed-off-by: Danilo C. L. de Paula +--- + pc-bios/s390-ccw/main.c | 2 + + pc-bios/s390-ccw/s390-arch.h | 90 ++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 92 insertions(+) + create mode 100644 pc-bios/s390-ccw/s390-arch.h + +diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c +index 10f04c6..e403b5f 100644 +--- a/pc-bios/s390-ccw/main.c ++++ b/pc-bios/s390-ccw/main.c +@@ -9,6 +9,7 @@ + */ + + #include "libc.h" ++#include "s390-arch.h" + #include "s390-ccw.h" + #include "cio.h" + #include "virtio.h" +@@ -19,6 +20,7 @@ static char loadparm_str[LOADPARM_LEN + 1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + QemuIplParameters qipl; + IplParameterBlock iplb __attribute__((__aligned__(PAGE_SIZE))); + static bool have_iplb; ++LowCore const *lowcore; /* Yes, this *is* a pointer to address 0 */ + + #define LOADPARM_PROMPT "PROMPT " + #define LOADPARM_EMPTY " " +diff --git a/pc-bios/s390-ccw/s390-arch.h b/pc-bios/s390-ccw/s390-arch.h +new file mode 100644 +index 0000000..5e92c7a +--- /dev/null ++++ b/pc-bios/s390-ccw/s390-arch.h +@@ -0,0 +1,90 @@ ++/* ++ * S390 Basic Architecture ++ * ++ * Copyright (c) 2019 Jason J. Herne ++ * ++ * This work is licensed under the terms of the GNU GPL, version 2 or (at ++ * your option) any later version. See the COPYING file in the top-level ++ * directory. ++ */ ++ ++#ifndef S390_ARCH_H ++#define S390_ARCH_H ++ ++typedef struct PSW { ++ uint64_t mask; ++ uint64_t addr; ++} __attribute__ ((aligned(8))) PSW; ++_Static_assert(sizeof(struct PSW) == 16, "PSW size incorrect"); ++ ++/* Older PSW format used by LPSW instruction */ ++typedef struct PSWLegacy { ++ uint32_t mask; ++ uint32_t addr; ++} __attribute__ ((aligned(8))) PSWLegacy; ++_Static_assert(sizeof(struct PSWLegacy) == 8, "PSWLegacy size incorrect"); ++ ++/* s390 psw bit masks */ ++#define PSW_MASK_IOINT 0x0200000000000000ULL ++#define PSW_MASK_WAIT 0x0002000000000000ULL ++#define PSW_MASK_EAMODE 0x0000000100000000ULL ++#define PSW_MASK_BAMODE 0x0000000080000000ULL ++#define PSW_MASK_ZMODE (PSW_MASK_EAMODE | PSW_MASK_BAMODE) ++ ++/* Low core mapping */ ++typedef struct LowCore { ++ /* prefix area: defined by architecture */ ++ PSWLegacy ipl_psw; /* 0x000 */ ++ uint32_t ccw1[2]; /* 0x008 */ ++ uint32_t ccw2[2]; /* 0x010 */ ++ uint8_t pad1[0x80 - 0x18]; /* 0x018 */ ++ uint32_t ext_params; /* 0x080 */ ++ uint16_t cpu_addr; /* 0x084 */ ++ uint16_t ext_int_code; /* 0x086 */ ++ uint16_t svc_ilen; /* 0x088 */ ++ uint16_t svc_code; /* 0x08a */ ++ uint16_t pgm_ilen; /* 0x08c */ ++ uint16_t pgm_code; /* 0x08e */ ++ uint32_t data_exc_code; /* 0x090 */ ++ uint16_t mon_class_num; /* 0x094 */ ++ uint16_t per_perc_atmid; /* 0x096 */ ++ uint64_t per_address; /* 0x098 */ ++ uint8_t exc_access_id; /* 0x0a0 */ ++ uint8_t per_access_id; /* 0x0a1 */ ++ uint8_t op_access_id; /* 0x0a2 */ ++ uint8_t ar_access_id; /* 0x0a3 */ ++ uint8_t pad2[0xA8 - 0xA4]; /* 0x0a4 */ ++ uint64_t trans_exc_code; /* 0x0a8 */ ++ uint64_t monitor_code; /* 0x0b0 */ ++ uint16_t subchannel_id; /* 0x0b8 */ ++ uint16_t subchannel_nr; /* 0x0ba */ ++ uint32_t io_int_parm; /* 0x0bc */ ++ uint32_t io_int_word; /* 0x0c0 */ ++ uint8_t pad3[0xc8 - 0xc4]; /* 0x0c4 */ ++ uint32_t stfl_fac_list; /* 0x0c8 */ ++ uint8_t pad4[0xe8 - 0xcc]; /* 0x0cc */ ++ uint64_t mcic; /* 0x0e8 */ ++ uint8_t pad5[0xf4 - 0xf0]; /* 0x0f0 */ ++ uint32_t external_damage_code; /* 0x0f4 */ ++ uint64_t failing_storage_address; /* 0x0f8 */ ++ uint8_t pad6[0x110 - 0x100]; /* 0x100 */ ++ uint64_t per_breaking_event_addr; /* 0x110 */ ++ uint8_t pad7[0x120 - 0x118]; /* 0x118 */ ++ PSW restart_old_psw; /* 0x120 */ ++ PSW external_old_psw; /* 0x130 */ ++ PSW svc_old_psw; /* 0x140 */ ++ PSW program_old_psw; /* 0x150 */ ++ PSW mcck_old_psw; /* 0x160 */ ++ PSW io_old_psw; /* 0x170 */ ++ uint8_t pad8[0x1a0 - 0x180]; /* 0x180 */ ++ PSW restart_new_psw; /* 0x1a0 */ ++ PSW external_new_psw; /* 0x1b0 */ ++ PSW svc_new_psw; /* 0x1c0 */ ++ PSW program_new_psw; /* 0x1d0 */ ++ PSW mcck_new_psw; /* 0x1e0 */ ++ PSW io_new_psw; /* 0x1f0 */ ++} __attribute__((packed, aligned(8192))) LowCore; ++ ++extern LowCore const *lowcore; ++ ++#endif +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390-bios-Refactor-virtio-to-run-channel-programs-vi.patch b/SOURCES/kvm-s390-bios-Refactor-virtio-to-run-channel-programs-vi.patch new file mode 100644 index 0000000..ba8e222 --- /dev/null +++ b/SOURCES/kvm-s390-bios-Refactor-virtio-to-run-channel-programs-vi.patch @@ -0,0 +1,159 @@ +From 776fe22777dd348073449622797cfd9d12058f38 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Mon, 14 Oct 2019 10:06:41 +0100 +Subject: [PATCH 16/21] s390-bios: Refactor virtio to run channel programs via + cio + +RH-Author: Thomas Huth +Message-id: <20191014100645.22862-14-thuth@redhat.com> +Patchwork-id: 91793 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH v2 13/17] s390-bios: Refactor virtio to run channel programs via cio +Bugzilla: 1664376 +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand +RH-Acked-by: Jens Freimann + +From: "Jason J. Herne" + +Now that we have a Channel I/O library let's modify virtio boot code to +make use of it for running channel programs. + +Signed-off-by: Jason J. Herne +Reviewed-by: Cornelia Huck +Acked-by: Thomas Huth +Message-Id: <1554388475-18329-13-git-send-email-jjherne@linux.ibm.com> +Signed-off-by: Thomas Huth +(cherry picked from commit 9de6cbb152bee3917e58ad00633eddafb40d6678) +Signed-off-by: Danilo C. L. de Paula +--- + pc-bios/s390-ccw/virtio.c | 57 ++++++++++++++++++++++------------------------- + 1 file changed, 27 insertions(+), 30 deletions(-) + +diff --git a/pc-bios/s390-ccw/virtio.c b/pc-bios/s390-ccw/virtio.c +index aa9da72..35278eae 100644 +--- a/pc-bios/s390-ccw/virtio.c ++++ b/pc-bios/s390-ccw/virtio.c +@@ -14,6 +14,7 @@ + #include "virtio.h" + #include "virtio-scsi.h" + #include "bswap.h" ++#include "helper.h" + + #define VRING_WAIT_REPLY_TIMEOUT 30 + +@@ -89,33 +90,20 @@ int drain_irqs(SubChannelId schid) + } + } + +-static int run_ccw(VDev *vdev, int cmd, void *ptr, int len) ++static int run_ccw(VDev *vdev, int cmd, void *ptr, int len, bool sli) + { + Ccw1 ccw = {}; +- CmdOrb orb = {}; +- int r; +- +- enable_subchannel(vdev->schid); +- +- /* start subchannel command */ +- orb.fmt = 1; +- orb.cpa = (u32)(long)&ccw; +- orb.lpm = 0x80; + + ccw.cmd_code = cmd; + ccw.cda = (long)ptr; + ccw.count = len; + +- r = ssch(vdev->schid, &orb); +- /* +- * XXX Wait until device is done processing the CCW. For now we can +- * assume that a simple tsch will have finished the CCW processing, +- * but the architecture allows for asynchronous operation +- */ +- if (!r) { +- r = drain_irqs(vdev->schid); ++ if (sli) { ++ ccw.flags |= CCW_FLAG_SLI; + } +- return r; ++ ++ enable_subchannel(vdev->schid); ++ return do_cio(vdev->schid, vdev->senseid.cu_type, ptr2u32(&ccw), CCW_FMT1); + } + + static void vring_init(VRing *vr, VqInfo *info) +@@ -257,7 +245,7 @@ void virtio_setup_ccw(VDev *vdev) + vdev->config.blk.blk_size = 0; /* mark "illegal" - setup started... */ + vdev->guessed_disk_nature = VIRTIO_GDN_NONE; + +- run_ccw(vdev, CCW_CMD_VDEV_RESET, NULL, 0); ++ run_ccw(vdev, CCW_CMD_VDEV_RESET, NULL, 0, false); + + switch (vdev->senseid.cu_model) { + case VIRTIO_ID_NET: +@@ -278,18 +266,19 @@ void virtio_setup_ccw(VDev *vdev) + default: + panic("Unsupported virtio device\n"); + } +- IPL_assert(run_ccw(vdev, CCW_CMD_READ_CONF, &vdev->config, cfg_size) == 0, +- "Could not get block device configuration"); ++ IPL_assert( ++ run_ccw(vdev, CCW_CMD_READ_CONF, &vdev->config, cfg_size, false) == 0, ++ "Could not get block device configuration"); + + /* Feature negotiation */ + for (i = 0; i < ARRAY_SIZE(vdev->guest_features); i++) { + feats.features = 0; + feats.index = i; +- rc = run_ccw(vdev, CCW_CMD_READ_FEAT, &feats, sizeof(feats)); ++ rc = run_ccw(vdev, CCW_CMD_READ_FEAT, &feats, sizeof(feats), false); + IPL_assert(rc == 0, "Could not get features bits"); + vdev->guest_features[i] &= bswap32(feats.features); + feats.features = bswap32(vdev->guest_features[i]); +- rc = run_ccw(vdev, CCW_CMD_WRITE_FEAT, &feats, sizeof(feats)); ++ rc = run_ccw(vdev, CCW_CMD_WRITE_FEAT, &feats, sizeof(feats), false); + IPL_assert(rc == 0, "Could not set features bits"); + } + +@@ -306,16 +295,17 @@ void virtio_setup_ccw(VDev *vdev) + }; + + IPL_assert( +- run_ccw(vdev, CCW_CMD_READ_VQ_CONF, &config, sizeof(config)) == 0, ++ run_ccw(vdev, CCW_CMD_READ_VQ_CONF, &config, sizeof(config), false) == 0, + "Could not get block device VQ configuration"); + info.num = config.num; + vring_init(&vdev->vrings[i], &info); + vdev->vrings[i].schid = vdev->schid; +- IPL_assert(run_ccw(vdev, CCW_CMD_SET_VQ, &info, sizeof(info)) == 0, +- "Cannot set VQ info"); ++ IPL_assert( ++ run_ccw(vdev, CCW_CMD_SET_VQ, &info, sizeof(info), false) == 0, ++ "Cannot set VQ info"); + } + IPL_assert( +- run_ccw(vdev, CCW_CMD_WRITE_STATUS, &status, sizeof(status)) == 0, ++ run_ccw(vdev, CCW_CMD_WRITE_STATUS, &status, sizeof(status), false) == 0, + "Could not write status to host"); + } + +@@ -323,8 +313,15 @@ bool virtio_is_supported(SubChannelId schid) + { + vdev.schid = schid; + memset(&vdev.senseid, 0, sizeof(vdev.senseid)); +- /* run sense id command */ +- if (run_ccw(&vdev, CCW_CMD_SENSE_ID, &vdev.senseid, sizeof(vdev.senseid))) { ++ ++ /* ++ * Run sense id command. ++ * The size of the senseid data differs between devices (notably, ++ * between virtio devices and dasds), so specify the largest possible ++ * size and suppress the incorrect length indication for smaller sizes. ++ */ ++ if (run_ccw(&vdev, CCW_CMD_SENSE_ID, &vdev.senseid, sizeof(vdev.senseid), ++ true)) { + return false; + } + if (vdev.senseid.cu_type == 0x3832) { +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390-bios-Support-booting-from-real-dasd-device.patch b/SOURCES/kvm-s390-bios-Support-booting-from-real-dasd-device.patch new file mode 100644 index 0000000..86522dc --- /dev/null +++ b/SOURCES/kvm-s390-bios-Support-booting-from-real-dasd-device.patch @@ -0,0 +1,520 @@ +From 2267eadd85126ea711cc8314c7df45a70486651c Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Mon, 14 Oct 2019 10:06:44 +0100 +Subject: [PATCH 19/21] s390-bios: Support booting from real dasd device + +RH-Author: Thomas Huth +Message-id: <20191014100645.22862-17-thuth@redhat.com> +Patchwork-id: 91791 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH v2 16/17] s390-bios: Support booting from real dasd device +Bugzilla: 1664376 +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand +RH-Acked-by: Jens Freimann + +From: "Jason J. Herne" + +Allows guest to boot from a vfio configured real dasd device. + +Signed-off-by: Jason J. Herne +Reviewed-by: Cornelia Huck +Message-Id: <1554388475-18329-16-git-send-email-jjherne@linux.ibm.com> +Signed-off-by: Thomas Huth +(cherry picked from commit efa47d36da89f4b23c315a7cc085fab0d15eb47c) +Signed-off-by: Danilo C. L. de Paula + +Conflicts: + MAINTAINERS + (simple contextual conflict due to missing downstream commits) + +Signed-off-by: Danilo C. L. de Paula +--- + MAINTAINERS | 3 +- + docs/devel/s390-dasd-ipl.txt | 133 ++++++++++++++++++++++++ + pc-bios/s390-ccw/Makefile | 2 +- + pc-bios/s390-ccw/dasd-ipl.c | 235 +++++++++++++++++++++++++++++++++++++++++++ + pc-bios/s390-ccw/dasd-ipl.h | 16 +++ + pc-bios/s390-ccw/main.c | 5 + + pc-bios/s390-ccw/s390-arch.h | 13 +++ + 7 files changed, 405 insertions(+), 2 deletions(-) + create mode 100644 docs/devel/s390-dasd-ipl.txt + create mode 100644 pc-bios/s390-ccw/dasd-ipl.c + create mode 100644 pc-bios/s390-ccw/dasd-ipl.h + +diff --git a/MAINTAINERS b/MAINTAINERS +index 9b74756..770885a 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -896,7 +896,8 @@ M: Thomas Huth + S: Supported + F: pc-bios/s390-ccw/ + F: pc-bios/s390-ccw.img +-T: git git://github.com/borntraeger/qemu.git s390-next ++F: docs/devel/s390-dasd-ipl.txt ++T: git https://github.com/borntraeger/qemu.git s390-next + L: qemu-s390x@nongnu.org + + UniCore32 Machines +diff --git a/docs/devel/s390-dasd-ipl.txt b/docs/devel/s390-dasd-ipl.txt +new file mode 100644 +index 0000000..9107e04 +--- /dev/null ++++ b/docs/devel/s390-dasd-ipl.txt +@@ -0,0 +1,133 @@ ++***************************** ++***** s390 hardware IPL ***** ++***************************** ++ ++The s390 hardware IPL process consists of the following steps. ++ ++1. A READ IPL ccw is constructed in memory location 0x0. ++ This ccw, by definition, reads the IPL1 record which is located on the disk ++ at cylinder 0 track 0 record 1. Note that the chain flag is on in this ccw ++ so when it is complete another ccw will be fetched and executed from memory ++ location 0x08. ++ ++2. Execute the Read IPL ccw at 0x00, thereby reading IPL1 data into 0x00. ++ IPL1 data is 24 bytes in length and consists of the following pieces of ++ information: [psw][read ccw][tic ccw]. When the machine executes the Read ++ IPL ccw it read the 24-bytes of IPL1 to be read into memory starting at ++ location 0x0. Then the ccw program at 0x08 which consists of a read ++ ccw and a tic ccw is automatically executed because of the chain flag from ++ the original READ IPL ccw. The read ccw will read the IPL2 data into memory ++ and the TIC (Transfer In Channel) will transfer control to the channel ++ program contained in the IPL2 data. The TIC channel command is the ++ equivalent of a branch/jump/goto instruction for channel programs. ++ NOTE: The ccws in IPL1 are defined by the architecture to be format 0. ++ ++3. Execute IPL2. ++ The TIC ccw instruction at the end of the IPL1 channel program will begin ++ the execution of the IPL2 channel program. IPL2 is stage-2 of the boot ++ process and will contain a larger channel program than IPL1. The point of ++ IPL2 is to find and load either the operating system or a small program that ++ loads the operating system from disk. At the end of this step all or some of ++ the real operating system is loaded into memory and we are ready to hand ++ control over to the guest operating system. At this point the guest ++ operating system is entirely responsible for loading any more data it might ++ need to function. NOTE: The IPL2 channel program might read data into memory ++ location 0 thereby overwriting the IPL1 psw and channel program. This is ok ++ as long as the data placed in location 0 contains a psw whose instruction ++ address points to the guest operating system code to execute at the end of ++ the IPL/boot process. ++ NOTE: The ccws in IPL2 are defined by the architecture to be format 0. ++ ++4. Start executing the guest operating system. ++ The psw that was loaded into memory location 0 as part of the ipl process ++ should contain the needed flags for the operating system we have loaded. The ++ psw's instruction address will point to the location in memory where we want ++ to start executing the operating system. This psw is loaded (via LPSW ++ instruction) causing control to be passed to the operating system code. ++ ++In a non-virtualized environment this process, handled entirely by the hardware, ++is kicked off by the user initiating a "Load" procedure from the hardware ++management console. This "Load" procedure crafts a special "Read IPL" ccw in ++memory location 0x0 that reads IPL1. It then executes this ccw thereby kicking ++off the reading of IPL1 data. Since the channel program from IPL1 will be ++written immediately after the special "Read IPL" ccw, the IPL1 channel program ++will be executed immediately (the special read ccw has the chaining bit turned ++on). The TIC at the end of the IPL1 channel program will cause the IPL2 channel ++program to be executed automatically. After this sequence completes the "Load" ++procedure then loads the psw from 0x0. ++ ++********************************************************** ++***** How this all pertains to QEMU (and the kernel) ***** ++********************************************************** ++ ++In theory we should merely have to do the following to IPL/boot a guest ++operating system from a DASD device: ++ ++1. Place a "Read IPL" ccw into memory location 0x0 with chaining bit on. ++2. Execute channel program at 0x0. ++3. LPSW 0x0. ++ ++However, our emulation of the machine's channel program logic within the kernel ++is missing one key feature that is required for this process to work: ++non-prefetch of ccw data. ++ ++When we start a channel program we pass the channel subsystem parameters via an ++ORB (Operation Request Block). One of those parameters is a prefetch bit. If the ++bit is on then the vfio-ccw kernel driver is allowed to read the entire channel ++program from guest memory before it starts executing it. This means that any ++channel commands that read additional channel commands will not work as expected ++because the newly read commands will only exist in guest memory and NOT within ++the kernel's channel subsystem memory. The kernel vfio-ccw driver currently ++requires this bit to be on for all channel programs. This is a problem because ++the IPL process consists of transferring control from the "Read IPL" ccw ++immediately to the IPL1 channel program that was read by "Read IPL". ++ ++Not being able to turn off prefetch will also prevent the TIC at the end of the ++IPL1 channel program from transferring control to the IPL2 channel program. ++ ++Lastly, in some cases (the zipl bootloader for example) the IPL2 program also ++transfers control to another channel program segment immediately after reading ++it from the disk. So we need to be able to handle this case. ++ ++************************** ++***** What QEMU does ***** ++************************** ++ ++Since we are forced to live with prefetch we cannot use the very simple IPL ++procedure we defined in the preceding section. So we compensate by doing the ++following. ++ ++1. Place "Read IPL" ccw into memory location 0x0, but turn off chaining bit. ++2. Execute "Read IPL" at 0x0. ++ ++ So now IPL1's psw is at 0x0 and IPL1's channel program is at 0x08. ++ ++4. Write a custom channel program that will seek to the IPL2 record and then ++ execute the READ and TIC ccws from IPL1. Normally the seek is not required ++ because after reading the IPL1 record the disk is automatically positioned ++ to read the very next record which will be IPL2. But since we are not reading ++ both IPL1 and IPL2 as part of the same channel program we must manually set ++ the position. ++ ++5. Grab the target address of the TIC instruction from the IPL1 channel program. ++ This address is where the IPL2 channel program starts. ++ ++ Now IPL2 is loaded into memory somewhere, and we know the address. ++ ++6. Execute the IPL2 channel program at the address obtained in step #5. ++ ++ Because this channel program can be dynamic, we must use a special algorithm ++ that detects a READ immediately followed by a TIC and breaks the ccw chain ++ by turning off the chain bit in the READ ccw. When control is returned from ++ the kernel/hardware to the QEMU bios code we immediately issue another start ++ subchannel to execute the remaining TIC instruction. This causes the entire ++ channel program (starting from the TIC) and all needed data to be refetched ++ thereby stepping around the limitation that would otherwise prevent this ++ channel program from executing properly. ++ ++ Now the operating system code is loaded somewhere in guest memory and the psw ++ in memory location 0x0 will point to entry code for the guest operating ++ system. ++ ++7. LPSW 0x0. ++ LPSW transfers control to the guest operating system and we're done. +diff --git a/pc-bios/s390-ccw/Makefile b/pc-bios/s390-ccw/Makefile +index acca961..d6a6e18 100644 +--- a/pc-bios/s390-ccw/Makefile ++++ b/pc-bios/s390-ccw/Makefile +@@ -10,7 +10,7 @@ $(call set-vpath, $(SRC_PATH)/pc-bios/s390-ccw) + .PHONY : all clean build-all + + OBJECTS = start.o main.o bootmap.o jump2ipl.o sclp.o menu.o \ +- virtio.o virtio-scsi.o virtio-blkdev.o libc.o cio.o ++ virtio.o virtio-scsi.o virtio-blkdev.o libc.o cio.o dasd-ipl.o + + QEMU_CFLAGS := $(filter -W%, $(QEMU_CFLAGS)) + QEMU_CFLAGS += -ffreestanding -fno-delete-null-pointer-checks -msoft-float +diff --git a/pc-bios/s390-ccw/dasd-ipl.c b/pc-bios/s390-ccw/dasd-ipl.c +new file mode 100644 +index 0000000..0fc879b +--- /dev/null ++++ b/pc-bios/s390-ccw/dasd-ipl.c +@@ -0,0 +1,235 @@ ++/* ++ * S390 IPL (boot) from a real DASD device via vfio framework. ++ * ++ * Copyright (c) 2019 Jason J. Herne ++ * ++ * This work is licensed under the terms of the GNU GPL, version 2 or (at ++ * your option) any later version. See the COPYING file in the top-level ++ * directory. ++ */ ++ ++#include "libc.h" ++#include "s390-ccw.h" ++#include "s390-arch.h" ++#include "dasd-ipl.h" ++#include "helper.h" ++ ++static char prefix_page[PAGE_SIZE * 2] ++ __attribute__((__aligned__(PAGE_SIZE * 2))); ++ ++static void enable_prefixing(void) ++{ ++ memcpy(&prefix_page, lowcore, 4096); ++ set_prefix(ptr2u32(&prefix_page)); ++} ++ ++static void disable_prefixing(void) ++{ ++ set_prefix(0); ++ /* Copy io interrupt info back to low core */ ++ memcpy((void *)&lowcore->subchannel_id, prefix_page + 0xB8, 12); ++} ++ ++static bool is_read_tic_ccw_chain(Ccw0 *ccw) ++{ ++ Ccw0 *next_ccw = ccw + 1; ++ ++ return ((ccw->cmd_code == CCW_CMD_DASD_READ || ++ ccw->cmd_code == CCW_CMD_DASD_READ_MT) && ++ ccw->chain && next_ccw->cmd_code == CCW_CMD_TIC); ++} ++ ++static bool dynamic_cp_fixup(uint32_t ccw_addr, uint32_t *next_cpa) ++{ ++ Ccw0 *cur_ccw = (Ccw0 *)(uint64_t)ccw_addr; ++ Ccw0 *tic_ccw; ++ ++ while (true) { ++ /* Skip over inline TIC (it might not have the chain bit on) */ ++ if (cur_ccw->cmd_code == CCW_CMD_TIC && ++ cur_ccw->cda == ptr2u32(cur_ccw) - 8) { ++ cur_ccw += 1; ++ continue; ++ } ++ ++ if (!cur_ccw->chain) { ++ break; ++ } ++ if (is_read_tic_ccw_chain(cur_ccw)) { ++ /* ++ * Breaking a chain of CCWs may alter the semantics or even the ++ * validity of a channel program. The heuristic implemented below ++ * seems to work well in practice for the channel programs ++ * generated by zipl. ++ */ ++ tic_ccw = cur_ccw + 1; ++ *next_cpa = tic_ccw->cda; ++ cur_ccw->chain = 0; ++ return true; ++ } ++ cur_ccw += 1; ++ } ++ return false; ++} ++ ++static int run_dynamic_ccw_program(SubChannelId schid, uint16_t cutype, ++ uint32_t cpa) ++{ ++ bool has_next; ++ uint32_t next_cpa = 0; ++ int rc; ++ ++ do { ++ has_next = dynamic_cp_fixup(cpa, &next_cpa); ++ ++ print_int("executing ccw chain at ", cpa); ++ enable_prefixing(); ++ rc = do_cio(schid, cutype, cpa, CCW_FMT0); ++ disable_prefixing(); ++ ++ if (rc) { ++ break; ++ } ++ cpa = next_cpa; ++ } while (has_next); ++ ++ return rc; ++} ++ ++static void make_readipl(void) ++{ ++ Ccw0 *ccwIplRead = (Ccw0 *)0x00; ++ ++ /* Create Read IPL ccw at address 0 */ ++ ccwIplRead->cmd_code = CCW_CMD_READ_IPL; ++ ccwIplRead->cda = 0x00; /* Read into address 0x00 in main memory */ ++ ccwIplRead->chain = 0; /* Chain flag */ ++ ccwIplRead->count = 0x18; /* Read 0x18 bytes of data */ ++} ++ ++static void run_readipl(SubChannelId schid, uint16_t cutype) ++{ ++ if (do_cio(schid, cutype, 0x00, CCW_FMT0)) { ++ panic("dasd-ipl: Failed to run Read IPL channel program\n"); ++ } ++} ++ ++/* ++ * The architecture states that IPL1 data should consist of a psw followed by ++ * format-0 READ and TIC CCWs. Let's sanity check. ++ */ ++static void check_ipl1(void) ++{ ++ Ccw0 *ccwread = (Ccw0 *)0x08; ++ Ccw0 *ccwtic = (Ccw0 *)0x10; ++ ++ if (ccwread->cmd_code != CCW_CMD_DASD_READ || ++ ccwtic->cmd_code != CCW_CMD_TIC) { ++ panic("dasd-ipl: IPL1 data invalid. Is this disk really bootable?\n"); ++ } ++} ++ ++static void check_ipl2(uint32_t ipl2_addr) ++{ ++ Ccw0 *ccw = u32toptr(ipl2_addr); ++ ++ if (ipl2_addr == 0x00) { ++ panic("IPL2 address invalid. Is this disk really bootable?\n"); ++ } ++ if (ccw->cmd_code == 0x00) { ++ panic("IPL2 ccw data invalid. Is this disk really bootable?\n"); ++ } ++} ++ ++static uint32_t read_ipl2_addr(void) ++{ ++ Ccw0 *ccwtic = (Ccw0 *)0x10; ++ ++ return ccwtic->cda; ++} ++ ++static void ipl1_fixup(void) ++{ ++ Ccw0 *ccwSeek = (Ccw0 *) 0x08; ++ Ccw0 *ccwSearchID = (Ccw0 *) 0x10; ++ Ccw0 *ccwSearchTic = (Ccw0 *) 0x18; ++ Ccw0 *ccwRead = (Ccw0 *) 0x20; ++ CcwSeekData *seekData = (CcwSeekData *) 0x30; ++ CcwSearchIdData *searchData = (CcwSearchIdData *) 0x38; ++ ++ /* move IPL1 CCWs to make room for CCWs needed to locate record 2 */ ++ memcpy(ccwRead, (void *)0x08, 16); ++ ++ /* Disable chaining so we don't TIC to IPL2 channel program */ ++ ccwRead->chain = 0x00; ++ ++ ccwSeek->cmd_code = CCW_CMD_DASD_SEEK; ++ ccwSeek->cda = ptr2u32(seekData); ++ ccwSeek->chain = 1; ++ ccwSeek->count = sizeof(*seekData); ++ seekData->reserved = 0x00; ++ seekData->cyl = 0x00; ++ seekData->head = 0x00; ++ ++ ccwSearchID->cmd_code = CCW_CMD_DASD_SEARCH_ID_EQ; ++ ccwSearchID->cda = ptr2u32(searchData); ++ ccwSearchID->chain = 1; ++ ccwSearchID->count = sizeof(*searchData); ++ searchData->cyl = 0; ++ searchData->head = 0; ++ searchData->record = 2; ++ ++ /* Go back to Search CCW if correct record not yet found */ ++ ccwSearchTic->cmd_code = CCW_CMD_TIC; ++ ccwSearchTic->cda = ptr2u32(ccwSearchID); ++} ++ ++static void run_ipl1(SubChannelId schid, uint16_t cutype) ++ { ++ uint32_t startAddr = 0x08; ++ ++ if (do_cio(schid, cutype, startAddr, CCW_FMT0)) { ++ panic("dasd-ipl: Failed to run IPL1 channel program\n"); ++ } ++} ++ ++static void run_ipl2(SubChannelId schid, uint16_t cutype, uint32_t addr) ++{ ++ if (run_dynamic_ccw_program(schid, cutype, addr)) { ++ panic("dasd-ipl: Failed to run IPL2 channel program\n"); ++ } ++} ++ ++/* ++ * Limitations in vfio-ccw support complicate the IPL process. Details can ++ * be found in docs/devel/s390-dasd-ipl.txt ++ */ ++void dasd_ipl(SubChannelId schid, uint16_t cutype) ++{ ++ PSWLegacy *pswl = (PSWLegacy *) 0x00; ++ uint32_t ipl2_addr; ++ ++ /* Construct Read IPL CCW and run it to read IPL1 from boot disk */ ++ make_readipl(); ++ run_readipl(schid, cutype); ++ ipl2_addr = read_ipl2_addr(); ++ check_ipl1(); ++ ++ /* ++ * Fixup IPL1 channel program to account for vfio-ccw limitations, then run ++ * it to read IPL2 channel program from boot disk. ++ */ ++ ipl1_fixup(); ++ run_ipl1(schid, cutype); ++ check_ipl2(ipl2_addr); ++ ++ /* ++ * Run IPL2 channel program to read operating system code from boot disk ++ */ ++ run_ipl2(schid, cutype, ipl2_addr); ++ ++ /* Transfer control to the guest operating system */ ++ pswl->mask |= PSW_MASK_EAMODE; /* Force z-mode */ ++ pswl->addr |= PSW_MASK_BAMODE; /* ... */ ++ jump_to_low_kernel(); ++} +diff --git a/pc-bios/s390-ccw/dasd-ipl.h b/pc-bios/s390-ccw/dasd-ipl.h +new file mode 100644 +index 0000000..c394828 +--- /dev/null ++++ b/pc-bios/s390-ccw/dasd-ipl.h +@@ -0,0 +1,16 @@ ++/* ++ * S390 IPL (boot) from a real DASD device via vfio framework. ++ * ++ * Copyright (c) 2019 Jason J. Herne ++ * ++ * This work is licensed under the terms of the GNU GPL, version 2 or (at ++ * your option) any later version. See the COPYING file in the top-level ++ * directory. ++ */ ++ ++#ifndef DASD_IPL_H ++#define DASD_IPL_H ++ ++void dasd_ipl(SubChannelId schid, uint16_t cutype); ++ ++#endif /* DASD_IPL_H */ +diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c +index 57a1013..3c449ad 100644 +--- a/pc-bios/s390-ccw/main.c ++++ b/pc-bios/s390-ccw/main.c +@@ -13,6 +13,7 @@ + #include "s390-ccw.h" + #include "cio.h" + #include "virtio.h" ++#include "dasd-ipl.h" + + char stack[PAGE_SIZE * 8] __attribute__((__aligned__(PAGE_SIZE))); + static SubChannelId blk_schid = { .one = 1 }; +@@ -209,6 +210,10 @@ int main(void) + + cutype = cu_type(blk_schid); + switch (cutype) { ++ case CU_TYPE_DASD_3990: ++ case CU_TYPE_DASD_2107: ++ dasd_ipl(blk_schid, cutype); /* no return */ ++ break; + case CU_TYPE_VIRTIO: + virtio_setup(); + zipl_load(); /* no return */ +diff --git a/pc-bios/s390-ccw/s390-arch.h b/pc-bios/s390-ccw/s390-arch.h +index 5e92c7a..504fc7c 100644 +--- a/pc-bios/s390-ccw/s390-arch.h ++++ b/pc-bios/s390-ccw/s390-arch.h +@@ -87,4 +87,17 @@ typedef struct LowCore { + + extern LowCore const *lowcore; + ++static inline void set_prefix(uint32_t address) ++{ ++ asm volatile("spx %0" : : "m" (address) : "memory"); ++} ++ ++static inline uint32_t store_prefix(void) ++{ ++ uint32_t address; ++ ++ asm volatile("stpx %0" : "=m" (address)); ++ return address; ++} ++ + #endif +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390-bios-Support-for-running-format-0-1-channel-pro.patch b/SOURCES/kvm-s390-bios-Support-for-running-format-0-1-channel-pro.patch new file mode 100644 index 0000000..eb6a65d --- /dev/null +++ b/SOURCES/kvm-s390-bios-Support-for-running-format-0-1-channel-pro.patch @@ -0,0 +1,445 @@ +From 363d844cccb965c9eb0e0e6b5ca100e9532a2f0a Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Mon, 14 Oct 2019 10:06:37 +0100 +Subject: [PATCH 12/21] s390-bios: Support for running format-0/1 channel + programs + +RH-Author: Thomas Huth +Message-id: <20191014100645.22862-10-thuth@redhat.com> +Patchwork-id: 91783 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH v2 09/17] s390-bios: Support for running format-0/1 channel programs +Bugzilla: 1664376 +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand +RH-Acked-by: Jens Freimann + +From: "Jason J. Herne" + +Introduce a library function for executing format-0 and format-1 +channel programs and waiting for their completion before continuing +execution. + +Add cu_type() to channel io library. This will be used to query control +unit type which is used to determine if we are booting a virtio device or a +real dasd device. + +Signed-off-by: Jason J. Herne +Reviewed-by: Cornelia Huck +Reviewed-by: Farhan Ali +Message-Id: <1554388475-18329-9-git-send-email-jjherne@linux.ibm.com> +Signed-off-by: Thomas Huth +(cherry picked from commit 3083a1bbb8716e9052fe375f68f330107ee13127) +Signed-off-by: Danilo C. L. de Paula +--- + pc-bios/s390-ccw/cio.c | 144 ++++++++++++++++++++++++++++++++++++++++++++ + pc-bios/s390-ccw/cio.h | 130 ++++++++++++++++++++++++++++++++++++++- + pc-bios/s390-ccw/s390-ccw.h | 1 + + pc-bios/s390-ccw/start.S | 29 +++++++++ + 4 files changed, 301 insertions(+), 3 deletions(-) + +diff --git a/pc-bios/s390-ccw/cio.c b/pc-bios/s390-ccw/cio.c +index 87c6b34..c43e50b 100644 +--- a/pc-bios/s390-ccw/cio.c ++++ b/pc-bios/s390-ccw/cio.c +@@ -13,10 +13,14 @@ + + #include "libc.h" + #include "s390-ccw.h" ++#include "s390-arch.h" ++#include "helper.h" + #include "cio.h" + + static char chsc_page[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE))); + ++static int __do_cio(SubChannelId schid, uint32_t ccw_addr, int fmt, Irb *irb); ++ + int enable_mss_facility(void) + { + int ret; +@@ -42,3 +46,143 @@ void enable_subchannel(SubChannelId schid) + schib.pmcw.ena = 1; + msch(schid, &schib); + } ++ ++uint16_t cu_type(SubChannelId schid) ++{ ++ Ccw1 sense_id_ccw; ++ SenseId sense_data; ++ ++ sense_id_ccw.cmd_code = CCW_CMD_SENSE_ID; ++ sense_id_ccw.cda = ptr2u32(&sense_data); ++ sense_id_ccw.count = sizeof(sense_data); ++ sense_id_ccw.flags |= CCW_FLAG_SLI; ++ ++ if (do_cio(schid, CU_TYPE_UNKNOWN, ptr2u32(&sense_id_ccw), CCW_FMT1)) { ++ panic("Failed to run SenseID CCw\n"); ++ } ++ ++ return sense_data.cu_type; ++} ++ ++int basic_sense(SubChannelId schid, uint16_t cutype, void *sense_data, ++ uint16_t data_size) ++{ ++ Ccw1 senseCcw; ++ Irb irb; ++ ++ senseCcw.cmd_code = CCW_CMD_BASIC_SENSE; ++ senseCcw.cda = ptr2u32(sense_data); ++ senseCcw.count = data_size; ++ ++ return __do_cio(schid, ptr2u32(&senseCcw), CCW_FMT1, &irb); ++} ++ ++static bool irb_error(Irb *irb) ++{ ++ if (irb->scsw.cstat) { ++ return true; ++ } ++ return irb->scsw.dstat != (SCSW_DSTAT_DEVEND | SCSW_DSTAT_CHEND); ++} ++ ++/* ++ * Handles executing ssch, tsch and returns the irb obtained from tsch. ++ * Returns 0 on success, -1 if unexpected status pending and we need to retry, ++ * otherwise returns condition code from ssch/tsch for error cases. ++ */ ++static int __do_cio(SubChannelId schid, uint32_t ccw_addr, int fmt, Irb *irb) ++{ ++ CmdOrb orb = {}; ++ int rc; ++ ++ IPL_assert(fmt == 0 || fmt == 1, "Invalid ccw format"); ++ ++ /* ccw_addr must be <= 24 bits and point to at least one whole ccw. */ ++ if (fmt == 0) { ++ IPL_assert(ccw_addr <= 0xFFFFFF - 8, "Invalid ccw address"); ++ } ++ ++ orb.fmt = fmt; ++ orb.pfch = 1; /* QEMU's cio implementation requires prefetch */ ++ orb.c64 = 1; /* QEMU's cio implementation requires 64-bit idaws */ ++ orb.lpm = 0xFF; /* All paths allowed */ ++ orb.cpa = ccw_addr; ++ ++ rc = ssch(schid, &orb); ++ if (rc == 1 || rc == 2) { ++ /* Subchannel status pending or busy. Eat status and ask for retry. */ ++ tsch(schid, irb); ++ return -1; ++ } ++ if (rc) { ++ print_int("ssch failed with cc=", rc); ++ return rc; ++ } ++ ++ consume_io_int(); ++ ++ /* collect status */ ++ rc = tsch(schid, irb); ++ if (rc) { ++ print_int("tsch failed with cc=", rc); ++ } ++ ++ return rc; ++} ++ ++/* ++ * Executes a channel program at a given subchannel. The request to run the ++ * channel program is sent to the subchannel, we then wait for the interrupt ++ * signaling completion of the I/O operation(s) performed by the channel ++ * program. Lastly we verify that the i/o operation completed without error and ++ * that the interrupt we received was for the subchannel used to run the ++ * channel program. ++ * ++ * Note: This function assumes it is running in an environment where no other ++ * cpus are generating or receiving I/O interrupts. So either run it in a ++ * single-cpu environment or make sure all other cpus are not doing I/O and ++ * have I/O interrupts masked off. We also assume that only one device is ++ * active (generating i/o interrupts). ++ * ++ * Returns non-zero on error. ++ */ ++int do_cio(SubChannelId schid, uint16_t cutype, uint32_t ccw_addr, int fmt) ++{ ++ Irb irb = {}; ++ SenseDataEckdDasd sd; ++ int rc, retries = 0; ++ ++ while (true) { ++ rc = __do_cio(schid, ccw_addr, fmt, &irb); ++ ++ if (rc == -1) { ++ retries++; ++ continue; ++ } ++ if (rc) { ++ /* ssch/tsch error. Message already reported by __do_cio */ ++ break; ++ } ++ ++ if (!irb_error(&irb)) { ++ break; ++ } ++ ++ /* ++ * Unexpected unit check, or interface-control-check. Use sense to ++ * clear (unit check only) then retry. ++ */ ++ if ((unit_check(&irb) || iface_ctrl_check(&irb)) && retries <= 2) { ++ if (unit_check(&irb)) { ++ basic_sense(schid, cutype, &sd, sizeof(sd)); ++ } ++ retries++; ++ continue; ++ } ++ ++ rc = -1; ++ break; ++ } ++ ++ return rc; ++} +diff --git a/pc-bios/s390-ccw/cio.h b/pc-bios/s390-ccw/cio.h +index 218fd96..1637e32 100644 +--- a/pc-bios/s390-ccw/cio.h ++++ b/pc-bios/s390-ccw/cio.h +@@ -70,9 +70,46 @@ struct scsw { + __u16 count; + } __attribute__ ((packed)); + +-#define SCSW_FCTL_CLEAR_FUNC 0x1000 +-#define SCSW_FCTL_HALT_FUNC 0x2000 ++/* Function Control */ + #define SCSW_FCTL_START_FUNC 0x4000 ++#define SCSW_FCTL_HALT_FUNC 0x2000 ++#define SCSW_FCTL_CLEAR_FUNC 0x1000 ++ ++/* Activity Control */ ++#define SCSW_ACTL_RESUME_PEND 0x0800 ++#define SCSW_ACTL_START_PEND 0x0400 ++#define SCSW_ACTL_HALT_PEND 0x0200 ++#define SCSW_ACTL_CLEAR_PEND 0x0100 ++#define SCSW_ACTL_CH_ACTIVE 0x0080 ++#define SCSW_ACTL_DEV_ACTIVE 0x0040 ++#define SCSW_ACTL_SUSPENDED 0x0020 ++ ++/* Status Control */ ++#define SCSW_SCTL_ALERT 0x0010 ++#define SCSW_SCTL_INTERMED 0x0008 ++#define SCSW_SCTL_PRIMARY 0x0004 ++#define SCSW_SCTL_SECONDARY 0x0002 ++#define SCSW_SCTL_STATUS_PEND 0x0001 ++ ++/* SCSW Device Status Flags */ ++#define SCSW_DSTAT_ATTN 0x80 ++#define SCSW_DSTAT_STATMOD 0x40 ++#define SCSW_DSTAT_CUEND 0x20 ++#define SCSW_DSTAT_BUSY 0x10 ++#define SCSW_DSTAT_CHEND 0x08 ++#define SCSW_DSTAT_DEVEND 0x04 ++#define SCSW_DSTAT_UCHK 0x02 ++#define SCSW_DSTAT_UEXCP 0x01 ++ ++/* SCSW Subchannel Status Flags */ ++#define SCSW_CSTAT_PCINT 0x80 ++#define SCSW_CSTAT_BADLEN 0x40 ++#define SCSW_CSTAT_PROGCHK 0x20 ++#define SCSW_CSTAT_PROTCHK 0x10 ++#define SCSW_CSTAT_CHDCHK 0x08 ++#define SCSW_CSTAT_CHCCHK 0x04 ++#define SCSW_CSTAT_ICCHK 0x02 ++#define SCSW_CSTAT_CHAINCHK 0x01 + + /* + * subchannel information block +@@ -127,7 +164,23 @@ struct tpi_info { + __u32 reserved4:12; + } __attribute__ ((packed, aligned(4))); + +-/* channel command word (type 1) */ ++/* channel command word (format 0) */ ++typedef struct ccw0 { ++ __u8 cmd_code; ++ __u32 cda:24; ++ __u32 chainData:1; ++ __u32 chain:1; ++ __u32 sli:1; ++ __u32 skip:1; ++ __u32 pci:1; ++ __u32 ida:1; ++ __u32 suspend:1; ++ __u32 mida:1; ++ __u8 reserved; ++ __u16 count; ++} __attribute__ ((packed, aligned(8))) Ccw0; ++ ++/* channel command word (format 1) */ + typedef struct ccw1 { + __u8 cmd_code; + __u8 flags; +@@ -135,6 +188,10 @@ typedef struct ccw1 { + __u32 cda; + } __attribute__ ((packed, aligned(8))) Ccw1; + ++/* do_cio() CCW formats */ ++#define CCW_FMT0 0x00 ++#define CCW_FMT1 0x01 ++ + #define CCW_FLAG_DC 0x80 + #define CCW_FLAG_CC 0x40 + #define CCW_FLAG_SLI 0x20 +@@ -190,6 +247,11 @@ struct ciw { + __u16 count; + }; + ++#define CU_TYPE_UNKNOWN 0x0000 ++#define CU_TYPE_DASD_2107 0x2107 ++#define CU_TYPE_VIRTIO 0x3832 ++#define CU_TYPE_DASD_3990 0x3990 ++ + /* + * sense-id response buffer layout + */ +@@ -205,6 +267,64 @@ typedef struct senseid { + struct ciw ciw[62]; + } __attribute__ ((packed, aligned(4))) SenseId; + ++/* ++ * architected values for first sense byte - common_status. Bits 0-5 of this ++ * field are common to all device types. ++ */ ++#define SNS_STAT0_CMD_REJECT 0x80 ++#define SNS_STAT0_INTERVENTION_REQ 0x40 ++#define SNS_STAT0_BUS_OUT_CHECK 0x20 ++#define SNS_STAT0_EQUIPMENT_CHECK 0x10 ++#define SNS_STAT0_DATA_CHECK 0x08 ++#define SNS_STAT0_OVERRUN 0x04 ++#define SNS_STAT0_INCOMPL_DOMAIN 0x01 ++ ++/* ECKD DASD status[0] byte */ ++#define SNS_STAT1_PERM_ERR 0x80 ++#define SNS_STAT1_INV_TRACK_FORMAT 0x40 ++#define SNS_STAT1_EOC 0x20 ++#define SNS_STAT1_MESSAGE_TO_OPER 0x10 ++#define SNS_STAT1_NO_REC_FOUND 0x08 ++#define SNS_STAT1_FILE_PROTECTED 0x04 ++#define SNS_STAT1_WRITE_INHIBITED 0x02 ++#define SNS_STAT1_IMPRECISE_END 0x01 ++ ++/* ECKD DASD status[1] byte */ ++#define SNS_STAT2_REQ_INH_WRITE 0x80 ++#define SNS_STAT2_CORRECTABLE 0x40 ++#define SNS_STAT2_FIRST_LOG_ERR 0x20 ++#define SNS_STAT2_ENV_DATA_PRESENT 0x10 ++#define SNS_STAT2_IMPRECISE_END 0x04 ++ ++/* ECKD DASD 24-byte Sense fmt_msg codes */ ++#define SENSE24_FMT_PROG_SYS 0x0 ++#define SENSE24_FMT_EQUIPMENT 0x2 ++#define SENSE24_FMT_CONTROLLER 0x3 ++#define SENSE24_FMT_MISC 0xF ++ ++/* basic sense response buffer layout */ ++typedef struct SenseDataEckdDasd { ++ uint8_t common_status; ++ uint8_t status[2]; ++ uint8_t res_count; ++ uint8_t phys_drive_id; ++ uint8_t low_cyl_addr; ++ uint8_t head_high_cyl_addr; ++ uint8_t fmt_msg; ++ uint64_t fmt_dependent_info[2]; ++ uint8_t reserved; ++ uint8_t program_action_code; ++ uint16_t config_info; ++ uint8_t mcode_hicyl; ++ uint8_t cyl_head_addr[3]; ++} __attribute__ ((packed, aligned(4))) SenseDataEckdDasd; ++ ++#define ECKD_SENSE24_GET_FMT(sd) (sd->fmt_msg & 0xF0 >> 4) ++#define ECKD_SENSE24_GET_MSG(sd) (sd->fmt_msg & 0x0F) ++ ++#define unit_check(irb) ((irb)->scsw.dstat & SCSW_DSTAT_UCHK) ++#define iface_ctrl_check(irb) ((irb)->scsw.cstat & SCSW_CSTAT_ICCHK) ++ + /* interruption response block */ + typedef struct irb { + struct scsw scsw; +@@ -215,6 +335,10 @@ typedef struct irb { + + int enable_mss_facility(void); + void enable_subchannel(SubChannelId schid); ++uint16_t cu_type(SubChannelId schid); ++int basic_sense(SubChannelId schid, uint16_t cutype, void *sense_data, ++ uint16_t data_size); ++int do_cio(SubChannelId schid, uint16_t cutype, uint32_t ccw_addr, int fmt); + + /* + * Some S390 specific IO instructions as inline +diff --git a/pc-bios/s390-ccw/s390-ccw.h b/pc-bios/s390-ccw/s390-ccw.h +index b39ee5d..11bce7d 100644 +--- a/pc-bios/s390-ccw/s390-ccw.h ++++ b/pc-bios/s390-ccw/s390-ccw.h +@@ -52,6 +52,7 @@ typedef unsigned long long __u64; + /* start.s */ + void disabled_wait(void); + void consume_sclp_int(void); ++void consume_io_int(void); + + /* main.c */ + void panic(const char *string); +diff --git a/pc-bios/s390-ccw/start.S b/pc-bios/s390-ccw/start.S +index eb8d024..fe2a4c3 100644 +--- a/pc-bios/s390-ccw/start.S ++++ b/pc-bios/s390-ccw/start.S +@@ -71,6 +71,26 @@ consume_sclp_int: + larl %r1, enabled_wait_psw + lpswe 0(%r1) + ++/* ++ * void consume_io_int(void) ++ * ++ * eats one I/O interrupt ++ */ ++ .globl consume_io_int ++consume_io_int: ++ /* enable I/O interrupts in cr6 */ ++ stctg %c6,%c6,0(%r15) ++ oi 4(%r15), 0xff ++ lctlg %c6,%c6,0(%r15) ++ /* prepare i/o call handler */ ++ larl %r1, io_new_code ++ stg %r1, 0x1f8 ++ larl %r1, io_new_mask ++ mvc 0x1f0(8),0(%r1) ++ /* load enabled wait PSW */ ++ larl %r1, enabled_wait_psw ++ lpswe 0(%r1) ++ + external_new_code: + /* disable service interrupts in cr0 */ + stctg 0,0,0(15) +@@ -78,6 +98,13 @@ external_new_code: + lctlg 0,0,0(15) + br 14 + ++io_new_code: ++ /* disable I/O interrupts in cr6 */ ++ stctg %c6,%c6,0(%r15) ++ ni 4(%r15), 0x00 ++ lctlg %c6,%c6,0(%r15) ++ br %r14 ++ + .align 8 + disabled_wait_psw: + .quad 0x0002000180000000,0x0000000000000000 +@@ -85,3 +112,5 @@ enabled_wait_psw: + .quad 0x0302000180000000,0x0000000000000000 + external_new_mask: + .quad 0x0000000180000000 ++io_new_mask: ++ .quad 0x0000000180000000 +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390-bios-Use-control-unit-type-to-determine-boot-me.patch b/SOURCES/kvm-s390-bios-Use-control-unit-type-to-determine-boot-me.patch new file mode 100644 index 0000000..d9daa9c --- /dev/null +++ b/SOURCES/kvm-s390-bios-Use-control-unit-type-to-determine-boot-me.patch @@ -0,0 +1,106 @@ +From 4b0f36b50e79fe6d345c85f60f12508c17c44f1d Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Mon, 14 Oct 2019 10:06:42 +0100 +Subject: [PATCH 17/21] s390-bios: Use control unit type to determine boot + method + +RH-Author: Thomas Huth +Message-id: <20191014100645.22862-15-thuth@redhat.com> +Patchwork-id: 91785 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH v2 14/17] s390-bios: Use control unit type to determine boot method +Bugzilla: 1664376 +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand +RH-Acked-by: Jens Freimann + +From: "Jason J. Herne" + +The boot method is different depending on which device type we are +booting from. Let's examine the control unit type to determine if we're +a virtio device. We'll eventually add a case to check for a real dasd device +here as well. + +Since we have to call enable_subchannel() in main now, might as well +remove that call from virtio.c : run_ccw(). This requires adding some +additional enable_subchannel calls to not break calls to +virtio_is_supported(). + +Signed-off-by: Jason J. Herne +Reviewed-by: Cornelia Huck +Reviewed-by: Thomas Huth +Message-Id: <1554388475-18329-14-git-send-email-jjherne@linux.ibm.com> +Signed-off-by: Thomas Huth +(cherry picked from commit 3668cb7ce864ee9351d5d20a1ec6b427cd0b3be4) +Signed-off-by: Danilo C. L. de Paula +--- + pc-bios/s390-ccw/main.c | 16 ++++++++++++++-- + pc-bios/s390-ccw/netmain.c | 1 + + pc-bios/s390-ccw/virtio.c | 1 - + 3 files changed, 15 insertions(+), 3 deletions(-) + +diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c +index d3a161c..57a1013 100644 +--- a/pc-bios/s390-ccw/main.c ++++ b/pc-bios/s390-ccw/main.c +@@ -76,6 +76,7 @@ static bool find_subch(int dev_no) + /* Skip net devices since no IPLB is created and therefore no + * network bootloader has been loaded + */ ++ enable_subchannel(blk_schid); + if (virtio_is_supported(blk_schid) && + virtio_get_device_type() == VIRTIO_ID_NET && dev_no < 0) { + continue; +@@ -198,13 +199,24 @@ static void virtio_setup(void) + + int main(void) + { ++ uint16_t cutype; ++ + sclp_setup(); + css_setup(); + boot_setup(); + find_boot_device(); ++ enable_subchannel(blk_schid); + +- virtio_setup(); +- zipl_load(); /* no return */ ++ cutype = cu_type(blk_schid); ++ switch (cutype) { ++ case CU_TYPE_VIRTIO: ++ virtio_setup(); ++ zipl_load(); /* no return */ ++ break; ++ default: ++ print_int("Attempting to boot from unexpected device type", cutype); ++ panic(""); ++ } + + panic("Failed to load OS from hard disk\n"); + return 0; /* make compiler happy */ +diff --git a/pc-bios/s390-ccw/netmain.c b/pc-bios/s390-ccw/netmain.c +index 4e1b8cf..69cf59d 100644 +--- a/pc-bios/s390-ccw/netmain.c ++++ b/pc-bios/s390-ccw/netmain.c +@@ -304,6 +304,7 @@ static bool find_net_dev(Schib *schib, int dev_no) + if (!schib->pmcw.dnv) { + continue; + } ++ enable_subchannel(net_schid); + if (!virtio_is_supported(net_schid)) { + continue; + } +diff --git a/pc-bios/s390-ccw/virtio.c b/pc-bios/s390-ccw/virtio.c +index 35278eae..fb40ca9 100644 +--- a/pc-bios/s390-ccw/virtio.c ++++ b/pc-bios/s390-ccw/virtio.c +@@ -102,7 +102,6 @@ static int run_ccw(VDev *vdev, int cmd, void *ptr, int len, bool sli) + ccw.flags |= CCW_FLAG_SLI; + } + +- enable_subchannel(vdev->schid); + return do_cio(vdev->schid, vdev->senseid.cu_type, ptr2u32(&ccw), CCW_FMT1); + } + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390-bios-Use-control-unit-type-to-find-bootable-dev.patch b/SOURCES/kvm-s390-bios-Use-control-unit-type-to-find-bootable-dev.patch new file mode 100644 index 0000000..296f273 --- /dev/null +++ b/SOURCES/kvm-s390-bios-Use-control-unit-type-to-find-bootable-dev.patch @@ -0,0 +1,127 @@ +From cdc1df196d9e1cf5e6f6fe2900637b78d606ee85 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Mon, 14 Oct 2019 10:06:45 +0100 +Subject: [PATCH 20/21] s390-bios: Use control unit type to find bootable + devices + +RH-Author: Thomas Huth +Message-id: <20191014100645.22862-18-thuth@redhat.com> +Patchwork-id: 91790 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH v2 17/17] s390-bios: Use control unit type to find bootable devices +Bugzilla: 1664376 +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand +RH-Acked-by: Jens Freimann + +From: "Jason J. Herne" + +When the user does not specify which device to boot from then we end +up guessing. Instead of simply grabbing the first available device let's +be a little bit smarter and only choose devices that might be bootable +like disk, and not console devices. + +Signed-off-by: Jason J. Herne +Message-Id: <1554388475-18329-17-git-send-email-jjherne@linux.ibm.com> +[thuth: Added fix for virtio_is_supported() not being called anymore] +Signed-off-by: Thomas Huth +(cherry picked from commit 2880469c95e42f8a5b0acbe8c4808255cc6c9e5b) + +Signed-off-by: Danilo C. L. de Paula +--- + pc-bios/s390-ccw/main.c | 45 +++++++++++++++++++++++++++++++++++---------- + 1 file changed, 35 insertions(+), 10 deletions(-) + +diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c +index 3c449ad..a69c733 100644 +--- a/pc-bios/s390-ccw/main.c ++++ b/pc-bios/s390-ccw/main.c +@@ -21,6 +21,7 @@ static char loadparm_str[LOADPARM_LEN + 1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + QemuIplParameters qipl; + IplParameterBlock iplb __attribute__((__aligned__(PAGE_SIZE))); + static bool have_iplb; ++static uint16_t cutype; + LowCore const *lowcore; /* Yes, this *is* a pointer to address 0 */ + + #define LOADPARM_PROMPT "PROMPT " +@@ -58,11 +59,15 @@ unsigned int get_loadparm_index(void) + * subchannel information block (schib) with the connected subchannel's info. + * NOTE: The global variable blk_schid is updated to contain the subchannel + * information. ++ * ++ * If the caller gives dev_no=-1 then the user did not specify a boot device. ++ * In this case we'll just use the first potentially bootable device we find. + */ + static bool find_subch(int dev_no) + { + Schib schib; + int i, r; ++ bool is_virtio; + + for (i = 0; i < 0x10000; i++) { + blk_schid.sch_no = i; +@@ -74,16 +79,39 @@ static bool find_subch(int dev_no) + continue; + } + +- /* Skip net devices since no IPLB is created and therefore no +- * network bootloader has been loaded +- */ + enable_subchannel(blk_schid); +- if (virtio_is_supported(blk_schid) && +- virtio_get_device_type() == VIRTIO_ID_NET && dev_no < 0) { +- continue; ++ cutype = cu_type(blk_schid); ++ ++ /* ++ * Note: we always have to run virtio_is_supported() here to make ++ * sure that the vdev.senseid data gets pre-initialized correctly ++ */ ++ is_virtio = virtio_is_supported(blk_schid); ++ ++ /* No specific devno given, just return 1st possibly bootable device */ ++ if (dev_no < 0) { ++ switch (cutype) { ++ case CU_TYPE_VIRTIO: ++ if (is_virtio) { ++ /* ++ * Skip net devices since no IPLB is created and therefore ++ * no network bootloader has been loaded ++ */ ++ if (virtio_get_device_type() != VIRTIO_ID_NET) { ++ return true; ++ } ++ } ++ continue; ++ case CU_TYPE_DASD_3990: ++ case CU_TYPE_DASD_2107: ++ return true; ++ default: ++ continue; ++ } + } + +- if ((dev_no < 0) || (schib.pmcw.dev == dev_no)) { ++ /* Caller asked for a specific devno */ ++ if (schib.pmcw.dev == dev_no) { + return true; + } + } +@@ -200,15 +228,12 @@ static void virtio_setup(void) + + int main(void) + { +- uint16_t cutype; +- + sclp_setup(); + css_setup(); + boot_setup(); + find_boot_device(); + enable_subchannel(blk_schid); + +- cutype = cu_type(blk_schid); + switch (cutype) { + case CU_TYPE_DASD_3990: + case CU_TYPE_DASD_2107: +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390-bios-cio-error-handling.patch b/SOURCES/kvm-s390-bios-cio-error-handling.patch new file mode 100644 index 0000000..f7bf350 --- /dev/null +++ b/SOURCES/kvm-s390-bios-cio-error-handling.patch @@ -0,0 +1,341 @@ +From f7d509d82aeb0af595c6dcfade7904b248ed180b Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Mon, 14 Oct 2019 10:06:38 +0100 +Subject: [PATCH 13/21] s390-bios: cio error handling + +RH-Author: Thomas Huth +Message-id: <20191014100645.22862-11-thuth@redhat.com> +Patchwork-id: 91787 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH v2 10/17] s390-bios: cio error handling +Bugzilla: 1664376 +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand +RH-Acked-by: Jens Freimann + +From: "Jason J. Herne" + +Add verbose error output for when unexpected i/o errors happen. This eases the +burden of debugging and reporting i/o errors. No error information is printed +in the success case, here is an example of what is output on error: + +cio device error + ssid : 0x0000000000000000 + cssid : 0x0000000000000000 + sch_no: 0x0000000000000000 + +Interrupt Response Block Data: + Function Ctrl : [Start] + Activity Ctrl : [Start-Pending] + Status Ctrl : [Alert] [Primary] [Secondary] [Status-Pending] + Device Status : [Unit-Check] + Channel Status : + cpa=: 0x000000007f8d6038 + prev_ccw=: 0x0000000000000000 + this_ccw=: 0x0000000000000000 +Eckd Dasd Sense Data (fmt 32-bytes): + Sense Condition Flags : + Residual Count =: 0x0000000000000000 + Phys Drive ID =: 0x000000000000009e + low cyl address =: 0x0000000000000000 + head addr & hi cyl =: 0x0000000000000000 + format/message =: 0x0000000000000008 + fmt-dependent[0-7] =: 0x0000000000000004 + fmt-dependent[8-15]=: 0xe561282305082fff + prog action code =: 0x0000000000000016 + Configuration info =: 0x00000000000040e0 + mcode / hi-cyl =: 0x0000000000000000 + cyl & head addr [0]=: 0x0000000000000000 + cyl & head addr [1]=: 0x0000000000000000 + cyl & head addr [2]=: 0x0000000000000000 + +The Sense Data section is currently only printed for ECKD DASD. + +Signed-off-by: Jason J. Herne +Reviewed-by: Cornelia Huck +Message-Id: <1554388475-18329-10-git-send-email-jjherne@linux.ibm.com> +Signed-off-by: Thomas Huth +(cherry picked from commit 86c58705bb186cfa73a03851047da2c2c37b9418) +Signed-off-by: Danilo C. L. de Paula +--- + pc-bios/s390-ccw/cio.c | 235 ++++++++++++++++++++++++++++++++++++++++++++++++ + pc-bios/s390-ccw/libc.h | 11 +++ + 2 files changed, 246 insertions(+) + +diff --git a/pc-bios/s390-ccw/cio.c b/pc-bios/s390-ccw/cio.c +index c43e50b..339ec5f 100644 +--- a/pc-bios/s390-ccw/cio.c ++++ b/pc-bios/s390-ccw/cio.c +@@ -85,6 +85,228 @@ static bool irb_error(Irb *irb) + return irb->scsw.dstat != (SCSW_DSTAT_DEVEND | SCSW_DSTAT_CHEND); + } + ++static void print_eckd_dasd_sense_data(SenseDataEckdDasd *sd) ++{ ++ char msgline[512]; ++ ++ if (sd->config_info & 0x8000) { ++ sclp_print("Eckd Dasd Sense Data (fmt 24-bytes):\n"); ++ } else { ++ sclp_print("Eckd Dasd Sense Data (fmt 32-bytes):\n"); ++ } ++ ++ strcat(msgline, " Sense Condition Flags :"); ++ if (sd->common_status & SNS_STAT0_CMD_REJECT) { ++ strcat(msgline, " [Cmd-Reject]"); ++ } ++ if (sd->common_status & SNS_STAT0_INTERVENTION_REQ) { ++ strcat(msgline, " [Intervention-Required]"); ++ } ++ if (sd->common_status & SNS_STAT0_BUS_OUT_CHECK) { ++ strcat(msgline, " [Bus-Out-Parity-Check]"); ++ } ++ if (sd->common_status & SNS_STAT0_EQUIPMENT_CHECK) { ++ strcat(msgline, " [Equipment-Check]"); ++ } ++ if (sd->common_status & SNS_STAT0_DATA_CHECK) { ++ strcat(msgline, " [Data-Check]"); ++ } ++ if (sd->common_status & SNS_STAT0_OVERRUN) { ++ strcat(msgline, " [Overrun]"); ++ } ++ if (sd->common_status & SNS_STAT0_INCOMPL_DOMAIN) { ++ strcat(msgline, " [Incomplete-Domain]"); ++ } ++ ++ if (sd->status[0] & SNS_STAT1_PERM_ERR) { ++ strcat(msgline, " [Permanent-Error]"); ++ } ++ if (sd->status[0] & SNS_STAT1_INV_TRACK_FORMAT) { ++ strcat(msgline, " [Invalid-Track-Fmt]"); ++ } ++ if (sd->status[0] & SNS_STAT1_EOC) { ++ strcat(msgline, " [End-of-Cyl]"); ++ } ++ if (sd->status[0] & SNS_STAT1_MESSAGE_TO_OPER) { ++ strcat(msgline, " [Operator-Msg]"); ++ } ++ if (sd->status[0] & SNS_STAT1_NO_REC_FOUND) { ++ strcat(msgline, " [No-Record-Found]"); ++ } ++ if (sd->status[0] & SNS_STAT1_FILE_PROTECTED) { ++ strcat(msgline, " [File-Protected]"); ++ } ++ if (sd->status[0] & SNS_STAT1_WRITE_INHIBITED) { ++ strcat(msgline, " [Write-Inhibited]"); ++ } ++ if (sd->status[0] & SNS_STAT1_IMPRECISE_END) { ++ strcat(msgline, " [Imprecise-Ending]"); ++ } ++ ++ if (sd->status[1] & SNS_STAT2_REQ_INH_WRITE) { ++ strcat(msgline, " [Req-Inhibit-Write]"); ++ } ++ if (sd->status[1] & SNS_STAT2_CORRECTABLE) { ++ strcat(msgline, " [Correctable-Data-Check]"); ++ } ++ if (sd->status[1] & SNS_STAT2_FIRST_LOG_ERR) { ++ strcat(msgline, " [First-Error-Log]"); ++ } ++ if (sd->status[1] & SNS_STAT2_ENV_DATA_PRESENT) { ++ strcat(msgline, " [Env-Data-Present]"); ++ } ++ if (sd->status[1] & SNS_STAT2_IMPRECISE_END) { ++ strcat(msgline, " [Imprecise-End]"); ++ } ++ strcat(msgline, "\n"); ++ sclp_print(msgline); ++ ++ print_int(" Residual Count =", sd->res_count); ++ print_int(" Phys Drive ID =", sd->phys_drive_id); ++ print_int(" low cyl address =", sd->low_cyl_addr); ++ print_int(" head addr & hi cyl =", sd->head_high_cyl_addr); ++ print_int(" format/message =", sd->fmt_msg); ++ print_int(" fmt-dependent[0-7] =", sd->fmt_dependent_info[0]); ++ print_int(" fmt-dependent[8-15]=", sd->fmt_dependent_info[1]); ++ print_int(" prog action code =", sd->program_action_code); ++ print_int(" Configuration info =", sd->config_info); ++ print_int(" mcode / hi-cyl =", sd->mcode_hicyl); ++ print_int(" cyl & head addr [0]=", sd->cyl_head_addr[0]); ++ print_int(" cyl & head addr [1]=", sd->cyl_head_addr[1]); ++ print_int(" cyl & head addr [2]=", sd->cyl_head_addr[2]); ++} ++ ++static void print_irb_err(Irb *irb) ++{ ++ uint64_t this_ccw = *(uint64_t *)u32toptr(irb->scsw.cpa); ++ uint64_t prev_ccw = *(uint64_t *)u32toptr(irb->scsw.cpa - 8); ++ char msgline[256]; ++ ++ sclp_print("Interrupt Response Block Data:\n"); ++ ++ strcat(msgline, " Function Ctrl :"); ++ if (irb->scsw.ctrl & SCSW_FCTL_START_FUNC) { ++ strcat(msgline, " [Start]"); ++ } ++ if (irb->scsw.ctrl & SCSW_FCTL_HALT_FUNC) { ++ strcat(msgline, " [Halt]"); ++ } ++ if (irb->scsw.ctrl & SCSW_FCTL_CLEAR_FUNC) { ++ strcat(msgline, " [Clear]"); ++ } ++ strcat(msgline, "\n"); ++ sclp_print(msgline); ++ ++ msgline[0] = '\0'; ++ strcat(msgline, " Activity Ctrl :"); ++ if (irb->scsw.ctrl & SCSW_ACTL_RESUME_PEND) { ++ strcat(msgline, " [Resume-Pending]"); ++ } ++ if (irb->scsw.ctrl & SCSW_ACTL_START_PEND) { ++ strcat(msgline, " [Start-Pending]"); ++ } ++ if (irb->scsw.ctrl & SCSW_ACTL_HALT_PEND) { ++ strcat(msgline, " [Halt-Pending]"); ++ } ++ if (irb->scsw.ctrl & SCSW_ACTL_CLEAR_PEND) { ++ strcat(msgline, " [Clear-Pending]"); ++ } ++ if (irb->scsw.ctrl & SCSW_ACTL_CH_ACTIVE) { ++ strcat(msgline, " [Channel-Active]"); ++ } ++ if (irb->scsw.ctrl & SCSW_ACTL_DEV_ACTIVE) { ++ strcat(msgline, " [Device-Active]"); ++ } ++ if (irb->scsw.ctrl & SCSW_ACTL_SUSPENDED) { ++ strcat(msgline, " [Suspended]"); ++ } ++ strcat(msgline, "\n"); ++ sclp_print(msgline); ++ ++ msgline[0] = '\0'; ++ strcat(msgline, " Status Ctrl :"); ++ if (irb->scsw.ctrl & SCSW_SCTL_ALERT) { ++ strcat(msgline, " [Alert]"); ++ } ++ if (irb->scsw.ctrl & SCSW_SCTL_INTERMED) { ++ strcat(msgline, " [Intermediate]"); ++ } ++ if (irb->scsw.ctrl & SCSW_SCTL_PRIMARY) { ++ strcat(msgline, " [Primary]"); ++ } ++ if (irb->scsw.ctrl & SCSW_SCTL_SECONDARY) { ++ strcat(msgline, " [Secondary]"); ++ } ++ if (irb->scsw.ctrl & SCSW_SCTL_STATUS_PEND) { ++ strcat(msgline, " [Status-Pending]"); ++ } ++ ++ strcat(msgline, "\n"); ++ sclp_print(msgline); ++ ++ msgline[0] = '\0'; ++ strcat(msgline, " Device Status :"); ++ if (irb->scsw.dstat & SCSW_DSTAT_ATTN) { ++ strcat(msgline, " [Attention]"); ++ } ++ if (irb->scsw.dstat & SCSW_DSTAT_STATMOD) { ++ strcat(msgline, " [Status-Modifier]"); ++ } ++ if (irb->scsw.dstat & SCSW_DSTAT_CUEND) { ++ strcat(msgline, " [Ctrl-Unit-End]"); ++ } ++ if (irb->scsw.dstat & SCSW_DSTAT_BUSY) { ++ strcat(msgline, " [Busy]"); ++ } ++ if (irb->scsw.dstat & SCSW_DSTAT_CHEND) { ++ strcat(msgline, " [Channel-End]"); ++ } ++ if (irb->scsw.dstat & SCSW_DSTAT_DEVEND) { ++ strcat(msgline, " [Device-End]"); ++ } ++ if (irb->scsw.dstat & SCSW_DSTAT_UCHK) { ++ strcat(msgline, " [Unit-Check]"); ++ } ++ if (irb->scsw.dstat & SCSW_DSTAT_UEXCP) { ++ strcat(msgline, " [Unit-Exception]"); ++ } ++ strcat(msgline, "\n"); ++ sclp_print(msgline); ++ ++ msgline[0] = '\0'; ++ strcat(msgline, " Channel Status :"); ++ if (irb->scsw.cstat & SCSW_CSTAT_PCINT) { ++ strcat(msgline, " [Program-Ctrl-Interruption]"); ++ } ++ if (irb->scsw.cstat & SCSW_CSTAT_BADLEN) { ++ strcat(msgline, " [Incorrect-Length]"); ++ } ++ if (irb->scsw.cstat & SCSW_CSTAT_PROGCHK) { ++ strcat(msgline, " [Program-Check]"); ++ } ++ if (irb->scsw.cstat & SCSW_CSTAT_PROTCHK) { ++ strcat(msgline, " [Protection-Check]"); ++ } ++ if (irb->scsw.cstat & SCSW_CSTAT_CHDCHK) { ++ strcat(msgline, " [Channel-Data-Check]"); ++ } ++ if (irb->scsw.cstat & SCSW_CSTAT_CHCCHK) { ++ strcat(msgline, " [Channel-Ctrl-Check]"); ++ } ++ if (irb->scsw.cstat & SCSW_CSTAT_ICCHK) { ++ strcat(msgline, " [Interface-Ctrl-Check]"); ++ } ++ if (irb->scsw.cstat & SCSW_CSTAT_CHAINCHK) { ++ strcat(msgline, " [Chaining-Check]"); ++ } ++ strcat(msgline, "\n"); ++ sclp_print(msgline); ++ ++ print_int(" cpa=", irb->scsw.cpa); ++ print_int(" prev_ccw=", prev_ccw); ++ print_int(" this_ccw=", this_ccw); ++} ++ + /* + * Handles executing ssch, tsch and returns the irb obtained from tsch. + * Returns 0 on success, -1 if unexpected status pending and we need to retry, +@@ -180,6 +402,19 @@ int do_cio(SubChannelId schid, uint16_t cutype, uint32_t ccw_addr, int fmt) + continue; + } + ++ sclp_print("cio device error\n"); ++ print_int(" ssid ", schid.ssid); ++ print_int(" cssid ", schid.cssid); ++ print_int(" sch_no", schid.sch_no); ++ print_int(" ctrl-unit type", cutype); ++ sclp_print("\n"); ++ print_irb_err(&irb); ++ if (cutype == CU_TYPE_DASD_3990 || cutype == CU_TYPE_DASD_2107 || ++ cutype == CU_TYPE_UNKNOWN) { ++ if (!basic_sense(schid, cutype, &sd, sizeof(sd))) { ++ print_eckd_dasd_sense_data(&sd); ++ } ++ } + rc = -1; + break; + } +diff --git a/pc-bios/s390-ccw/libc.h b/pc-bios/s390-ccw/libc.h +index 818517f..bcdc457 100644 +--- a/pc-bios/s390-ccw/libc.h ++++ b/pc-bios/s390-ccw/libc.h +@@ -67,6 +67,17 @@ static inline size_t strlen(const char *str) + return i; + } + ++static inline char *strcat(char *dest, const char *src) ++{ ++ int i; ++ char *dest_end = dest + strlen(dest); ++ ++ for (i = 0; i <= strlen(src); i++) { ++ dest_end[i] = src[i]; ++ } ++ return dest; ++} ++ + static inline int isdigit(int c) + { + return (c >= '0') && (c <= '9'); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390-bios-decouple-cio-setup-from-virtio.patch b/SOURCES/kvm-s390-bios-decouple-cio-setup-from-virtio.patch new file mode 100644 index 0000000..f51a3a0 --- /dev/null +++ b/SOURCES/kvm-s390-bios-decouple-cio-setup-from-virtio.patch @@ -0,0 +1,82 @@ +From 19b96c7f412b9b8d893ec9ebd2603565d6afa178 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Mon, 14 Oct 2019 10:06:31 +0100 +Subject: [PATCH 06/21] s390-bios: decouple cio setup from virtio + +RH-Author: Thomas Huth +Message-id: <20191014100645.22862-4-thuth@redhat.com> +Patchwork-id: 91776 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH v2 03/17] s390-bios: decouple cio setup from virtio +Bugzilla: 1664376 +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand +RH-Acked-by: Jens Freimann + +From: "Jason J. Herne" + +Move channel i/o setup code out to a separate function. This decouples cio +setup from the virtio code path and allows us to make use of it for booting +dasd devices. + +Signed-off-by: Jason J. Herne +Acked-by: Halil Pasic +Reviewed-by: Collin Walling +Reviewed-by: Farhan Ali +Reviewed-by: Thomas Huth +Reviewed-by: Cornelia Huck +Message-Id: <1554388475-18329-3-git-send-email-jjherne@linux.ibm.com> +Signed-off-by: Thomas Huth +(cherry picked from commit 87f910c142d5589ef937ac216f92c6dcddae955e) +Signed-off-by: Danilo C. L. de Paula +--- + pc-bios/s390-ccw/main.c | 20 +++++++++++++------- + 1 file changed, 13 insertions(+), 7 deletions(-) + +diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c +index 544851d..e82fe2c 100644 +--- a/pc-bios/s390-ccw/main.c ++++ b/pc-bios/s390-ccw/main.c +@@ -99,6 +99,18 @@ static void menu_setup(void) + } + } + ++/* ++ * Initialize the channel I/O subsystem so we can talk to our ipl/boot device. ++ */ ++static void css_setup(void) ++{ ++ /* ++ * Unconditionally enable mss support. In every sane configuration this ++ * will succeed; and even if it doesn't, stsch_err() can handle it. ++ */ ++ enable_mss_facility(); ++} ++ + static void virtio_setup(void) + { + Schib schib; +@@ -109,13 +121,6 @@ static void virtio_setup(void) + VDev *vdev = virtio_get_device(); + QemuIplParameters *early_qipl = (QemuIplParameters *)QIPL_ADDRESS; + +- /* +- * We unconditionally enable mss support. In every sane configuration, +- * this will succeed; and even if it doesn't, stsch_err() can deal +- * with the consequences. +- */ +- enable_mss_facility(); +- + sclp_get_loadparm_ascii(loadparm_str); + memcpy(ldp + 10, loadparm_str, LOADPARM_LEN); + sclp_print(ldp); +@@ -168,6 +173,7 @@ static void virtio_setup(void) + int main(void) + { + sclp_setup(); ++ css_setup(); + virtio_setup(); + + zipl_load(); /* no return */ +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390-bios-decouple-common-boot-logic-from-virtio.patch b/SOURCES/kvm-s390-bios-decouple-common-boot-logic-from-virtio.patch new file mode 100644 index 0000000..cf40956 --- /dev/null +++ b/SOURCES/kvm-s390-bios-decouple-common-boot-logic-from-virtio.patch @@ -0,0 +1,110 @@ +From 59ef4d9a3358627fbd7001028903cd89e061a216 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Mon, 14 Oct 2019 10:06:32 +0100 +Subject: [PATCH 07/21] s390-bios: decouple common boot logic from virtio + +RH-Author: Thomas Huth +Message-id: <20191014100645.22862-5-thuth@redhat.com> +Patchwork-id: 91778 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH v2 04/17] s390-bios: decouple common boot logic from virtio +Bugzilla: 1664376 +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand +RH-Acked-by: Jens Freimann + +From: "Jason J. Herne" + +Create a boot_setup function to handle getting boot information from +the machine/hypervisor. This decouples common boot logic from the +virtio code path and allows us to make use of it for the real dasd boot +scenario. + +Signed-off-by: Jason J. Herne +Acked-by: Halil Pasic +Reviewed-by: Collin Walling +Reviewed-by: Farhan Ali +Reviewed-by: Cornelia Huck +Message-Id: <1554388475-18329-4-git-send-email-jjherne@linux.ibm.com> +Signed-off-by: Thomas Huth +(cherry picked from commit a5f6e0975b1f1b79f446c8323e62fd0534408da6) +Signed-off-by: Danilo C. L. de Paula +--- + pc-bios/s390-ccw/main.c | 28 ++++++++++++++++++++-------- + 1 file changed, 20 insertions(+), 8 deletions(-) + +diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c +index e82fe2c..67df421 100644 +--- a/pc-bios/s390-ccw/main.c ++++ b/pc-bios/s390-ccw/main.c +@@ -14,16 +14,17 @@ + + char stack[PAGE_SIZE * 8] __attribute__((__aligned__(PAGE_SIZE))); + static SubChannelId blk_schid = { .one = 1 }; +-IplParameterBlock iplb __attribute__((__aligned__(PAGE_SIZE))); + static char loadparm_str[LOADPARM_LEN + 1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + QemuIplParameters qipl; ++IplParameterBlock iplb __attribute__((__aligned__(PAGE_SIZE))); ++static bool have_iplb; + + #define LOADPARM_PROMPT "PROMPT " + #define LOADPARM_EMPTY " " + #define BOOT_MENU_FLAG_MASK (QIPL_FLAG_BM_OPTS_CMD | QIPL_FLAG_BM_OPTS_ZIPL) + + /* +- * Priniciples of Operations (SA22-7832-09) chapter 17 requires that ++ * Principles of Operations (SA22-7832-09) chapter 17 requires that + * a subsystem-identification is at 184-187 and bytes 188-191 are zero + * after list-directed-IPL and ccw-IPL. + */ +@@ -111,23 +112,33 @@ static void css_setup(void) + enable_mss_facility(); + } + ++/* ++ * Collect various pieces of information from the hypervisor/hardware that ++ * we'll use to determine exactly how we'll boot. ++ */ ++static void boot_setup(void) ++{ ++ char lpmsg[] = "LOADPARM=[________]\n"; ++ ++ sclp_get_loadparm_ascii(loadparm_str); ++ memcpy(lpmsg + 10, loadparm_str, 8); ++ sclp_print(lpmsg); ++ ++ have_iplb = store_iplb(&iplb); ++} ++ + static void virtio_setup(void) + { + Schib schib; + int ssid; + bool found = false; + uint16_t dev_no; +- char ldp[] = "LOADPARM=[________]\n"; + VDev *vdev = virtio_get_device(); + QemuIplParameters *early_qipl = (QemuIplParameters *)QIPL_ADDRESS; + +- sclp_get_loadparm_ascii(loadparm_str); +- memcpy(ldp + 10, loadparm_str, LOADPARM_LEN); +- sclp_print(ldp); +- + memcpy(&qipl, early_qipl, sizeof(QemuIplParameters)); + +- if (store_iplb(&iplb)) { ++ if (have_iplb) { + switch (iplb.pbt) { + case S390_IPL_TYPE_CCW: + dev_no = iplb.ccw.devno; +@@ -174,6 +185,7 @@ int main(void) + { + sclp_setup(); + css_setup(); ++ boot_setup(); + virtio_setup(); + + zipl_load(); /* no return */ +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390-bios-ptr2u32-and-u32toptr.patch b/SOURCES/kvm-s390-bios-ptr2u32-and-u32toptr.patch new file mode 100644 index 0000000..b34c971 --- /dev/null +++ b/SOURCES/kvm-s390-bios-ptr2u32-and-u32toptr.patch @@ -0,0 +1,72 @@ +From d032dae613dc006c91ad8581f203af1bd4bdbf9c Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Mon, 14 Oct 2019 10:06:36 +0100 +Subject: [PATCH 11/21] s390-bios: ptr2u32 and u32toptr + +RH-Author: Thomas Huth +Message-id: <20191014100645.22862-9-thuth@redhat.com> +Patchwork-id: 91788 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH v2 08/17] s390-bios: ptr2u32 and u32toptr +Bugzilla: 1664376 +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand +RH-Acked-by: Jens Freimann + +From: "Jason J. Herne" + +Introduce inline functions to convert between pointers and unsigned 32-bit +ints. These are used to hide the ugliness required to avoid compiler +warnings. + +Signed-off-by: Jason J. Herne +Acked-by: Cornelia Huck +Reviewed-by: Thomas Huth +Message-Id: <1554388475-18329-8-git-send-email-jjherne@linux.ibm.com> +Signed-off-by: Thomas Huth +(cherry picked from commit 1fb3e5cde8dcd9b5917aea9a0b2918e16be8be1e) +Signed-off-by: Danilo C. L. de Paula +--- + pc-bios/s390-ccw/helper.h | 31 +++++++++++++++++++++++++++++++ + 1 file changed, 31 insertions(+) + create mode 100644 pc-bios/s390-ccw/helper.h + +diff --git a/pc-bios/s390-ccw/helper.h b/pc-bios/s390-ccw/helper.h +new file mode 100644 +index 0000000..78d5bc7 +--- /dev/null ++++ b/pc-bios/s390-ccw/helper.h +@@ -0,0 +1,31 @@ ++/* ++ * Helper Functions ++ * ++ * Copyright (c) 2019 IBM Corp. ++ * ++ * Author(s): Jason J. Herne ++ * ++ * This work is licensed under the terms of the GNU GPL, version 2 or (at ++ * your option) any later version. See the COPYING file in the top-level ++ * directory. ++ */ ++ ++#ifndef S390_CCW_HELPER_H ++#define S390_CCW_HELPER_H ++ ++#include "s390-ccw.h" ++ ++/* Avoids compiler warnings when casting a pointer to a u32 */ ++static inline uint32_t ptr2u32(void *ptr) ++{ ++ IPL_assert((uint64_t)ptr <= 0xffffffff, "ptr2u32: ptr too large"); ++ return (uint32_t)(uint64_t)ptr; ++} ++ ++/* Avoids compiler warnings when casting a u32 to a pointer */ ++static inline void *u32toptr(uint32_t n) ++{ ++ return (void *)(uint64_t)n; ++} ++ ++#endif +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390-cpumodel-fix-description-for-the-new-vector-fac.patch b/SOURCES/kvm-s390-cpumodel-fix-description-for-the-new-vector-fac.patch new file mode 100644 index 0000000..9ad4f46 --- /dev/null +++ b/SOURCES/kvm-s390-cpumodel-fix-description-for-the-new-vector-fac.patch @@ -0,0 +1,48 @@ +From bd0e218dc19724fb4c61d259601d116113f114a5 Mon Sep 17 00:00:00 2001 +From: David Hildenbrand +Date: Tue, 16 Jul 2019 20:44:19 +0100 +Subject: [PATCH 17/39] s390: cpumodel: fix description for the new vector + facility + +RH-Author: David Hildenbrand +Message-id: <20190716204422.9350-2-david@redhat.com> +Patchwork-id: 89547 +O-Subject: [RHEL8.1 qemu-kvm PATCH 1/4] s390: cpumodel: fix description for the new vector facility +Bugzilla: 1729975 +RH-Acked-by: Thomas Huth +RH-Acked-by: Cornelia Huck +RH-Acked-by: Jens Freimann + +Conflicts: upstream moved the definitions + +The new facility is called "Vector-Packed-Decimal-Enhancement Facility" +and not "Vector BCD enhancements facility 1". As the shortname might +have already found its way into some backports, let's keep vxbeh. + +Fixes: 54d65de0b525 ("s390x/cpumodel: vector enhancements") +Signed-off-by: Christian Borntraeger +Message-Id: <20190708150931.93448-1-borntraeger@de.ibm.com> +Signed-off-by: Cornelia Huck +(cherry picked from commit d05be57ddc2e1722f527aa4c20d84dfd15c840ec) +Signed-off-by: David Hildenbrand +Signed-off-by: Danilo C. L. de Paula +--- + target/s390x/cpu_features.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/target/s390x/cpu_features.c b/target/s390x/cpu_features.c +index f64f581..5be6f59 100644 +--- a/target/s390x/cpu_features.c ++++ b/target/s390x/cpu_features.c +@@ -111,7 +111,7 @@ static const S390FeatDef s390_features[] = { + FEAT_INIT("vxeh2", S390_FEAT_TYPE_STFL, 148, "Vector Enhancements facility 2"), + FEAT_INIT("esort-base", S390_FEAT_TYPE_STFL, 150, "Enhanced-sort facility (excluding subfunctions)"), + FEAT_INIT("deflate-base", S390_FEAT_TYPE_STFL, 151, "Deflate-conversion facility (excluding subfunctions)"), +- FEAT_INIT("vxbeh", S390_FEAT_TYPE_STFL, 152, "Vector BCD enhancements facility 1"), ++ FEAT_INIT("vxbeh", S390_FEAT_TYPE_STFL, 152, "Vector-Packed-Decimal-Enhancement Facility"), + FEAT_INIT("msa9-base", S390_FEAT_TYPE_STFL, 155, "Message-security-assist-extension-9 facility (excluding subfunctions)"), + FEAT_INIT("etoken", S390_FEAT_TYPE_STFL, 156, "Etoken facility"), + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390x-cpumodel-Rework-CPU-feature-definition.patch b/SOURCES/kvm-s390x-cpumodel-Rework-CPU-feature-definition.patch new file mode 100644 index 0000000..f1fbf6f --- /dev/null +++ b/SOURCES/kvm-s390x-cpumodel-Rework-CPU-feature-definition.patch @@ -0,0 +1,1168 @@ +From 7d9350b6ad9f0b5dcdd098092eb3760bdbcf9d54 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Wed, 18 Sep 2019 14:35:48 +0100 +Subject: [PATCH 09/22] s390x/cpumodel: Rework CPU feature definition + +RH-Author: Thomas Huth +Message-id: <20190918143549.16340-2-thuth@redhat.com> +Patchwork-id: 90759 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH 1/2] s390x/cpumodel: Rework CPU feature definition +Bugzilla: 1660909 +RH-Acked-by: David Hildenbrand +RH-Acked-by: Cornelia Huck +RH-Acked-by: Jens Freimann + +Let's define features at a single spot and make it less error prone to +define new features. + +Acked-by: Janosch Frank +Acked-by: Cornelia Huck +Signed-off-by: David Hildenbrand +(cherry picked from commit 220ae9002f33480fa30050140c852847677b3c06) +Signed-off-by: Danilo C. L. de Paula + +Conflicts: + The "vxpdeh" line needed adaption due to out-of-order backported commits: + + d05be57ddc2e1722f527aa4c20d84dfd15c840ec + s390: cpumodel: fix description for the new vector facility + + 0d4cb295db7503fbac2f5bb3e878a56630231fed + s390x/cpumodel: also change name of vxbeh + + 5d8866c89817998a3d9c3055d5dc2b5a8e78658a + s390x/cpumodel: change internal name of vxpdeh to match description + +Signed-off-by: Thomas Huth +Signed-off-by: Danilo C. L. de Paula +--- + target/s390x/cpu_features.c | 352 ++-------------------------------- + target/s390x/cpu_features_def.h | 352 +--------------------------------- + target/s390x/cpu_features_def.inc.h | 369 ++++++++++++++++++++++++++++++++++++ + 3 files changed, 386 insertions(+), 687 deletions(-) + create mode 100644 target/s390x/cpu_features_def.inc.h + +diff --git a/target/s390x/cpu_features.c b/target/s390x/cpu_features.c +index 065db76..9f817e3 100644 +--- a/target/s390x/cpu_features.c ++++ b/target/s390x/cpu_features.c +@@ -2,8 +2,9 @@ + * CPU features/facilities for s390x + * + * Copyright IBM Corp. 2016, 2018 ++ * Copyright Red Hat, Inc. 2019 + * +- * Author(s): David Hildenbrand ++ * Author(s): David Hildenbrand + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at + * your option) any later version. See the COPYING file in the top-level +@@ -14,346 +15,17 @@ + #include "qemu/module.h" + #include "cpu_features.h" + +-#define FEAT_INIT(_name, _type, _bit, _desc) \ +- { \ +- .name = _name, \ +- .type = _type, \ +- .bit = _bit, \ +- .desc = _desc, \ +- } +- +-/* S390FeatDef.bit is not applicable as there is no feature block. */ +-#define FEAT_INIT_MISC(_name, _desc) \ +- FEAT_INIT(_name, S390_FEAT_TYPE_MISC, 0, _desc) +- +-/* indexed by feature number for easy lookup */ +-static const S390FeatDef s390_features[] = { +- FEAT_INIT("esan3", S390_FEAT_TYPE_STFL, 0, "Instructions marked as n3"), +- FEAT_INIT("zarch", S390_FEAT_TYPE_STFL, 1, "z/Architecture architectural mode"), +- FEAT_INIT("dateh", S390_FEAT_TYPE_STFL, 3, "DAT-enhancement facility"), +- FEAT_INIT("idtes", S390_FEAT_TYPE_STFL, 4, "IDTE selective TLB segment-table clearing"), +- FEAT_INIT("idter", S390_FEAT_TYPE_STFL, 5, "IDTE selective TLB region-table clearing"), +- FEAT_INIT("asnlxr", S390_FEAT_TYPE_STFL, 6, "ASN-and-LX reuse facility"), +- FEAT_INIT("stfle", S390_FEAT_TYPE_STFL, 7, "Store-facility-list-extended facility"), +- FEAT_INIT("edat", S390_FEAT_TYPE_STFL, 8, "Enhanced-DAT facility"), +- FEAT_INIT("srs", S390_FEAT_TYPE_STFL, 9, "Sense-running-status facility"), +- FEAT_INIT("csske", S390_FEAT_TYPE_STFL, 10, "Conditional-SSKE facility"), +- FEAT_INIT("ctop", S390_FEAT_TYPE_STFL, 11, "Configuration-topology facility"), +- FEAT_INIT("apqci", S390_FEAT_TYPE_STFL, 12, "Query AP Configuration Information facility"), +- FEAT_INIT("ipter", S390_FEAT_TYPE_STFL, 13, "IPTE-range facility"), +- FEAT_INIT("nonqks", S390_FEAT_TYPE_STFL, 14, "Nonquiescing key-setting facility"), +- FEAT_INIT("apft", S390_FEAT_TYPE_STFL, 15, "AP Facilities Test facility"), +- FEAT_INIT("etf2", S390_FEAT_TYPE_STFL, 16, "Extended-translation facility 2"), +- FEAT_INIT("msa-base", S390_FEAT_TYPE_STFL, 17, "Message-security-assist facility (excluding subfunctions)"), +- FEAT_INIT("ldisp", S390_FEAT_TYPE_STFL, 18, "Long-displacement facility"), +- FEAT_INIT("ldisphp", S390_FEAT_TYPE_STFL, 19, "Long-displacement facility has high performance"), +- FEAT_INIT("hfpm", S390_FEAT_TYPE_STFL, 20, "HFP-multiply-add/subtract facility"), +- FEAT_INIT("eimm", S390_FEAT_TYPE_STFL, 21, "Extended-immediate facility"), +- FEAT_INIT("etf3", S390_FEAT_TYPE_STFL, 22, "Extended-translation facility 3"), +- FEAT_INIT("hfpue", S390_FEAT_TYPE_STFL, 23, "HFP-unnormalized-extension facility"), +- FEAT_INIT("etf2eh", S390_FEAT_TYPE_STFL, 24, "ETF2-enhancement facility"), +- FEAT_INIT("stckf", S390_FEAT_TYPE_STFL, 25, "Store-clock-fast facility"), +- FEAT_INIT("parseh", S390_FEAT_TYPE_STFL, 26, "Parsing-enhancement facility"), +- FEAT_INIT("mvcos", S390_FEAT_TYPE_STFL, 27, "Move-with-optional-specification facility"), +- FEAT_INIT("tods-base", S390_FEAT_TYPE_STFL, 28, "TOD-clock-steering facility (excluding subfunctions)"), +- FEAT_INIT("etf3eh", S390_FEAT_TYPE_STFL, 30, "ETF3-enhancement facility"), +- FEAT_INIT("ectg", S390_FEAT_TYPE_STFL, 31, "Extract-CPU-time facility"), +- FEAT_INIT("csst", S390_FEAT_TYPE_STFL, 32, "Compare-and-swap-and-store facility"), +- FEAT_INIT("csst2", S390_FEAT_TYPE_STFL, 33, "Compare-and-swap-and-store facility 2"), +- FEAT_INIT("ginste", S390_FEAT_TYPE_STFL, 34, "General-instructions-extension facility"), +- FEAT_INIT("exrl", S390_FEAT_TYPE_STFL, 35, "Execute-extensions facility"), +- FEAT_INIT("emon", S390_FEAT_TYPE_STFL, 36, "Enhanced-monitor facility"), +- FEAT_INIT("fpe", S390_FEAT_TYPE_STFL, 37, "Floating-point extension facility"), +- FEAT_INIT("opc", S390_FEAT_TYPE_STFL, 38, "Order Preserving Compression facility"), +- FEAT_INIT("sprogp", S390_FEAT_TYPE_STFL, 40, "Set-program-parameters facility"), +- FEAT_INIT("fpseh", S390_FEAT_TYPE_STFL, 41, "Floating-point-support-enhancement facilities"), +- FEAT_INIT("dfp", S390_FEAT_TYPE_STFL, 42, "DFP (decimal-floating-point) facility"), +- FEAT_INIT("dfphp", S390_FEAT_TYPE_STFL, 43, "DFP (decimal-floating-point) facility has high performance"), +- FEAT_INIT("pfpo", S390_FEAT_TYPE_STFL, 44, "PFPO instruction"), +- FEAT_INIT("stfle45", S390_FEAT_TYPE_STFL, 45, "Various facilities introduced with z196"), +- FEAT_INIT("cmpsceh", S390_FEAT_TYPE_STFL, 47, "CMPSC-enhancement facility"), +- FEAT_INIT("dfpzc", S390_FEAT_TYPE_STFL, 48, "Decimal-floating-point zoned-conversion facility"), +- FEAT_INIT("stfle49", S390_FEAT_TYPE_STFL, 49, "Various facilities introduced with zEC12"), +- FEAT_INIT("cte", S390_FEAT_TYPE_STFL, 50, "Constrained transactional-execution facility"), +- FEAT_INIT("ltlbc", S390_FEAT_TYPE_STFL, 51, "Local-TLB-clearing facility"), +- FEAT_INIT("iacc2", S390_FEAT_TYPE_STFL, 52, "Interlocked-access facility 2"), +- FEAT_INIT("stfle53", S390_FEAT_TYPE_STFL, 53, "Various facilities introduced with z13"), +- FEAT_INIT("eec", S390_FEAT_TYPE_STFL, 54, "Entropy encoding compression facility"), +- FEAT_INIT("msa5-base", S390_FEAT_TYPE_STFL, 57, "Message-security-assist-extension-5 facility (excluding subfunctions)"), +- FEAT_INIT("minste2", S390_FEAT_TYPE_STFL, 58, "Miscellaneous-instruction-extensions facility 2"), +- FEAT_INIT("sema", S390_FEAT_TYPE_STFL, 59, "Semaphore-assist facility"), +- FEAT_INIT("tsi", S390_FEAT_TYPE_STFL, 60, "Time-slice Instrumentation facility"), +- FEAT_INIT("minste3", S390_FEAT_TYPE_STFL, 61, "Miscellaneous-Instruction-Extensions Facility 3"), +- FEAT_INIT("ri", S390_FEAT_TYPE_STFL, 64, "CPU runtime-instrumentation facility"), +- FEAT_INIT("zpci", S390_FEAT_TYPE_STFL, 69, "z/PCI facility"), +- FEAT_INIT("aen", S390_FEAT_TYPE_STFL, 71, "General-purpose-adapter-event-notification facility"), +- FEAT_INIT("ais", S390_FEAT_TYPE_STFL, 72, "General-purpose-adapter-interruption-suppression facility"), +- FEAT_INIT("te", S390_FEAT_TYPE_STFL, 73, "Transactional-execution facility"), +- FEAT_INIT("sthyi", S390_FEAT_TYPE_STFL, 74, "Store-hypervisor-information facility"), +- FEAT_INIT("aefsi", S390_FEAT_TYPE_STFL, 75, "Access-exception-fetch/store-indication facility"), +- FEAT_INIT("msa3-base", S390_FEAT_TYPE_STFL, 76, "Message-security-assist-extension-3 facility (excluding subfunctions)"), +- FEAT_INIT("msa4-base", S390_FEAT_TYPE_STFL, 77, "Message-security-assist-extension-4 facility (excluding subfunctions)"), +- FEAT_INIT("edat2", S390_FEAT_TYPE_STFL, 78, "Enhanced-DAT facility 2"), +- FEAT_INIT("dfppc", S390_FEAT_TYPE_STFL, 80, "Decimal-floating-point packed-conversion facility"), +- FEAT_INIT("ppa15", S390_FEAT_TYPE_STFL, 81, "PPA15 is installed"), +- FEAT_INIT("bpb", S390_FEAT_TYPE_STFL, 82, "Branch prediction blocking"), +- FEAT_INIT("vx", S390_FEAT_TYPE_STFL, 129, "Vector facility"), +- FEAT_INIT("iep", S390_FEAT_TYPE_STFL, 130, "Instruction-execution-protection facility"), +- FEAT_INIT("sea_esop2", S390_FEAT_TYPE_STFL, 131, "Side-effect-access facility and Enhanced-suppression-on-protection facility 2"), +- FEAT_INIT("gs", S390_FEAT_TYPE_STFL, 133, "Guarded-storage facility"), +- FEAT_INIT("vxpd", S390_FEAT_TYPE_STFL, 134, "Vector packed decimal facility"), +- FEAT_INIT("vxeh", S390_FEAT_TYPE_STFL, 135, "Vector enhancements facility"), +- FEAT_INIT("mepoch", S390_FEAT_TYPE_STFL, 139, "Multiple-epoch facility"), +- FEAT_INIT("tpei", S390_FEAT_TYPE_STFL, 144, "Test-pending-external-interruption facility"), +- FEAT_INIT("irbm", S390_FEAT_TYPE_STFL, 145, "Insert-reference-bits-multiple facility"), +- FEAT_INIT("msa8-base", S390_FEAT_TYPE_STFL, 146, "Message-security-assist-extension-8 facility (excluding subfunctions)"), +- FEAT_INIT("cmmnt", S390_FEAT_TYPE_STFL, 147, "CMM: ESSA-enhancement (no translate) facility"), +- FEAT_INIT("vxeh2", S390_FEAT_TYPE_STFL, 148, "Vector Enhancements facility 2"), +- FEAT_INIT("esort-base", S390_FEAT_TYPE_STFL, 150, "Enhanced-sort facility (excluding subfunctions)"), +- FEAT_INIT("deflate-base", S390_FEAT_TYPE_STFL, 151, "Deflate-conversion facility (excluding subfunctions)"), +- FEAT_INIT("vxpdeh", S390_FEAT_TYPE_STFL, 152, "Vector-Packed-Decimal-Enhancement Facility"), +- FEAT_INIT("msa9-base", S390_FEAT_TYPE_STFL, 155, "Message-security-assist-extension-9 facility (excluding subfunctions)"), +- FEAT_INIT("etoken", S390_FEAT_TYPE_STFL, 156, "Etoken facility"), +- +- /* SCLP SCCB Byte 80 - 98 (bit numbers relative to byte-80) */ +- FEAT_INIT("gsls", S390_FEAT_TYPE_SCLP_CONF_CHAR, 40, "SIE: Guest-storage-limit-suppression facility"), +- FEAT_INIT("esop", S390_FEAT_TYPE_SCLP_CONF_CHAR, 46, "Enhanced-suppression-on-protection facility"), +- FEAT_INIT("hpma2", S390_FEAT_TYPE_SCLP_CONF_CHAR, 90, "Host page management assist 2 Facility"), /* 91-2 */ +- FEAT_INIT("kss", S390_FEAT_TYPE_SCLP_CONF_CHAR, 151, "SIE: Keyless-subset facility"), /* 98-7 */ +- +- /* SCLP SCCB Byte 116 - 119 (bit numbers relative to byte-116) */ +- FEAT_INIT("64bscao", S390_FEAT_TYPE_SCLP_CONF_CHAR_EXT, 0, "SIE: 64-bit-SCAO facility"), +- FEAT_INIT("cmma", S390_FEAT_TYPE_SCLP_CONF_CHAR_EXT, 1, "SIE: Collaborative-memory-management assist"), +- FEAT_INIT("pfmfi", S390_FEAT_TYPE_SCLP_CONF_CHAR_EXT, 9, "SIE: PFMF interpretation facility"), +- FEAT_INIT("ibs", S390_FEAT_TYPE_SCLP_CONF_CHAR_EXT, 10, "SIE: Interlock-and-broadcast-suppression facility"), +- +- FEAT_INIT("sief2", S390_FEAT_TYPE_SCLP_CPU, 4, "SIE: interception format 2 (Virtual SIE)"), +- FEAT_INIT("skey", S390_FEAT_TYPE_SCLP_CPU, 5, "SIE: Storage-key facility"), +- FEAT_INIT("gpereh", S390_FEAT_TYPE_SCLP_CPU, 10, "SIE: Guest-PER enhancement facility"), +- FEAT_INIT("siif", S390_FEAT_TYPE_SCLP_CPU, 11, "SIE: Shared IPTE-interlock facility"), +- FEAT_INIT("sigpif", S390_FEAT_TYPE_SCLP_CPU, 12, "SIE: SIGP interpretation facility"), +- FEAT_INIT("ib", S390_FEAT_TYPE_SCLP_CPU, 42, "SIE: Intervention bypass facility"), +- FEAT_INIT("cei", S390_FEAT_TYPE_SCLP_CPU, 43, "SIE: Conditional-external-interception facility"), +- +- FEAT_INIT_MISC("dateh2", "DAT-enhancement facility 2"), +- FEAT_INIT_MISC("cmm", "Collaborative-memory-management facility"), +- FEAT_INIT_MISC("ap", "AP instructions installed"), +- +- FEAT_INIT("plo-cl", S390_FEAT_TYPE_PLO, 0, "PLO Compare and load (32 bit in general registers)"), +- FEAT_INIT("plo-clg", S390_FEAT_TYPE_PLO, 1, "PLO Compare and load (64 bit in parameter list)"), +- FEAT_INIT("plo-clgr", S390_FEAT_TYPE_PLO, 2, "PLO Compare and load (32 bit in general registers)"), +- FEAT_INIT("plo-clx", S390_FEAT_TYPE_PLO, 3, "PLO Compare and load (128 bit in parameter list)"), +- FEAT_INIT("plo-cs", S390_FEAT_TYPE_PLO, 4, "PLO Compare and swap (32 bit in general registers)"), +- FEAT_INIT("plo-csg", S390_FEAT_TYPE_PLO, 5, "PLO Compare and swap (64 bit in parameter list)"), +- FEAT_INIT("plo-csgr", S390_FEAT_TYPE_PLO, 6, "PLO Compare and swap (32 bit in general registers)"), +- FEAT_INIT("plo-csx", S390_FEAT_TYPE_PLO, 7, "PLO Compare and swap (128 bit in parameter list)"), +- FEAT_INIT("plo-dcs", S390_FEAT_TYPE_PLO, 8, "PLO Double compare and swap (32 bit in general registers)"), +- FEAT_INIT("plo-dcsg", S390_FEAT_TYPE_PLO, 9, "PLO Double compare and swap (64 bit in parameter list)"), +- FEAT_INIT("plo-dcsgr", S390_FEAT_TYPE_PLO, 10, "PLO Double compare and swap (32 bit in general registers)"), +- FEAT_INIT("plo-dcsx", S390_FEAT_TYPE_PLO, 11, "PLO Double compare and swap (128 bit in parameter list)"), +- FEAT_INIT("plo-csst", S390_FEAT_TYPE_PLO, 12, "PLO Compare and swap and store (32 bit in general registers)"), +- FEAT_INIT("plo-csstg", S390_FEAT_TYPE_PLO, 13, "PLO Compare and swap and store (64 bit in parameter list)"), +- FEAT_INIT("plo-csstgr", S390_FEAT_TYPE_PLO, 14, "PLO Compare and swap and store (32 bit in general registers)"), +- FEAT_INIT("plo-csstx", S390_FEAT_TYPE_PLO, 15, "PLO Compare and swap and store (128 bit in parameter list)"), +- FEAT_INIT("plo-csdst", S390_FEAT_TYPE_PLO, 16, "PLO Compare and swap and double store (32 bit in general registers)"), +- FEAT_INIT("plo-csdstg", S390_FEAT_TYPE_PLO, 17, "PLO Compare and swap and double store (64 bit in parameter list)"), +- FEAT_INIT("plo-csdstgr", S390_FEAT_TYPE_PLO, 18, "PLO Compare and swap and double store (32 bit in general registers)"), +- FEAT_INIT("plo-csdstx", S390_FEAT_TYPE_PLO, 19, "PLO Compare and swap and double store (128 bit in parameter list)"), +- FEAT_INIT("plo-cstst", S390_FEAT_TYPE_PLO, 20, "PLO Compare and swap and triple store (32 bit in general registers)"), +- FEAT_INIT("plo-cststg", S390_FEAT_TYPE_PLO, 21, "PLO Compare and swap and triple store (64 bit in parameter list)"), +- FEAT_INIT("plo-cststgr", S390_FEAT_TYPE_PLO, 22, "PLO Compare and swap and triple store (32 bit in general registers)"), +- FEAT_INIT("plo-cststx", S390_FEAT_TYPE_PLO, 23, "PLO Compare and swap and triple store (128 bit in parameter list)"), +- +- FEAT_INIT("ptff-qto", S390_FEAT_TYPE_PTFF, 1, "PTFF Query TOD Offset"), +- FEAT_INIT("ptff-qsi", S390_FEAT_TYPE_PTFF, 2, "PTFF Query Steering Information"), +- FEAT_INIT("ptff-qpc", S390_FEAT_TYPE_PTFF, 3, "PTFF Query Physical Clock"), +- FEAT_INIT("ptff-qui", S390_FEAT_TYPE_PTFF, 4, "PTFF Query UTC Information"), +- FEAT_INIT("ptff-qtou", S390_FEAT_TYPE_PTFF, 5, "PTFF Query TOD Offset User"), +- FEAT_INIT("ptff-qsie", S390_FEAT_TYPE_PTFF, 10, "PTFF Query Steering Information Extended"), +- FEAT_INIT("ptff-qtoue", S390_FEAT_TYPE_PTFF, 13, "PTFF Query TOD Offset User Extended"), +- FEAT_INIT("ptff-sto", S390_FEAT_TYPE_PTFF, 65, "PTFF Set TOD Offset"), +- FEAT_INIT("ptff-stou", S390_FEAT_TYPE_PTFF, 69, "PTFF Set TOD Offset User"), +- FEAT_INIT("ptff-stoe", S390_FEAT_TYPE_PTFF, 73, "PTFF Set TOD Offset Extended"), +- FEAT_INIT("ptff-stoue", S390_FEAT_TYPE_PTFF, 77, "PTFF Set TOD Offset User Extended"), +- +- FEAT_INIT("kmac-dea", S390_FEAT_TYPE_KMAC, 1, "KMAC DEA"), +- FEAT_INIT("kmac-tdea-128", S390_FEAT_TYPE_KMAC, 2, "KMAC TDEA-128"), +- FEAT_INIT("kmac-tdea-192", S390_FEAT_TYPE_KMAC, 3, "KMAC TDEA-192"), +- FEAT_INIT("kmac-edea", S390_FEAT_TYPE_KMAC, 9, "KMAC Encrypted-DEA"), +- FEAT_INIT("kmac-etdea-128", S390_FEAT_TYPE_KMAC, 10, "KMAC Encrypted-TDEA-128"), +- FEAT_INIT("kmac-etdea-192", S390_FEAT_TYPE_KMAC, 11, "KMAC Encrypted-TDEA-192"), +- FEAT_INIT("kmac-aes-128", S390_FEAT_TYPE_KMAC, 18, "KMAC AES-128"), +- FEAT_INIT("kmac-aes-192", S390_FEAT_TYPE_KMAC, 19, "KMAC AES-192"), +- FEAT_INIT("kmac-aes-256", S390_FEAT_TYPE_KMAC, 20, "KMAC AES-256"), +- FEAT_INIT("kmac-eaes-128", S390_FEAT_TYPE_KMAC, 26, "KMAC Encrypted-AES-128"), +- FEAT_INIT("kmac-eaes-192", S390_FEAT_TYPE_KMAC, 27, "KMAC Encrypted-AES-192"), +- FEAT_INIT("kmac-eaes-256", S390_FEAT_TYPE_KMAC, 28, "KMAC Encrypted-AES-256"), +- +- FEAT_INIT("kmc-dea", S390_FEAT_TYPE_KMC, 1, "KMC DEA"), +- FEAT_INIT("kmc-tdea-128", S390_FEAT_TYPE_KMC, 2, "KMC TDEA-128"), +- FEAT_INIT("kmc-tdea-192", S390_FEAT_TYPE_KMC, 3, "KMC TDEA-192"), +- FEAT_INIT("kmc-edea", S390_FEAT_TYPE_KMC, 9, "KMC Encrypted-DEA"), +- FEAT_INIT("kmc-etdea-128", S390_FEAT_TYPE_KMC, 10, "KMC Encrypted-TDEA-128"), +- FEAT_INIT("kmc-etdea-192", S390_FEAT_TYPE_KMC, 11, "KMC Encrypted-TDEA-192"), +- FEAT_INIT("kmc-aes-128", S390_FEAT_TYPE_KMC, 18, "KMC AES-128"), +- FEAT_INIT("kmc-aes-192", S390_FEAT_TYPE_KMC, 19, "KMC AES-192"), +- FEAT_INIT("kmc-aes-256", S390_FEAT_TYPE_KMC, 20, "KMC AES-256"), +- FEAT_INIT("kmc-eaes-128", S390_FEAT_TYPE_KMC, 26, "KMC Encrypted-AES-128"), +- FEAT_INIT("kmc-eaes-192", S390_FEAT_TYPE_KMC, 27, "KMC Encrypted-AES-192"), +- FEAT_INIT("kmc-eaes-256", S390_FEAT_TYPE_KMC, 28, "KMC Encrypted-AES-256"), +- FEAT_INIT("kmc-prng", S390_FEAT_TYPE_KMC, 67, "KMC PRNG"), +- +- FEAT_INIT("km-dea", S390_FEAT_TYPE_KM, 1, "KM DEA"), +- FEAT_INIT("km-tdea-128", S390_FEAT_TYPE_KM, 2, "KM TDEA-128"), +- FEAT_INIT("km-tdea-192", S390_FEAT_TYPE_KM, 3, "KM TDEA-192"), +- FEAT_INIT("km-edea", S390_FEAT_TYPE_KM, 9, "KM Encrypted-DEA"), +- FEAT_INIT("km-etdea-128", S390_FEAT_TYPE_KM, 10, "KM Encrypted-TDEA-128"), +- FEAT_INIT("km-etdea-192", S390_FEAT_TYPE_KM, 11, "KM Encrypted-TDEA-192"), +- FEAT_INIT("km-aes-128", S390_FEAT_TYPE_KM, 18, "KM AES-128"), +- FEAT_INIT("km-aes-192", S390_FEAT_TYPE_KM, 19, "KM AES-192"), +- FEAT_INIT("km-aes-256", S390_FEAT_TYPE_KM, 20, "KM AES-256"), +- FEAT_INIT("km-eaes-128", S390_FEAT_TYPE_KM, 26, "KM Encrypted-AES-128"), +- FEAT_INIT("km-eaes-192", S390_FEAT_TYPE_KM, 27, "KM Encrypted-AES-192"), +- FEAT_INIT("km-eaes-256", S390_FEAT_TYPE_KM, 28, "KM Encrypted-AES-256"), +- FEAT_INIT("km-xts-aes-128", S390_FEAT_TYPE_KM, 50, "KM XTS-AES-128"), +- FEAT_INIT("km-xts-aes-256", S390_FEAT_TYPE_KM, 52, "KM XTS-AES-256"), +- FEAT_INIT("km-xts-eaes-128", S390_FEAT_TYPE_KM, 58, "KM XTS-Encrypted-AES-128"), +- FEAT_INIT("km-xts-eaes-256", S390_FEAT_TYPE_KM, 60, "KM XTS-Encrypted-AES-256"), +- +- FEAT_INIT("kimd-sha-1", S390_FEAT_TYPE_KIMD, 1, "KIMD SHA-1"), +- FEAT_INIT("kimd-sha-256", S390_FEAT_TYPE_KIMD, 2, "KIMD SHA-256"), +- FEAT_INIT("kimd-sha-512", S390_FEAT_TYPE_KIMD, 3, "KIMD SHA-512"), +- FEAT_INIT("kimd-sha3-224", S390_FEAT_TYPE_KIMD, 32, "KIMD SHA3-224"), +- FEAT_INIT("kimd-sha3-256", S390_FEAT_TYPE_KIMD, 33, "KIMD SHA3-256"), +- FEAT_INIT("kimd-sha3-384", S390_FEAT_TYPE_KIMD, 34, "KIMD SHA3-384"), +- FEAT_INIT("kimd-sha3-512", S390_FEAT_TYPE_KIMD, 35, "KIMD SHA3-512"), +- FEAT_INIT("kimd-shake-128", S390_FEAT_TYPE_KIMD, 36, "KIMD SHAKE-128"), +- FEAT_INIT("kimd-shake-256", S390_FEAT_TYPE_KIMD, 37, "KIMD SHAKE-256"), +- FEAT_INIT("kimd-ghash", S390_FEAT_TYPE_KIMD, 65, "KIMD GHASH"), +- +- FEAT_INIT("klmd-sha-1", S390_FEAT_TYPE_KLMD, 1, "KLMD SHA-1"), +- FEAT_INIT("klmd-sha-256", S390_FEAT_TYPE_KLMD, 2, "KLMD SHA-256"), +- FEAT_INIT("klmd-sha-512", S390_FEAT_TYPE_KLMD, 3, "KLMD SHA-512"), +- FEAT_INIT("klmd-sha3-224", S390_FEAT_TYPE_KLMD, 32, "KLMD SHA3-224"), +- FEAT_INIT("klmd-sha3-256", S390_FEAT_TYPE_KLMD, 33, "KLMD SHA3-256"), +- FEAT_INIT("klmd-sha3-384", S390_FEAT_TYPE_KLMD, 34, "KLMD SHA3-384"), +- FEAT_INIT("klmd-sha3-512", S390_FEAT_TYPE_KLMD, 35, "KLMD SHA3-512"), +- FEAT_INIT("klmd-shake-128", S390_FEAT_TYPE_KLMD, 36, "KLMD SHAKE-128"), +- FEAT_INIT("klmd-shake-256", S390_FEAT_TYPE_KLMD, 37, "KLMD SHAKE-256"), +- +- FEAT_INIT("pckmo-edea", S390_FEAT_TYPE_PCKMO, 1, "PCKMO Encrypted-DEA-Key"), +- FEAT_INIT("pckmo-etdea-128", S390_FEAT_TYPE_PCKMO, 2, "PCKMO Encrypted-TDEA-128-Key"), +- FEAT_INIT("pckmo-etdea-192", S390_FEAT_TYPE_PCKMO, 3, "PCKMO Encrypted-TDEA-192-Key"), +- FEAT_INIT("pckmo-aes-128", S390_FEAT_TYPE_PCKMO, 18, "PCKMO Encrypted-AES-128-Key"), +- FEAT_INIT("pckmo-aes-192", S390_FEAT_TYPE_PCKMO, 19, "PCKMO Encrypted-AES-192-Key"), +- FEAT_INIT("pckmo-aes-256", S390_FEAT_TYPE_PCKMO, 20, "PCKMO Encrypted-AES-256-Key"), +- FEAT_INIT("pckmo-ecc-p256", S390_FEAT_TYPE_PCKMO, 32, "PCKMO Encrypt-ECC-P256-Key"), +- FEAT_INIT("pckmo-ecc-p384", S390_FEAT_TYPE_PCKMO, 33, "PCKMO Encrypt-ECC-P384-Key"), +- FEAT_INIT("pckmo-ecc-p521", S390_FEAT_TYPE_PCKMO, 34, "PCKMO Encrypt-ECC-P521-Key"), +- FEAT_INIT("pckmo-ecc-ed25519", S390_FEAT_TYPE_PCKMO, 40 , "PCKMO Encrypt-ECC-Ed25519-Key"), +- FEAT_INIT("pckmo-ecc-ed448", S390_FEAT_TYPE_PCKMO, 41 , "PCKMO Encrypt-ECC-Ed448-Key"), +- +- FEAT_INIT("kmctr-dea", S390_FEAT_TYPE_KMCTR, 1, "KMCTR DEA"), +- FEAT_INIT("kmctr-tdea-128", S390_FEAT_TYPE_KMCTR, 2, "KMCTR TDEA-128"), +- FEAT_INIT("kmctr-tdea-192", S390_FEAT_TYPE_KMCTR, 3, "KMCTR TDEA-192"), +- FEAT_INIT("kmctr-edea", S390_FEAT_TYPE_KMCTR, 9, "KMCTR Encrypted-DEA"), +- FEAT_INIT("kmctr-etdea-128", S390_FEAT_TYPE_KMCTR, 10, "KMCTR Encrypted-TDEA-128"), +- FEAT_INIT("kmctr-etdea-192", S390_FEAT_TYPE_KMCTR, 11, "KMCTR Encrypted-TDEA-192"), +- FEAT_INIT("kmctr-aes-128", S390_FEAT_TYPE_KMCTR, 18, "KMCTR AES-128"), +- FEAT_INIT("kmctr-aes-192", S390_FEAT_TYPE_KMCTR, 19, "KMCTR AES-192"), +- FEAT_INIT("kmctr-aes-256", S390_FEAT_TYPE_KMCTR, 20, "KMCTR AES-256"), +- FEAT_INIT("kmctr-eaes-128", S390_FEAT_TYPE_KMCTR, 26, "KMCTR Encrypted-AES-128"), +- FEAT_INIT("kmctr-eaes-192", S390_FEAT_TYPE_KMCTR, 27, "KMCTR Encrypted-AES-192"), +- FEAT_INIT("kmctr-eaes-256", S390_FEAT_TYPE_KMCTR, 28, "KMCTR Encrypted-AES-256"), +- +- FEAT_INIT("kmf-dea", S390_FEAT_TYPE_KMF, 1, "KMF DEA"), +- FEAT_INIT("kmf-tdea-128", S390_FEAT_TYPE_KMF, 2, "KMF TDEA-128"), +- FEAT_INIT("kmf-tdea-192", S390_FEAT_TYPE_KMF, 3, "KMF TDEA-192"), +- FEAT_INIT("kmf-edea", S390_FEAT_TYPE_KMF, 9, "KMF Encrypted-DEA"), +- FEAT_INIT("kmf-etdea-128", S390_FEAT_TYPE_KMF, 10, "KMF Encrypted-TDEA-128"), +- FEAT_INIT("kmf-etdea-192", S390_FEAT_TYPE_KMF, 11, "KMF Encrypted-TDEA-192"), +- FEAT_INIT("kmf-aes-128", S390_FEAT_TYPE_KMF, 18, "KMF AES-128"), +- FEAT_INIT("kmf-aes-192", S390_FEAT_TYPE_KMF, 19, "KMF AES-192"), +- FEAT_INIT("kmf-aes-256", S390_FEAT_TYPE_KMF, 20, "KMF AES-256"), +- FEAT_INIT("kmf-eaes-128", S390_FEAT_TYPE_KMF, 26, "KMF Encrypted-AES-128"), +- FEAT_INIT("kmf-eaes-192", S390_FEAT_TYPE_KMF, 27, "KMF Encrypted-AES-192"), +- FEAT_INIT("kmf-eaes-256", S390_FEAT_TYPE_KMF, 28, "KMF Encrypted-AES-256"), +- +- FEAT_INIT("kmo-dea", S390_FEAT_TYPE_KMO, 1, "KMO DEA"), +- FEAT_INIT("kmo-tdea-128", S390_FEAT_TYPE_KMO, 2, "KMO TDEA-128"), +- FEAT_INIT("kmo-tdea-192", S390_FEAT_TYPE_KMO, 3, "KMO TDEA-192"), +- FEAT_INIT("kmo-edea", S390_FEAT_TYPE_KMO, 9, "KMO Encrypted-DEA"), +- FEAT_INIT("kmo-etdea-128", S390_FEAT_TYPE_KMO, 10, "KMO Encrypted-TDEA-128"), +- FEAT_INIT("kmo-etdea-192", S390_FEAT_TYPE_KMO, 11, "KMO Encrypted-TDEA-192"), +- FEAT_INIT("kmo-aes-128", S390_FEAT_TYPE_KMO, 18, "KMO AES-128"), +- FEAT_INIT("kmo-aes-192", S390_FEAT_TYPE_KMO, 19, "KMO AES-192"), +- FEAT_INIT("kmo-aes-256", S390_FEAT_TYPE_KMO, 20, "KMO AES-256"), +- FEAT_INIT("kmo-eaes-128", S390_FEAT_TYPE_KMO, 26, "KMO Encrypted-AES-128"), +- FEAT_INIT("kmo-eaes-192", S390_FEAT_TYPE_KMO, 27, "KMO Encrypted-AES-192"), +- FEAT_INIT("kmo-eaes-256", S390_FEAT_TYPE_KMO, 28, "KMO Encrypted-AES-256"), +- +- FEAT_INIT("pcc-cmac-dea", S390_FEAT_TYPE_PCC, 1, "PCC Compute-Last-Block-CMAC-Using-DEA"), +- FEAT_INIT("pcc-cmac-tdea-128", S390_FEAT_TYPE_PCC, 2, "PCC Compute-Last-Block-CMAC-Using-TDEA-128"), +- FEAT_INIT("pcc-cmac-tdea-192", S390_FEAT_TYPE_PCC, 3, "PCC Compute-Last-Block-CMAC-Using-TDEA-192"), +- FEAT_INIT("pcc-cmac-edea", S390_FEAT_TYPE_PCC, 9, "PCC Compute-Last-Block-CMAC-Using-Encrypted-DEA"), +- FEAT_INIT("pcc-cmac-etdea-128", S390_FEAT_TYPE_PCC, 10, "PCC Compute-Last-Block-CMAC-Using-Encrypted-TDEA-128"), +- FEAT_INIT("pcc-cmac-etdea-192", S390_FEAT_TYPE_PCC, 11, "PCC Compute-Last-Block-CMAC-Using-EncryptedTDEA-192"), +- FEAT_INIT("pcc-cmac-aes-128", S390_FEAT_TYPE_PCC, 18, "PCC Compute-Last-Block-CMAC-Using-AES-128"), +- FEAT_INIT("pcc-cmac-aes-192", S390_FEAT_TYPE_PCC, 19, "PCC Compute-Last-Block-CMAC-Using-AES-192"), +- FEAT_INIT("pcc-cmac-eaes-256", S390_FEAT_TYPE_PCC, 20, "PCC Compute-Last-Block-CMAC-Using-AES-256"), +- FEAT_INIT("pcc-cmac-eaes-128", S390_FEAT_TYPE_PCC, 26, "PCC Compute-Last-Block-CMAC-Using-Encrypted-AES-128"), +- FEAT_INIT("pcc-cmac-eaes-192", S390_FEAT_TYPE_PCC, 27, "PCC Compute-Last-Block-CMAC-Using-Encrypted-AES-192"), +- FEAT_INIT("pcc-cmac-eaes-256", S390_FEAT_TYPE_PCC, 28, "PCC Compute-Last-Block-CMAC-Using-Encrypted-AES-256"), +- FEAT_INIT("pcc-xts-aes-128", S390_FEAT_TYPE_PCC, 50, "PCC Compute-XTS-Parameter-Using-AES-128"), +- FEAT_INIT("pcc-xts-aes-256", S390_FEAT_TYPE_PCC, 52, "PCC Compute-XTS-Parameter-Using-AES-256"), +- FEAT_INIT("pcc-xts-eaes-128", S390_FEAT_TYPE_PCC, 58, "PCC Compute-XTS-Parameter-Using-Encrypted-AES-128"), +- FEAT_INIT("pcc-xts-eaes-256", S390_FEAT_TYPE_PCC, 60, "PCC Compute-XTS-Parameter-Using-Encrypted-AES-256"), +- FEAT_INIT("pcc-scalar-mult-p256", S390_FEAT_TYPE_PCC, 64, "PCC Scalar-Multiply-P256"), +- FEAT_INIT("pcc-scalar-mult-p384", S390_FEAT_TYPE_PCC, 65, "PCC Scalar-Multiply-P384"), +- FEAT_INIT("pcc-scalar-mult-p521", S390_FEAT_TYPE_PCC, 66, "PCC Scalar-Multiply-P521"), +- FEAT_INIT("pcc-scalar-mult-ed25519", S390_FEAT_TYPE_PCC, 72, "PCC Scalar-Multiply-Ed25519"), +- FEAT_INIT("pcc-scalar-mult-ed448", S390_FEAT_TYPE_PCC, 73, "PCC Scalar-Multiply-Ed448"), +- FEAT_INIT("pcc-scalar-mult-x25519", S390_FEAT_TYPE_PCC, 80, "PCC Scalar-Multiply-X25519"), +- FEAT_INIT("pcc-scalar-mult-x448", S390_FEAT_TYPE_PCC, 81, "PCC Scalar-Multiply-X448"), +- +- FEAT_INIT("ppno-sha-512-drng", S390_FEAT_TYPE_PPNO, 3, "PPNO SHA-512-DRNG"), +- FEAT_INIT("prno-trng-qrtcr", S390_FEAT_TYPE_PPNO, 112, "PRNO TRNG-Query-Raw-to-Conditioned-Ratio"), +- FEAT_INIT("prno-trng", S390_FEAT_TYPE_PPNO, 114, "PRNO TRNG"), +- +- FEAT_INIT("kma-gcm-aes-128", S390_FEAT_TYPE_KMA, 18, "KMA GCM-AES-128"), +- FEAT_INIT("kma-gcm-aes-192", S390_FEAT_TYPE_KMA, 19, "KMA GCM-AES-192"), +- FEAT_INIT("kma-gcm-aes-256", S390_FEAT_TYPE_KMA, 20, "KMA GCM-AES-256"), +- FEAT_INIT("kma-gcm-eaes-128", S390_FEAT_TYPE_KMA, 26, "KMA GCM-Encrypted-AES-128"), +- FEAT_INIT("kma-gcm-eaes-192", S390_FEAT_TYPE_KMA, 27, "KMA GCM-Encrypted-AES-192"), +- FEAT_INIT("kma-gcm-eaes-256", S390_FEAT_TYPE_KMA, 28, "KMA GCM-Encrypted-AES-256"), +- +- FEAT_INIT("kdsa-ecdsa-verify-p256", S390_FEAT_TYPE_KDSA, 1, "KDSA ECDSA-Verify-P256"), +- FEAT_INIT("kdsa-ecdsa-verify-p384", S390_FEAT_TYPE_KDSA, 2, "KDSA ECDSA-Verify-P384"), +- FEAT_INIT("kdsa-ecdsa-verify-p521", S390_FEAT_TYPE_KDSA, 3, "KDSA ECDSA-Verify-P521"), +- FEAT_INIT("kdsa-ecdsa-sign-p256", S390_FEAT_TYPE_KDSA, 9, "KDSA ECDSA-Sign-P256"), +- FEAT_INIT("kdsa-ecdsa-sign-p384", S390_FEAT_TYPE_KDSA, 10, "KDSA ECDSA-Sign-P384"), +- FEAT_INIT("kdsa-ecdsa-sign-p521", S390_FEAT_TYPE_KDSA, 11, "KDSA ECDSA-Sign-P521"), +- FEAT_INIT("kdsa-eecdsa-sign-p256", S390_FEAT_TYPE_KDSA, 17, "KDSA Encrypted-ECDSA-Sign-P256"), +- FEAT_INIT("kdsa-eecdsa-sign-p384", S390_FEAT_TYPE_KDSA, 18, "KDSA Encrypted-ECDSA-Sign-P384"), +- FEAT_INIT("kdsa-eecdsa-sign-p521", S390_FEAT_TYPE_KDSA, 19, "KDSA Encrypted-ECDSA-Sign-P521"), +- FEAT_INIT("kdsa-eddsa-verify-ed25519", S390_FEAT_TYPE_KDSA, 32, "KDSA EdDSA-Verify-Ed25519"), +- FEAT_INIT("kdsa-eddsa-verify-ed448", S390_FEAT_TYPE_KDSA, 36, "KDSA EdDSA-Verify-Ed448"), +- FEAT_INIT("kdsa-eddsa-sign-ed25519", S390_FEAT_TYPE_KDSA, 40, "KDSA EdDSA-Sign-Ed25519"), +- FEAT_INIT("kdsa-eddsa-sign-ed448", S390_FEAT_TYPE_KDSA, 44, "KDSA EdDSA-Sign-Ed448"), +- FEAT_INIT("kdsa-eeddsa-sign-ed25519", S390_FEAT_TYPE_KDSA, 48, "KDSA Encrypted-EdDSA-Sign-Ed25519"), +- FEAT_INIT("kdsa-eeddsa-sign-ed448", S390_FEAT_TYPE_KDSA, 52, "KDSA Encrypted-EdDSA-Sign-Ed448"), +- +- FEAT_INIT("sortl-sflr", S390_FEAT_TYPE_SORTL, 1, "SORTL SFLR"), +- FEAT_INIT("sortl-svlr", S390_FEAT_TYPE_SORTL, 2, "SORTL SVLR"), +- FEAT_INIT("sortl-32", S390_FEAT_TYPE_SORTL, 130, "SORTL 32 input lists"), +- FEAT_INIT("sortl-128", S390_FEAT_TYPE_SORTL, 132, "SORTL 128 input lists"), +- FEAT_INIT("sortl-f0", S390_FEAT_TYPE_SORTL, 192, "SORTL format 0 parameter-block"), +- +- FEAT_INIT("dfltcc-gdht", S390_FEAT_TYPE_DFLTCC, 1, "DFLTCC GDHT"), +- FEAT_INIT("dfltcc-cmpr", S390_FEAT_TYPE_DFLTCC, 2, "DFLTCC CMPR"), +- FEAT_INIT("dfltcc-xpnd", S390_FEAT_TYPE_DFLTCC, 4, "DFLTCC XPND"), +- FEAT_INIT("dfltcc-f0", S390_FEAT_TYPE_DFLTCC, 192, "DFLTCC format 0 parameter-block"), ++#define DEF_FEAT(_FEAT, _NAME, _TYPE, _BIT, _DESC) \ ++ [S390_FEAT_##_FEAT] = { \ ++ .name = _NAME, \ ++ .type = S390_FEAT_TYPE_##_TYPE, \ ++ .bit = _BIT, \ ++ .desc = _DESC, \ ++ }, ++static const S390FeatDef s390_features[S390_FEAT_MAX] = { ++ #include "cpu_features_def.inc.h" + }; ++#undef DEF_FEAT + + const S390FeatDef *s390_feat_def(S390Feat feat) + { +diff --git a/target/s390x/cpu_features_def.h b/target/s390x/cpu_features_def.h +index a7abe4d..412d356 100644 +--- a/target/s390x/cpu_features_def.h ++++ b/target/s390x/cpu_features_def.h +@@ -2,9 +2,10 @@ + * CPU features/facilities for s390 + * + * Copyright IBM Corp. 2016, 2018 ++ * Copyright Red Hat, Inc. 2019 + * + * Author(s): Michael Mueller +- * David Hildenbrand ++ * David Hildenbrand + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at + * your option) any later version. See the COPYING file in the top-level +@@ -14,354 +15,11 @@ + #ifndef TARGET_S390X_CPU_FEATURES_DEF_H + #define TARGET_S390X_CPU_FEATURES_DEF_H + ++#define DEF_FEAT(_FEAT, ...) S390_FEAT_##_FEAT, + typedef enum { +- /* Stfle */ +- S390_FEAT_ESAN3 = 0, +- S390_FEAT_ZARCH, +- S390_FEAT_DAT_ENH, +- S390_FEAT_IDTE_SEGMENT, +- S390_FEAT_IDTE_REGION, +- S390_FEAT_ASN_LX_REUSE, +- S390_FEAT_STFLE, +- S390_FEAT_EDAT, +- S390_FEAT_SENSE_RUNNING_STATUS, +- S390_FEAT_CONDITIONAL_SSKE, +- S390_FEAT_CONFIGURATION_TOPOLOGY, +- S390_FEAT_AP_QUERY_CONFIG_INFO, +- S390_FEAT_IPTE_RANGE, +- S390_FEAT_NONQ_KEY_SETTING, +- S390_FEAT_AP_FACILITIES_TEST, +- S390_FEAT_EXTENDED_TRANSLATION_2, +- S390_FEAT_MSA, +- S390_FEAT_LONG_DISPLACEMENT, +- S390_FEAT_LONG_DISPLACEMENT_FAST, +- S390_FEAT_HFP_MADDSUB, +- S390_FEAT_EXTENDED_IMMEDIATE, +- S390_FEAT_EXTENDED_TRANSLATION_3, +- S390_FEAT_HFP_UNNORMALIZED_EXT, +- S390_FEAT_ETF2_ENH, +- S390_FEAT_STORE_CLOCK_FAST, +- S390_FEAT_PARSING_ENH, +- S390_FEAT_MOVE_WITH_OPTIONAL_SPEC, +- S390_FEAT_TOD_CLOCK_STEERING, +- S390_FEAT_ETF3_ENH, +- S390_FEAT_EXTRACT_CPU_TIME, +- S390_FEAT_COMPARE_AND_SWAP_AND_STORE, +- S390_FEAT_COMPARE_AND_SWAP_AND_STORE_2, +- S390_FEAT_GENERAL_INSTRUCTIONS_EXT, +- S390_FEAT_EXECUTE_EXT, +- S390_FEAT_ENHANCED_MONITOR, +- S390_FEAT_FLOATING_POINT_EXT, +- S390_FEAT_ORDER_PRESERVING_COMPRESSION, +- S390_FEAT_SET_PROGRAM_PARAMETERS, +- S390_FEAT_FLOATING_POINT_SUPPPORT_ENH, +- S390_FEAT_DFP, +- S390_FEAT_DFP_FAST, +- S390_FEAT_PFPO, +- S390_FEAT_STFLE_45, +- S390_FEAT_CMPSC_ENH, +- S390_FEAT_DFP_ZONED_CONVERSION, +- S390_FEAT_STFLE_49, +- S390_FEAT_CONSTRAINT_TRANSACTIONAL_EXE, +- S390_FEAT_LOCAL_TLB_CLEARING, +- S390_FEAT_INTERLOCKED_ACCESS_2, +- S390_FEAT_STFLE_53, +- S390_FEAT_ENTROPY_ENC_COMP, +- S390_FEAT_MSA_EXT_5, +- S390_FEAT_MISC_INSTRUCTION_EXT, +- S390_FEAT_SEMAPHORE_ASSIST, +- S390_FEAT_TIME_SLICE_INSTRUMENTATION, +- S390_FEAT_MISC_INSTRUCTION_EXT3, +- S390_FEAT_RUNTIME_INSTRUMENTATION, +- S390_FEAT_ZPCI, +- S390_FEAT_ADAPTER_EVENT_NOTIFICATION, +- S390_FEAT_ADAPTER_INT_SUPPRESSION, +- S390_FEAT_TRANSACTIONAL_EXE, +- S390_FEAT_STORE_HYPERVISOR_INFO, +- S390_FEAT_ACCESS_EXCEPTION_FS_INDICATION, +- S390_FEAT_MSA_EXT_3, +- S390_FEAT_MSA_EXT_4, +- S390_FEAT_EDAT_2, +- S390_FEAT_DFP_PACKED_CONVERSION, +- S390_FEAT_PPA15, +- S390_FEAT_BPB, +- S390_FEAT_VECTOR, +- S390_FEAT_INSTRUCTION_EXEC_PROT, +- S390_FEAT_SIDE_EFFECT_ACCESS_ESOP2, +- S390_FEAT_GUARDED_STORAGE, +- S390_FEAT_VECTOR_PACKED_DECIMAL, +- S390_FEAT_VECTOR_ENH, +- S390_FEAT_MULTIPLE_EPOCH, +- S390_FEAT_TEST_PENDING_EXT_INTERRUPTION, +- S390_FEAT_INSERT_REFERENCE_BITS_MULT, +- S390_FEAT_MSA_EXT_8, +- S390_FEAT_CMM_NT, +- S390_FEAT_VECTOR_ENH2, +- S390_FEAT_ESORT_BASE, +- S390_FEAT_DEFLATE_BASE, +- S390_FEAT_VECTOR_PACKED_DECIMAL_ENH, +- S390_FEAT_MSA_EXT_9, +- S390_FEAT_ETOKEN, +- +- /* Sclp Conf Char */ +- S390_FEAT_SIE_GSLS, +- S390_FEAT_ESOP, +- S390_FEAT_HPMA2, +- S390_FEAT_SIE_KSS, +- +- /* Sclp Conf Char Ext */ +- S390_FEAT_SIE_64BSCAO, +- S390_FEAT_SIE_CMMA, +- S390_FEAT_SIE_PFMFI, +- S390_FEAT_SIE_IBS, +- +- /* Sclp Cpu */ +- S390_FEAT_SIE_F2, +- S390_FEAT_SIE_SKEY, +- S390_FEAT_SIE_GPERE, +- S390_FEAT_SIE_SIIF, +- S390_FEAT_SIE_SIGPIF, +- S390_FEAT_SIE_IB, +- S390_FEAT_SIE_CEI, +- +- /* Misc */ +- S390_FEAT_DAT_ENH_2, +- S390_FEAT_CMM, +- S390_FEAT_AP, +- +- /* PLO */ +- S390_FEAT_PLO_CL, +- S390_FEAT_PLO_CLG, +- S390_FEAT_PLO_CLGR, +- S390_FEAT_PLO_CLX, +- S390_FEAT_PLO_CS, +- S390_FEAT_PLO_CSG, +- S390_FEAT_PLO_CSGR, +- S390_FEAT_PLO_CSX, +- S390_FEAT_PLO_DCS, +- S390_FEAT_PLO_DCSG, +- S390_FEAT_PLO_DCSGR, +- S390_FEAT_PLO_DCSX, +- S390_FEAT_PLO_CSST, +- S390_FEAT_PLO_CSSTG, +- S390_FEAT_PLO_CSSTGR, +- S390_FEAT_PLO_CSSTX, +- S390_FEAT_PLO_CSDST, +- S390_FEAT_PLO_CSDSTG, +- S390_FEAT_PLO_CSDSTGR, +- S390_FEAT_PLO_CSDSTX, +- S390_FEAT_PLO_CSTST, +- S390_FEAT_PLO_CSTSTG, +- S390_FEAT_PLO_CSTSTGR, +- S390_FEAT_PLO_CSTSTX, +- +- /* PTFF */ +- S390_FEAT_PTFF_QTO, +- S390_FEAT_PTFF_QSI, +- S390_FEAT_PTFF_QPT, +- S390_FEAT_PTFF_QUI, +- S390_FEAT_PTFF_QTOU, +- S390_FEAT_PTFF_QSIE, +- S390_FEAT_PTFF_QTOUE, +- S390_FEAT_PTFF_STO, +- S390_FEAT_PTFF_STOU, +- S390_FEAT_PTFF_STOE, +- S390_FEAT_PTFF_STOUE, +- +- /* KMAC */ +- S390_FEAT_KMAC_DEA, +- S390_FEAT_KMAC_TDEA_128, +- S390_FEAT_KMAC_TDEA_192, +- S390_FEAT_KMAC_EDEA, +- S390_FEAT_KMAC_ETDEA_128, +- S390_FEAT_KMAC_ETDEA_192, +- S390_FEAT_KMAC_AES_128, +- S390_FEAT_KMAC_AES_192, +- S390_FEAT_KMAC_AES_256, +- S390_FEAT_KMAC_EAES_128, +- S390_FEAT_KMAC_EAES_192, +- S390_FEAT_KMAC_EAES_256, +- +- /* KMC */ +- S390_FEAT_KMC_DEA, +- S390_FEAT_KMC_TDEA_128, +- S390_FEAT_KMC_TDEA_192, +- S390_FEAT_KMC_EDEA, +- S390_FEAT_KMC_ETDEA_128, +- S390_FEAT_KMC_ETDEA_192, +- S390_FEAT_KMC_AES_128, +- S390_FEAT_KMC_AES_192, +- S390_FEAT_KMC_AES_256, +- S390_FEAT_KMC_EAES_128, +- S390_FEAT_KMC_EAES_192, +- S390_FEAT_KMC_EAES_256, +- S390_FEAT_KMC_PRNG, +- +- /* KM */ +- S390_FEAT_KM_DEA, +- S390_FEAT_KM_TDEA_128, +- S390_FEAT_KM_TDEA_192, +- S390_FEAT_KM_EDEA, +- S390_FEAT_KM_ETDEA_128, +- S390_FEAT_KM_ETDEA_192, +- S390_FEAT_KM_AES_128, +- S390_FEAT_KM_AES_192, +- S390_FEAT_KM_AES_256, +- S390_FEAT_KM_EAES_128, +- S390_FEAT_KM_EAES_192, +- S390_FEAT_KM_EAES_256, +- S390_FEAT_KM_XTS_AES_128, +- S390_FEAT_KM_XTS_AES_256, +- S390_FEAT_KM_XTS_EAES_128, +- S390_FEAT_KM_XTS_EAES_256, +- +- /* KIMD */ +- S390_FEAT_KIMD_SHA_1, +- S390_FEAT_KIMD_SHA_256, +- S390_FEAT_KIMD_SHA_512, +- S390_FEAT_KIMD_SHA3_224, +- S390_FEAT_KIMD_SHA3_256, +- S390_FEAT_KIMD_SHA3_384, +- S390_FEAT_KIMD_SHA3_512, +- S390_FEAT_KIMD_SHAKE_128, +- S390_FEAT_KIMD_SHAKE_256, +- S390_FEAT_KIMD_GHASH, +- +- /* KLMD */ +- S390_FEAT_KLMD_SHA_1, +- S390_FEAT_KLMD_SHA_256, +- S390_FEAT_KLMD_SHA_512, +- S390_FEAT_KLMD_SHA3_224, +- S390_FEAT_KLMD_SHA3_256, +- S390_FEAT_KLMD_SHA3_384, +- S390_FEAT_KLMD_SHA3_512, +- S390_FEAT_KLMD_SHAKE_128, +- S390_FEAT_KLMD_SHAKE_256, +- +- /* PCKMO */ +- S390_FEAT_PCKMO_EDEA, +- S390_FEAT_PCKMO_ETDEA_128, +- S390_FEAT_PCKMO_ETDEA_256, +- S390_FEAT_PCKMO_AES_128, +- S390_FEAT_PCKMO_AES_192, +- S390_FEAT_PCKMO_AES_256, +- S390_FEAT_PCKMO_ECC_P256, +- S390_FEAT_PCKMO_ECC_P384, +- S390_FEAT_PCKMO_ECC_P521, +- S390_FEAT_PCKMO_ECC_ED25519, +- S390_FEAT_PCKMO_ECC_ED448, +- +- /* KMCTR */ +- S390_FEAT_KMCTR_DEA, +- S390_FEAT_KMCTR_TDEA_128, +- S390_FEAT_KMCTR_TDEA_192, +- S390_FEAT_KMCTR_EDEA, +- S390_FEAT_KMCTR_ETDEA_128, +- S390_FEAT_KMCTR_ETDEA_192, +- S390_FEAT_KMCTR_AES_128, +- S390_FEAT_KMCTR_AES_192, +- S390_FEAT_KMCTR_AES_256, +- S390_FEAT_KMCTR_EAES_128, +- S390_FEAT_KMCTR_EAES_192, +- S390_FEAT_KMCTR_EAES_256, +- +- /* KMF */ +- S390_FEAT_KMF_DEA, +- S390_FEAT_KMF_TDEA_128, +- S390_FEAT_KMF_TDEA_192, +- S390_FEAT_KMF_EDEA, +- S390_FEAT_KMF_ETDEA_128, +- S390_FEAT_KMF_ETDEA_192, +- S390_FEAT_KMF_AES_128, +- S390_FEAT_KMF_AES_192, +- S390_FEAT_KMF_AES_256, +- S390_FEAT_KMF_EAES_128, +- S390_FEAT_KMF_EAES_192, +- S390_FEAT_KMF_EAES_256, +- +- /* KMO */ +- S390_FEAT_KMO_DEA, +- S390_FEAT_KMO_TDEA_128, +- S390_FEAT_KMO_TDEA_192, +- S390_FEAT_KMO_EDEA, +- S390_FEAT_KMO_ETDEA_128, +- S390_FEAT_KMO_ETDEA_192, +- S390_FEAT_KMO_AES_128, +- S390_FEAT_KMO_AES_192, +- S390_FEAT_KMO_AES_256, +- S390_FEAT_KMO_EAES_128, +- S390_FEAT_KMO_EAES_192, +- S390_FEAT_KMO_EAES_256, +- +- /* PCC */ +- S390_FEAT_PCC_CMAC_DEA, +- S390_FEAT_PCC_CMAC_TDEA_128, +- S390_FEAT_PCC_CMAC_TDEA_192, +- S390_FEAT_PCC_CMAC_ETDEA_128, +- S390_FEAT_PCC_CMAC_ETDEA_192, +- S390_FEAT_PCC_CMAC_TDEA, +- S390_FEAT_PCC_CMAC_AES_128, +- S390_FEAT_PCC_CMAC_AES_192, +- S390_FEAT_PCC_CMAC_AES_256, +- S390_FEAT_PCC_CMAC_EAES_128, +- S390_FEAT_PCC_CMAC_EAES_192, +- S390_FEAT_PCC_CMAC_EAES_256, +- S390_FEAT_PCC_XTS_AES_128, +- S390_FEAT_PCC_XTS_AES_256, +- S390_FEAT_PCC_XTS_EAES_128, +- S390_FEAT_PCC_XTS_EAES_256, +- S390_FEAT_PCC_SCALAR_MULT_P256, +- S390_FEAT_PCC_SCALAR_MULT_P384, +- S390_FEAT_PCC_SCALAR_MULT_P512, +- S390_FEAT_PCC_SCALAR_MULT_ED25519, +- S390_FEAT_PCC_SCALAR_MULT_ED448, +- S390_FEAT_PCC_SCALAR_MULT_X25519, +- S390_FEAT_PCC_SCALAR_MULT_X448, +- +- /* PPNO/PRNO */ +- S390_FEAT_PPNO_SHA_512_DRNG, +- S390_FEAT_PRNO_TRNG_QRTCR, +- S390_FEAT_PRNO_TRNG, +- +- /* KMA */ +- S390_FEAT_KMA_GCM_AES_128, +- S390_FEAT_KMA_GCM_AES_192, +- S390_FEAT_KMA_GCM_AES_256 , +- S390_FEAT_KMA_GCM_EAES_128, +- S390_FEAT_KMA_GCM_EAES_192, +- S390_FEAT_KMA_GCM_EAES_256, +- +- /* KDSA */ +- S390_FEAT_ECDSA_VERIFY_P256, +- S390_FEAT_ECDSA_VERIFY_P384, +- S390_FEAT_ECDSA_VERIFY_P512, +- S390_FEAT_ECDSA_SIGN_P256, +- S390_FEAT_ECDSA_SIGN_P384, +- S390_FEAT_ECDSA_SIGN_P512, +- S390_FEAT_EECDSA_SIGN_P256, +- S390_FEAT_EECDSA_SIGN_P384, +- S390_FEAT_EECDSA_SIGN_P512, +- S390_FEAT_EDDSA_VERIFY_ED25519, +- S390_FEAT_EDDSA_VERIFY_ED448, +- S390_FEAT_EDDSA_SIGN_ED25519, +- S390_FEAT_EDDSA_SIGN_ED448, +- S390_FEAT_EEDDSA_SIGN_ED25519, +- S390_FEAT_EEDDSA_SIGN_ED448, +- +- /* SORTL */ +- S390_FEAT_SORTL_SFLR, +- S390_FEAT_SORTL_SVLR, +- S390_FEAT_SORTL_32, +- S390_FEAT_SORTL_128, +- S390_FEAT_SORTL_F0, +- +- /* DEFLATE */ +- S390_FEAT_DEFLATE_GHDT, +- S390_FEAT_DEFLATE_CMPR, +- S390_FEAT_DEFLATE_XPND, +- S390_FEAT_DEFLATE_F0, +- ++ #include "cpu_features_def.inc.h" + S390_FEAT_MAX, + } S390Feat; ++#undef DEF_FEAT + + #endif /* TARGET_S390X_CPU_FEATURES_DEF_H */ +diff --git a/target/s390x/cpu_features_def.inc.h b/target/s390x/cpu_features_def.inc.h +new file mode 100644 +index 0000000..011ce4d +--- /dev/null ++++ b/target/s390x/cpu_features_def.inc.h +@@ -0,0 +1,369 @@ ++/* ++ * RAW s390x CPU feature definitions: ++ * ++ * DEF_FEAT(_FEAT, _NAME, _TYPE, _BIT, _DESC): ++ * - _FEAT: Feature (enum) name used internally (S390_FEAT_##_FEAT) ++ * - _NAME: Feature name exposed to the user. ++ * - _TYPE: Feature type (S390_FEAT_TYPE_##_TYPE). ++ * - _BIT: Feature bit number within feature type block (unused for MISC). ++ * - _DESC: Feature description, exposed to the user. ++ * ++ * Copyright IBM Corp. 2016, 2018 ++ * Copyright Red Hat, Inc. 2019 ++ * ++ * Author(s): Michael Mueller ++ * David Hildenbrand ++ * ++ * This work is licensed under the terms of the GNU GPL, version 2 or (at ++ * your option) any later version. See the COPYING file in the top-level ++ * directory. ++ */ ++ ++/* Features exposed via the STFL(E) instruction. */ ++DEF_FEAT(ESAN3, "esan3", STFL, 0, "Instructions marked as n3") ++DEF_FEAT(ZARCH, "zarch", STFL, 1, "z/Architecture architectural mode") ++DEF_FEAT(DAT_ENH, "dateh", STFL, 3, "DAT-enhancement facility") ++DEF_FEAT(IDTE_SEGMENT, "idtes", STFL, 4, "IDTE selective TLB segment-table clearing") ++DEF_FEAT(IDTE_REGION, "idter", STFL, 5, "IDTE selective TLB region-table clearing") ++DEF_FEAT(ASN_LX_REUSE, "asnlxr", STFL, 6, "ASN-and-LX reuse facility") ++DEF_FEAT(STFLE, "stfle", STFL, 7, "Store-facility-list-extended facility") ++DEF_FEAT(EDAT, "edat", STFL, 8, "Enhanced-DAT facility") ++DEF_FEAT(SENSE_RUNNING_STATUS, "srs", STFL, 9, "Sense-running-status facility") ++DEF_FEAT(CONDITIONAL_SSKE, "csske", STFL, 10, "Conditional-SSKE facility") ++DEF_FEAT(CONFIGURATION_TOPOLOGY, "ctop", STFL, 11, "Configuration-topology facility") ++DEF_FEAT(AP_QUERY_CONFIG_INFO, "apqci", STFL, 12, "Query AP Configuration Information facility") ++DEF_FEAT(IPTE_RANGE, "ipter", STFL, 13, "IPTE-range facility") ++DEF_FEAT(NONQ_KEY_SETTING, "nonqks", STFL, 14, "Nonquiescing key-setting facility") ++DEF_FEAT(AP_FACILITIES_TEST, "apft", STFL, 15, "AP Facilities Test facility") ++DEF_FEAT(EXTENDED_TRANSLATION_2, "etf2", STFL, 16, "Extended-translation facility 2") ++DEF_FEAT(MSA, "msa-base", STFL, 17, "Message-security-assist facility (excluding subfunctions)") ++DEF_FEAT(LONG_DISPLACEMENT, "ldisp", STFL, 18, "Long-displacement facility") ++DEF_FEAT(LONG_DISPLACEMENT_FAST, "ldisphp", STFL, 19, "Long-displacement facility has high performance") ++DEF_FEAT(HFP_MADDSUB, "hfpm", STFL, 20, "HFP-multiply-add/subtract facility") ++DEF_FEAT(EXTENDED_IMMEDIATE, "eimm", STFL, 21, "Extended-immediate facility") ++DEF_FEAT(EXTENDED_TRANSLATION_3, "etf3", STFL, 22, "Extended-translation facility 3") ++DEF_FEAT(HFP_UNNORMALIZED_EXT, "hfpue", STFL, 23, "HFP-unnormalized-extension facility") ++DEF_FEAT(ETF2_ENH, "etf2eh", STFL, 24, "ETF2-enhancement facility") ++DEF_FEAT(STORE_CLOCK_FAST, "stckf", STFL, 25, "Store-clock-fast facility") ++DEF_FEAT(PARSING_ENH, "parseh", STFL, 26, "Parsing-enhancement facility") ++DEF_FEAT(MOVE_WITH_OPTIONAL_SPEC, "mvcos", STFL, 27, "Move-with-optional-specification facility") ++DEF_FEAT(TOD_CLOCK_STEERING, "tods-base", STFL, 28, "TOD-clock-steering facility (excluding subfunctions)") ++DEF_FEAT(ETF3_ENH, "etf3eh", STFL, 30, "ETF3-enhancement facility") ++DEF_FEAT(EXTRACT_CPU_TIME, "ectg", STFL, 31, "Extract-CPU-time facility") ++DEF_FEAT(COMPARE_AND_SWAP_AND_STORE, "csst", STFL, 32, "Compare-and-swap-and-store facility") ++DEF_FEAT(COMPARE_AND_SWAP_AND_STORE_2, "csst2", STFL, 33, "Compare-and-swap-and-store facility 2") ++DEF_FEAT(GENERAL_INSTRUCTIONS_EXT, "ginste", STFL, 34, "General-instructions-extension facility") ++DEF_FEAT(EXECUTE_EXT, "exrl", STFL, 35, "Execute-extensions facility") ++DEF_FEAT(ENHANCED_MONITOR, "emon", STFL, 36, "Enhanced-monitor facility") ++DEF_FEAT(FLOATING_POINT_EXT, "fpe", STFL, 37, "Floating-point extension facility") ++DEF_FEAT(ORDER_PRESERVING_COMPRESSION, "opc", STFL, 38, "Order Preserving Compression facility") ++DEF_FEAT(SET_PROGRAM_PARAMETERS, "sprogp", STFL, 40, "Set-program-parameters facility") ++DEF_FEAT(FLOATING_POINT_SUPPPORT_ENH, "fpseh", STFL, 41, "Floating-point-support-enhancement facilities") ++DEF_FEAT(DFP, "dfp", STFL, 42, "DFP (decimal-floating-point) facility") ++DEF_FEAT(DFP_FAST, "dfphp", STFL, 43, "DFP (decimal-floating-point) facility has high performance") ++DEF_FEAT(PFPO, "pfpo", STFL, 44, "PFPO instruction") ++DEF_FEAT(STFLE_45, "stfle45", STFL, 45, "Various facilities introduced with z196") ++DEF_FEAT(CMPSC_ENH, "cmpsceh", STFL, 47, "CMPSC-enhancement facility") ++DEF_FEAT(DFP_ZONED_CONVERSION, "dfpzc", STFL, 48, "Decimal-floating-point zoned-conversion facility") ++DEF_FEAT(STFLE_49, "stfle49", STFL, 49, "Various facilities introduced with zEC12") ++DEF_FEAT(CONSTRAINT_TRANSACTIONAL_EXE, "cte", STFL, 50, "Constrained transactional-execution facility") ++DEF_FEAT(LOCAL_TLB_CLEARING, "ltlbc", STFL, 51, "Local-TLB-clearing facility") ++DEF_FEAT(INTERLOCKED_ACCESS_2, "iacc2", STFL, 52, "Interlocked-access facility 2") ++DEF_FEAT(STFLE_53, "stfle53", STFL, 53, "Various facilities introduced with z13") ++DEF_FEAT(ENTROPY_ENC_COMP, "eec", STFL, 54, "Entropy encoding compression facility") ++DEF_FEAT(MSA_EXT_5, "msa5-base", STFL, 57, "Message-security-assist-extension-5 facility (excluding subfunctions)") ++DEF_FEAT(MISC_INSTRUCTION_EXT, "minste2", STFL, 58, "Miscellaneous-instruction-extensions facility 2") ++DEF_FEAT(SEMAPHORE_ASSIST, "sema", STFL, 59, "Semaphore-assist facility") ++DEF_FEAT(TIME_SLICE_INSTRUMENTATION, "tsi", STFL, 60, "Time-slice Instrumentation facility") ++DEF_FEAT(MISC_INSTRUCTION_EXT3, "minste3", STFL, 61, "Miscellaneous-Instruction-Extensions Facility 3") ++DEF_FEAT(RUNTIME_INSTRUMENTATION, "ri", STFL, 64, "CPU runtime-instrumentation facility") ++DEF_FEAT(ZPCI, "zpci", STFL, 69, "z/PCI facility") ++DEF_FEAT(ADAPTER_EVENT_NOTIFICATION, "aen", STFL, 71, "General-purpose-adapter-event-notification facility") ++DEF_FEAT(ADAPTER_INT_SUPPRESSION, "ais", STFL, 72, "General-purpose-adapter-interruption-suppression facility") ++DEF_FEAT(TRANSACTIONAL_EXE, "te", STFL, 73, "Transactional-execution facility") ++DEF_FEAT(STORE_HYPERVISOR_INFO, "sthyi", STFL, 74, "Store-hypervisor-information facility") ++DEF_FEAT(ACCESS_EXCEPTION_FS_INDICATION, "aefsi", STFL, 75, "Access-exception-fetch/store-indication facility") ++DEF_FEAT(MSA_EXT_3, "msa3-base", STFL, 76, "Message-security-assist-extension-3 facility (excluding subfunctions)") ++DEF_FEAT(MSA_EXT_4, "msa4-base", STFL, 77, "Message-security-assist-extension-4 facility (excluding subfunctions)") ++DEF_FEAT(EDAT_2, "edat2", STFL, 78, "Enhanced-DAT facility 2") ++DEF_FEAT(DFP_PACKED_CONVERSION, "dfppc", STFL, 80, "Decimal-floating-point packed-conversion facility") ++DEF_FEAT(PPA15, "ppa15", STFL, 81, "PPA15 is installed") ++DEF_FEAT(BPB, "bpb", STFL, 82, "Branch prediction blocking") ++DEF_FEAT(VECTOR, "vx", STFL, 129, "Vector facility") ++DEF_FEAT(INSTRUCTION_EXEC_PROT, "iep", STFL, 130, "Instruction-execution-protection facility") ++DEF_FEAT(SIDE_EFFECT_ACCESS_ESOP2, "sea_esop2", STFL, 131, "Side-effect-access facility and Enhanced-suppression-on-protection facility 2") ++DEF_FEAT(GUARDED_STORAGE, "gs", STFL, 133, "Guarded-storage facility") ++DEF_FEAT(VECTOR_PACKED_DECIMAL, "vxpd", STFL, 134, "Vector packed decimal facility") ++DEF_FEAT(VECTOR_ENH, "vxeh", STFL, 135, "Vector enhancements facility") ++DEF_FEAT(MULTIPLE_EPOCH, "mepoch", STFL, 139, "Multiple-epoch facility") ++DEF_FEAT(TEST_PENDING_EXT_INTERRUPTION, "tpei", STFL, 144, "Test-pending-external-interruption facility") ++DEF_FEAT(INSERT_REFERENCE_BITS_MULT, "irbm", STFL, 145, "Insert-reference-bits-multiple facility") ++DEF_FEAT(MSA_EXT_8, "msa8-base", STFL, 146, "Message-security-assist-extension-8 facility (excluding subfunctions)") ++DEF_FEAT(CMM_NT, "cmmnt", STFL, 147, "CMM: ESSA-enhancement (no translate) facility") ++DEF_FEAT(VECTOR_ENH2, "vxeh2", STFL, 148, "Vector Enhancements facility 2") ++DEF_FEAT(ESORT_BASE, "esort-base", STFL, 150, "Enhanced-sort facility (excluding subfunctions)") ++DEF_FEAT(DEFLATE_BASE, "deflate-base", STFL, 151, "Deflate-conversion facility (excluding subfunctions)") ++DEF_FEAT(VECTOR_PACKED_DECIMAL_ENH, "vxpdeh", STFL, 152, "Vector-Packed-Decimal-Enhancement Facility") ++DEF_FEAT(MSA_EXT_9, "msa9-base", STFL, 155, "Message-security-assist-extension-9 facility (excluding subfunctions)") ++DEF_FEAT(ETOKEN, "etoken", STFL, 156, "Etoken facility") ++ ++/* Features exposed via SCLP SCCB Byte 80 - 98 (bit numbers relative to byte-80) */ ++DEF_FEAT(SIE_GSLS, "gsls", SCLP_CONF_CHAR, 40, "SIE: Guest-storage-limit-suppression facility") ++DEF_FEAT(ESOP, "esop", SCLP_CONF_CHAR, 46, "Enhanced-suppression-on-protection facility") ++DEF_FEAT(HPMA2, "hpma2", SCLP_CONF_CHAR, 90, "Host page management assist 2 Facility") /* 91-2 */ ++DEF_FEAT(SIE_KSS, "kss", SCLP_CONF_CHAR, 151, "SIE: Keyless-subset facility") /* 98-7 */ ++ ++/* Features exposed via SCLP SCCB Byte 116 - 119 (bit numbers relative to byte-116) */ ++DEF_FEAT(SIE_64BSCAO, "64bscao", SCLP_CONF_CHAR_EXT, 0, "SIE: 64-bit-SCAO facility") ++DEF_FEAT(SIE_CMMA, "cmma", SCLP_CONF_CHAR_EXT, 1, "SIE: Collaborative-memory-management assist") ++DEF_FEAT(SIE_PFMFI, "pfmfi", SCLP_CONF_CHAR_EXT, 9, "SIE: PFMF interpretation facility") ++DEF_FEAT(SIE_IBS, "ibs", SCLP_CONF_CHAR_EXT, 10, "SIE: Interlock-and-broadcast-suppression facility") ++ ++/* Features exposed via SCLP CPU info. */ ++DEF_FEAT(SIE_F2, "sief2", SCLP_CPU, 4, "SIE: interception format 2 (Virtual SIE)") ++DEF_FEAT(SIE_SKEY, "skey", SCLP_CPU, 5, "SIE: Storage-key facility") ++DEF_FEAT(SIE_GPERE, "gpereh", SCLP_CPU, 10, "SIE: Guest-PER enhancement facility") ++DEF_FEAT(SIE_SIIF, "siif", SCLP_CPU, 11, "SIE: Shared IPTE-interlock facility") ++DEF_FEAT(SIE_SIGPIF, "sigpif", SCLP_CPU, 12, "SIE: SIGP interpretation facility") ++DEF_FEAT(SIE_IB, "ib", SCLP_CPU, 42, "SIE: Intervention bypass facility") ++DEF_FEAT(SIE_CEI, "cei", SCLP_CPU, 43, "SIE: Conditional-external-interception facility") ++ ++/* ++ * Features exposed via no feature bit (but e.g., instruction sensing) ++ * -> the feature bit number is irrelavant ++ */ ++DEF_FEAT(DAT_ENH_2, "dateh2", MISC, 0, "DAT-enhancement facility 2") ++DEF_FEAT(CMM, "cmm", MISC, 0, "Collaborative-memory-management facility") ++DEF_FEAT(AP, "ap", MISC, 0, "AP instructions installed") ++ ++/* Features exposed via the PLO instruction. */ ++DEF_FEAT(PLO_CL, "plo-cl", PLO, 0, "PLO Compare and load (32 bit in general registers)") ++DEF_FEAT(PLO_CLG, "plo-clg", PLO, 1, "PLO Compare and load (64 bit in parameter list)") ++DEF_FEAT(PLO_CLGR, "plo-clgr", PLO, 2, "PLO Compare and load (32 bit in general registers)") ++DEF_FEAT(PLO_CLX, "plo-clx", PLO, 3, "PLO Compare and load (128 bit in parameter list)") ++DEF_FEAT(PLO_CS, "plo-cs", PLO, 4, "PLO Compare and swap (32 bit in general registers)") ++DEF_FEAT(PLO_CSG, "plo-csg", PLO, 5, "PLO Compare and swap (64 bit in parameter list)") ++DEF_FEAT(PLO_CSGR, "plo-csgr", PLO, 6, "PLO Compare and swap (32 bit in general registers)") ++DEF_FEAT(PLO_CSX, "plo-csx", PLO, 7, "PLO Compare and swap (128 bit in parameter list)") ++DEF_FEAT(PLO_DCS, "plo-dcs", PLO, 8, "PLO Double compare and swap (32 bit in general registers)") ++DEF_FEAT(PLO_DCSG, "plo-dcsg", PLO, 9, "PLO Double compare and swap (64 bit in parameter list)") ++DEF_FEAT(PLO_DCSGR, "plo-dcsgr", PLO, 10, "PLO Double compare and swap (32 bit in general registers)") ++DEF_FEAT(PLO_DCSX, "plo-dcsx", PLO, 11, "PLO Double compare and swap (128 bit in parameter list)") ++DEF_FEAT(PLO_CSST, "plo-csst", PLO, 12, "PLO Compare and swap and store (32 bit in general registers)") ++DEF_FEAT(PLO_CSSTG, "plo-csstg", PLO, 13, "PLO Compare and swap and store (64 bit in parameter list)") ++DEF_FEAT(PLO_CSSTGR, "plo-csstgr", PLO, 14, "PLO Compare and swap and store (32 bit in general registers)") ++DEF_FEAT(PLO_CSSTX, "plo-csstx", PLO, 15, "PLO Compare and swap and store (128 bit in parameter list)") ++DEF_FEAT(PLO_CSDST, "plo-csdst", PLO, 16, "PLO Compare and swap and double store (32 bit in general registers)") ++DEF_FEAT(PLO_CSDSTG, "plo-csdstg", PLO, 17, "PLO Compare and swap and double store (64 bit in parameter list)") ++DEF_FEAT(PLO_CSDSTGR, "plo-csdstgr", PLO, 18, "PLO Compare and swap and double store (32 bit in general registers)") ++DEF_FEAT(PLO_CSDSTX, "plo-csdstx", PLO, 19, "PLO Compare and swap and double store (128 bit in parameter list)") ++DEF_FEAT(PLO_CSTST, "plo-cstst", PLO, 20, "PLO Compare and swap and triple store (32 bit in general registers)") ++DEF_FEAT(PLO_CSTSTG, "plo-cststg", PLO, 21, "PLO Compare and swap and triple store (64 bit in parameter list)") ++DEF_FEAT(PLO_CSTSTGR, "plo-cststgr", PLO, 22, "PLO Compare and swap and triple store (32 bit in general registers)") ++DEF_FEAT(PLO_CSTSTX, "plo-cststx", PLO, 23, "PLO Compare and swap and triple store (128 bit in parameter list)") ++ ++/* Features exposed via the PTFF instruction. */ ++DEF_FEAT(PTFF_QTO, "ptff-qto", PTFF, 1, "PTFF Query TOD Offset") ++DEF_FEAT(PTFF_QSI, "ptff-qsi", PTFF, 2, "PTFF Query Steering Information") ++DEF_FEAT(PTFF_QPT, "ptff-qpc", PTFF, 3, "PTFF Query Physical Clock") ++DEF_FEAT(PTFF_QUI, "ptff-qui", PTFF, 4, "PTFF Query UTC Information") ++DEF_FEAT(PTFF_QTOU, "ptff-qtou", PTFF, 5, "PTFF Query TOD Offset User") ++DEF_FEAT(PTFF_QSIE, "ptff-qsie", PTFF, 10, "PTFF Query Steering Information Extended") ++DEF_FEAT(PTFF_QTOUE, "ptff-qtoue", PTFF, 13, "PTFF Query TOD Offset User Extended") ++DEF_FEAT(PTFF_STO, "ptff-sto", PTFF, 65, "PTFF Set TOD Offset") ++DEF_FEAT(PTFF_STOU, "ptff-stou", PTFF, 69, "PTFF Set TOD Offset User") ++DEF_FEAT(PTFF_STOE, "ptff-stoe", PTFF, 73, "PTFF Set TOD Offset Extended") ++DEF_FEAT(PTFF_STOUE, "ptff-stoue", PTFF, 77, "PTFF Set TOD Offset User Extended") ++ ++/* Features exposed via the KMAC instruction. */ ++DEF_FEAT(KMAC_DEA, "kmac-dea", KMAC, 1, "KMAC DEA") ++DEF_FEAT(KMAC_TDEA_128, "kmac-tdea-128", KMAC, 2, "KMAC TDEA-128") ++DEF_FEAT(KMAC_TDEA_192, "kmac-tdea-192", KMAC, 3, "KMAC TDEA-192") ++DEF_FEAT(KMAC_EDEA, "kmac-edea", KMAC, 9, "KMAC Encrypted-DEA") ++DEF_FEAT(KMAC_ETDEA_128, "kmac-etdea-128", KMAC, 10, "KMAC Encrypted-TDEA-128") ++DEF_FEAT(KMAC_ETDEA_192, "kmac-etdea-192", KMAC, 11, "KMAC Encrypted-TDEA-192") ++DEF_FEAT(KMAC_AES_128, "kmac-aes-128", KMAC, 18, "KMAC AES-128") ++DEF_FEAT(KMAC_AES_192, "kmac-aes-192", KMAC, 19, "KMAC AES-192") ++DEF_FEAT(KMAC_AES_256, "kmac-aes-256", KMAC, 20, "KMAC AES-256") ++DEF_FEAT(KMAC_EAES_128, "kmac-eaes-128", KMAC, 26, "KMAC Encrypted-AES-128") ++DEF_FEAT(KMAC_EAES_192, "kmac-eaes-192", KMAC, 27, "KMAC Encrypted-AES-192") ++DEF_FEAT(KMAC_EAES_256, "kmac-eaes-256", KMAC, 28, "KMAC Encrypted-AES-256") ++ ++/* Features exposed via the KMC instruction. */ ++DEF_FEAT(KMC_DEA, "kmc-dea", KMC, 1, "KMC DEA") ++DEF_FEAT(KMC_TDEA_128, "kmc-tdea-128", KMC, 2, "KMC TDEA-128") ++DEF_FEAT(KMC_TDEA_192, "kmc-tdea-192", KMC, 3, "KMC TDEA-192") ++DEF_FEAT(KMC_EDEA, "kmc-edea", KMC, 9, "KMC Encrypted-DEA") ++DEF_FEAT(KMC_ETDEA_128, "kmc-etdea-128", KMC, 10, "KMC Encrypted-TDEA-128") ++DEF_FEAT(KMC_ETDEA_192, "kmc-etdea-192", KMC, 11, "KMC Encrypted-TDEA-192") ++DEF_FEAT(KMC_AES_128, "kmc-aes-128", KMC, 18, "KMC AES-128") ++DEF_FEAT(KMC_AES_192, "kmc-aes-192", KMC, 19, "KMC AES-192") ++DEF_FEAT(KMC_AES_256, "kmc-aes-256", KMC, 20, "KMC AES-256") ++DEF_FEAT(KMC_EAES_128, "kmc-eaes-128", KMC, 26, "KMC Encrypted-AES-128") ++DEF_FEAT(KMC_EAES_192, "kmc-eaes-192", KMC, 27, "KMC Encrypted-AES-192") ++DEF_FEAT(KMC_EAES_256, "kmc-eaes-256", KMC, 28, "KMC Encrypted-AES-256") ++DEF_FEAT(KMC_PRNG, "kmc-prng", KMC, 67, "KMC PRNG") ++ ++/* Features exposed via the KM instruction. */ ++DEF_FEAT(KM_DEA, "km-dea", KM, 1, "KM DEA") ++DEF_FEAT(KM_TDEA_128, "km-tdea-128", KM, 2, "KM TDEA-128") ++DEF_FEAT(KM_TDEA_192, "km-tdea-192", KM, 3, "KM TDEA-192") ++DEF_FEAT(KM_EDEA, "km-edea", KM, 9, "KM Encrypted-DEA") ++DEF_FEAT(KM_ETDEA_128, "km-etdea-128", KM, 10, "KM Encrypted-TDEA-128") ++DEF_FEAT(KM_ETDEA_192, "km-etdea-192", KM, 11, "KM Encrypted-TDEA-192") ++DEF_FEAT(KM_AES_128, "km-aes-128", KM, 18, "KM AES-128") ++DEF_FEAT(KM_AES_192, "km-aes-192", KM, 19, "KM AES-192") ++DEF_FEAT(KM_AES_256, "km-aes-256", KM, 20, "KM AES-256") ++DEF_FEAT(KM_EAES_128, "km-eaes-128", KM, 26, "KM Encrypted-AES-128") ++DEF_FEAT(KM_EAES_192, "km-eaes-192", KM, 27, "KM Encrypted-AES-192") ++DEF_FEAT(KM_EAES_256, "km-eaes-256", KM, 28, "KM Encrypted-AES-256") ++DEF_FEAT(KM_XTS_AES_128, "km-xts-aes-128", KM, 50, "KM XTS-AES-128") ++DEF_FEAT(KM_XTS_AES_256, "km-xts-aes-256", KM, 52, "KM XTS-AES-256") ++DEF_FEAT(KM_XTS_EAES_128, "km-xts-eaes-128", KM, 58, "KM XTS-Encrypted-AES-128") ++DEF_FEAT(KM_XTS_EAES_256, "km-xts-eaes-256", KM, 60, "KM XTS-Encrypted-AES-256") ++ ++/* Features exposed via the KIMD instruction. */ ++DEF_FEAT(KIMD_SHA_1, "kimd-sha-1", KIMD, 1, "KIMD SHA-1") ++DEF_FEAT(KIMD_SHA_256, "kimd-sha-256", KIMD, 2, "KIMD SHA-256") ++DEF_FEAT(KIMD_SHA_512, "kimd-sha-512", KIMD, 3, "KIMD SHA-512") ++DEF_FEAT(KIMD_SHA3_224, "kimd-sha3-224", KIMD, 32, "KIMD SHA3-224") ++DEF_FEAT(KIMD_SHA3_256, "kimd-sha3-256", KIMD, 33, "KIMD SHA3-256") ++DEF_FEAT(KIMD_SHA3_384, "kimd-sha3-384", KIMD, 34, "KIMD SHA3-384") ++DEF_FEAT(KIMD_SHA3_512, "kimd-sha3-512", KIMD, 35, "KIMD SHA3-512") ++DEF_FEAT(KIMD_SHAKE_128, "kimd-shake-128", KIMD, 36, "KIMD SHAKE-128") ++DEF_FEAT(KIMD_SHAKE_256, "kimd-shake-256", KIMD, 37, "KIMD SHAKE-256") ++DEF_FEAT(KIMD_GHASH, "kimd-ghash", KIMD, 65, "KIMD GHASH") ++ ++/* Features exposed via the KLMD instruction. */ ++DEF_FEAT(KLMD_SHA_1, "klmd-sha-1", KLMD, 1, "KLMD SHA-1") ++DEF_FEAT(KLMD_SHA_256, "klmd-sha-256", KLMD, 2, "KLMD SHA-256") ++DEF_FEAT(KLMD_SHA_512, "klmd-sha-512", KLMD, 3, "KLMD SHA-512") ++DEF_FEAT(KLMD_SHA3_224, "klmd-sha3-224", KLMD, 32, "KLMD SHA3-224") ++DEF_FEAT(KLMD_SHA3_256, "klmd-sha3-256", KLMD, 33, "KLMD SHA3-256") ++DEF_FEAT(KLMD_SHA3_384, "klmd-sha3-384", KLMD, 34, "KLMD SHA3-384") ++DEF_FEAT(KLMD_SHA3_512, "klmd-sha3-512", KLMD, 35, "KLMD SHA3-512") ++DEF_FEAT(KLMD_SHAKE_128, "klmd-shake-128", KLMD, 36, "KLMD SHAKE-128") ++DEF_FEAT(KLMD_SHAKE_256, "klmd-shake-256", KLMD, 37, "KLMD SHAKE-256") ++ ++/* Features exposed via the PCKMO instruction. */ ++DEF_FEAT(PCKMO_EDEA, "pckmo-edea", PCKMO, 1, "PCKMO Encrypted-DEA-Key") ++DEF_FEAT(PCKMO_ETDEA_128, "pckmo-etdea-128", PCKMO, 2, "PCKMO Encrypted-TDEA-128-Key") ++DEF_FEAT(PCKMO_ETDEA_256, "pckmo-etdea-192", PCKMO, 3, "PCKMO Encrypted-TDEA-192-Key") ++DEF_FEAT(PCKMO_AES_128, "pckmo-aes-128", PCKMO, 18, "PCKMO Encrypted-AES-128-Key") ++DEF_FEAT(PCKMO_AES_192, "pckmo-aes-192", PCKMO, 19, "PCKMO Encrypted-AES-192-Key") ++DEF_FEAT(PCKMO_AES_256, "pckmo-aes-256", PCKMO, 20, "PCKMO Encrypted-AES-256-Key") ++DEF_FEAT(PCKMO_ECC_P256, "pckmo-ecc-p256", PCKMO, 32, "PCKMO Encrypt-ECC-P256-Key") ++DEF_FEAT(PCKMO_ECC_P384, "pckmo-ecc-p384", PCKMO, 33, "PCKMO Encrypt-ECC-P384-Key") ++DEF_FEAT(PCKMO_ECC_P521, "pckmo-ecc-p521", PCKMO, 34, "PCKMO Encrypt-ECC-P521-Key") ++DEF_FEAT(PCKMO_ECC_ED25519, "pckmo-ecc-ed25519", PCKMO, 40 , "PCKMO Encrypt-ECC-Ed25519-Key") ++DEF_FEAT(PCKMO_ECC_ED448, "pckmo-ecc-ed448", PCKMO, 41 , "PCKMO Encrypt-ECC-Ed448-Key") ++ ++/* Features exposed via the KMCTR instruction. */ ++DEF_FEAT(KMCTR_DEA, "kmctr-dea", KMCTR, 1, "KMCTR DEA") ++DEF_FEAT(KMCTR_TDEA_128, "kmctr-tdea-128", KMCTR, 2, "KMCTR TDEA-128") ++DEF_FEAT(KMCTR_TDEA_192, "kmctr-tdea-192", KMCTR, 3, "KMCTR TDEA-192") ++DEF_FEAT(KMCTR_EDEA, "kmctr-edea", KMCTR, 9, "KMCTR Encrypted-DEA") ++DEF_FEAT(KMCTR_ETDEA_128, "kmctr-etdea-128", KMCTR, 10, "KMCTR Encrypted-TDEA-128") ++DEF_FEAT(KMCTR_ETDEA_192, "kmctr-etdea-192", KMCTR, 11, "KMCTR Encrypted-TDEA-192") ++DEF_FEAT(KMCTR_AES_128, "kmctr-aes-128", KMCTR, 18, "KMCTR AES-128") ++DEF_FEAT(KMCTR_AES_192, "kmctr-aes-192", KMCTR, 19, "KMCTR AES-192") ++DEF_FEAT(KMCTR_AES_256, "kmctr-aes-256", KMCTR, 20, "KMCTR AES-256") ++DEF_FEAT(KMCTR_EAES_128, "kmctr-eaes-128", KMCTR, 26, "KMCTR Encrypted-AES-128") ++DEF_FEAT(KMCTR_EAES_192, "kmctr-eaes-192", KMCTR, 27, "KMCTR Encrypted-AES-192") ++DEF_FEAT(KMCTR_EAES_256, "kmctr-eaes-256", KMCTR, 28, "KMCTR Encrypted-AES-256") ++ ++/* Features exposed via the KMF instruction. */ ++DEF_FEAT(KMF_DEA, "kmf-dea", KMF, 1, "KMF DEA") ++DEF_FEAT(KMF_TDEA_128, "kmf-tdea-128", KMF, 2, "KMF TDEA-128") ++DEF_FEAT(KMF_TDEA_192, "kmf-tdea-192", KMF, 3, "KMF TDEA-192") ++DEF_FEAT(KMF_EDEA, "kmf-edea", KMF, 9, "KMF Encrypted-DEA") ++DEF_FEAT(KMF_ETDEA_128, "kmf-etdea-128", KMF, 10, "KMF Encrypted-TDEA-128") ++DEF_FEAT(KMF_ETDEA_192, "kmf-etdea-192", KMF, 11, "KMF Encrypted-TDEA-192") ++DEF_FEAT(KMF_AES_128, "kmf-aes-128", KMF, 18, "KMF AES-128") ++DEF_FEAT(KMF_AES_192, "kmf-aes-192", KMF, 19, "KMF AES-192") ++DEF_FEAT(KMF_AES_256, "kmf-aes-256", KMF, 20, "KMF AES-256") ++DEF_FEAT(KMF_EAES_128, "kmf-eaes-128", KMF, 26, "KMF Encrypted-AES-128") ++DEF_FEAT(KMF_EAES_192, "kmf-eaes-192", KMF, 27, "KMF Encrypted-AES-192") ++DEF_FEAT(KMF_EAES_256, "kmf-eaes-256", KMF, 28, "KMF Encrypted-AES-256") ++ ++/* Features exposed via the KMO instruction. */ ++DEF_FEAT(KMO_DEA, "kmo-dea", KMO, 1, "KMO DEA") ++DEF_FEAT(KMO_TDEA_128, "kmo-tdea-128", KMO, 2, "KMO TDEA-128") ++DEF_FEAT(KMO_TDEA_192, "kmo-tdea-192", KMO, 3, "KMO TDEA-192") ++DEF_FEAT(KMO_EDEA, "kmo-edea", KMO, 9, "KMO Encrypted-DEA") ++DEF_FEAT(KMO_ETDEA_128, "kmo-etdea-128", KMO, 10, "KMO Encrypted-TDEA-128") ++DEF_FEAT(KMO_ETDEA_192, "kmo-etdea-192", KMO, 11, "KMO Encrypted-TDEA-192") ++DEF_FEAT(KMO_AES_128, "kmo-aes-128", KMO, 18, "KMO AES-128") ++DEF_FEAT(KMO_AES_192, "kmo-aes-192", KMO, 19, "KMO AES-192") ++DEF_FEAT(KMO_AES_256, "kmo-aes-256", KMO, 20, "KMO AES-256") ++DEF_FEAT(KMO_EAES_128, "kmo-eaes-128", KMO, 26, "KMO Encrypted-AES-128") ++DEF_FEAT(KMO_EAES_192, "kmo-eaes-192", KMO, 27, "KMO Encrypted-AES-192") ++DEF_FEAT(KMO_EAES_256, "kmo-eaes-256", KMO, 28, "KMO Encrypted-AES-256") ++ ++/* Features exposed via the PCC instruction. */ ++DEF_FEAT(PCC_CMAC_DEA, "pcc-cmac-dea", PCC, 1, "PCC Compute-Last-Block-CMAC-Using-DEA") ++DEF_FEAT(PCC_CMAC_TDEA_128, "pcc-cmac-tdea-128", PCC, 2, "PCC Compute-Last-Block-CMAC-Using-TDEA-128") ++DEF_FEAT(PCC_CMAC_TDEA_192, "pcc-cmac-tdea-192", PCC, 3, "PCC Compute-Last-Block-CMAC-Using-TDEA-192") ++DEF_FEAT(PCC_CMAC_ETDEA_128, "pcc-cmac-edea", PCC, 9, "PCC Compute-Last-Block-CMAC-Using-Encrypted-DEA") ++DEF_FEAT(PCC_CMAC_ETDEA_192, "pcc-cmac-etdea-128", PCC, 10, "PCC Compute-Last-Block-CMAC-Using-Encrypted-TDEA-128") ++DEF_FEAT(PCC_CMAC_TDEA, "pcc-cmac-etdea-192", PCC, 11, "PCC Compute-Last-Block-CMAC-Using-EncryptedTDEA-192") ++DEF_FEAT(PCC_CMAC_AES_128, "pcc-cmac-aes-128", PCC, 18, "PCC Compute-Last-Block-CMAC-Using-AES-128") ++DEF_FEAT(PCC_CMAC_AES_192, "pcc-cmac-aes-192", PCC, 19, "PCC Compute-Last-Block-CMAC-Using-AES-192") ++DEF_FEAT(PCC_CMAC_AES_256, "pcc-cmac-eaes-256", PCC, 20, "PCC Compute-Last-Block-CMAC-Using-AES-256") ++DEF_FEAT(PCC_CMAC_EAES_128, "pcc-cmac-eaes-128", PCC, 26, "PCC Compute-Last-Block-CMAC-Using-Encrypted-AES-128") ++DEF_FEAT(PCC_CMAC_EAES_192, "pcc-cmac-eaes-192", PCC, 27, "PCC Compute-Last-Block-CMAC-Using-Encrypted-AES-192") ++DEF_FEAT(PCC_CMAC_EAES_256, "pcc-cmac-eaes-256", PCC, 28, "PCC Compute-Last-Block-CMAC-Using-Encrypted-AES-256") ++DEF_FEAT(PCC_XTS_AES_128, "pcc-xts-aes-128", PCC, 50, "PCC Compute-XTS-Parameter-Using-AES-128") ++DEF_FEAT(PCC_XTS_AES_256, "pcc-xts-aes-256", PCC, 52, "PCC Compute-XTS-Parameter-Using-AES-256") ++DEF_FEAT(PCC_XTS_EAES_128, "pcc-xts-eaes-128", PCC, 58, "PCC Compute-XTS-Parameter-Using-Encrypted-AES-128") ++DEF_FEAT(PCC_XTS_EAES_256, "pcc-xts-eaes-256", PCC, 60, "PCC Compute-XTS-Parameter-Using-Encrypted-AES-256") ++DEF_FEAT(PCC_SCALAR_MULT_P256, "pcc-scalar-mult-p256", PCC, 64, "PCC Scalar-Multiply-P256") ++DEF_FEAT(PCC_SCALAR_MULT_P384, "pcc-scalar-mult-p384", PCC, 65, "PCC Scalar-Multiply-P384") ++DEF_FEAT(PCC_SCALAR_MULT_P512, "pcc-scalar-mult-p521", PCC, 66, "PCC Scalar-Multiply-P521") ++DEF_FEAT(PCC_SCALAR_MULT_ED25519, "pcc-scalar-mult-ed25519", PCC, 72, "PCC Scalar-Multiply-Ed25519") ++DEF_FEAT(PCC_SCALAR_MULT_ED448, "pcc-scalar-mult-ed448", PCC, 73, "PCC Scalar-Multiply-Ed448") ++DEF_FEAT(PCC_SCALAR_MULT_X25519, "pcc-scalar-mult-x25519", PCC, 80, "PCC Scalar-Multiply-X25519") ++DEF_FEAT(PCC_SCALAR_MULT_X448, "pcc-scalar-mult-x448", PCC, 81, "PCC Scalar-Multiply-X448") ++ ++/* Features exposed via the PPNO/PRNO instruction. */ ++DEF_FEAT(PPNO_SHA_512_DRNG, "ppno-sha-512-drng", PPNO, 3, "PPNO SHA-512-DRNG") ++DEF_FEAT(PRNO_TRNG_QRTCR, "prno-trng-qrtcr", PPNO, 112, "PRNO TRNG-Query-Raw-to-Conditioned-Ratio") ++DEF_FEAT(PRNO_TRNG, "prno-trng", PPNO, 114, "PRNO TRNG") ++ ++/* Features exposed via the KMA instruction. */ ++DEF_FEAT(KMA_GCM_AES_128, "kma-gcm-aes-128", KMA, 18, "KMA GCM-AES-128") ++DEF_FEAT(KMA_GCM_AES_192, "kma-gcm-aes-192", KMA, 19, "KMA GCM-AES-192") ++DEF_FEAT(KMA_GCM_AES_256, "kma-gcm-aes-256", KMA, 20, "KMA GCM-AES-256") ++DEF_FEAT(KMA_GCM_EAES_128, "kma-gcm-eaes-128", KMA, 26, "KMA GCM-Encrypted-AES-128") ++DEF_FEAT(KMA_GCM_EAES_192, "kma-gcm-eaes-192", KMA, 27, "KMA GCM-Encrypted-AES-192") ++DEF_FEAT(KMA_GCM_EAES_256, "kma-gcm-eaes-256", KMA, 28, "KMA GCM-Encrypted-AES-256") ++ ++/* Features exposed via the KDSA instruction. */ ++DEF_FEAT(ECDSA_VERIFY_P256, "kdsa-ecdsa-verify-p256", KDSA, 1, "KDSA ECDSA-Verify-P256") ++DEF_FEAT(ECDSA_VERIFY_P384, "kdsa-ecdsa-verify-p384", KDSA, 2, "KDSA ECDSA-Verify-P384") ++DEF_FEAT(ECDSA_VERIFY_P512, "kdsa-ecdsa-verify-p521", KDSA, 3, "KDSA ECDSA-Verify-P521") ++DEF_FEAT(ECDSA_SIGN_P256, "kdsa-ecdsa-sign-p256", KDSA, 9, "KDSA ECDSA-Sign-P256") ++DEF_FEAT(ECDSA_SIGN_P384, "kdsa-ecdsa-sign-p384", KDSA, 10, "KDSA ECDSA-Sign-P384") ++DEF_FEAT(ECDSA_SIGN_P512, "kdsa-ecdsa-sign-p521", KDSA, 11, "KDSA ECDSA-Sign-P521") ++DEF_FEAT(EECDSA_SIGN_P256, "kdsa-eecdsa-sign-p256", KDSA, 17, "KDSA Encrypted-ECDSA-Sign-P256") ++DEF_FEAT(EECDSA_SIGN_P384, "kdsa-eecdsa-sign-p384", KDSA, 18, "KDSA Encrypted-ECDSA-Sign-P384") ++DEF_FEAT(EECDSA_SIGN_P512, "kdsa-eecdsa-sign-p521", KDSA, 19, "KDSA Encrypted-ECDSA-Sign-P521") ++DEF_FEAT(EDDSA_VERIFY_ED25519, "kdsa-eddsa-verify-ed25519", KDSA, 32, "KDSA EdDSA-Verify-Ed25519") ++DEF_FEAT(EDDSA_VERIFY_ED448, "kdsa-eddsa-verify-ed448", KDSA, 36, "KDSA EdDSA-Verify-Ed448") ++DEF_FEAT(EDDSA_SIGN_ED25519, "kdsa-eddsa-sign-ed25519", KDSA, 40, "KDSA EdDSA-Sign-Ed25519") ++DEF_FEAT(EDDSA_SIGN_ED448, "kdsa-eddsa-sign-ed448", KDSA, 44, "KDSA EdDSA-Sign-Ed448") ++DEF_FEAT(EEDDSA_SIGN_ED25519, "kdsa-eeddsa-sign-ed25519", KDSA, 48, "KDSA Encrypted-EdDSA-Sign-Ed25519") ++DEF_FEAT(EEDDSA_SIGN_ED448, "kdsa-eeddsa-sign-ed448", KDSA, 52, "KDSA Encrypted-EdDSA-Sign-Ed448") ++ ++/* Features exposed via the SORTL instruction. */ ++DEF_FEAT(SORTL_SFLR, "sortl-sflr", SORTL, 1, "SORTL SFLR") ++DEF_FEAT(SORTL_SVLR, "sortl-svlr", SORTL, 2, "SORTL SVLR") ++DEF_FEAT(SORTL_32, "sortl-32", SORTL, 130, "SORTL 32 input lists") ++DEF_FEAT(SORTL_128, "sortl-128", SORTL, 132, "SORTL 128 input lists") ++DEF_FEAT(SORTL_F0, "sortl-f0", SORTL, 192, "SORTL format 0 parameter-block") ++ ++/* Features exposed via the DEFLATE instruction. */ ++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") +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390x-cpumodel-Set-up-CPU-model-for-AQIC-interceptio.patch b/SOURCES/kvm-s390x-cpumodel-Set-up-CPU-model-for-AQIC-interceptio.patch new file mode 100644 index 0000000..7ef39c4 --- /dev/null +++ b/SOURCES/kvm-s390x-cpumodel-Set-up-CPU-model-for-AQIC-interceptio.patch @@ -0,0 +1,96 @@ +From ad53e96559cfe9d5f1b5518c3c925618e7e1bcc7 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Wed, 18 Sep 2019 14:35:49 +0100 +Subject: [PATCH 10/22] s390x/cpumodel: Set up CPU model for AQIC interception + +RH-Author: Thomas Huth +Message-id: <20190918143549.16340-3-thuth@redhat.com> +Patchwork-id: 90760 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH 2/2] s390x/cpumodel: Set up CPU model for AQIC interception +Bugzilla: 1660909 +RH-Acked-by: David Hildenbrand +RH-Acked-by: Cornelia Huck +RH-Acked-by: Jens Freimann + +From: Pierre Morel + +Let's add support for the AP-Queue interruption facility to the CPU +model. + +The S390_FEAT_AP_QUEUE_INTERRUPT_CONTROL, CPU facility indicates +whether the PQAP instruction with the AQIC command is available +to the guest. +This feature will be enabled only if the AP instructions are +available on the linux host and AQIC facility is installed on +the host. + +This feature must be turned on from userspace to intercept AP +instructions on the KVM guest. The QEMU command line to turn +this feature on looks something like this: + + qemu-system-s390x ... -cpu xxx,apqi=on ... +or + ... -cpu host + +Right now AP pass-through devices do not support migration, +which means that we do not have to take care of migrating +the interrupt data: +virsh migrate apguest --live qemu+ssh://root@target.lan/system +error: Requested operation is not valid: domain has assigned non-USB host devices + +Signed-off-by: Pierre Morel +Reviewed-by: Tony Krowiak +Reviewed-by: Christian Borntraeger +Reviewed-by: Halil Pasic +Signed-off-by: Christian Borntraeger +[rebase to newest qemu and fixup description] +Message-Id: <20190705153249.12525-1-borntraeger@de.ibm.com> +Signed-off-by: Cornelia Huck +(cherry picked from commit 9ef2d19e5f5dfdebc9877c77951c28f25c74e000) + +Signed-off-by: Danilo C. L. de Paula +--- + target/s390x/cpu_features_def.inc.h | 1 + + target/s390x/cpu_models.c | 1 + + target/s390x/gen-features.c | 1 + + 3 files changed, 3 insertions(+) + +diff --git a/target/s390x/cpu_features_def.inc.h b/target/s390x/cpu_features_def.inc.h +index 011ce4d..dead061 100644 +--- a/target/s390x/cpu_features_def.inc.h ++++ b/target/s390x/cpu_features_def.inc.h +@@ -77,6 +77,7 @@ DEF_FEAT(SEMAPHORE_ASSIST, "sema", STFL, 59, "Semaphore-assist facility") + DEF_FEAT(TIME_SLICE_INSTRUMENTATION, "tsi", STFL, 60, "Time-slice Instrumentation facility") + DEF_FEAT(MISC_INSTRUCTION_EXT3, "minste3", STFL, 61, "Miscellaneous-Instruction-Extensions Facility 3") + DEF_FEAT(RUNTIME_INSTRUMENTATION, "ri", STFL, 64, "CPU runtime-instrumentation facility") ++DEF_FEAT(AP_QUEUE_INTERRUPT_CONTROL, "apqi", STFL, 65, "AP-Queue interruption facility") + DEF_FEAT(ZPCI, "zpci", STFL, 69, "z/PCI facility") + DEF_FEAT(ADAPTER_EVENT_NOTIFICATION, "aen", STFL, 71, "General-purpose-adapter-event-notification facility") + DEF_FEAT(ADAPTER_INT_SUPPRESSION, "ais", STFL, 72, "General-purpose-adapter-interruption-suppression facility") +diff --git a/target/s390x/cpu_models.c b/target/s390x/cpu_models.c +index 91afc6b..f16ef64 100644 +--- a/target/s390x/cpu_models.c ++++ b/target/s390x/cpu_models.c +@@ -792,6 +792,7 @@ static void check_consistency(const S390CPUModel *model) + { S390_FEAT_PTFF_QTOUE, S390_FEAT_MULTIPLE_EPOCH }, + { S390_FEAT_PTFF_STOE, S390_FEAT_MULTIPLE_EPOCH }, + { S390_FEAT_PTFF_STOUE, S390_FEAT_MULTIPLE_EPOCH }, ++ { S390_FEAT_AP_QUEUE_INTERRUPT_CONTROL, S390_FEAT_AP }, + }; + int i; + +diff --git a/target/s390x/gen-features.c b/target/s390x/gen-features.c +index 24d78e9..17bb04e 100644 +--- a/target/s390x/gen-features.c ++++ b/target/s390x/gen-features.c +@@ -519,6 +519,7 @@ static uint16_t full_GEN12_GA1[] = { + S390_FEAT_EDAT_2, + S390_FEAT_SIDE_EFFECT_ACCESS_ESOP2, + S390_FEAT_AP_QUERY_CONFIG_INFO, ++ S390_FEAT_AP_QUEUE_INTERRUPT_CONTROL, + S390_FEAT_AP_FACILITIES_TEST, + S390_FEAT_AP, + }; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390x-cpumodel-also-change-name-of-vxbeh.patch b/SOURCES/kvm-s390x-cpumodel-also-change-name-of-vxbeh.patch new file mode 100644 index 0000000..211a7b8 --- /dev/null +++ b/SOURCES/kvm-s390x-cpumodel-also-change-name-of-vxbeh.patch @@ -0,0 +1,56 @@ +From 0b358ba0410babbf96d5c0db6ec0502498871435 Mon Sep 17 00:00:00 2001 +From: David Hildenbrand +Date: Tue, 16 Jul 2019 20:44:21 +0100 +Subject: [PATCH 19/39] s390x/cpumodel: also change name of vxbeh + +RH-Author: David Hildenbrand +Message-id: <20190716204422.9350-4-david@redhat.com> +Patchwork-id: 89550 +O-Subject: [RHEL8.1 qemu-kvm PATCH 3/4] s390x/cpumodel: also change name of vxbeh +Bugzilla: 1729975 +RH-Acked-by: Thomas Huth +RH-Acked-by: Cornelia Huck +RH-Acked-by: Jens Freimann + +Conflicts: upstream moved the definitions + +David suggested to keep everything in sync as 4.1 is not yet released. +This patch fixes the name "vxbeh" into "vxpdeh". + +To simplify the backports this patch will not change VECTOR_BCD_ENH as +this is just an internal name. That will be done by an extra patch that +does not need to be backported. + +Suggested-by: David Hildenbrand +Fixes: d05be57ddc2e ("s390: cpumodel: fix description for the new vector facility") +Fixes: 54d65de0b525 ("s390x/cpumodel: vector enhancements") +Signed-off-by: Christian Borntraeger +Message-Id: <20190715142304.215018-3-borntraeger@de.ibm.com> +[CH: vxp->vxpdeh, as discussed] +Reviewed-by: David Hildenbrand +Reviewed-by: Thomas Huth +Signed-off-by: Cornelia Huck +(cherry picked from commit 0d4cb295db7503fbac2f5bb3e878a56630231fed) +Signed-off-by: David Hildenbrand + +Signed-off-by: Danilo C. L. de Paula +--- + target/s390x/cpu_features.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/target/s390x/cpu_features.c b/target/s390x/cpu_features.c +index 5be6f59..065db76 100644 +--- a/target/s390x/cpu_features.c ++++ b/target/s390x/cpu_features.c +@@ -111,7 +111,7 @@ static const S390FeatDef s390_features[] = { + FEAT_INIT("vxeh2", S390_FEAT_TYPE_STFL, 148, "Vector Enhancements facility 2"), + FEAT_INIT("esort-base", S390_FEAT_TYPE_STFL, 150, "Enhanced-sort facility (excluding subfunctions)"), + FEAT_INIT("deflate-base", S390_FEAT_TYPE_STFL, 151, "Deflate-conversion facility (excluding subfunctions)"), +- FEAT_INIT("vxbeh", S390_FEAT_TYPE_STFL, 152, "Vector-Packed-Decimal-Enhancement Facility"), ++ FEAT_INIT("vxpdeh", S390_FEAT_TYPE_STFL, 152, "Vector-Packed-Decimal-Enhancement Facility"), + FEAT_INIT("msa9-base", S390_FEAT_TYPE_STFL, 155, "Message-security-assist-extension-9 facility (excluding subfunctions)"), + FEAT_INIT("etoken", S390_FEAT_TYPE_STFL, 156, "Etoken facility"), + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390x-cpumodel-change-internal-name-of-vxpdeh-to-mat.patch b/SOURCES/kvm-s390x-cpumodel-change-internal-name-of-vxpdeh-to-mat.patch new file mode 100644 index 0000000..ebdb1c5 --- /dev/null +++ b/SOURCES/kvm-s390x-cpumodel-change-internal-name-of-vxpdeh-to-mat.patch @@ -0,0 +1,73 @@ +From 6bd2a32b23c4d1ea45f7aea34d95817e7f1f5e0b Mon Sep 17 00:00:00 2001 +From: David Hildenbrand +Date: Tue, 16 Jul 2019 20:44:22 +0100 +Subject: [PATCH 20/39] s390x/cpumodel: change internal name of vxpdeh to match + description + +RH-Author: David Hildenbrand +Message-id: <20190716204422.9350-5-david@redhat.com> +Patchwork-id: 89548 +O-Subject: [RHEL8.1 qemu-kvm PATCH 4/4] s390x/cpumodel: change internal name of vxpdeh to match description +Bugzilla: 1729975 +RH-Acked-by: Thomas Huth +RH-Acked-by: Cornelia Huck +RH-Acked-by: Jens Freimann + +Conflicts: upstream changed the way cpu features are defined + +The internal macro name VECTOR_BCD_ENH does not match the actual +description. Fix this. + +Signed-off-by: Christian Borntraeger +Message-Id: <20190715142304.215018-4-borntraeger@de.ibm.com> +[CH: vxp->vxpdeh, as discussed] +Reviewed-by: David Hildenbrand +Reviewed-by: Thomas Huth +Signed-off-by: Cornelia Huck +(cherry picked from commit 5d8866c89817998a3d9c3055d5dc2b5a8e78658a) +Signed-off-by: David Hildenbrand + +Signed-off-by: Danilo C. L. de Paula +--- + target/s390x/cpu_features_def.h | 2 +- + target/s390x/gen-features.c | 4 ++-- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/target/s390x/cpu_features_def.h b/target/s390x/cpu_features_def.h +index 292b17b..a7abe4d 100644 +--- a/target/s390x/cpu_features_def.h ++++ b/target/s390x/cpu_features_def.h +@@ -99,7 +99,7 @@ typedef enum { + S390_FEAT_VECTOR_ENH2, + S390_FEAT_ESORT_BASE, + S390_FEAT_DEFLATE_BASE, +- S390_FEAT_VECTOR_BCD_ENH, ++ S390_FEAT_VECTOR_PACKED_DECIMAL_ENH, + S390_FEAT_MSA_EXT_9, + S390_FEAT_ETOKEN, + +diff --git a/target/s390x/gen-features.c b/target/s390x/gen-features.c +index 384d60a..24d78e9 100644 +--- a/target/s390x/gen-features.c ++++ b/target/s390x/gen-features.c +@@ -557,7 +557,7 @@ static uint16_t full_GEN15_GA1[] = { + S390_FEAT_VECTOR_ENH2, + S390_FEAT_GROUP_ENH_SORT, + S390_FEAT_GROUP_DEFLATE_CONVERSION, +- S390_FEAT_VECTOR_BCD_ENH, ++ S390_FEAT_VECTOR_PACKED_DECIMAL_ENH, + S390_FEAT_GROUP_MSA_EXT_9, + S390_FEAT_GROUP_MSA_EXT_9_PCKMO, + S390_FEAT_ETOKEN, +@@ -648,7 +648,7 @@ static uint16_t default_GEN14_GA2[] = { + static uint16_t default_GEN15_GA1[] = { + S390_FEAT_VECTOR_ENH2, + S390_FEAT_GROUP_DEFLATE_CONVERSION, +- S390_FEAT_VECTOR_BCD_ENH, ++ S390_FEAT_VECTOR_PACKED_DECIMAL_ENH, + S390_FEAT_GROUP_MSA_EXT_9, + S390_FEAT_GROUP_MSA_EXT_9_PCKMO, + S390_FEAT_ETOKEN, +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390x-cpumodel-remove-esort-from-the-default-model.patch b/SOURCES/kvm-s390x-cpumodel-remove-esort-from-the-default-model.patch new file mode 100644 index 0000000..437c871 --- /dev/null +++ b/SOURCES/kvm-s390x-cpumodel-remove-esort-from-the-default-model.patch @@ -0,0 +1,44 @@ +From 87e37d8c60b92b595e6199f9ea6b10d8502aa564 Mon Sep 17 00:00:00 2001 +From: David Hildenbrand +Date: Tue, 16 Jul 2019 20:44:20 +0100 +Subject: [PATCH 18/39] s390x/cpumodel: remove esort from the default model + +RH-Author: David Hildenbrand +Message-id: <20190716204422.9350-3-david@redhat.com> +Patchwork-id: 89549 +O-Subject: [RHEL8.1 qemu-kvm PATCH 2/4] s390x/cpumodel: remove esort from the default model +Bugzilla: 1729975 +RH-Acked-by: Thomas Huth +RH-Acked-by: Cornelia Huck +RH-Acked-by: Jens Freimann + +esort might not be available on all models. + +Fixes: caef62430fed6e73 ("s390x/cpumodel: add gen15 defintions") +Signed-off-by: Christian Borntraeger +Message-Id: <20190715142304.215018-2-borntraeger@de.ibm.com> +Reviewed-by: David Hildenbrand +Reviewed-by: Thomas Huth +Signed-off-by: Cornelia Huck +(cherry picked from commit de6bb08570065eb318849dfd7f316448e51197b5) +Signed-off-by: David Hildenbrand +Signed-off-by: Danilo C. L. de Paula +--- + target/s390x/gen-features.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/target/s390x/gen-features.c b/target/s390x/gen-features.c +index 818d51c..384d60a 100644 +--- a/target/s390x/gen-features.c ++++ b/target/s390x/gen-features.c +@@ -647,7 +647,6 @@ static uint16_t default_GEN14_GA2[] = { + + static uint16_t default_GEN15_GA1[] = { + S390_FEAT_VECTOR_ENH2, +- S390_FEAT_GROUP_ENH_SORT, + S390_FEAT_GROUP_DEFLATE_CONVERSION, + S390_FEAT_VECTOR_BCD_ENH, + S390_FEAT_GROUP_MSA_EXT_9, +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390x-vfio-ap-Implement-hot-plug-unplug-of-vfio-ap-d.patch b/SOURCES/kvm-s390x-vfio-ap-Implement-hot-plug-unplug-of-vfio-ap-d.patch new file mode 100644 index 0000000..af41a46 --- /dev/null +++ b/SOURCES/kvm-s390x-vfio-ap-Implement-hot-plug-unplug-of-vfio-ap-d.patch @@ -0,0 +1,153 @@ +From e855a53f491f73e05e2b6542fb556ad80d45f89e Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Thu, 17 Oct 2019 08:43:01 +0100 +Subject: [PATCH 21/21] s390x/vfio-ap: Implement hot plug/unplug of vfio-ap + device + +RH-Author: Thomas Huth +Message-id: <20191017084301.8658-2-thuth@redhat.com> +Patchwork-id: 91819 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH 1/1] s390x/vfio-ap: Implement hot plug/unplug of vfio-ap device +Bugzilla: 1660906 +RH-Acked-by: David Hildenbrand +RH-Acked-by: Cornelia Huck +RH-Acked-by: John Snow + +From: Tony Krowiak + +Introduces hot plug/unplug support for the vfio-ap device. + +To hot plug a vfio-ap device using the QEMU device_add command: + + (qemu) device_add vfio-ap,sysfsdev=$path-to-mdev + + Where $path-to-mdev is the absolute path to the mediated matrix device + to which AP resources to be used by the guest have been assigned. + +A vfio-ap device can be hot plugged only if: + +1. A vfio-ap device has not been attached to the virtual machine's ap-bus + via the QEMU command line or a prior hot plug action. + +2. The guest was started with the CPU model feature for AP enabled + (e.g., -cpu host,ap=on) + +To hot unplug a vfio-ap device using the QEMU device_del command: + + (qemu) device_del vfio-ap,sysfsdev=$path-to-mdev + + Where $path-to-mdev is the absolute path to the mediated matrix device + specified when the vfio-ap device was attached to the virtual machine's + ap-bus. + +A vfio-ap device can be hot unplugged only if: + +1. A vfio-ap device has been attached to the virtual machine's ap-bus + via the QEMU command line or a prior hot plug action. + +2. The guest was started with the CPU model feature for AP enabled + (e.g., -cpu host,ap=on) + +Please note that a hot plug handler is not necessary for the vfio-ap device +because the AP matrix configuration for the guest is performed by the +kernel device driver when the vfio-ap device is realized. The vfio-ap device +represents a VFIO mediated device created in the host sysfs for use by a guest. +The mdev device is configured with an AP matrix (i.e., adapters and domains) via +its sysfs attribute interfaces prior to starting the guest or plugging a vfio-ap +device in. When the device is realized, a file descriptor is opened on the mdev +device which results in a callback to the vfio_ap kernel device driver. The +device driver then configures the AP matrix in the guest's SIE state description +from the AP matrix assigned via the mdev device's sysfs interfaces. The AP +devices will be created for the guest when the AP bus running on the guest +subsequently performs its periodic scan for AP devices. + +The qdev_simple_device_unplug_cb() callback function is used for the same +reaons; namely, the vfio_ap kernel device driver will perform the AP resource +de-configuration for the guest when the vfio-ap device is unplugged. When the +vfio-ap device is unrealized, the mdev device file descriptor is closed which +results in a callback to the vfio_ap kernel device driver. The device driver +then clears the AP matrix configuration in the guest's SIE state description +and resets all of the affected queues. The AP devices created for the guest +will be removed when the AP bus running on the guest subsequently performs +its periodic scan and finds there are no longer any AP resources assigned to the +guest. + +Signed-off-by: Tony Krowiak +Reviewed-by: Pierre Morel +Reviewed-by: David Hildenbrand +Reviewed-by: Halil Pasic +Tested-by: Pierre Morel +Message-Id: <1550519397-25359-2-git-send-email-akrowiak@linux.ibm.com> +[CH: adapt to changed qbus_set_hotplug_handler() signature] +Signed-off-by: Cornelia Huck +(cherry picked from commit 374b78e37029b05f7ee2f40d0d0aabf5b5b03ce0) + +Changed the qbus_set_hotplug_handler() line for RHEL: We do no have +commit 94d1cc5f03a in downstream, so no need for the OBJECT() cast here. + +Signed-off-by: Thomas Huth +Signed-off-by: Danilo C. L. de Paula +--- + hw/s390x/ap-bridge.c | 12 +++++++++++- + hw/vfio/ap.c | 2 +- + 2 files changed, 12 insertions(+), 2 deletions(-) + +diff --git a/hw/s390x/ap-bridge.c b/hw/s390x/ap-bridge.c +index 3795d30..25a0341 100644 +--- a/hw/s390x/ap-bridge.c ++++ b/hw/s390x/ap-bridge.c +@@ -39,6 +39,7 @@ static const TypeInfo ap_bus_info = { + void s390_init_ap(void) + { + DeviceState *dev; ++ BusState *bus; + + /* If no AP instructions then no need for AP bridge */ + if (!s390_has_feat(S390_FEAT_AP)) { +@@ -52,13 +53,18 @@ void s390_init_ap(void) + qdev_init_nofail(dev); + + /* Create bus on bridge device */ +- qbus_create(TYPE_AP_BUS, dev, TYPE_AP_BUS); ++ bus = qbus_create(TYPE_AP_BUS, dev, TYPE_AP_BUS); ++ ++ /* Enable hotplugging */ ++ qbus_set_hotplug_handler(bus, dev, &error_abort); + } + + static void ap_bridge_class_init(ObjectClass *oc, void *data) + { + DeviceClass *dc = DEVICE_CLASS(oc); ++ HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc); + ++ hc->unplug = qdev_simple_device_unplug_cb; + set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); + } + +@@ -67,6 +73,10 @@ static const TypeInfo ap_bridge_info = { + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = 0, + .class_init = ap_bridge_class_init, ++ .interfaces = (InterfaceInfo[]) { ++ { TYPE_HOTPLUG_HANDLER }, ++ { } ++ } + }; + + static void ap_register(void) +diff --git a/hw/vfio/ap.c b/hw/vfio/ap.c +index 3962bb7..a899f8e 100644 +--- a/hw/vfio/ap.c ++++ b/hw/vfio/ap.c +@@ -161,7 +161,7 @@ static void vfio_ap_class_init(ObjectClass *klass, void *data) + set_bit(DEVICE_CATEGORY_MISC, dc->categories); + dc->realize = vfio_ap_realize; + dc->unrealize = vfio_ap_unrealize; +- dc->hotpluggable = false; ++ dc->hotpluggable = true; + dc->reset = vfio_ap_reset; + dc->bus_type = TYPE_AP_BUS; + } +-- +1.8.3.1 + diff --git a/SOURCES/kvm-slirp-check-sscanf-result-when-emulating-ident.patch b/SOURCES/kvm-slirp-check-sscanf-result-when-emulating-ident.patch new file mode 100644 index 0000000..1cd1228 --- /dev/null +++ b/SOURCES/kvm-slirp-check-sscanf-result-when-emulating-ident.patch @@ -0,0 +1,62 @@ +From 49fbfce352a678b538113598cba05c48281174a4 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Wed, 24 Jul 2019 15:53:34 +0100 +Subject: [PATCH 09/14] slirp: check sscanf result when emulating ident +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Philippe Mathieu-Daudé +Message-id: <20190724155337.25303-2-philmd@redhat.com> +Patchwork-id: 89675 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v2 1/4] slirp: check sscanf result when emulating ident +Bugzilla: 1727642 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Marc-André Lureau +RH-Acked-by: Thomas Huth + +From: William Bowling + +When emulating ident in tcp_emu, if the strchr checks passed but the +sscanf check failed, two uninitialized variables would be copied and +sent in the reply, so move this code inside the if(sscanf()) clause. + +Signed-off-by: William Bowling +Cc: qemu-stable@nongnu.org +Cc: secalert@redhat.com +Message-Id: <1551476756-25749-1-git-send-email-will@wbowling.info> +Signed-off-by: Samuel Thibault +Reviewed-by: Philippe Mathieu-Daudé +(cherry picked from commit d3222975c7d6cda9e25809dea05241188457b113) +Fixes: CVE-2019-9824 +Signed-off-by: Philippe Mathieu-Daudé +Signed-off-by: Danilo C. L. de Paula +--- + slirp/tcp_subr.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/slirp/tcp_subr.c b/slirp/tcp_subr.c +index 1c7eb28..af1b3eb 100644 +--- a/slirp/tcp_subr.c ++++ b/slirp/tcp_subr.c +@@ -665,12 +665,12 @@ tcp_emu(struct socket *so, struct mbuf *m) + break; + } + } ++ so_rcv->sb_cc = snprintf(so_rcv->sb_data, ++ so_rcv->sb_datalen, ++ "%d,%d\r\n", n1, n2); ++ so_rcv->sb_rptr = so_rcv->sb_data; ++ so_rcv->sb_wptr = so_rcv->sb_data + so_rcv->sb_cc; + } +- so_rcv->sb_cc = snprintf(so_rcv->sb_data, +- so_rcv->sb_datalen, +- "%d,%d\r\n", n1, n2); +- so_rcv->sb_rptr = so_rcv->sb_data; +- so_rcv->sb_wptr = so_rcv->sb_data + so_rcv->sb_cc; + } + m_free(m); + return 0; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-slirp-don-t-manipulate-so_rcv-in-tcp_emu.patch b/SOURCES/kvm-slirp-don-t-manipulate-so_rcv-in-tcp_emu.patch new file mode 100644 index 0000000..0ae23ce --- /dev/null +++ b/SOURCES/kvm-slirp-don-t-manipulate-so_rcv-in-tcp_emu.patch @@ -0,0 +1,131 @@ +From e63645b8e4335e71721defc01db16db7cebe09b8 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Wed, 24 Jul 2019 15:53:37 +0100 +Subject: [PATCH 12/14] slirp: don't manipulate so_rcv in tcp_emu() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Philippe Mathieu-Daudé +Message-id: <20190724155337.25303-5-philmd@redhat.com> +Patchwork-id: 89676 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v2 4/4] slirp: don't manipulate so_rcv in tcp_emu() +Bugzilla: 1727642 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Marc-André Lureau +RH-Acked-by: Thomas Huth + +From: Marc-André Lureau + +For some reason, EMU_IDENT is not like other "emulated" protocols and +tries to reconstitute the original buffer, if it came in multiple +packets. Unfortunately, it does so wrongly, as it doesn't respect the +sbuf circular buffer appending rules, nor does it maintain some of the +invariants (rptr is incremented without bounds, etc): this leads to +further memory corruption revealed by ASAN or various malloc +errors. Furthermore, the so_rcv buffer is regularly flushed, so there +is no guarantee that buffer reconstruction will do what is expected. + +Instead, do what the function comment says: "XXX Assumes the whole +command came in one packet", and don't touch so_rcv. + +Related to: https://bugzilla.redhat.com/show_bug.cgi?id=1664205 + +Cc: Prasad J Pandit +Signed-off-by: Marc-André Lureau + +(cherry picked from libslirp commit +9da0da837780f825b5db31db6620492f8b7cd5d6) +[ MA - backported with style conflicts, and without qemu commit +a7104eda7dab99d0cdbd3595c211864cba415905 which is unnecessary with +this patch ] +Signed-off-by: Marc-André Lureau +Signed-off-by: Philippe Mathieu-Daudé + +Signed-off-by: Danilo C. L. de Paula +--- + slirp/tcp_subr.c | 62 ++++++++++++++++++++++++-------------------------------- + 1 file changed, 27 insertions(+), 35 deletions(-) + +diff --git a/slirp/tcp_subr.c b/slirp/tcp_subr.c +index e245e0d..0152f72 100644 +--- a/slirp/tcp_subr.c ++++ b/slirp/tcp_subr.c +@@ -636,47 +636,39 @@ tcp_emu(struct socket *so, struct mbuf *m) + struct socket *tmpso; + struct sockaddr_in addr; + socklen_t addrlen = sizeof(struct sockaddr_in); +- struct sbuf *so_rcv = &so->so_rcv; ++ char *eol = g_strstr_len(m->m_data, m->m_len, "\r\n"); + +- if (m->m_len > so_rcv->sb_datalen +- - (so_rcv->sb_wptr - so_rcv->sb_data)) { +- return 1; ++ if (!eol) { ++ return 1; + } + +- memcpy(so_rcv->sb_wptr, m->m_data, m->m_len); +- so_rcv->sb_wptr += m->m_len; +- so_rcv->sb_rptr += m->m_len; +- m_inc(m, m->m_len + 1); +- m->m_data[m->m_len] = 0; /* NULL terminate */ +- if (strchr(m->m_data, '\r') || strchr(m->m_data, '\n')) { +- if (sscanf(so_rcv->sb_data, "%u%*[ ,]%u", &n1, &n2) == 2) { +- HTONS(n1); +- HTONS(n2); +- /* n2 is the one on our host */ +- for (tmpso = slirp->tcb.so_next; +- tmpso != &slirp->tcb; +- tmpso = tmpso->so_next) { +- if (tmpso->so_laddr.s_addr == so->so_laddr.s_addr && +- tmpso->so_lport == n2 && +- tmpso->so_faddr.s_addr == so->so_faddr.s_addr && +- tmpso->so_fport == n1) { +- if (getsockname(tmpso->s, +- (struct sockaddr *)&addr, &addrlen) == 0) +- n2 = addr.sin_port; +- break; +- } ++ *eol = '\0'; ++ if (sscanf(m->m_data, "%u%*[ ,]%u", &n1, &n2) == 2) { ++ HTONS(n1); ++ HTONS(n2); ++ /* n2 is the one on our host */ ++ for (tmpso = slirp->tcb.so_next; tmpso != &slirp->tcb; ++ tmpso = tmpso->so_next) { ++ if (tmpso->so_laddr.s_addr == so->so_laddr.s_addr && ++ tmpso->so_lport == n2 && ++ tmpso->so_faddr.s_addr == so->so_faddr.s_addr && ++ tmpso->so_fport == n1) { ++ if (getsockname(tmpso->s, (struct sockaddr *)&addr, ++ &addrlen) == 0) ++ n2 = addr.sin_port; ++ break; + } +- NTOHS(n1); +- NTOHS(n2); +- so_rcv->sb_cc = snprintf(so_rcv->sb_data, +- so_rcv->sb_datalen, +- "%d,%d\r\n", n1, n2); +- so_rcv->sb_rptr = so_rcv->sb_data; +- so_rcv->sb_wptr = so_rcv->sb_data + so_rcv->sb_cc; + } ++ NTOHS(n1); ++ NTOHS(n2); ++ m_inc(m, snprintf(NULL, 0, "%d,%d\r\n", n1, n2) + 1); ++ m->m_len = snprintf(m->m_data, M_ROOM(m), "%d,%d\r\n", n1, n2); ++ assert(m->m_len < M_ROOM(m)); ++ } else { ++ *eol = '\r'; + } +- m_free(m); +- return 0; ++ ++ return 1; + } + + case EMU_FTP: /* ftp */ +-- +1.8.3.1 + diff --git a/SOURCES/kvm-slirp-ensure-there-is-enough-space-in-mbuf-to-null-t.patch b/SOURCES/kvm-slirp-ensure-there-is-enough-space-in-mbuf-to-null-t.patch new file mode 100644 index 0000000..96e39d3 --- /dev/null +++ b/SOURCES/kvm-slirp-ensure-there-is-enough-space-in-mbuf-to-null-t.patch @@ -0,0 +1,71 @@ +From ad30988fde29143951447e7f973918eaa09c448c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Wed, 24 Jul 2019 15:53:36 +0100 +Subject: [PATCH 11/14] slirp: ensure there is enough space in mbuf to + null-terminate +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Philippe Mathieu-Daudé +Message-id: <20190724155337.25303-4-philmd@redhat.com> +Patchwork-id: 89678 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v2 3/4] slirp: ensure there is enough space in mbuf to null-terminate +Bugzilla: 1727642 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Marc-André Lureau +RH-Acked-by: Thomas Huth + +From: Marc-André Lureau + +Prevents from buffer overflows. +Related to: https://bugzilla.redhat.com/show_bug.cgi?id=1664205 + +Cc: Prasad J Pandit +Signed-off-by: Marc-André Lureau + +(cherry picked from libslirp commit +306fef58b54d793ba4b259728c21322765bda917) + +[ MA - backported with style conflicts fixes ] +Signed-off-by: Marc-André Lureau +Signed-off-by: Miroslav Rezanina +(cherry picked from commit e80c12dfdbde349dcd225771a4801b47be0b3b5f) +Signed-off-by: Philippe Mathieu-Daudé + +Signed-off-by: Danilo C. L. de Paula +--- + slirp/tcp_subr.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/slirp/tcp_subr.c b/slirp/tcp_subr.c +index 393447d..e245e0d 100644 +--- a/slirp/tcp_subr.c ++++ b/slirp/tcp_subr.c +@@ -646,6 +646,7 @@ tcp_emu(struct socket *so, struct mbuf *m) + memcpy(so_rcv->sb_wptr, m->m_data, m->m_len); + so_rcv->sb_wptr += m->m_len; + so_rcv->sb_rptr += m->m_len; ++ m_inc(m, m->m_len + 1); + m->m_data[m->m_len] = 0; /* NULL terminate */ + if (strchr(m->m_data, '\r') || strchr(m->m_data, '\n')) { + if (sscanf(so_rcv->sb_data, "%u%*[ ,]%u", &n1, &n2) == 2) { +@@ -679,6 +680,7 @@ tcp_emu(struct socket *so, struct mbuf *m) + } + + case EMU_FTP: /* ftp */ ++ m_inc(m, m->m_len + 1); + *(m->m_data+m->m_len) = 0; /* NUL terminate for strstr */ + if ((bptr = (char *)strstr(m->m_data, "ORT")) != NULL) { + /* +@@ -776,6 +778,7 @@ tcp_emu(struct socket *so, struct mbuf *m) + /* + * Need to emulate DCC CHAT, DCC SEND and DCC MOVE + */ ++ m_inc(m, m->m_len + 1); + *(m->m_data+m->m_len) = 0; /* NULL terminate the string for strstr */ + if ((bptr = (char *)strstr(m->m_data, "DCC")) == NULL) + return 1; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-slirp-fix-big-little-endian-conversion-in-ident-prot.patch b/SOURCES/kvm-slirp-fix-big-little-endian-conversion-in-ident-prot.patch new file mode 100644 index 0000000..38c4c71 --- /dev/null +++ b/SOURCES/kvm-slirp-fix-big-little-endian-conversion-in-ident-prot.patch @@ -0,0 +1,50 @@ +From f4157e1c90e8986d95a57bf00cc8c0e297869c35 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Wed, 24 Jul 2019 15:53:35 +0100 +Subject: [PATCH 10/14] slirp: fix big/little endian conversion in ident + protocol +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Philippe Mathieu-Daudé +Message-id: <20190724155337.25303-3-philmd@redhat.com> +Patchwork-id: 89674 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v2 2/4] slirp: fix big/little endian conversion in ident protocol +Bugzilla: 1727642 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Marc-André Lureau +RH-Acked-by: Thomas Huth + +From: Samuel Thibault + +Signed-off-by: Samuel Thibault +Reviewed-by: Philippe Mathieu-Daudé +(cherry picked from commit 1fd71067dae501f1c78618e9583c6cc72db0cfa6) +Signed-off-by: Philippe Mathieu-Daudé +Signed-off-by: Danilo C. L. de Paula +--- + slirp/tcp_subr.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/slirp/tcp_subr.c b/slirp/tcp_subr.c +index af1b3eb..393447d 100644 +--- a/slirp/tcp_subr.c ++++ b/slirp/tcp_subr.c +@@ -661,10 +661,12 @@ tcp_emu(struct socket *so, struct mbuf *m) + tmpso->so_fport == n1) { + if (getsockname(tmpso->s, + (struct sockaddr *)&addr, &addrlen) == 0) +- n2 = ntohs(addr.sin_port); ++ n2 = addr.sin_port; + break; + } + } ++ NTOHS(n1); ++ NTOHS(n2); + so_rcv->sb_cc = snprintf(so_rcv->sb_data, + so_rcv->sb_datalen, + "%d,%d\r\n", n1, n2); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-ssh-switch-from-libssh2-to-libssh.patch b/SOURCES/kvm-ssh-switch-from-libssh2-to-libssh.patch new file mode 100644 index 0000000..9473ffc --- /dev/null +++ b/SOURCES/kvm-ssh-switch-from-libssh2-to-libssh.patch @@ -0,0 +1,1526 @@ +From 4d4eb9e793e7722c05c697812320a14ae5797bae Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Mon, 8 Jul 2019 15:26:00 +0100 +Subject: [PATCH 14/39] ssh: switch from libssh2 to libssh +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Pino Toscano +Message-id: <20190708152601.21123-10-ptoscano@redhat.com> +Patchwork-id: 89421 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v3 09/10] ssh: switch from libssh2 to libssh +Bugzilla: 1513367 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Max Reitz +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Markus Armbruster + +Rewrite the implementation of the ssh block driver to use libssh instead +of libssh2. The libssh library has various advantages over libssh2: +- easier API for authentication (for example for using ssh-agent) +- easier API for known_hosts handling +- supports newer types of keys in known_hosts + +Use APIs/features available in libssh 0.8 conditionally, to support +older versions (which are not recommended though). + +Adjust the iotest 207 according to the different error message, and to +find the default key type for localhost (to properly compare the +fingerprint with). +Contributed-by: Max Reitz + +Adjust the various Docker/Travis scripts to use libssh when available +instead of libssh2. The mingw/mxe testing is dropped for now, as there +are no packages for it. + +Signed-off-by: Pino Toscano +Tested-by: Philippe Mathieu-Daudé +Acked-by: Alex Bennée +Message-id: 20190620200840.17655-1-ptoscano@redhat.com +Reviewed-by: Philippe Mathieu-Daudé +Message-id: 5873173.t2JhDm7DL7@lindworm.usersys.redhat.com +Signed-off-by: Max Reitz +(cherry picked from commit b10d49d7619e4957b4b971f816661b57e5061d71) +Signed-off-by: Pino Toscano +Signed-off-by: Danilo C. L. de Paula +--- + .travis.yml | 4 +- + block/Makefile.objs | 6 +- + block/ssh.c | 652 ++++++++++++--------- + block/trace-events | 14 +- + configure | 65 +- + docs/qemu-block-drivers.texi | 2 +- + tests/docker/dockerfiles/debian-win32-cross.docker | 1 - + tests/docker/dockerfiles/debian-win64-cross.docker | 1 - + tests/docker/dockerfiles/fedora.docker | 6 +- + tests/docker/dockerfiles/ubuntu.docker | 2 +- + tests/qemu-iotests/207 | 54 +- + tests/qemu-iotests/207.out | 2 +- + 12 files changed, 450 insertions(+), 359 deletions(-) + +diff --git a/.travis.yml b/.travis.yml +index c1e9923..d174d82 100644 +--- a/.travis.yml ++++ b/.travis.yml +@@ -28,7 +28,7 @@ addons: + - libseccomp-dev + - libspice-protocol-dev + - libspice-server-dev +- - libssh2-1-dev ++ - libssh-dev + - liburcu-dev + - libusb-1.0-0-dev + - libvte-2.90-dev +@@ -188,7 +188,7 @@ matrix: + - libseccomp-dev + - libspice-protocol-dev + - libspice-server-dev +- - libssh2-1-dev ++ - libssh-dev + - liburcu-dev + - libusb-1.0-0-dev + - libvte-2.90-dev +diff --git a/block/Makefile.objs b/block/Makefile.objs +index ac7a1f8..51cd336 100644 +--- a/block/Makefile.objs ++++ b/block/Makefile.objs +@@ -30,7 +30,7 @@ block-obj-$(CONFIG_CURL) += curl.o + block-obj-$(CONFIG_RBD) += rbd.o + block-obj-$(CONFIG_GLUSTERFS) += gluster.o + block-obj-$(CONFIG_VXHS) += vxhs.o +-block-obj-$(CONFIG_LIBSSH2) += ssh.o ++block-obj-$(CONFIG_LIBSSH) += ssh.o + block-obj-y += accounting.o dirty-bitmap.o + block-obj-y += write-threshold.o + block-obj-y += backup.o +@@ -51,8 +51,8 @@ rbd.o-libs := $(RBD_LIBS) + gluster.o-cflags := $(GLUSTERFS_CFLAGS) + gluster.o-libs := $(GLUSTERFS_LIBS) + vxhs.o-libs := $(VXHS_LIBS) +-ssh.o-cflags := $(LIBSSH2_CFLAGS) +-ssh.o-libs := $(LIBSSH2_LIBS) ++ssh.o-cflags := $(LIBSSH_CFLAGS) ++ssh.o-libs := $(LIBSSH_LIBS) + block-obj-dmg-bz2-$(CONFIG_BZIP2) += dmg-bz2.o + block-obj-$(if $(CONFIG_DMG),m,n) += $(block-obj-dmg-bz2-y) + dmg-bz2.o-libs := $(BZIP2_LIBS) +diff --git a/block/ssh.c b/block/ssh.c +index f0ef874..a4a374c 100644 +--- a/block/ssh.c ++++ b/block/ssh.c +@@ -24,8 +24,8 @@ + + #include "qemu/osdep.h" + +-#include +-#include ++#include ++#include + + #include "block/block_int.h" + #include "block/qdict.h" +@@ -44,13 +44,11 @@ + #include "trace.h" + + /* +- * TRACE_LIBSSH2= enables tracing in libssh2 itself. Note +- * that this requires that libssh2 was specially compiled with the +- * `./configure --enable-debug' option, so most likely you will have +- * to compile it yourself. The meaning of is described +- * here: http://www.libssh2.org/libssh2_trace.html ++ * TRACE_LIBSSH= enables tracing in libssh itself. ++ * The meaning of is described here: ++ * http://api.libssh.org/master/group__libssh__log.html + */ +-#define TRACE_LIBSSH2 0 /* or try: LIBSSH2_TRACE_SFTP */ ++#define TRACE_LIBSSH 0 /* see: SSH_LOG_* */ + + typedef struct BDRVSSHState { + /* Coroutine. */ +@@ -58,18 +56,15 @@ typedef struct BDRVSSHState { + + /* SSH connection. */ + int sock; /* socket */ +- LIBSSH2_SESSION *session; /* ssh session */ +- LIBSSH2_SFTP *sftp; /* sftp session */ +- LIBSSH2_SFTP_HANDLE *sftp_handle; /* sftp remote file handle */ ++ ssh_session session; /* ssh session */ ++ sftp_session sftp; /* sftp session */ ++ sftp_file sftp_handle; /* sftp remote file handle */ + +- /* See ssh_seek() function below. */ +- int64_t offset; +- bool offset_op_read; +- +- /* File attributes at open. We try to keep the .filesize field ++ /* ++ * File attributes at open. We try to keep the .size field + * updated if it changes (eg by writing at the end of the file). + */ +- LIBSSH2_SFTP_ATTRIBUTES attrs; ++ sftp_attributes attrs; + + InetSocketAddress *inet; + +@@ -89,7 +84,6 @@ static void ssh_state_init(BDRVSSHState *s) + { + memset(s, 0, sizeof *s); + s->sock = -1; +- s->offset = -1; + qemu_co_mutex_init(&s->lock); + } + +@@ -97,20 +91,18 @@ static void ssh_state_free(BDRVSSHState *s) + { + g_free(s->user); + ++ if (s->attrs) { ++ sftp_attributes_free(s->attrs); ++ } + if (s->sftp_handle) { +- libssh2_sftp_close(s->sftp_handle); ++ sftp_close(s->sftp_handle); + } + if (s->sftp) { +- libssh2_sftp_shutdown(s->sftp); ++ sftp_free(s->sftp); + } + if (s->session) { +- libssh2_session_disconnect(s->session, +- "from qemu ssh client: " +- "user closed the connection"); +- libssh2_session_free(s->session); +- } +- if (s->sock >= 0) { +- close(s->sock); ++ ssh_disconnect(s->session); ++ ssh_free(s->session); /* This frees s->sock */ + } + } + +@@ -125,13 +117,13 @@ session_error_setg(Error **errp, BDRVSSHState *s, const char *fs, ...) + va_end(args); + + if (s->session) { +- char *ssh_err; ++ const char *ssh_err; + int ssh_err_code; + +- /* This is not an errno. See . */ +- ssh_err_code = libssh2_session_last_error(s->session, +- &ssh_err, NULL, 0); +- error_setg(errp, "%s: %s (libssh2 error code: %d)", ++ /* This is not an errno. See . */ ++ ssh_err = ssh_get_error(s->session); ++ ssh_err_code = ssh_get_error_code(s->session); ++ error_setg(errp, "%s: %s (libssh error code: %d)", + msg, ssh_err, ssh_err_code); + } else { + error_setg(errp, "%s", msg); +@@ -150,18 +142,18 @@ sftp_error_setg(Error **errp, BDRVSSHState *s, const char *fs, ...) + va_end(args); + + if (s->sftp) { +- char *ssh_err; ++ const char *ssh_err; + int ssh_err_code; +- unsigned long sftp_err_code; ++ int sftp_err_code; + +- /* This is not an errno. See . */ +- ssh_err_code = libssh2_session_last_error(s->session, +- &ssh_err, NULL, 0); +- /* See . */ +- sftp_err_code = libssh2_sftp_last_error((s)->sftp); ++ /* This is not an errno. See . */ ++ ssh_err = ssh_get_error(s->session); ++ ssh_err_code = ssh_get_error_code(s->session); ++ /* See . */ ++ sftp_err_code = sftp_get_error(s->sftp); + + error_setg(errp, +- "%s: %s (libssh2 error code: %d, sftp error code: %lu)", ++ "%s: %s (libssh error code: %d, sftp error code: %d)", + msg, ssh_err, ssh_err_code, sftp_err_code); + } else { + error_setg(errp, "%s", msg); +@@ -171,15 +163,15 @@ sftp_error_setg(Error **errp, BDRVSSHState *s, const char *fs, ...) + + static void sftp_error_trace(BDRVSSHState *s, const char *op) + { +- char *ssh_err; ++ const char *ssh_err; + int ssh_err_code; +- unsigned long sftp_err_code; ++ int sftp_err_code; + +- /* This is not an errno. See . */ +- ssh_err_code = libssh2_session_last_error(s->session, +- &ssh_err, NULL, 0); +- /* See . */ +- sftp_err_code = libssh2_sftp_last_error((s)->sftp); ++ /* This is not an errno. See . */ ++ ssh_err = ssh_get_error(s->session); ++ ssh_err_code = ssh_get_error_code(s->session); ++ /* See . */ ++ sftp_err_code = sftp_get_error(s->sftp); + + trace_sftp_error(op, ssh_err, ssh_err_code, sftp_err_code); + } +@@ -280,82 +272,120 @@ static void ssh_parse_filename(const char *filename, QDict *options, + parse_uri(filename, options, errp); + } + +-static int check_host_key_knownhosts(BDRVSSHState *s, +- const char *host, int port, Error **errp) ++static int check_host_key_knownhosts(BDRVSSHState *s, Error **errp) + { +- const char *home; +- char *knh_file = NULL; +- LIBSSH2_KNOWNHOSTS *knh = NULL; +- struct libssh2_knownhost *found; +- int ret, r; +- const char *hostkey; +- size_t len; +- int type; +- +- hostkey = libssh2_session_hostkey(s->session, &len, &type); +- if (!hostkey) { ++ int ret; ++#ifdef HAVE_LIBSSH_0_8 ++ enum ssh_known_hosts_e state; ++ int r; ++ ssh_key pubkey; ++ enum ssh_keytypes_e pubkey_type; ++ unsigned char *server_hash = NULL; ++ size_t server_hash_len; ++ char *fingerprint = NULL; ++ ++ state = ssh_session_is_known_server(s->session); ++ trace_ssh_server_status(state); ++ ++ switch (state) { ++ case SSH_KNOWN_HOSTS_OK: ++ /* OK */ ++ trace_ssh_check_host_key_knownhosts(); ++ break; ++ case SSH_KNOWN_HOSTS_CHANGED: + ret = -EINVAL; +- session_error_setg(errp, s, "failed to read remote host key"); ++ r = ssh_get_server_publickey(s->session, &pubkey); ++ if (r == 0) { ++ r = ssh_get_publickey_hash(pubkey, SSH_PUBLICKEY_HASH_SHA256, ++ &server_hash, &server_hash_len); ++ pubkey_type = ssh_key_type(pubkey); ++ ssh_key_free(pubkey); ++ } ++ if (r == 0) { ++ fingerprint = ssh_get_fingerprint_hash(SSH_PUBLICKEY_HASH_SHA256, ++ server_hash, ++ server_hash_len); ++ ssh_clean_pubkey_hash(&server_hash); ++ } ++ if (fingerprint) { ++ error_setg(errp, ++ "host key (%s key with fingerprint %s) does not match " ++ "the one in known_hosts; this may be a possible attack", ++ ssh_key_type_to_char(pubkey_type), fingerprint); ++ ssh_string_free_char(fingerprint); ++ } else { ++ error_setg(errp, ++ "host key does not match the one in known_hosts; this " ++ "may be a possible attack"); ++ } + goto out; +- } +- +- knh = libssh2_knownhost_init(s->session); +- if (!knh) { ++ case SSH_KNOWN_HOSTS_OTHER: + ret = -EINVAL; +- session_error_setg(errp, s, +- "failed to initialize known hosts support"); ++ error_setg(errp, ++ "host key for this server not found, another type exists"); ++ goto out; ++ case SSH_KNOWN_HOSTS_UNKNOWN: ++ ret = -EINVAL; ++ error_setg(errp, "no host key was found in known_hosts"); ++ goto out; ++ case SSH_KNOWN_HOSTS_NOT_FOUND: ++ ret = -ENOENT; ++ error_setg(errp, "known_hosts file not found"); ++ goto out; ++ case SSH_KNOWN_HOSTS_ERROR: ++ ret = -EINVAL; ++ error_setg(errp, "error while checking the host"); ++ goto out; ++ default: ++ ret = -EINVAL; ++ error_setg(errp, "error while checking for known server (%d)", state); + goto out; + } ++#else /* !HAVE_LIBSSH_0_8 */ ++ int state; + +- home = getenv("HOME"); +- if (home) { +- knh_file = g_strdup_printf("%s/.ssh/known_hosts", home); +- } else { +- knh_file = g_strdup_printf("/root/.ssh/known_hosts"); +- } +- +- /* Read all known hosts from OpenSSH-style known_hosts file. */ +- libssh2_knownhost_readfile(knh, knh_file, LIBSSH2_KNOWNHOST_FILE_OPENSSH); ++ state = ssh_is_server_known(s->session); ++ trace_ssh_server_status(state); + +- r = libssh2_knownhost_checkp(knh, host, port, hostkey, len, +- LIBSSH2_KNOWNHOST_TYPE_PLAIN| +- LIBSSH2_KNOWNHOST_KEYENC_RAW, +- &found); +- switch (r) { +- case LIBSSH2_KNOWNHOST_CHECK_MATCH: ++ switch (state) { ++ case SSH_SERVER_KNOWN_OK: + /* OK */ +- trace_ssh_check_host_key_knownhosts(found->key); ++ trace_ssh_check_host_key_knownhosts(); + break; +- case LIBSSH2_KNOWNHOST_CHECK_MISMATCH: ++ case SSH_SERVER_KNOWN_CHANGED: + ret = -EINVAL; +- session_error_setg(errp, s, +- "host key does not match the one in known_hosts" +- " (found key %s)", found->key); ++ error_setg(errp, ++ "host key does not match the one in known_hosts; this " ++ "may be a possible attack"); + goto out; +- case LIBSSH2_KNOWNHOST_CHECK_NOTFOUND: ++ case SSH_SERVER_FOUND_OTHER: + ret = -EINVAL; +- session_error_setg(errp, s, "no host key was found in known_hosts"); ++ error_setg(errp, ++ "host key for this server not found, another type exists"); + goto out; +- case LIBSSH2_KNOWNHOST_CHECK_FAILURE: ++ case SSH_SERVER_FILE_NOT_FOUND: ++ ret = -ENOENT; ++ error_setg(errp, "known_hosts file not found"); ++ goto out; ++ case SSH_SERVER_NOT_KNOWN: + ret = -EINVAL; +- session_error_setg(errp, s, +- "failure matching the host key with known_hosts"); ++ error_setg(errp, "no host key was found in known_hosts"); ++ goto out; ++ case SSH_SERVER_ERROR: ++ ret = -EINVAL; ++ error_setg(errp, "server error"); + goto out; + default: + ret = -EINVAL; +- session_error_setg(errp, s, "unknown error matching the host key" +- " with known_hosts (%d)", r); ++ error_setg(errp, "error while checking for known server (%d)", state); + goto out; + } ++#endif /* !HAVE_LIBSSH_0_8 */ + + /* known_hosts checking successful. */ + ret = 0; + + out: +- if (knh != NULL) { +- libssh2_knownhost_free(knh); +- } +- g_free(knh_file); + return ret; + } + +@@ -399,18 +429,34 @@ static int compare_fingerprint(const unsigned char *fingerprint, size_t len, + + static int + check_host_key_hash(BDRVSSHState *s, const char *hash, +- int hash_type, size_t fingerprint_len, Error **errp) ++ enum ssh_publickey_hash_type type, Error **errp) + { +- const char *fingerprint; +- +- fingerprint = libssh2_hostkey_hash(s->session, hash_type); +- if (!fingerprint) { ++ int r; ++ ssh_key pubkey; ++ unsigned char *server_hash; ++ size_t server_hash_len; ++ ++#ifdef HAVE_LIBSSH_0_8 ++ r = ssh_get_server_publickey(s->session, &pubkey); ++#else ++ r = ssh_get_publickey(s->session, &pubkey); ++#endif ++ if (r != SSH_OK) { + session_error_setg(errp, s, "failed to read remote host key"); + return -EINVAL; + } + +- if(compare_fingerprint((unsigned char *) fingerprint, fingerprint_len, +- hash) != 0) { ++ r = ssh_get_publickey_hash(pubkey, type, &server_hash, &server_hash_len); ++ ssh_key_free(pubkey); ++ if (r != 0) { ++ session_error_setg(errp, s, ++ "failed reading the hash of the server SSH key"); ++ return -EINVAL; ++ } ++ ++ r = compare_fingerprint(server_hash, server_hash_len, hash); ++ ssh_clean_pubkey_hash(&server_hash); ++ if (r != 0) { + error_setg(errp, "remote host key does not match host_key_check '%s'", + hash); + return -EPERM; +@@ -419,8 +465,7 @@ check_host_key_hash(BDRVSSHState *s, const char *hash, + return 0; + } + +-static int check_host_key(BDRVSSHState *s, const char *host, int port, +- SshHostKeyCheck *hkc, Error **errp) ++static int check_host_key(BDRVSSHState *s, SshHostKeyCheck *hkc, Error **errp) + { + SshHostKeyCheckMode mode; + +@@ -436,15 +481,15 @@ static int check_host_key(BDRVSSHState *s, const char *host, int port, + case SSH_HOST_KEY_CHECK_MODE_HASH: + if (hkc->u.hash.type == SSH_HOST_KEY_CHECK_HASH_TYPE_MD5) { + return check_host_key_hash(s, hkc->u.hash.hash, +- LIBSSH2_HOSTKEY_HASH_MD5, 16, errp); ++ SSH_PUBLICKEY_HASH_MD5, errp); + } else if (hkc->u.hash.type == SSH_HOST_KEY_CHECK_HASH_TYPE_SHA1) { + return check_host_key_hash(s, hkc->u.hash.hash, +- LIBSSH2_HOSTKEY_HASH_SHA1, 20, errp); ++ SSH_PUBLICKEY_HASH_SHA1, errp); + } + g_assert_not_reached(); + break; + case SSH_HOST_KEY_CHECK_MODE_KNOWN_HOSTS: +- return check_host_key_knownhosts(s, host, port, errp); ++ return check_host_key_knownhosts(s, errp); + default: + g_assert_not_reached(); + } +@@ -452,60 +497,43 @@ static int check_host_key(BDRVSSHState *s, const char *host, int port, + return -EINVAL; + } + +-static int authenticate(BDRVSSHState *s, const char *user, Error **errp) ++static int authenticate(BDRVSSHState *s, Error **errp) + { + int r, ret; +- const char *userauthlist; +- LIBSSH2_AGENT *agent = NULL; +- struct libssh2_agent_publickey *identity; +- struct libssh2_agent_publickey *prev_identity = NULL; ++ int method; + +- userauthlist = libssh2_userauth_list(s->session, user, strlen(user)); +- if (strstr(userauthlist, "publickey") == NULL) { ++ /* Try to authenticate with the "none" method. */ ++ r = ssh_userauth_none(s->session, NULL); ++ if (r == SSH_AUTH_ERROR) { + ret = -EPERM; +- error_setg(errp, +- "remote server does not support \"publickey\" authentication"); ++ session_error_setg(errp, s, "failed to authenticate using none " ++ "authentication"); + goto out; +- } +- +- /* Connect to ssh-agent and try each identity in turn. */ +- agent = libssh2_agent_init(s->session); +- if (!agent) { +- ret = -EINVAL; +- session_error_setg(errp, s, "failed to initialize ssh-agent support"); +- goto out; +- } +- if (libssh2_agent_connect(agent)) { +- ret = -ECONNREFUSED; +- session_error_setg(errp, s, "failed to connect to ssh-agent"); +- goto out; +- } +- if (libssh2_agent_list_identities(agent)) { +- ret = -EINVAL; +- session_error_setg(errp, s, +- "failed requesting identities from ssh-agent"); ++ } else if (r == SSH_AUTH_SUCCESS) { ++ /* Authenticated! */ ++ ret = 0; + goto out; + } + +- for(;;) { +- r = libssh2_agent_get_identity(agent, &identity, prev_identity); +- if (r == 1) { /* end of list */ +- break; +- } +- if (r < 0) { ++ method = ssh_userauth_list(s->session, NULL); ++ trace_ssh_auth_methods(method); ++ ++ /* ++ * Try to authenticate with publickey, using the ssh-agent ++ * if available. ++ */ ++ if (method & SSH_AUTH_METHOD_PUBLICKEY) { ++ r = ssh_userauth_publickey_auto(s->session, NULL, NULL); ++ if (r == SSH_AUTH_ERROR) { + ret = -EINVAL; +- session_error_setg(errp, s, +- "failed to obtain identity from ssh-agent"); ++ session_error_setg(errp, s, "failed to authenticate using " ++ "publickey authentication"); + goto out; +- } +- r = libssh2_agent_userauth(agent, user, identity); +- if (r == 0) { ++ } else if (r == SSH_AUTH_SUCCESS) { + /* Authenticated! */ + ret = 0; + goto out; + } +- /* Failed to authenticate with this identity, try the next one. */ +- prev_identity = identity; + } + + ret = -EPERM; +@@ -513,13 +541,6 @@ static int authenticate(BDRVSSHState *s, const char *user, Error **errp) + "and the identities held by your ssh-agent"); + + out: +- if (agent != NULL) { +- /* Note: libssh2 implementation implicitly calls +- * libssh2_agent_disconnect if necessary. +- */ +- libssh2_agent_free(agent); +- } +- + return ret; + } + +@@ -638,7 +659,8 @@ static int connect_to_ssh(BDRVSSHState *s, BlockdevOptionsSsh *opts, + int ssh_flags, int creat_mode, Error **errp) + { + int r, ret; +- long port = 0; ++ unsigned int port = 0; ++ int new_sock = -1; + + if (opts->has_user) { + s->user = g_strdup(opts->user); +@@ -655,71 +677,147 @@ static int connect_to_ssh(BDRVSSHState *s, BlockdevOptionsSsh *opts, + s->inet = opts->server; + opts->server = NULL; + +- if (qemu_strtol(s->inet->port, NULL, 10, &port) < 0) { ++ if (qemu_strtoui(s->inet->port, NULL, 10, &port) < 0) { + error_setg(errp, "Use only numeric port value"); + ret = -EINVAL; + goto err; + } + + /* Open the socket and connect. */ +- s->sock = inet_connect_saddr(s->inet, errp); +- if (s->sock < 0) { ++ new_sock = inet_connect_saddr(s->inet, errp); ++ if (new_sock < 0) { + ret = -EIO; + goto err; + } + ++ /* ++ * Try to disable the Nagle algorithm on TCP sockets to reduce latency, ++ * but do not fail if it cannot be disabled. ++ */ ++ r = socket_set_nodelay(new_sock); ++ if (r < 0) { ++ warn_report("can't set TCP_NODELAY for the ssh server %s: %s", ++ s->inet->host, strerror(errno)); ++ } ++ + /* Create SSH session. */ +- s->session = libssh2_session_init(); ++ s->session = ssh_new(); + if (!s->session) { + ret = -EINVAL; +- session_error_setg(errp, s, "failed to initialize libssh2 session"); ++ session_error_setg(errp, s, "failed to initialize libssh session"); + goto err; + } + +-#if TRACE_LIBSSH2 != 0 +- libssh2_trace(s->session, TRACE_LIBSSH2); +-#endif ++ /* ++ * Make sure we are in blocking mode during the connection and ++ * authentication phases. ++ */ ++ ssh_set_blocking(s->session, 1); + +- r = libssh2_session_handshake(s->session, s->sock); +- if (r != 0) { ++ r = ssh_options_set(s->session, SSH_OPTIONS_USER, s->user); ++ if (r < 0) { ++ ret = -EINVAL; ++ session_error_setg(errp, s, ++ "failed to set the user in the libssh session"); ++ goto err; ++ } ++ ++ r = ssh_options_set(s->session, SSH_OPTIONS_HOST, s->inet->host); ++ if (r < 0) { ++ ret = -EINVAL; ++ session_error_setg(errp, s, ++ "failed to set the host in the libssh session"); ++ goto err; ++ } ++ ++ if (port > 0) { ++ r = ssh_options_set(s->session, SSH_OPTIONS_PORT, &port); ++ if (r < 0) { ++ ret = -EINVAL; ++ session_error_setg(errp, s, ++ "failed to set the port in the libssh session"); ++ goto err; ++ } ++ } ++ ++ r = ssh_options_set(s->session, SSH_OPTIONS_COMPRESSION, "none"); ++ if (r < 0) { ++ ret = -EINVAL; ++ session_error_setg(errp, s, ++ "failed to disable the compression in the libssh " ++ "session"); ++ goto err; ++ } ++ ++ /* Read ~/.ssh/config. */ ++ r = ssh_options_parse_config(s->session, NULL); ++ if (r < 0) { ++ ret = -EINVAL; ++ session_error_setg(errp, s, "failed to parse ~/.ssh/config"); ++ goto err; ++ } ++ ++ r = ssh_options_set(s->session, SSH_OPTIONS_FD, &new_sock); ++ if (r < 0) { ++ ret = -EINVAL; ++ session_error_setg(errp, s, ++ "failed to set the socket in the libssh session"); ++ goto err; ++ } ++ /* libssh took ownership of the socket. */ ++ s->sock = new_sock; ++ new_sock = -1; ++ ++ /* Connect. */ ++ r = ssh_connect(s->session); ++ if (r != SSH_OK) { + ret = -EINVAL; + session_error_setg(errp, s, "failed to establish SSH session"); + goto err; + } + + /* Check the remote host's key against known_hosts. */ +- ret = check_host_key(s, s->inet->host, port, opts->host_key_check, errp); ++ ret = check_host_key(s, opts->host_key_check, errp); + if (ret < 0) { + goto err; + } + + /* Authenticate. */ +- ret = authenticate(s, s->user, errp); ++ ret = authenticate(s, errp); + if (ret < 0) { + goto err; + } + + /* Start SFTP. */ +- s->sftp = libssh2_sftp_init(s->session); ++ s->sftp = sftp_new(s->session); + if (!s->sftp) { +- session_error_setg(errp, s, "failed to initialize sftp handle"); ++ session_error_setg(errp, s, "failed to create sftp handle"); ++ ret = -EINVAL; ++ goto err; ++ } ++ ++ r = sftp_init(s->sftp); ++ if (r < 0) { ++ sftp_error_setg(errp, s, "failed to initialize sftp handle"); + ret = -EINVAL; + goto err; + } + + /* Open the remote file. */ + trace_ssh_connect_to_ssh(opts->path, ssh_flags, creat_mode); +- s->sftp_handle = libssh2_sftp_open(s->sftp, opts->path, ssh_flags, +- creat_mode); ++ s->sftp_handle = sftp_open(s->sftp, opts->path, ssh_flags, creat_mode); + if (!s->sftp_handle) { +- session_error_setg(errp, s, "failed to open remote file '%s'", +- opts->path); ++ sftp_error_setg(errp, s, "failed to open remote file '%s'", ++ opts->path); + ret = -EINVAL; + goto err; + } + +- r = libssh2_sftp_fstat(s->sftp_handle, &s->attrs); +- if (r < 0) { ++ /* Make sure the SFTP file is handled in blocking mode. */ ++ sftp_file_set_blocking(s->sftp_handle); ++ ++ s->attrs = sftp_fstat(s->sftp_handle); ++ if (!s->attrs) { + sftp_error_setg(errp, s, "failed to read file attributes"); + return -EINVAL; + } +@@ -727,21 +825,27 @@ static int connect_to_ssh(BDRVSSHState *s, BlockdevOptionsSsh *opts, + return 0; + + err: ++ if (s->attrs) { ++ sftp_attributes_free(s->attrs); ++ } ++ s->attrs = NULL; + if (s->sftp_handle) { +- libssh2_sftp_close(s->sftp_handle); ++ sftp_close(s->sftp_handle); + } + s->sftp_handle = NULL; + if (s->sftp) { +- libssh2_sftp_shutdown(s->sftp); ++ sftp_free(s->sftp); + } + s->sftp = NULL; + if (s->session) { +- libssh2_session_disconnect(s->session, +- "from qemu ssh client: " +- "error opening connection"); +- libssh2_session_free(s->session); ++ ssh_disconnect(s->session); ++ ssh_free(s->session); + } + s->session = NULL; ++ s->sock = -1; ++ if (new_sock >= 0) { ++ close(new_sock); ++ } + + return ret; + } +@@ -756,9 +860,11 @@ static int ssh_file_open(BlockDriverState *bs, QDict *options, int bdrv_flags, + + ssh_state_init(s); + +- ssh_flags = LIBSSH2_FXF_READ; ++ ssh_flags = 0; + if (bdrv_flags & BDRV_O_RDWR) { +- ssh_flags |= LIBSSH2_FXF_WRITE; ++ ssh_flags |= O_RDWR; ++ } else { ++ ssh_flags |= O_RDONLY; + } + + opts = ssh_parse_options(options, errp); +@@ -773,18 +879,13 @@ static int ssh_file_open(BlockDriverState *bs, QDict *options, int bdrv_flags, + } + + /* Go non-blocking. */ +- libssh2_session_set_blocking(s->session, 0); ++ ssh_set_blocking(s->session, 0); + + qapi_free_BlockdevOptionsSsh(opts); + + return 0; + + err: +- if (s->sock >= 0) { +- close(s->sock); +- } +- s->sock = -1; +- + qapi_free_BlockdevOptionsSsh(opts); + + return ret; +@@ -795,25 +896,25 @@ static int ssh_grow_file(BDRVSSHState *s, int64_t offset, Error **errp) + { + ssize_t ret; + char c[1] = { '\0' }; +- int was_blocking = libssh2_session_get_blocking(s->session); ++ int was_blocking = ssh_is_blocking(s->session); + + /* offset must be strictly greater than the current size so we do + * not overwrite anything */ +- assert(offset > 0 && offset > s->attrs.filesize); ++ assert(offset > 0 && offset > s->attrs->size); + +- libssh2_session_set_blocking(s->session, 1); ++ ssh_set_blocking(s->session, 1); + +- libssh2_sftp_seek64(s->sftp_handle, offset - 1); +- ret = libssh2_sftp_write(s->sftp_handle, c, 1); ++ sftp_seek64(s->sftp_handle, offset - 1); ++ ret = sftp_write(s->sftp_handle, c, 1); + +- libssh2_session_set_blocking(s->session, was_blocking); ++ ssh_set_blocking(s->session, was_blocking); + + if (ret < 0) { + sftp_error_setg(errp, s, "Failed to grow file"); + return -EIO; + } + +- s->attrs.filesize = offset; ++ s->attrs->size = offset; + return 0; + } + +@@ -841,8 +942,7 @@ static int ssh_co_create(BlockdevCreateOptions *options, Error **errp) + ssh_state_init(&s); + + ret = connect_to_ssh(&s, opts->location, +- LIBSSH2_FXF_READ|LIBSSH2_FXF_WRITE| +- LIBSSH2_FXF_CREAT|LIBSSH2_FXF_TRUNC, ++ O_RDWR | O_CREAT | O_TRUNC, + 0644, errp); + if (ret < 0) { + goto fail; +@@ -911,10 +1011,8 @@ static int ssh_has_zero_init(BlockDriverState *bs) + /* Assume false, unless we can positively prove it's true. */ + int has_zero_init = 0; + +- if (s->attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) { +- if (s->attrs.permissions & LIBSSH2_SFTP_S_IFREG) { +- has_zero_init = 1; +- } ++ if (s->attrs->type == SSH_FILEXFER_TYPE_REGULAR) { ++ has_zero_init = 1; + } + + return has_zero_init; +@@ -951,12 +1049,12 @@ static coroutine_fn void co_yield(BDRVSSHState *s, BlockDriverState *bs) + .co = qemu_coroutine_self() + }; + +- r = libssh2_session_block_directions(s->session); ++ r = ssh_get_poll_flags(s->session); + +- if (r & LIBSSH2_SESSION_BLOCK_INBOUND) { ++ if (r & SSH_READ_PENDING) { + rd_handler = restart_coroutine; + } +- if (r & LIBSSH2_SESSION_BLOCK_OUTBOUND) { ++ if (r & SSH_WRITE_PENDING) { + wr_handler = restart_coroutine; + } + +@@ -968,33 +1066,6 @@ static coroutine_fn void co_yield(BDRVSSHState *s, BlockDriverState *bs) + trace_ssh_co_yield_back(s->sock); + } + +-/* SFTP has a function `libssh2_sftp_seek64' which seeks to a position +- * in the remote file. Notice that it just updates a field in the +- * sftp_handle structure, so there is no network traffic and it cannot +- * fail. +- * +- * However, `libssh2_sftp_seek64' does have a catastrophic effect on +- * performance since it causes the handle to throw away all in-flight +- * reads and buffered readahead data. Therefore this function tries +- * to be intelligent about when to call the underlying libssh2 function. +- */ +-#define SSH_SEEK_WRITE 0 +-#define SSH_SEEK_READ 1 +-#define SSH_SEEK_FORCE 2 +- +-static void ssh_seek(BDRVSSHState *s, int64_t offset, int flags) +-{ +- bool op_read = (flags & SSH_SEEK_READ) != 0; +- bool force = (flags & SSH_SEEK_FORCE) != 0; +- +- if (force || op_read != s->offset_op_read || offset != s->offset) { +- trace_ssh_seek(offset); +- libssh2_sftp_seek64(s->sftp_handle, offset); +- s->offset = offset; +- s->offset_op_read = op_read; +- } +-} +- + static coroutine_fn int ssh_read(BDRVSSHState *s, BlockDriverState *bs, + int64_t offset, size_t size, + QEMUIOVector *qiov) +@@ -1006,7 +1077,8 @@ static coroutine_fn int ssh_read(BDRVSSHState *s, BlockDriverState *bs, + + trace_ssh_read(offset, size); + +- ssh_seek(s, offset, SSH_SEEK_READ); ++ trace_ssh_seek(offset); ++ sftp_seek64(s->sftp_handle, offset); + + /* This keeps track of the current iovec element ('i'), where we + * will write to next ('buf'), and the end of the current iovec +@@ -1016,35 +1088,35 @@ static coroutine_fn int ssh_read(BDRVSSHState *s, BlockDriverState *bs, + buf = i->iov_base; + end_of_vec = i->iov_base + i->iov_len; + +- /* libssh2 has a hard-coded limit of 2000 bytes per request, +- * although it will also do readahead behind our backs. Therefore +- * we may have to do repeated reads here until we have read 'size' +- * bytes. +- */ + for (got = 0; got < size; ) { ++ size_t request_read_size; + again: +- trace_ssh_read_buf(buf, end_of_vec - buf); +- r = libssh2_sftp_read(s->sftp_handle, buf, end_of_vec - buf); +- trace_ssh_read_return(r); ++ /* ++ * The size of SFTP packets is limited to 32K bytes, so limit ++ * the amount of data requested to 16K, as libssh currently ++ * does not handle multiple requests on its own. ++ */ ++ request_read_size = MIN(end_of_vec - buf, 16384); ++ trace_ssh_read_buf(buf, end_of_vec - buf, request_read_size); ++ r = sftp_read(s->sftp_handle, buf, request_read_size); ++ trace_ssh_read_return(r, sftp_get_error(s->sftp)); + +- if (r == LIBSSH2_ERROR_EAGAIN || r == LIBSSH2_ERROR_TIMEOUT) { ++ if (r == SSH_AGAIN) { + co_yield(s, bs); + goto again; + } +- if (r < 0) { +- sftp_error_trace(s, "read"); +- s->offset = -1; +- return -EIO; +- } +- if (r == 0) { ++ if (r == SSH_EOF || (r == 0 && sftp_get_error(s->sftp) == SSH_FX_EOF)) { + /* EOF: Short read so pad the buffer with zeroes and return it. */ + qemu_iovec_memset(qiov, got, 0, size - got); + return 0; + } ++ if (r <= 0) { ++ sftp_error_trace(s, "read"); ++ return -EIO; ++ } + + got += r; + buf += r; +- s->offset += r; + if (buf >= end_of_vec && got < size) { + i++; + buf = i->iov_base; +@@ -1081,7 +1153,8 @@ static int ssh_write(BDRVSSHState *s, BlockDriverState *bs, + + trace_ssh_write(offset, size); + +- ssh_seek(s, offset, SSH_SEEK_WRITE); ++ trace_ssh_seek(offset); ++ sftp_seek64(s->sftp_handle, offset); + + /* This keeps track of the current iovec element ('i'), where we + * will read from next ('buf'), and the end of the current iovec +@@ -1092,46 +1165,37 @@ static int ssh_write(BDRVSSHState *s, BlockDriverState *bs, + end_of_vec = i->iov_base + i->iov_len; + + for (written = 0; written < size; ) { ++ size_t request_write_size; + again: +- trace_ssh_write_buf(buf, end_of_vec - buf); +- r = libssh2_sftp_write(s->sftp_handle, buf, end_of_vec - buf); +- trace_ssh_write_return(r); ++ /* ++ * Avoid too large data packets, as libssh currently does not ++ * handle multiple requests on its own. ++ */ ++ request_write_size = MIN(end_of_vec - buf, 131072); ++ trace_ssh_write_buf(buf, end_of_vec - buf, request_write_size); ++ r = sftp_write(s->sftp_handle, buf, request_write_size); ++ trace_ssh_write_return(r, sftp_get_error(s->sftp)); + +- if (r == LIBSSH2_ERROR_EAGAIN || r == LIBSSH2_ERROR_TIMEOUT) { ++ if (r == SSH_AGAIN) { + co_yield(s, bs); + goto again; + } + if (r < 0) { + sftp_error_trace(s, "write"); +- s->offset = -1; + return -EIO; + } +- /* The libssh2 API is very unclear about this. A comment in +- * the code says "nothing was acked, and no EAGAIN was +- * received!" which apparently means that no data got sent +- * out, and the underlying channel didn't return any EAGAIN +- * indication. I think this is a bug in either libssh2 or +- * OpenSSH (server-side). In any case, forcing a seek (to +- * discard libssh2 internal buffers), and then trying again +- * works for me. +- */ +- if (r == 0) { +- ssh_seek(s, offset + written, SSH_SEEK_WRITE|SSH_SEEK_FORCE); +- co_yield(s, bs); +- goto again; +- } + + written += r; + buf += r; +- s->offset += r; + if (buf >= end_of_vec && written < size) { + i++; + buf = i->iov_base; + end_of_vec = i->iov_base + i->iov_len; + } + +- if (offset + written > s->attrs.filesize) +- s->attrs.filesize = offset + written; ++ if (offset + written > s->attrs->size) { ++ s->attrs->size = offset + written; ++ } + } + + return 0; +@@ -1164,24 +1228,24 @@ static void unsafe_flush_warning(BDRVSSHState *s, const char *what) + } + } + +-#ifdef HAS_LIBSSH2_SFTP_FSYNC ++#ifdef HAVE_LIBSSH_0_8 + + static coroutine_fn int ssh_flush(BDRVSSHState *s, BlockDriverState *bs) + { + int r; + + trace_ssh_flush(); ++ ++ if (!sftp_extension_supported(s->sftp, "fsync@openssh.com", "1")) { ++ unsafe_flush_warning(s, "OpenSSH >= 6.3"); ++ return 0; ++ } + again: +- r = libssh2_sftp_fsync(s->sftp_handle); +- if (r == LIBSSH2_ERROR_EAGAIN || r == LIBSSH2_ERROR_TIMEOUT) { ++ r = sftp_fsync(s->sftp_handle); ++ if (r == SSH_AGAIN) { + co_yield(s, bs); + goto again; + } +- if (r == LIBSSH2_ERROR_SFTP_PROTOCOL && +- libssh2_sftp_last_error(s->sftp) == LIBSSH2_FX_OP_UNSUPPORTED) { +- unsafe_flush_warning(s, "OpenSSH >= 6.3"); +- return 0; +- } + if (r < 0) { + sftp_error_trace(s, "fsync"); + return -EIO; +@@ -1202,25 +1266,25 @@ static coroutine_fn int ssh_co_flush(BlockDriverState *bs) + return ret; + } + +-#else /* !HAS_LIBSSH2_SFTP_FSYNC */ ++#else /* !HAVE_LIBSSH_0_8 */ + + static coroutine_fn int ssh_co_flush(BlockDriverState *bs) + { + BDRVSSHState *s = bs->opaque; + +- unsafe_flush_warning(s, "libssh2 >= 1.4.4"); ++ unsafe_flush_warning(s, "libssh >= 0.8.0"); + return 0; + } + +-#endif /* !HAS_LIBSSH2_SFTP_FSYNC */ ++#endif /* !HAVE_LIBSSH_0_8 */ + + static int64_t ssh_getlength(BlockDriverState *bs) + { + BDRVSSHState *s = bs->opaque; + int64_t length; + +- /* Note we cannot make a libssh2 call here. */ +- length = (int64_t) s->attrs.filesize; ++ /* Note we cannot make a libssh call here. */ ++ length = (int64_t) s->attrs->size; + trace_ssh_getlength(length); + + return length; +@@ -1237,12 +1301,12 @@ static int coroutine_fn ssh_co_truncate(BlockDriverState *bs, int64_t offset, + return -ENOTSUP; + } + +- if (offset < s->attrs.filesize) { ++ if (offset < s->attrs->size) { + error_setg(errp, "ssh driver does not support shrinking files"); + return -ENOTSUP; + } + +- if (offset == s->attrs.filesize) { ++ if (offset == s->attrs->size) { + return 0; + } + +@@ -1307,12 +1371,16 @@ static void bdrv_ssh_init(void) + { + int r; + +- r = libssh2_init(0); ++ r = ssh_init(); + if (r != 0) { +- fprintf(stderr, "libssh2 initialization failed, %d\n", r); ++ fprintf(stderr, "libssh initialization failed, %d\n", r); + exit(EXIT_FAILURE); + } + ++#if TRACE_LIBSSH != 0 ++ ssh_set_log_level(TRACE_LIBSSH); ++#endif ++ + bdrv_register(&bdrv_ssh); + } + +diff --git a/block/trace-events b/block/trace-events +index 23c9963..0017e33 100644 +--- a/block/trace-events ++++ b/block/trace-events +@@ -154,19 +154,21 @@ nvme_cmd_map_qiov_iov(void *s, int i, void *page, int pages) "s %p iov[%d] %p pa + # block/ssh.c + ssh_restart_coroutine(void *co) "co=%p" + ssh_flush(void) "fsync" +-ssh_check_host_key_knownhosts(const char *key) "host key OK: %s" ++ssh_check_host_key_knownhosts(void) "host key OK" + ssh_connect_to_ssh(char *path, int flags, int mode) "opening file %s flags=0x%x creat_mode=0%o" + ssh_co_yield(int sock, void *rd_handler, void *wr_handler) "s->sock=%d rd_handler=%p wr_handler=%p" + ssh_co_yield_back(int sock) "s->sock=%d - back" + ssh_getlength(int64_t length) "length=%" PRIi64 + ssh_co_create_opts(uint64_t size) "total_size=%" PRIu64 + ssh_read(int64_t offset, size_t size) "offset=%" PRIi64 " size=%zu" +-ssh_read_buf(void *buf, size_t size) "sftp_read buf=%p size=%zu" +-ssh_read_return(ssize_t ret) "sftp_read returned %zd" ++ssh_read_buf(void *buf, size_t size, size_t actual_size) "sftp_read buf=%p size=%zu (actual size=%zu)" ++ssh_read_return(ssize_t ret, int sftp_err) "sftp_read returned %zd (sftp error=%d)" + ssh_write(int64_t offset, size_t size) "offset=%" PRIi64 " size=%zu" +-ssh_write_buf(void *buf, size_t size) "sftp_write buf=%p size=%zu" +-ssh_write_return(ssize_t ret) "sftp_write returned %zd" ++ssh_write_buf(void *buf, size_t size, size_t actual_size) "sftp_write buf=%p size=%zu (actual size=%zu)" ++ssh_write_return(ssize_t ret, int sftp_err) "sftp_write returned %zd (sftp error=%d)" + ssh_seek(int64_t offset) "seeking to offset=%" PRIi64 ++ssh_auth_methods(int methods) "auth methods=0x%x" ++ssh_server_status(int status) "server status=%d" + + # ssh.c +-sftp_error(const char *op, const char *ssh_err, int ssh_err_code, unsigned long sftp_err_code) "%s failed: %s (libssh2 error code: %d, sftp error code: %lu)" ++sftp_error(const char *op, const char *ssh_err, int ssh_err_code, int sftp_err_code) "%s failed: %s (libssh error code: %d, sftp error code: %d)" +diff --git a/configure b/configure +index c9a1034..eefec38 100755 +--- a/configure ++++ b/configure +@@ -445,7 +445,7 @@ gcrypt_kdf="no" + vte="" + virglrenderer="" + tpm="yes" +-libssh2="" ++libssh="" + live_block_migration="yes" + numa="" + tcmalloc="no" +@@ -1334,9 +1334,9 @@ for opt do + ;; + --enable-tpm) tpm="yes" + ;; +- --disable-libssh2) libssh2="no" ++ --disable-libssh) libssh="no" + ;; +- --enable-libssh2) libssh2="yes" ++ --enable-libssh) libssh="yes" + ;; + --disable-live-block-migration) live_block_migration="no" + ;; +@@ -1669,7 +1669,7 @@ disabled with --disable-FEATURE, default is enabled if available: + coroutine-pool coroutine freelist (better performance) + glusterfs GlusterFS backend + tpm TPM support +- libssh2 ssh block device support ++ libssh ssh block device support + numa libnuma support + libxml2 for Parallels image format + tcmalloc tcmalloc support +@@ -3656,43 +3656,34 @@ EOF + fi + + ########################################## +-# libssh2 probe +-min_libssh2_version=1.2.8 +-if test "$libssh2" != "no" ; then +- if $pkg_config --atleast-version=$min_libssh2_version libssh2; then +- libssh2_cflags=$($pkg_config libssh2 --cflags) +- libssh2_libs=$($pkg_config libssh2 --libs) +- libssh2=yes ++# libssh probe ++if test "$libssh" != "no" ; then ++ if $pkg_config --exists libssh; then ++ libssh_cflags=$($pkg_config libssh --cflags) ++ libssh_libs=$($pkg_config libssh --libs) ++ libssh=yes + else +- if test "$libssh2" = "yes" ; then +- error_exit "libssh2 >= $min_libssh2_version required for --enable-libssh2" ++ if test "$libssh" = "yes" ; then ++ error_exit "libssh required for --enable-libssh" + fi +- libssh2=no ++ libssh=no + fi + fi + + ########################################## +-# libssh2_sftp_fsync probe ++# Check for libssh 0.8 ++# This is done like this instead of using the LIBSSH_VERSION_* and ++# SSH_VERSION_* macros because some distributions in the past shipped ++# snapshots of the future 0.8 from Git, and those snapshots did not ++# have updated version numbers (still referring to 0.7.0). + +-if test "$libssh2" = "yes"; then ++if test "$libssh" = "yes"; then + cat > $TMPC < +-#include +-#include +-int main(void) { +- LIBSSH2_SESSION *session; +- LIBSSH2_SFTP *sftp; +- LIBSSH2_SFTP_HANDLE *sftp_handle; +- session = libssh2_session_init (); +- sftp = libssh2_sftp_init (session); +- sftp_handle = libssh2_sftp_open (sftp, "/", 0, 0); +- libssh2_sftp_fsync (sftp_handle); +- return 0; +-} ++#include ++int main(void) { return ssh_get_server_publickey(NULL, NULL); } + EOF +- # libssh2_cflags/libssh2_libs defined in previous test. +- if compile_prog "$libssh2_cflags" "$libssh2_libs" ; then +- QEMU_CFLAGS="-DHAS_LIBSSH2_SFTP_FSYNC $QEMU_CFLAGS" ++ if compile_prog "$libssh_cflags" "$libssh_libs"; then ++ libssh_cflags="-DHAVE_LIBSSH_0_8 $libssh_cflags" + fi + fi + +@@ -5998,7 +5989,7 @@ echo "GlusterFS support $glusterfs" + echo "gcov $gcov_tool" + echo "gcov enabled $gcov" + echo "TPM support $tpm" +-echo "libssh2 support $libssh2" ++echo "libssh support $libssh" + echo "TPM passthrough $tpm_passthrough" + echo "TPM emulator $tpm_emulator" + echo "QOM debugging $qom_cast_debug" +@@ -6664,10 +6655,10 @@ if test "$glusterfs_iocb_has_stat" = "yes" ; then + echo "CONFIG_GLUSTERFS_IOCB_HAS_STAT=y" >> $config_host_mak + fi + +-if test "$libssh2" = "yes" ; then +- echo "CONFIG_LIBSSH2=m" >> $config_host_mak +- echo "LIBSSH2_CFLAGS=$libssh2_cflags" >> $config_host_mak +- echo "LIBSSH2_LIBS=$libssh2_libs" >> $config_host_mak ++if test "$libssh" = "yes" ; then ++ echo "CONFIG_LIBSSH=m" >> $config_host_mak ++ echo "LIBSSH_CFLAGS=$libssh_cflags" >> $config_host_mak ++ echo "LIBSSH_LIBS=$libssh_libs" >> $config_host_mak + fi + + if test "$live_block_migration" = "yes" ; then +diff --git a/docs/qemu-block-drivers.texi b/docs/qemu-block-drivers.texi +index e0d752a..5004dec 100644 +--- a/docs/qemu-block-drivers.texi ++++ b/docs/qemu-block-drivers.texi +@@ -782,7 +782,7 @@ print a warning when @code{fsync} is not supported: + + warning: ssh server @code{ssh.example.com:22} does not support fsync + +-With sufficiently new versions of libssh2 and OpenSSH, @code{fsync} is ++With sufficiently new versions of libssh and OpenSSH, @code{fsync} is + supported. + + @node disk_images_nvme +diff --git a/tests/docker/dockerfiles/debian-win32-cross.docker b/tests/docker/dockerfiles/debian-win32-cross.docker +index dd021f2..0a4970c 100644 +--- a/tests/docker/dockerfiles/debian-win32-cross.docker ++++ b/tests/docker/dockerfiles/debian-win32-cross.docker +@@ -15,7 +15,6 @@ RUN DEBIAN_FRONTEND=noninteractive eatmydata \ + mxe-$TARGET-w64-mingw32.shared-curl \ + mxe-$TARGET-w64-mingw32.shared-glib \ + mxe-$TARGET-w64-mingw32.shared-libgcrypt \ +- mxe-$TARGET-w64-mingw32.shared-libssh2 \ + mxe-$TARGET-w64-mingw32.shared-libusb1 \ + mxe-$TARGET-w64-mingw32.shared-lzo \ + mxe-$TARGET-w64-mingw32.shared-nettle \ +diff --git a/tests/docker/dockerfiles/debian-win64-cross.docker b/tests/docker/dockerfiles/debian-win64-cross.docker +index 4542bcc..b27985b 100644 +--- a/tests/docker/dockerfiles/debian-win64-cross.docker ++++ b/tests/docker/dockerfiles/debian-win64-cross.docker +@@ -15,7 +15,6 @@ RUN DEBIAN_FRONTEND=noninteractive eatmydata \ + mxe-$TARGET-w64-mingw32.shared-curl \ + mxe-$TARGET-w64-mingw32.shared-glib \ + mxe-$TARGET-w64-mingw32.shared-libgcrypt \ +- mxe-$TARGET-w64-mingw32.shared-libssh2 \ + mxe-$TARGET-w64-mingw32.shared-libusb1 \ + mxe-$TARGET-w64-mingw32.shared-lzo \ + mxe-$TARGET-w64-mingw32.shared-nettle \ +diff --git a/tests/docker/dockerfiles/fedora.docker b/tests/docker/dockerfiles/fedora.docker +index b706f42..2dd598d 100644 +--- a/tests/docker/dockerfiles/fedora.docker ++++ b/tests/docker/dockerfiles/fedora.docker +@@ -6,18 +6,18 @@ ENV PACKAGES \ + bluez-libs-devel brlapi-devel bzip2-devel \ + device-mapper-multipath-devel glusterfs-api-devel gnutls-devel \ + gtk3-devel libattr-devel libcap-devel libcap-ng-devel libcurl-devel \ +- libjpeg-devel libpng-devel librbd-devel libssh2-devel libusbx-devel \ ++ libjpeg-devel libpng-devel librbd-devel libssh-devel libusbx-devel \ + libxml2-devel lzo-devel ncurses-devel nettle-devel nss-devel \ + numactl-devel SDL2-devel snappy-devel spice-server-devel \ + systemtap-sdt-devel usbredir-devel virglrenderer-devel vte3-devel \ + xen-devel \ + mingw32-pixman mingw32-glib2 mingw32-gmp mingw32-SDL mingw32-pkg-config \ + mingw32-gtk2 mingw32-gtk3 mingw32-gnutls mingw32-nettle mingw32-libtasn1 \ +- mingw32-libjpeg-turbo mingw32-libpng mingw32-curl mingw32-libssh2 \ ++ mingw32-libjpeg-turbo mingw32-libpng mingw32-curl \ + mingw32-bzip2 \ + mingw64-pixman mingw64-glib2 mingw64-gmp mingw64-SDL mingw64-pkg-config \ + mingw64-gtk2 mingw64-gtk3 mingw64-gnutls mingw64-nettle mingw64-libtasn1 \ +- mingw64-libjpeg-turbo mingw64-libpng mingw64-curl mingw64-libssh2 \ ++ mingw64-libjpeg-turbo mingw64-libpng mingw64-curl \ + mingw64-bzip2 + ENV QEMU_CONFIGURE_OPTS --python=/usr/bin/python3 + +diff --git a/tests/docker/dockerfiles/ubuntu.docker b/tests/docker/dockerfiles/ubuntu.docker +index dabbf2a..be37ff1 100644 +--- a/tests/docker/dockerfiles/ubuntu.docker ++++ b/tests/docker/dockerfiles/ubuntu.docker +@@ -4,7 +4,7 @@ RUN echo "deb http://archive.ubuntu.com/ubuntu/ trusty universe multiverse" >> \ + RUN apt-get update + ENV PACKAGES flex bison \ + libusb-1.0-0-dev libiscsi-dev librados-dev libncurses5-dev libncursesw5-dev \ +- libseccomp-dev libgnutls-dev libssh2-1-dev libspice-server-dev \ ++ libseccomp-dev libgnutls-dev libssh-dev libspice-server-dev \ + libspice-protocol-dev libnss3-dev libfdt-dev \ + libgtk-3-dev libvte-2.91-dev libsdl1.2-dev libpng12-dev libpixman-1-dev \ + libvdeplug-dev liblzo2-dev libsnappy-dev libbz2-dev libxen-dev librdmacm-dev libibverbs-dev \ +diff --git a/tests/qemu-iotests/207 b/tests/qemu-iotests/207 +index aaad656..219f1a6 100755 +--- a/tests/qemu-iotests/207 ++++ b/tests/qemu-iotests/207 +@@ -106,12 +106,49 @@ with iotests.FilePath('t.img') as disk_path, \ + + iotests.img_info_log(remote_path) + +- md5_key = subprocess.check_output( +- 'ssh-keyscan -t rsa 127.0.0.1 2>/dev/null | grep -v "\\^#" | ' + +- 'cut -d" " -f3 | base64 -d | md5sum -b | cut -d" " -f1', +- shell=True).rstrip().decode('ascii') ++ keys = subprocess.check_output( ++ 'ssh-keyscan 127.0.0.1 2>/dev/null | grep -v "\\^#" | ' + ++ 'cut -d" " -f3', ++ shell=True).rstrip().decode('ascii').split('\n') ++ ++ # Mappings of base64 representations to digests ++ md5_keys = {} ++ sha1_keys = {} ++ ++ for key in keys: ++ md5_keys[key] = subprocess.check_output( ++ 'echo %s | base64 -d | md5sum -b | cut -d" " -f1' % key, ++ shell=True).rstrip().decode('ascii') ++ ++ sha1_keys[key] = subprocess.check_output( ++ 'echo %s | base64 -d | sha1sum -b | cut -d" " -f1' % key, ++ shell=True).rstrip().decode('ascii') + + vm.launch() ++ ++ # Find correct key first ++ matching_key = None ++ for key in keys: ++ result = vm.qmp('blockdev-add', ++ driver='ssh', node_name='node0', path=disk_path, ++ server={ ++ 'host': '127.0.0.1', ++ 'port': '22', ++ }, host_key_check={ ++ 'mode': 'hash', ++ 'type': 'md5', ++ 'hash': md5_keys[key], ++ }) ++ ++ if 'error' not in result: ++ vm.qmp('blockdev-del', node_name='node0') ++ matching_key = key ++ break ++ ++ if matching_key is None: ++ vm.shutdown() ++ iotests.notrun('Did not find a key that fits 127.0.0.1') ++ + blockdev_create(vm, { 'driver': 'ssh', + 'location': { + 'path': disk_path, +@@ -136,7 +173,7 @@ with iotests.FilePath('t.img') as disk_path, \ + 'host-key-check': { + 'mode': 'hash', + 'type': 'md5', +- 'hash': md5_key, ++ 'hash': md5_keys[matching_key], + } + }, + 'size': 8388608 }) +@@ -144,11 +181,6 @@ with iotests.FilePath('t.img') as disk_path, \ + + iotests.img_info_log(remote_path) + +- sha1_key = subprocess.check_output( +- 'ssh-keyscan -t rsa 127.0.0.1 2>/dev/null | grep -v "\\^#" | ' + +- 'cut -d" " -f3 | base64 -d | sha1sum -b | cut -d" " -f1', +- shell=True).rstrip().decode('ascii') +- + vm.launch() + blockdev_create(vm, { 'driver': 'ssh', + 'location': { +@@ -174,7 +206,7 @@ with iotests.FilePath('t.img') as disk_path, \ + 'host-key-check': { + 'mode': 'hash', + 'type': 'sha1', +- 'hash': sha1_key, ++ 'hash': sha1_keys[matching_key], + } + }, + 'size': 4194304 }) +diff --git a/tests/qemu-iotests/207.out b/tests/qemu-iotests/207.out +index 789b465..48318ce 100644 +--- a/tests/qemu-iotests/207.out ++++ b/tests/qemu-iotests/207.out +@@ -68,7 +68,7 @@ virtual size: 4.0M (4194304 bytes) + + {"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"mode": "none"}, "path": "/this/is/not/an/existing/path", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 4194304}}} + {"return": {}} +-Job failed: failed to open remote file '/this/is/not/an/existing/path': Failed opening remote file (libssh2 error code: -31) ++Job failed: failed to open remote file '/this/is/not/an/existing/path': SFTP server: No such file (libssh error code: 1, sftp error code: 2) + {"execute": "job-dismiss", "arguments": {"id": "job0"}} + {"return": {}} + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-support-overcommit-cpu-pm-on-off.patch b/SOURCES/kvm-support-overcommit-cpu-pm-on-off.patch new file mode 100644 index 0000000..3da6e68 --- /dev/null +++ b/SOURCES/kvm-support-overcommit-cpu-pm-on-off.patch @@ -0,0 +1,181 @@ +From 1cfbcbeebc6d9ca1f1f7656fff572bf6ac50de76 Mon Sep 17 00:00:00 2001 +From: "plai@redhat.com" +Date: Tue, 26 Nov 2019 19:36:52 +0000 +Subject: [PATCH 08/11] kvm: support -overcommit cpu-pm=on|off + +RH-Author: plai@redhat.com +Message-id: <1574797015-32564-5-git-send-email-plai@redhat.com> +Patchwork-id: 92697 +O-Subject: [RHEL8.2 qemu-kvm PATCH 4/7] kvm: support -overcommit cpu-pm=on|off +Bugzilla: 1634827 +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Michael S. Tsirkin +RH-Acked-by: Igor Mammedov + +From: "Michael S. Tsirkin" + +With this flag, kvm allows guest to control host CPU power state. This +increases latency for other processes using same host CPU in an +unpredictable way, but if decreases idle entry/exit times for the +running VCPU, so to use it QEMU needs a hint about whether host CPU is +overcommitted, hence the flag name. + +Follow-up patches will expose this capability to guest +(using mwait leaf). + +Based on a patch by Wanpeng Li . + +Signed-off-by: Michael S. Tsirkin +Message-Id: <20180622192148.178309-2-mst@redhat.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit 6f131f13e68d648a8e4f083c667ab1acd88ce4cd) +Signed-off-by: Paul Lai +Signed-off-by: Danilo C. L. de Paula +--- + include/sysemu/sysemu.h | 1 + + qemu-options.hx | 24 ++++++++++++++++++++++++ + target/i386/kvm.c | 23 +++++++++++++++++++++++ + vl.c | 32 +++++++++++++++++++++++++++++++- + 4 files changed, 79 insertions(+), 1 deletion(-) + +diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h +index f20e4f5..f38fad0 100644 +--- a/include/sysemu/sysemu.h ++++ b/include/sysemu/sysemu.h +@@ -131,6 +131,7 @@ extern bool boot_strict; + extern uint8_t *boot_splash_filedata; + extern size_t boot_splash_filedata_size; + extern bool enable_mlock; ++extern bool enable_cpu_pm; + extern uint8_t qemu_extra_params_fw[2]; + extern QEMUClockType rtc_clock; + extern const char *mem_path; +diff --git a/qemu-options.hx b/qemu-options.hx +index 1243057..99933a0 100644 +--- a/qemu-options.hx ++++ b/qemu-options.hx +@@ -3331,6 +3331,30 @@ mlocking qemu-kvm and guest memory can be enabled via @option{mlock=on} + (enabled by default). + ETEXI + ++DEF("overcommit", HAS_ARG, QEMU_OPTION_overcommit, ++ "--overcommit [mem-lock=on|off][cpu-pm=on|off]\n" ++ " run qemu with overcommit hints\n" ++ " mem-lock=on|off controls memory lock support (default: off)\n" ++ " cpu-pm=on|off controls cpu power management (default: off)\n", ++ QEMU_ARCH_ALL) ++STEXI ++@item -overcommit mem-lock=on|off ++@item -overcommit cpu-pm=on|off ++@findex -overcommit ++Run qemu with hints about host resource overcommit. The default is ++to assume that host overcommits all resources. ++ ++Locking qemu and guest memory can be enabled via @option{mem-lock=on} (disabled ++by default). This works when host memory is not overcommitted and reduces the ++worst-case latency for guest. This is equivalent to @option{realtime}. ++ ++Guest ability to manage power state of host cpus (increasing latency for other ++processes on the same host cpu, but decreasing latency for guest) can be ++enabled via @option{cpu-pm=on} (disabled by default). This works best when ++host CPU is not overcommitted. When used, host estimates of CPU cycle and power ++utilization will be incorrect, not taking into account guest idle time. ++ETEXI ++ + DEF("gdb", HAS_ARG, QEMU_OPTION_gdb, \ + "-gdb dev wait for gdb connection on 'dev'\n", QEMU_ARCH_ALL) + STEXI +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index 107c53b..879c3e0 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -1606,6 +1606,29 @@ int kvm_arch_init(MachineState *ms, KVMState *s) + smram_machine_done.notify = register_smram_listener; + qemu_add_machine_init_done_notifier(&smram_machine_done); + } ++ ++ if (enable_cpu_pm) { ++ int disable_exits = kvm_check_extension(s, KVM_CAP_X86_DISABLE_EXITS); ++ int ret; ++ ++/* Work around for kernel header with a typo. TODO: fix header and drop. */ ++#if defined(KVM_X86_DISABLE_EXITS_HTL) && !defined(KVM_X86_DISABLE_EXITS_HLT) ++#define KVM_X86_DISABLE_EXITS_HLT KVM_X86_DISABLE_EXITS_HTL ++#endif ++ if (disable_exits) { ++ disable_exits &= (KVM_X86_DISABLE_EXITS_MWAIT | ++ KVM_X86_DISABLE_EXITS_HLT | ++ KVM_X86_DISABLE_EXITS_PAUSE); ++ } ++ ++ ret = kvm_vm_enable_cap(s, KVM_CAP_X86_DISABLE_EXITS, 0, ++ disable_exits); ++ if (ret < 0) { ++ error_report("kvm: guest stopping CPU not supported: %s", ++ strerror(-ret)); ++ } ++ } ++ + return 0; + } + +diff --git a/vl.c b/vl.c +index 932c1cf..aa08ab5 100644 +--- a/vl.c ++++ b/vl.c +@@ -150,6 +150,7 @@ ram_addr_t ram_size; + const char *mem_path = NULL; + int mem_prealloc = 0; /* force preallocation of physical target memory */ + bool enable_mlock = false; ++bool enable_cpu_pm = false; + int nb_nics; + NICInfo nd_table[MAX_NICS]; + int autostart; +@@ -428,6 +429,22 @@ static QemuOptsList qemu_realtime_opts = { + }, + }; + ++static QemuOptsList qemu_overcommit_opts = { ++ .name = "overcommit", ++ .head = QTAILQ_HEAD_INITIALIZER(qemu_overcommit_opts.head), ++ .desc = { ++ { ++ .name = "mem-lock", ++ .type = QEMU_OPT_BOOL, ++ }, ++ { ++ .name = "cpu-pm", ++ .type = QEMU_OPT_BOOL, ++ }, ++ { /* end of list */ } ++ }, ++}; ++ + static QemuOptsList qemu_msg_opts = { + .name = "msg", + .head = QTAILQ_HEAD_INITIALIZER(qemu_msg_opts.head), +@@ -4089,7 +4106,20 @@ int main(int argc, char **argv, char **envp) + if (!opts) { + exit(1); + } +- enable_mlock = qemu_opt_get_bool(opts, "mlock", true); ++ /* Don't override the -overcommit option if set */ ++ enable_mlock = enable_mlock || ++ qemu_opt_get_bool(opts, "mlock", true); ++ break; ++ case QEMU_OPTION_overcommit: ++ opts = qemu_opts_parse_noisily(qemu_find_opts("overcommit"), ++ optarg, false); ++ if (!opts) { ++ exit(1); ++ } ++ /* Don't override the -realtime option if set */ ++ enable_mlock = enable_mlock || ++ qemu_opt_get_bool(opts, "mem-lock", false); ++ enable_cpu_pm = qemu_opt_get_bool(opts, "cpu-pm", false); + break; + case QEMU_OPTION_msg: + opts = qemu_opts_parse_noisily(qemu_find_opts("msg"), optarg, +-- +1.8.3.1 + diff --git a/SOURCES/kvm-tap-set-vhostfd-passed-from-qemu-cli-to-non-blocking.patch b/SOURCES/kvm-tap-set-vhostfd-passed-from-qemu-cli-to-non-blocking.patch new file mode 100644 index 0000000..1bf8142 --- /dev/null +++ b/SOURCES/kvm-tap-set-vhostfd-passed-from-qemu-cli-to-non-blocking.patch @@ -0,0 +1,66 @@ +From 689a30f211939282ce6de9d3597c0fc6ad674a6e Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Fri, 26 Jul 2019 11:29:51 +0100 +Subject: [PATCH 13/14] tap: set vhostfd passed from qemu cli to non-blocking + +RH-Author: Laszlo Ersek +Message-id: <20190726112951.11834-2-lersek@redhat.com> +Patchwork-id: 89734 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 1/1] tap: set vhostfd passed from qemu cli to non-blocking +Bugzilla: 1732642 +RH-Acked-by: Xiao Wang +RH-Acked-by: Stefano Garzarella +RH-Acked-by: John Snow + +From: Brijesh Singh + +A guest boot hangs while probing the network interface when +iommu_platform=on is used. + +The following qemu cli hangs without this patch: + +# $QEMU \ + -netdev tap,fd=3,id=hostnet0,vhost=on,vhostfd=4 3<>/dev/tap67 4<>/dev/host-net \ + -device virtio-net-pci,netdev=hostnet0,id=net0,iommu_platform=on,disable-legacy=on \ + ... + +Commit: c471ad0e9bd46 (vhost_net: device IOTLB support) took care of +setting vhostfd to non-blocking when QEMU opens /dev/host-net but if +the fd is passed from qemu cli then we need to ensure that fd is set +to non-blocking. + +Fixes: c471ad0e9bd46 ("vhost_net: device IOTLB support") +Cc: qemu-stable@nongnu.org +Cc: Michael S. Tsirkin +Cc: Jason Wang +Signed-off-by: Brijesh Singh +Signed-off-by: Jason Wang +(cherry picked from commit d542800d1edc62f63f8a29cfa6bdd1a9536ae11c) +Signed-off-by: Danilo C. L. de Paula +--- + net/tap.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/tap.c b/net/tap.c +index 2b3a36f..89c4e19 100644 +--- a/net/tap.c ++++ b/net/tap.c +@@ -40,6 +40,7 @@ + #include "qemu-common.h" + #include "qemu/cutils.h" + #include "qemu/error-report.h" ++#include "qemu/sockets.h" + + #include "net/tap.h" + +@@ -693,6 +694,7 @@ static void net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer, + } + return; + } ++ qemu_set_nonblock(vhostfd); + } else { + vhostfd = open("/dev/vhost-net", O_RDWR); + if (vhostfd < 0) { +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-Add-support-for-save-load-IA32_UMWAIT_CO.patch b/SOURCES/kvm-target-i386-Add-support-for-save-load-IA32_UMWAIT_CO.patch new file mode 100644 index 0000000..da6cbe9 --- /dev/null +++ b/SOURCES/kvm-target-i386-Add-support-for-save-load-IA32_UMWAIT_CO.patch @@ -0,0 +1,147 @@ +From 9c3757a2d7302918456da459a8d188bb41299891 Mon Sep 17 00:00:00 2001 +From: Tao Xu +Date: Fri, 11 Oct 2019 15:41:03 +0800 +Subject: [PATCH 11/11] target/i386: Add support for save/load + IA32_UMWAIT_CONTROL MSR + +RH-Author: plai@redhat.com +Message-id: <1574797015-32564-8-git-send-email-plai@redhat.com> +Patchwork-id: 92693 +O-Subject: [RHEL8.2 qemu-kvm PATCH 7/7] target/i386: Add support for save/load IA32_UMWAIT_CONTROL MSR +Bugzilla: 1634827 +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Michael S. Tsirkin +RH-Acked-by: Igor Mammedov + +UMWAIT and TPAUSE instructions use 32bits IA32_UMWAIT_CONTROL at MSR +index E1H to determines the maximum time in TSC-quanta that the processor +can reside in either C0.1 or C0.2. + +This patch is to Add support for save/load IA32_UMWAIT_CONTROL MSR in +guest. + +Co-developed-by: Jingqi Liu +Signed-off-by: Jingqi Liu +Signed-off-by: Tao Xu +Message-Id: <20191011074103.30393-3-tao3.xu@intel.com> +Signed-off-by: Paolo Bonzini +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.h | 2 ++ + target/i386/kvm.c | 13 +++++++++++++ + target/i386/machine.c | 20 ++++++++++++++++++++ + 3 files changed, 35 insertions(+) + +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index fac98aa..ecbe4f0 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -461,6 +461,7 @@ typedef enum X86Seg { + + #define MSR_IA32_BNDCFGS 0x00000d90 + #define MSR_IA32_XSS 0x00000da0 ++#define MSR_IA32_UMWAIT_CONTROL 0xe1 + + #define MSR_IA32_VMX_BASIC 0x00000480 + #define MSR_IA32_VMX_PINBASED_CTLS 0x00000481 +@@ -1510,6 +1511,7 @@ typedef struct CPUX86State { + uint16_t fpregs_format_vmstate; + + uint64_t xss; ++ uint32_t umwait; + + TPRAccess tpr_access_type; + } CPUX86State; +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index 0fd5650..ad58bfb 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -91,6 +91,7 @@ static bool has_msr_hv_synic; + static bool has_msr_hv_stimer; + static bool has_msr_hv_frequencies; + static bool has_msr_xss; ++static bool has_msr_umwait; + static bool has_msr_spec_ctrl; + static bool has_msr_tsx_ctrl; + static bool has_msr_virt_ssbd; +@@ -1450,6 +1451,9 @@ static int kvm_get_supported_msrs(KVMState *s) + case MSR_IA32_XSS: + has_msr_xss = true; + break; ++ case MSR_IA32_UMWAIT_CONTROL: ++ has_msr_umwait = true; ++ break; + case HV_X64_MSR_CRASH_CTL: + has_msr_hv_crash = true; + break; +@@ -2134,6 +2138,9 @@ static int kvm_put_msrs(X86CPU *cpu, int level) + if (has_msr_xss) { + kvm_msr_entry_add(cpu, MSR_IA32_XSS, env->xss); + } ++ if (has_msr_umwait) { ++ kvm_msr_entry_add(cpu, MSR_IA32_UMWAIT_CONTROL, env->umwait); ++ } + if (has_msr_spec_ctrl) { + kvm_msr_entry_add(cpu, MSR_IA32_SPEC_CTRL, env->spec_ctrl); + } +@@ -2533,6 +2540,9 @@ static int kvm_get_msrs(X86CPU *cpu) + if (has_msr_xss) { + kvm_msr_entry_add(cpu, MSR_IA32_XSS, 0); + } ++ if (has_msr_umwait) { ++ kvm_msr_entry_add(cpu, MSR_IA32_UMWAIT_CONTROL, 0); ++ } + if (has_msr_spec_ctrl) { + kvm_msr_entry_add(cpu, MSR_IA32_SPEC_CTRL, 0); + } +@@ -2780,6 +2790,9 @@ static int kvm_get_msrs(X86CPU *cpu) + case MSR_IA32_XSS: + env->xss = msrs[i].data; + break; ++ case MSR_IA32_UMWAIT_CONTROL: ++ env->umwait = msrs[i].data; ++ break; + default: + if (msrs[i].index >= MSR_MC0_CTL && + msrs[i].index < MSR_MC0_CTL + (env->mcg_cap & 0xff) * 4) { +diff --git a/target/i386/machine.c b/target/i386/machine.c +index 76b173c..960cb51 100644 +--- a/target/i386/machine.c ++++ b/target/i386/machine.c +@@ -894,6 +894,25 @@ static const VMStateDescription vmstate_xss = { + } + }; + ++static bool umwait_needed(void *opaque) ++{ ++ X86CPU *cpu = opaque; ++ CPUX86State *env = &cpu->env; ++ ++ return env->umwait != 0; ++} ++ ++static const VMStateDescription vmstate_umwait = { ++ .name = "cpu/umwait", ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .needed = umwait_needed, ++ .fields = (VMStateField[]) { ++ VMSTATE_UINT32(env.umwait, X86CPU), ++ VMSTATE_END_OF_LIST() ++ } ++}; ++ + #ifdef TARGET_X86_64 + static bool pkru_needed(void *opaque) + { +@@ -1360,6 +1379,7 @@ VMStateDescription vmstate_x86_cpu = { + &vmstate_msr_hyperv_stimer, + &vmstate_avx512, + &vmstate_xss, ++ &vmstate_umwait, + &vmstate_tsc_khz, + &vmstate_msr_smi_count, + #ifdef TARGET_X86_64 +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-Disable-MPX-support-on-named-CPU-models.patch b/SOURCES/kvm-target-i386-Disable-MPX-support-on-named-CPU-models.patch new file mode 100644 index 0000000..a8dfc93 --- /dev/null +++ b/SOURCES/kvm-target-i386-Disable-MPX-support-on-named-CPU-models.patch @@ -0,0 +1,59 @@ +From defbb3b33db7fcbc9da20c1350ce90a6b5e279bb Mon Sep 17 00:00:00 2001 +From: "plai@redhat.com" +Date: Mon, 1 Jul 2019 16:17:32 +0100 +Subject: [PATCH 03/39] target/i386: Disable MPX support on named CPU models +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: plai@redhat.com +Message-id: <1561997854-9646-4-git-send-email-plai@redhat.com> +Patchwork-id: 89333 +O-Subject: [RHEL8.1 qemu-kvm PATCH v6 3/5] target/i386: Disable MPX support on named CPU models +Bugzilla: 1629906 +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Bandan Das + +From: Paolo Bonzini + +MPX support is being phased out by Intel; GCC has dropped it, Linux +is also going to do that. Even though KVM will have special code +to support MPX after the kernel proper stops enabling it in XCR0, +we probably also want to deprecate that in a few years. As a start, +do not enable it by default for any named CPU model starting with +the 4.0 machine types; this include Skylake, Icelake and Cascadelake. + +Signed-off-by: Paolo Bonzini +Message-Id: <20181220121100.21554-1-pbonzini@redhat.com> +Reviewed-by:   Wainer dos Santos Moschetta +Signed-off-by: Eduardo Habkost +(cherry picked from commit ecb85fe48cacb2f8740186e81f2f38a2e02bd963) +Signed-off-by: Paul Lai +Signed-off-by: Danilo C. L. de Paula + +Conflicts: + hw/i386/pc.c changes to include/hw/i386/pc.h + target/i386/cpu.c + +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index c4b31eb..094f8a1 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -2512,7 +2512,7 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_7_0_EBX_HLE | CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP | + CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_INVPCID | + CPUID_7_0_EBX_RTM | CPUID_7_0_EBX_RDSEED | CPUID_7_0_EBX_ADX | +- CPUID_7_0_EBX_SMAP | CPUID_7_0_EBX_MPX | CPUID_7_0_EBX_CLWB | ++ CPUID_7_0_EBX_SMAP | CPUID_7_0_EBX_CLWB | + CPUID_7_0_EBX_AVX512F | CPUID_7_0_EBX_AVX512DQ | + CPUID_7_0_EBX_AVX512BW | CPUID_7_0_EBX_AVX512CD | + CPUID_7_0_EBX_AVX512VL | CPUID_7_0_EBX_CLFLUSHOPT | +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-Export-TAA_NO-bit-to-guests.patch b/SOURCES/kvm-target-i386-Export-TAA_NO-bit-to-guests.patch new file mode 100644 index 0000000..e3eaa99 --- /dev/null +++ b/SOURCES/kvm-target-i386-Export-TAA_NO-bit-to-guests.patch @@ -0,0 +1,48 @@ +From 3048f38859988e7b6d63099350769ecb9ac0e76f Mon Sep 17 00:00:00 2001 +From: Eduardo Habkost +Date: Tue, 3 Dec 2019 23:53:07 +0000 +Subject: [PATCH 1/2] target/i386: Export TAA_NO bit to guests + +RH-Author: Eduardo Habkost +Message-id: <20191203235308.590845-2-ehabkost@redhat.com> +Patchwork-id: 92851 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH 1/2] target/i386: Export TAA_NO bit to guests +Bugzilla: 1771971 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Igor Mammedov + +From: Pawan Gupta + +TSX Async Abort (TAA) is a side channel attack on internal buffers in +some Intel processors similar to Microachitectural Data Sampling (MDS). + +Some future Intel processors will use the ARCH_CAP_TAA_NO bit in the +IA32_ARCH_CAPABILITIES MSR to report that they are not vulnerable to +TAA. Make this bit available to guests. + +Signed-off-by: Pawan Gupta +Signed-off-by: Paolo Bonzini +(cherry picked from commit 7fac38635e1cc5ebae34eb6530da1009bd5808e4) +Signed-off-by: Eduardo Habkost +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 3effcf3..68fe865 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -1144,7 +1144,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + .feat_names = { + "rdctl-no", "ibrs-all", "rsba", "skip-l1dfl-vmentry", + "ssb-no", "mds-no", NULL, NULL, +- NULL, NULL, NULL, NULL, ++ "taa-no", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-add-MDS-NO-feature.patch b/SOURCES/kvm-target-i386-add-MDS-NO-feature.patch new file mode 100644 index 0000000..e465737 --- /dev/null +++ b/SOURCES/kvm-target-i386-add-MDS-NO-feature.patch @@ -0,0 +1,51 @@ +From 354818b02978df635ea030462223283529711970 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Sun, 23 Jun 2019 15:19:12 +0200 +Subject: [PATCH 1/4] target/i386: add MDS-NO feature + +RH-Author: Paolo Bonzini +Message-id: <20190623151912.7829-1-pbonzini@redhat.com> +Patchwork-id: 88872 +O-Subject: [RHEL-8.1.0 PATCH qemu-kvm] target/i386: add MDS-NO feature +Bugzilla: 1714792 +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Stefano Garzarella +RH-Acked-by: Miroslav Rezanina + +Bugzilla: 1714792 + +Brew build: 22307357 + +Microarchitectural Data Sampling is a hardware vulnerability which allows +unprivileged speculative access to data which is available in various CPU +internal buffers. + +Some Intel processors use the ARCH_CAP_MDS_NO bit in the +IA32_ARCH_CAPABILITIES +MSR to report that they are not vulnerable, make it available to guests. + +Signed-off-by: Paolo Bonzini +Message-Id: <20190516185320.28340-1-pbonzini@redhat.com> +Signed-off-by: Eduardo Habkost +(cherry picked from commit 20140a82c67467f53814ca197403d5e1b561a5e5) +Signed-off-by: Miroslav Rezanina +--- + target/i386/cpu.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 4411012..5c10093 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -1147,7 +1147,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + .type = MSR_FEATURE_WORD, + .feat_names = { + "rdctl-no", "ibrs-all", "rsba", "skip-l1dfl-vmentry", +- "ssb-no", NULL, NULL, NULL, ++ "ssb-no", "mds-no", NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-add-VMX-definitions.patch b/SOURCES/kvm-target-i386-add-VMX-definitions.patch new file mode 100644 index 0000000..3d70b4d --- /dev/null +++ b/SOURCES/kvm-target-i386-add-VMX-definitions.patch @@ -0,0 +1,177 @@ +From 968d0586936c356ca19f6f3b659ab094a2825374 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Fri, 22 Nov 2019 11:53:42 +0000 +Subject: [PATCH 09/16] target/i386: add VMX definitions + +RH-Author: Paolo Bonzini +Message-id: <20191122115348.25000-10-pbonzini@redhat.com> +Patchwork-id: 92604 +O-Subject: [RHEL8.2/rhel qemu-kvm PATCH 09/15] target/i386: add VMX definitions +Bugzilla: 1689270 +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Maxim Levitsky + +These will be used to compile the list of VMX features for named +CPU models, and/or by the code that sets up the VMX MSRs. + +Signed-off-by: Paolo Bonzini +(cherry picked from commit 704798add83be4ac868ffcb495480065fb665794) + +RHEL: context +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.h | 130 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 130 insertions(+) + +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index edba84e..2d1f247 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -459,6 +459,25 @@ typedef enum X86Seg { + #define MSR_IA32_BNDCFGS 0x00000d90 + #define MSR_IA32_XSS 0x00000da0 + ++#define MSR_IA32_VMX_BASIC 0x00000480 ++#define MSR_IA32_VMX_PINBASED_CTLS 0x00000481 ++#define MSR_IA32_VMX_PROCBASED_CTLS 0x00000482 ++#define MSR_IA32_VMX_EXIT_CTLS 0x00000483 ++#define MSR_IA32_VMX_ENTRY_CTLS 0x00000484 ++#define MSR_IA32_VMX_MISC 0x00000485 ++#define MSR_IA32_VMX_CR0_FIXED0 0x00000486 ++#define MSR_IA32_VMX_CR0_FIXED1 0x00000487 ++#define MSR_IA32_VMX_CR4_FIXED0 0x00000488 ++#define MSR_IA32_VMX_CR4_FIXED1 0x00000489 ++#define MSR_IA32_VMX_VMCS_ENUM 0x0000048a ++#define MSR_IA32_VMX_PROCBASED_CTLS2 0x0000048b ++#define MSR_IA32_VMX_EPT_VPID_CAP 0x0000048c ++#define MSR_IA32_VMX_TRUE_PINBASED_CTLS 0x0000048d ++#define MSR_IA32_VMX_TRUE_PROCBASED_CTLS 0x0000048e ++#define MSR_IA32_VMX_TRUE_EXIT_CTLS 0x0000048f ++#define MSR_IA32_VMX_TRUE_ENTRY_CTLS 0x00000490 ++#define MSR_IA32_VMX_VMFUNC 0x00000491 ++ + #define XSTATE_FP_BIT 0 + #define XSTATE_SSE_BIT 1 + #define XSTATE_YMM_BIT 2 +@@ -749,6 +768,117 @@ typedef uint64_t FeatureWordArray[FEATURE_WORDS]; + + #define MSR_CORE_CAP_SPLIT_LOCK_DETECT (1U << 5) + ++/* VMX MSR features */ ++#define MSR_VMX_BASIC_VMCS_REVISION_MASK 0x7FFFFFFFull ++#define MSR_VMX_BASIC_VMXON_REGION_SIZE_MASK (0x00001FFFull << 32) ++#define MSR_VMX_BASIC_VMCS_MEM_TYPE_MASK (0x003C0000ull << 32) ++#define MSR_VMX_BASIC_DUAL_MONITOR (1ULL << 49) ++#define MSR_VMX_BASIC_INS_OUTS (1ULL << 54) ++#define MSR_VMX_BASIC_TRUE_CTLS (1ULL << 55) ++ ++#define MSR_VMX_MISC_PREEMPTION_TIMER_SHIFT_MASK 0x1Full ++#define MSR_VMX_MISC_STORE_LMA (1ULL << 5) ++#define MSR_VMX_MISC_ACTIVITY_HLT (1ULL << 6) ++#define MSR_VMX_MISC_ACTIVITY_SHUTDOWN (1ULL << 7) ++#define MSR_VMX_MISC_ACTIVITY_WAIT_SIPI (1ULL << 8) ++#define MSR_VMX_MISC_MAX_MSR_LIST_SIZE_MASK 0x0E000000ull ++#define MSR_VMX_MISC_VMWRITE_VMEXIT (1ULL << 29) ++#define MSR_VMX_MISC_ZERO_LEN_INJECT (1ULL << 30) ++ ++#define MSR_VMX_EPT_EXECONLY (1ULL << 0) ++#define MSR_VMX_EPT_PAGE_WALK_LENGTH_4 (1ULL << 6) ++#define MSR_VMX_EPT_PAGE_WALK_LENGTH_5 (1ULL << 7) ++#define MSR_VMX_EPT_UC (1ULL << 8) ++#define MSR_VMX_EPT_WB (1ULL << 14) ++#define MSR_VMX_EPT_2MB (1ULL << 16) ++#define MSR_VMX_EPT_1GB (1ULL << 17) ++#define MSR_VMX_EPT_INVEPT (1ULL << 20) ++#define MSR_VMX_EPT_AD_BITS (1ULL << 21) ++#define MSR_VMX_EPT_ADVANCED_VMEXIT_INFO (1ULL << 22) ++#define MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT (1ULL << 25) ++#define MSR_VMX_EPT_INVEPT_ALL_CONTEXT (1ULL << 26) ++#define MSR_VMX_EPT_INVVPID (1ULL << 32) ++#define MSR_VMX_EPT_INVVPID_SINGLE_ADDR (1ULL << 40) ++#define MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT (1ULL << 41) ++#define MSR_VMX_EPT_INVVPID_ALL_CONTEXT (1ULL << 42) ++#define MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS (1ULL << 43) ++ ++#define MSR_VMX_VMFUNC_EPT_SWITCHING (1ULL << 0) ++ ++ ++/* VMX controls */ ++#define VMX_CPU_BASED_VIRTUAL_INTR_PENDING 0x00000004 ++#define VMX_CPU_BASED_USE_TSC_OFFSETING 0x00000008 ++#define VMX_CPU_BASED_HLT_EXITING 0x00000080 ++#define VMX_CPU_BASED_INVLPG_EXITING 0x00000200 ++#define VMX_CPU_BASED_MWAIT_EXITING 0x00000400 ++#define VMX_CPU_BASED_RDPMC_EXITING 0x00000800 ++#define VMX_CPU_BASED_RDTSC_EXITING 0x00001000 ++#define VMX_CPU_BASED_CR3_LOAD_EXITING 0x00008000 ++#define VMX_CPU_BASED_CR3_STORE_EXITING 0x00010000 ++#define VMX_CPU_BASED_CR8_LOAD_EXITING 0x00080000 ++#define VMX_CPU_BASED_CR8_STORE_EXITING 0x00100000 ++#define VMX_CPU_BASED_TPR_SHADOW 0x00200000 ++#define VMX_CPU_BASED_VIRTUAL_NMI_PENDING 0x00400000 ++#define VMX_CPU_BASED_MOV_DR_EXITING 0x00800000 ++#define VMX_CPU_BASED_UNCOND_IO_EXITING 0x01000000 ++#define VMX_CPU_BASED_USE_IO_BITMAPS 0x02000000 ++#define VMX_CPU_BASED_MONITOR_TRAP_FLAG 0x08000000 ++#define VMX_CPU_BASED_USE_MSR_BITMAPS 0x10000000 ++#define VMX_CPU_BASED_MONITOR_EXITING 0x20000000 ++#define VMX_CPU_BASED_PAUSE_EXITING 0x40000000 ++#define VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS 0x80000000 ++ ++#define VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES 0x00000001 ++#define VMX_SECONDARY_EXEC_ENABLE_EPT 0x00000002 ++#define VMX_SECONDARY_EXEC_DESC 0x00000004 ++#define VMX_SECONDARY_EXEC_RDTSCP 0x00000008 ++#define VMX_SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE 0x00000010 ++#define VMX_SECONDARY_EXEC_ENABLE_VPID 0x00000020 ++#define VMX_SECONDARY_EXEC_WBINVD_EXITING 0x00000040 ++#define VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST 0x00000080 ++#define VMX_SECONDARY_EXEC_APIC_REGISTER_VIRT 0x00000100 ++#define VMX_SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY 0x00000200 ++#define VMX_SECONDARY_EXEC_PAUSE_LOOP_EXITING 0x00000400 ++#define VMX_SECONDARY_EXEC_RDRAND_EXITING 0x00000800 ++#define VMX_SECONDARY_EXEC_ENABLE_INVPCID 0x00001000 ++#define VMX_SECONDARY_EXEC_ENABLE_VMFUNC 0x00002000 ++#define VMX_SECONDARY_EXEC_SHADOW_VMCS 0x00004000 ++#define VMX_SECONDARY_EXEC_ENCLS_EXITING 0x00008000 ++#define VMX_SECONDARY_EXEC_RDSEED_EXITING 0x00010000 ++#define VMX_SECONDARY_EXEC_ENABLE_PML 0x00020000 ++#define VMX_SECONDARY_EXEC_XSAVES 0x00100000 ++ ++#define VMX_PIN_BASED_EXT_INTR_MASK 0x00000001 ++#define VMX_PIN_BASED_NMI_EXITING 0x00000008 ++#define VMX_PIN_BASED_VIRTUAL_NMIS 0x00000020 ++#define VMX_PIN_BASED_VMX_PREEMPTION_TIMER 0x00000040 ++#define VMX_PIN_BASED_POSTED_INTR 0x00000080 ++ ++#define VMX_VM_EXIT_SAVE_DEBUG_CONTROLS 0x00000004 ++#define VMX_VM_EXIT_HOST_ADDR_SPACE_SIZE 0x00000200 ++#define VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL 0x00001000 ++#define VMX_VM_EXIT_ACK_INTR_ON_EXIT 0x00008000 ++#define VMX_VM_EXIT_SAVE_IA32_PAT 0x00040000 ++#define VMX_VM_EXIT_LOAD_IA32_PAT 0x00080000 ++#define VMX_VM_EXIT_SAVE_IA32_EFER 0x00100000 ++#define VMX_VM_EXIT_LOAD_IA32_EFER 0x00200000 ++#define VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER 0x00400000 ++#define VMX_VM_EXIT_CLEAR_BNDCFGS 0x00800000 ++#define VMX_VM_EXIT_PT_CONCEAL_PIP 0x01000000 ++#define VMX_VM_EXIT_CLEAR_IA32_RTIT_CTL 0x02000000 ++ ++#define VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS 0x00000004 ++#define VMX_VM_ENTRY_IA32E_MODE 0x00000200 ++#define VMX_VM_ENTRY_SMM 0x00000400 ++#define VMX_VM_ENTRY_DEACT_DUAL_MONITOR 0x00000800 ++#define VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL 0x00002000 ++#define VMX_VM_ENTRY_LOAD_IA32_PAT 0x00004000 ++#define VMX_VM_ENTRY_LOAD_IA32_EFER 0x00008000 ++#define VMX_VM_ENTRY_LOAD_BNDCFGS 0x00010000 ++#define VMX_VM_ENTRY_PT_CONCEAL_PIP 0x00020000 ++#define VMX_VM_ENTRY_LOAD_IA32_RTIT_CTL 0x00040000 ++ + #ifndef HYPERV_SPINLOCK_NEVER_RETRY + #define HYPERV_SPINLOCK_NEVER_RETRY 0xFFFFFFFF + #endif +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-add-VMX-features-to-named-CPU-models-RHE.patch b/SOURCES/kvm-target-i386-add-VMX-features-to-named-CPU-models-RHE.patch new file mode 100644 index 0000000..3d1cb0c --- /dev/null +++ b/SOURCES/kvm-target-i386-add-VMX-features-to-named-CPU-models-RHE.patch @@ -0,0 +1,654 @@ +From 1163b93bcdbef8e11c276722014d39c3619dbd1b Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Fri, 22 Nov 2019 11:53:48 +0000 +Subject: [PATCH 15/16] target/i386: add VMX features to named CPU models (RHEL + only) + +RH-Author: Paolo Bonzini +Message-id: <20191122115348.25000-16-pbonzini@redhat.com> +Patchwork-id: 92614 +O-Subject: [RHEL8.2/rhel qemu-kvm PATCH 15/15] target/i386: add VMX features to named CPU models (RHEL only) +Bugzilla: 1689270 +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Maxim Levitsky + +Upstream has switched to versioned CPU models in order to provide the +noTSX and IBRS variants. In 2.12, VMX features have to be duplicated by +hand. + +Signed-off-by: Paolo Bonzini +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 538 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 538 insertions(+) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 36c9252..3effcf3 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -2212,6 +2212,46 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX, + .features[FEAT_8000_0001_ECX] = + CPUID_EXT3_LAHF_LM, ++ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS | ++ MSR_VMX_BASIC_TRUE_CTLS, ++ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | ++ VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VMX_VM_ENTRY_LOAD_IA32_PAT | ++ VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_LOAD_IA32_EFER, ++ .features[FEAT_VMX_EPT_VPID_CAPS] = MSR_VMX_EPT_EXECONLY | ++ MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | ++ MSR_VMX_EPT_1GB | MSR_VMX_EPT_INVEPT | ++ MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | MSR_VMX_EPT_INVVPID_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS, ++ .features[FEAT_VMX_EXIT_CTLS] = ++ VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | ++ VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | ++ VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_LOAD_IA32_EFER | ++ VMX_VM_EXIT_SAVE_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | ++ VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, ++ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT, ++ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | ++ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS | ++ VMX_PIN_BASED_VMX_PREEMPTION_TIMER, ++ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | ++ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | ++ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | ++ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | ++ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | ++ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | ++ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | ++ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | ++ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | ++ VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | ++ VMX_CPU_BASED_MONITOR_TRAP_FLAG | ++ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, ++ .features[FEAT_VMX_SECONDARY_CTLS] = ++ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | ++ VMX_SECONDARY_EXEC_WBINVD_EXITING | VMX_SECONDARY_EXEC_ENABLE_EPT | ++ VMX_SECONDARY_EXEC_DESC | VMX_SECONDARY_EXEC_RDTSCP | ++ VMX_SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | ++ VMX_SECONDARY_EXEC_ENABLE_VPID, + .xlevel = 0x80000008, + .model_id = "Intel Core i7 9xx (Nehalem Core i7, IBRS update)", + }, +@@ -2307,6 +2347,47 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_7_0_EDX_SPEC_CTRL, + .features[FEAT_6_EAX] = + CPUID_6_EAX_ARAT, ++ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS | ++ MSR_VMX_BASIC_TRUE_CTLS, ++ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | ++ VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VMX_VM_ENTRY_LOAD_IA32_PAT | ++ VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_LOAD_IA32_EFER, ++ .features[FEAT_VMX_EPT_VPID_CAPS] = MSR_VMX_EPT_EXECONLY | ++ MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | ++ MSR_VMX_EPT_1GB | MSR_VMX_EPT_INVEPT | ++ MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | MSR_VMX_EPT_INVVPID_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS, ++ .features[FEAT_VMX_EXIT_CTLS] = ++ VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | ++ VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | ++ VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_LOAD_IA32_EFER | ++ VMX_VM_EXIT_SAVE_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | ++ VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, ++ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT | ++ MSR_VMX_MISC_STORE_LMA, ++ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | ++ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS | ++ VMX_PIN_BASED_VMX_PREEMPTION_TIMER, ++ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | ++ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | ++ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | ++ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | ++ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | ++ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | ++ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | ++ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | ++ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | ++ VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | ++ VMX_CPU_BASED_MONITOR_TRAP_FLAG | ++ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, ++ .features[FEAT_VMX_SECONDARY_CTLS] = ++ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | ++ VMX_SECONDARY_EXEC_WBINVD_EXITING | VMX_SECONDARY_EXEC_ENABLE_EPT | ++ VMX_SECONDARY_EXEC_DESC | VMX_SECONDARY_EXEC_RDTSCP | ++ VMX_SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | ++ VMX_SECONDARY_EXEC_ENABLE_VPID | VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST, + .xlevel = 0x80000008, + .model_id = "Westmere E56xx/L56xx/X56xx (IBRS update)", + }, +@@ -2412,6 +2493,47 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_XSAVE_XSAVEOPT, + .features[FEAT_6_EAX] = + CPUID_6_EAX_ARAT, ++ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS | ++ MSR_VMX_BASIC_TRUE_CTLS, ++ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | ++ VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VMX_VM_ENTRY_LOAD_IA32_PAT | ++ VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_LOAD_IA32_EFER, ++ .features[FEAT_VMX_EPT_VPID_CAPS] = MSR_VMX_EPT_EXECONLY | ++ MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | ++ MSR_VMX_EPT_1GB | MSR_VMX_EPT_INVEPT | ++ MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | MSR_VMX_EPT_INVVPID_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS, ++ .features[FEAT_VMX_EXIT_CTLS] = ++ VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | ++ VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | ++ VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_LOAD_IA32_EFER | ++ VMX_VM_EXIT_SAVE_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | ++ VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, ++ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT | ++ MSR_VMX_MISC_STORE_LMA, ++ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | ++ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS | ++ VMX_PIN_BASED_VMX_PREEMPTION_TIMER, ++ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | ++ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | ++ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | ++ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | ++ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | ++ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | ++ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | ++ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | ++ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | ++ VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | ++ VMX_CPU_BASED_MONITOR_TRAP_FLAG | ++ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, ++ .features[FEAT_VMX_SECONDARY_CTLS] = ++ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | ++ VMX_SECONDARY_EXEC_WBINVD_EXITING | VMX_SECONDARY_EXEC_ENABLE_EPT | ++ VMX_SECONDARY_EXEC_DESC | VMX_SECONDARY_EXEC_RDTSCP | ++ VMX_SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | ++ VMX_SECONDARY_EXEC_ENABLE_VPID | VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST, + .xlevel = 0x80000008, + .model_id = "Intel Xeon E312xx (Sandy Bridge, IBRS update)", + }, +@@ -2526,6 +2648,50 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_XSAVE_XSAVEOPT, + .features[FEAT_6_EAX] = + CPUID_6_EAX_ARAT, ++ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS | ++ MSR_VMX_BASIC_TRUE_CTLS, ++ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | ++ VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VMX_VM_ENTRY_LOAD_IA32_PAT | ++ VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_LOAD_IA32_EFER, ++ .features[FEAT_VMX_EPT_VPID_CAPS] = MSR_VMX_EPT_EXECONLY | ++ MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | ++ MSR_VMX_EPT_1GB | MSR_VMX_EPT_INVEPT | ++ MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | MSR_VMX_EPT_INVVPID_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS, ++ .features[FEAT_VMX_EXIT_CTLS] = ++ VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | ++ VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | ++ VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_LOAD_IA32_EFER | ++ VMX_VM_EXIT_SAVE_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | ++ VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, ++ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT | ++ MSR_VMX_MISC_STORE_LMA, ++ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | ++ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS | ++ VMX_PIN_BASED_VMX_PREEMPTION_TIMER | VMX_PIN_BASED_POSTED_INTR, ++ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | ++ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | ++ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | ++ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | ++ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | ++ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | ++ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | ++ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | ++ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | ++ VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | ++ VMX_CPU_BASED_MONITOR_TRAP_FLAG | ++ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, ++ .features[FEAT_VMX_SECONDARY_CTLS] = ++ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | ++ VMX_SECONDARY_EXEC_WBINVD_EXITING | VMX_SECONDARY_EXEC_ENABLE_EPT | ++ VMX_SECONDARY_EXEC_DESC | VMX_SECONDARY_EXEC_RDTSCP | ++ VMX_SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | ++ VMX_SECONDARY_EXEC_ENABLE_VPID | VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST | ++ VMX_SECONDARY_EXEC_APIC_REGISTER_VIRT | ++ VMX_SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY | ++ VMX_SECONDARY_EXEC_RDRAND_EXITING, + .xlevel = 0x80000008, + .model_id = "Intel Xeon E3-12xx v2 (Ivy Bridge, IBRS)", + }, +@@ -2562,6 +2728,52 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_XSAVE_XSAVEOPT, + .features[FEAT_6_EAX] = + CPUID_6_EAX_ARAT, ++ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS | ++ MSR_VMX_BASIC_TRUE_CTLS, ++ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | ++ VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VMX_VM_ENTRY_LOAD_IA32_PAT | ++ VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_LOAD_IA32_EFER, ++ .features[FEAT_VMX_EPT_VPID_CAPS] = MSR_VMX_EPT_EXECONLY | ++ MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | ++ MSR_VMX_EPT_1GB | MSR_VMX_EPT_INVEPT | ++ MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | MSR_VMX_EPT_INVVPID_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS | MSR_VMX_EPT_AD_BITS, ++ .features[FEAT_VMX_EXIT_CTLS] = ++ VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | ++ VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | ++ VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_LOAD_IA32_EFER | ++ VMX_VM_EXIT_SAVE_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | ++ VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, ++ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT | ++ MSR_VMX_MISC_STORE_LMA | MSR_VMX_MISC_VMWRITE_VMEXIT, ++ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | ++ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS | ++ VMX_PIN_BASED_VMX_PREEMPTION_TIMER | VMX_PIN_BASED_POSTED_INTR, ++ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | ++ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | ++ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | ++ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | ++ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | ++ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | ++ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | ++ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | ++ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | ++ VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | ++ VMX_CPU_BASED_MONITOR_TRAP_FLAG | ++ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, ++ .features[FEAT_VMX_SECONDARY_CTLS] = ++ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | ++ VMX_SECONDARY_EXEC_WBINVD_EXITING | VMX_SECONDARY_EXEC_ENABLE_EPT | ++ VMX_SECONDARY_EXEC_DESC | VMX_SECONDARY_EXEC_RDTSCP | ++ VMX_SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | ++ VMX_SECONDARY_EXEC_ENABLE_VPID | VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST | ++ VMX_SECONDARY_EXEC_APIC_REGISTER_VIRT | ++ VMX_SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY | ++ VMX_SECONDARY_EXEC_RDRAND_EXITING | VMX_SECONDARY_EXEC_ENABLE_INVPCID | ++ VMX_SECONDARY_EXEC_ENABLE_VMFUNC | VMX_SECONDARY_EXEC_SHADOW_VMCS, ++ .features[FEAT_VMX_VMFUNC] = MSR_VMX_VMFUNC_EPT_SWITCHING, + .xlevel = 0x80000008, + .model_id = "Intel Core Processor (Haswell, no TSX)", + }, +@@ -2600,6 +2812,52 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_XSAVE_XSAVEOPT, + .features[FEAT_6_EAX] = + CPUID_6_EAX_ARAT, ++ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS | ++ MSR_VMX_BASIC_TRUE_CTLS, ++ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | ++ VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VMX_VM_ENTRY_LOAD_IA32_PAT | ++ VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_LOAD_IA32_EFER, ++ .features[FEAT_VMX_EPT_VPID_CAPS] = MSR_VMX_EPT_EXECONLY | ++ MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | ++ MSR_VMX_EPT_1GB | MSR_VMX_EPT_INVEPT | ++ MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | MSR_VMX_EPT_INVVPID_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS | MSR_VMX_EPT_AD_BITS, ++ .features[FEAT_VMX_EXIT_CTLS] = ++ VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | ++ VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | ++ VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_LOAD_IA32_EFER | ++ VMX_VM_EXIT_SAVE_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | ++ VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, ++ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT | ++ MSR_VMX_MISC_STORE_LMA | MSR_VMX_MISC_VMWRITE_VMEXIT, ++ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | ++ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS | ++ VMX_PIN_BASED_VMX_PREEMPTION_TIMER | VMX_PIN_BASED_POSTED_INTR, ++ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | ++ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | ++ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | ++ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | ++ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | ++ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | ++ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | ++ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | ++ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | ++ VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | ++ VMX_CPU_BASED_MONITOR_TRAP_FLAG | ++ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, ++ .features[FEAT_VMX_SECONDARY_CTLS] = ++ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | ++ VMX_SECONDARY_EXEC_WBINVD_EXITING | VMX_SECONDARY_EXEC_ENABLE_EPT | ++ VMX_SECONDARY_EXEC_DESC | VMX_SECONDARY_EXEC_RDTSCP | ++ VMX_SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | ++ VMX_SECONDARY_EXEC_ENABLE_VPID | VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST | ++ VMX_SECONDARY_EXEC_APIC_REGISTER_VIRT | ++ VMX_SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY | ++ VMX_SECONDARY_EXEC_RDRAND_EXITING | VMX_SECONDARY_EXEC_ENABLE_INVPCID | ++ VMX_SECONDARY_EXEC_ENABLE_VMFUNC | VMX_SECONDARY_EXEC_SHADOW_VMCS, ++ .features[FEAT_VMX_VMFUNC] = MSR_VMX_VMFUNC_EPT_SWITCHING, + .xlevel = 0x80000008, + .model_id = "Intel Core Processor (Haswell, no TSX, IBRS)", + }, +@@ -2722,6 +2980,52 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_XSAVE_XSAVEOPT, + .features[FEAT_6_EAX] = + CPUID_6_EAX_ARAT, ++ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS | ++ MSR_VMX_BASIC_TRUE_CTLS, ++ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | ++ VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VMX_VM_ENTRY_LOAD_IA32_PAT | ++ VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_LOAD_IA32_EFER, ++ .features[FEAT_VMX_EPT_VPID_CAPS] = MSR_VMX_EPT_EXECONLY | ++ MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | ++ MSR_VMX_EPT_1GB | MSR_VMX_EPT_INVEPT | ++ MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | MSR_VMX_EPT_INVVPID_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS | MSR_VMX_EPT_AD_BITS, ++ .features[FEAT_VMX_EXIT_CTLS] = ++ VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | ++ VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | ++ VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_LOAD_IA32_EFER | ++ VMX_VM_EXIT_SAVE_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | ++ VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, ++ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT | ++ MSR_VMX_MISC_STORE_LMA | MSR_VMX_MISC_VMWRITE_VMEXIT, ++ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | ++ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS | ++ VMX_PIN_BASED_VMX_PREEMPTION_TIMER | VMX_PIN_BASED_POSTED_INTR, ++ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | ++ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | ++ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | ++ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | ++ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | ++ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | ++ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | ++ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | ++ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | ++ VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | ++ VMX_CPU_BASED_MONITOR_TRAP_FLAG | ++ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, ++ .features[FEAT_VMX_SECONDARY_CTLS] = ++ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | ++ VMX_SECONDARY_EXEC_WBINVD_EXITING | VMX_SECONDARY_EXEC_ENABLE_EPT | ++ VMX_SECONDARY_EXEC_DESC | VMX_SECONDARY_EXEC_RDTSCP | ++ VMX_SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | ++ VMX_SECONDARY_EXEC_ENABLE_VPID | VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST | ++ VMX_SECONDARY_EXEC_APIC_REGISTER_VIRT | ++ VMX_SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY | ++ VMX_SECONDARY_EXEC_RDRAND_EXITING | VMX_SECONDARY_EXEC_ENABLE_INVPCID | ++ VMX_SECONDARY_EXEC_ENABLE_VMFUNC | VMX_SECONDARY_EXEC_SHADOW_VMCS, ++ .features[FEAT_VMX_VMFUNC] = MSR_VMX_VMFUNC_EPT_SWITCHING, + .xlevel = 0x80000008, + .model_id = "Intel Core Processor (Haswell, IBRS)", + }, +@@ -2760,6 +3064,53 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_XSAVE_XSAVEOPT, + .features[FEAT_6_EAX] = + CPUID_6_EAX_ARAT, ++ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS | ++ MSR_VMX_BASIC_TRUE_CTLS, ++ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | ++ VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VMX_VM_ENTRY_LOAD_IA32_PAT | ++ VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_LOAD_IA32_EFER, ++ .features[FEAT_VMX_EPT_VPID_CAPS] = MSR_VMX_EPT_EXECONLY | ++ MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | ++ MSR_VMX_EPT_1GB | MSR_VMX_EPT_INVEPT | ++ MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | MSR_VMX_EPT_INVVPID_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS | MSR_VMX_EPT_AD_BITS, ++ .features[FEAT_VMX_EXIT_CTLS] = ++ VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | ++ VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | ++ VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_LOAD_IA32_EFER | ++ VMX_VM_EXIT_SAVE_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | ++ VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, ++ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT | ++ MSR_VMX_MISC_STORE_LMA | MSR_VMX_MISC_VMWRITE_VMEXIT, ++ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | ++ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS | ++ VMX_PIN_BASED_VMX_PREEMPTION_TIMER | VMX_PIN_BASED_POSTED_INTR, ++ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | ++ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | ++ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | ++ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | ++ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | ++ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | ++ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | ++ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | ++ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | ++ VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | ++ VMX_CPU_BASED_MONITOR_TRAP_FLAG | ++ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, ++ .features[FEAT_VMX_SECONDARY_CTLS] = ++ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | ++ VMX_SECONDARY_EXEC_WBINVD_EXITING | VMX_SECONDARY_EXEC_ENABLE_EPT | ++ VMX_SECONDARY_EXEC_DESC | VMX_SECONDARY_EXEC_RDTSCP | ++ VMX_SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | ++ VMX_SECONDARY_EXEC_ENABLE_VPID | VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST | ++ VMX_SECONDARY_EXEC_APIC_REGISTER_VIRT | ++ VMX_SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY | ++ VMX_SECONDARY_EXEC_RDRAND_EXITING | VMX_SECONDARY_EXEC_ENABLE_INVPCID | ++ VMX_SECONDARY_EXEC_ENABLE_VMFUNC | VMX_SECONDARY_EXEC_SHADOW_VMCS | ++ VMX_SECONDARY_EXEC_RDSEED_EXITING | VMX_SECONDARY_EXEC_ENABLE_PML, ++ .features[FEAT_VMX_VMFUNC] = MSR_VMX_VMFUNC_EPT_SWITCHING, + .xlevel = 0x80000008, + .model_id = "Intel Core Processor (Broadwell, no TSX)", + }, +@@ -2800,6 +3151,53 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_XSAVE_XSAVEOPT, + .features[FEAT_6_EAX] = + CPUID_6_EAX_ARAT, ++ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS | ++ MSR_VMX_BASIC_TRUE_CTLS, ++ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | ++ VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VMX_VM_ENTRY_LOAD_IA32_PAT | ++ VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_LOAD_IA32_EFER, ++ .features[FEAT_VMX_EPT_VPID_CAPS] = MSR_VMX_EPT_EXECONLY | ++ MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | ++ MSR_VMX_EPT_1GB | MSR_VMX_EPT_INVEPT | ++ MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | MSR_VMX_EPT_INVVPID_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS | MSR_VMX_EPT_AD_BITS, ++ .features[FEAT_VMX_EXIT_CTLS] = ++ VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | ++ VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | ++ VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_LOAD_IA32_EFER | ++ VMX_VM_EXIT_SAVE_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | ++ VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, ++ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT | ++ MSR_VMX_MISC_STORE_LMA | MSR_VMX_MISC_VMWRITE_VMEXIT, ++ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | ++ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS | ++ VMX_PIN_BASED_VMX_PREEMPTION_TIMER | VMX_PIN_BASED_POSTED_INTR, ++ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | ++ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | ++ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | ++ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | ++ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | ++ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | ++ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | ++ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | ++ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | ++ VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | ++ VMX_CPU_BASED_MONITOR_TRAP_FLAG | ++ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, ++ .features[FEAT_VMX_SECONDARY_CTLS] = ++ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | ++ VMX_SECONDARY_EXEC_WBINVD_EXITING | VMX_SECONDARY_EXEC_ENABLE_EPT | ++ VMX_SECONDARY_EXEC_DESC | VMX_SECONDARY_EXEC_RDTSCP | ++ VMX_SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | ++ VMX_SECONDARY_EXEC_ENABLE_VPID | VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST | ++ VMX_SECONDARY_EXEC_APIC_REGISTER_VIRT | ++ VMX_SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY | ++ VMX_SECONDARY_EXEC_RDRAND_EXITING | VMX_SECONDARY_EXEC_ENABLE_INVPCID | ++ VMX_SECONDARY_EXEC_ENABLE_VMFUNC | VMX_SECONDARY_EXEC_SHADOW_VMCS | ++ VMX_SECONDARY_EXEC_RDSEED_EXITING | VMX_SECONDARY_EXEC_ENABLE_PML, ++ .features[FEAT_VMX_VMFUNC] = MSR_VMX_VMFUNC_EPT_SWITCHING, + .xlevel = 0x80000008, + .model_id = "Intel Core Processor (Broadwell, no TSX, IBRS)", + }, +@@ -2925,6 +3323,53 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_XSAVE_XSAVEOPT, + .features[FEAT_6_EAX] = + CPUID_6_EAX_ARAT, ++ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS | ++ MSR_VMX_BASIC_TRUE_CTLS, ++ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | ++ VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VMX_VM_ENTRY_LOAD_IA32_PAT | ++ VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_LOAD_IA32_EFER, ++ .features[FEAT_VMX_EPT_VPID_CAPS] = MSR_VMX_EPT_EXECONLY | ++ MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | ++ MSR_VMX_EPT_1GB | MSR_VMX_EPT_INVEPT | ++ MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | MSR_VMX_EPT_INVVPID_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS | MSR_VMX_EPT_AD_BITS, ++ .features[FEAT_VMX_EXIT_CTLS] = ++ VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | ++ VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | ++ VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_LOAD_IA32_EFER | ++ VMX_VM_EXIT_SAVE_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | ++ VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, ++ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT | ++ MSR_VMX_MISC_STORE_LMA | MSR_VMX_MISC_VMWRITE_VMEXIT, ++ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | ++ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS | ++ VMX_PIN_BASED_VMX_PREEMPTION_TIMER | VMX_PIN_BASED_POSTED_INTR, ++ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | ++ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | ++ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | ++ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | ++ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | ++ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | ++ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | ++ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | ++ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | ++ VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | ++ VMX_CPU_BASED_MONITOR_TRAP_FLAG | ++ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, ++ .features[FEAT_VMX_SECONDARY_CTLS] = ++ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | ++ VMX_SECONDARY_EXEC_WBINVD_EXITING | VMX_SECONDARY_EXEC_ENABLE_EPT | ++ VMX_SECONDARY_EXEC_DESC | VMX_SECONDARY_EXEC_RDTSCP | ++ VMX_SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | ++ VMX_SECONDARY_EXEC_ENABLE_VPID | VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST | ++ VMX_SECONDARY_EXEC_APIC_REGISTER_VIRT | ++ VMX_SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY | ++ VMX_SECONDARY_EXEC_RDRAND_EXITING | VMX_SECONDARY_EXEC_ENABLE_INVPCID | ++ VMX_SECONDARY_EXEC_ENABLE_VMFUNC | VMX_SECONDARY_EXEC_SHADOW_VMCS | ++ VMX_SECONDARY_EXEC_RDSEED_EXITING | VMX_SECONDARY_EXEC_ENABLE_PML, ++ .features[FEAT_VMX_VMFUNC] = MSR_VMX_VMFUNC_EPT_SWITCHING, + .xlevel = 0x80000008, + .model_id = "Intel Core Processor (Broadwell, IBRS)", + }, +@@ -3062,6 +3507,51 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_XSAVE_XGETBV1, + .features[FEAT_6_EAX] = + CPUID_6_EAX_ARAT, ++ /* Missing: Mode-based execute control (XS/XU), processor tracing, TSC scaling */ ++ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS | ++ MSR_VMX_BASIC_TRUE_CTLS, ++ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | ++ VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VMX_VM_ENTRY_LOAD_IA32_PAT | ++ VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_LOAD_IA32_EFER, ++ .features[FEAT_VMX_EPT_VPID_CAPS] = MSR_VMX_EPT_EXECONLY | ++ MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | ++ MSR_VMX_EPT_1GB | MSR_VMX_EPT_INVEPT | ++ MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | MSR_VMX_EPT_INVVPID_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS | MSR_VMX_EPT_AD_BITS, ++ .features[FEAT_VMX_EXIT_CTLS] = ++ VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | ++ VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | ++ VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_LOAD_IA32_EFER | ++ VMX_VM_EXIT_SAVE_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | ++ VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, ++ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT | ++ MSR_VMX_MISC_STORE_LMA | MSR_VMX_MISC_VMWRITE_VMEXIT, ++ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | ++ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS | ++ VMX_PIN_BASED_VMX_PREEMPTION_TIMER, ++ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | ++ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | ++ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | ++ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | ++ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | ++ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | ++ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | ++ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | ++ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | ++ VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | ++ VMX_CPU_BASED_MONITOR_TRAP_FLAG | ++ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, ++ .features[FEAT_VMX_SECONDARY_CTLS] = ++ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | ++ VMX_SECONDARY_EXEC_WBINVD_EXITING | VMX_SECONDARY_EXEC_ENABLE_EPT | ++ VMX_SECONDARY_EXEC_DESC | VMX_SECONDARY_EXEC_RDTSCP | ++ VMX_SECONDARY_EXEC_ENABLE_VPID | VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST | ++ VMX_SECONDARY_EXEC_RDRAND_EXITING | VMX_SECONDARY_EXEC_ENABLE_INVPCID | ++ VMX_SECONDARY_EXEC_ENABLE_VMFUNC | VMX_SECONDARY_EXEC_SHADOW_VMCS | ++ VMX_SECONDARY_EXEC_RDSEED_EXITING | VMX_SECONDARY_EXEC_ENABLE_PML, ++ .features[FEAT_VMX_VMFUNC] = MSR_VMX_VMFUNC_EPT_SWITCHING, + .xlevel = 0x80000008, + .model_id = "Intel Core Processor (Skylake, IBRS)", + }, +@@ -3208,6 +3698,54 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_XSAVE_XGETBV1, + .features[FEAT_6_EAX] = + CPUID_6_EAX_ARAT, ++ /* Missing: Mode-based execute control (XS/XU), processor tracing, TSC scaling */ ++ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS | ++ MSR_VMX_BASIC_TRUE_CTLS, ++ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | ++ VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VMX_VM_ENTRY_LOAD_IA32_PAT | ++ VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_LOAD_IA32_EFER, ++ .features[FEAT_VMX_EPT_VPID_CAPS] = MSR_VMX_EPT_EXECONLY | ++ MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | ++ MSR_VMX_EPT_1GB | MSR_VMX_EPT_INVEPT | ++ MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | MSR_VMX_EPT_INVVPID_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS | MSR_VMX_EPT_AD_BITS, ++ .features[FEAT_VMX_EXIT_CTLS] = ++ VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | ++ VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | ++ VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_LOAD_IA32_EFER | ++ VMX_VM_EXIT_SAVE_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | ++ VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, ++ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT | ++ MSR_VMX_MISC_STORE_LMA | MSR_VMX_MISC_VMWRITE_VMEXIT, ++ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | ++ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS | ++ VMX_PIN_BASED_VMX_PREEMPTION_TIMER | VMX_PIN_BASED_POSTED_INTR, ++ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | ++ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | ++ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | ++ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | ++ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | ++ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | ++ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | ++ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | ++ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | ++ VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | ++ VMX_CPU_BASED_MONITOR_TRAP_FLAG | ++ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, ++ .features[FEAT_VMX_SECONDARY_CTLS] = ++ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | ++ VMX_SECONDARY_EXEC_WBINVD_EXITING | VMX_SECONDARY_EXEC_ENABLE_EPT | ++ VMX_SECONDARY_EXEC_DESC | VMX_SECONDARY_EXEC_RDTSCP | ++ VMX_SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | ++ VMX_SECONDARY_EXEC_ENABLE_VPID | VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST | ++ VMX_SECONDARY_EXEC_APIC_REGISTER_VIRT | ++ VMX_SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY | ++ VMX_SECONDARY_EXEC_RDRAND_EXITING | VMX_SECONDARY_EXEC_ENABLE_INVPCID | ++ VMX_SECONDARY_EXEC_ENABLE_VMFUNC | VMX_SECONDARY_EXEC_SHADOW_VMCS | ++ VMX_SECONDARY_EXEC_RDSEED_EXITING | VMX_SECONDARY_EXEC_ENABLE_PML, ++ .features[FEAT_VMX_VMFUNC] = MSR_VMX_VMFUNC_EPT_SWITCHING, + .xlevel = 0x80000008, + .model_id = "Intel Xeon Processor (Skylake, IBRS)", + }, +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-add-VMX-features-to-named-CPU-models.patch b/SOURCES/kvm-target-i386-add-VMX-features-to-named-CPU-models.patch new file mode 100644 index 0000000..3ca0136 --- /dev/null +++ b/SOURCES/kvm-target-i386-add-VMX-features-to-named-CPU-models.patch @@ -0,0 +1,891 @@ +From a958a54a1072e201d209fd54e3fd0b55a331c5da Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Fri, 22 Nov 2019 11:53:47 +0000 +Subject: [PATCH 14/16] target/i386: add VMX features to named CPU models + +RH-Author: Paolo Bonzini +Message-id: <20191122115348.25000-15-pbonzini@redhat.com> +Patchwork-id: 92613 +O-Subject: [RHEL8.2/rhel qemu-kvm PATCH 14/15] target/i386: add VMX features to named CPU models +Bugzilla: 1689270 +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Maxim Levitsky + +This allows using "-cpu Haswell,+vmx", which we did not really want to +support in QEMU but was produced by Libvirt when using the "host-model" +CPU model. Without this patch, no VMX feature is _actually_ supported +(only the basic instruction set extensions are) and KVM fails to load +in the guest. + +This was produced from the output of scripts/kvm/vmxcap using the following +very ugly Python script: + + bits = { + 'INS/OUTS instruction information': ['FEAT_VMX_BASIC', 'MSR_VMX_BASIC_INS_OUTS'], + 'IA32_VMX_TRUE_*_CTLS support': ['FEAT_VMX_BASIC', 'MSR_VMX_BASIC_TRUE_CTLS'], + 'External interrupt exiting': ['FEAT_VMX_PINBASED_CTLS', 'VMX_PIN_BASED_EXT_INTR_MASK'], + 'NMI exiting': ['FEAT_VMX_PINBASED_CTLS', 'VMX_PIN_BASED_NMI_EXITING'], + 'Virtual NMIs': ['FEAT_VMX_PINBASED_CTLS', 'VMX_PIN_BASED_VIRTUAL_NMIS'], + 'Activate VMX-preemption timer': ['FEAT_VMX_PINBASED_CTLS', 'VMX_PIN_BASED_VMX_PREEMPTION_TIMER'], + 'Process posted interrupts': ['FEAT_VMX_PINBASED_CTLS', 'VMX_PIN_BASED_POSTED_INTR'], + 'Interrupt window exiting': ['FEAT_VMX_PROCBASED_CTLS', 'VMX_CPU_BASED_VIRTUAL_INTR_PENDING'], + 'Use TSC offsetting': ['FEAT_VMX_PROCBASED_CTLS', 'VMX_CPU_BASED_USE_TSC_OFFSETING'], + 'HLT exiting': ['FEAT_VMX_PROCBASED_CTLS', 'VMX_CPU_BASED_HLT_EXITING'], + 'INVLPG exiting': ['FEAT_VMX_PROCBASED_CTLS', 'VMX_CPU_BASED_INVLPG_EXITING'], + 'MWAIT exiting': ['FEAT_VMX_PROCBASED_CTLS', 'VMX_CPU_BASED_MWAIT_EXITING'], + 'RDPMC exiting': ['FEAT_VMX_PROCBASED_CTLS', 'VMX_CPU_BASED_RDPMC_EXITING'], + 'RDTSC exiting': ['FEAT_VMX_PROCBASED_CTLS', 'VMX_CPU_BASED_RDTSC_EXITING'], + 'CR3-load exiting': ['FEAT_VMX_PROCBASED_CTLS', 'VMX_CPU_BASED_CR3_LOAD_EXITING'], + 'CR3-store exiting': ['FEAT_VMX_PROCBASED_CTLS', 'VMX_CPU_BASED_CR3_STORE_EXITING'], + 'CR8-load exiting': ['FEAT_VMX_PROCBASED_CTLS', 'VMX_CPU_BASED_CR8_LOAD_EXITING'], + 'CR8-store exiting': ['FEAT_VMX_PROCBASED_CTLS', 'VMX_CPU_BASED_CR8_STORE_EXITING'], + 'Use TPR shadow': ['FEAT_VMX_PROCBASED_CTLS', 'VMX_CPU_BASED_TPR_SHADOW'], + 'NMI-window exiting': ['FEAT_VMX_PROCBASED_CTLS', 'VMX_CPU_BASED_VIRTUAL_NMI_PENDING'], + 'MOV-DR exiting': ['FEAT_VMX_PROCBASED_CTLS', 'VMX_CPU_BASED_MOV_DR_EXITING'], + 'Unconditional I/O exiting': ['FEAT_VMX_PROCBASED_CTLS', 'VMX_CPU_BASED_UNCOND_IO_EXITING'], + 'Use I/O bitmaps': ['FEAT_VMX_PROCBASED_CTLS', 'VMX_CPU_BASED_USE_IO_BITMAPS'], + 'Monitor trap flag': ['FEAT_VMX_PROCBASED_CTLS', 'VMX_CPU_BASED_MONITOR_TRAP_FLAG'], + 'Use MSR bitmaps': ['FEAT_VMX_PROCBASED_CTLS', 'VMX_CPU_BASED_USE_MSR_BITMAPS'], + 'MONITOR exiting': ['FEAT_VMX_PROCBASED_CTLS', 'VMX_CPU_BASED_MONITOR_EXITING'], + 'PAUSE exiting': ['FEAT_VMX_PROCBASED_CTLS', 'VMX_CPU_BASED_PAUSE_EXITING'], + 'Activate secondary control': ['FEAT_VMX_PROCBASED_CTLS', 'VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS'], + 'Virtualize APIC accesses': ['FEAT_VMX_SECONDARY_CTLS', 'VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES'], + 'Enable EPT': ['FEAT_VMX_SECONDARY_CTLS', 'VMX_SECONDARY_EXEC_ENABLE_EPT'], + 'Descriptor-table exiting': ['FEAT_VMX_SECONDARY_CTLS', 'VMX_SECONDARY_EXEC_DESC'], + 'Enable RDTSCP': ['FEAT_VMX_SECONDARY_CTLS', 'VMX_SECONDARY_EXEC_RDTSCP'], + 'Virtualize x2APIC mode': ['FEAT_VMX_SECONDARY_CTLS', 'VMX_SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE'], + 'Enable VPID': ['FEAT_VMX_SECONDARY_CTLS', 'VMX_SECONDARY_EXEC_ENABLE_VPID'], + 'WBINVD exiting': ['FEAT_VMX_SECONDARY_CTLS', 'VMX_SECONDARY_EXEC_WBINVD_EXITING'], + 'Unrestricted guest': ['FEAT_VMX_SECONDARY_CTLS', 'VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST'], + 'APIC register emulation': ['FEAT_VMX_SECONDARY_CTLS', 'VMX_SECONDARY_EXEC_APIC_REGISTER_VIRT'], + 'Virtual interrupt delivery': ['FEAT_VMX_SECONDARY_CTLS', 'VMX_SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY'], + 'PAUSE-loop exiting': ['FEAT_VMX_SECONDARY_CTLS', 'VMX_SECONDARY_EXEC_PAUSE_LOOP_EXITING'], + 'RDRAND exiting': ['FEAT_VMX_SECONDARY_CTLS', 'VMX_SECONDARY_EXEC_RDRAND_EXITING'], + 'Enable INVPCID': ['FEAT_VMX_SECONDARY_CTLS', 'VMX_SECONDARY_EXEC_ENABLE_INVPCID'], + 'Enable VM functions': ['FEAT_VMX_SECONDARY_CTLS', 'VMX_SECONDARY_EXEC_ENABLE_VMFUNC'], + 'VMCS shadowing': ['FEAT_VMX_SECONDARY_CTLS', 'VMX_SECONDARY_EXEC_SHADOW_VMCS'], + 'RDSEED exiting': ['FEAT_VMX_SECONDARY_CTLS', 'VMX_SECONDARY_EXEC_RDSEED_EXITING'], + 'Enable PML': ['FEAT_VMX_SECONDARY_CTLS', 'VMX_SECONDARY_EXEC_ENABLE_PML'], + 'Enable XSAVES/XRSTORS': ['FEAT_VMX_SECONDARY_CTLS', 'VMX_SECONDARY_EXEC_XSAVES'], + 'Save debug controls': ['FEAT_VMX_EXIT_CTLS', 'VMX_VM_EXIT_SAVE_DEBUG_CONTROLS'], + 'Load IA32_PERF_GLOBAL_CTRL': ['FEAT_VMX_EXIT_CTLS', 'VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL'], + 'Acknowledge interrupt on exit': ['FEAT_VMX_EXIT_CTLS', 'VMX_VM_EXIT_ACK_INTR_ON_EXIT'], + 'Save IA32_PAT': ['FEAT_VMX_EXIT_CTLS', 'VMX_VM_EXIT_SAVE_IA32_PAT'], + 'Load IA32_PAT': ['FEAT_VMX_EXIT_CTLS', 'VMX_VM_EXIT_LOAD_IA32_PAT'], + 'Save IA32_EFER': ['FEAT_VMX_EXIT_CTLS', 'VMX_VM_EXIT_SAVE_IA32_EFER'], + 'Load IA32_EFER': ['FEAT_VMX_EXIT_CTLS', 'VMX_VM_EXIT_LOAD_IA32_EFER'], + 'Save VMX-preemption timer value': ['FEAT_VMX_EXIT_CTLS', 'VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER'], + 'Clear IA32_BNDCFGS': ['FEAT_VMX_EXIT_CTLS', 'VMX_VM_EXIT_CLEAR_BNDCFGS'], + 'Load debug controls': ['FEAT_VMX_ENTRY_CTLS', 'VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS'], + 'IA-32e mode guest': ['FEAT_VMX_ENTRY_CTLS', 'VMX_VM_ENTRY_IA32E_MODE'], + 'Load IA32_PERF_GLOBAL_CTRL': ['FEAT_VMX_ENTRY_CTLS', 'VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL'], + 'Load IA32_PAT': ['FEAT_VMX_ENTRY_CTLS', 'VMX_VM_ENTRY_LOAD_IA32_PAT'], + 'Load IA32_EFER': ['FEAT_VMX_ENTRY_CTLS', 'VMX_VM_ENTRY_LOAD_IA32_EFER'], + 'Load IA32_BNDCFGS': ['FEAT_VMX_ENTRY_CTLS', 'VMX_VM_ENTRY_LOAD_BNDCFGS'], + 'Store EFER.LMA into IA-32e mode guest control': ['FEAT_VMX_MISC', 'MSR_VMX_MISC_STORE_LMA'], + 'HLT activity state': ['FEAT_VMX_MISC', 'MSR_VMX_MISC_ACTIVITY_HLT'], + 'VMWRITE to VM-exit information fields': ['FEAT_VMX_MISC', 'MSR_VMX_MISC_VMWRITE_VMEXIT'], + 'Inject event with insn length=0': ['FEAT_VMX_MISC', 'MSR_VMX_MISC_ZERO_LEN_INJECT'], + 'Execute-only EPT translations': ['FEAT_VMX_EPT_VPID_CAPS', 'MSR_VMX_EPT_EXECONLY'], + 'Page-walk length 4': ['FEAT_VMX_EPT_VPID_CAPS', 'MSR_VMX_EPT_PAGE_WALK_LENGTH_4'], + 'Paging-structure memory type WB': ['FEAT_VMX_EPT_VPID_CAPS', 'MSR_VMX_EPT_WB'], + '2MB EPT pages': ['FEAT_VMX_EPT_VPID_CAPS', 'MSR_VMX_EPT_2MB | MSR_VMX_EPT_1GB'], + 'INVEPT supported': ['FEAT_VMX_EPT_VPID_CAPS', 'MSR_VMX_EPT_INVEPT'], + 'EPT accessed and dirty flags': ['FEAT_VMX_EPT_VPID_CAPS', 'MSR_VMX_EPT_AD_BITS'], + 'Single-context INVEPT': ['FEAT_VMX_EPT_VPID_CAPS', 'MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT'], + 'All-context INVEPT': ['FEAT_VMX_EPT_VPID_CAPS', 'MSR_VMX_EPT_INVEPT_ALL_CONTEXT'], + 'INVVPID supported': ['FEAT_VMX_EPT_VPID_CAPS', 'MSR_VMX_EPT_INVVPID'], + 'Individual-address INVVPID': ['FEAT_VMX_EPT_VPID_CAPS', 'MSR_VMX_EPT_INVVPID_SINGLE_ADDR'], + 'Single-context INVVPID': ['FEAT_VMX_EPT_VPID_CAPS', 'MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT'], + 'All-context INVVPID': ['FEAT_VMX_EPT_VPID_CAPS', 'MSR_VMX_EPT_INVVPID_ALL_CONTEXT'], + 'Single-context-retaining-globals INVVPID': ['FEAT_VMX_EPT_VPID_CAPS', 'MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS'], + 'EPTP Switching': ['FEAT_VMX_VMFUNC', 'MSR_VMX_VMFUNC_EPT_SWITCHING'] + } + + import sys + import textwrap + + out = {} + for l in sys.stdin.readlines(): + l = l.rstrip() + if l.endswith('!!'): + l = l[:-2].rstrip() + if l.startswith(' ') and (l.endswith('default') or l.endswith('yes')): + l = l[4:] + for key, value in bits.items(): + if l.startswith(key): + ctl, bit = value + if ctl in out: + out[ctl] = out[ctl] + ' | ' + else: + out[ctl] = ' [%s] = ' % ctl + out[ctl] = out[ctl] + bit + + for x in sorted(out.keys()): + print("\n ".join(textwrap.wrap(out[x] + ","))) + +Note that the script has a bug in that some keys apply to both VM entry +and VM exit controls ("load IA32_PERF_GLOBAL_CTRL", "load IA32_EFER", +"load IA32_PAT". Those have to be fixed by hand. + +Reviewed-by: Eduardo Habkost +Signed-off-by: Paolo Bonzini +(cherry picked from commit 0723cc8a5558c94388db75ae1f4991314914edd3) + +RHEL: no Denverton and Snowridge +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 617 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 617 insertions(+) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 9074a2e..36c9252 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -1689,6 +1689,34 @@ static CPUCaches epyc_cache_info = { + }, + }; + ++/* The following VMX features are not supported by KVM and are left out in the ++ * CPU definitions: ++ * ++ * Dual-monitor support (all processors) ++ * Entry to SMM ++ * Deactivate dual-monitor treatment ++ * Number of CR3-target values ++ * Shutdown activity state ++ * Wait-for-SIPI activity state ++ * PAUSE-loop exiting (Westmere and newer) ++ * EPT-violation #VE (Broadwell and newer) ++ * Inject event with insn length=0 (Skylake and newer) ++ * Conceal non-root operation from PT ++ * Conceal VM exits from PT ++ * Conceal VM entries from PT ++ * Enable ENCLS exiting ++ * Mode-based execute control (XS/XU) ++ s TSC scaling (Skylake Server and newer) ++ * GPA translation for PT (IceLake and newer) ++ * User wait and pause ++ * ENCLV exiting ++ * Load IA32_RTIT_CTL ++ * Clear IA32_RTIT_CTL ++ * Advanced VM-exit information for EPT violations ++ * Sub-page write permissions ++ * PT in VMX operation ++ */ ++ + static X86CPUDefinition builtin_x86_defs[] = { + { + /* qemu64 is the default CPU model for all *-rhel7.* machine-types. +@@ -1769,6 +1797,24 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX, + .features[FEAT_8000_0001_ECX] = + CPUID_EXT3_LAHF_LM, ++ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS, ++ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE, ++ .features[FEAT_VMX_EXIT_CTLS] = VMX_VM_EXIT_ACK_INTR_ON_EXIT, ++ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT, ++ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | ++ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS, ++ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | ++ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | ++ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | ++ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | ++ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | ++ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | ++ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | ++ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | ++ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | ++ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, ++ .features[FEAT_VMX_SECONDARY_CTLS] = ++ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES, + .xlevel = 0x80000008, + .model_id = "Intel(R) Core(TM)2 Duo CPU T7700 @ 2.40GHz", + }, +@@ -1796,6 +1842,20 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_EXT3_OSVW, CPUID_EXT3_IBS, CPUID_EXT3_SVM */ + .features[FEAT_8000_0001_ECX] = + 0, ++ /* VMX features from Cedar Mill/Prescott */ ++ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE, ++ .features[FEAT_VMX_EXIT_CTLS] = VMX_VM_EXIT_ACK_INTR_ON_EXIT, ++ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT, ++ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | ++ VMX_PIN_BASED_NMI_EXITING, ++ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | ++ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | ++ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | ++ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | ++ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | ++ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | ++ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | ++ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING, + .xlevel = 0x80000008, + .model_id = "Common KVM processor" + }, +@@ -1827,6 +1887,19 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_EXT_SSE3, + .features[FEAT_8000_0001_ECX] = + 0, ++ /* VMX features from Yonah */ ++ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE, ++ .features[FEAT_VMX_EXIT_CTLS] = VMX_VM_EXIT_ACK_INTR_ON_EXIT, ++ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT, ++ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | ++ VMX_PIN_BASED_NMI_EXITING, ++ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | ++ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | ++ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | ++ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | ++ VMX_CPU_BASED_MOV_DR_EXITING | VMX_CPU_BASED_UNCOND_IO_EXITING | ++ VMX_CPU_BASED_USE_IO_BITMAPS | VMX_CPU_BASED_MONITOR_EXITING | ++ VMX_CPU_BASED_PAUSE_EXITING | VMX_CPU_BASED_USE_MSR_BITMAPS, + .xlevel = 0x80000008, + .model_id = "Common 32-bit KVM processor" + }, +@@ -1848,6 +1921,18 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_EXT_SSE3 | CPUID_EXT_MONITOR, + .features[FEAT_8000_0001_EDX] = + CPUID_EXT2_NX, ++ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE, ++ .features[FEAT_VMX_EXIT_CTLS] = VMX_VM_EXIT_ACK_INTR_ON_EXIT, ++ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT, ++ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | ++ VMX_PIN_BASED_NMI_EXITING, ++ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | ++ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | ++ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | ++ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | ++ VMX_CPU_BASED_MOV_DR_EXITING | VMX_CPU_BASED_UNCOND_IO_EXITING | ++ VMX_CPU_BASED_USE_IO_BITMAPS | VMX_CPU_BASED_MONITOR_EXITING | ++ VMX_CPU_BASED_PAUSE_EXITING | VMX_CPU_BASED_USE_MSR_BITMAPS, + .xlevel = 0x80000008, + .model_id = "Genuine Intel(R) CPU T2600 @ 2.16GHz", + }, +@@ -1977,6 +2062,24 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_EXT2_LM | CPUID_EXT2_NX | CPUID_EXT2_SYSCALL, + .features[FEAT_8000_0001_ECX] = + CPUID_EXT3_LAHF_LM, ++ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS, ++ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE, ++ .features[FEAT_VMX_EXIT_CTLS] = VMX_VM_EXIT_ACK_INTR_ON_EXIT, ++ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT, ++ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | ++ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS, ++ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | ++ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | ++ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | ++ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | ++ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | ++ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | ++ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | ++ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | ++ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | ++ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, ++ .features[FEAT_VMX_SECONDARY_CTLS] = ++ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES, + .xlevel = 0x80000008, + .model_id = "Intel Celeron_4x0 (Conroe/Merom Class Core 2)", + }, +@@ -2000,6 +2103,27 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_EXT2_LM | CPUID_EXT2_NX | CPUID_EXT2_SYSCALL, + .features[FEAT_8000_0001_ECX] = + CPUID_EXT3_LAHF_LM, ++ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS, ++ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | ++ VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL, ++ .features[FEAT_VMX_EXIT_CTLS] = VMX_VM_EXIT_ACK_INTR_ON_EXIT | ++ VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL, ++ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT, ++ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | ++ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS, ++ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | ++ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | ++ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | ++ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | ++ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | ++ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | ++ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | ++ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | ++ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | ++ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, ++ .features[FEAT_VMX_SECONDARY_CTLS] = ++ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | ++ VMX_SECONDARY_EXEC_WBINVD_EXITING, + .xlevel = 0x80000008, + .model_id = "Intel Core 2 Duo P9xxx (Penryn Class Core 2)", + }, +@@ -2023,6 +2147,46 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX, + .features[FEAT_8000_0001_ECX] = + CPUID_EXT3_LAHF_LM, ++ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS | ++ MSR_VMX_BASIC_TRUE_CTLS, ++ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | ++ VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VMX_VM_ENTRY_LOAD_IA32_PAT | ++ VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_LOAD_IA32_EFER, ++ .features[FEAT_VMX_EPT_VPID_CAPS] = MSR_VMX_EPT_EXECONLY | ++ MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | ++ MSR_VMX_EPT_1GB | MSR_VMX_EPT_INVEPT | ++ MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | MSR_VMX_EPT_INVVPID_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS, ++ .features[FEAT_VMX_EXIT_CTLS] = ++ VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | ++ VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | ++ VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_LOAD_IA32_EFER | ++ VMX_VM_EXIT_SAVE_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | ++ VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, ++ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT, ++ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | ++ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS | ++ VMX_PIN_BASED_VMX_PREEMPTION_TIMER, ++ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | ++ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | ++ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | ++ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | ++ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | ++ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | ++ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | ++ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | ++ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | ++ VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | ++ VMX_CPU_BASED_MONITOR_TRAP_FLAG | ++ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, ++ .features[FEAT_VMX_SECONDARY_CTLS] = ++ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | ++ VMX_SECONDARY_EXEC_WBINVD_EXITING | VMX_SECONDARY_EXEC_ENABLE_EPT | ++ VMX_SECONDARY_EXEC_DESC | VMX_SECONDARY_EXEC_RDTSCP | ++ VMX_SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | ++ VMX_SECONDARY_EXEC_ENABLE_VPID, + .xlevel = 0x80000008, + .model_id = "Intel Core i7 9xx (Nehalem Class Core i7)", + }, +@@ -2074,6 +2238,47 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_EXT3_LAHF_LM, + .features[FEAT_6_EAX] = + CPUID_6_EAX_ARAT, ++ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS | ++ MSR_VMX_BASIC_TRUE_CTLS, ++ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | ++ VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VMX_VM_ENTRY_LOAD_IA32_PAT | ++ VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_LOAD_IA32_EFER, ++ .features[FEAT_VMX_EPT_VPID_CAPS] = MSR_VMX_EPT_EXECONLY | ++ MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | ++ MSR_VMX_EPT_1GB | MSR_VMX_EPT_INVEPT | ++ MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | MSR_VMX_EPT_INVVPID_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS, ++ .features[FEAT_VMX_EXIT_CTLS] = ++ VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | ++ VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | ++ VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_LOAD_IA32_EFER | ++ VMX_VM_EXIT_SAVE_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | ++ VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, ++ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT | ++ MSR_VMX_MISC_STORE_LMA, ++ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | ++ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS | ++ VMX_PIN_BASED_VMX_PREEMPTION_TIMER, ++ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | ++ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | ++ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | ++ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | ++ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | ++ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | ++ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | ++ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | ++ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | ++ VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | ++ VMX_CPU_BASED_MONITOR_TRAP_FLAG | ++ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, ++ .features[FEAT_VMX_SECONDARY_CTLS] = ++ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | ++ VMX_SECONDARY_EXEC_WBINVD_EXITING | VMX_SECONDARY_EXEC_ENABLE_EPT | ++ VMX_SECONDARY_EXEC_DESC | VMX_SECONDARY_EXEC_RDTSCP | ++ VMX_SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | ++ VMX_SECONDARY_EXEC_ENABLE_VPID | VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST, + .xlevel = 0x80000008, + .model_id = "Westmere E56xx/L56xx/X56xx (Nehalem-C)", + }, +@@ -2133,6 +2338,47 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_XSAVE_XSAVEOPT, + .features[FEAT_6_EAX] = + CPUID_6_EAX_ARAT, ++ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS | ++ MSR_VMX_BASIC_TRUE_CTLS, ++ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | ++ VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VMX_VM_ENTRY_LOAD_IA32_PAT | ++ VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_LOAD_IA32_EFER, ++ .features[FEAT_VMX_EPT_VPID_CAPS] = MSR_VMX_EPT_EXECONLY | ++ MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | ++ MSR_VMX_EPT_1GB | MSR_VMX_EPT_INVEPT | ++ MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | MSR_VMX_EPT_INVVPID_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS, ++ .features[FEAT_VMX_EXIT_CTLS] = ++ VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | ++ VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | ++ VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_LOAD_IA32_EFER | ++ VMX_VM_EXIT_SAVE_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | ++ VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, ++ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT | ++ MSR_VMX_MISC_STORE_LMA, ++ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | ++ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS | ++ VMX_PIN_BASED_VMX_PREEMPTION_TIMER, ++ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | ++ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | ++ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | ++ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | ++ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | ++ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | ++ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | ++ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | ++ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | ++ VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | ++ VMX_CPU_BASED_MONITOR_TRAP_FLAG | ++ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, ++ .features[FEAT_VMX_SECONDARY_CTLS] = ++ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | ++ VMX_SECONDARY_EXEC_WBINVD_EXITING | VMX_SECONDARY_EXEC_ENABLE_EPT | ++ VMX_SECONDARY_EXEC_DESC | VMX_SECONDARY_EXEC_RDTSCP | ++ VMX_SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | ++ VMX_SECONDARY_EXEC_ENABLE_VPID | VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST, + .xlevel = 0x80000008, + .model_id = "Intel Xeon E312xx (Sandy Bridge)", + }, +@@ -2200,6 +2446,50 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_XSAVE_XSAVEOPT, + .features[FEAT_6_EAX] = + CPUID_6_EAX_ARAT, ++ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS | ++ MSR_VMX_BASIC_TRUE_CTLS, ++ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | ++ VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VMX_VM_ENTRY_LOAD_IA32_PAT | ++ VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_LOAD_IA32_EFER, ++ .features[FEAT_VMX_EPT_VPID_CAPS] = MSR_VMX_EPT_EXECONLY | ++ MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | ++ MSR_VMX_EPT_1GB | MSR_VMX_EPT_INVEPT | ++ MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | MSR_VMX_EPT_INVVPID_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS, ++ .features[FEAT_VMX_EXIT_CTLS] = ++ VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | ++ VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | ++ VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_LOAD_IA32_EFER | ++ VMX_VM_EXIT_SAVE_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | ++ VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, ++ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT | ++ MSR_VMX_MISC_STORE_LMA, ++ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | ++ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS | ++ VMX_PIN_BASED_VMX_PREEMPTION_TIMER | VMX_PIN_BASED_POSTED_INTR, ++ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | ++ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | ++ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | ++ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | ++ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | ++ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | ++ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | ++ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | ++ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | ++ VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | ++ VMX_CPU_BASED_MONITOR_TRAP_FLAG | ++ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, ++ .features[FEAT_VMX_SECONDARY_CTLS] = ++ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | ++ VMX_SECONDARY_EXEC_WBINVD_EXITING | VMX_SECONDARY_EXEC_ENABLE_EPT | ++ VMX_SECONDARY_EXEC_DESC | VMX_SECONDARY_EXEC_RDTSCP | ++ VMX_SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | ++ VMX_SECONDARY_EXEC_ENABLE_VPID | VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST | ++ VMX_SECONDARY_EXEC_APIC_REGISTER_VIRT | ++ VMX_SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY | ++ VMX_SECONDARY_EXEC_RDRAND_EXITING, + .xlevel = 0x80000008, + .model_id = "Intel Xeon E3-12xx v2 (Ivy Bridge)", + }, +@@ -2347,6 +2637,52 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_XSAVE_XSAVEOPT, + .features[FEAT_6_EAX] = + CPUID_6_EAX_ARAT, ++ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS | ++ MSR_VMX_BASIC_TRUE_CTLS, ++ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | ++ VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VMX_VM_ENTRY_LOAD_IA32_PAT | ++ VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_LOAD_IA32_EFER, ++ .features[FEAT_VMX_EPT_VPID_CAPS] = MSR_VMX_EPT_EXECONLY | ++ MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | ++ MSR_VMX_EPT_1GB | MSR_VMX_EPT_INVEPT | ++ MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | MSR_VMX_EPT_INVVPID_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS | MSR_VMX_EPT_AD_BITS, ++ .features[FEAT_VMX_EXIT_CTLS] = ++ VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | ++ VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | ++ VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_LOAD_IA32_EFER | ++ VMX_VM_EXIT_SAVE_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | ++ VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, ++ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT | ++ MSR_VMX_MISC_STORE_LMA | MSR_VMX_MISC_VMWRITE_VMEXIT, ++ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | ++ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS | ++ VMX_PIN_BASED_VMX_PREEMPTION_TIMER | VMX_PIN_BASED_POSTED_INTR, ++ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | ++ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | ++ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | ++ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | ++ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | ++ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | ++ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | ++ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | ++ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | ++ VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | ++ VMX_CPU_BASED_MONITOR_TRAP_FLAG | ++ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, ++ .features[FEAT_VMX_SECONDARY_CTLS] = ++ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | ++ VMX_SECONDARY_EXEC_WBINVD_EXITING | VMX_SECONDARY_EXEC_ENABLE_EPT | ++ VMX_SECONDARY_EXEC_DESC | VMX_SECONDARY_EXEC_RDTSCP | ++ VMX_SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | ++ VMX_SECONDARY_EXEC_ENABLE_VPID | VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST | ++ VMX_SECONDARY_EXEC_APIC_REGISTER_VIRT | ++ VMX_SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY | ++ VMX_SECONDARY_EXEC_RDRAND_EXITING | VMX_SECONDARY_EXEC_ENABLE_INVPCID | ++ VMX_SECONDARY_EXEC_ENABLE_VMFUNC | VMX_SECONDARY_EXEC_SHADOW_VMCS, ++ .features[FEAT_VMX_VMFUNC] = MSR_VMX_VMFUNC_EPT_SWITCHING, + .xlevel = 0x80000008, + .model_id = "Intel Core Processor (Haswell)", + }, +@@ -2502,6 +2838,53 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_XSAVE_XSAVEOPT, + .features[FEAT_6_EAX] = + CPUID_6_EAX_ARAT, ++ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS | ++ MSR_VMX_BASIC_TRUE_CTLS, ++ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | ++ VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VMX_VM_ENTRY_LOAD_IA32_PAT | ++ VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_LOAD_IA32_EFER, ++ .features[FEAT_VMX_EPT_VPID_CAPS] = MSR_VMX_EPT_EXECONLY | ++ MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | ++ MSR_VMX_EPT_1GB | MSR_VMX_EPT_INVEPT | ++ MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | MSR_VMX_EPT_INVVPID_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS | MSR_VMX_EPT_AD_BITS, ++ .features[FEAT_VMX_EXIT_CTLS] = ++ VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | ++ VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | ++ VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_LOAD_IA32_EFER | ++ VMX_VM_EXIT_SAVE_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | ++ VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, ++ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT | ++ MSR_VMX_MISC_STORE_LMA | MSR_VMX_MISC_VMWRITE_VMEXIT, ++ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | ++ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS | ++ VMX_PIN_BASED_VMX_PREEMPTION_TIMER | VMX_PIN_BASED_POSTED_INTR, ++ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | ++ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | ++ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | ++ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | ++ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | ++ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | ++ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | ++ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | ++ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | ++ VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | ++ VMX_CPU_BASED_MONITOR_TRAP_FLAG | ++ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, ++ .features[FEAT_VMX_SECONDARY_CTLS] = ++ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | ++ VMX_SECONDARY_EXEC_WBINVD_EXITING | VMX_SECONDARY_EXEC_ENABLE_EPT | ++ VMX_SECONDARY_EXEC_DESC | VMX_SECONDARY_EXEC_RDTSCP | ++ VMX_SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | ++ VMX_SECONDARY_EXEC_ENABLE_VPID | VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST | ++ VMX_SECONDARY_EXEC_APIC_REGISTER_VIRT | ++ VMX_SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY | ++ VMX_SECONDARY_EXEC_RDRAND_EXITING | VMX_SECONDARY_EXEC_ENABLE_INVPCID | ++ VMX_SECONDARY_EXEC_ENABLE_VMFUNC | VMX_SECONDARY_EXEC_SHADOW_VMCS | ++ VMX_SECONDARY_EXEC_RDSEED_EXITING | VMX_SECONDARY_EXEC_ENABLE_PML, ++ .features[FEAT_VMX_VMFUNC] = MSR_VMX_VMFUNC_EPT_SWITCHING, + .xlevel = 0x80000008, + .model_id = "Intel Core Processor (Broadwell)", + }, +@@ -2587,6 +2970,51 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_XSAVE_XGETBV1, + .features[FEAT_6_EAX] = + CPUID_6_EAX_ARAT, ++ /* Missing: Mode-based execute control (XS/XU), processor tracing, TSC scaling */ ++ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS | ++ MSR_VMX_BASIC_TRUE_CTLS, ++ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | ++ VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VMX_VM_ENTRY_LOAD_IA32_PAT | ++ VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_LOAD_IA32_EFER, ++ .features[FEAT_VMX_EPT_VPID_CAPS] = MSR_VMX_EPT_EXECONLY | ++ MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | ++ MSR_VMX_EPT_1GB | MSR_VMX_EPT_INVEPT | ++ MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | MSR_VMX_EPT_INVVPID_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS | MSR_VMX_EPT_AD_BITS, ++ .features[FEAT_VMX_EXIT_CTLS] = ++ VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | ++ VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | ++ VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_LOAD_IA32_EFER | ++ VMX_VM_EXIT_SAVE_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | ++ VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, ++ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT | ++ MSR_VMX_MISC_STORE_LMA | MSR_VMX_MISC_VMWRITE_VMEXIT, ++ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | ++ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS | ++ VMX_PIN_BASED_VMX_PREEMPTION_TIMER, ++ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | ++ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | ++ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | ++ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | ++ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | ++ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | ++ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | ++ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | ++ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | ++ VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | ++ VMX_CPU_BASED_MONITOR_TRAP_FLAG | ++ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, ++ .features[FEAT_VMX_SECONDARY_CTLS] = ++ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | ++ VMX_SECONDARY_EXEC_WBINVD_EXITING | VMX_SECONDARY_EXEC_ENABLE_EPT | ++ VMX_SECONDARY_EXEC_DESC | VMX_SECONDARY_EXEC_RDTSCP | ++ VMX_SECONDARY_EXEC_ENABLE_VPID | VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST | ++ VMX_SECONDARY_EXEC_RDRAND_EXITING | VMX_SECONDARY_EXEC_ENABLE_INVPCID | ++ VMX_SECONDARY_EXEC_ENABLE_VMFUNC | VMX_SECONDARY_EXEC_SHADOW_VMCS | ++ VMX_SECONDARY_EXEC_RDSEED_EXITING | VMX_SECONDARY_EXEC_ENABLE_PML, ++ .features[FEAT_VMX_VMFUNC] = MSR_VMX_VMFUNC_EPT_SWITCHING, + .xlevel = 0x80000008, + .model_id = "Intel Core Processor (Skylake)", + }, +@@ -2682,6 +3110,54 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_XSAVE_XGETBV1, + .features[FEAT_6_EAX] = + CPUID_6_EAX_ARAT, ++ /* Missing: Mode-based execute control (XS/XU), processor tracing, TSC scaling */ ++ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS | ++ MSR_VMX_BASIC_TRUE_CTLS, ++ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | ++ VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VMX_VM_ENTRY_LOAD_IA32_PAT | ++ VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_LOAD_IA32_EFER, ++ .features[FEAT_VMX_EPT_VPID_CAPS] = MSR_VMX_EPT_EXECONLY | ++ MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | ++ MSR_VMX_EPT_1GB | MSR_VMX_EPT_INVEPT | ++ MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | MSR_VMX_EPT_INVVPID_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS | MSR_VMX_EPT_AD_BITS, ++ .features[FEAT_VMX_EXIT_CTLS] = ++ VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | ++ VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | ++ VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_LOAD_IA32_EFER | ++ VMX_VM_EXIT_SAVE_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | ++ VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, ++ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT | ++ MSR_VMX_MISC_STORE_LMA | MSR_VMX_MISC_VMWRITE_VMEXIT, ++ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | ++ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS | ++ VMX_PIN_BASED_VMX_PREEMPTION_TIMER | VMX_PIN_BASED_POSTED_INTR, ++ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | ++ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | ++ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | ++ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | ++ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | ++ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | ++ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | ++ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | ++ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | ++ VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | ++ VMX_CPU_BASED_MONITOR_TRAP_FLAG | ++ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, ++ .features[FEAT_VMX_SECONDARY_CTLS] = ++ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | ++ VMX_SECONDARY_EXEC_WBINVD_EXITING | VMX_SECONDARY_EXEC_ENABLE_EPT | ++ VMX_SECONDARY_EXEC_DESC | VMX_SECONDARY_EXEC_RDTSCP | ++ VMX_SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | ++ VMX_SECONDARY_EXEC_ENABLE_VPID | VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST | ++ VMX_SECONDARY_EXEC_APIC_REGISTER_VIRT | ++ VMX_SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY | ++ VMX_SECONDARY_EXEC_RDRAND_EXITING | VMX_SECONDARY_EXEC_ENABLE_INVPCID | ++ VMX_SECONDARY_EXEC_ENABLE_VMFUNC | VMX_SECONDARY_EXEC_SHADOW_VMCS | ++ VMX_SECONDARY_EXEC_RDSEED_EXITING | VMX_SECONDARY_EXEC_ENABLE_PML, ++ .features[FEAT_VMX_VMFUNC] = MSR_VMX_VMFUNC_EPT_SWITCHING, + .xlevel = 0x80000008, + .model_id = "Intel Xeon Processor (Skylake)", + }, +@@ -2785,6 +3261,54 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_XSAVE_XGETBV1, + .features[FEAT_6_EAX] = + CPUID_6_EAX_ARAT, ++ /* Missing: Mode-based execute control (XS/XU), processor tracing, TSC scaling */ ++ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS | ++ MSR_VMX_BASIC_TRUE_CTLS, ++ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | ++ VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VMX_VM_ENTRY_LOAD_IA32_PAT | ++ VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_LOAD_IA32_EFER, ++ .features[FEAT_VMX_EPT_VPID_CAPS] = MSR_VMX_EPT_EXECONLY | ++ MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | ++ MSR_VMX_EPT_1GB | MSR_VMX_EPT_INVEPT | ++ MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | MSR_VMX_EPT_INVVPID_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS | MSR_VMX_EPT_AD_BITS, ++ .features[FEAT_VMX_EXIT_CTLS] = ++ VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | ++ VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | ++ VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_LOAD_IA32_EFER | ++ VMX_VM_EXIT_SAVE_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | ++ VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, ++ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT | ++ MSR_VMX_MISC_STORE_LMA | MSR_VMX_MISC_VMWRITE_VMEXIT, ++ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | ++ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS | ++ VMX_PIN_BASED_VMX_PREEMPTION_TIMER | VMX_PIN_BASED_POSTED_INTR, ++ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | ++ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | ++ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | ++ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | ++ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | ++ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | ++ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | ++ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | ++ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | ++ VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | ++ VMX_CPU_BASED_MONITOR_TRAP_FLAG | ++ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, ++ .features[FEAT_VMX_SECONDARY_CTLS] = ++ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | ++ VMX_SECONDARY_EXEC_WBINVD_EXITING | VMX_SECONDARY_EXEC_ENABLE_EPT | ++ VMX_SECONDARY_EXEC_DESC | VMX_SECONDARY_EXEC_RDTSCP | ++ VMX_SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | ++ VMX_SECONDARY_EXEC_ENABLE_VPID | VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST | ++ VMX_SECONDARY_EXEC_APIC_REGISTER_VIRT | ++ VMX_SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY | ++ VMX_SECONDARY_EXEC_RDRAND_EXITING | VMX_SECONDARY_EXEC_ENABLE_INVPCID | ++ VMX_SECONDARY_EXEC_ENABLE_VMFUNC | VMX_SECONDARY_EXEC_SHADOW_VMCS | ++ VMX_SECONDARY_EXEC_RDSEED_EXITING | VMX_SECONDARY_EXEC_ENABLE_PML, ++ .features[FEAT_VMX_VMFUNC] = MSR_VMX_VMFUNC_EPT_SWITCHING, + .xlevel = 0x80000008, + .model_id = "Intel Xeon Processor (Cascadelake)", + }, +@@ -2840,6 +3364,51 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_XSAVE_XGETBV1, + .features[FEAT_6_EAX] = + CPUID_6_EAX_ARAT, ++ /* Missing: Mode-based execute control (XS/XU), processor tracing, TSC scaling */ ++ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS | ++ MSR_VMX_BASIC_TRUE_CTLS, ++ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | ++ VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VMX_VM_ENTRY_LOAD_IA32_PAT | ++ VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_LOAD_IA32_EFER, ++ .features[FEAT_VMX_EPT_VPID_CAPS] = MSR_VMX_EPT_EXECONLY | ++ MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | ++ MSR_VMX_EPT_1GB | MSR_VMX_EPT_INVEPT | ++ MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | MSR_VMX_EPT_INVVPID_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS | MSR_VMX_EPT_AD_BITS, ++ .features[FEAT_VMX_EXIT_CTLS] = ++ VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | ++ VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | ++ VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_LOAD_IA32_EFER | ++ VMX_VM_EXIT_SAVE_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | ++ VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, ++ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT | ++ MSR_VMX_MISC_STORE_LMA | MSR_VMX_MISC_VMWRITE_VMEXIT, ++ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | ++ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS | ++ VMX_PIN_BASED_VMX_PREEMPTION_TIMER, ++ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | ++ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | ++ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | ++ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | ++ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | ++ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | ++ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | ++ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | ++ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | ++ VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | ++ VMX_CPU_BASED_MONITOR_TRAP_FLAG | ++ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, ++ .features[FEAT_VMX_SECONDARY_CTLS] = ++ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | ++ VMX_SECONDARY_EXEC_WBINVD_EXITING | VMX_SECONDARY_EXEC_ENABLE_EPT | ++ VMX_SECONDARY_EXEC_DESC | VMX_SECONDARY_EXEC_RDTSCP | ++ VMX_SECONDARY_EXEC_ENABLE_VPID | VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST | ++ VMX_SECONDARY_EXEC_RDRAND_EXITING | VMX_SECONDARY_EXEC_ENABLE_INVPCID | ++ VMX_SECONDARY_EXEC_ENABLE_VMFUNC | VMX_SECONDARY_EXEC_SHADOW_VMCS | ++ VMX_SECONDARY_EXEC_RDSEED_EXITING | VMX_SECONDARY_EXEC_ENABLE_PML, ++ .features[FEAT_VMX_VMFUNC] = MSR_VMX_VMFUNC_EPT_SWITCHING, + .xlevel = 0x80000008, + .model_id = "Intel Core Processor (Icelake)", + }, +@@ -2898,6 +3467,54 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_XSAVE_XGETBV1, + .features[FEAT_6_EAX] = + CPUID_6_EAX_ARAT, ++ /* Missing: Mode-based execute control (XS/XU), processor tracing, TSC scaling */ ++ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS | ++ MSR_VMX_BASIC_TRUE_CTLS, ++ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | ++ VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VMX_VM_ENTRY_LOAD_IA32_PAT | ++ VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_LOAD_IA32_EFER, ++ .features[FEAT_VMX_EPT_VPID_CAPS] = MSR_VMX_EPT_EXECONLY | ++ MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | ++ MSR_VMX_EPT_1GB | MSR_VMX_EPT_INVEPT | ++ MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | MSR_VMX_EPT_INVVPID_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS | MSR_VMX_EPT_AD_BITS, ++ .features[FEAT_VMX_EXIT_CTLS] = ++ VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | ++ VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | ++ VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_LOAD_IA32_EFER | ++ VMX_VM_EXIT_SAVE_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | ++ VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, ++ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT | ++ MSR_VMX_MISC_STORE_LMA | MSR_VMX_MISC_VMWRITE_VMEXIT, ++ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | ++ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS | ++ VMX_PIN_BASED_VMX_PREEMPTION_TIMER | VMX_PIN_BASED_POSTED_INTR, ++ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | ++ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | ++ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | ++ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | ++ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | ++ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | ++ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | ++ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | ++ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | ++ VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | ++ VMX_CPU_BASED_MONITOR_TRAP_FLAG | ++ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, ++ .features[FEAT_VMX_SECONDARY_CTLS] = ++ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | ++ VMX_SECONDARY_EXEC_WBINVD_EXITING | VMX_SECONDARY_EXEC_ENABLE_EPT | ++ VMX_SECONDARY_EXEC_DESC | VMX_SECONDARY_EXEC_RDTSCP | ++ VMX_SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | ++ VMX_SECONDARY_EXEC_ENABLE_VPID | VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST | ++ VMX_SECONDARY_EXEC_APIC_REGISTER_VIRT | ++ VMX_SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY | ++ VMX_SECONDARY_EXEC_RDRAND_EXITING | VMX_SECONDARY_EXEC_ENABLE_INVPCID | ++ VMX_SECONDARY_EXEC_ENABLE_VMFUNC | VMX_SECONDARY_EXEC_SHADOW_VMCS | ++ VMX_SECONDARY_EXEC_RDSEED_EXITING | VMX_SECONDARY_EXEC_ENABLE_PML, ++ .features[FEAT_VMX_VMFUNC] = MSR_VMX_VMFUNC_EPT_SWITCHING, + .xlevel = 0x80000008, + .model_id = "Intel Xeon Processor (Icelake)", + }, +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-add-VMX-features.patch b/SOURCES/kvm-target-i386-add-VMX-features.patch new file mode 100644 index 0000000..7bbb35a --- /dev/null +++ b/SOURCES/kvm-target-i386-add-VMX-features.patch @@ -0,0 +1,503 @@ +From 88ab13cec526a16cb02bf1af51bdd33230308d36 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Fri, 22 Nov 2019 11:53:44 +0000 +Subject: [PATCH 11/16] target/i386: add VMX features + +RH-Author: Paolo Bonzini +Message-id: <20191122115348.25000-12-pbonzini@redhat.com> +Patchwork-id: 92608 +O-Subject: [RHEL8.2/rhel qemu-kvm PATCH 11/15] target/i386: add VMX features +Bugzilla: 1689270 +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Maxim Levitsky + +Add code to convert the VMX feature words back into MSR values, +allowing the user to enable/disable VMX features as they wish. The same +infrastructure enables support for limiting VMX features in named +CPU models. + +Signed-off-by: Paolo Bonzini +(cherry picked from commit 20a78b02d31534ae478779c2f2816c273601e869) +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 225 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ + target/i386/cpu.h | 9 +++ + target/i386/kvm.c | 162 ++++++++++++++++++++++++++++++++++++++- + 3 files changed, 394 insertions(+), 2 deletions(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 3e77830..9074a2e 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -1171,6 +1171,163 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + .index = MSR_IA32_CORE_CAPABILITY, + }, + }, ++ ++ [FEAT_VMX_PROCBASED_CTLS] = { ++ .type = MSR_FEATURE_WORD, ++ .feat_names = { ++ NULL, NULL, "vmx-vintr-pending", "vmx-tsc-offset", ++ NULL, NULL, NULL, "vmx-hlt-exit", ++ NULL, "vmx-invlpg-exit", "vmx-mwait-exit", "vmx-rdpmc-exit", ++ "vmx-rdtsc-exit", NULL, NULL, "vmx-cr3-load-noexit", ++ "vmx-cr3-store-noexit", NULL, NULL, "vmx-cr8-load-exit", ++ "vmx-cr8-store-exit", "vmx-flexpriority", "vmx-vnmi-pending", "vmx-movdr-exit", ++ "vmx-io-exit", "vmx-io-bitmap", NULL, "vmx-mtf", ++ "vmx-msr-bitmap", "vmx-monitor-exit", "vmx-pause-exit", "vmx-secondary-ctls", ++ }, ++ .msr = { ++ .index = MSR_IA32_VMX_TRUE_PROCBASED_CTLS, ++ } ++ }, ++ ++ [FEAT_VMX_SECONDARY_CTLS] = { ++ .type = MSR_FEATURE_WORD, ++ .feat_names = { ++ "vmx-apicv-xapic", "vmx-ept", "vmx-desc-exit", "vmx-rdtscp-exit", ++ "vmx-apicv-x2apic", "vmx-vpid", "vmx-wbinvd-exit", "vmx-unrestricted-guest", ++ "vmx-apicv-register", "vmx-apicv-vid", "vmx-ple", "vmx-rdrand-exit", ++ "vmx-invpcid-exit", "vmx-vmfunc", "vmx-shadow-vmcs", "vmx-encls-exit", ++ "vmx-rdseed-exit", "vmx-pml", NULL, NULL, ++ "vmx-xsaves", NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ }, ++ .msr = { ++ .index = MSR_IA32_VMX_PROCBASED_CTLS2, ++ } ++ }, ++ ++ [FEAT_VMX_PINBASED_CTLS] = { ++ .type = MSR_FEATURE_WORD, ++ .feat_names = { ++ "vmx-intr-exit", NULL, NULL, "vmx-nmi-exit", ++ NULL, "vmx-vnmi", "vmx-preemption-timer", "vmx-posted-intr", ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ }, ++ .msr = { ++ .index = MSR_IA32_VMX_TRUE_PINBASED_CTLS, ++ } ++ }, ++ ++ [FEAT_VMX_EXIT_CTLS] = { ++ .type = MSR_FEATURE_WORD, ++ /* ++ * VMX_VM_EXIT_HOST_ADDR_SPACE_SIZE is copied from ++ * the LM CPUID bit. ++ */ ++ .feat_names = { ++ NULL, NULL, "vmx-exit-nosave-debugctl", NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, NULL /* vmx-exit-host-addr-space-size */, NULL, NULL, ++ "vmx-exit-load-perf-global-ctrl", NULL, NULL, "vmx-exit-ack-intr", ++ NULL, NULL, "vmx-exit-save-pat", "vmx-exit-load-pat", ++ "vmx-exit-save-efer", "vmx-exit-load-efer", ++ "vmx-exit-save-preemption-timer", "vmx-exit-clear-bndcfgs", ++ NULL, "vmx-exit-clear-rtit-ctl", NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ }, ++ .msr = { ++ .index = MSR_IA32_VMX_TRUE_EXIT_CTLS, ++ } ++ }, ++ ++ [FEAT_VMX_ENTRY_CTLS] = { ++ .type = MSR_FEATURE_WORD, ++ .feat_names = { ++ NULL, NULL, "vmx-entry-noload-debugctl", NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, "vmx-entry-ia32e-mode", NULL, NULL, ++ NULL, "vmx-entry-load-perf-global-ctrl", "vmx-entry-load-pat", "vmx-entry-load-efer", ++ "vmx-entry-load-bndcfgs", NULL, "vmx-entry-load-rtit-ctl", NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ }, ++ .msr = { ++ .index = MSR_IA32_VMX_TRUE_ENTRY_CTLS, ++ } ++ }, ++ ++ [FEAT_VMX_MISC] = { ++ .type = MSR_FEATURE_WORD, ++ .feat_names = { ++ NULL, NULL, NULL, NULL, ++ NULL, "vmx-store-lma", "vmx-activity-hlt", "vmx-activity-shutdown", ++ "vmx-activity-wait-sipi", NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, "vmx-vmwrite-vmexit-fields", "vmx-zero-len-inject", NULL, ++ }, ++ .msr = { ++ .index = MSR_IA32_VMX_MISC, ++ } ++ }, ++ ++ [FEAT_VMX_EPT_VPID_CAPS] = { ++ .type = MSR_FEATURE_WORD, ++ .feat_names = { ++ "vmx-ept-execonly", NULL, NULL, NULL, ++ NULL, NULL, "vmx-page-walk-4", "vmx-page-walk-5", ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ "vmx-ept-2mb", "vmx-ept-1gb", NULL, NULL, ++ "vmx-invept", "vmx-eptad", "vmx-ept-advanced-exitinfo", NULL, ++ NULL, "vmx-invept-single-context", "vmx-invept-all-context", NULL, ++ NULL, NULL, NULL, NULL, ++ "vmx-invvpid", NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ "vmx-invvpid-single-addr", "vmx-invept-single-context", ++ "vmx-invvpid-all-context", "vmx-invept-single-context-noglobals", ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ }, ++ .msr = { ++ .index = MSR_IA32_VMX_EPT_VPID_CAP, ++ } ++ }, ++ ++ [FEAT_VMX_BASIC] = { ++ .type = MSR_FEATURE_WORD, ++ .feat_names = { ++ [54] = "vmx-ins-outs", ++ [55] = "vmx-true-ctls", ++ }, ++ .msr = { ++ .index = MSR_IA32_VMX_BASIC, ++ }, ++ /* Just to be safe - we don't support setting the MSEG version field. */ ++ .no_autoenable_flags = MSR_VMX_BASIC_DUAL_MONITOR, ++ }, ++ ++ [FEAT_VMX_VMFUNC] = { ++ .type = MSR_FEATURE_WORD, ++ .feat_names = { ++ [0] = "vmx-eptp-switching", ++ }, ++ .msr = { ++ .index = MSR_IA32_VMX_VMFUNC, ++ } ++ }, ++ + }; + + typedef struct FeatureMask { +@@ -1191,6 +1348,74 @@ static FeatureDep feature_dependencies[] = { + .from = { FEAT_7_0_EDX, CPUID_7_0_EDX_CORE_CAPABILITY }, + .to = { FEAT_CORE_CAPABILITY, ~0ull }, + }, ++ { ++ .from = { FEAT_1_ECX, CPUID_EXT_VMX }, ++ .to = { FEAT_VMX_PROCBASED_CTLS, ~0ull }, ++ }, ++ { ++ .from = { FEAT_1_ECX, CPUID_EXT_VMX }, ++ .to = { FEAT_VMX_PINBASED_CTLS, ~0ull }, ++ }, ++ { ++ .from = { FEAT_1_ECX, CPUID_EXT_VMX }, ++ .to = { FEAT_VMX_EXIT_CTLS, ~0ull }, ++ }, ++ { ++ .from = { FEAT_1_ECX, CPUID_EXT_VMX }, ++ .to = { FEAT_VMX_ENTRY_CTLS, ~0ull }, ++ }, ++ { ++ .from = { FEAT_1_ECX, CPUID_EXT_VMX }, ++ .to = { FEAT_VMX_MISC, ~0ull }, ++ }, ++ { ++ .from = { FEAT_1_ECX, CPUID_EXT_VMX }, ++ .to = { FEAT_VMX_BASIC, ~0ull }, ++ }, ++ { ++ .from = { FEAT_8000_0001_EDX, CPUID_EXT2_LM }, ++ .to = { FEAT_VMX_ENTRY_CTLS, VMX_VM_ENTRY_IA32E_MODE }, ++ }, ++ { ++ .from = { FEAT_VMX_PROCBASED_CTLS, VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS }, ++ .to = { FEAT_VMX_SECONDARY_CTLS, ~0ull }, ++ }, ++ { ++ .from = { FEAT_XSAVE, CPUID_XSAVE_XSAVES }, ++ .to = { FEAT_VMX_SECONDARY_CTLS, VMX_SECONDARY_EXEC_XSAVES }, ++ }, ++ { ++ .from = { FEAT_1_ECX, CPUID_EXT_RDRAND }, ++ .to = { FEAT_VMX_SECONDARY_CTLS, VMX_SECONDARY_EXEC_RDRAND_EXITING }, ++ }, ++ { ++ .from = { FEAT_7_0_EBX, CPUID_7_0_EBX_INVPCID }, ++ .to = { FEAT_VMX_SECONDARY_CTLS, VMX_SECONDARY_EXEC_ENABLE_INVPCID }, ++ }, ++ { ++ .from = { FEAT_7_0_EBX, CPUID_7_0_EBX_RDSEED }, ++ .to = { FEAT_VMX_SECONDARY_CTLS, VMX_SECONDARY_EXEC_RDSEED_EXITING }, ++ }, ++ { ++ .from = { FEAT_8000_0001_EDX, CPUID_EXT2_RDTSCP }, ++ .to = { FEAT_VMX_SECONDARY_CTLS, VMX_SECONDARY_EXEC_RDTSCP }, ++ }, ++ { ++ .from = { FEAT_VMX_SECONDARY_CTLS, VMX_SECONDARY_EXEC_ENABLE_EPT }, ++ .to = { FEAT_VMX_EPT_VPID_CAPS, 0xffffffffull }, ++ }, ++ { ++ .from = { FEAT_VMX_SECONDARY_CTLS, VMX_SECONDARY_EXEC_ENABLE_EPT }, ++ .to = { FEAT_VMX_SECONDARY_CTLS, VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST }, ++ }, ++ { ++ .from = { FEAT_VMX_SECONDARY_CTLS, VMX_SECONDARY_EXEC_ENABLE_VPID }, ++ .to = { FEAT_VMX_EPT_VPID_CAPS, 0xffffffffull << 32 }, ++ }, ++ { ++ .from = { FEAT_VMX_SECONDARY_CTLS, VMX_SECONDARY_EXEC_ENABLE_VMFUNC }, ++ .to = { FEAT_VMX_VMFUNC, ~0ull }, ++ }, + }; + + typedef struct X86RegisterInfo32 { +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index 2d1f247..386e821 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -522,6 +522,15 @@ typedef enum FeatureWord { + FEAT_XSAVE_COMP_HI, /* CPUID[EAX=0xd,ECX=0].EDX */ + FEAT_ARCH_CAPABILITIES, + FEAT_CORE_CAPABILITY, ++ FEAT_VMX_PROCBASED_CTLS, ++ FEAT_VMX_SECONDARY_CTLS, ++ FEAT_VMX_PINBASED_CTLS, ++ FEAT_VMX_EXIT_CTLS, ++ FEAT_VMX_ENTRY_CTLS, ++ FEAT_VMX_MISC, ++ FEAT_VMX_EPT_VPID_CAPS, ++ FEAT_VMX_BASIC, ++ FEAT_VMX_VMFUNC, + FEATURE_WORDS, + } FeatureWord; + +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index 85abd37..512d7d5 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -96,6 +96,7 @@ static bool has_msr_virt_ssbd; + static bool has_msr_smi_count; + static bool has_msr_arch_capabs; + static bool has_msr_core_capabs; ++static bool has_msr_vmx_vmfunc; + + static uint32_t has_architectural_pmu_version; + static uint32_t num_architectural_pmu_gp_counters; +@@ -429,7 +430,8 @@ uint64_t kvm_arch_get_supported_msr_feature(KVMState *s, uint32_t index) + struct kvm_msrs info; + struct kvm_msr_entry entries[1]; + } msr_data; +- uint32_t ret; ++ uint64_t value; ++ uint32_t ret, can_be_one, must_be_one; + + if (kvm_feature_msrs == NULL) { /* Host doesn't support feature MSRs */ + return 0; +@@ -455,7 +457,25 @@ uint64_t kvm_arch_get_supported_msr_feature(KVMState *s, uint32_t index) + exit(1); + } + +- return msr_data.entries[0].data; ++ value = msr_data.entries[0].data; ++ switch (index) { ++ case MSR_IA32_VMX_PROCBASED_CTLS2: ++ case MSR_IA32_VMX_TRUE_PINBASED_CTLS: ++ case MSR_IA32_VMX_TRUE_PROCBASED_CTLS: ++ case MSR_IA32_VMX_TRUE_ENTRY_CTLS: ++ case MSR_IA32_VMX_TRUE_EXIT_CTLS: ++ /* ++ * Return true for bits that can be one, but do not have to be one. ++ * The SDM tells us which bits could have a "must be one" setting, ++ * so we can do the opposite transformation in make_vmx_msr_value. ++ */ ++ must_be_one = (uint32_t)value; ++ can_be_one = (uint32_t)(value >> 32); ++ return can_be_one & ~must_be_one; ++ ++ default: ++ return value; ++ } + } + + +@@ -1430,6 +1450,9 @@ static int kvm_get_supported_msrs(KVMState *s) + case MSR_IA32_CORE_CAPABILITY: + has_msr_core_capabs = true; + break; ++ case MSR_IA32_VMX_VMFUNC: ++ has_msr_vmx_vmfunc = true; ++ break; + } + } + } +@@ -1886,6 +1909,132 @@ static int kvm_put_msr_feature_control(X86CPU *cpu) + return 0; + } + ++static uint64_t make_vmx_msr_value(uint32_t index, uint32_t features) ++{ ++ uint32_t default1, can_be_one, can_be_zero; ++ uint32_t must_be_one; ++ ++ switch (index) { ++ case MSR_IA32_VMX_TRUE_PINBASED_CTLS: ++ default1 = 0x00000016; ++ break; ++ case MSR_IA32_VMX_TRUE_PROCBASED_CTLS: ++ default1 = 0x0401e172; ++ break; ++ case MSR_IA32_VMX_TRUE_ENTRY_CTLS: ++ default1 = 0x000011ff; ++ break; ++ case MSR_IA32_VMX_TRUE_EXIT_CTLS: ++ default1 = 0x00036dff; ++ break; ++ case MSR_IA32_VMX_PROCBASED_CTLS2: ++ default1 = 0; ++ break; ++ default: ++ abort(); ++ } ++ ++ /* If a feature bit is set, the control can be either set or clear. ++ * Otherwise the value is limited to either 0 or 1 by default1. ++ */ ++ can_be_one = features | default1; ++ can_be_zero = features | ~default1; ++ must_be_one = ~can_be_zero; ++ ++ /* ++ * Bit 0:31 -> 0 if the control bit can be zero (i.e. 1 if it must be one). ++ * Bit 32:63 -> 1 if the control bit can be one. ++ */ ++ return must_be_one | (((uint64_t)can_be_one) << 32); ++} ++ ++#define VMCS12_MAX_FIELD_INDEX (0x17) ++ ++static void kvm_msr_entry_add_vmx(X86CPU *cpu, FeatureWordArray f) ++{ ++ uint64_t kvm_vmx_basic = ++ kvm_arch_get_supported_msr_feature(kvm_state, ++ MSR_IA32_VMX_BASIC); ++ uint64_t kvm_vmx_misc = ++ kvm_arch_get_supported_msr_feature(kvm_state, ++ MSR_IA32_VMX_MISC); ++ uint64_t kvm_vmx_ept_vpid = ++ kvm_arch_get_supported_msr_feature(kvm_state, ++ MSR_IA32_VMX_EPT_VPID_CAP); ++ ++ /* ++ * If the guest is 64-bit, a value of 1 is allowed for the host address ++ * space size vmexit control. ++ */ ++ uint64_t fixed_vmx_exit = f[FEAT_8000_0001_EDX] & CPUID_EXT2_LM ++ ? (uint64_t)VMX_VM_EXIT_HOST_ADDR_SPACE_SIZE << 32 : 0; ++ ++ /* ++ * Bits 0-30, 32-44 and 50-53 come from the host. KVM should ++ * not change them for backwards compatibility. ++ */ ++ uint64_t fixed_vmx_basic = kvm_vmx_basic & ++ (MSR_VMX_BASIC_VMCS_REVISION_MASK | ++ MSR_VMX_BASIC_VMXON_REGION_SIZE_MASK | ++ MSR_VMX_BASIC_VMCS_MEM_TYPE_MASK); ++ ++ /* ++ * Same for bits 0-4 and 25-27. Bits 16-24 (CR3 target count) can ++ * change in the future but are always zero for now, clear them to be ++ * future proof. Bits 32-63 in theory could change, though KVM does ++ * not support dual-monitor treatment and probably never will; mask ++ * them out as well. ++ */ ++ uint64_t fixed_vmx_misc = kvm_vmx_misc & ++ (MSR_VMX_MISC_PREEMPTION_TIMER_SHIFT_MASK | ++ MSR_VMX_MISC_MAX_MSR_LIST_SIZE_MASK); ++ ++ /* ++ * EPT memory types should not change either, so we do not bother ++ * adding features for them. ++ */ ++ uint64_t fixed_vmx_ept_mask = ++ (f[FEAT_VMX_SECONDARY_CTLS] & VMX_SECONDARY_EXEC_ENABLE_EPT ? ++ MSR_VMX_EPT_UC | MSR_VMX_EPT_WB : 0); ++ uint64_t fixed_vmx_ept_vpid = kvm_vmx_ept_vpid & fixed_vmx_ept_mask; ++ ++ kvm_msr_entry_add(cpu, MSR_IA32_VMX_TRUE_PROCBASED_CTLS, ++ make_vmx_msr_value(MSR_IA32_VMX_TRUE_PROCBASED_CTLS, ++ f[FEAT_VMX_PROCBASED_CTLS])); ++ kvm_msr_entry_add(cpu, MSR_IA32_VMX_TRUE_PINBASED_CTLS, ++ make_vmx_msr_value(MSR_IA32_VMX_TRUE_PINBASED_CTLS, ++ f[FEAT_VMX_PINBASED_CTLS])); ++ kvm_msr_entry_add(cpu, MSR_IA32_VMX_TRUE_EXIT_CTLS, ++ make_vmx_msr_value(MSR_IA32_VMX_TRUE_EXIT_CTLS, ++ f[FEAT_VMX_EXIT_CTLS]) | fixed_vmx_exit); ++ kvm_msr_entry_add(cpu, MSR_IA32_VMX_TRUE_ENTRY_CTLS, ++ make_vmx_msr_value(MSR_IA32_VMX_TRUE_ENTRY_CTLS, ++ f[FEAT_VMX_ENTRY_CTLS])); ++ kvm_msr_entry_add(cpu, MSR_IA32_VMX_PROCBASED_CTLS2, ++ make_vmx_msr_value(MSR_IA32_VMX_PROCBASED_CTLS2, ++ f[FEAT_VMX_SECONDARY_CTLS])); ++ kvm_msr_entry_add(cpu, MSR_IA32_VMX_EPT_VPID_CAP, ++ f[FEAT_VMX_EPT_VPID_CAPS] | fixed_vmx_ept_vpid); ++ kvm_msr_entry_add(cpu, MSR_IA32_VMX_BASIC, ++ f[FEAT_VMX_BASIC] | fixed_vmx_basic); ++ kvm_msr_entry_add(cpu, MSR_IA32_VMX_MISC, ++ f[FEAT_VMX_MISC] | fixed_vmx_misc); ++ if (has_msr_vmx_vmfunc) { ++ kvm_msr_entry_add(cpu, MSR_IA32_VMX_VMFUNC, f[FEAT_VMX_VMFUNC]); ++ } ++ ++ /* ++ * Just to be safe, write these with constant values. The CRn_FIXED1 ++ * MSRs are generated by KVM based on the vCPU's CPUID. ++ */ ++ kvm_msr_entry_add(cpu, MSR_IA32_VMX_CR0_FIXED0, ++ CR0_PE_MASK | CR0_PG_MASK | CR0_NE_MASK); ++ kvm_msr_entry_add(cpu, MSR_IA32_VMX_CR4_FIXED0, ++ CR4_VMXE_MASK); ++ kvm_msr_entry_add(cpu, MSR_IA32_VMX_VMCS_ENUM, ++ VMCS12_MAX_FIELD_INDEX << 1); ++} ++ + static int kvm_put_msrs(X86CPU *cpu, int level) + { + CPUX86State *env = &cpu->env; +@@ -2112,7 +2261,16 @@ static int kvm_put_msrs(X86CPU *cpu, int level) + + /* Note: MSR_IA32_FEATURE_CONTROL is written separately, see + * kvm_put_msr_feature_control. */ ++ ++ /* ++ * Older kernels do not include VMX MSRs in KVM_GET_MSR_INDEX_LIST, but ++ * all kernels with MSR features should have them. ++ */ ++ if (kvm_feature_msrs && cpu_has_vmx(env)) { ++ kvm_msr_entry_add_vmx(cpu, env->features); ++ } + } ++ + if (env->mcg_cap) { + int i; + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-add-support-for-MSR_IA32_TSX_CTRL.patch b/SOURCES/kvm-target-i386-add-support-for-MSR_IA32_TSX_CTRL.patch new file mode 100644 index 0000000..fab9b64 --- /dev/null +++ b/SOURCES/kvm-target-i386-add-support-for-MSR_IA32_TSX_CTRL.patch @@ -0,0 +1,161 @@ +From 39c3a18b4b956d0533e07de2640be064e07e3c97 Mon Sep 17 00:00:00 2001 +From: Eduardo Habkost +Date: Tue, 3 Dec 2019 23:53:08 +0000 +Subject: [PATCH 2/2] target/i386: add support for MSR_IA32_TSX_CTRL + +RH-Author: Eduardo Habkost +Message-id: <20191203235308.590845-3-ehabkost@redhat.com> +Patchwork-id: 92850 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH 2/2] target/i386: add support for MSR_IA32_TSX_CTRL +Bugzilla: 1771971 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Igor Mammedov + +From: Paolo Bonzini + +The MSR_IA32_TSX_CTRL MSR can be used to hide TSX (also known as the +Trusty Side-channel Extension). By virtualizing the MSR, KVM guests +can disable TSX and avoid paying the price of mitigating TSX-based +attacks on microarchitectural side channels. + +Reviewed-by: Eduardo Habkost +Signed-off-by: Paolo Bonzini +(cherry picked from commit 2a9758c51e2c2d13fc3845c3d603c11df98b8823) +Signed-off-by: Eduardo Habkost +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 2 +- + target/i386/cpu.h | 4 ++++ + target/i386/kvm.c | 13 +++++++++++++ + target/i386/machine.c | 20 ++++++++++++++++++++ + 4 files changed, 38 insertions(+), 1 deletion(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 68fe865..ef6b958 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -1143,7 +1143,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + .type = MSR_FEATURE_WORD, + .feat_names = { + "rdctl-no", "ibrs-all", "rsba", "skip-l1dfl-vmentry", +- "ssb-no", "mds-no", NULL, NULL, ++ "ssb-no", "mds-no", NULL, "tsx-ctrl", + "taa-no", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index 386e821..8d8814e 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -355,6 +355,9 @@ typedef enum X86Seg { + #define MSR_IA32_PRED_CMD 0x49 + #define MSR_IA32_CORE_CAPABILITY 0xcf + #define MSR_IA32_ARCH_CAPABILITIES 0x10a ++#define ARCH_CAP_TSX_CTRL_MSR (1<<7) ++ ++#define MSR_IA32_TSX_CTRL 0x122 + #define MSR_IA32_TSCDEADLINE 0x6e0 + + #define FEATURE_CONTROL_LOCKED (1<<0) +@@ -1373,6 +1376,7 @@ typedef struct CPUX86State { + uint64_t msr_smi_count; + + uint32_t pkru; ++ uint32_t tsx_ctrl; + + uint64_t spec_ctrl; + uint64_t virt_ssbd; +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index 6366172..107c53b 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -92,6 +92,7 @@ static bool has_msr_hv_stimer; + static bool has_msr_hv_frequencies; + static bool has_msr_xss; + static bool has_msr_spec_ctrl; ++static bool has_msr_tsx_ctrl; + static bool has_msr_virt_ssbd; + static bool has_msr_smi_count; + static bool has_msr_arch_capabs; +@@ -1458,6 +1459,9 @@ static int kvm_get_supported_msrs(KVMState *s) + case MSR_IA32_SPEC_CTRL: + has_msr_spec_ctrl = true; + break; ++ case MSR_IA32_TSX_CTRL: ++ has_msr_tsx_ctrl = true; ++ break; + case MSR_VIRT_SSBD: + has_msr_virt_ssbd = true; + break; +@@ -2095,6 +2099,9 @@ static int kvm_put_msrs(X86CPU *cpu, int level) + if (has_msr_spec_ctrl) { + kvm_msr_entry_add(cpu, MSR_IA32_SPEC_CTRL, env->spec_ctrl); + } ++ if (has_msr_tsx_ctrl) { ++ kvm_msr_entry_add(cpu, MSR_IA32_TSX_CTRL, env->tsx_ctrl); ++ } + if (has_msr_virt_ssbd) { + kvm_msr_entry_add(cpu, MSR_VIRT_SSBD, env->virt_ssbd); + } +@@ -2491,6 +2498,9 @@ static int kvm_get_msrs(X86CPU *cpu) + if (has_msr_spec_ctrl) { + kvm_msr_entry_add(cpu, MSR_IA32_SPEC_CTRL, 0); + } ++ if (has_msr_tsx_ctrl) { ++ kvm_msr_entry_add(cpu, MSR_IA32_TSX_CTRL, 0); ++ } + if (has_msr_virt_ssbd) { + kvm_msr_entry_add(cpu, MSR_VIRT_SSBD, 0); + } +@@ -2862,6 +2872,9 @@ static int kvm_get_msrs(X86CPU *cpu) + case MSR_IA32_SPEC_CTRL: + env->spec_ctrl = msrs[i].data; + break; ++ case MSR_IA32_TSX_CTRL: ++ env->tsx_ctrl = msrs[i].data; ++ break; + case MSR_VIRT_SSBD: + env->virt_ssbd = msrs[i].data; + break; +diff --git a/target/i386/machine.c b/target/i386/machine.c +index fa8d1cc..76b173c 100644 +--- a/target/i386/machine.c ++++ b/target/i386/machine.c +@@ -1226,6 +1226,25 @@ static const VMStateDescription vmstate_efer32 = { + }; + #endif + ++static bool msr_tsx_ctrl_needed(void *opaque) ++{ ++ X86CPU *cpu = opaque; ++ CPUX86State *env = &cpu->env; ++ ++ return env->features[FEAT_ARCH_CAPABILITIES] & ARCH_CAP_TSX_CTRL_MSR; ++} ++ ++static const VMStateDescription vmstate_msr_tsx_ctrl = { ++ .name = "cpu/msr_tsx_ctrl", ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .needed = msr_tsx_ctrl_needed, ++ .fields = (VMStateField[]) { ++ VMSTATE_UINT32(env.tsx_ctrl, X86CPU), ++ VMSTATE_END_OF_LIST() ++ } ++}; ++ + VMStateDescription vmstate_x86_cpu = { + .name = "cpu", + .version_id = 12, +@@ -1357,6 +1376,7 @@ VMStateDescription vmstate_x86_cpu = { + #ifdef CONFIG_KVM + &vmstate_nested_state, + #endif ++ &vmstate_msr_tsx_ctrl, + NULL + } + }; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-adjust-for-missing-VMX-features.patch b/SOURCES/kvm-target-i386-adjust-for-missing-VMX-features.patch new file mode 100644 index 0000000..c193e7f --- /dev/null +++ b/SOURCES/kvm-target-i386-adjust-for-missing-VMX-features.patch @@ -0,0 +1,49 @@ +From 76abda27a42dfe08598b38582210f7aeb31e6685 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Fri, 22 Nov 2019 11:53:46 +0000 +Subject: [PATCH 13/16] target/i386: adjust for missing VMX features + +RH-Author: Paolo Bonzini +Message-id: <20191122115348.25000-14-pbonzini@redhat.com> +Patchwork-id: 92611 +O-Subject: [RHEL8.2/rhel qemu-kvm PATCH 13/15] target/i386: adjust for missing VMX features +Bugzilla: 1689270 +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Maxim Levitsky + +vmx-exit-load-perf-global-ctrl and vmx-entry-load-perf-global-ctrl +have only been added to kernel 5.4, so disable them in RHEL until +we add them to the kernel. At that point, they could be added back +to a new machine type. + +Signed-off-by: Paolo Bonzini +Signed-off-by: Danilo C. L. de Paula +--- + include/hw/i386/pc.h | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h +index 88ffd40..b546aed 100644 +--- a/include/hw/i386/pc.h ++++ b/include/hw/i386/pc.h +@@ -968,6 +968,16 @@ extern void igd_passthrough_isa_bridge_create(PCIBus *bus, uint16_t gpu_dev_id); + #define PC_RHEL_COMPAT \ + { /* PC_RHEL_COMPAT */ \ + .driver = TYPE_X86_CPU,\ ++ .property = "vmx-exit-load-perf-global-ctrl",\ ++ .value = "off",\ ++ },\ ++ { /* PC_RHEL_COMPAT */ \ ++ .driver = TYPE_X86_CPU,\ ++ .property = "vmx-entry-load-perf-global-ctrl",\ ++ .value = "off",\ ++ },\ ++ { /* PC_RHEL_COMPAT */ \ ++ .driver = TYPE_X86_CPU,\ + .property = "host-phys-bits",\ + .value = "on",\ + },\ +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-define-a-new-MSR-based-feature-word-FEAT.patch b/SOURCES/kvm-target-i386-define-a-new-MSR-based-feature-word-FEAT.patch new file mode 100644 index 0000000..5654ec6 --- /dev/null +++ b/SOURCES/kvm-target-i386-define-a-new-MSR-based-feature-word-FEAT.patch @@ -0,0 +1,152 @@ +From 127410386296459cf3eec4b12d7451afc50d2503 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Fri, 22 Nov 2019 11:53:36 +0000 +Subject: [PATCH 03/16] target/i386: define a new MSR based feature word - + FEAT_CORE_CAPABILITY + +RH-Author: Paolo Bonzini +Message-id: <20191122115348.25000-4-pbonzini@redhat.com> +Patchwork-id: 92603 +O-Subject: [RHEL8.2/rhel qemu-kvm PATCH 03/15] target/i386: define a new MSR based feature word - FEAT_CORE_CAPABILITY +Bugzilla: 1689270 +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Maxim Levitsky + +From: Xiaoyao Li + +MSR IA32_CORE_CAPABILITY is a feature-enumerating MSR, which only +enumerates the feature split lock detection (via bit 5) by now. + +The existence of MSR IA32_CORE_CAPABILITY is enumerated by CPUID.7_0:EDX[30]. + +The latest kernel patches about them can be found here: +https://lkml.org/lkml/2019/4/24/1909 + +Signed-off-by: Xiaoyao Li +Message-Id: <20190617153654.916-1-xiaoyao.li@linux.intel.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit 597360c0d8ebda9ca6f239db724a25bddec62b2f) + +RHEL: context +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 22 +++++++++++++++++++++- + target/i386/cpu.h | 5 +++++ + target/i386/kvm.c | 9 +++++++++ + 3 files changed, 35 insertions(+), 1 deletion(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 8c1338f..52f1f33 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -1045,7 +1045,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, "spec-ctrl", "stibp", +- NULL, "arch-capabilities", NULL, "ssbd", ++ NULL, "arch-capabilities", "core-capability", "ssbd", + }, + .cpuid = { + .eax = 7, +@@ -1163,6 +1163,26 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + } + }, + }, ++ [FEAT_CORE_CAPABILITY] = { ++ .type = MSR_FEATURE_WORD, ++ .feat_names = { ++ NULL, NULL, NULL, NULL, ++ NULL, "split-lock-detect", NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ }, ++ .msr = { ++ .index = MSR_IA32_CORE_CAPABILITY, ++ .cpuid_dep = { ++ FEAT_7_0_EDX, ++ CPUID_7_0_EDX_CORE_CAPABILITY, ++ }, ++ }, ++ }, + }; + + typedef struct X86RegisterInfo32 { +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index 1ad54bd..f9b93be 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -353,6 +353,7 @@ typedef enum X86Seg { + #define MSR_IA32_SPEC_CTRL 0x48 + #define MSR_VIRT_SSBD 0xc001011f + #define MSR_IA32_PRED_CMD 0x49 ++#define MSR_IA32_CORE_CAPABILITY 0xcf + #define MSR_IA32_ARCH_CAPABILITIES 0x10a + #define MSR_IA32_TSCDEADLINE 0x6e0 + +@@ -501,6 +502,7 @@ typedef enum FeatureWord { + FEAT_XSAVE_COMP_LO, /* CPUID[EAX=0xd,ECX=0].EAX */ + FEAT_XSAVE_COMP_HI, /* CPUID[EAX=0xd,ECX=0].EDX */ + FEAT_ARCH_CAPABILITIES, ++ FEAT_CORE_CAPABILITY, + FEATURE_WORDS, + } FeatureWord; + +@@ -690,6 +692,7 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS]; + #define CPUID_7_0_EDX_AVX512_4FMAPS (1U << 3) /* AVX512 Multiply Accumulation Single Precision */ + #define CPUID_7_0_EDX_SPEC_CTRL (1U << 26) /* Speculation Control */ + #define CPUID_7_0_EDX_ARCH_CAPABILITIES (1U << 29) /*Arch Capabilities*/ ++#define CPUID_7_0_EDX_CORE_CAPABILITY (1U << 30) /*Core Capability*/ + #define CPUID_7_0_EDX_SPEC_CTRL_SSBD (1U << 31) /* Speculative Store Bypass Disable */ + + #define KVM_HINTS_DEDICATED (1U << 0) +@@ -744,6 +747,8 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS]; + #define MSR_ARCH_CAP_SKIP_L1DFL_VMENTRY (1U << 3) + #define MSR_ARCH_CAP_SSB_NO (1U << 4) + ++#define MSR_CORE_CAP_SPLIT_LOCK_DETECT (1U << 5) ++ + #ifndef HYPERV_SPINLOCK_NEVER_RETRY + #define HYPERV_SPINLOCK_NEVER_RETRY 0xFFFFFFFF + #endif +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index da5f07e..849a11a 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -95,6 +95,7 @@ static bool has_msr_spec_ctrl; + static bool has_msr_virt_ssbd; + static bool has_msr_smi_count; + static bool has_msr_arch_capabs; ++static bool has_msr_core_capabs; + + static uint32_t has_architectural_pmu_version; + static uint32_t num_architectural_pmu_gp_counters; +@@ -1428,6 +1429,9 @@ static int kvm_get_supported_msrs(KVMState *s) + case MSR_IA32_ARCH_CAPABILITIES: + has_msr_arch_capabs = true; + break; ++ case MSR_IA32_CORE_CAPABILITY: ++ has_msr_core_capabs = true; ++ break; + } + } + } +@@ -1947,6 +1951,11 @@ static int kvm_put_msrs(X86CPU *cpu, int level) + env->features[FEAT_ARCH_CAPABILITIES]); + } + ++ if (has_msr_core_capabs) { ++ kvm_msr_entry_add(cpu, MSR_IA32_CORE_CAPABILITY, ++ env->features[FEAT_CORE_CAPABILITY]); ++ } ++ + /* + * The following MSRs have side effects on the guest or are too heavy + * for normal writeback. Limit them to reset or full state updates. +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-expand-feature-words-to-64-bits.patch b/SOURCES/kvm-target-i386-expand-feature-words-to-64-bits.patch new file mode 100644 index 0000000..11e064e --- /dev/null +++ b/SOURCES/kvm-target-i386-expand-feature-words-to-64-bits.patch @@ -0,0 +1,306 @@ +From a31ce6a9fa171f677bf52dd0b0076e7b92d9ae33 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Fri, 22 Nov 2019 11:53:41 +0000 +Subject: [PATCH 08/16] target/i386: expand feature words to 64 bits + +RH-Author: Paolo Bonzini +Message-id: <20191122115348.25000-9-pbonzini@redhat.com> +Patchwork-id: 92612 +O-Subject: [RHEL8.2/rhel qemu-kvm PATCH 08/15] target/i386: expand feature words to 64 bits +Bugzilla: 1689270 +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Maxim Levitsky + +VMX requires 64-bit feature words for the IA32_VMX_EPT_VPID_CAP +and IA32_VMX_BASIC MSRs. (The VMX control MSRs are 64-bit wide but +actually have only 32 bits of information). + +Signed-off-by: Paolo Bonzini +(cherry picked from commit ede146c2e720b670350c7ef5e9af44e80a73fe97) +Signed-off-by: Danilo C. L. de Paula +--- + include/sysemu/kvm.h | 2 +- + target/i386/cpu.c | 71 +++++++++++++++++++++++++++------------------------- + target/i386/cpu.h | 2 +- + target/i386/kvm.c | 2 +- + 4 files changed, 40 insertions(+), 37 deletions(-) + +diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h +index 3cf04cf..2c7f841 100644 +--- a/include/sysemu/kvm.h ++++ b/include/sysemu/kvm.h +@@ -466,7 +466,7 @@ int kvm_vm_check_extension(KVMState *s, unsigned int extension); + + uint32_t kvm_arch_get_supported_cpuid(KVMState *env, uint32_t function, + uint32_t index, int reg); +-uint32_t kvm_arch_get_supported_msr_feature(KVMState *s, uint32_t index); ++uint64_t kvm_arch_get_supported_msr_feature(KVMState *s, uint32_t index); + + + void kvm_set_sigmask_len(KVMState *s, unsigned int sigmask_len); +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index a7360b3..3e77830 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -785,7 +785,7 @@ typedef struct FeatureWordInfo { + * In cases of disagreement between feature naming conventions, + * aliases may be added. + */ +- const char *feat_names[32]; ++ const char *feat_names[64]; + union { + /* If type==CPUID_FEATURE_WORD */ + struct { +@@ -799,11 +799,11 @@ typedef struct FeatureWordInfo { + uint32_t index; + } msr; + }; +- uint32_t tcg_features; /* Feature flags supported by TCG */ +- uint32_t unmigratable_flags; /* Feature flags known to be unmigratable */ +- uint32_t migratable_flags; /* Feature flags known to be migratable */ ++ uint64_t tcg_features; /* Feature flags supported by TCG */ ++ uint64_t unmigratable_flags; /* Feature flags known to be unmigratable */ ++ uint64_t migratable_flags; /* Feature flags known to be migratable */ + /* Features that shouldn't be auto-enabled by "-cpu host" */ +- uint32_t no_autoenable_flags; ++ uint64_t no_autoenable_flags; + } FeatureWordInfo; + + static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { +@@ -1175,7 +1175,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + + typedef struct FeatureMask { + FeatureWord index; +- uint32_t mask; ++ uint64_t mask; + } FeatureMask; + + typedef struct FeatureDep { +@@ -1185,11 +1185,11 @@ typedef struct FeatureDep { + static FeatureDep feature_dependencies[] = { + { + .from = { FEAT_7_0_EDX, CPUID_7_0_EDX_ARCH_CAPABILITIES }, +- .to = { FEAT_ARCH_CAPABILITIES, ~0u }, ++ .to = { FEAT_ARCH_CAPABILITIES, ~0ull }, + }, + { + .from = { FEAT_7_0_EDX, CPUID_7_0_EDX_CORE_CAPABILITY }, +- .to = { FEAT_CORE_CAPABILITY, ~0u }, ++ .to = { FEAT_CORE_CAPABILITY, ~0ull }, + }, + }; + +@@ -1301,14 +1301,14 @@ const char *get_register_name_32(unsigned int reg) + * Returns the set of feature flags that are supported and migratable by + * QEMU, for a given FeatureWord. + */ +-static uint32_t x86_cpu_get_migratable_flags(FeatureWord w) ++static uint64_t x86_cpu_get_migratable_flags(FeatureWord w) + { + FeatureWordInfo *wi = &feature_word_info[w]; +- uint32_t r = 0; ++ uint64_t r = 0; + int i; + +- for (i = 0; i < 32; i++) { +- uint32_t f = 1U << i; ++ for (i = 0; i < 64; i++) { ++ uint64_t f = 1ULL << i; + + /* If the feature name is known, it is implicitly considered migratable, + * unless it is explicitly set in unmigratable_flags */ +@@ -2948,7 +2948,7 @@ void x86_cpu_change_kvm_default(const char *prop, const char *value) + assert(pv->prop); + } + +-static uint32_t x86_cpu_get_supported_feature_word(FeatureWord w, ++static uint64_t x86_cpu_get_supported_feature_word(FeatureWord w, + bool migratable_only); + + static bool lmce_supported(void) +@@ -3142,7 +3142,7 @@ static bool x86_cpu_have_filtered_features(X86CPU *cpu) + return false; + } + +-static void mark_unavailable_features(X86CPU *cpu, FeatureWord w, uint32_t mask, ++static void mark_unavailable_features(X86CPU *cpu, FeatureWord w, uint64_t mask, + const char *verbose_prefix) + { + CPUX86State *env = &cpu->env; +@@ -3159,8 +3159,8 @@ static void mark_unavailable_features(X86CPU *cpu, FeatureWord w, uint32_t mask, + return; + } + +- for (i = 0; i < 32; ++i) { +- if ((1UL << i) & mask) { ++ for (i = 0; i < 64; ++i) { ++ if ((1ULL << i) & mask) { + feat_word_str = feature_word_description(f, i); + warn_report("%s: %s%s%s [bit %d]", + verbose_prefix, +@@ -3403,7 +3403,7 @@ static void x86_cpu_get_feature_words(Object *obj, Visitor *v, + const char *name, void *opaque, + Error **errp) + { +- uint32_t *array = (uint32_t *)opaque; ++ uint64_t *array = (uint64_t *)opaque; + FeatureWord w; + X86CPUFeatureWordInfo word_infos[FEATURE_WORDS] = { }; + X86CPUFeatureWordInfoList list_entries[FEATURE_WORDS] = { }; +@@ -3487,6 +3487,7 @@ static inline void feat2prop(char *s) + /* Return the feature property name for a feature flag bit */ + static const char *x86_cpu_feature_name(FeatureWord w, int bitnr) + { ++ const char *name; + /* XSAVE components are automatically enabled by other features, + * so return the original feature name instead + */ +@@ -3500,9 +3501,11 @@ static const char *x86_cpu_feature_name(FeatureWord w, int bitnr) + } + } + +- assert(bitnr < 32); ++ assert(bitnr < 64); + assert(w < FEATURE_WORDS); +- return feature_word_info[w].feat_names[bitnr]; ++ name = feature_word_info[w].feat_names[bitnr]; ++ assert(bitnr < 32 || !(name && feature_word_info[w].type == CPUID_FEATURE_WORD)); ++ return name; + } + + /* Compatibily hack to maintain legacy +-feat semantic, +@@ -3619,10 +3622,10 @@ static void x86_cpu_list_feature_names(FeatureWordArray features, + strList **next = feat_names; + + for (w = 0; w < FEATURE_WORDS; w++) { +- uint32_t filtered = features[w]; ++ uint64_t filtered = features[w]; + int i; +- for (i = 0; i < 32; i++) { +- if (filtered & (1UL << i)) { ++ for (i = 0; i < 64; i++) { ++ if (filtered & (1ULL << i)) { + strList *new = g_new0(strList, 1); + new->value = g_strdup(x86_cpu_feature_name(w, i)); + *next = new; +@@ -3760,7 +3763,7 @@ void x86_cpu_list(FILE *f, fprintf_function cpu_fprintf) + names = NULL; + for (i = 0; i < ARRAY_SIZE(feature_word_info); i++) { + FeatureWordInfo *fw = &feature_word_info[i]; +- for (j = 0; j < 32; j++) { ++ for (j = 0; j < 64; j++) { + if (fw->feat_names[j]) { + names = g_list_append(names, (gpointer)fw->feat_names[j]); + } +@@ -3807,11 +3810,11 @@ CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp) + return cpu_list; + } + +-static uint32_t x86_cpu_get_supported_feature_word(FeatureWord w, ++static uint64_t x86_cpu_get_supported_feature_word(FeatureWord w, + bool migratable_only) + { + FeatureWordInfo *wi = &feature_word_info[w]; +- uint32_t r = 0; ++ uint64_t r = 0; + + if (kvm_enabled()) { + switch (wi->type) { +@@ -3950,7 +3953,7 @@ static QDict *x86_cpu_static_props(void) + for (w = 0; w < FEATURE_WORDS; w++) { + FeatureWordInfo *fi = &feature_word_info[w]; + int bit; +- for (bit = 0; bit < 32; bit++) { ++ for (bit = 0; bit < 64; bit++) { + if (!fi->feat_names[bit]) { + continue; + } +@@ -5015,7 +5018,7 @@ static void x86_cpu_expand_features(X86CPU *cpu, Error **errp) + for (i = 0; i < ARRAY_SIZE(feature_dependencies); i++) { + FeatureDep *d = &feature_dependencies[i]; + if (!(env->features[d->from.index] & d->from.mask)) { +- uint32_t unavailable_features = env->features[d->to.index] & d->to.mask; ++ uint64_t unavailable_features = env->features[d->to.index] & d->to.mask; + + /* Not an error unless the dependent feature was added explicitly. */ + mark_unavailable_features(cpu, d->to.index, +@@ -5094,10 +5097,10 @@ static void x86_cpu_filter_features(X86CPU *cpu, bool verbose) + } + + for (w = 0; w < FEATURE_WORDS; w++) { +- uint32_t host_feat = ++ uint64_t host_feat = + x86_cpu_get_supported_feature_word(w, false); +- uint32_t requested_features = env->features[w]; +- uint32_t unavailable_features = requested_features & ~host_feat; ++ uint64_t requested_features = env->features[w]; ++ uint64_t unavailable_features = requested_features & ~host_feat; + mark_unavailable_features(cpu, w, unavailable_features, prefix); + } + +@@ -5380,7 +5383,7 @@ static void x86_cpu_unrealizefn(DeviceState *dev, Error **errp) + + typedef struct BitProperty { + FeatureWord w; +- uint32_t mask; ++ uint64_t mask; + } BitProperty; + + static void x86_cpu_get_bit_prop(Object *obj, Visitor *v, const char *name, +@@ -5388,7 +5391,7 @@ static void x86_cpu_get_bit_prop(Object *obj, Visitor *v, const char *name, + { + X86CPU *cpu = X86_CPU(obj); + BitProperty *fp = opaque; +- uint32_t f = cpu->env.features[fp->w]; ++ uint64_t f = cpu->env.features[fp->w]; + bool value = (f & fp->mask) == fp->mask; + visit_type_bool(v, name, &value, errp); + } +@@ -5441,7 +5444,7 @@ static void x86_cpu_register_bit_prop(X86CPU *cpu, + { + BitProperty *fp; + ObjectProperty *op; +- uint32_t mask = (1UL << bitnr); ++ uint64_t mask = (1ULL << bitnr); + + op = object_property_find(OBJECT(cpu), prop_name, NULL); + if (op) { +@@ -5577,7 +5580,7 @@ static void x86_cpu_initfn(Object *obj) + for (w = 0; w < FEATURE_WORDS; w++) { + int bitnr; + +- for (bitnr = 0; bitnr < 32; bitnr++) { ++ for (bitnr = 0; bitnr < 64; bitnr++) { + x86_cpu_register_feature_bit_props(cpu, w, bitnr); + } + } +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index f9b93be..edba84e 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -506,7 +506,7 @@ typedef enum FeatureWord { + FEATURE_WORDS, + } FeatureWord; + +-typedef uint32_t FeatureWordArray[FEATURE_WORDS]; ++typedef uint64_t FeatureWordArray[FEATURE_WORDS]; + + /* cpuid_features bits */ + #define CPUID_FP87 (1U << 0) +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index 2290c5d..85abd37 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -423,7 +423,7 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function, + return ret; + } + +-uint32_t kvm_arch_get_supported_msr_feature(KVMState *s, uint32_t index) ++uint64_t kvm_arch_get_supported_msr_feature(KVMState *s, uint32_t index) + { + struct { + struct kvm_msrs info; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-handle-filtered_features-in-a-new-functi.patch b/SOURCES/kvm-target-i386-handle-filtered_features-in-a-new-functi.patch new file mode 100644 index 0000000..f48b1d1 --- /dev/null +++ b/SOURCES/kvm-target-i386-handle-filtered_features-in-a-new-functi.patch @@ -0,0 +1,187 @@ +From d7362c761ef55b7f665c4dff61d9e58b153ff11c Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Fri, 22 Nov 2019 11:53:39 +0000 +Subject: [PATCH 06/16] target/i386: handle filtered_features in a new function + mark_unavailable_features + +RH-Author: Paolo Bonzini +Message-id: <20191122115348.25000-7-pbonzini@redhat.com> +Patchwork-id: 92600 +O-Subject: [RHEL8.2/rhel qemu-kvm PATCH 06/15] target/i386: handle filtered_features in a new function mark_unavailable_features +Bugzilla: 1689270 +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Maxim Levitsky + +The next patch will add a different reason for filtering features, unrelated +to host feature support. Extract a new function that takes care of disabling +the features and optionally reporting them. + +Signed-off-by: Paolo Bonzini +(cherry picked from commit 245edd0cfb1481b7a0398cce45df23db50f00034) +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 87 ++++++++++++++++++++++++++++++------------------------- + 1 file changed, 48 insertions(+), 39 deletions(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index d0c48c2..b06ce9d 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -3121,17 +3121,41 @@ static char *feature_word_description(FeatureWordInfo *f, uint32_t bit) + return NULL; + } + +-static void report_unavailable_features(FeatureWord w, uint32_t mask) ++static bool x86_cpu_have_filtered_features(X86CPU *cpu) + { ++ FeatureWord w; ++ ++ for (w = 0; w < FEATURE_WORDS; w++) { ++ if (cpu->filtered_features[w]) { ++ return true; ++ } ++ } ++ ++ return false; ++} ++ ++static void mark_unavailable_features(X86CPU *cpu, FeatureWord w, uint32_t mask, ++ const char *verbose_prefix) ++{ ++ CPUX86State *env = &cpu->env; + FeatureWordInfo *f = &feature_word_info[w]; + int i; + char *feat_word_str; + ++ if (!cpu->force_features) { ++ env->features[w] &= ~mask; ++ } ++ cpu->filtered_features[w] |= mask; ++ ++ if (!verbose_prefix) { ++ return; ++ } ++ + for (i = 0; i < 32; ++i) { + if ((1UL << i) & mask) { + feat_word_str = feature_word_description(f, i); +- warn_report("%s doesn't support requested feature: %s%s%s [bit %d]", +- accel_uses_host_cpuid() ? "host" : "TCG", ++ warn_report("%s: %s%s%s [bit %d]", ++ verbose_prefix, + feat_word_str, + f->feat_names[i] ? "." : "", + f->feat_names[i] ? f->feat_names[i] : "", i); +@@ -3577,7 +3601,7 @@ static void x86_cpu_parse_featurestr(const char *typename, char *features, + } + + static void x86_cpu_expand_features(X86CPU *cpu, Error **errp); +-static int x86_cpu_filter_features(X86CPU *cpu); ++static void x86_cpu_filter_features(X86CPU *cpu, bool verbose); + + /* Build a list with the name of all features on a feature word array */ + static void x86_cpu_list_feature_names(FeatureWordArray features, +@@ -3642,7 +3666,7 @@ static void x86_cpu_class_check_missing_features(X86CPUClass *xcc, + next = &new->next; + } + +- x86_cpu_filter_features(xc); ++ x86_cpu_filter_features(xc, false); + + x86_cpu_list_feature_names(xc->filtered_features, next); + +@@ -3811,15 +3835,6 @@ static uint32_t x86_cpu_get_supported_feature_word(FeatureWord w, + return r; + } + +-static void x86_cpu_report_filtered_features(X86CPU *cpu) +-{ +- FeatureWord w; +- +- for (w = 0; w < FEATURE_WORDS; w++) { +- report_unavailable_features(w, cpu->filtered_features[w]); +- } +-} +- + static void x86_cpu_apply_props(X86CPU *cpu, PropValue *props) + { + PropValue *pv; +@@ -5042,24 +5057,24 @@ out: + * + * Returns: 0 if all flags are supported by the host, non-zero otherwise. + */ +-static int x86_cpu_filter_features(X86CPU *cpu) ++static void x86_cpu_filter_features(X86CPU *cpu, bool verbose) + { + CPUX86State *env = &cpu->env; + FeatureWord w; +- int rv = 0; ++ const char *prefix = NULL; ++ ++ if (verbose) { ++ prefix = accel_uses_host_cpuid() ++ ? "host doesn't support requested feature" ++ : "TCG doesn't support requested feature"; ++ } + + for (w = 0; w < FEATURE_WORDS; w++) { + uint32_t host_feat = + x86_cpu_get_supported_feature_word(w, false); + uint32_t requested_features = env->features[w]; +- uint32_t available_features = requested_features & host_feat; +- if (!cpu->force_features) { +- env->features[w] = available_features; +- } +- cpu->filtered_features[w] = requested_features & ~available_features; +- if (cpu->filtered_features[w]) { +- rv = 1; +- } ++ uint32_t unavailable_features = requested_features & ~host_feat; ++ mark_unavailable_features(cpu, w, unavailable_features, prefix); + } + + if ((env->features[FEAT_7_0_EBX] & CPUID_7_0_EBX_INTEL_PT) && +@@ -5085,13 +5100,9 @@ static int x86_cpu_filter_features(X86CPU *cpu) + * host can't emulate the capabilities we report on + * cpu_x86_cpuid(), intel-pt can't be enabled on the current host. + */ +- env->features[FEAT_7_0_EBX] &= ~CPUID_7_0_EBX_INTEL_PT; +- cpu->filtered_features[FEAT_7_0_EBX] |= CPUID_7_0_EBX_INTEL_PT; +- rv = 1; ++ mark_unavailable_features(cpu, FEAT_7_0_EBX, CPUID_7_0_EBX_INTEL_PT, prefix); + } + } +- +- return rv; + } + + static void x86_cpu_realizefn(DeviceState *dev, Error **errp) +@@ -5120,16 +5131,14 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp) + goto out; + } + +- if (x86_cpu_filter_features(cpu) && +- (cpu->check_cpuid || cpu->enforce_cpuid)) { +- x86_cpu_report_filtered_features(cpu); +- if (cpu->enforce_cpuid) { +- error_setg(&local_err, +- accel_uses_host_cpuid() ? +- "Host doesn't support requested features" : +- "TCG doesn't support requested features"); +- goto out; +- } ++ x86_cpu_filter_features(cpu, cpu->check_cpuid || cpu->enforce_cpuid); ++ ++ if (cpu->enforce_cpuid && x86_cpu_have_filtered_features(cpu)) { ++ error_setg(&local_err, ++ accel_uses_host_cpuid() ? ++ "Host doesn't support requested features" : ++ "TCG doesn't support requested features"); ++ goto out; + } + + /* On AMD CPUs, some CPUID[8000_0001].EDX bits must match the bits on +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-introduce-generic-feature-dependency-mec.patch b/SOURCES/kvm-target-i386-introduce-generic-feature-dependency-mec.patch new file mode 100644 index 0000000..e3bf334 --- /dev/null +++ b/SOURCES/kvm-target-i386-introduce-generic-feature-dependency-mec.patch @@ -0,0 +1,158 @@ +From 98145bfcdcee809e370d65eb3a97a9529670ec06 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Fri, 22 Nov 2019 11:53:40 +0000 +Subject: [PATCH 07/16] target/i386: introduce generic feature dependency + mechanism + +RH-Author: Paolo Bonzini +Message-id: <20191122115348.25000-8-pbonzini@redhat.com> +Patchwork-id: 92610 +O-Subject: [RHEL8.2/rhel qemu-kvm PATCH 07/15] target/i386: introduce generic feature dependency mechanism +Bugzilla: 1689270 +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Maxim Levitsky + +Sometimes a CPU feature does not make sense unless another is +present. In the case of VMX features, KVM does not even allow +setting the VMX controls to some invalid combinations. + +Therefore, this patch adds a generic mechanism that looks for bits +that the user explicitly cleared, and uses them to remove other bits +from the expanded CPU definition. If these dependent bits were also +explicitly *set* by the user, this will be a warning for "-cpu check" +and an error for "-cpu enforce". If not, then the dependent bits are +cleared silently, for convenience. + +With VMX features, this will be used so that for example +"-cpu host,-rdrand" will also hide support for RDRAND exiting. + +Signed-off-by: Paolo Bonzini +(cherry picked from commit 99e24dbdaa682c7b9d0bb5b463638c585bcee1c3) +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 72 ++++++++++++++++++++++++++++++++++++------------------- + 1 file changed, 48 insertions(+), 24 deletions(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index b06ce9d..a7360b3 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -797,10 +797,6 @@ typedef struct FeatureWordInfo { + /* If type==MSR_FEATURE_WORD */ + struct { + uint32_t index; +- struct { /*CPUID that enumerate this MSR*/ +- FeatureWord cpuid_class; +- uint32_t cpuid_flag; +- } cpuid_dep; + } msr; + }; + uint32_t tcg_features; /* Feature flags supported by TCG */ +@@ -1157,10 +1153,6 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + }, + .msr = { + .index = MSR_IA32_ARCH_CAPABILITIES, +- .cpuid_dep = { +- FEAT_7_0_EDX, +- CPUID_7_0_EDX_ARCH_CAPABILITIES +- } + }, + }, + [FEAT_CORE_CAPABILITY] = { +@@ -1177,14 +1169,30 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + }, + .msr = { + .index = MSR_IA32_CORE_CAPABILITY, +- .cpuid_dep = { +- FEAT_7_0_EDX, +- CPUID_7_0_EDX_CORE_CAPABILITY, +- }, + }, + }, + }; + ++typedef struct FeatureMask { ++ FeatureWord index; ++ uint32_t mask; ++} FeatureMask; ++ ++typedef struct FeatureDep { ++ FeatureMask from, to; ++} FeatureDep; ++ ++static FeatureDep feature_dependencies[] = { ++ { ++ .from = { FEAT_7_0_EDX, CPUID_7_0_EDX_ARCH_CAPABILITIES }, ++ .to = { FEAT_ARCH_CAPABILITIES, ~0u }, ++ }, ++ { ++ .from = { FEAT_7_0_EDX, CPUID_7_0_EDX_CORE_CAPABILITY }, ++ .to = { FEAT_CORE_CAPABILITY, ~0u }, ++ }, ++}; ++ + typedef struct X86RegisterInfo32 { + /* Name of register */ + const char *name; +@@ -4967,9 +4975,26 @@ static void x86_cpu_expand_features(X86CPU *cpu, Error **errp) + { + CPUX86State *env = &cpu->env; + FeatureWord w; ++ int i; + GList *l; + Error *local_err = NULL; + ++ for (l = plus_features; l; l = l->next) { ++ const char *prop = l->data; ++ object_property_set_bool(OBJECT(cpu), true, prop, &local_err); ++ if (local_err) { ++ goto out; ++ } ++ } ++ ++ for (l = minus_features; l; l = l->next) { ++ const char *prop = l->data; ++ object_property_set_bool(OBJECT(cpu), false, prop, &local_err); ++ if (local_err) { ++ goto out; ++ } ++ } ++ + /*TODO: Now cpu->max_features doesn't overwrite features + * set using QOM properties, and we can convert + * plus_features & minus_features to global properties +@@ -4987,19 +5012,18 @@ static void x86_cpu_expand_features(X86CPU *cpu, Error **errp) + } + } + +- for (l = plus_features; l; l = l->next) { +- const char *prop = l->data; +- object_property_set_bool(OBJECT(cpu), true, prop, &local_err); +- if (local_err) { +- goto out; +- } +- } ++ for (i = 0; i < ARRAY_SIZE(feature_dependencies); i++) { ++ FeatureDep *d = &feature_dependencies[i]; ++ if (!(env->features[d->from.index] & d->from.mask)) { ++ uint32_t unavailable_features = env->features[d->to.index] & d->to.mask; + +- for (l = minus_features; l; l = l->next) { +- const char *prop = l->data; +- object_property_set_bool(OBJECT(cpu), false, prop, &local_err); +- if (local_err) { +- goto out; ++ /* Not an error unless the dependent feature was added explicitly. */ ++ mark_unavailable_features(cpu, d->to.index, ++ unavailable_features & env->user_features[d->to.index], ++ "This feature depends on other features that were not requested"); ++ ++ env->user_features[d->to.index] |= unavailable_features; ++ env->features[d->to.index] &= ~unavailable_features; + } + } + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-kvm-Add-nested-migration-blocker-only-wh.patch b/SOURCES/kvm-target-i386-kvm-Add-nested-migration-blocker-only-wh.patch new file mode 100644 index 0000000..b50ba57 --- /dev/null +++ b/SOURCES/kvm-target-i386-kvm-Add-nested-migration-blocker-only-wh.patch @@ -0,0 +1,60 @@ +From a99cae3466f0fae8a46c58f4e07ed6b6a481a0a5 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 22 Jul 2019 18:22:17 +0100 +Subject: [PATCH 36/39] target/i386: kvm: Add nested migration blocker only + when kernel lacks required capabilities + +RH-Author: Paolo Bonzini +Message-id: <20190722182220.19374-16-pbonzini@redhat.com> +Patchwork-id: 89632 +O-Subject: [RHEL-8.1.0 PATCH qemu-kvm v3 15/18] target/i386: kvm: Add nested migration blocker only when kernel lacks required capabilities +Bugzilla: 1689269 +RH-Acked-by: Peter Xu +RH-Acked-by: Laurent Vivier +RH-Acked-by: Dr. David Alan Gilbert + +From: Liran Alon + +Previous commits have added support for migration of nested virtualization +workloads. This was done by utilising two new KVM capabilities: +KVM_CAP_NESTED_STATE and KVM_CAP_EXCEPTION_PAYLOAD. Both which are +required in order to correctly migrate such workloads. + +Therefore, change code to add a migration blocker for vCPUs exposed with +Intel VMX or AMD SVM in case one of these kernel capabilities is +missing. + +Signed-off-by: Liran Alon +Reviewed-by: Maran Wilson +Message-Id: <20190619162140.133674-11-liran.alon@oracle.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit 12604092e26cdace44c901bc429e7e4c7c3e0cab) +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/kvm.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index aa2d589..0619aba 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -1159,9 +1159,14 @@ int kvm_arch_init_vcpu(CPUState *cs) + !!(c->ecx & CPUID_EXT_SMX); + } + +- if (cpu_has_vmx(env) && !nested_virt_mig_blocker) { ++ if (cpu_has_vmx(env) && !nested_virt_mig_blocker && ++ ((kvm_max_nested_state_length() <= 0) || !has_exception_payload)) { + error_setg(&nested_virt_mig_blocker, +- "Nested virtualization does not support live migration yet"); ++ "Kernel do not provide required capabilities for " ++ "nested virtualization migration. " ++ "(CAP_NESTED_STATE=%d, CAP_EXCEPTION_PAYLOAD=%d)", ++ kvm_max_nested_state_length() > 0, ++ has_exception_payload); + r = migrate_add_blocker(nested_virt_mig_blocker, &local_err); + if (local_err) { + error_report_err(local_err); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-kvm-Add-support-for-KVM_CAP_EXCEPTION_PA.patch b/SOURCES/kvm-target-i386-kvm-Add-support-for-KVM_CAP_EXCEPTION_PA.patch new file mode 100644 index 0000000..53e4621 --- /dev/null +++ b/SOURCES/kvm-target-i386-kvm-Add-support-for-KVM_CAP_EXCEPTION_PA.patch @@ -0,0 +1,451 @@ +From 05a54f3fc44598f917d72a1f2570c43ec042cdb8 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 22 Jul 2019 18:22:16 +0100 +Subject: [PATCH 35/39] target/i386: kvm: Add support for + KVM_CAP_EXCEPTION_PAYLOAD + +RH-Author: Paolo Bonzini +Message-id: <20190722182220.19374-15-pbonzini@redhat.com> +Patchwork-id: 89631 +O-Subject: [RHEL-8.1.0 PATCH qemu-kvm v3 14/18] target/i386: kvm: Add support for KVM_CAP_EXCEPTION_PAYLOAD +Bugzilla: 1689269 +RH-Acked-by: Peter Xu +RH-Acked-by: Laurent Vivier +RH-Acked-by: Dr. David Alan Gilbert + +From: Liran Alon + +Kernel commit c4f55198c7c2 ("kvm: x86: Introduce KVM_CAP_EXCEPTION_PAYLOAD") +introduced a new KVM capability which allows userspace to correctly +distinguish between pending and injected exceptions. + +This distinguish is important in case of nested virtualization scenarios +because a L2 pending exception can still be intercepted by the L1 hypervisor +while a L2 injected exception cannot. + +Furthermore, when an exception is attempted to be injected by QEMU, +QEMU should specify the exception payload (CR2 in case of #PF or +DR6 in case of #DB) instead of having the payload already delivered in +the respective vCPU register. Because in case exception is injected to +L2 guest and is intercepted by L1 hypervisor, then payload needs to be +reported to L1 intercept (VMExit handler) while still preserving +respective vCPU register unchanged. + +This commit adds support for QEMU to properly utilise this new KVM +capability (KVM_CAP_EXCEPTION_PAYLOAD). + +Reviewed-by: Nikita Leshenko +Signed-off-by: Liran Alon +Message-Id: <20190619162140.133674-10-liran.alon@oracle.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit fd13f23b8c95311eff74426921557eee592b0ed3) +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 6 ++- + target/i386/cpu.h | 6 ++- + target/i386/hvf/hvf.c | 10 +++-- + target/i386/hvf/x86hvf.c | 4 +- + target/i386/kvm.c | 101 +++++++++++++++++++++++++++++++++++++++-------- + target/i386/machine.c | 84 ++++++++++++++++++++++++++++++++++++++- + 6 files changed, 187 insertions(+), 24 deletions(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index bd0b784..f71b044 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -4645,7 +4645,11 @@ static void x86_cpu_reset(CPUState *s) + memset(env->mtrr_fixed, 0, sizeof(env->mtrr_fixed)); + + env->interrupt_injected = -1; +- env->exception_injected = -1; ++ env->exception_nr = -1; ++ env->exception_pending = 0; ++ env->exception_injected = 0; ++ env->exception_has_payload = false; ++ env->exception_payload = 0; + env->nmi_injected = false; + #if !defined(CONFIG_USER_ONLY) + /* We hard-wire the BSP to the first CPU. */ +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index 86f3d98..d120f62 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -1325,10 +1325,14 @@ typedef struct CPUX86State { + + /* For KVM */ + uint32_t mp_state; +- int32_t exception_injected; ++ int32_t exception_nr; + int32_t interrupt_injected; + uint8_t soft_interrupt; ++ uint8_t exception_pending; ++ uint8_t exception_injected; + uint8_t has_error_code; ++ uint8_t exception_has_payload; ++ uint64_t exception_payload; + uint32_t ins_len; + uint32_t sipi_vector; + bool tsc_valid; +diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c +index c367539..acc0bb9 100644 +--- a/target/i386/hvf/hvf.c ++++ b/target/i386/hvf/hvf.c +@@ -617,7 +617,9 @@ static void hvf_store_events(CPUState *cpu, uint32_t ins_len, uint64_t idtvec_in + X86CPU *x86_cpu = X86_CPU(cpu); + CPUX86State *env = &x86_cpu->env; + +- env->exception_injected = -1; ++ env->exception_nr = -1; ++ env->exception_pending = 0; ++ env->exception_injected = 0; + env->interrupt_injected = -1; + env->nmi_injected = false; + if (idtvec_info & VMCS_IDT_VEC_VALID) { +@@ -631,7 +633,8 @@ static void hvf_store_events(CPUState *cpu, uint32_t ins_len, uint64_t idtvec_in + break; + case VMCS_IDT_VEC_HWEXCEPTION: + case VMCS_IDT_VEC_SWEXCEPTION: +- env->exception_injected = idtvec_info & VMCS_IDT_VEC_VECNUM; ++ env->exception_nr = idtvec_info & VMCS_IDT_VEC_VECNUM; ++ env->exception_injected = 1; + break; + case VMCS_IDT_VEC_PRIV_SWEXCEPTION: + default: +@@ -925,7 +928,8 @@ int hvf_vcpu_exec(CPUState *cpu) + macvm_set_rip(cpu, rip + ins_len); + break; + case VMX_REASON_VMCALL: +- env->exception_injected = EXCP0D_GPF; ++ env->exception_nr = EXCP0D_GPF; ++ env->exception_injected = 1; + env->has_error_code = true; + env->error_code = 0; + break; +diff --git a/target/i386/hvf/x86hvf.c b/target/i386/hvf/x86hvf.c +index 6c88939..f0e58a8 100644 +--- a/target/i386/hvf/x86hvf.c ++++ b/target/i386/hvf/x86hvf.c +@@ -362,8 +362,8 @@ bool hvf_inject_interrupts(CPUState *cpu_state) + if (env->interrupt_injected != -1) { + vector = env->interrupt_injected; + intr_type = VMCS_INTR_T_SWINTR; +- } else if (env->exception_injected != -1) { +- vector = env->exception_injected; ++ } else if (env->exception_nr != -1) { ++ vector = env->exception_nr; + if (vector == EXCP03_INT3 || vector == EXCP04_INTO) { + intr_type = VMCS_INTR_T_SWEXCEPTION; + } else { +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index ddceb7d..aa2d589 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -103,6 +103,7 @@ static uint32_t num_architectural_pmu_fixed_counters; + static int has_xsave; + static int has_xcrs; + static int has_pit_state2; ++static int has_exception_payload; + + static bool has_msr_mcg_ext_ctl; + +@@ -569,15 +570,56 @@ void kvm_arch_on_sigbus_vcpu(CPUState *c, int code, void *addr) + /* Hope we are lucky for AO MCE */ + } + ++static void kvm_reset_exception(CPUX86State *env) ++{ ++ env->exception_nr = -1; ++ env->exception_pending = 0; ++ env->exception_injected = 0; ++ env->exception_has_payload = false; ++ env->exception_payload = 0; ++} ++ ++static void kvm_queue_exception(CPUX86State *env, ++ int32_t exception_nr, ++ uint8_t exception_has_payload, ++ uint64_t exception_payload) ++{ ++ assert(env->exception_nr == -1); ++ assert(!env->exception_pending); ++ assert(!env->exception_injected); ++ assert(!env->exception_has_payload); ++ ++ env->exception_nr = exception_nr; ++ ++ if (has_exception_payload) { ++ env->exception_pending = 1; ++ ++ env->exception_has_payload = exception_has_payload; ++ env->exception_payload = exception_payload; ++ } else { ++ env->exception_injected = 1; ++ ++ if (exception_nr == EXCP01_DB) { ++ assert(exception_has_payload); ++ env->dr[6] = exception_payload; ++ } else if (exception_nr == EXCP0E_PAGE) { ++ assert(exception_has_payload); ++ env->cr[2] = exception_payload; ++ } else { ++ assert(!exception_has_payload); ++ } ++ } ++} ++ + static int kvm_inject_mce_oldstyle(X86CPU *cpu) + { + CPUX86State *env = &cpu->env; + +- if (!kvm_has_vcpu_events() && env->exception_injected == EXCP12_MCHK) { ++ if (!kvm_has_vcpu_events() && env->exception_nr == EXCP12_MCHK) { + unsigned int bank, bank_num = env->mcg_cap & 0xff; + struct kvm_x86_mce mce; + +- env->exception_injected = -1; ++ kvm_reset_exception(env); + + /* + * There must be at least one bank in use if an MCE is pending. +@@ -1458,6 +1500,16 @@ int kvm_arch_init(MachineState *ms, KVMState *s) + has_pit_state2 = kvm_check_extension(s, KVM_CAP_PIT_STATE2); + #endif + ++ has_exception_payload = kvm_check_extension(s, KVM_CAP_EXCEPTION_PAYLOAD); ++ if (has_exception_payload) { ++ ret = kvm_vm_enable_cap(s, KVM_CAP_EXCEPTION_PAYLOAD, 0, true); ++ if (ret < 0) { ++ error_report("kvm: Failed to enable exception payload cap: %s", ++ strerror(-ret)); ++ return ret; ++ } ++ } ++ + ret = kvm_get_supported_msrs(s); + if (ret < 0) { + return ret; +@@ -2717,8 +2769,16 @@ static int kvm_put_vcpu_events(X86CPU *cpu, int level) + return 0; + } + +- events.exception.injected = (env->exception_injected >= 0); +- events.exception.nr = env->exception_injected; ++ events.flags = 0; ++ ++ if (has_exception_payload) { ++ events.flags |= KVM_VCPUEVENT_VALID_PAYLOAD; ++ events.exception.pending = env->exception_pending; ++ events.exception_has_payload = env->exception_has_payload; ++ events.exception_payload = env->exception_payload; ++ } ++ events.exception.nr = env->exception_nr; ++ events.exception.injected = env->exception_injected; + events.exception.has_error_code = env->has_error_code; + events.exception.error_code = env->error_code; + +@@ -2731,7 +2791,6 @@ static int kvm_put_vcpu_events(X86CPU *cpu, int level) + events.nmi.masked = !!(env->hflags2 & HF2_NMI_MASK); + + events.sipi_vector = env->sipi_vector; +- events.flags = 0; + + if (has_msr_smbase) { + events.smi.smm = !!(env->hflags & HF_SMM_MASK); +@@ -2781,8 +2840,19 @@ static int kvm_get_vcpu_events(X86CPU *cpu) + if (ret < 0) { + return ret; + } +- env->exception_injected = +- events.exception.injected ? events.exception.nr : -1; ++ ++ if (events.flags & KVM_VCPUEVENT_VALID_PAYLOAD) { ++ env->exception_pending = events.exception.pending; ++ env->exception_has_payload = events.exception_has_payload; ++ env->exception_payload = events.exception_payload; ++ } else { ++ env->exception_pending = 0; ++ env->exception_has_payload = false; ++ } ++ env->exception_injected = events.exception.injected; ++ env->exception_nr = ++ (env->exception_pending || env->exception_injected) ? ++ events.exception.nr : -1; + env->has_error_code = events.exception.has_error_code; + env->error_code = events.exception.error_code; + +@@ -2834,12 +2904,12 @@ static int kvm_guest_debug_workarounds(X86CPU *cpu) + unsigned long reinject_trap = 0; + + if (!kvm_has_vcpu_events()) { +- if (env->exception_injected == EXCP01_DB) { ++ if (env->exception_nr == EXCP01_DB) { + reinject_trap = KVM_GUESTDBG_INJECT_DB; + } else if (env->exception_injected == EXCP03_INT3) { + reinject_trap = KVM_GUESTDBG_INJECT_BP; + } +- env->exception_injected = -1; ++ kvm_reset_exception(env); + } + + /* +@@ -3215,13 +3285,13 @@ int kvm_arch_process_async_events(CPUState *cs) + + kvm_cpu_synchronize_state(cs); + +- if (env->exception_injected == EXCP08_DBLE) { ++ if (env->exception_nr == EXCP08_DBLE) { + /* this means triple fault */ + qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); + cs->exit_request = 1; + return 0; + } +- env->exception_injected = EXCP12_MCHK; ++ kvm_queue_exception(env, EXCP12_MCHK, 0, 0); + env->has_error_code = 0; + + cs->halted = 0; +@@ -3436,14 +3506,13 @@ static int kvm_handle_debug(X86CPU *cpu, + } + if (ret == 0) { + cpu_synchronize_state(cs); +- assert(env->exception_injected == -1); ++ assert(env->exception_nr == -1); + + /* pass to guest */ +- env->exception_injected = arch_info->exception; ++ kvm_queue_exception(env, arch_info->exception, ++ arch_info->exception == EXCP01_DB, ++ arch_info->dr6); + env->has_error_code = 0; +- if (arch_info->exception == EXCP01_DB) { +- env->dr[6] = arch_info->dr6; +- } + } + + return ret; +diff --git a/target/i386/machine.c b/target/i386/machine.c +index a2ddbba..5ffee8f 100644 +--- a/target/i386/machine.c ++++ b/target/i386/machine.c +@@ -239,6 +239,41 @@ static int cpu_pre_save(void *opaque) + } + #endif + ++ /* ++ * When vCPU is running L2 and exception is still pending, ++ * it can potentially be intercepted by L1 hypervisor. ++ * In contrast to an injected exception which cannot be ++ * intercepted anymore. ++ * ++ * Furthermore, when a L2 exception is intercepted by L1 ++ * hypervisor, it's exception payload (CR2/DR6 on #PF/#DB) ++ * should not be set yet in the respective vCPU register. ++ * Thus, in case an exception is pending, it is ++ * important to save the exception payload seperately. ++ * ++ * Therefore, if an exception is not in a pending state ++ * or vCPU is not in guest-mode, it is not important to ++ * distinguish between a pending and injected exception ++ * and we don't need to store seperately the exception payload. ++ * ++ * In order to preserve better backwards-compatabile migration, ++ * convert a pending exception to an injected exception in ++ * case it is not important to distingiush between them ++ * as described above. ++ */ ++ if (env->exception_pending && !(env->hflags & HF_GUEST_MASK)) { ++ env->exception_pending = 0; ++ env->exception_injected = 1; ++ ++ if (env->exception_has_payload) { ++ if (env->exception_nr == EXCP01_DB) { ++ env->dr[6] = env->exception_payload; ++ } else if (env->exception_nr == EXCP0E_PAGE) { ++ env->cr[2] = env->exception_payload; ++ } ++ } ++ } ++ + return 0; + } + +@@ -296,6 +331,23 @@ static int cpu_post_load(void *opaque, int version_id) + } + #endif + ++ /* ++ * There are cases that we can get valid exception_nr with both ++ * exception_pending and exception_injected being cleared. ++ * This can happen in one of the following scenarios: ++ * 1) Source is older QEMU without KVM_CAP_EXCEPTION_PAYLOAD support. ++ * 2) Source is running on kernel without KVM_CAP_EXCEPTION_PAYLOAD support. ++ * 3) "cpu/exception_info" subsection not sent because there is no exception ++ * pending or guest wasn't running L2 (See comment in cpu_pre_save()). ++ * ++ * In those cases, we can just deduce that a valid exception_nr means ++ * we can treat the exception as already injected. ++ */ ++ if ((env->exception_nr != -1) && ++ !env->exception_pending && !env->exception_injected) { ++ env->exception_injected = 1; ++ } ++ + env->fpstt = (env->fpus_vmstate >> 11) & 7; + env->fpus = env->fpus_vmstate & ~0x3800; + env->fptag_vmstate ^= 0xff; +@@ -341,6 +393,35 @@ static bool steal_time_msr_needed(void *opaque) + return cpu->env.steal_time_msr != 0; + } + ++static bool exception_info_needed(void *opaque) ++{ ++ X86CPU *cpu = opaque; ++ CPUX86State *env = &cpu->env; ++ ++ /* ++ * It is important to save exception-info only in case ++ * we need to distingiush between a pending and injected ++ * exception. Which is only required in case there is a ++ * pending exception and vCPU is running L2. ++ * For more info, refer to comment in cpu_pre_save(). ++ */ ++ return env->exception_pending && (env->hflags & HF_GUEST_MASK); ++} ++ ++static const VMStateDescription vmstate_exception_info = { ++ .name = "cpu/exception_info", ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .needed = exception_info_needed, ++ .fields = (VMStateField[]) { ++ VMSTATE_UINT8(env.exception_pending, X86CPU), ++ VMSTATE_UINT8(env.exception_injected, X86CPU), ++ VMSTATE_UINT8(env.exception_has_payload, X86CPU), ++ VMSTATE_UINT64(env.exception_payload, X86CPU), ++ VMSTATE_END_OF_LIST() ++ } ++}; ++ + static const VMStateDescription vmstate_steal_time_msr = { + .name = "cpu/steal_time_msr", + .version_id = 1, +@@ -1219,7 +1300,7 @@ VMStateDescription vmstate_x86_cpu = { + VMSTATE_INT32(env.interrupt_injected, X86CPU), + VMSTATE_UINT32(env.mp_state, X86CPU), + VMSTATE_UINT64(env.tsc, X86CPU), +- VMSTATE_INT32(env.exception_injected, X86CPU), ++ VMSTATE_INT32(env.exception_nr, X86CPU), + VMSTATE_UINT8(env.soft_interrupt, X86CPU), + VMSTATE_UINT8(env.nmi_injected, X86CPU), + VMSTATE_UINT8(env.nmi_pending, X86CPU), +@@ -1243,6 +1324,7 @@ VMStateDescription vmstate_x86_cpu = { + /* The above list is not sorted /wrt version numbers, watch out! */ + }, + .subsections = (const VMStateDescription*[]) { ++ &vmstate_exception_info, + &vmstate_async_pf_msr, + &vmstate_pv_eoi_msr, + &vmstate_steal_time_msr, +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-kvm-Add-support-for-save-and-restore-nes.patch b/SOURCES/kvm-target-i386-kvm-Add-support-for-save-and-restore-nes.patch new file mode 100644 index 0000000..176b679 --- /dev/null +++ b/SOURCES/kvm-target-i386-kvm-Add-support-for-save-and-restore-nes.patch @@ -0,0 +1,464 @@ +From 0a1fd178d9b7c054d229b60540b7d12d87eb8070 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 22 Jul 2019 18:22:15 +0100 +Subject: [PATCH 34/39] target/i386: kvm: Add support for save and restore + nested state + +RH-Author: Paolo Bonzini +Message-id: <20190722182220.19374-14-pbonzini@redhat.com> +Patchwork-id: 89629 +O-Subject: [RHEL-8.1.0 PATCH qemu-kvm v3 13/18] target/i386: kvm: Add support for save and restore nested state +Bugzilla: 1689269 +RH-Acked-by: Peter Xu +RH-Acked-by: Laurent Vivier +RH-Acked-by: Dr. David Alan Gilbert + +From: Liran Alon + +Kernel commit 8fcc4b5923af ("kvm: nVMX: Introduce KVM_CAP_NESTED_STATE") +introduced new IOCTLs to extract and restore vCPU state related to +Intel VMX & AMD SVM. + +Utilize these IOCTLs to add support for migration of VMs which are +running nested hypervisors. + +Reviewed-by: Nikita Leshenko +Reviewed-by: Maran Wilson +Tested-by: Maran Wilson +Signed-off-by: Liran Alon +Message-Id: <20190619162140.133674-9-liran.alon@oracle.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit ebbfef2f34cfc749c045a4569dedb4f748ec024a) +Signed-off-by: Danilo C. L. de Paula +--- + accel/kvm/kvm-all.c | 8 ++ + include/sysemu/kvm.h | 1 + + target/i386/cpu.h | 3 + + target/i386/kvm.c | 80 ++++++++++++++++++++ + target/i386/machine.c | 198 ++++++++++++++++++++++++++++++++++++++++++++++++++ + 5 files changed, 290 insertions(+) + +diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c +index a939b26..2130fcb 100644 +--- a/accel/kvm/kvm-all.c ++++ b/accel/kvm/kvm-all.c +@@ -87,6 +87,7 @@ struct KVMState + #ifdef KVM_CAP_SET_GUEST_DEBUG + struct kvm_sw_breakpoint_head kvm_sw_breakpoints; + #endif ++ int max_nested_state_len; + int many_ioeventfds; + int intx_set_mask; + bool sync_mmu; +@@ -1646,6 +1647,8 @@ static int kvm_init(MachineState *ms) + s->debugregs = kvm_check_extension(s, KVM_CAP_DEBUGREGS); + #endif + ++ s->max_nested_state_len = kvm_check_extension(s, KVM_CAP_NESTED_STATE); ++ + #ifdef KVM_CAP_IRQ_ROUTING + kvm_direct_msi_allowed = (kvm_check_extension(s, KVM_CAP_SIGNAL_MSI) > 0); + #endif +@@ -2207,6 +2210,11 @@ int kvm_has_debugregs(void) + return kvm_state->debugregs; + } + ++int kvm_max_nested_state_length(void) ++{ ++ return kvm_state->max_nested_state_len; ++} ++ + int kvm_has_many_ioeventfds(void) + { + if (!kvm_enabled()) { +diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h +index a5a6dff..3cf04cf 100644 +--- a/include/sysemu/kvm.h ++++ b/include/sysemu/kvm.h +@@ -211,6 +211,7 @@ bool kvm_has_sync_mmu(void); + int kvm_has_vcpu_events(void); + int kvm_has_robust_singlestep(void); + int kvm_has_debugregs(void); ++int kvm_max_nested_state_length(void); + int kvm_has_pit_state2(void); + int kvm_has_many_ioeventfds(void); + int kvm_has_gsi_routing(void); +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index f595fc3..86f3d98 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -1335,6 +1335,9 @@ typedef struct CPUX86State { + int64_t tsc_khz; + int64_t user_tsc_khz; /* for sanity check only */ + void *kvm_xsave_buf; ++#if defined(CONFIG_KVM) ++ struct kvm_nested_state *nested_state; ++#endif + #if defined(CONFIG_HVF) + HVFX86EmulatorState *hvf_emul; + #endif +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index 8a6da90..ddceb7d 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -789,6 +789,7 @@ int kvm_arch_init_vcpu(CPUState *cs) + struct kvm_cpuid_entry2 *c; + uint32_t signature[3]; + int kvm_base = KVM_CPUID_SIGNATURE; ++ int max_nested_state_len; + int r; + Error *local_err = NULL; + +@@ -1180,6 +1181,24 @@ int kvm_arch_init_vcpu(CPUState *cs) + if (has_xsave) { + env->kvm_xsave_buf = qemu_memalign(4096, sizeof(struct kvm_xsave)); + } ++ ++ max_nested_state_len = kvm_max_nested_state_length(); ++ if (max_nested_state_len > 0) { ++ assert(max_nested_state_len >= offsetof(struct kvm_nested_state, data)); ++ env->nested_state = g_malloc0(max_nested_state_len); ++ ++ env->nested_state->size = max_nested_state_len; ++ ++ if (IS_INTEL_CPU(env)) { ++ struct kvm_vmx_nested_state_hdr *vmx_hdr = ++ &env->nested_state->hdr.vmx; ++ ++ env->nested_state->format = KVM_STATE_NESTED_FORMAT_VMX; ++ vmx_hdr->vmxon_pa = -1ull; ++ vmx_hdr->vmcs12_pa = -1ull; ++ } ++ } ++ + cpu->kvm_msr_buf = g_malloc0(MSR_BUF_SIZE); + + if (!(env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_RDTSCP)) { +@@ -1199,12 +1218,18 @@ int kvm_arch_init_vcpu(CPUState *cs) + int kvm_arch_destroy_vcpu(CPUState *cs) + { + X86CPU *cpu = X86_CPU(cs); ++ CPUX86State *env = &cpu->env; + + if (cpu->kvm_msr_buf) { + g_free(cpu->kvm_msr_buf); + cpu->kvm_msr_buf = NULL; + } + ++ if (env->nested_state) { ++ g_free(env->nested_state); ++ env->nested_state = NULL; ++ } ++ + return 0; + } + +@@ -2875,6 +2900,52 @@ static int kvm_get_debugregs(X86CPU *cpu) + return 0; + } + ++static int kvm_put_nested_state(X86CPU *cpu) ++{ ++ CPUX86State *env = &cpu->env; ++ int max_nested_state_len = kvm_max_nested_state_length(); ++ ++ if (max_nested_state_len <= 0) { ++ return 0; ++ } ++ ++ assert(env->nested_state->size <= max_nested_state_len); ++ return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_NESTED_STATE, env->nested_state); ++} ++ ++static int kvm_get_nested_state(X86CPU *cpu) ++{ ++ CPUX86State *env = &cpu->env; ++ int max_nested_state_len = kvm_max_nested_state_length(); ++ int ret; ++ ++ if (max_nested_state_len <= 0) { ++ return 0; ++ } ++ ++ /* ++ * It is possible that migration restored a smaller size into ++ * nested_state->hdr.size than what our kernel support. ++ * We preserve migration origin nested_state->hdr.size for ++ * call to KVM_SET_NESTED_STATE but wish that our next call ++ * to KVM_GET_NESTED_STATE will use max size our kernel support. ++ */ ++ env->nested_state->size = max_nested_state_len; ++ ++ ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_NESTED_STATE, env->nested_state); ++ if (ret < 0) { ++ return ret; ++ } ++ ++ if (env->nested_state->flags & KVM_STATE_NESTED_GUEST_MODE) { ++ env->hflags |= HF_GUEST_MASK; ++ } else { ++ env->hflags &= ~HF_GUEST_MASK; ++ } ++ ++ return ret; ++} ++ + int kvm_arch_put_registers(CPUState *cpu, int level) + { + X86CPU *x86_cpu = X86_CPU(cpu); +@@ -2882,6 +2953,11 @@ int kvm_arch_put_registers(CPUState *cpu, int level) + + assert(cpu_is_stopped(cpu) || qemu_cpu_is_self(cpu)); + ++ ret = kvm_put_nested_state(x86_cpu); ++ if (ret < 0) { ++ return ret; ++ } ++ + if (level >= KVM_PUT_RESET_STATE) { + ret = kvm_put_msr_feature_control(x86_cpu); + if (ret < 0) { +@@ -2997,6 +3073,10 @@ int kvm_arch_get_registers(CPUState *cs) + if (ret < 0) { + goto out; + } ++ ret = kvm_get_nested_state(cpu); ++ if (ret < 0) { ++ goto out; ++ } + ret = 0; + out: + cpu_sync_bndcs_hflags(&cpu->env); +diff --git a/target/i386/machine.c b/target/i386/machine.c +index 561d4a5..a2ddbba 100644 +--- a/target/i386/machine.c ++++ b/target/i386/machine.c +@@ -230,6 +230,15 @@ static int cpu_pre_save(void *opaque) + env->segs[R_SS].flags &= ~(env->segs[R_SS].flags & DESC_DPL_MASK); + } + ++#ifdef CONFIG_KVM ++ /* Verify we have nested virtualization state from kernel if required */ ++ if (kvm_enabled() && cpu_has_vmx(env) && !env->nested_state) { ++ error_report("Guest enabled nested virtualization but kernel " ++ "does not support saving of nested state"); ++ return -EINVAL; ++ } ++#endif ++ + return 0; + } + +@@ -277,6 +286,16 @@ static int cpu_post_load(void *opaque, int version_id) + env->hflags &= ~HF_CPL_MASK; + env->hflags |= (env->segs[R_SS].flags >> DESC_DPL_SHIFT) & HF_CPL_MASK; + ++#ifdef CONFIG_KVM ++ if ((env->hflags & HF_GUEST_MASK) && ++ (!env->nested_state || ++ !(env->nested_state->flags & KVM_STATE_NESTED_GUEST_MODE))) { ++ error_report("vCPU set in guest-mode inconsistent with " ++ "migrated kernel nested state"); ++ return -EINVAL; ++ } ++#endif ++ + env->fpstt = (env->fpus_vmstate >> 11) & 7; + env->fpus = env->fpus_vmstate & ~0x3800; + env->fptag_vmstate ^= 0xff; +@@ -819,6 +838,182 @@ static const VMStateDescription vmstate_tsc_khz = { + } + }; + ++#ifdef CONFIG_KVM ++ ++static bool vmx_vmcs12_needed(void *opaque) ++{ ++ struct kvm_nested_state *nested_state = opaque; ++ return (nested_state->size > ++ offsetof(struct kvm_nested_state, data.vmx[0].vmcs12)); ++} ++ ++static const VMStateDescription vmstate_vmx_vmcs12 = { ++ .name = "cpu/kvm_nested_state/vmx/vmcs12", ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .needed = vmx_vmcs12_needed, ++ .fields = (VMStateField[]) { ++ VMSTATE_UINT8_ARRAY(data.vmx[0].vmcs12, ++ struct kvm_nested_state, ++ KVM_STATE_NESTED_VMX_VMCS_SIZE), ++ VMSTATE_END_OF_LIST() ++ } ++}; ++ ++static bool vmx_shadow_vmcs12_needed(void *opaque) ++{ ++ struct kvm_nested_state *nested_state = opaque; ++ return (nested_state->size > ++ offsetof(struct kvm_nested_state, data.vmx[0].shadow_vmcs12)); ++} ++ ++static const VMStateDescription vmstate_vmx_shadow_vmcs12 = { ++ .name = "cpu/kvm_nested_state/vmx/shadow_vmcs12", ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .needed = vmx_shadow_vmcs12_needed, ++ .fields = (VMStateField[]) { ++ VMSTATE_UINT8_ARRAY(data.vmx[0].shadow_vmcs12, ++ struct kvm_nested_state, ++ KVM_STATE_NESTED_VMX_VMCS_SIZE), ++ VMSTATE_END_OF_LIST() ++ } ++}; ++ ++static bool vmx_nested_state_needed(void *opaque) ++{ ++ struct kvm_nested_state *nested_state = opaque; ++ ++ return ((nested_state->format == KVM_STATE_NESTED_FORMAT_VMX) && ++ ((nested_state->hdr.vmx.vmxon_pa != -1ull) || ++ (nested_state->hdr.vmx.smm.flags & KVM_STATE_NESTED_SMM_VMXON))); ++} ++ ++static const VMStateDescription vmstate_vmx_nested_state = { ++ .name = "cpu/kvm_nested_state/vmx", ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .needed = vmx_nested_state_needed, ++ .fields = (VMStateField[]) { ++ VMSTATE_U64(hdr.vmx.vmxon_pa, struct kvm_nested_state), ++ VMSTATE_U64(hdr.vmx.vmcs12_pa, struct kvm_nested_state), ++ VMSTATE_U16(hdr.vmx.smm.flags, struct kvm_nested_state), ++ VMSTATE_END_OF_LIST() ++ }, ++ .subsections = (const VMStateDescription*[]) { ++ &vmstate_vmx_vmcs12, ++ &vmstate_vmx_shadow_vmcs12, ++ NULL, ++ } ++}; ++ ++static bool svm_nested_state_needed(void *opaque) ++{ ++ struct kvm_nested_state *nested_state = opaque; ++ ++ return (nested_state->format == KVM_STATE_NESTED_FORMAT_SVM); ++} ++ ++static const VMStateDescription vmstate_svm_nested_state = { ++ .name = "cpu/kvm_nested_state/svm", ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .needed = svm_nested_state_needed, ++ .fields = (VMStateField[]) { ++ VMSTATE_END_OF_LIST() ++ } ++}; ++ ++static bool nested_state_needed(void *opaque) ++{ ++ X86CPU *cpu = opaque; ++ CPUX86State *env = &cpu->env; ++ ++ return (env->nested_state && ++ (vmx_nested_state_needed(env->nested_state) || ++ svm_nested_state_needed(env->nested_state))); ++} ++ ++static int nested_state_post_load(void *opaque, int version_id) ++{ ++ X86CPU *cpu = opaque; ++ CPUX86State *env = &cpu->env; ++ struct kvm_nested_state *nested_state = env->nested_state; ++ int min_nested_state_len = offsetof(struct kvm_nested_state, data); ++ int max_nested_state_len = kvm_max_nested_state_length(); ++ ++ /* ++ * If our kernel don't support setting nested state ++ * and we have received nested state from migration stream, ++ * we need to fail migration ++ */ ++ if (max_nested_state_len <= 0) { ++ error_report("Received nested state when kernel cannot restore it"); ++ return -EINVAL; ++ } ++ ++ /* ++ * Verify that the size of received nested_state struct ++ * at least cover required header and is not larger ++ * than the max size that our kernel support ++ */ ++ if (nested_state->size < min_nested_state_len) { ++ error_report("Received nested state size less than min: " ++ "len=%d, min=%d", ++ nested_state->size, min_nested_state_len); ++ return -EINVAL; ++ } ++ if (nested_state->size > max_nested_state_len) { ++ error_report("Recieved unsupported nested state size: " ++ "nested_state->size=%d, max=%d", ++ nested_state->size, max_nested_state_len); ++ return -EINVAL; ++ } ++ ++ /* Verify format is valid */ ++ if ((nested_state->format != KVM_STATE_NESTED_FORMAT_VMX) && ++ (nested_state->format != KVM_STATE_NESTED_FORMAT_SVM)) { ++ error_report("Received invalid nested state format: %d", ++ nested_state->format); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static const VMStateDescription vmstate_kvm_nested_state = { ++ .name = "cpu/kvm_nested_state", ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .fields = (VMStateField[]) { ++ VMSTATE_U16(flags, struct kvm_nested_state), ++ VMSTATE_U16(format, struct kvm_nested_state), ++ VMSTATE_U32(size, struct kvm_nested_state), ++ VMSTATE_END_OF_LIST() ++ }, ++ .subsections = (const VMStateDescription*[]) { ++ &vmstate_vmx_nested_state, ++ &vmstate_svm_nested_state, ++ NULL ++ } ++}; ++ ++static const VMStateDescription vmstate_nested_state = { ++ .name = "cpu/nested_state", ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .needed = nested_state_needed, ++ .post_load = nested_state_post_load, ++ .fields = (VMStateField[]) { ++ VMSTATE_STRUCT_POINTER(env.nested_state, X86CPU, ++ vmstate_kvm_nested_state, ++ struct kvm_nested_state), ++ VMSTATE_END_OF_LIST() ++ } ++}; ++ ++#endif ++ + static bool mcg_ext_ctl_needed(void *opaque) + { + X86CPU *cpu = opaque; +@@ -1080,6 +1275,9 @@ VMStateDescription vmstate_x86_cpu = { + #ifndef TARGET_X86_64 + &vmstate_efer32, + #endif ++#ifdef CONFIG_KVM ++ &vmstate_nested_state, ++#endif + NULL + } + }; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-kvm-Block-migration-for-vCPUs-exposed-wi.patch b/SOURCES/kvm-target-i386-kvm-Block-migration-for-vCPUs-exposed-wi.patch new file mode 100644 index 0000000..c4e9269 --- /dev/null +++ b/SOURCES/kvm-target-i386-kvm-Block-migration-for-vCPUs-exposed-wi.patch @@ -0,0 +1,130 @@ +From 0d5048785d6edd2fee3b22aa6901e55539e07525 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 22 Jul 2019 18:22:11 +0100 +Subject: [PATCH 30/39] target/i386: kvm: Block migration for vCPUs exposed + with nested virtualization + +RH-Author: Paolo Bonzini +Message-id: <20190722182220.19374-10-pbonzini@redhat.com> +Patchwork-id: 89633 +O-Subject: [RHEL-8.1.0 PATCH qemu-kvm v3 09/18] target/i386: kvm: Block migration for vCPUs exposed with nested virtualization +Bugzilla: 1689269 +RH-Acked-by: Peter Xu +RH-Acked-by: Laurent Vivier +RH-Acked-by: Dr. David Alan Gilbert + +From: Liran Alon + +Commit d98f26073beb ("target/i386: kvm: add VMX migration blocker") +added a migration blocker for vCPU exposed with Intel VMX. +However, migration should also be blocked for vCPU exposed with +AMD SVM. + +Both cases should be blocked because QEMU should extract additional +vCPU state from KVM that should be migrated as part of vCPU VMState. +E.g. Whether vCPU is running in guest-mode or host-mode. + +Fixes: d98f26073beb ("target/i386: kvm: add VMX migration blocker") +Reviewed-by: Maran Wilson +Signed-off-by: Liran Alon +Message-Id: <20190619162140.133674-6-liran.alon@oracle.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit 18ab37ba1cee290923240744288dbee8be9355fb) +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 6 ------ + target/i386/cpu.h | 12 ++++++++++++ + target/i386/kvm.c | 14 +++++++------- + 3 files changed, 19 insertions(+), 13 deletions(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index af62281..bd0b784 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -5034,12 +5034,6 @@ static int x86_cpu_filter_features(X86CPU *cpu) + return rv; + } + +-#define IS_INTEL_CPU(env) ((env)->cpuid_vendor1 == CPUID_VENDOR_INTEL_1 && \ +- (env)->cpuid_vendor2 == CPUID_VENDOR_INTEL_2 && \ +- (env)->cpuid_vendor3 == CPUID_VENDOR_INTEL_3) +-#define IS_AMD_CPU(env) ((env)->cpuid_vendor1 == CPUID_VENDOR_AMD_1 && \ +- (env)->cpuid_vendor2 == CPUID_VENDOR_AMD_2 && \ +- (env)->cpuid_vendor3 == CPUID_VENDOR_AMD_3) + static void x86_cpu_realizefn(DeviceState *dev, Error **errp) + { + CPUState *cs = CPU(dev); +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index 923dfcd..f595fc3 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -722,6 +722,13 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS]; + + #define CPUID_VENDOR_VIA "CentaurHauls" + ++#define IS_INTEL_CPU(env) ((env)->cpuid_vendor1 == CPUID_VENDOR_INTEL_1 && \ ++ (env)->cpuid_vendor2 == CPUID_VENDOR_INTEL_2 && \ ++ (env)->cpuid_vendor3 == CPUID_VENDOR_INTEL_3) ++#define IS_AMD_CPU(env) ((env)->cpuid_vendor1 == CPUID_VENDOR_AMD_1 && \ ++ (env)->cpuid_vendor2 == CPUID_VENDOR_AMD_2 && \ ++ (env)->cpuid_vendor3 == CPUID_VENDOR_AMD_3) ++ + #define CPUID_MWAIT_IBE (1U << 1) /* Interrupts can exit capability */ + #define CPUID_MWAIT_EMX (1U << 0) /* enumeration supported */ + +@@ -1829,6 +1836,11 @@ static inline int32_t x86_get_a20_mask(CPUX86State *env) + } + } + ++static inline bool cpu_has_vmx(CPUX86State *env) ++{ ++ return env->features[FEAT_1_ECX] & CPUID_EXT_VMX; ++} ++ + /* fpu_helper.c */ + void update_fp_status(CPUX86State *env); + void update_mxcsr_status(CPUX86State *env); +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index 1a4ff3c..f741e8b 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -772,7 +772,7 @@ static int hyperv_handle_properties(CPUState *cs) + } + + static Error *invtsc_mig_blocker; +-static Error *vmx_mig_blocker; ++static Error *nested_virt_mig_blocker; + + #define KVM_MAX_CPUID_ENTRIES 100 + +@@ -1116,13 +1116,13 @@ int kvm_arch_init_vcpu(CPUState *cs) + !!(c->ecx & CPUID_EXT_SMX); + } + +- if ((env->features[FEAT_1_ECX] & CPUID_EXT_VMX) && !vmx_mig_blocker) { +- error_setg(&vmx_mig_blocker, +- "Nested VMX virtualization does not support live migration yet"); +- r = migrate_add_blocker(vmx_mig_blocker, &local_err); ++ if (cpu_has_vmx(env) && !nested_virt_mig_blocker) { ++ error_setg(&nested_virt_mig_blocker, ++ "Nested virtualization does not support live migration yet"); ++ r = migrate_add_blocker(nested_virt_mig_blocker, &local_err); + if (local_err) { + error_report_err(local_err); +- error_free(vmx_mig_blocker); ++ error_free(nested_virt_mig_blocker); + return r; + } + } +@@ -1191,7 +1191,7 @@ int kvm_arch_init_vcpu(CPUState *cs) + fail: + migrate_del_blocker(invtsc_mig_blocker); + fail2: +- migrate_del_blocker(vmx_mig_blocker); ++ migrate_del_blocker(nested_virt_mig_blocker); + + return r; + } +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-kvm-Delete-VMX-migration-blocker-on-vCPU.patch b/SOURCES/kvm-target-i386-kvm-Delete-VMX-migration-blocker-on-vCPU.patch new file mode 100644 index 0000000..215a425 --- /dev/null +++ b/SOURCES/kvm-target-i386-kvm-Delete-VMX-migration-blocker-on-vCPU.patch @@ -0,0 +1,72 @@ +From 9cf495aabeeaf4fdccae83d748a70936e3bf26ab Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 22 Jul 2019 18:22:07 +0100 +Subject: [PATCH 26/39] target/i386: kvm: Delete VMX migration blocker on vCPU + init failure + +RH-Author: Paolo Bonzini +Message-id: <20190722182220.19374-6-pbonzini@redhat.com> +Patchwork-id: 89624 +O-Subject: [RHEL-8.1.0 PATCH qemu-kvm v3 05/18] target/i386: kvm: Delete VMX migration blocker on vCPU init failure +Bugzilla: 1689269 +RH-Acked-by: Peter Xu +RH-Acked-by: Laurent Vivier +RH-Acked-by: Dr. David Alan Gilbert + +From: Liran Alon + +Commit d98f26073beb ("target/i386: kvm: add VMX migration blocker") +added migration blocker for vCPU exposed with Intel VMX because QEMU +doesn't yet contain code to support migration of nested virtualization +workloads. + +However, that commit missed adding deletion of the migration blocker in +case init of vCPU failed. Similar to invtsc_mig_blocker. This commit fix +that issue. + +Fixes: d98f26073beb ("target/i386: kvm: add VMX migration blocker") +Signed-off-by: Liran Alon +Reviewed-by: Maran Wilson +Message-Id: <20190619162140.133674-2-liran.alon@oracle.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit 6b2341eeea43c00b8e266026cec84d57af1484dc) +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/kvm.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index 875412c..8e861a1 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -798,7 +798,7 @@ int kvm_arch_init_vcpu(CPUState *cs) + + r = kvm_arch_set_tsc_khz(cs); + if (r < 0) { +- goto fail; ++ return r; + } + + /* vcpu's TSC frequency is either specified by user, or following +@@ -1142,7 +1142,7 @@ int kvm_arch_init_vcpu(CPUState *cs) + if (local_err) { + error_report_err(local_err); + error_free(invtsc_mig_blocker); +- return r; ++ goto fail2; + } + /* for savevm */ + vmstate_x86_cpu.unmigratable = 1; +@@ -1190,6 +1190,9 @@ int kvm_arch_init_vcpu(CPUState *cs) + + fail: + migrate_del_blocker(invtsc_mig_blocker); ++ fail2: ++ migrate_del_blocker(vmx_mig_blocker); ++ + return r; + } + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-kvm-Demand-nested-migration-kernel-capab.patch b/SOURCES/kvm-target-i386-kvm-Demand-nested-migration-kernel-capab.patch new file mode 100644 index 0000000..07ddbfd --- /dev/null +++ b/SOURCES/kvm-target-i386-kvm-Demand-nested-migration-kernel-capab.patch @@ -0,0 +1,217 @@ +From 2427e21de274cf7b56ef79e4a7ba78a08def7a58 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 22 Jul 2019 18:22:18 +0100 +Subject: [PATCH 37/39] target/i386: kvm: Demand nested migration kernel + capabilities only when vCPU may have enabled VMX + +RH-Author: Paolo Bonzini +Message-id: <20190722182220.19374-17-pbonzini@redhat.com> +Patchwork-id: 89634 +O-Subject: [RHEL-8.1.0 PATCH qemu-kvm v3 16/18] target/i386: kvm: Demand nested migration kernel capabilities only when vCPU may have enabled VMX +Bugzilla: 1689269 +RH-Acked-by: Peter Xu +RH-Acked-by: Laurent Vivier +RH-Acked-by: Dr. David Alan Gilbert + +From: Liran Alon + +Previous to this change, a vCPU exposed with VMX running on a kernel +without KVM_CAP_NESTED_STATE or KVM_CAP_EXCEPTION_PAYLOAD resulted in +adding a migration blocker. This was because when the code was written +it was thought there is no way to reliably know if a vCPU is utilising +VMX or not at runtime. However, it turns out that this can be known to +some extent: + +In order for a vCPU to enter VMX operation it must have CR4.VMXE set. +Since it was set, CR4.VMXE must remain set as long as the vCPU is in +VMX operation. This is because CR4.VMXE is one of the bits set +in MSR_IA32_VMX_CR4_FIXED1. +There is one exception to the above statement when vCPU enters SMM mode. +When a vCPU enters SMM mode, it temporarily exits VMX operation and +may also reset CR4.VMXE during execution in SMM mode. +When the vCPU exits SMM mode, vCPU state is restored to be in VMX operation +and CR4.VMXE is restored to its original state of being set. +Therefore, when the vCPU is not in SMM mode, we can infer whether +VMX is being used by examining CR4.VMXE. Otherwise, we cannot +know for certain but assume the worse that vCPU may utilise VMX. + +Summaring all the above, a vCPU may have enabled VMX in case +CR4.VMXE is set or vCPU is in SMM mode. + +Therefore, remove migration blocker and check before migration +(cpu_pre_save()) if the vCPU may have enabled VMX. If true, only then +require relevant kernel capabilities. + +While at it, demand KVM_CAP_EXCEPTION_PAYLOAD only when the vCPU is in +guest-mode and there is a pending/injected exception. Otherwise, this +kernel capability is not required for proper migration. + +Reviewed-by: Joao Martins +Signed-off-by: Liran Alon +Reviewed-by: Maran Wilson +Tested-by: Maran Wilson +Signed-off-by: Paolo Bonzini +(cherry picked from commit 79a197ab180e75838523c58973b1221ad7bf51eb) +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.h | 22 ++++++++++++++++++++++ + target/i386/kvm.c | 26 ++++++-------------------- + target/i386/kvm_i386.h | 1 + + target/i386/machine.c | 24 ++++++++++++++++++++---- + 4 files changed, 49 insertions(+), 24 deletions(-) + +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index d120f62..273c90b 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -1848,6 +1848,28 @@ static inline bool cpu_has_vmx(CPUX86State *env) + return env->features[FEAT_1_ECX] & CPUID_EXT_VMX; + } + ++/* ++ * In order for a vCPU to enter VMX operation it must have CR4.VMXE set. ++ * Since it was set, CR4.VMXE must remain set as long as vCPU is in ++ * VMX operation. This is because CR4.VMXE is one of the bits set ++ * in MSR_IA32_VMX_CR4_FIXED1. ++ * ++ * There is one exception to above statement when vCPU enters SMM mode. ++ * When a vCPU enters SMM mode, it temporarily exit VMX operation and ++ * may also reset CR4.VMXE during execution in SMM mode. ++ * When vCPU exits SMM mode, vCPU state is restored to be in VMX operation ++ * and CR4.VMXE is restored to it's original value of being set. ++ * ++ * Therefore, when vCPU is not in SMM mode, we can infer whether ++ * VMX is being used by examining CR4.VMXE. Otherwise, we cannot ++ * know for certain. ++ */ ++static inline bool cpu_vmx_maybe_enabled(CPUX86State *env) ++{ ++ return cpu_has_vmx(env) && ++ ((env->cr[4] & CR4_VMXE_MASK) || (env->hflags & HF_SMM_MASK)); ++} ++ + /* fpu_helper.c */ + void update_fp_status(CPUX86State *env); + void update_mxcsr_status(CPUX86State *env); +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index 0619aba..0bd286e 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -127,6 +127,11 @@ bool kvm_has_adjust_clock_stable(void) + return (ret == KVM_CLOCK_TSC_STABLE); + } + ++bool kvm_has_exception_payload(void) ++{ ++ return has_exception_payload; ++} ++ + bool kvm_allows_irq0_override(void) + { + return !kvm_irqchip_in_kernel() || kvm_has_gsi_routing(); +@@ -814,7 +819,6 @@ static int hyperv_handle_properties(CPUState *cs) + } + + static Error *invtsc_mig_blocker; +-static Error *nested_virt_mig_blocker; + + #define KVM_MAX_CPUID_ENTRIES 100 + +@@ -1159,22 +1163,6 @@ int kvm_arch_init_vcpu(CPUState *cs) + !!(c->ecx & CPUID_EXT_SMX); + } + +- if (cpu_has_vmx(env) && !nested_virt_mig_blocker && +- ((kvm_max_nested_state_length() <= 0) || !has_exception_payload)) { +- error_setg(&nested_virt_mig_blocker, +- "Kernel do not provide required capabilities for " +- "nested virtualization migration. " +- "(CAP_NESTED_STATE=%d, CAP_EXCEPTION_PAYLOAD=%d)", +- kvm_max_nested_state_length() > 0, +- has_exception_payload); +- r = migrate_add_blocker(nested_virt_mig_blocker, &local_err); +- if (local_err) { +- error_report_err(local_err); +- error_free(nested_virt_mig_blocker); +- return r; +- } +- } +- + if (env->mcg_cap & MCG_LMCE_P) { + has_msr_mcg_ext_ctl = has_msr_feature_control = true; + } +@@ -1190,7 +1178,7 @@ int kvm_arch_init_vcpu(CPUState *cs) + if (local_err) { + error_report_err(local_err); + error_free(invtsc_mig_blocker); +- goto fail2; ++ return r; + } + /* for savevm */ + vmstate_x86_cpu.unmigratable = 1; +@@ -1256,8 +1244,6 @@ int kvm_arch_init_vcpu(CPUState *cs) + + fail: + migrate_del_blocker(invtsc_mig_blocker); +- fail2: +- migrate_del_blocker(nested_virt_mig_blocker); + + return r; + } +diff --git a/target/i386/kvm_i386.h b/target/i386/kvm_i386.h +index 1de9876..df9bbf3 100644 +--- a/target/i386/kvm_i386.h ++++ b/target/i386/kvm_i386.h +@@ -41,6 +41,7 @@ + bool kvm_allows_irq0_override(void); + bool kvm_has_smm(void); + bool kvm_has_adjust_clock_stable(void); ++bool kvm_has_exception_payload(void); + void kvm_synchronize_all_tsc(void); + void kvm_arch_reset_vcpu(X86CPU *cs); + void kvm_arch_do_init_vcpu(X86CPU *cs); +diff --git a/target/i386/machine.c b/target/i386/machine.c +index 5ffee8f..8d90d98 100644 +--- a/target/i386/machine.c ++++ b/target/i386/machine.c +@@ -7,6 +7,7 @@ + #include "hw/i386/pc.h" + #include "hw/isa/isa.h" + #include "migration/cpu.h" ++#include "kvm_i386.h" + + #include "sysemu/kvm.h" + +@@ -231,10 +232,25 @@ static int cpu_pre_save(void *opaque) + } + + #ifdef CONFIG_KVM +- /* Verify we have nested virtualization state from kernel if required */ +- if (kvm_enabled() && cpu_has_vmx(env) && !env->nested_state) { +- error_report("Guest enabled nested virtualization but kernel " +- "does not support saving of nested state"); ++ /* ++ * In case vCPU may have enabled VMX, we need to make sure kernel have ++ * required capabilities in order to perform migration correctly: ++ * ++ * 1) We must be able to extract vCPU nested-state from KVM. ++ * ++ * 2) In case vCPU is running in guest-mode and it has a pending exception, ++ * we must be able to determine if it's in a pending or injected state. ++ * Note that in case KVM don't have required capability to do so, ++ * a pending/injected exception will always appear as an ++ * injected exception. ++ */ ++ if (kvm_enabled() && cpu_vmx_maybe_enabled(env) && ++ (!env->nested_state || ++ (!kvm_has_exception_payload() && (env->hflags & HF_GUEST_MASK) && ++ env->exception_injected))) { ++ error_report("Guest maybe enabled nested virtualization but kernel " ++ "does not support required capabilities to save vCPU " ++ "nested state"); + return -EINVAL; + } + #endif +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-kvm-Re-inject-DB-to-guest-with-updated-D.patch b/SOURCES/kvm-target-i386-kvm-Re-inject-DB-to-guest-with-updated-D.patch new file mode 100644 index 0000000..adb30cb --- /dev/null +++ b/SOURCES/kvm-target-i386-kvm-Re-inject-DB-to-guest-with-updated-D.patch @@ -0,0 +1,66 @@ +From c31315e765df0137cb7dfedb3869db72d6d2ca57 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 22 Jul 2019 18:22:10 +0100 +Subject: [PATCH 29/39] target/i386: kvm: Re-inject #DB to guest with updated + DR6 + +RH-Author: Paolo Bonzini +Message-id: <20190722182220.19374-9-pbonzini@redhat.com> +Patchwork-id: 89626 +O-Subject: [RHEL-8.1.0 PATCH qemu-kvm v3 08/18] target/i386: kvm: Re-inject #DB to guest with updated DR6 +Bugzilla: 1689269 +RH-Acked-by: Peter Xu +RH-Acked-by: Laurent Vivier +RH-Acked-by: Dr. David Alan Gilbert + +From: Liran Alon + +If userspace (QEMU) debug guest, when #DB is raised in guest and +intercepted by KVM, KVM forwards information on #DB to userspace +instead of injecting #DB to guest. +While doing so, KVM don't update vCPU DR6 but instead report the #DB DR6 +value to userspace for further handling. +See KVM's handle_exception() DB_VECTOR handler. + +QEMU handler for this case is kvm_handle_debug(). This handler basically +checks if #DB is related to one of user set hardware breakpoints and if +not, it re-inject #DB into guest. +The re-injection is done by setting env->exception_injected to #DB which +will later be passed as events.exception.nr to KVM_SET_VCPU_EVENTS ioctl +by kvm_put_vcpu_events(). + +However, in case userspace re-injects #DB, KVM expects userspace to set +vCPU DR6 as reported to userspace when #DB was intercepted! Otherwise, +KVM_REQ_EVENT handler will inject #DB with wrong DR6 to guest. + +Fix this issue by updating vCPU DR6 appropriately when re-inject #DB to +guest. + +Reviewed-by: Nikita Leshenko +Reviewed-by: Krish Sadhukhan +Signed-off-by: Liran Alon +Message-Id: <20190619162140.133674-5-liran.alon@oracle.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit bceeeef9e7544057659118688243260c390eceb9) +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/kvm.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index 4138fe9..1a4ff3c 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -3363,6 +3363,9 @@ static int kvm_handle_debug(X86CPU *cpu, + /* pass to guest */ + env->exception_injected = arch_info->exception; + env->has_error_code = 0; ++ if (arch_info->exception == EXCP01_DB) { ++ env->dr[6] = arch_info->dr6; ++ } + } + + return ret; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-kvm-Use-symbolic-constant-for-DB-BP-exce.patch b/SOURCES/kvm-target-i386-kvm-Use-symbolic-constant-for-DB-BP-exce.patch new file mode 100644 index 0000000..b551bc8 --- /dev/null +++ b/SOURCES/kvm-target-i386-kvm-Use-symbolic-constant-for-DB-BP-exce.patch @@ -0,0 +1,58 @@ +From 0168573b58d5e70a60c9fef319ba510aa9648f2d Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 22 Jul 2019 18:22:09 +0100 +Subject: [PATCH 28/39] target/i386: kvm: Use symbolic constant for #DB/#BP + exception constants + +RH-Author: Paolo Bonzini +Message-id: <20190722182220.19374-8-pbonzini@redhat.com> +Patchwork-id: 89625 +O-Subject: [RHEL-8.1.0 PATCH qemu-kvm v3 07/18] target/i386: kvm: Use symbolic constant for #DB/#BP exception constants +Bugzilla: 1689269 +RH-Acked-by: Peter Xu +RH-Acked-by: Laurent Vivier +RH-Acked-by: Dr. David Alan Gilbert + +From: Liran Alon + +Reviewed-by: Nikita Leshenko +Reviewed-by: Krish Sadhukhan +Signed-off-by: Liran Alon +Message-Id: <20190619162140.133674-4-liran.alon@oracle.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit 37936ac70f6c20aec6f537349eb797fb98f9a99d) +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/kvm.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index 305809f..4138fe9 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -2811,9 +2811,9 @@ static int kvm_guest_debug_workarounds(X86CPU *cpu) + unsigned long reinject_trap = 0; + + if (!kvm_has_vcpu_events()) { +- if (env->exception_injected == 1) { ++ if (env->exception_injected == EXCP01_DB) { + reinject_trap = KVM_GUESTDBG_INJECT_DB; +- } else if (env->exception_injected == 3) { ++ } else if (env->exception_injected == EXCP03_INT3) { + reinject_trap = KVM_GUESTDBG_INJECT_BP; + } + env->exception_injected = -1; +@@ -3325,8 +3325,8 @@ static int kvm_handle_debug(X86CPU *cpu, + int ret = 0; + int n; + +- if (arch_info->exception == 1) { +- if (arch_info->dr6 & (1 << 14)) { ++ if (arch_info->exception == EXCP01_DB) { ++ if (arch_info->dr6 & DR6_BS) { + if (cs->singlestep_enabled) { + ret = EXCP_DEBUG; + } +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-kvm-add-VMX-migration-blocker.patch b/SOURCES/kvm-target-i386-kvm-add-VMX-migration-blocker.patch new file mode 100644 index 0000000..2adbaea --- /dev/null +++ b/SOURCES/kvm-target-i386-kvm-add-VMX-migration-blocker.patch @@ -0,0 +1,60 @@ +From 9a920701b3d2d78612bc454c407cf7b0d01f51c6 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 22 Jul 2019 18:22:05 +0100 +Subject: [PATCH 24/39] target/i386: kvm: add VMX migration blocker + +RH-Author: Paolo Bonzini +Message-id: <20190722182220.19374-4-pbonzini@redhat.com> +Patchwork-id: 89621 +O-Subject: [RHEL-8.1.0 PATCH qemu-kvm v3 03/18] target/i386: kvm: add VMX migration blocker +Bugzilla: 1689269 +RH-Acked-by: Peter Xu +RH-Acked-by: Laurent Vivier +RH-Acked-by: Dr. David Alan Gilbert + +Nested VMX does not support live migration yet. Add a blocker +until that is worked out. + +Nested SVM only does not support it, but unfortunately it is +enabled by default for -cpu host so we cannot really disable it. + +Signed-off-by: Paolo Bonzini +(cherry picked from commit d98f26073bebddcd3da0ba1b86c3a34e840c0fb8) +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/kvm.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index 8a4d31d..d414187 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -772,6 +772,7 @@ static int hyperv_handle_properties(CPUState *cs) + } + + static Error *invtsc_mig_blocker; ++static Error *vmx_mig_blocker; + + #define KVM_MAX_CPUID_ENTRIES 100 + +@@ -1115,6 +1116,17 @@ int kvm_arch_init_vcpu(CPUState *cs) + !!(c->ecx & CPUID_EXT_SMX); + } + ++ if ((env->features[FEAT_1_ECX] & CPUID_EXT_VMX) && !vmx_mig_blocker) { ++ error_setg(&vmx_mig_blocker, ++ "Nested VMX virtualization does not support live migration yet"); ++ r = migrate_add_blocker(vmx_mig_blocker, &local_err); ++ if (local_err) { ++ error_report_err(local_err); ++ error_free(vmx_mig_blocker); ++ return r; ++ } ++ } ++ + if (env->mcg_cap & MCG_LMCE_P) { + has_msr_mcg_ext_ctl = has_msr_feature_control = true; + } +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-kvm-do-not-initialize-padding-fields.patch b/SOURCES/kvm-target-i386-kvm-do-not-initialize-padding-fields.patch new file mode 100644 index 0000000..8f32cad --- /dev/null +++ b/SOURCES/kvm-target-i386-kvm-do-not-initialize-padding-fields.patch @@ -0,0 +1,52 @@ +From 61f0e94fd78c21f2d7e1b2893dc11103399a0efe Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 22 Jul 2019 18:22:12 +0100 +Subject: [PATCH 31/39] target-i386: kvm: do not initialize padding fields + +RH-Author: Paolo Bonzini +Message-id: <20190722182220.19374-11-pbonzini@redhat.com> +Patchwork-id: 89627 +O-Subject: [RHEL-8.1.0 PATCH qemu-kvm v3 10/18] target-i386: kvm: do not initialize padding fields +Bugzilla: 1689269 +RH-Acked-by: Peter Xu +RH-Acked-by: Laurent Vivier +RH-Acked-by: Dr. David Alan Gilbert + +The exception.pad field is going to be renamed to pending in an upcoming +header file update. Remove the unnecessary initialization; it was +introduced to please valgrind (commit 7e680753cfa2) but they were later +rendered unnecessary by commit 076796f8fd27f4d, which added the "= {}" +initializer to the declaration of "events". Therefore the patch does +not change behavior in any way. + +Reviewed-by: Peter Maydell +Signed-off-by: Paolo Bonzini +(cherry picked from commit b31c003895b030bea1319037d6bec976d47d9020) +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/kvm.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index f741e8b..8a6da90 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -2696,7 +2696,6 @@ static int kvm_put_vcpu_events(X86CPU *cpu, int level) + events.exception.nr = env->exception_injected; + events.exception.has_error_code = env->has_error_code; + events.exception.error_code = env->error_code; +- events.exception.pad = 0; + + events.interrupt.injected = (env->interrupt_injected >= 0); + events.interrupt.nr = env->interrupt_injected; +@@ -2705,7 +2704,6 @@ static int kvm_put_vcpu_events(X86CPU *cpu, int level) + events.nmi.injected = env->nmi_injected; + events.nmi.pending = env->nmi_pending; + events.nmi.masked = !!(env->hflags2 & HF2_NMI_MASK); +- events.nmi.pad = 0; + + events.sipi_vector = env->sipi_vector; + events.flags = 0; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-kvm-just-return-after-migrate_add_blocke.patch b/SOURCES/kvm-target-i386-kvm-just-return-after-migrate_add_blocke.patch new file mode 100644 index 0000000..2a3cbc8 --- /dev/null +++ b/SOURCES/kvm-target-i386-kvm-just-return-after-migrate_add_blocke.patch @@ -0,0 +1,45 @@ +From 28e39ed55e3b01d883e0fa7d2d65937769fa5f72 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 22 Jul 2019 18:22:06 +0100 +Subject: [PATCH 25/39] target/i386: kvm: just return after migrate_add_blocker + failed + +RH-Author: Paolo Bonzini +Message-id: <20190722182220.19374-5-pbonzini@redhat.com> +Patchwork-id: 89622 +O-Subject: [RHEL-8.1.0 PATCH qemu-kvm v3 04/18] target/i386: kvm: just return after migrate_add_blocker failed +Bugzilla: 1689269 +RH-Acked-by: Peter Xu +RH-Acked-by: Laurent Vivier +RH-Acked-by: Dr. David Alan Gilbert + +From: Li Qiang + +When migrate_add_blocker failed, the invtsc_mig_blocker is not +appended so no need to remove. This can save several instructions. + +Signed-off-by: Li Qiang +Message-Id: <20181006091816.7659-1-liq3ea@163.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit 0c2ed83fa45aa5d80ecc7d3fff0ab38db2db5972) +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/kvm.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index d414187..875412c 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -1142,7 +1142,7 @@ int kvm_arch_init_vcpu(CPUState *cs) + if (local_err) { + error_report_err(local_err); + error_free(invtsc_mig_blocker); +- goto fail; ++ return r; + } + /* for savevm */ + vmstate_x86_cpu.unmigratable = 1; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-kvm-kvm_get_supported_msrs-cleanup.patch b/SOURCES/kvm-target-i386-kvm-kvm_get_supported_msrs-cleanup.patch new file mode 100644 index 0000000..3fffb50 --- /dev/null +++ b/SOURCES/kvm-target-i386-kvm-kvm_get_supported_msrs-cleanup.patch @@ -0,0 +1,231 @@ +From 07cb338d84e4f439b0a62fbdcbe2162936e3728a Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Fri, 22 Nov 2019 11:53:38 +0000 +Subject: [PATCH 05/16] target-i386: kvm: 'kvm_get_supported_msrs' cleanup + +RH-Author: Paolo Bonzini +Message-id: <20191122115348.25000-6-pbonzini@redhat.com> +Patchwork-id: 92606 +O-Subject: [RHEL8.2/rhel qemu-kvm PATCH 05/15] target-i386: kvm: 'kvm_get_supported_msrs' cleanup +Bugzilla: 1689270 +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Maxim Levitsky + +From: Li Qiang + +Function 'kvm_get_supported_msrs' is only called once +now, get rid of the static variable 'kvm_supported_msrs'. + +Signed-off-by: Li Qiang +Message-Id: <20190725151639.21693-1-liq3ea@163.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit de428cead63a958137ee63efcc3cceaf75f6c125) + +RHEL: no HV_X64_MSR_REENLIGHTENMENT_CONTROL +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/kvm.c | 179 +++++++++++++++++++++++++++--------------------------- + 1 file changed, 88 insertions(+), 91 deletions(-) + +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index 849a11a..2290c5d 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -1340,105 +1340,102 @@ static int kvm_get_supported_feature_msrs(KVMState *s) + + static int kvm_get_supported_msrs(KVMState *s) + { +- static int kvm_supported_msrs; + int ret = 0; ++ struct kvm_msr_list msr_list, *kvm_msr_list; + +- /* first time */ +- if (kvm_supported_msrs == 0) { +- struct kvm_msr_list msr_list, *kvm_msr_list; ++ /* ++ * Obtain MSR list from KVM. These are the MSRs that we must ++ * save/restore. ++ */ ++ msr_list.nmsrs = 0; ++ ret = kvm_ioctl(s, KVM_GET_MSR_INDEX_LIST, &msr_list); ++ if (ret < 0 && ret != -E2BIG) { ++ return ret; ++ } ++ /* ++ * Old kernel modules had a bug and could write beyond the provided ++ * memory. Allocate at least a safe amount of 1K. ++ */ ++ kvm_msr_list = g_malloc0(MAX(1024, sizeof(msr_list) + ++ msr_list.nmsrs * ++ sizeof(msr_list.indices[0]))); + +- kvm_supported_msrs = -1; ++ kvm_msr_list->nmsrs = msr_list.nmsrs; ++ ret = kvm_ioctl(s, KVM_GET_MSR_INDEX_LIST, kvm_msr_list); ++ if (ret >= 0) { ++ int i; + +- /* Obtain MSR list from KVM. These are the MSRs that we must +- * save/restore */ +- msr_list.nmsrs = 0; +- ret = kvm_ioctl(s, KVM_GET_MSR_INDEX_LIST, &msr_list); +- if (ret < 0 && ret != -E2BIG) { +- return ret; +- } +- /* Old kernel modules had a bug and could write beyond the provided +- memory. Allocate at least a safe amount of 1K. */ +- kvm_msr_list = g_malloc0(MAX(1024, sizeof(msr_list) + +- msr_list.nmsrs * +- sizeof(msr_list.indices[0]))); +- +- kvm_msr_list->nmsrs = msr_list.nmsrs; +- ret = kvm_ioctl(s, KVM_GET_MSR_INDEX_LIST, kvm_msr_list); +- if (ret >= 0) { +- int i; +- +- for (i = 0; i < kvm_msr_list->nmsrs; i++) { +- switch (kvm_msr_list->indices[i]) { +- case MSR_STAR: +- has_msr_star = true; +- break; +- case MSR_VM_HSAVE_PA: +- has_msr_hsave_pa = true; +- break; +- case MSR_TSC_AUX: +- has_msr_tsc_aux = true; +- break; +- case MSR_TSC_ADJUST: +- has_msr_tsc_adjust = true; +- break; +- case MSR_IA32_TSCDEADLINE: +- has_msr_tsc_deadline = true; +- break; +- case MSR_IA32_SMBASE: +- has_msr_smbase = true; +- break; +- case MSR_SMI_COUNT: +- has_msr_smi_count = true; +- break; +- case MSR_IA32_MISC_ENABLE: +- has_msr_misc_enable = true; +- break; +- case MSR_IA32_BNDCFGS: +- has_msr_bndcfgs = true; +- break; +- case MSR_IA32_XSS: +- has_msr_xss = true; +- break; +- case HV_X64_MSR_CRASH_CTL: +- has_msr_hv_crash = true; +- break; +- case HV_X64_MSR_RESET: +- has_msr_hv_reset = true; +- break; +- case HV_X64_MSR_VP_INDEX: +- has_msr_hv_vpindex = true; +- break; +- case HV_X64_MSR_VP_RUNTIME: +- has_msr_hv_runtime = true; +- break; +- case HV_X64_MSR_SCONTROL: +- has_msr_hv_synic = true; +- break; +- case HV_X64_MSR_STIMER0_CONFIG: +- has_msr_hv_stimer = true; +- break; +- case HV_X64_MSR_TSC_FREQUENCY: +- has_msr_hv_frequencies = true; +- break; +- case MSR_IA32_SPEC_CTRL: +- has_msr_spec_ctrl = true; +- break; +- case MSR_VIRT_SSBD: +- has_msr_virt_ssbd = true; +- break; +- case MSR_IA32_ARCH_CAPABILITIES: +- has_msr_arch_capabs = true; +- break; +- case MSR_IA32_CORE_CAPABILITY: +- has_msr_core_capabs = true; +- break; +- } ++ for (i = 0; i < kvm_msr_list->nmsrs; i++) { ++ switch (kvm_msr_list->indices[i]) { ++ case MSR_STAR: ++ has_msr_star = true; ++ break; ++ case MSR_VM_HSAVE_PA: ++ has_msr_hsave_pa = true; ++ break; ++ case MSR_TSC_AUX: ++ has_msr_tsc_aux = true; ++ break; ++ case MSR_TSC_ADJUST: ++ has_msr_tsc_adjust = true; ++ break; ++ case MSR_IA32_TSCDEADLINE: ++ has_msr_tsc_deadline = true; ++ break; ++ case MSR_IA32_SMBASE: ++ has_msr_smbase = true; ++ break; ++ case MSR_SMI_COUNT: ++ has_msr_smi_count = true; ++ break; ++ case MSR_IA32_MISC_ENABLE: ++ has_msr_misc_enable = true; ++ break; ++ case MSR_IA32_BNDCFGS: ++ has_msr_bndcfgs = true; ++ break; ++ case MSR_IA32_XSS: ++ has_msr_xss = true; ++ break; ++ case HV_X64_MSR_CRASH_CTL: ++ has_msr_hv_crash = true; ++ break; ++ case HV_X64_MSR_RESET: ++ has_msr_hv_reset = true; ++ break; ++ case HV_X64_MSR_VP_INDEX: ++ has_msr_hv_vpindex = true; ++ break; ++ case HV_X64_MSR_VP_RUNTIME: ++ has_msr_hv_runtime = true; ++ break; ++ case HV_X64_MSR_SCONTROL: ++ has_msr_hv_synic = true; ++ break; ++ case HV_X64_MSR_STIMER0_CONFIG: ++ has_msr_hv_stimer = true; ++ break; ++ case HV_X64_MSR_TSC_FREQUENCY: ++ has_msr_hv_frequencies = true; ++ break; ++ case MSR_IA32_SPEC_CTRL: ++ has_msr_spec_ctrl = true; ++ break; ++ case MSR_VIRT_SSBD: ++ has_msr_virt_ssbd = true; ++ break; ++ case MSR_IA32_ARCH_CAPABILITIES: ++ has_msr_arch_capabs = true; ++ break; ++ case MSR_IA32_CORE_CAPABILITY: ++ has_msr_core_capabs = true; ++ break; + } + } +- +- g_free(kvm_msr_list); + } + ++ g_free(kvm_msr_list); ++ + return ret; + } + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-rename-HF_SVMI_MASK-to-HF_GUEST_MASK.patch b/SOURCES/kvm-target-i386-rename-HF_SVMI_MASK-to-HF_GUEST_MASK.patch new file mode 100644 index 0000000..63d5112 --- /dev/null +++ b/SOURCES/kvm-target-i386-rename-HF_SVMI_MASK-to-HF_GUEST_MASK.patch @@ -0,0 +1,150 @@ +From 9d1e37615a8285d852b7d8f829b9f9aeed703f14 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 22 Jul 2019 18:22:04 +0100 +Subject: [PATCH 23/39] target/i386: rename HF_SVMI_MASK to HF_GUEST_MASK + +RH-Author: Paolo Bonzini +Message-id: <20190722182220.19374-3-pbonzini@redhat.com> +Patchwork-id: 89620 +O-Subject: [RHEL-8.1.0 PATCH qemu-kvm v3 02/18] target/i386: rename HF_SVMI_MASK to HF_GUEST_MASK +Bugzilla: 1689269 +RH-Acked-by: Peter Xu +RH-Acked-by: Laurent Vivier +RH-Acked-by: Dr. David Alan Gilbert + +This flag will be used for KVM's nested VMX migration; the HF_GUEST_MASK name +is already used in KVM, adopt it in QEMU as well. + +Signed-off-by: Paolo Bonzini +(cherry picked from commit f8dc4c645ec2956a6cd97e0ca0fdd4753181f735) +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.h | 4 ++-- + target/i386/excp_helper.c | 2 +- + target/i386/seg_helper.c | 6 +++--- + target/i386/svm_helper.c | 6 +++--- + target/i386/translate.c | 4 ++-- + 5 files changed, 11 insertions(+), 11 deletions(-) + +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index 4f9df6e..923dfcd 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -171,7 +171,7 @@ typedef enum X86Seg { + #define HF_AC_SHIFT 18 /* must be same as eflags */ + #define HF_SMM_SHIFT 19 /* CPU in SMM mode */ + #define HF_SVME_SHIFT 20 /* SVME enabled (copy of EFER.SVME) */ +-#define HF_SVMI_SHIFT 21 /* SVM intercepts are active */ ++#define HF_GUEST_SHIFT 21 /* SVM intercepts are active */ + #define HF_OSFXSR_SHIFT 22 /* CR4.OSFXSR */ + #define HF_SMAP_SHIFT 23 /* CR4.SMAP */ + #define HF_IOBPT_SHIFT 24 /* an io breakpoint enabled */ +@@ -196,7 +196,7 @@ typedef enum X86Seg { + #define HF_AC_MASK (1 << HF_AC_SHIFT) + #define HF_SMM_MASK (1 << HF_SMM_SHIFT) + #define HF_SVME_MASK (1 << HF_SVME_SHIFT) +-#define HF_SVMI_MASK (1 << HF_SVMI_SHIFT) ++#define HF_GUEST_MASK (1 << HF_GUEST_SHIFT) + #define HF_OSFXSR_MASK (1 << HF_OSFXSR_SHIFT) + #define HF_SMAP_MASK (1 << HF_SMAP_SHIFT) + #define HF_IOBPT_MASK (1 << HF_IOBPT_SHIFT) +diff --git a/target/i386/excp_helper.c b/target/i386/excp_helper.c +index cb4d1b7..7153837 100644 +--- a/target/i386/excp_helper.c ++++ b/target/i386/excp_helper.c +@@ -53,7 +53,7 @@ static int check_exception(CPUX86State *env, int intno, int *error_code, + + #if !defined(CONFIG_USER_ONLY) + if (env->old_exception == EXCP08_DBLE) { +- if (env->hflags & HF_SVMI_MASK) { ++ if (env->hflags & HF_GUEST_MASK) { + cpu_vmexit(env, SVM_EXIT_SHUTDOWN, 0, retaddr); /* does not return */ + } + +diff --git a/target/i386/seg_helper.c b/target/i386/seg_helper.c +index 600a4d7..f028045 100644 +--- a/target/i386/seg_helper.c ++++ b/target/i386/seg_helper.c +@@ -1239,7 +1239,7 @@ static void do_interrupt_all(X86CPU *cpu, int intno, int is_int, + } + if (env->cr[0] & CR0_PE_MASK) { + #if !defined(CONFIG_USER_ONLY) +- if (env->hflags & HF_SVMI_MASK) { ++ if (env->hflags & HF_GUEST_MASK) { + handle_even_inj(env, intno, is_int, error_code, is_hw, 0); + } + #endif +@@ -1254,7 +1254,7 @@ static void do_interrupt_all(X86CPU *cpu, int intno, int is_int, + } + } else { + #if !defined(CONFIG_USER_ONLY) +- if (env->hflags & HF_SVMI_MASK) { ++ if (env->hflags & HF_GUEST_MASK) { + handle_even_inj(env, intno, is_int, error_code, is_hw, 1); + } + #endif +@@ -1262,7 +1262,7 @@ static void do_interrupt_all(X86CPU *cpu, int intno, int is_int, + } + + #if !defined(CONFIG_USER_ONLY) +- if (env->hflags & HF_SVMI_MASK) { ++ if (env->hflags & HF_GUEST_MASK) { + CPUState *cs = CPU(cpu); + uint32_t event_inj = x86_ldl_phys(cs, env->vm_vmcb + + offsetof(struct vmcb, +diff --git a/target/i386/svm_helper.c b/target/i386/svm_helper.c +index 3504923..5b8458d 100644 +--- a/target/i386/svm_helper.c ++++ b/target/i386/svm_helper.c +@@ -206,7 +206,7 @@ void helper_vmrun(CPUX86State *env, int aflag, int next_eip_addend) + )); + + /* enable intercepts */ +- env->hflags |= HF_SVMI_MASK; ++ env->hflags |= HF_GUEST_MASK; + + env->tsc_offset = x86_ldq_phys(cs, env->vm_vmcb + + offsetof(struct vmcb, control.tsc_offset)); +@@ -481,7 +481,7 @@ void cpu_svm_check_intercept_param(CPUX86State *env, uint32_t type, + { + CPUState *cs = CPU(x86_env_get_cpu(env)); + +- if (likely(!(env->hflags & HF_SVMI_MASK))) { ++ if (likely(!(env->hflags & HF_GUEST_MASK))) { + return; + } + switch (type) { +@@ -674,7 +674,7 @@ void do_vmexit(CPUX86State *env, uint32_t exit_code, uint64_t exit_info_1) + + /* Reload the host state from vm_hsave */ + env->hflags2 &= ~(HF2_HIF_MASK | HF2_VINTR_MASK); +- env->hflags &= ~HF_SVMI_MASK; ++ env->hflags &= ~HF_GUEST_MASK; + env->intercept = 0; + env->intercept_exceptions = 0; + cs->interrupt_request &= ~CPU_INTERRUPT_VIRQ; +diff --git a/target/i386/translate.c b/target/i386/translate.c +index c9ed8dc..2a1b39e 100644 +--- a/target/i386/translate.c ++++ b/target/i386/translate.c +@@ -621,7 +621,7 @@ static void gen_check_io(DisasContext *s, TCGMemOp ot, target_ulong cur_eip, + tcg_abort(); + } + } +- if(s->flags & HF_SVMI_MASK) { ++ if(s->flags & HF_GUEST_MASK) { + gen_update_cc_op(s); + gen_jmp_im(cur_eip); + svm_flags |= (1 << (4 + ot)); +@@ -2305,7 +2305,7 @@ gen_svm_check_intercept_param(DisasContext *s, target_ulong pc_start, + uint32_t type, uint64_t param) + { + /* no SVM activated; fast case */ +- if (likely(!(s->flags & HF_SVMI_MASK))) ++ if (likely(!(s->flags & HF_GUEST_MASK))) + return; + gen_update_cc_op(s); + gen_jmp_im(pc_start - s->cs_base); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-sev-Do-not-unpin-ram-device-memory-regio.patch b/SOURCES/kvm-target-i386-sev-Do-not-unpin-ram-device-memory-regio.patch new file mode 100644 index 0000000..487e127 --- /dev/null +++ b/SOURCES/kvm-target-i386-sev-Do-not-unpin-ram-device-memory-regio.patch @@ -0,0 +1,59 @@ +From b150f14fa8adcfe255c0380427e31d033bd44789 Mon Sep 17 00:00:00 2001 +From: Alex Williamson +Date: Mon, 22 Jul 2019 18:09:47 +0100 +Subject: [PATCH 21/39] target/i386: sev: Do not unpin ram device memory region + +RH-Author: Alex Williamson +Message-id: <156381893103.14196.5165276806848335745.stgit@gimli.home> +Patchwork-id: 89617 +O-Subject: [RHEL-8.1 qemu-kvm PATCH] target/i386: sev: Do not unpin ram device memory region +Bugzilla: 1728958 +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Auger Eric +RH-Acked-by: Laszlo Ersek + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1728958 +Brew: https://brewweb.engineering.redhat.com/brew/taskinfo?taskID=22722091 +Branch: rhel-8.1.0 + +The commit referenced below skipped pinning ram device memory when +ram blocks are added, we need to do the same when they're removed. + +Cc: Brijesh Singh +Cc: Paolo Bonzini +Fixes: cedc0ad539af ("target/i386: sev: Do not pin the ram device memory region") +Signed-off-by: Alex Williamson +Message-Id: <156320087103.2556.10983987500488190423.stgit@gimli.home> +Reviewed-by: Singh, Brijesh +Signed-off-by: Paolo Bonzini +(cherry picked from commit 56e2ec9488b3b281130e064929f8ae5595d6ac39) +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/sev.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/target/i386/sev.c b/target/i386/sev.c +index b8009b0..7051a30 100644 +--- a/target/i386/sev.c ++++ b/target/i386/sev.c +@@ -159,6 +159,17 @@ sev_ram_block_removed(RAMBlockNotifier *n, void *host, size_t size) + { + int r; + struct kvm_enc_region range; ++ ram_addr_t offset; ++ MemoryRegion *mr; ++ ++ /* ++ * The RAM device presents a memory region that should be treated ++ * as IO region and should not have been pinned. ++ */ ++ mr = memory_region_from_host(host, &offset); ++ if (mr && memory_region_is_ram_device(mr)) { ++ return; ++ } + + range.addr = (__u64)(unsigned long)host; + range.size = size; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-skip-KVM_GET-SET_NESTED_STATE-if-VMX-dis.patch b/SOURCES/kvm-target-i386-skip-KVM_GET-SET_NESTED_STATE-if-VMX-dis.patch new file mode 100644 index 0000000..dbf7d93 --- /dev/null +++ b/SOURCES/kvm-target-i386-skip-KVM_GET-SET_NESTED_STATE-if-VMX-dis.patch @@ -0,0 +1,126 @@ +From a8a32dd460a1d838cfe97ec53a2eb76c018c5dbf Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 22 Jul 2019 18:22:19 +0100 +Subject: [PATCH 38/39] target/i386: skip KVM_GET/SET_NESTED_STATE if VMX + disabled, or for SVM + +RH-Author: Paolo Bonzini +Message-id: <20190722182220.19374-18-pbonzini@redhat.com> +Patchwork-id: 89636 +O-Subject: [RHEL-8.1.0 PATCH qemu-kvm v3 17/18] target/i386: skip KVM_GET/SET_NESTED_STATE if VMX disabled, or for SVM +Bugzilla: 1689269 +RH-Acked-by: Peter Xu +RH-Acked-by: Laurent Vivier +RH-Acked-by: Dr. David Alan Gilbert + +Do not allocate env->nested_state unless we later need to migrate the +nested virtualization state. + +With this change, nested_state_needed() will return false if the +VMX flag is not included in the virtual machine. KVM_GET/SET_NESTED_STATE +is also disabled for SVM which is safer (we know that at least the NPT +root and paging mode have to be saved/loaded), and thus the corresponding +subsection can go away as well. + +Inspired by a patch from Liran Alon. + +Signed-off-by: Paolo Bonzini +(cherry picked from commit 1e44f3ab71fb4291d266a264f7c207ae5c6d59b2) +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/kvm.c | 16 ++++++++-------- + target/i386/machine.c | 21 +-------------------- + 2 files changed, 9 insertions(+), 28 deletions(-) + +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index 0bd286e..8648f1f 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -1220,15 +1220,15 @@ int kvm_arch_init_vcpu(CPUState *cs) + max_nested_state_len = kvm_max_nested_state_length(); + if (max_nested_state_len > 0) { + assert(max_nested_state_len >= offsetof(struct kvm_nested_state, data)); +- env->nested_state = g_malloc0(max_nested_state_len); + +- env->nested_state->size = max_nested_state_len; +- +- if (IS_INTEL_CPU(env)) { +- struct kvm_vmx_nested_state_hdr *vmx_hdr = +- &env->nested_state->hdr.vmx; ++ if (cpu_has_vmx(env)) { ++ struct kvm_vmx_nested_state_hdr *vmx_hdr; + ++ env->nested_state = g_malloc0(max_nested_state_len); ++ env->nested_state->size = max_nested_state_len; + env->nested_state->format = KVM_STATE_NESTED_FORMAT_VMX; ++ ++ vmx_hdr = &env->nested_state->hdr.vmx; + vmx_hdr->vmxon_pa = -1ull; + vmx_hdr->vmcs12_pa = -1ull; + } +@@ -2966,7 +2966,7 @@ static int kvm_put_nested_state(X86CPU *cpu) + CPUX86State *env = &cpu->env; + int max_nested_state_len = kvm_max_nested_state_length(); + +- if (max_nested_state_len <= 0) { ++ if (!env->nested_state) { + return 0; + } + +@@ -2980,7 +2980,7 @@ static int kvm_get_nested_state(X86CPU *cpu) + int max_nested_state_len = kvm_max_nested_state_length(); + int ret; + +- if (max_nested_state_len <= 0) { ++ if (!env->nested_state) { + return 0; + } + +diff --git a/target/i386/machine.c b/target/i386/machine.c +index 8d90d98..fa8d1cc 100644 +--- a/target/i386/machine.c ++++ b/target/i386/machine.c +@@ -1004,31 +1004,13 @@ static const VMStateDescription vmstate_vmx_nested_state = { + } + }; + +-static bool svm_nested_state_needed(void *opaque) +-{ +- struct kvm_nested_state *nested_state = opaque; +- +- return (nested_state->format == KVM_STATE_NESTED_FORMAT_SVM); +-} +- +-static const VMStateDescription vmstate_svm_nested_state = { +- .name = "cpu/kvm_nested_state/svm", +- .version_id = 1, +- .minimum_version_id = 1, +- .needed = svm_nested_state_needed, +- .fields = (VMStateField[]) { +- VMSTATE_END_OF_LIST() +- } +-}; +- + static bool nested_state_needed(void *opaque) + { + X86CPU *cpu = opaque; + CPUX86State *env = &cpu->env; + + return (env->nested_state && +- (vmx_nested_state_needed(env->nested_state) || +- svm_nested_state_needed(env->nested_state))); ++ vmx_nested_state_needed(env->nested_state)); + } + + static int nested_state_post_load(void *opaque, int version_id) +@@ -1090,7 +1072,6 @@ static const VMStateDescription vmstate_kvm_nested_state = { + }, + .subsections = (const VMStateDescription*[]) { + &vmstate_vmx_nested_state, +- &vmstate_svm_nested_state, + NULL + } + }; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-work-around-KVM_GET_MSRS-bug-for-seconda.patch b/SOURCES/kvm-target-i386-work-around-KVM_GET_MSRS-bug-for-seconda.patch new file mode 100644 index 0000000..94e6eb6 --- /dev/null +++ b/SOURCES/kvm-target-i386-work-around-KVM_GET_MSRS-bug-for-seconda.patch @@ -0,0 +1,60 @@ +From 92fad7ff756d40b231399a1eeedb7caca9ab321e Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Fri, 22 Nov 2019 11:53:45 +0000 +Subject: [PATCH 12/16] target/i386: work around KVM_GET_MSRS bug for secondary + execution controls + +RH-Author: Paolo Bonzini +Message-id: <20191122115348.25000-13-pbonzini@redhat.com> +Patchwork-id: 92609 +O-Subject: [RHEL8.2/rhel qemu-kvm PATCH 12/15] target/i386: work around KVM_GET_MSRS bug for secondary execution controls +Bugzilla: 1689270 +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Maxim Levitsky + +Some secondary controls are automatically enabled/disabled based on the CPUID +values that are set for the guest. However, they are still available at a +global level and therefore should be present when KVM_GET_MSRS is sent to +/dev/kvm. + +Unfortunately KVM forgot to include those, so fix that. + +Signed-off-by: Paolo Bonzini +(cherry picked from commit 048c95163b472ed737a2f0dca4f4e23a82ac2f8a) +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/kvm.c | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index 512d7d5..6366172 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -460,6 +460,23 @@ uint64_t kvm_arch_get_supported_msr_feature(KVMState *s, uint32_t index) + value = msr_data.entries[0].data; + switch (index) { + case MSR_IA32_VMX_PROCBASED_CTLS2: ++ /* KVM forgot to add these bits for some time, do this ourselves. */ ++ if (kvm_arch_get_supported_cpuid(s, 0xD, 1, R_ECX) & CPUID_XSAVE_XSAVES) { ++ value |= (uint64_t)VMX_SECONDARY_EXEC_XSAVES << 32; ++ } ++ if (kvm_arch_get_supported_cpuid(s, 1, 0, R_ECX) & CPUID_EXT_RDRAND) { ++ value |= (uint64_t)VMX_SECONDARY_EXEC_RDRAND_EXITING << 32; ++ } ++ if (kvm_arch_get_supported_cpuid(s, 7, 0, R_EBX) & CPUID_7_0_EBX_INVPCID) { ++ value |= (uint64_t)VMX_SECONDARY_EXEC_ENABLE_INVPCID << 32; ++ } ++ if (kvm_arch_get_supported_cpuid(s, 7, 0, R_EBX) & CPUID_7_0_EBX_RDSEED) { ++ value |= (uint64_t)VMX_SECONDARY_EXEC_RDSEED_EXITING << 32; ++ } ++ if (kvm_arch_get_supported_cpuid(s, 0x80000001, 0, R_EDX) & CPUID_EXT2_RDTSCP) { ++ value |= (uint64_t)VMX_SECONDARY_EXEC_RDTSCP << 32; ++ } ++ /* fall through */ + case MSR_IA32_VMX_TRUE_PINBASED_CTLS: + case MSR_IA32_VMX_TRUE_PROCBASED_CTLS: + case MSR_IA32_VMX_TRUE_ENTRY_CTLS: +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-ppc-spapr-Add-SPAPR_CAP_CCF_ASSIST.patch b/SOURCES/kvm-target-ppc-spapr-Add-SPAPR_CAP_CCF_ASSIST.patch new file mode 100644 index 0000000..a87ebe8 --- /dev/null +++ b/SOURCES/kvm-target-ppc-spapr-Add-SPAPR_CAP_CCF_ASSIST.patch @@ -0,0 +1,244 @@ +From d63d52e74a9af9d7d45f5734c4a6e127c3ecc0b4 Mon Sep 17 00:00:00 2001 +From: Sam Bobroff +Date: Thu, 29 Aug 2019 05:53:36 +0100 +Subject: [PATCH 03/10] target/ppc/spapr: Add SPAPR_CAP_CCF_ASSIST + +RH-Author: Sam Bobroff +Message-id: <80714b6e8fc19054881e9c1eaf1b8a332f8e104f.1567057498.git.sbobroff@redhat.com> +Patchwork-id: 90189 +O-Subject: [RHEL8.1 qemu-kvm BZ1744415 PATCH 2/2] target/ppc/spapr: Add SPAPR_CAP_CCF_ASSIST +Bugzilla: 1744415 +RH-Acked-by: David Gibson +RH-Acked-by: Laurent Vivier +RH-Acked-by: Thomas Huth + +From: Suraj Jitindar Singh + +Introduce a new spapr_cap SPAPR_CAP_CCF_ASSIST to be used to indicate +the requirement for a hw-assisted version of the count cache flush +workaround. + +The count cache flush workaround is a software workaround which can be +used to flush the count cache on context switch. Some revisions of +hardware may have a hardware accelerated flush, in which case the +software flush can be shortened. This cap is used to set the +availability of such hardware acceleration for the count cache flush +routine. + +The availability of such hardware acceleration is indicated by the +H_CPU_CHAR_BCCTR_FLUSH_ASSIST flag being set in the characteristics +returned from the KVM_PPC_GET_CPU_CHAR ioctl. + +Signed-off-by: Suraj Jitindar Singh +Message-Id: <20190301031912.28809-2-sjitindarsingh@gmail.com> +[dwg: Small style fixes] +Signed-off-by: David Gibson +(cherry picked from commit 8ff43ee404d3e295839d1fd4e9e6571ca7a62a66) +[SB: Minor fixup for context change.] + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1744415 +Brew: https://brewweb.engineering.redhat.com/brew/taskinfo?taskID=23229146 +Signed-off-by: Sam Bobroff +Testing: QEMU -M cap-ibs=workaround,cap-ccf-assist=on, check guest dmesg +Signed-off-by: Danilo C. L. de Paula +--- + hw/ppc/spapr.c | 2 ++ + hw/ppc/spapr_caps.c | 25 +++++++++++++++++++++++++ + hw/ppc/spapr_hcall.c | 5 +++++ + include/hw/ppc/spapr.h | 5 ++++- + target/ppc/kvm.c | 16 ++++++++++++++++ + target/ppc/kvm_ppc.h | 6 ++++++ + 6 files changed, 58 insertions(+), 1 deletion(-) + +diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c +index c72aad1..1a2f0d9 100644 +--- a/hw/ppc/spapr.c ++++ b/hw/ppc/spapr.c +@@ -1828,6 +1828,7 @@ static const VMStateDescription vmstate_spapr = { + &vmstate_spapr_cap_sbbc, + &vmstate_spapr_cap_ibs, + &vmstate_spapr_cap_nested_kvm_hv, ++ &vmstate_spapr_cap_ccf_assist, + NULL + } + }; +@@ -3939,6 +3940,7 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data) + smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_BROKEN; + smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_BROKEN; + smc->default_caps.caps[SPAPR_CAP_NESTED_KVM_HV] = SPAPR_CAP_OFF; ++ smc->default_caps.caps[SPAPR_CAP_CCF_ASSIST] = SPAPR_CAP_OFF; + spapr_caps_add_properties(smc, &error_abort); + smc->has_power9_support = true; + } +diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c +index dfc8cce..5353255 100644 +--- a/hw/ppc/spapr_caps.c ++++ b/hw/ppc/spapr_caps.c +@@ -285,6 +285,21 @@ static void cap_nested_kvm_hv_apply(sPAPRMachineState *spapr, + } + } + ++static void cap_ccf_assist_apply(sPAPRMachineState *spapr, uint8_t val, ++ Error **errp) ++{ ++ uint8_t kvm_val = kvmppc_get_cap_count_cache_flush_assist(); ++ ++ if (tcg_enabled() && val) { ++ /* TODO - for now only allow broken for TCG */ ++ error_setg(errp, ++"Requested count cache flush assist capability level not supported by tcg, try cap-ccf-assist=off"); ++ } else if (kvm_enabled() && (val > kvm_val)) { ++ error_setg(errp, ++"Requested count cache flush assist capability level not supported by kvm, try cap-ccf-assist=off"); ++ } ++} ++ + sPAPRCapabilityInfo capability_table[SPAPR_CAP_NUM] = { + [SPAPR_CAP_HTM] = { + .name = "htm", +@@ -354,6 +369,15 @@ sPAPRCapabilityInfo capability_table[SPAPR_CAP_NUM] = { + .type = "bool", + .apply = cap_nested_kvm_hv_apply, + }, ++ [SPAPR_CAP_CCF_ASSIST] = { ++ .name = "ccf-assist", ++ .description = "Count Cache Flush Assist via HW Instruction", ++ .index = SPAPR_CAP_CCF_ASSIST, ++ .get = spapr_cap_get_bool, ++ .set = spapr_cap_set_bool, ++ .type = "bool", ++ .apply = cap_ccf_assist_apply, ++ }, + }; + + static sPAPRCapabilities default_caps_with_cpu(sPAPRMachineState *spapr, +@@ -470,6 +494,7 @@ SPAPR_CAP_MIG_STATE(cfpc, SPAPR_CAP_CFPC); + SPAPR_CAP_MIG_STATE(sbbc, SPAPR_CAP_SBBC); + SPAPR_CAP_MIG_STATE(ibs, SPAPR_CAP_IBS); + SPAPR_CAP_MIG_STATE(nested_kvm_hv, SPAPR_CAP_NESTED_KVM_HV); ++SPAPR_CAP_MIG_STATE(ccf_assist, SPAPR_CAP_CCF_ASSIST); + + void spapr_caps_reset(sPAPRMachineState *spapr) + { +diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c +index 01c4215..141d1f4 100644 +--- a/hw/ppc/spapr_hcall.c ++++ b/hw/ppc/spapr_hcall.c +@@ -1675,6 +1675,8 @@ static target_ulong h_get_cpu_characteristics(PowerPCCPU *cpu, + uint8_t safe_cache = spapr_get_cap(spapr, SPAPR_CAP_CFPC); + uint8_t safe_bounds_check = spapr_get_cap(spapr, SPAPR_CAP_SBBC); + uint8_t safe_indirect_branch = spapr_get_cap(spapr, SPAPR_CAP_IBS); ++ uint8_t count_cache_flush_assist = spapr_get_cap(spapr, ++ SPAPR_CAP_CCF_ASSIST); + + switch (safe_cache) { + case SPAPR_CAP_WORKAROUND: +@@ -1715,6 +1717,9 @@ static target_ulong h_get_cpu_characteristics(PowerPCCPU *cpu, + break; + case SPAPR_CAP_WORKAROUND: + behaviour |= H_CPU_BEHAV_FLUSH_COUNT_CACHE; ++ if (count_cache_flush_assist) { ++ characteristics |= H_CPU_CHAR_BCCTR_FLUSH_ASSIST; ++ } + break; + default: /* broken */ + assert(safe_indirect_branch == SPAPR_CAP_BROKEN); +diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h +index 8bb95bb..4aff3b6 100644 +--- a/include/hw/ppc/spapr.h ++++ b/include/hw/ppc/spapr.h +@@ -68,8 +68,10 @@ typedef enum { + #define SPAPR_CAP_IBS 0x05 + /* Nested KVM-HV */ + #define SPAPR_CAP_NESTED_KVM_HV 0x06 ++/* Count Cache Flush Assist HW Instruction */ ++#define SPAPR_CAP_CCF_ASSIST 0x07 + /* Num Caps */ +-#define SPAPR_CAP_NUM (SPAPR_CAP_NESTED_KVM_HV + 1) ++#define SPAPR_CAP_NUM (SPAPR_CAP_CCF_ASSIST + 1) + + /* + * Capability Values +@@ -807,6 +809,7 @@ extern const VMStateDescription vmstate_spapr_cap_cfpc; + extern const VMStateDescription vmstate_spapr_cap_sbbc; + extern const VMStateDescription vmstate_spapr_cap_ibs; + extern const VMStateDescription vmstate_spapr_cap_nested_kvm_hv; ++extern const VMStateDescription vmstate_spapr_cap_ccf_assist; + + static inline uint8_t spapr_get_cap(sPAPRMachineState *spapr, int cap) + { +diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c +index 0e94cfc..8f90ee5 100644 +--- a/target/ppc/kvm.c ++++ b/target/ppc/kvm.c +@@ -92,6 +92,7 @@ static int cap_ppc_pvr_compat; + static int cap_ppc_safe_cache; + static int cap_ppc_safe_bounds_check; + static int cap_ppc_safe_indirect_branch; ++static int cap_ppc_count_cache_flush_assist; + static int cap_ppc_nested_kvm_hv; + + static uint32_t debug_inst_opcode; +@@ -2526,6 +2527,14 @@ static int parse_cap_ppc_safe_indirect_branch(struct kvm_ppc_cpu_char c) + return 0; + } + ++static int parse_cap_ppc_count_cache_flush_assist(struct kvm_ppc_cpu_char c) ++{ ++ if (c.character & c.character_mask & H_CPU_CHAR_BCCTR_FLUSH_ASSIST) { ++ return 1; ++ } ++ return 0; ++} ++ + static void kvmppc_get_cpu_characteristics(KVMState *s) + { + struct kvm_ppc_cpu_char c; +@@ -2548,6 +2557,8 @@ static void kvmppc_get_cpu_characteristics(KVMState *s) + cap_ppc_safe_cache = parse_cap_ppc_safe_cache(c); + cap_ppc_safe_bounds_check = parse_cap_ppc_safe_bounds_check(c); + cap_ppc_safe_indirect_branch = parse_cap_ppc_safe_indirect_branch(c); ++ cap_ppc_count_cache_flush_assist = ++ parse_cap_ppc_count_cache_flush_assist(c); + } + + int kvmppc_get_cap_safe_cache(void) +@@ -2565,6 +2576,11 @@ int kvmppc_get_cap_safe_indirect_branch(void) + return cap_ppc_safe_indirect_branch; + } + ++int kvmppc_get_cap_count_cache_flush_assist(void) ++{ ++ return cap_ppc_count_cache_flush_assist; ++} ++ + bool kvmppc_has_cap_nested_kvm_hv(void) + { + return !!cap_ppc_nested_kvm_hv; +diff --git a/target/ppc/kvm_ppc.h b/target/ppc/kvm_ppc.h +index dc86eff..e440c75 100644 +--- a/target/ppc/kvm_ppc.h ++++ b/target/ppc/kvm_ppc.h +@@ -63,6 +63,7 @@ bool kvmppc_has_cap_mmu_hash_v3(void); + int kvmppc_get_cap_safe_cache(void); + int kvmppc_get_cap_safe_bounds_check(void); + int kvmppc_get_cap_safe_indirect_branch(void); ++int kvmppc_get_cap_count_cache_flush_assist(void); + bool kvmppc_has_cap_nested_kvm_hv(void); + int kvmppc_set_cap_nested_kvm_hv(int enable); + int kvmppc_enable_hwrng(void); +@@ -316,6 +317,11 @@ static inline int kvmppc_get_cap_safe_indirect_branch(void) + return 0; + } + ++static inline int kvmppc_get_cap_count_cache_flush_assist(void) ++{ ++ return 0; ++} ++ + static inline bool kvmppc_has_cap_nested_kvm_hv(void) + { + return false; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-ppc-spapr-Add-workaround-option-to-SPAPR_CAP_.patch b/SOURCES/kvm-target-ppc-spapr-Add-workaround-option-to-SPAPR_CAP_.patch new file mode 100644 index 0000000..456c37e --- /dev/null +++ b/SOURCES/kvm-target-ppc-spapr-Add-workaround-option-to-SPAPR_CAP_.patch @@ -0,0 +1,173 @@ +From c1bd7825b1cbe0ff34be196effc7a18992cce269 Mon Sep 17 00:00:00 2001 +From: Sam Bobroff +Date: Thu, 29 Aug 2019 05:53:35 +0100 +Subject: [PATCH 02/10] target/ppc/spapr: Add workaround option to + SPAPR_CAP_IBS + +RH-Author: Sam Bobroff +Message-id: <67946d77e95afc19f2afc5f8dfa4e89335dbb58d.1567057498.git.sbobroff@redhat.com> +Patchwork-id: 90188 +O-Subject: [RHEL8.1 qemu-kvm BZ1744415 PATCH 1/2] target/ppc/spapr: Add workaround option to SPAPR_CAP_IBS +Bugzilla: 1744415 +RH-Acked-by: David Gibson +RH-Acked-by: Laurent Vivier +RH-Acked-by: Thomas Huth + +From: Suraj Jitindar Singh + +The spapr_cap SPAPR_CAP_IBS is used to indicate the level of capability +for mitigations for indirect branch speculation. Currently the available +values are broken (default), fixed-ibs (fixed by serialising indirect +branches) and fixed-ccd (fixed by diabling the count cache). + +Introduce a new value for this capability denoted workaround, meaning that +software can work around the issue by flushing the count cache on +context switch. This option is available if the hypervisor sets the +H_CPU_BEHAV_FLUSH_COUNT_CACHE flag in the cpu behaviours returned from +the KVM_PPC_GET_CPU_CHAR ioctl. + +Signed-off-by: Suraj Jitindar Singh +Message-Id: <20190301031912.28809-1-sjitindarsingh@gmail.com> +Signed-off-by: David Gibson +(cherry picked from commit 399b2896d4948a1ec0278d896ea3a561df768d64) + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1744415 +Brew: https://brewweb.engineering.redhat.com/brew/taskinfo?taskID=23229146 +Signed-off-by: Sam Bobroff +Testing: Start QEMU with -M cap-ibs=workaround, check guest dmesg +Signed-off-by: Danilo C. L. de Paula +--- + hw/ppc/spapr_caps.c | 21 ++++++++++----------- + hw/ppc/spapr_hcall.c | 5 +++++ + include/hw/ppc/spapr.h | 7 +++++++ + target/ppc/kvm.c | 8 +++++++- + 4 files changed, 29 insertions(+), 12 deletions(-) + +diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c +index 86a7947..dfc8cce 100644 +--- a/hw/ppc/spapr_caps.c ++++ b/hw/ppc/spapr_caps.c +@@ -236,11 +236,13 @@ static void cap_safe_bounds_check_apply(sPAPRMachineState *spapr, uint8_t val, + } + + sPAPRCapPossible cap_ibs_possible = { +- .num = 4, ++ .num = 5, + /* Note workaround only maintained for compatibility */ +- .vals = {"broken", "workaround", "fixed-ibs", "fixed-ccd"}, +- .help = "broken - no protection, fixed-ibs - indirect branch serialisation," +- " fixed-ccd - cache count disabled", ++ .vals = {"broken", "workaround", "fixed-ibs", "fixed-ccd", "fixed-na"}, ++ .help = "broken - no protection, workaround - count cache flush" ++ ", fixed-ibs - indirect branch serialisation," ++ " fixed-ccd - cache count disabled," ++ " fixed-na - fixed in hardware (no longer applicable)", + }; + + static void cap_safe_indirect_branch_apply(sPAPRMachineState *spapr, +@@ -248,15 +250,11 @@ static void cap_safe_indirect_branch_apply(sPAPRMachineState *spapr, + { + uint8_t kvm_val = kvmppc_get_cap_safe_indirect_branch(); + +- if (val == SPAPR_CAP_WORKAROUND) { /* Can only be Broken or Fixed */ +- error_setg(errp, +-"Requested safe indirect branch capability level \"workaround\" not valid, try cap-ibs=%s", +- cap_ibs_possible.vals[kvm_val]); +- } else if (tcg_enabled() && val) { ++ if (tcg_enabled() && val) { + /* TODO - for now only allow broken for TCG */ + error_setg(errp, + "Requested safe indirect branch capability level not supported by tcg, try a different value for cap-ibs"); +- } else if (kvm_enabled() && val && (val != kvm_val)) { ++ } else if (kvm_enabled() && (val > kvm_val)) { + error_setg(errp, + "Requested safe indirect branch capability level not supported by kvm, try cap-ibs=%s", + cap_ibs_possible.vals[kvm_val]); +@@ -338,7 +336,8 @@ sPAPRCapabilityInfo capability_table[SPAPR_CAP_NUM] = { + [SPAPR_CAP_IBS] = { + .name = "ibs", + .description = +- "Indirect Branch Speculation (broken, fixed-ibs, fixed-ccd)", ++ "Indirect Branch Speculation (broken, workaround, fixed-ibs," ++ "fixed-ccd, fixed-na)", + .index = SPAPR_CAP_IBS, + .get = spapr_cap_get_string, + .set = spapr_cap_set_string, +diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c +index 16bccdd..01c4215 100644 +--- a/hw/ppc/spapr_hcall.c ++++ b/hw/ppc/spapr_hcall.c +@@ -1705,12 +1705,17 @@ static target_ulong h_get_cpu_characteristics(PowerPCCPU *cpu, + } + + switch (safe_indirect_branch) { ++ case SPAPR_CAP_FIXED_NA: ++ break; + case SPAPR_CAP_FIXED_CCD: + characteristics |= H_CPU_CHAR_CACHE_COUNT_DIS; + break; + case SPAPR_CAP_FIXED_IBS: + characteristics |= H_CPU_CHAR_BCCTRL_SERIALISED; + break; ++ case SPAPR_CAP_WORKAROUND: ++ behaviour |= H_CPU_BEHAV_FLUSH_COUNT_CACHE; ++ break; + default: /* broken */ + assert(safe_indirect_branch == SPAPR_CAP_BROKEN); + break; +diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h +index 72cfa49..8bb95bb 100644 +--- a/include/hw/ppc/spapr.h ++++ b/include/hw/ppc/spapr.h +@@ -77,12 +77,17 @@ typedef enum { + /* Bool Caps */ + #define SPAPR_CAP_OFF 0x00 + #define SPAPR_CAP_ON 0x01 ++ + /* Custom Caps */ ++ ++/* Generic */ + #define SPAPR_CAP_BROKEN 0x00 + #define SPAPR_CAP_WORKAROUND 0x01 + #define SPAPR_CAP_FIXED 0x02 ++/* SPAPR_CAP_IBS (cap-ibs) */ + #define SPAPR_CAP_FIXED_IBS 0x02 + #define SPAPR_CAP_FIXED_CCD 0x03 ++#define SPAPR_CAP_FIXED_NA 0x10 /* Lets leave a bit of a gap... */ + + typedef struct sPAPRCapabilities sPAPRCapabilities; + struct sPAPRCapabilities { +@@ -322,9 +327,11 @@ struct sPAPRMachineState { + #define H_CPU_CHAR_HON_BRANCH_HINTS PPC_BIT(5) + #define H_CPU_CHAR_THR_RECONF_TRIG PPC_BIT(6) + #define H_CPU_CHAR_CACHE_COUNT_DIS PPC_BIT(7) ++#define H_CPU_CHAR_BCCTR_FLUSH_ASSIST PPC_BIT(9) + #define H_CPU_BEHAV_FAVOUR_SECURITY PPC_BIT(0) + #define H_CPU_BEHAV_L1D_FLUSH_PR PPC_BIT(1) + #define H_CPU_BEHAV_BNDS_CHK_SPEC_BAR PPC_BIT(2) ++#define H_CPU_BEHAV_FLUSH_COUNT_CACHE PPC_BIT(5) + + /* Each control block has to be on a 4K boundary */ + #define H_CB_ALIGNMENT 4096 +diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c +index b9858fa..0e94cfc 100644 +--- a/target/ppc/kvm.c ++++ b/target/ppc/kvm.c +@@ -2511,7 +2511,13 @@ static int parse_cap_ppc_safe_bounds_check(struct kvm_ppc_cpu_char c) + + static int parse_cap_ppc_safe_indirect_branch(struct kvm_ppc_cpu_char c) + { +- if (c.character & c.character_mask & H_CPU_CHAR_CACHE_COUNT_DIS) { ++ if ((~c.behaviour & c.behaviour_mask & H_CPU_BEHAV_FLUSH_COUNT_CACHE) && ++ (~c.character & c.character_mask & H_CPU_CHAR_CACHE_COUNT_DIS) && ++ (~c.character & c.character_mask & H_CPU_CHAR_BCCTRL_SERIALISED)) { ++ return SPAPR_CAP_FIXED_NA; ++ } else if (c.behaviour & c.behaviour_mask & H_CPU_BEHAV_FLUSH_COUNT_CACHE) { ++ return SPAPR_CAP_WORKAROUND; ++ } else if (c.character & c.character_mask & H_CPU_CHAR_CACHE_COUNT_DIS) { + return SPAPR_CAP_FIXED_CCD; + } else if (c.character & c.character_mask & H_CPU_CHAR_BCCTRL_SERIALISED) { + return SPAPR_CAP_FIXED_IBS; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-test-bdrv-drain-AioContext-switch-in-drained-section.patch b/SOURCES/kvm-test-bdrv-drain-AioContext-switch-in-drained-section.patch new file mode 100644 index 0000000..2d8d04d --- /dev/null +++ b/SOURCES/kvm-test-bdrv-drain-AioContext-switch-in-drained-section.patch @@ -0,0 +1,76 @@ +From 7db4d6a7b791006e5b927d0a30f0106ce0c8b14d Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Wed, 14 Aug 2019 08:42:28 +0100 +Subject: [PATCH 05/10] test-bdrv-drain: AioContext switch in drained section + +RH-Author: Kevin Wolf +Message-id: <20190814084229.6458-5-kwolf@redhat.com> +Patchwork-id: 89965 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 4/5] test-bdrv-drain: AioContext switch in drained section +Bugzilla: 1716349 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Max Reitz +RH-Acked-by: Paolo Bonzini + +Signed-off-by: Kevin Wolf +Reviewed-by: Eric Blake +(cherry picked from commit 247d2737715833525725d27e5cecf5840c62f900) +Signed-off-by: Kevin Wolf +Signed-off-by: Danilo C. L. de Paula +--- + tests/test-bdrv-drain.c | 32 ++++++++++++++++++++++++++++++++ + 1 file changed, 32 insertions(+) + +diff --git a/tests/test-bdrv-drain.c b/tests/test-bdrv-drain.c +index 8641b54..05c6f12 100644 +--- a/tests/test-bdrv-drain.c ++++ b/tests/test-bdrv-drain.c +@@ -1521,6 +1521,36 @@ static void test_append_to_drained(void) + blk_unref(blk); + } + ++static void test_set_aio_context(void) ++{ ++ BlockDriverState *bs; ++ IOThread *a = iothread_new(); ++ IOThread *b = iothread_new(); ++ AioContext *ctx_a = iothread_get_aio_context(a); ++ AioContext *ctx_b = iothread_get_aio_context(b); ++ ++ bs = bdrv_new_open_driver(&bdrv_test, "test-node", BDRV_O_RDWR, ++ &error_abort); ++ ++ bdrv_drained_begin(bs); ++ bdrv_set_aio_context(bs, ctx_a); ++ ++ aio_context_acquire(ctx_a); ++ bdrv_drained_end(bs); ++ ++ bdrv_drained_begin(bs); ++ bdrv_set_aio_context(bs, ctx_b); ++ aio_context_release(ctx_a); ++ aio_context_acquire(ctx_b); ++ bdrv_set_aio_context(bs, qemu_get_aio_context()); ++ aio_context_release(ctx_b); ++ bdrv_drained_end(bs); ++ ++ bdrv_unref(bs); ++ iothread_join(a); ++ iothread_join(b); ++} ++ + int main(int argc, char **argv) + { + int ret; +@@ -1602,6 +1632,8 @@ int main(int argc, char **argv) + + g_test_add_func("/bdrv-drain/attach/drain", test_append_to_drained); + ++ g_test_add_func("/bdrv-drain/set_aio_context", test_set_aio_context); ++ + ret = g_test_run(); + qemu_event_destroy(&done_event); + return ret; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-usb-drop-unnecessary-usb_device_post_load-checks.patch b/SOURCES/kvm-usb-drop-unnecessary-usb_device_post_load-checks.patch new file mode 100644 index 0000000..60e2d2e --- /dev/null +++ b/SOURCES/kvm-usb-drop-unnecessary-usb_device_post_load-checks.patch @@ -0,0 +1,127 @@ +From 24ca1010222cadbfc3c734406b665e6a9775d9d9 Mon Sep 17 00:00:00 2001 +From: "Dr. David Alan Gilbert" +Date: Tue, 1 Oct 2019 18:49:25 +0100 +Subject: [PATCH 03/21] usb: drop unnecessary usb_device_post_load checks + +RH-Author: Dr. David Alan Gilbert +Message-id: <20191001184925.29912-2-dgilbert@redhat.com> +Patchwork-id: 90933 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH 1/1] usb: drop unnecessary usb_device_post_load checks +Bugzilla: 1757482 +RH-Acked-by: Maxim Levitsky +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Igor Mammedov + +From: Jonathan Davies + +In usb_device_post_load, certain values of dev->setup_len or +dev->setup_index can cause -EINVAL to be returned. One example is when +setup_len exceeds 4096, the hard-coded value of sizeof(dev->data_buf). +This can happen through legitimate guest activity and will cause all +subsequent attempts to migrate the guest to fail in vmstate_load_state. + +The values of these variables can be set by USB packets originating in +the guest. There are two ways in which they can be set: in +do_token_setup and in do_parameter in hw/usb/core.c. + +It is easy to craft a USB packet in a guest that causes do_token_setup +to set setup_len to a value larger than 4096. When this has been done +once, all subsequent attempts to migrate the VM will fail in +usb_device_post_load until the VM is next power-cycled or a +smaller-sized USB packet is sent to the device. + +Sample code for achieving this in a VM started with "-device usb-tablet" +running Linux with CONFIG_HIDRAW=y and HID_MAX_BUFFER_SIZE > 4096: + + #include + #include + #include + #include + + int main() { + char buf[4097]; + int fd = open("/dev/hidraw0", O_RDWR|O_NONBLOCK); + + buf[0] = 0x1; + write(fd, buf, 4097); + + return 0; + } + +When this code is run in the VM, qemu will output: + + usb_generic_handle_packet: ctrl buffer too small (4097 > 4096) + +A subsequent attempt to migrate the VM will fail and output the +following on the destination host: + + qemu-kvm: error while loading state for instance 0x0 of device '0000:00:06.7/1/usb-ptr' + qemu-kvm: load of migration failed: Invalid argument + +The idea behind checking the values of setup_len and setup_index before +they are used is correct, but doing it in usb_device_post_load feels +arbitrary, and will cause unnecessary migration failures. Indeed, none +of the commit messages for c60174e8, 9f8e9895 and 719ffe1f justify why +post_load is the right place to do these checks. They correctly point +out that the important thing to protect is the usb_packet_copy. + +Instead, the right place to do the checks is in do_token_setup and +do_parameter. Indeed, there are already some checks here. We can examine +each of the disjuncts currently tested in usb_device_post_load to see +whether any need adding to do_token_setup or do_parameter to improve +safety there: + + * dev->setup_index < 0 + - This test is not needed because setup_index is explicitly set to +0 in do_token_setup and do_parameter. + + * dev->setup_len < 0 + - In both do_token_setup and do_parameter, the value of setup_len +is computed by (s->setup_buf[7] << 8) | s->setup_buf[6]. Since +s->setup_buf is a byte array and setup_len is an int32_t, it's +impossible for this arithmetic to set setup_len's top bit, so it can +never be negative. + + * dev->setup_index > dev->setup_len + - Since setup_index is 0, this is equivalent to the previous test, +so is redundant. + + * dev->setup_len > sizeof(dev->data_buf) + - This condition is already explicitly checked in both +do_token_setup and do_parameter. + +Hence there is no need to bolster the existing checks in do_token_setup +or do_parameter, and we can safely remove these checks from +usb_device_post_load without reducing safety but allowing migrations to +proceed regardless of what USB packets have been generated by the guest. + +Signed-off-by: Jonathan Davies +Message-Id: <20190107175117.23769-1-jonathan.davies@nutanix.com> +Signed-off-by: Gerd Hoffmann +Signed-off-by: Dr. David Alan Gilbert +(cherry picked from commit f30815390adb1ec153327c3832ab378e8bce9808) +Signed-off-by: Danilo C. L. de Paula +--- + hw/usb/bus.c | 6 ------ + 1 file changed, 6 deletions(-) + +diff --git a/hw/usb/bus.c b/hw/usb/bus.c +index 11f7720..5499810 100644 +--- a/hw/usb/bus.c ++++ b/hw/usb/bus.c +@@ -59,12 +59,6 @@ static int usb_device_post_load(void *opaque, int version_id) + } else { + dev->attached = true; + } +- if (dev->setup_index < 0 || +- dev->setup_len < 0 || +- dev->setup_index > dev->setup_len || +- dev->setup_len > sizeof(dev->data_buf)) { +- return -EINVAL; +- } + return 0; + } + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-usb-hub-clear-suspend-on-detach.patch b/SOURCES/kvm-usb-hub-clear-suspend-on-detach.patch new file mode 100644 index 0000000..52f82f5 --- /dev/null +++ b/SOURCES/kvm-usb-hub-clear-suspend-on-detach.patch @@ -0,0 +1,43 @@ +From 24300291c98529f7d5a00ebdf6fdea68f8af97f5 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Wed, 14 Aug 2019 09:47:34 +0100 +Subject: [PATCH 2/3] usb-hub: clear suspend on detach +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Gerd Hoffmann +Message-id: <20190814094734.18110-2-kraxel@redhat.com> +Patchwork-id: 89977 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 1/1] usb-hub: clear suspend on detach +Bugzilla: 1619661 +RH-Acked-by: John Snow +RH-Acked-by: Markus Armbruster +RH-Acked-by: Philippe Mathieu-Daudé + +Signed-off-by: Gerd Hoffmann +Message-id: 20180912114012.6034-1-kraxel@redhat.com +(cherry picked from commit 3e9191acb797e4298adb853bf6c75cd31af47ef9) +Signed-off-by: Danilo C. L. de Paula +--- + hw/usb/dev-hub.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/hw/usb/dev-hub.c b/hw/usb/dev-hub.c +index 752e30c..2452e88 100644 +--- a/hw/usb/dev-hub.c ++++ b/hw/usb/dev-hub.c +@@ -191,6 +191,10 @@ static void usb_hub_detach(USBPort *port1) + port->wPortStatus &= ~PORT_STAT_ENABLE; + port->wPortChange |= PORT_STAT_C_ENABLE; + } ++ if (port->wPortStatus & PORT_STAT_SUSPEND) { ++ port->wPortStatus &= ~PORT_STAT_SUSPEND; ++ port->wPortChange |= PORT_STAT_C_SUSPEND; ++ } + usb_wakeup(s->intr, 0); + } + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-util-mmap-alloc-Add-a-is_pmem-parameter-to-qemu_ram_.patch b/SOURCES/kvm-util-mmap-alloc-Add-a-is_pmem-parameter-to-qemu_ram_.patch new file mode 100644 index 0000000..ec01556 --- /dev/null +++ b/SOURCES/kvm-util-mmap-alloc-Add-a-is_pmem-parameter-to-qemu_ram_.patch @@ -0,0 +1,120 @@ +From 5e258b59991284cf2e6bfcac04ff2de01dc83005 Mon Sep 17 00:00:00 2001 +From: "plai@redhat.com" +Date: Tue, 20 Aug 2019 16:12:48 +0100 +Subject: [PATCH 01/11] util/mmap-alloc: Add a 'is_pmem' parameter to + qemu_ram_mmap +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: plai@redhat.com +Message-id: <1566317571-5697-2-git-send-email-plai@redhat.com> +Patchwork-id: 90084 +O-Subject: [RHEL8.2 qemu-kvm PATCH 1/4] util/mmap-alloc: Add a 'is_pmem' parameter to qemu_ram_mmap +Bugzilla: 1539282 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Pankaj Gupta +RH-Acked-by: Eduardo Habkost + +From: Zhang Yi + +besides the existing 'shared' flags, we are going to add +'is_pmem' to qemu_ram_mmap(), which indicated the memory backend +file is a persist memory. + +Signed-off-by: Haozhong Zhang +Signed-off-by: Zhang Yi +Reviewed-by: Pankaj Gupta +Message-Id: <786c46862cfeb253ee0ea2f44d62ffe76edb7fa4.1549555521.git.yi.z.zhang@linux.intel.com> +Reviewed-by: Michael S. Tsirkin +Reviewed-by: Pankaj Gupta +Signed-off-by: Eduardo Habkost +(cherry picked from commit 2ac0f1621c9be59eebc844fa10361a84fd726185) +Signed-off-by: Paul Lai +Signed-off-by: Danilo C. L. de Paula +--- + exec.c | 2 +- + include/qemu/mmap-alloc.h | 21 ++++++++++++++++++++- + util/mmap-alloc.c | 6 +++++- + util/oslib-posix.c | 2 +- + 4 files changed, 27 insertions(+), 4 deletions(-) + +diff --git a/exec.c b/exec.c +index 9028700..a79eaa3 100644 +--- a/exec.c ++++ b/exec.c +@@ -1669,7 +1669,7 @@ static void *file_ram_alloc(RAMBlock *block, + } + + area = qemu_ram_mmap(fd, memory, block->mr->align, +- block->flags & RAM_SHARED); ++ block->flags & RAM_SHARED, block->flags & RAM_PMEM); + if (area == MAP_FAILED) { + error_setg_errno(errp, errno, + "unable to map backing store for guest RAM"); +diff --git a/include/qemu/mmap-alloc.h b/include/qemu/mmap-alloc.h +index 50385e3..190688a 100644 +--- a/include/qemu/mmap-alloc.h ++++ b/include/qemu/mmap-alloc.h +@@ -7,7 +7,26 @@ size_t qemu_fd_getpagesize(int fd); + + size_t qemu_mempath_getpagesize(const char *mem_path); + +-void *qemu_ram_mmap(int fd, size_t size, size_t align, bool shared); ++/** ++ * qemu_ram_mmap: mmap the specified file or device. ++ * ++ * Parameters: ++ * @fd: the file or the device to mmap ++ * @size: the number of bytes to be mmaped ++ * @align: if not zero, specify the alignment of the starting mapping address; ++ * otherwise, the alignment in use will be determined by QEMU. ++ * @shared: map has RAM_SHARED flag. ++ * @is_pmem: map has RAM_PMEM flag. ++ * ++ * Return: ++ * On success, return a pointer to the mapped area. ++ * On failure, return MAP_FAILED. ++ */ ++void *qemu_ram_mmap(int fd, ++ size_t size, ++ size_t align, ++ bool shared, ++ bool is_pmem); + + void qemu_ram_munmap(void *ptr, size_t size); + +diff --git a/util/mmap-alloc.c b/util/mmap-alloc.c +index 2fd8cbc..55d1890 100644 +--- a/util/mmap-alloc.c ++++ b/util/mmap-alloc.c +@@ -73,7 +73,11 @@ size_t qemu_mempath_getpagesize(const char *mem_path) + return getpagesize(); + } + +-void *qemu_ram_mmap(int fd, size_t size, size_t align, bool shared) ++void *qemu_ram_mmap(int fd, ++ size_t size, ++ size_t align, ++ bool shared, ++ bool is_pmem) + { + /* + * Note: this always allocates at least one extra page of virtual address +diff --git a/util/oslib-posix.c b/util/oslib-posix.c +index 13b6f8d..c36b2bb 100644 +--- a/util/oslib-posix.c ++++ b/util/oslib-posix.c +@@ -130,7 +130,7 @@ void *qemu_memalign(size_t alignment, size_t size) + void *qemu_anon_ram_alloc(size_t size, uint64_t *alignment, bool shared) + { + size_t align = QEMU_VMALLOC_ALIGN; +- void *ptr = qemu_ram_mmap(-1, size, align, shared); ++ void *ptr = qemu_ram_mmap(-1, size, align, shared, false); + + if (ptr == MAP_FAILED) { + return NULL; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-util-mmap-alloc-support-MAP_SYNC-in-qemu_ram_mmap.patch b/SOURCES/kvm-util-mmap-alloc-support-MAP_SYNC-in-qemu_ram_mmap.patch new file mode 100644 index 0000000..dbbcec5 --- /dev/null +++ b/SOURCES/kvm-util-mmap-alloc-support-MAP_SYNC-in-qemu_ram_mmap.patch @@ -0,0 +1,176 @@ +From 4438710f7aa42f55d189d1b6adb09b1c0471495e Mon Sep 17 00:00:00 2001 +From: "plai@redhat.com" +Date: Tue, 20 Aug 2019 16:12:51 +0100 +Subject: [PATCH 04/11] util/mmap-alloc: support MAP_SYNC in qemu_ram_mmap() + +RH-Author: plai@redhat.com +Message-id: <1566317571-5697-5-git-send-email-plai@redhat.com> +Patchwork-id: 90085 +O-Subject: [RHEL8.2 qemu-kvm PATCH 4/4] util/mmap-alloc: support MAP_SYNC in qemu_ram_mmap() +Bugzilla: 1539282 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Pankaj Gupta +RH-Acked-by: Eduardo Habkost + +From: Zhang Yi + +When a file supporting DAX is used as vNVDIMM backend, mmap it with +MAP_SYNC flag in addition which can ensure file system metadata +synced in each guest writes to the backend file, without other QEMU +actions (e.g., periodic fsync() by QEMU). + +Current, We have below different possible use cases: + +1. pmem=on is set, shared=on is set, MAP_SYNC supported: + a: backend is a dax supporting file. + - MAP_SYNC will active. + b: backend is not a dax supporting file. + - mmap will trigger a warning. then MAP_SYNC flag will be ignored + +2. The rest of cases: + - we will never pass the MAP_SYNC to mmap2 + +Signed-off-by: Haozhong Zhang +Signed-off-by: Zhang Yi +[ehabkost: Rebased patch to latest code on master] +Signed-off-by: Eduardo Habkost +Signed-off-by: Wei Yang +Tested-by: Wei Yang +Message-Id: <20190422004849.26463-2-richardw.yang@linux.intel.com> +[ehabkost: squashed documentation patch] +Message-Id: <20190422004849.26463-3-richardw.yang@linux.intel.com> +[ehabkost: documentation fixup] +Reviewed-by: Michael S. Tsirkin +Reviewed-by: Pankaj Gupta +Reviewed-by: Stefan Hajnoczi +Signed-off-by: Eduardo Habkost + +(cherry picked from commit 119906afa5ca610adb87c55ab0d8e53c9104bfc3) +Signed-off-by: Paul Lai +Signed-off-by: Danilo C. L. de Paula +--- + docs/nvdimm.txt | 22 +++++++++++++++++++--- + qemu-options.hx | 5 +++++ + util/mmap-alloc.c | 41 ++++++++++++++++++++++++++++++++++++++++- + 3 files changed, 64 insertions(+), 4 deletions(-) + +diff --git a/docs/nvdimm.txt b/docs/nvdimm.txt +index 5f158a6..33ce9aa 100644 +--- a/docs/nvdimm.txt ++++ b/docs/nvdimm.txt +@@ -143,9 +143,25 @@ Guest Data Persistence + ---------------------- + + Though QEMU supports multiple types of vNVDIMM backends on Linux, +-currently the only one that can guarantee the guest write persistence +-is the device DAX on the real NVDIMM device (e.g., /dev/dax0.0), to +-which all guest access do not involve any host-side kernel cache. ++the only backend that can guarantee the guest write persistence is: ++ ++A. DAX device (e.g., /dev/dax0.0, ) or ++B. DAX file(mounted with dax option) ++ ++When using B (A file supporting direct mapping of persistent memory) ++as a backend, write persistence is guaranteed if the host kernel has ++support for the MAP_SYNC flag in the mmap system call (available ++since Linux 4.15 and on certain distro kernels) and additionally ++both 'pmem' and 'share' flags are set to 'on' on the backend. ++ ++If these conditions are not satisfied i.e. if either 'pmem' or 'share' ++are not set, if the backend file does not support DAX or if MAP_SYNC ++is not supported by the host kernel, write persistence is not ++guaranteed after a system crash. For compatibility reasons, these ++conditions are ignored if not satisfied. Currently, no way is ++provided to test for them. ++For more details, please reference mmap(2) man page: ++http://man7.org/linux/man-pages/man2/mmap.2.html. + + When using other types of backends, it's suggested to set 'unarmed' + option of '-device nvdimm' to 'on', which sets the unarmed flag of the +diff --git a/qemu-options.hx b/qemu-options.hx +index 1b6786b..1243057 100644 +--- a/qemu-options.hx ++++ b/qemu-options.hx +@@ -4057,6 +4057,11 @@ using the SNIA NVM programming model (e.g. Intel NVDIMM). + If @option{pmem} is set to 'on', QEMU will take necessary operations to + guarantee the persistence of its own writes to @option{mem-path} + (e.g. in vNVDIMM label emulation and live migration). ++Also, we will map the backend-file with MAP_SYNC flag, which ensures the ++file metadata is in sync for @option{mem-path} in case of host crash ++or a power failure. MAP_SYNC requires support from both the host kernel ++(since Linux kernel 4.15) and the filesystem of @option{mem-path} mounted ++with DAX option. + + @item -object memory-backend-ram,id=@var{id},merge=@var{on|off},dump=@var{on|off},share=@var{on|off},prealloc=@var{on|off},size=@var{size},host-nodes=@var{host-nodes},policy=@var{default|preferred|bind|interleave} + +diff --git a/util/mmap-alloc.c b/util/mmap-alloc.c +index bbd9077..4873984 100644 +--- a/util/mmap-alloc.c ++++ b/util/mmap-alloc.c +@@ -10,6 +10,13 @@ + * later. See the COPYING file in the top-level directory. + */ + ++#ifdef CONFIG_LINUX ++#include ++#else /* !CONFIG_LINUX */ ++#define MAP_SYNC 0x0 ++#define MAP_SHARED_VALIDATE 0x0 ++#endif /* CONFIG_LINUX */ ++ + #include "qemu/osdep.h" + #include "qemu/mmap-alloc.h" + #include "qemu/host-utils.h" +@@ -80,6 +87,7 @@ void *qemu_ram_mmap(int fd, + bool is_pmem) + { + int flags; ++ int map_sync_flags = 0; + int guardfd; + size_t offset; + size_t pagesize; +@@ -130,9 +138,40 @@ void *qemu_ram_mmap(int fd, + flags = MAP_FIXED; + flags |= fd == -1 ? MAP_ANONYMOUS : 0; + flags |= shared ? MAP_SHARED : MAP_PRIVATE; ++ if (shared && is_pmem) { ++ map_sync_flags = MAP_SYNC | MAP_SHARED_VALIDATE; ++ } ++ + offset = QEMU_ALIGN_UP((uintptr_t)guardptr, align) - (uintptr_t)guardptr; + +- ptr = mmap(guardptr + offset, size, PROT_READ | PROT_WRITE, flags, fd, 0); ++ ptr = mmap(guardptr + offset, size, PROT_READ | PROT_WRITE, ++ flags | map_sync_flags, fd, 0); ++ ++ if (ptr == MAP_FAILED && map_sync_flags) { ++ if (errno == ENOTSUP) { ++ char *proc_link, *file_name; ++ int len; ++ proc_link = g_strdup_printf("/proc/self/fd/%d", fd); ++ file_name = g_malloc0(PATH_MAX); ++ len = readlink(proc_link, file_name, PATH_MAX - 1); ++ if (len < 0) { ++ len = 0; ++ } ++ file_name[len] = '\0'; ++ fprintf(stderr, "Warning: requesting persistence across crashes " ++ "for backend file %s failed. Proceeding without " ++ "persistence, data might become corrupted in case of host " ++ "crash.\n", file_name); ++ g_free(proc_link); ++ g_free(file_name); ++ } ++ /* ++ * if map failed with MAP_SHARED_VALIDATE | MAP_SYNC, ++ * we will remove these flags to handle compatibility. ++ */ ++ ptr = mmap(guardptr + offset, size, PROT_READ | PROT_WRITE, ++ flags, fd, 0); ++ } + + if (ptr == MAP_FAILED) { + munmap(guardptr, total); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-vhost-fix-vhost_log-size-overflow-during-migration.patch b/SOURCES/kvm-vhost-fix-vhost_log-size-overflow-during-migration.patch new file mode 100644 index 0000000..b18a29e --- /dev/null +++ b/SOURCES/kvm-vhost-fix-vhost_log-size-overflow-during-migration.patch @@ -0,0 +1,81 @@ +From 8c80943cfe6e8e50f0a18cc2b4f09f9eefed47dc Mon Sep 17 00:00:00 2001 +From: "Dr. David Alan Gilbert" +Date: Tue, 26 Nov 2019 16:29:02 +0000 +Subject: [PATCH 16/16] vhost: fix vhost_log size overflow during migration + +RH-Author: Dr. David Alan Gilbert +Message-id: <20191126162902.46145-2-dgilbert@redhat.com> +Patchwork-id: 92689 +O-Subject: [RHEL-AV-8.2.0 qemu-kvm PATCH 1/1] vhost: fix vhost_log size overflow during migration +Bugzilla: 1776808 +RH-Acked-by: Peter Xu +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Michael S. Tsirkin + +From: Li Hangjing + +When a guest which doesn't support multiqueue is migrated with a multi queues +vhost-user-blk deivce, a crash will occur like: + +0 qemu_memfd_alloc (name=, size=562949953421312, seals=, fd=0x7f87171fe8b4, errp=0x7f87171fe8a8) at util/memfd.c:153 +1 0x00007f883559d7cf in vhost_log_alloc (size=70368744177664, share=true) at hw/virtio/vhost.c:186 +2 0x00007f88355a0758 in vhost_log_get (listener=0x7f8838bd7940, enable=1) at qemu-2-12/hw/virtio/vhost.c:211 +3 vhost_dev_log_resize (listener=0x7f8838bd7940, enable=1) at hw/virtio/vhost.c:263 +4 vhost_migration_log (listener=0x7f8838bd7940, enable=1) at hw/virtio/vhost.c:787 +5 0x00007f88355463d6 in memory_global_dirty_log_start () at memory.c:2503 +6 0x00007f8835550577 in ram_init_bitmaps (f=0x7f88384ce600, opaque=0x7f8836024098) at migration/ram.c:2173 +7 ram_init_all (f=0x7f88384ce600, opaque=0x7f8836024098) at migration/ram.c:2192 +8 ram_save_setup (f=0x7f88384ce600, opaque=0x7f8836024098) at migration/ram.c:2219 +9 0x00007f88357a419d in qemu_savevm_state_setup (f=0x7f88384ce600) at migration/savevm.c:1002 +10 0x00007f883579fc3e in migration_thread (opaque=0x7f8837530400) at migration/migration.c:2382 +11 0x00007f8832447893 in start_thread () from /lib64/libpthread.so.0 +12 0x00007f8832178bfd in clone () from /lib64/libc.so.6 + +This is because vhost_get_log_size() returns a overflowed vhost-log size. +In this function, it uses the uninitialized variable vqs->used_phys and +vqs->used_size to get the vhost-log size. + +Signed-off-by: Li Hangjing +Reviewed-by: Xie Yongji +Reviewed-by: Chai Wen +Message-Id: <20190603061524.24076-1-lihangjing@baidu.com> +Cc: qemu-stable@nongnu.org +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +(cherry picked from commit 240e647a14df9677b3a501f7b8b870e40aac3fd5) +Signed-off-by: Danilo C. L. de Paula +--- + hw/virtio/vhost.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c +index 1ae68ff..7bdc9c4 100644 +--- a/hw/virtio/vhost.c ++++ b/hw/virtio/vhost.c +@@ -131,6 +131,11 @@ static int vhost_sync_dirty_bitmap(struct vhost_dev *dev, + } + for (i = 0; i < dev->nvqs; ++i) { + struct vhost_virtqueue *vq = dev->vqs + i; ++ ++ if (!vq->used_phys && !vq->used_size) { ++ continue; ++ } ++ + vhost_dev_sync_region(dev, section, start_addr, end_addr, vq->used_phys, + range_get_last(vq->used_phys, vq->used_size)); + } +@@ -168,6 +173,11 @@ static uint64_t vhost_get_log_size(struct vhost_dev *dev) + } + for (i = 0; i < dev->nvqs; ++i) { + struct vhost_virtqueue *vq = dev->vqs + i; ++ ++ if (!vq->used_phys && !vq->used_size) { ++ continue; ++ } ++ + uint64_t last = vq->used_phys + vq->used_size - 1; + log_size = MAX(log_size, last / VHOST_LOG_CHUNK + 1); + } +-- +1.8.3.1 + diff --git a/SOURCES/kvm-virtio-blk-Cancel-the-pending-BH-when-the-dataplane-.patch b/SOURCES/kvm-virtio-blk-Cancel-the-pending-BH-when-the-dataplane-.patch new file mode 100644 index 0000000..4f86110 --- /dev/null +++ b/SOURCES/kvm-virtio-blk-Cancel-the-pending-BH-when-the-dataplane-.patch @@ -0,0 +1,92 @@ +From 93a7832d5dfd83f170119e7130f3968fe37fa8e6 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Fri, 13 Sep 2019 14:16:25 +0100 +Subject: [PATCH 08/22] virtio-blk: Cancel the pending BH when the dataplane is + reset +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Philippe Mathieu-Daudé +Message-id: <20190913141625.12521-2-philmd@redhat.com> +Patchwork-id: 90453 +O-Subject: [RHEL-7.7.z qemu-kvm-rhev + RHEL-8.1.0 qemu-kvm + RHEL-AV-8.1.0 qemu-kvm PATCH v2 1/1] virtio-blk: Cancel the pending BH when the dataplane is reset +Bugzilla: 1708459 +RH-Acked-by: John Snow +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Danilo de Paula + +When 'system_reset' is called, the main loop clear the memory +region cache before the BH has a chance to execute. Later when +the deferred function is called, some assumptions that were +made when scheduling them are no longer true when they actually +execute. + +This is what happens using a virtio-blk device (fresh RHEL7.8 install): + + $ (sleep 12.3; echo system_reset; sleep 12.3; echo system_reset; sleep 1; echo q) \ + | qemu-system-x86_64 -m 4G -smp 8 -boot menu=on \ + -device virtio-blk-pci,id=image1,drive=drive_image1 \ + -drive file=/var/lib/libvirt/images/rhel78.qcow2,if=none,id=drive_image1,format=qcow2,cache=none \ + -device virtio-net-pci,netdev=net0,id=nic0,mac=52:54:00:c4:e7:84 \ + -netdev tap,id=net0,script=/bin/true,downscript=/bin/true,vhost=on \ + -monitor stdio -serial null -nographic + (qemu) system_reset + (qemu) system_reset + (qemu) qemu-system-x86_64: hw/virtio/virtio.c:225: vring_get_region_caches: Assertion `caches != NULL' failed. + Aborted + + (gdb) bt + Thread 1 (Thread 0x7f109c17b680 (LWP 10939)): + #0 0x00005604083296d1 in vring_get_region_caches (vq=0x56040a24bdd0) at hw/virtio/virtio.c:227 + #1 0x000056040832972b in vring_avail_flags (vq=0x56040a24bdd0) at hw/virtio/virtio.c:235 + #2 0x000056040832d13d in virtio_should_notify (vdev=0x56040a240630, vq=0x56040a24bdd0) at hw/virtio/virtio.c:1648 + #3 0x000056040832d1f8 in virtio_notify_irqfd (vdev=0x56040a240630, vq=0x56040a24bdd0) at hw/virtio/virtio.c:1662 + #4 0x00005604082d213d in notify_guest_bh (opaque=0x56040a243ec0) at hw/block/dataplane/virtio-blk.c:75 + #5 0x000056040883dc35 in aio_bh_call (bh=0x56040a243f10) at util/async.c:90 + #6 0x000056040883dccd in aio_bh_poll (ctx=0x560409161980) at util/async.c:118 + #7 0x0000560408842af7 in aio_dispatch (ctx=0x560409161980) at util/aio-posix.c:460 + #8 0x000056040883e068 in aio_ctx_dispatch (source=0x560409161980, callback=0x0, user_data=0x0) at util/async.c:261 + #9 0x00007f10a8fca06d in g_main_context_dispatch () at /lib64/libglib-2.0.so.0 + #10 0x0000560408841445 in glib_pollfds_poll () at util/main-loop.c:215 + #11 0x00005604088414bf in os_host_main_loop_wait (timeout=0) at util/main-loop.c:238 + #12 0x00005604088415c4 in main_loop_wait (nonblocking=0) at util/main-loop.c:514 + #13 0x0000560408416b1e in main_loop () at vl.c:1923 + #14 0x000056040841e0e8 in main (argc=20, argv=0x7ffc2c3f9c58, envp=0x7ffc2c3f9d00) at vl.c:4578 + +Fix this by cancelling the BH when the virtio dataplane is stopped. + +[This is version of the patch was modified as discussed with Philippe on +the mailing list thread. +--Stefan] + +Reported-by: Yihuang Yu +Suggested-by: Stefan Hajnoczi +Fixes: https://bugs.launchpad.net/qemu/+bug/1839428 +Signed-off-by: Philippe Mathieu-Daudé +Message-Id: <20190816171503.24761-1-philmd@redhat.com> +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit ebb6ff25cd888a52a64a9adc3692541c6d1d9a42) +Signed-off-by: Philippe Mathieu-Daudé +Signed-off-by: Danilo C. L. de Paula +--- + hw/block/dataplane/virtio-blk.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c +index 101f32c..23e4022 100644 +--- a/hw/block/dataplane/virtio-blk.c ++++ b/hw/block/dataplane/virtio-blk.c +@@ -292,6 +292,9 @@ void virtio_blk_data_plane_stop(VirtIODevice *vdev) + virtio_bus_cleanup_host_notifier(VIRTIO_BUS(qbus), i); + } + ++ qemu_bh_cancel(s->bh); ++ notify_guest_bh(s); /* final chance to notify guest */ ++ + /* Clean up guest notifier (irq) */ + k->set_guest_notifiers(qbus->parent, nvqs, false); + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-virtio-blk-Increase-in_flight-for-request-restart-BH.patch b/SOURCES/kvm-virtio-blk-Increase-in_flight-for-request-restart-BH.patch new file mode 100644 index 0000000..27c6935 --- /dev/null +++ b/SOURCES/kvm-virtio-blk-Increase-in_flight-for-request-restart-BH.patch @@ -0,0 +1,62 @@ +From 2f11a1952881d9e2dcc8acb3549441dbd9ade1e3 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Wed, 14 Aug 2019 08:42:26 +0100 +Subject: [PATCH 03/10] virtio-blk: Increase in_flight for request restart BH + +RH-Author: Kevin Wolf +Message-id: <20190814084229.6458-3-kwolf@redhat.com> +Patchwork-id: 89967 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 2/5] virtio-blk: Increase in_flight for request restart BH +Bugzilla: 1716349 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Max Reitz +RH-Acked-by: Paolo Bonzini + +virtio_blk_dma_restart_bh() submits new requests, so in order to make +sure that these requests are not started inside a drained section of the +attached BlockBackend, we need to make sure that draining the +BlockBackend waits for the BH to be executed. + +This BH is still questionable because its scheduled in the main thread +instead of the configured iothread. Leave a FIXME comment for this. + +But with this fix, enabling the data plane at least waits for these +requests (in bdrv_set_aio_context()) instead of changing the AioContext +under their feet and making them run in the wrong thread, causing +crashes and failures (e.g. due to missing locking). + +Signed-off-by: Kevin Wolf +(cherry picked from commit 680f200217748e0920b79ec1d524717c2f50935b) +Signed-off-by: Kevin Wolf +Signed-off-by: Danilo C. L. de Paula +--- + hw/block/virtio-blk.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c +index b1532e4..691ade4 100644 +--- a/hw/block/virtio-blk.c ++++ b/hw/block/virtio-blk.c +@@ -678,6 +678,7 @@ static void virtio_blk_dma_restart_bh(void *opaque) + if (mrb.num_reqs) { + virtio_blk_submit_multireq(s->blk, &mrb); + } ++ blk_dec_in_flight(s->conf.conf.blk); + aio_context_release(blk_get_aio_context(s->conf.conf.blk)); + } + +@@ -691,8 +692,11 @@ static void virtio_blk_dma_restart_cb(void *opaque, int running, + } + + if (!s->bh) { ++ /* FIXME The data plane is not started yet, so these requests are ++ * processed in the main thread. */ + s->bh = aio_bh_new(blk_get_aio_context(s->conf.conf.blk), + virtio_blk_dma_restart_bh, s); ++ blk_inc_in_flight(s->conf.conf.blk); + qemu_bh_schedule(s->bh); + } + } +-- +1.8.3.1 + diff --git a/SOURCES/kvm-virtio-gpu-add-iommu-support.patch b/SOURCES/kvm-virtio-gpu-add-iommu-support.patch new file mode 100644 index 0000000..d66a172 --- /dev/null +++ b/SOURCES/kvm-virtio-gpu-add-iommu-support.patch @@ -0,0 +1,99 @@ +From c6874c974165bd783649ae9e0fb4390881c5e79c Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Thu, 4 Jul 2019 10:32:06 +0200 +Subject: [PATCH 3/4] virtio-gpu: add iommu support +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Gerd Hoffmann +Message-id: <20190704103207.29158-3-kraxel@redhat.com> +Patchwork-id: 89371 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v2 2/3] virtio-gpu: add iommu support +Bugzilla: 1531543 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Stefan Hajnoczi + +Switch from cpu_physical_memory_map to dma_memory_map, +so iommu mappings for virtio-gpu objects work properly. + +Signed-off-by: Gerd Hoffmann +Message-Id: <20180829122101.29852-3-kraxel@redhat.com> +(cherry picked from commit 8da132a56f7ebaabc5b674b5a3a2e6fa8934be45) +Signed-off-by: Miroslav Rezanina +--- + hw/display/virtio-gpu.c | 25 ++++++++++++++----------- + 1 file changed, 14 insertions(+), 11 deletions(-) + +diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c +index cb77ece..327c2be 100644 +--- a/hw/display/virtio-gpu.c ++++ b/hw/display/virtio-gpu.c +@@ -16,6 +16,7 @@ + #include "qemu/iov.h" + #include "ui/console.h" + #include "trace.h" ++#include "sysemu/dma.h" + #include "hw/virtio/virtio.h" + #include "hw/virtio/virtio-gpu.h" + #include "hw/virtio/virtio-bus.h" +@@ -725,7 +726,8 @@ int virtio_gpu_create_mapping_iov(VirtIOGPU *g, + uint32_t l = le32_to_cpu(ents[i].length); + hwaddr len = l; + (*iov)[i].iov_len = l; +- (*iov)[i].iov_base = cpu_physical_memory_map(a, &len, 1); ++ (*iov)[i].iov_base = dma_memory_map(VIRTIO_DEVICE(g)->dma_as, ++ a, &len, DMA_DIRECTION_TO_DEVICE); + if (addr) { + (*addr)[i] = a; + } +@@ -753,8 +755,10 @@ void virtio_gpu_cleanup_mapping_iov(VirtIOGPU *g, + int i; + + for (i = 0; i < count; i++) { +- cpu_physical_memory_unmap(iov[i].iov_base, iov[i].iov_len, 1, +- iov[i].iov_len); ++ dma_memory_unmap(VIRTIO_DEVICE(g)->dma_as, ++ iov[i].iov_base, iov[i].iov_len, ++ DMA_DIRECTION_TO_DEVICE, ++ iov[i].iov_len); + } + g_free(iov); + } +@@ -1146,13 +1150,17 @@ static int virtio_gpu_load(QEMUFile *f, void *opaque, size_t size, + for (i = 0; i < res->iov_cnt; i++) { + hwaddr len = res->iov[i].iov_len; + res->iov[i].iov_base = +- cpu_physical_memory_map(res->addrs[i], &len, 1); ++ dma_memory_map(VIRTIO_DEVICE(g)->dma_as, ++ res->addrs[i], &len, DMA_DIRECTION_TO_DEVICE); + + if (!res->iov[i].iov_base || len != res->iov[i].iov_len) { + /* Clean up the half-a-mapping we just created... */ + if (res->iov[i].iov_base) { +- cpu_physical_memory_unmap(res->iov[i].iov_base, +- len, 0, 0); ++ dma_memory_unmap(VIRTIO_DEVICE(g)->dma_as, ++ res->iov[i].iov_base, ++ res->iov[i].iov_len, ++ DMA_DIRECTION_TO_DEVICE, ++ res->iov[i].iov_len); + } + /* ...and the mappings for previous loop iterations */ + res->iov_cnt = i; +@@ -1204,11 +1212,6 @@ static void virtio_gpu_device_realize(DeviceState *qdev, Error **errp) + Error *local_err = NULL; + int i; + +- if (virtio_host_has_feature(vdev, VIRTIO_F_IOMMU_PLATFORM)) { +- error_setg(errp, "virtio-gpu does not support vIOMMU yet"); +- return; +- } +- + if (g->conf.max_outputs > VIRTIO_GPU_MAX_SCANOUTS) { + error_setg(errp, "invalid max_outputs > %d", VIRTIO_GPU_MAX_SCANOUTS); + return; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-virtio-gpu-fix-unmap-in-error-path.patch b/SOURCES/kvm-virtio-gpu-fix-unmap-in-error-path.patch new file mode 100644 index 0000000..712e2e4 --- /dev/null +++ b/SOURCES/kvm-virtio-gpu-fix-unmap-in-error-path.patch @@ -0,0 +1,52 @@ +From 29e3a6aebf124a88b26fd49a2dd0a99c38f918aa Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Thu, 4 Jul 2019 10:32:07 +0200 +Subject: [PATCH 4/4] virtio-gpu: fix unmap in error path +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Gerd Hoffmann +Message-id: <20190704103207.29158-4-kraxel@redhat.com> +Patchwork-id: 89373 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v2 3/3] virtio-gpu: fix unmap in error path +Bugzilla: 1531543 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Stefan Hajnoczi + +We land here in case not everything we've asked for could be mapped. +So unmap only the bytes which have actually been mapped. + +Also we didn't access anything, so acces_len can be 0. + +Reported-by: Laszlo Ersek +Signed-off-by: Gerd Hoffmann +Reviewed-by: Laszlo Ersek +Reviewed-by: Li Qiang +Message-id: 20190628072357.31782-1-kraxel@redhat.com +(cherry picked from commit a7f85e03b94ffaca75332cddf06426fc85ac611a) +Signed-off-by: Miroslav Rezanina +--- + hw/display/virtio-gpu.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c +index 327c2be..07712d0 100644 +--- a/hw/display/virtio-gpu.c ++++ b/hw/display/virtio-gpu.c +@@ -1158,9 +1158,9 @@ static int virtio_gpu_load(QEMUFile *f, void *opaque, size_t size, + if (res->iov[i].iov_base) { + dma_memory_unmap(VIRTIO_DEVICE(g)->dma_as, + res->iov[i].iov_base, +- res->iov[i].iov_len, ++ len, + DMA_DIRECTION_TO_DEVICE, +- res->iov[i].iov_len); ++ 0); + } + /* ...and the mappings for previous loop iterations */ + res->iov_cnt = i; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-virtio-gpu-pass-down-VirtIOGPU-pointer-to-a-bunch-of.patch b/SOURCES/kvm-virtio-gpu-pass-down-VirtIOGPU-pointer-to-a-bunch-of.patch new file mode 100644 index 0000000..33eb58b --- /dev/null +++ b/SOURCES/kvm-virtio-gpu-pass-down-VirtIOGPU-pointer-to-a-bunch-of.patch @@ -0,0 +1,193 @@ +From 5b896af413dae0e4933a6e5c277bfe7b4f2f9bb4 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Thu, 4 Jul 2019 10:32:05 +0200 +Subject: [PATCH 2/4] virtio-gpu: pass down VirtIOGPU pointer to a bunch of + functions +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Gerd Hoffmann +Message-id: <20190704103207.29158-2-kraxel@redhat.com> +Patchwork-id: 89374 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v2 1/3] virtio-gpu: pass down VirtIOGPU pointer to a bunch of functions +Bugzilla: 1531543 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Stefan Hajnoczi + +No functional change, just preparation for a followup patch +which needs a VirtIOGPU pointer. + +Signed-off-by: Gerd Hoffmann +Message-Id: <20180829122101.29852-2-kraxel@redhat.com> +(cherry picked from commit 3bb68f798da0234d5ca0ac6062aaa084afc83069) +Signed-off-by: Miroslav Rezanina +--- + hw/display/virtio-gpu-3d.c | 8 ++++---- + hw/display/virtio-gpu.c | 25 +++++++++++++++---------- + include/hw/virtio/virtio-gpu.h | 6 ++++-- + 3 files changed, 23 insertions(+), 16 deletions(-) + +diff --git a/hw/display/virtio-gpu-3d.c b/hw/display/virtio-gpu-3d.c +index 3558f38..55d7640 100644 +--- a/hw/display/virtio-gpu-3d.c ++++ b/hw/display/virtio-gpu-3d.c +@@ -86,7 +86,7 @@ static void virgl_cmd_resource_unref(VirtIOGPU *g, + &res_iovs, + &num_iovs); + if (res_iovs != NULL && num_iovs != 0) { +- virtio_gpu_cleanup_mapping_iov(res_iovs, num_iovs); ++ virtio_gpu_cleanup_mapping_iov(g, res_iovs, num_iovs); + } + virgl_renderer_resource_unref(unref.resource_id); + } +@@ -291,7 +291,7 @@ static void virgl_resource_attach_backing(VirtIOGPU *g, + VIRTIO_GPU_FILL_CMD(att_rb); + trace_virtio_gpu_cmd_res_back_attach(att_rb.resource_id); + +- ret = virtio_gpu_create_mapping_iov(&att_rb, cmd, NULL, &res_iovs); ++ ret = virtio_gpu_create_mapping_iov(g, &att_rb, cmd, NULL, &res_iovs); + if (ret != 0) { + cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC; + return; +@@ -301,7 +301,7 @@ static void virgl_resource_attach_backing(VirtIOGPU *g, + res_iovs, att_rb.nr_entries); + + if (ret != 0) +- virtio_gpu_cleanup_mapping_iov(res_iovs, att_rb.nr_entries); ++ virtio_gpu_cleanup_mapping_iov(g, res_iovs, att_rb.nr_entries); + } + + static void virgl_resource_detach_backing(VirtIOGPU *g, +@@ -320,7 +320,7 @@ static void virgl_resource_detach_backing(VirtIOGPU *g, + if (res_iovs == NULL || num_iovs == 0) { + return; + } +- virtio_gpu_cleanup_mapping_iov(res_iovs, num_iovs); ++ virtio_gpu_cleanup_mapping_iov(g, res_iovs, num_iovs); + } + + +diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c +index 08cd567..cb77ece 100644 +--- a/hw/display/virtio-gpu.c ++++ b/hw/display/virtio-gpu.c +@@ -28,7 +28,8 @@ + static struct virtio_gpu_simple_resource* + virtio_gpu_find_resource(VirtIOGPU *g, uint32_t resource_id); + +-static void virtio_gpu_cleanup_mapping(struct virtio_gpu_simple_resource *res); ++static void virtio_gpu_cleanup_mapping(VirtIOGPU *g, ++ struct virtio_gpu_simple_resource *res); + + static void + virtio_gpu_ctrl_hdr_bswap(struct virtio_gpu_ctrl_hdr *hdr) +@@ -441,7 +442,7 @@ static void virtio_gpu_resource_destroy(VirtIOGPU *g, + } + + pixman_image_unref(res->image); +- virtio_gpu_cleanup_mapping(res); ++ virtio_gpu_cleanup_mapping(g, res); + QTAILQ_REMOVE(&g->reslist, res, next); + g->hostmem -= res->hostmem; + g_free(res); +@@ -687,7 +688,8 @@ static void virtio_gpu_set_scanout(VirtIOGPU *g, + scanout->height = ss.r.height; + } + +-int virtio_gpu_create_mapping_iov(struct virtio_gpu_resource_attach_backing *ab, ++int virtio_gpu_create_mapping_iov(VirtIOGPU *g, ++ struct virtio_gpu_resource_attach_backing *ab, + struct virtio_gpu_ctrl_command *cmd, + uint64_t **addr, struct iovec **iov) + { +@@ -731,7 +733,7 @@ int virtio_gpu_create_mapping_iov(struct virtio_gpu_resource_attach_backing *ab, + qemu_log_mask(LOG_GUEST_ERROR, "%s: failed to map MMIO memory for" + " resource %d element %d\n", + __func__, ab->resource_id, i); +- virtio_gpu_cleanup_mapping_iov(*iov, i); ++ virtio_gpu_cleanup_mapping_iov(g, *iov, i); + g_free(ents); + *iov = NULL; + if (addr) { +@@ -745,7 +747,8 @@ int virtio_gpu_create_mapping_iov(struct virtio_gpu_resource_attach_backing *ab, + return 0; + } + +-void virtio_gpu_cleanup_mapping_iov(struct iovec *iov, uint32_t count) ++void virtio_gpu_cleanup_mapping_iov(VirtIOGPU *g, ++ struct iovec *iov, uint32_t count) + { + int i; + +@@ -756,9 +759,10 @@ void virtio_gpu_cleanup_mapping_iov(struct iovec *iov, uint32_t count) + g_free(iov); + } + +-static void virtio_gpu_cleanup_mapping(struct virtio_gpu_simple_resource *res) ++static void virtio_gpu_cleanup_mapping(VirtIOGPU *g, ++ struct virtio_gpu_simple_resource *res) + { +- virtio_gpu_cleanup_mapping_iov(res->iov, res->iov_cnt); ++ virtio_gpu_cleanup_mapping_iov(g, res->iov, res->iov_cnt); + res->iov = NULL; + res->iov_cnt = 0; + g_free(res->addrs); +@@ -790,7 +794,7 @@ virtio_gpu_resource_attach_backing(VirtIOGPU *g, + return; + } + +- ret = virtio_gpu_create_mapping_iov(&ab, cmd, &res->addrs, &res->iov); ++ ret = virtio_gpu_create_mapping_iov(g, &ab, cmd, &res->addrs, &res->iov); + if (ret != 0) { + cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC; + return; +@@ -817,7 +821,7 @@ virtio_gpu_resource_detach_backing(VirtIOGPU *g, + cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID; + return; + } +- virtio_gpu_cleanup_mapping(res); ++ virtio_gpu_cleanup_mapping(g, res); + } + + static void virtio_gpu_simple_process_cmd(VirtIOGPU *g, +@@ -1143,6 +1147,7 @@ static int virtio_gpu_load(QEMUFile *f, void *opaque, size_t size, + hwaddr len = res->iov[i].iov_len; + res->iov[i].iov_base = + cpu_physical_memory_map(res->addrs[i], &len, 1); ++ + if (!res->iov[i].iov_base || len != res->iov[i].iov_len) { + /* Clean up the half-a-mapping we just created... */ + if (res->iov[i].iov_base) { +@@ -1151,7 +1156,7 @@ static int virtio_gpu_load(QEMUFile *f, void *opaque, size_t size, + } + /* ...and the mappings for previous loop iterations */ + res->iov_cnt = i; +- virtio_gpu_cleanup_mapping(res); ++ virtio_gpu_cleanup_mapping(g, res); + pixman_image_unref(res->image); + g_free(res); + return -EINVAL; +diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h +index 22ac3c2..f95f8ce 100644 +--- a/include/hw/virtio/virtio-gpu.h ++++ b/include/hw/virtio/virtio-gpu.h +@@ -158,10 +158,12 @@ void virtio_gpu_ctrl_response_nodata(VirtIOGPU *g, + enum virtio_gpu_ctrl_type type); + void virtio_gpu_get_display_info(VirtIOGPU *g, + struct virtio_gpu_ctrl_command *cmd); +-int virtio_gpu_create_mapping_iov(struct virtio_gpu_resource_attach_backing *ab, ++int virtio_gpu_create_mapping_iov(VirtIOGPU *g, ++ struct virtio_gpu_resource_attach_backing *ab, + struct virtio_gpu_ctrl_command *cmd, + uint64_t **addr, struct iovec **iov); +-void virtio_gpu_cleanup_mapping_iov(struct iovec *iov, uint32_t count); ++void virtio_gpu_cleanup_mapping_iov(VirtIOGPU *g, ++ struct iovec *iov, uint32_t count); + void virtio_gpu_process_cmdq(VirtIOGPU *g); + + /* virtio-gpu-3d.c */ +-- +1.8.3.1 + diff --git a/SOURCES/kvm-vmstate-Add-support-for-kernel-integer-types.patch b/SOURCES/kvm-vmstate-Add-support-for-kernel-integer-types.patch new file mode 100644 index 0000000..00d55c2 --- /dev/null +++ b/SOURCES/kvm-vmstate-Add-support-for-kernel-integer-types.patch @@ -0,0 +1,75 @@ +From 8f7ed484aec956d81684bc2795d3da6969b20727 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 22 Jul 2019 18:22:14 +0100 +Subject: [PATCH 33/39] vmstate: Add support for kernel integer types + +RH-Author: Paolo Bonzini +Message-id: <20190722182220.19374-13-pbonzini@redhat.com> +Patchwork-id: 89630 +O-Subject: [RHEL-8.1.0 PATCH qemu-kvm v3 12/18] vmstate: Add support for kernel integer types +Bugzilla: 1689269 +RH-Acked-by: Peter Xu +RH-Acked-by: Laurent Vivier +RH-Acked-by: Dr. David Alan Gilbert + +From: Liran Alon + +Reviewed-by: Nikita Leshenko +Reviewed-by: Maran Wilson +Signed-off-by: Liran Alon +Reviewed-by: Dr. David Alan Gilbert +Message-Id: <20190619162140.133674-8-liran.alon@oracle.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit 6cfd7639329062797c04ec79adb1023a8ba2fcb4) +Signed-off-by: Danilo C. L. de Paula +--- + include/migration/vmstate.h | 26 ++++++++++++++++++++++++++ + 1 file changed, 26 insertions(+) + +diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h +index df463fd..380a0fd 100644 +--- a/include/migration/vmstate.h ++++ b/include/migration/vmstate.h +@@ -755,6 +755,19 @@ extern const VMStateInfo vmstate_info_qtailq; + #define VMSTATE_UINT64_V(_f, _s, _v) \ + VMSTATE_SINGLE(_f, _s, _v, vmstate_info_uint64, uint64_t) + ++#ifdef CONFIG_LINUX ++ ++#define VMSTATE_U8_V(_f, _s, _v) \ ++ VMSTATE_SINGLE(_f, _s, _v, vmstate_info_uint8, __u8) ++#define VMSTATE_U16_V(_f, _s, _v) \ ++ VMSTATE_SINGLE(_f, _s, _v, vmstate_info_uint16, __u16) ++#define VMSTATE_U32_V(_f, _s, _v) \ ++ VMSTATE_SINGLE(_f, _s, _v, vmstate_info_uint32, __u32) ++#define VMSTATE_U64_V(_f, _s, _v) \ ++ VMSTATE_SINGLE(_f, _s, _v, vmstate_info_uint64, __u64) ++ ++#endif ++ + #define VMSTATE_BOOL(_f, _s) \ + VMSTATE_BOOL_V(_f, _s, 0) + +@@ -776,6 +789,19 @@ extern const VMStateInfo vmstate_info_qtailq; + #define VMSTATE_UINT64(_f, _s) \ + VMSTATE_UINT64_V(_f, _s, 0) + ++#ifdef CONFIG_LINUX ++ ++#define VMSTATE_U8(_f, _s) \ ++ VMSTATE_U8_V(_f, _s, 0) ++#define VMSTATE_U16(_f, _s) \ ++ VMSTATE_U16_V(_f, _s, 0) ++#define VMSTATE_U32(_f, _s) \ ++ VMSTATE_U32_V(_f, _s, 0) ++#define VMSTATE_U64(_f, _s) \ ++ VMSTATE_U64_V(_f, _s, 0) ++ ++#endif ++ + #define VMSTATE_UINT8_EQUAL(_f, _s, _err_hint) \ + VMSTATE_SINGLE_FULL(_f, _s, 0, 0, \ + vmstate_info_uint8_equal, uint8_t, _err_hint) +-- +1.8.3.1 + diff --git a/SOURCES/kvm-vmxcap-correct-the-name-of-the-variables.patch b/SOURCES/kvm-vmxcap-correct-the-name-of-the-variables.patch new file mode 100644 index 0000000..074f148 --- /dev/null +++ b/SOURCES/kvm-vmxcap-correct-the-name-of-the-variables.patch @@ -0,0 +1,55 @@ +From 0d087d9d5276866b7a7c17cdb23e71b5636dc529 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Fri, 22 Nov 2019 11:53:43 +0000 +Subject: [PATCH 10/16] vmxcap: correct the name of the variables + +RH-Author: Paolo Bonzini +Message-id: <20191122115348.25000-11-pbonzini@redhat.com> +Patchwork-id: 92607 +O-Subject: [RHEL8.2/rhel qemu-kvm PATCH 10/15] vmxcap: correct the name of the variables +Bugzilla: 1689270 +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Maxim Levitsky + +The low bits are 1 if the control must be one, the high bits +are 1 if the control can be one. Correct the variable names +as they are very confusing. + +Signed-off-by: Paolo Bonzini +(cherry picked from commit 49d51b8927a9ea7267f4677a2e92f5046ce74025) +Signed-off-by: Danilo C. L. de Paula +--- + scripts/kvm/vmxcap | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/scripts/kvm/vmxcap b/scripts/kvm/vmxcap +index 99a8146..2db6832 100755 +--- a/scripts/kvm/vmxcap ++++ b/scripts/kvm/vmxcap +@@ -51,15 +51,15 @@ class Control(object): + return (val & 0xffffffff, val >> 32) + def show(self): + print(self.name) +- mbz, mb1 = self.read2(self.cap_msr) +- tmbz, tmb1 = 0, 0 ++ mb1, cb1 = self.read2(self.cap_msr) ++ tmb1, tcb1 = 0, 0 + if self.true_cap_msr: +- tmbz, tmb1 = self.read2(self.true_cap_msr) ++ tmb1, tcb1 = self.read2(self.true_cap_msr) + for bit in sorted(self.bits.keys()): +- zero = not (mbz & (1 << bit)) +- one = mb1 & (1 << bit) +- true_zero = not (tmbz & (1 << bit)) +- true_one = tmb1 & (1 << bit) ++ zero = not (mb1 & (1 << bit)) ++ one = cb1 & (1 << bit) ++ true_zero = not (tmb1 & (1 << bit)) ++ true_one = tcb1 & (1 << bit) + s= '?' + if (self.true_cap_msr and true_zero and true_one + and one and not zero): +-- +1.8.3.1 + diff --git a/SOURCES/kvm-vnc-detect-and-optimize-pageflips.patch b/SOURCES/kvm-vnc-detect-and-optimize-pageflips.patch new file mode 100644 index 0000000..eb67e2b --- /dev/null +++ b/SOURCES/kvm-vnc-detect-and-optimize-pageflips.patch @@ -0,0 +1,95 @@ +From 1b209dbf4eba1f7cdd456a809a2a8576e66a1464 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Tue, 13 Aug 2019 11:20:45 +0100 +Subject: [PATCH 01/10] vnc: detect and optimize pageflips +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Gerd Hoffmann +Message-id: <20190813112045.3887-2-kraxel@redhat.com> +Patchwork-id: 89956 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 1/1] vnc: detect and optimize pageflips +Bugzilla: 1727033 +RH-Acked-by: John Snow +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Thomas Huth + +When size and format of the display surface stays the same we can just +tag the guest display as dirty and be done with it. + +There is no need need to resize the vnc server display or to touch the +vnc client dirty bits. On the next refresh cycle +vnc_refresh_server_surface() will check for actual display content +changes and update the client dirty bits as needed. + +The desktop resize and framebuffer format notifications to the vnc +client will be skipped too. + +Signed-off-by: Gerd Hoffmann +Reviewed-by: Daniel P. Berrangé +Message-id: 20190116101049.8929-1-kraxel@redhat.com +(cherry picked from commit 61e77a5f0c788495566aecb437bcf6b2cf9cda97) +Signed-off-by: Danilo C. L. de Paula +--- + ui/vnc.c | 25 ++++++++++++++++++++++--- + 1 file changed, 22 insertions(+), 3 deletions(-) + +diff --git a/ui/vnc.c b/ui/vnc.c +index 86c6762..0bd44f1 100644 +--- a/ui/vnc.c ++++ b/ui/vnc.c +@@ -743,6 +743,17 @@ static void vnc_update_server_surface(VncDisplay *vd) + width, height); + } + ++static bool vnc_check_pageflip(DisplaySurface *s1, ++ DisplaySurface *s2) ++{ ++ return (s1 != NULL && ++ s2 != NULL && ++ surface_width(s1) == surface_width(s2) && ++ surface_height(s1) == surface_height(s2) && ++ surface_format(s1) == surface_format(s2)); ++ ++} ++ + static void vnc_dpy_switch(DisplayChangeListener *dcl, + DisplaySurface *surface) + { +@@ -750,6 +761,7 @@ static void vnc_dpy_switch(DisplayChangeListener *dcl, + "Display output is not active."; + static DisplaySurface *placeholder; + VncDisplay *vd = container_of(dcl, VncDisplay, dcl); ++ bool pageflip = vnc_check_pageflip(vd->ds, surface); + VncState *vs; + + if (surface == NULL) { +@@ -762,14 +774,21 @@ static void vnc_dpy_switch(DisplayChangeListener *dcl, + vnc_abort_display_jobs(vd); + vd->ds = surface; + +- /* server surface */ +- vnc_update_server_surface(vd); +- + /* guest surface */ + qemu_pixman_image_unref(vd->guest.fb); + vd->guest.fb = pixman_image_ref(surface->image); + vd->guest.format = surface->format; + ++ if (pageflip) { ++ vnc_set_area_dirty(vd->guest.dirty, vd, 0, 0, ++ surface_width(surface), ++ surface_height(surface)); ++ return; ++ } ++ ++ /* server surface */ ++ vnc_update_server_surface(vd); ++ + QTAILQ_FOREACH(vs, &vd->clients, next) { + vnc_colordepth(vs); + vnc_desktop_resize(vs); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-x86-cpu-Add-support-for-UMONITOR-UMWAIT-TPAUSE.patch b/SOURCES/kvm-x86-cpu-Add-support-for-UMONITOR-UMWAIT-TPAUSE.patch new file mode 100644 index 0000000..b8d255a --- /dev/null +++ b/SOURCES/kvm-x86-cpu-Add-support-for-UMONITOR-UMWAIT-TPAUSE.patch @@ -0,0 +1,108 @@ +From 7e7c5dab29ed99bda0fb5d810db6f12ae4aa2608 Mon Sep 17 00:00:00 2001 +From: "plai@redhat.com" +Date: Tue, 26 Nov 2019 18:36:54 +0000 +Subject: [PATCH 10/11] x86/cpu: Add support for UMONITOR/UMWAIT/TPAUSE +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +x86/cpu: Add support for UMONITOR/UMWAIT/TPAUSE + +RH-Author: plai@redhat.com +Message-id: <1574797015-32564-7-git-send-email-plai@redhat.com> +Patchwork-id: 92695 +O-Subject: [RHEL8.2 qemu-kvm PATCH 6/7] x86/cpu: Add support for UMONITOR/UMWAIT/TPAUSE +Bugzilla: 1634827 +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Michael S. Tsirkin +RH-Acked-by: Igor Mammedov + +From: Tao Xu + +UMONITOR, UMWAIT and TPAUSE are a set of user wait instructions. +This patch adds support for user wait instructions in KVM. Availability +of the user wait instructions is indicated by the presence of the CPUID +feature flag WAITPKG CPUID.0x07.0x0:ECX[5]. User wait instructions may +be executed at any privilege level, and use IA32_UMWAIT_CONTROL MSR to +set the maximum time. + +The patch enable the umonitor, umwait and tpause features in KVM. +Because umwait and tpause can put a (psysical) CPU into a power saving +state, by default we dont't expose it to kvm and enable it only when +guest CPUID has it. And use QEMU command-line "-overcommit cpu-pm=on" +(enable_cpu_pm is enabled), a VM can use UMONITOR, UMWAIT and TPAUSE +instructions. If the instruction causes a delay, the amount of time +delayed is called here the physical delay. The physical delay is first +computed by determining the virtual delay (the time to delay relative to +the VM’s timestamp counter). Otherwise, UMONITOR, UMWAIT and TPAUSE cause +an invalid-opcode exception(#UD). + +The release document ref below link: +https://software.intel.com/sites/default/files/\ +managed/39/c5/325462-sdm-vol-1-2abcd-3abcd.pdf + +Co-developed-by: Jingqi Liu +Signed-off-by: Jingqi Liu +Signed-off-by: Tao Xu +Message-Id: <20191011074103.30393-2-tao3.xu@intel.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit 67192a298f5bf98f96e5516c3b6474c49e4853cd) +Signed-off-by: Paul Lai + +Resolved Conflicts: + target/i386/cpu.c + target/i386/cpu.h + +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 2 +- + target/i386/cpu.h | 2 ++ + target/i386/kvm.c | 6 ++++++ + 3 files changed, 9 insertions(+), 1 deletion(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 87b0502..7d2afc7 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -1016,7 +1016,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + .type = CPUID_FEATURE_WORD, + .feat_names = { + NULL, "avx512vbmi", "umip", "pku", +- "ospke", NULL, "avx512vbmi2", NULL, ++ "ospke", "waitpkg", "avx512vbmi2", NULL, + "gfni", "vaes", "vpclmulqdq", "avx512vnni", + "avx512bitalg", NULL, "avx512-vpopcntdq", NULL, + "la57", NULL, NULL, NULL, +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index 7ab8ee9..fac98aa 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -708,6 +708,8 @@ typedef uint64_t FeatureWordArray[FEATURE_WORDS]; + #define CPUID_7_0_ECX_UMIP (1U << 2) + #define CPUID_7_0_ECX_PKU (1U << 3) + #define CPUID_7_0_ECX_OSPKE (1U << 4) ++/* UMONITOR/UMWAIT/TPAUSE Instructions */ ++#define CPUID_7_0_ECX_WAITPKG (1U << 5) + #define CPUID_7_0_ECX_VBMI2 (1U << 6) /* Additional VBMI Instrs */ + #define CPUID_7_0_ECX_GFNI (1U << 8) + #define CPUID_7_0_ECX_VAES (1U << 9) +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index ffd01f0..0fd5650 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -392,6 +392,12 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function, + if (host_tsx_blacklisted()) { + ret &= ~(CPUID_7_0_EBX_RTM | CPUID_7_0_EBX_HLE); + } ++ } else if (function == 7 && index == 0 && reg == R_ECX) { ++ if (enable_cpu_pm) { ++ ret |= CPUID_7_0_ECX_WAITPKG; ++ } else { ++ ret &= ~CPUID_7_0_ECX_WAITPKG; ++ } + } else if (function == 7 && index == 0 && reg == R_EDX) { + /* + * Linux v4.17-v4.20 incorrectly return ARCH_CAPABILITIES on SVM hosts. +-- +1.8.3.1 + diff --git a/SOURCES/kvm-x86-cpu-Enable-MOVDIR64B-cpu-feature.patch b/SOURCES/kvm-x86-cpu-Enable-MOVDIR64B-cpu-feature.patch new file mode 100644 index 0000000..005f5df --- /dev/null +++ b/SOURCES/kvm-x86-cpu-Enable-MOVDIR64B-cpu-feature.patch @@ -0,0 +1,71 @@ +From 04387fbe913b26a3819d711ea91b99be6faa8616 Mon Sep 17 00:00:00 2001 +From: "plai@redhat.com" +Date: Tue, 26 Nov 2019 19:36:50 +0000 +Subject: [PATCH 06/11] x86/cpu: Enable MOVDIR64B cpu feature + +RH-Author: plai@redhat.com +Message-id: <1574797015-32564-3-git-send-email-plai@redhat.com> +Patchwork-id: 92691 +O-Subject: [RHEL8.2 qemu-kvm PATCH 2/7] x86/cpu: Enable MOVDIR64B cpu feature +Bugzilla: 1634827 +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Michael S. Tsirkin +RH-Acked-by: Igor Mammedov + +From: Liu Jingqi + +MOVDIR64B moves 64-bytes as direct-store with 64-bytes write atomicity. +Direct store is implemented by using write combining (WC) for writing +data directly into memory without caching the data. + +The bit definition: +CPUID.(EAX=7,ECX=0):ECX[bit 28] MOVDIR64B + +The release document ref below link: +https://software.intel.com/sites/default/files/managed/c5/15/\ +architecture-instruction-set-extensions-programming-reference.pdf + +Cc: Xu Tao +Signed-off-by: Liu Jingqi +Message-Id: <1541488407-17045-3-git-send-email-jingqi.liu@intel.com> +Signed-off-by: Eduardo Habkost +(cherry picked from commit 1c65775ffc2dbd276a8bffe592feba0e186a151c) +Signed-off-by: Paul Lai + +Resolved Conflicts: + target/i386/cpu.c + +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 2 +- + target/i386/cpu.h | 1 + + 2 files changed, 2 insertions(+), 1 deletion(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index f2ab558..307b629 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -1022,7 +1022,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + "la57", NULL, NULL, NULL, + NULL, NULL, "rdpid", NULL, + NULL, "cldemote", NULL, "movdiri", +- NULL, NULL, NULL, NULL, ++ "movdir64b", NULL, NULL, NULL, + }, + .cpuid = { + .eax = 7, +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index 6ba0b1e..d33fa8d 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -719,6 +719,7 @@ typedef uint64_t FeatureWordArray[FEATURE_WORDS]; + #define CPUID_7_0_ECX_RDPID (1U << 22) + #define CPUID_7_0_ECX_CLDEMOTE (1U << 25) /* CLDEMOTE Instruction */ + #define CPUID_7_0_ECX_MOVDIRI (1U << 27) /* MOVDIRI Instruction */ ++#define CPUID_7_0_ECX_MOVDIR64B (1U << 28) /* MOVDIR64B Instruction */ + + #define CPUID_7_0_EDX_AVX512_4VNNIW (1U << 2) /* AVX512 Neural Network Instructions */ + #define CPUID_7_0_EDX_AVX512_4FMAPS (1U << 3) /* AVX512 Multiply Accumulation Single Precision */ +-- +1.8.3.1 + diff --git a/SOURCES/kvm-x86-cpu-Enable-MOVDIRI-cpu-feature.patch b/SOURCES/kvm-x86-cpu-Enable-MOVDIRI-cpu-feature.patch new file mode 100644 index 0000000..da10be4 --- /dev/null +++ b/SOURCES/kvm-x86-cpu-Enable-MOVDIRI-cpu-feature.patch @@ -0,0 +1,72 @@ +From a2765b13bbe4a4d5978cd25f451b35dbb137ab6e Mon Sep 17 00:00:00 2001 +From: "plai@redhat.com" +Date: Tue, 26 Nov 2019 19:36:49 +0000 +Subject: [PATCH 05/11] x86/cpu: Enable MOVDIRI cpu feature + +RH-Author: plai@redhat.com +Message-id: <1574797015-32564-2-git-send-email-plai@redhat.com> +Patchwork-id: 92696 +O-Subject: [RHEL8.2 qemu-kvm PATCH 1/7] x86/cpu: Enable MOVDIRI cpu feature +Bugzilla: 1634827 +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Michael S. Tsirkin +RH-Acked-by: Igor Mammedov + +From: Liu Jingqi + +MOVDIRI moves doubleword or quadword from register to memory through +direct store which is implemented by using write combining (WC) for +writing data directly into memory without caching the data. + +The bit definition: +CPUID.(EAX=7,ECX=0):ECX[bit 27] MOVDIRI + +The release document ref below link: +https://software.intel.com/sites/default/files/managed/c5/15/\ +architecture-instruction-set-extensions-programming-reference.pdf + +Cc: Xu Tao +Signed-off-by: Liu Jingqi +Message-Id: <1541488407-17045-2-git-send-email-jingqi.liu@intel.com> +Signed-off-by: Eduardo Habkost +(cherry picked from commit 24261de4916596d8ab5f5fee67e9e7a19e8325a5) +Signed-off-by: Paul Lai + +Resolved Conflicts: + target/i386/cpu.c + target/i386/cpu.h + +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 2 +- + target/i386/cpu.h | 1 + + 2 files changed, 2 insertions(+), 1 deletion(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index ef6b958..f2ab558 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -1021,7 +1021,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + "avx512bitalg", NULL, "avx512-vpopcntdq", NULL, + "la57", NULL, NULL, NULL, + NULL, NULL, "rdpid", NULL, +- NULL, "cldemote", NULL, NULL, ++ NULL, "cldemote", NULL, "movdiri", + NULL, NULL, NULL, NULL, + }, + .cpuid = { +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index 8d8814e..6ba0b1e 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -718,6 +718,7 @@ typedef uint64_t FeatureWordArray[FEATURE_WORDS]; + #define CPUID_7_0_ECX_LA57 (1U << 16) + #define CPUID_7_0_ECX_RDPID (1U << 22) + #define CPUID_7_0_ECX_CLDEMOTE (1U << 25) /* CLDEMOTE Instruction */ ++#define CPUID_7_0_ECX_MOVDIRI (1U << 27) /* MOVDIRI Instruction */ + + #define CPUID_7_0_EDX_AVX512_4VNNIW (1U << 2) /* AVX512 Neural Network Instructions */ + #define CPUID_7_0_EDX_AVX512_4FMAPS (1U << 3) /* AVX512 Multiply Accumulation Single Precision */ +-- +1.8.3.1 + diff --git a/SOURCES/kvm-x86-cpu-use-FeatureWordArray-to-define-filtered_feat.patch b/SOURCES/kvm-x86-cpu-use-FeatureWordArray-to-define-filtered_feat.patch new file mode 100644 index 0000000..65cceca --- /dev/null +++ b/SOURCES/kvm-x86-cpu-use-FeatureWordArray-to-define-filtered_feat.patch @@ -0,0 +1,44 @@ +From 8caf8808acc4b95a0bde03430b214a298da3a71a Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Fri, 22 Nov 2019 11:53:34 +0000 +Subject: [PATCH 01/16] x86/cpu: use FeatureWordArray to define + filtered_features + +RH-Author: Paolo Bonzini +Message-id: <20191122115348.25000-2-pbonzini@redhat.com> +Patchwork-id: 92599 +O-Subject: [RHEL8.2/rhel qemu-kvm PATCH 01/15] x86/cpu: use FeatureWordArray to define filtered_features +Bugzilla: 1689270 +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Maxim Levitsky + +From: Wei Yang + +Use the same definition as features/user_features in CPUX86State. + +Signed-off-by: Wei Yang +Message-Id: <20190620023746.9869-1-richardw.yang@linux.intel.com> +Signed-off-by: Eduardo Habkost +(cherry picked from commit f69ecddb4a02b5071297427b4ebb3d8f0cea7323) +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index 273c90b..add8b60 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -1409,7 +1409,7 @@ struct X86CPU { + bool cache_info_passthrough; + + /* Features that were filtered out because of missing host capabilities */ +- uint32_t filtered_features[FEATURE_WORDS]; ++ FeatureWordArray filtered_features; + + /* Enable PMU CPUID bits. This can't be enabled by default yet because + * it doesn't have ABI stability guarantees, as it passes all PMU CPUID +-- +1.8.3.1 + diff --git a/SPECS/qemu-kvm.spec b/SPECS/qemu-kvm.spec index 32c562b..adcb4a1 100644 --- a/SPECS/qemu-kvm.spec +++ b/SPECS/qemu-kvm.spec @@ -67,7 +67,7 @@ Obsoletes: %1-rhev Summary: QEMU is a machine emulator and virtualizer Name: qemu-kvm Version: 2.12.0 -Release: 77%{?dist} +Release: 94%{?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 @@ -1517,6 +1517,329 @@ Patch736: kvm-vfio-quirks-Add-common-quirk-alloc-helper.patch Patch737: kvm-vfio-Make-vfio_get_region_info_cap-public.patch # For bz#1710662 - [IBM 8.1 FEAT] POWER9 - Virt: qemu: NVLink2 passthru to guest - Nvidia Volta (GPU) (kvm) Patch738: kvm-spapr-Support-NVIDIA-V100-GPU-with-NVLink2.patch +# For bz#1721983 - qemu-kvm can't be build with new gluster version (6.0.6) +Patch739: kvm-gluster-Handle-changed-glfs_ftruncate-signature.patch +# For bz#1721983 - qemu-kvm can't be build with new gluster version (6.0.6) +Patch740: kvm-gluster-the-glfs_io_cbk-callback-function-pointer-ad.patch +# For bz#1712705 - CVE-2019-12155 qemu-kvm: QEMU: qxl: null pointer dereference while releasing spice resources [rhel-8] +Patch741: kvm-qxl-check-release-info-object.patch +# For bz#1707598 - qemu-iotest 182 fails without device hotplugging support +Patch742: kvm-iotests-Make-182-do-without-device_add.patch +# For bz#1714792 - [Intel 8.1 FEAT] MDS_NO exposure to guest +Patch743: kvm-target-i386-add-MDS-NO-feature.patch +# For bz#1531543 - [RFE] add iommu support to virtio-gpu +Patch744: kvm-virtio-gpu-pass-down-VirtIOGPU-pointer-to-a-bunch-of.patch +# For bz#1531543 - [RFE] add iommu support to virtio-gpu +Patch745: kvm-virtio-gpu-add-iommu-support.patch +# For bz#1531543 - [RFE] add iommu support to virtio-gpu +Patch746: kvm-virtio-gpu-fix-unmap-in-error-path.patch +# For bz#1629906 - [Intel 8.1 Feat] qemu-kvm Introduce Cascade Lake (CLX) cpu model +Patch747: kvm-i386-Add-new-model-of-Cascadelake-Server.patch +# For bz#1629906 - [Intel 8.1 Feat] qemu-kvm Introduce Cascade Lake (CLX) cpu model +Patch748: kvm-i386-Update-stepping-of-Cascadelake-Server.patch +# For bz#1629906 - [Intel 8.1 Feat] qemu-kvm Introduce Cascade Lake (CLX) cpu model +Patch749: kvm-target-i386-Disable-MPX-support-on-named-CPU-models.patch +# For bz#1629906 - [Intel 8.1 Feat] qemu-kvm Introduce Cascade Lake (CLX) cpu model +Patch750: kvm-i386-remove-the-INTEL_PT-CPUID-bit-from-named-CPU-NEW.patch +# For bz#1629906 - [Intel 8.1 Feat] qemu-kvm Introduce Cascade Lake (CLX) cpu model +Patch751: kvm-i386-Disable-OSPKE-on-CPU-model-definitions-NEW.patch +# For bz#1513367 - qemu with libssh +Patch752: kvm-block-ssh-Convert-from-DPRINTF-macro-to-trace-events.patch +# For bz#1513367 - qemu with libssh +Patch753: kvm-block-ssh-Do-not-report-read-write-flush-errors-to-t.patch +# For bz#1513367 - qemu with libssh +Patch754: kvm-qemu-iotests-Fix-paths-for-NFS.patch +# For bz#1513367 - qemu with libssh +Patch755: kvm-qemu-iotests-Filter-NFS-paths.patch +# For bz#1513367 - qemu with libssh +Patch756: kvm-iotests-Filter-SSH-paths.patch +# For bz#1513367 - qemu with libssh +Patch757: kvm-block-ssh-Implement-.bdrv_refresh_filename.patch +# For bz#1513367 - qemu with libssh +Patch758: kvm-iotests-Use-Python-byte-strings-where-appropriate.patch +# For bz#1513367 - qemu with libssh +Patch759: kvm-iotests-Unify-log-outputs-between-Python-2-and-3.patch +# For bz#1513367 - qemu with libssh +Patch760: kvm-ssh-switch-from-libssh2-to-libssh.patch +# For bz#1728657 - 'qemu-io write' to a raw image over libgfapi fails +Patch762: kvm-block-gluster-limit-the-transfer-size-to-512-MiB.patch +# For bz#1729975 - RHEL 8.1 Pre-Beta - Fix for hardware CPU Model +Patch763: kvm-s390-cpumodel-fix-description-for-the-new-vector-fac.patch +# For bz#1729975 - RHEL 8.1 Pre-Beta - Fix for hardware CPU Model +Patch764: kvm-s390x-cpumodel-remove-esort-from-the-default-model.patch +# For bz#1729975 - RHEL 8.1 Pre-Beta - Fix for hardware CPU Model +Patch765: kvm-s390x-cpumodel-also-change-name-of-vxbeh.patch +# For bz#1729975 - RHEL 8.1 Pre-Beta - Fix for hardware CPU Model +Patch766: kvm-s390x-cpumodel-change-internal-name-of-vxpdeh-to-mat.patch +# For bz#1728958 - Hot unplug vfio-pci NIC devices from sev guest will cause qemu-kvm: sev_ram_block_removed: failed to unregister region +Patch767: kvm-target-i386-sev-Do-not-unpin-ram-device-memory-regio.patch +# For bz#1689269 - Nested KVM: support for migration of nested hypervisors - Slow Train +Patch768: kvm-i386-Save-EFER-for-32-bit-targets.patch +# For bz#1689269 - Nested KVM: support for migration of nested hypervisors - Slow Train +Patch769: kvm-target-i386-rename-HF_SVMI_MASK-to-HF_GUEST_MASK.patch +# For bz#1689269 - Nested KVM: support for migration of nested hypervisors - Slow Train +Patch770: kvm-target-i386-kvm-add-VMX-migration-blocker.patch +# For bz#1689269 - Nested KVM: support for migration of nested hypervisors - Slow Train +Patch771: kvm-target-i386-kvm-just-return-after-migrate_add_blocke.patch +# For bz#1689269 - Nested KVM: support for migration of nested hypervisors - Slow Train +Patch772: kvm-target-i386-kvm-Delete-VMX-migration-blocker-on-vCPU.patch +# For bz#1689269 - Nested KVM: support for migration of nested hypervisors - Slow Train +Patch773: kvm-Introduce-kvm_arch_destroy_vcpu.patch +# For bz#1689269 - Nested KVM: support for migration of nested hypervisors - Slow Train +Patch774: kvm-target-i386-kvm-Use-symbolic-constant-for-DB-BP-exce.patch +# For bz#1689269 - Nested KVM: support for migration of nested hypervisors - Slow Train +Patch775: kvm-target-i386-kvm-Re-inject-DB-to-guest-with-updated-D.patch +# For bz#1689269 - Nested KVM: support for migration of nested hypervisors - Slow Train +Patch776: kvm-target-i386-kvm-Block-migration-for-vCPUs-exposed-wi.patch +# For bz#1689269 - Nested KVM: support for migration of nested hypervisors - Slow Train +Patch777: kvm-target-i386-kvm-do-not-initialize-padding-fields.patch +# For bz#1689269 - Nested KVM: support for migration of nested hypervisors - Slow Train +Patch778: kvm-linux-headers-synchronize-generic-and-x86-KVM-header.patch +# For bz#1689269 - Nested KVM: support for migration of nested hypervisors - Slow Train +Patch779: kvm-vmstate-Add-support-for-kernel-integer-types.patch +# For bz#1689269 - Nested KVM: support for migration of nested hypervisors - Slow Train +Patch780: kvm-target-i386-kvm-Add-support-for-save-and-restore-nes.patch +# For bz#1689269 - Nested KVM: support for migration of nested hypervisors - Slow Train +Patch781: kvm-target-i386-kvm-Add-support-for-KVM_CAP_EXCEPTION_PA.patch +# For bz#1689269 - Nested KVM: support for migration of nested hypervisors - Slow Train +Patch782: kvm-target-i386-kvm-Add-nested-migration-blocker-only-wh.patch +# For bz#1689269 - Nested KVM: support for migration of nested hypervisors - Slow Train +Patch783: kvm-target-i386-kvm-Demand-nested-migration-kernel-capab.patch +# For bz#1689269 - Nested KVM: support for migration of nested hypervisors - Slow Train +Patch784: kvm-target-i386-skip-KVM_GET-SET_NESTED_STATE-if-VMX-dis.patch +# For bz#1689269 - Nested KVM: support for migration of nested hypervisors - Slow Train +Patch785: kvm-i386-kvm-Do-not-sync-nested-state-during-runtime.patch +# For bz#1707192 - implement missing reset handler for cfi.pflash01 - slow train +Patch786: kvm-hw-block-pflash_cfi01-Add-missing-DeviceReset-handle.patch +# For bz#1678979 - qemu-img convert abort when converting image with unaligned size (qemu-img: block/io.c:2134: bdrv_co_block_status: Assertion `*pnum && (((*pnum) % (align)) == 0) && align > offset - aligned_offset\' failed) +Patch787: kvm-block-file-posix-Unaligned-O_DIRECT-block-status.patch +# For bz#1678979 - qemu-img convert abort when converting image with unaligned size (qemu-img: block/io.c:2134: bdrv_co_block_status: Assertion `*pnum && (((*pnum) % (align)) == 0) && align > offset - aligned_offset\' failed) +Patch788: kvm-iotests-Test-unaligned-raw-images-with-O_DIRECT.patch +# For bz#1678979 - qemu-img convert abort when converting image with unaligned size (qemu-img: block/io.c:2134: bdrv_co_block_status: Assertion `*pnum && (((*pnum) % (align)) == 0) && align > offset - aligned_offset\' failed) +Patch789: kvm-nbd-client-Lower-min_block-for-block-status-unaligne.patch +# For bz#1678979 - qemu-img convert abort when converting image with unaligned size (qemu-img: block/io.c:2134: bdrv_co_block_status: Assertion `*pnum && (((*pnum) % (align)) == 0) && align > offset - aligned_offset\' failed) +Patch790: kvm-nbd-client-Reject-inaccessible-tail-of-inconsistent-.patch +# For bz#1678979 - qemu-img convert abort when converting image with unaligned size (qemu-img: block/io.c:2134: bdrv_co_block_status: Assertion `*pnum && (((*pnum) % (align)) == 0) && align > offset - aligned_offset\' failed) +Patch791: kvm-nbd-client-Support-qemu-img-convert-from-unaligned-s.patch +# For bz#1678979 - qemu-img convert abort when converting image with unaligned size (qemu-img: block/io.c:2134: bdrv_co_block_status: Assertion `*pnum && (((*pnum) % (align)) == 0) && align > offset - aligned_offset\' failed) +Patch792: kvm-block-Add-bdrv_get_request_alignment.patch +# For bz#1678979 - qemu-img convert abort when converting image with unaligned size (qemu-img: block/io.c:2134: bdrv_co_block_status: Assertion `*pnum && (((*pnum) % (align)) == 0) && align > offset - aligned_offset\' failed) +Patch793: kvm-nbd-server-Advertise-actual-minimum-block-size.patch +# For bz#1727642 - CVE-2019-6778 qemu-kvm: QEMU: slirp: heap buffer overflow in tcp_emu() +Patch794: kvm-slirp-check-sscanf-result-when-emulating-ident.patch +# For bz#1727642 - CVE-2019-6778 qemu-kvm: QEMU: slirp: heap buffer overflow in tcp_emu() +Patch795: kvm-slirp-fix-big-little-endian-conversion-in-ident-prot.patch +# For bz#1727642 - CVE-2019-6778 qemu-kvm: QEMU: slirp: heap buffer overflow in tcp_emu() +Patch796: kvm-slirp-ensure-there-is-enough-space-in-mbuf-to-null-t.patch +# For bz#1727642 - CVE-2019-6778 qemu-kvm: QEMU: slirp: heap buffer overflow in tcp_emu() +Patch797: kvm-slirp-don-t-manipulate-so_rcv-in-tcp_emu.patch +# For bz#1732642 - enable the virtio-net frontend to work with the vhost-net backend in SEV guests +Patch798: kvm-tap-set-vhostfd-passed-from-qemu-cli-to-non-blocking.patch +# For bz#1734751 - CVE-2019-14378 qemu-kvm: QEMU: slirp: heap buffer overflow during packet reassembly [rhel-8.1.0] +Patch799: kvm-Fix-heap-overflow-in-ip_reass-on-big-packet-input.patch +# For bz#1727033 - vnc server should detect page-flips and avoid sending fullscreen updates then. +Patch800: kvm-vnc-detect-and-optimize-pageflips.patch +# For bz#1716349 - qemu with iothreads enabled crashes on resume after enospc pause for disk extension +Patch801: kvm-block-backend-Make-blk_inc-dec_in_flight-public.patch +# For bz#1716349 - qemu with iothreads enabled crashes on resume after enospc pause for disk extension +Patch802: kvm-virtio-blk-Increase-in_flight-for-request-restart-BH.patch +# For bz#1716349 - qemu with iothreads enabled crashes on resume after enospc pause for disk extension +Patch803: kvm-block-Fix-AioContext-switch-for-drained-node.patch +# For bz#1716349 - qemu with iothreads enabled crashes on resume after enospc pause for disk extension +Patch804: kvm-test-bdrv-drain-AioContext-switch-in-drained-section.patch +# For bz#1716349 - qemu with iothreads enabled crashes on resume after enospc pause for disk extension +Patch805: kvm-block-Use-normal-drain-for-bdrv_set_aio_context.patch +# For bz#1716347 - Qemu Core dump when quit vm that's in status "paused(io-error)" with data plane enabled +Patch806: kvm-block-Fix-AioContext-switch-for-bs-drv-NULL.patch +# For bz#1687541 - qemu aborted when start guest with a big iothreads +Patch807: kvm-iothread-fix-crash-with-invalid-properties.patch +# For bz#1687541 - qemu aborted when start guest with a big iothreads +Patch808: kvm-iothread-replace-init_done_cond-with-a-semaphore.patch +# For bz#1740797 - Disable memfd in QEMU +Patch809: kvm-RHEL-disable-hostmem-memfd.patch +# For bz#1684383 - qemu crashed when take screenshot for 2nd head of virtio video device if the display not opened by virt-viewer +Patch810: kvm-console-Avoid-segfault-in-screendump.patch +# For bz#1619661 - the attach hub on one hub still exits in device manager after unhotplug +Patch811: kvm-usb-hub-clear-suspend-on-detach.patch +# For bz#1727821 - Failed to convert a source image to the qcow2 image encrypted by luks +Patch812: kvm-qemu-img-fix-regression-copying-secrets-during-conve.patch +# For bz#1744415 - Backport support for count cache flush Spectre v2 mitigation [slow train] +Patch814: kvm-target-ppc-spapr-Add-workaround-option-to-SPAPR_CAP_.patch +# For bz#1744415 - Backport support for count cache flush Spectre v2 mitigation [slow train] +Patch815: kvm-target-ppc-spapr-Add-SPAPR_CAP_CCF_ASSIST.patch +# For bz#1747185 - "filtered-features" QOM property is not available +Patch816: kvm-i386-x86_cpu_list_feature_names-function.patch +# For bz#1747185 - "filtered-features" QOM property is not available +Patch817: kvm-i386-unavailable-features-QOM-property.patch +# For bz#1738839 - I/O error when virtio-blk disk is backed by a raw image on 4k disk +Patch818: kvm-file-posix-Handle-undetectable-alignment.patch +# For bz#1738839 - I/O error when virtio-blk disk is backed by a raw image on 4k disk +Patch819: kvm-iotests-Tweak-221-sizing-for-different-hole-granular.patch +# For bz#1738839 - I/O error when virtio-blk disk is backed by a raw image on 4k disk +Patch820: kvm-iotests-Filter-175-s-allocation-information.patch +# For bz#1738839 - I/O error when virtio-blk disk is backed by a raw image on 4k disk +Patch821: kvm-block-posix-Always-allocate-the-first-block.patch +# For bz#1738839 - I/O error when virtio-blk disk is backed by a raw image on 4k disk +Patch822: kvm-iotests-Test-allocate_first_block-with-O_DIRECT.patch +# For bz#1749022 - Please backport 950c4e6c94b1 ("opts: don't silently truncate long option values", 2018-05-09) +Patch823: kvm-accel-use-g_strsplit-for-parsing-accelerator-names.patch +# For bz#1749022 - Please backport 950c4e6c94b1 ("opts: don't silently truncate long option values", 2018-05-09) +Patch824: kvm-opts-don-t-silently-truncate-long-parameter-keys.patch +# For bz#1749022 - Please backport 950c4e6c94b1 ("opts: don't silently truncate long option values", 2018-05-09) +Patch825: kvm-opts-don-t-silently-truncate-long-option-values.patch +# For bz#1749022 - Please backport 950c4e6c94b1 ("opts: don't silently truncate long option values", 2018-05-09) +Patch826: kvm-i386-fix-regression-parsing-multiboot-initrd-modules.patch +# For bz#1749022 - Please backport 950c4e6c94b1 ("opts: don't silently truncate long option values", 2018-05-09) +Patch827: kvm-i386-only-parse-the-initrd_filename-once-for-multibo.patch +# For bz#1749022 - Please backport 950c4e6c94b1 ("opts: don't silently truncate long option values", 2018-05-09) +Patch828: kvm-opts-remove-redundant-check-for-NULL-parameter.patch +# For bz#1749724 - CVE-2019-15890 qemu-kvm: QEMU: Slirp: use-after-free during packet reassembly [rhel-8] +Patch829: kvm-Using-ip_deq-after-m_free-might-read-pointers-from-a.patch +# For bz#1708459 - qemu-kvm core dumped when repeat "system_reset" multiple times during guest boot +Patch830: kvm-virtio-blk-Cancel-the-pending-BH-when-the-dataplane-.patch +# For bz#1660909 - [IBM 8.2 FEAT] KVM s390x: Crypto Passthrough Interrupt Support - qemu part +Patch831: kvm-s390x-cpumodel-Rework-CPU-feature-definition.patch +# For bz#1660909 - [IBM 8.2 FEAT] KVM s390x: Crypto Passthrough Interrupt Support - qemu part +Patch832: kvm-s390x-cpumodel-Set-up-CPU-model-for-AQIC-interceptio.patch +# For bz#1746361 - ccid: Fix incorrect dwProtocol advertisement of T=0 +Patch833: kvm-ccid-Fix-dwProtocols-advertisement-of-T-0.patch +# For bz#1754643 - RHEL8.1 Snapshot3 - Passthrough PCI card goes into error state if used in domain (kvm) +Patch834: kvm-s390-PCI-fix-IOMMU-region-init.patch +# For bz#1607367 - After boot failed, guest should not reboot when set reboot-timeout < -1 +Patch835: kvm-fw_cfg-Improve-error-message-when-can-t-load-splash-.patch +# For bz#1607367 - After boot failed, guest should not reboot when set reboot-timeout < -1 +Patch836: kvm-fw_cfg-Fix-boot-bootsplash-error-checking.patch +# For bz#1607367 - After boot failed, guest should not reboot when set reboot-timeout < -1 +Patch837: kvm-fw_cfg-Fix-boot-reboot-timeout-error-checking.patch +# For bz#1607367 - After boot failed, guest should not reboot when set reboot-timeout < -1 +Patch838: kvm-hw-nvram-fw_cfg-Store-reboot-timeout-as-little-endia.patch +# For bz#1738440 - For intel-iommu, qemu shows conflict behaviors between booting a guest with vfio and hot plugging vfio device +Patch839: kvm-intel_iommu-Correct-caching-mode-error-message.patch +# For bz#1738440 - For intel-iommu, qemu shows conflict behaviors between booting a guest with vfio and hot plugging vfio device +Patch840: kvm-intel_iommu-Sanity-check-vfio-pci-config-on-machine-.patch +# For bz#1738440 - For intel-iommu, qemu shows conflict behaviors between booting a guest with vfio and hot plugging vfio device +Patch841: kvm-qdev-machine-Introduce-hotplug_allowed-hook.patch +# For bz#1738440 - For intel-iommu, qemu shows conflict behaviors between booting a guest with vfio and hot plugging vfio device +Patch842: kvm-pc-q35-Disallow-vfio-pci-hotplug-without-VT-d-cachin.patch +# For bz#1738440 - For intel-iommu, qemu shows conflict behaviors between booting a guest with vfio and hot plugging vfio device +Patch843: kvm-intel_iommu-Remove-the-caching-mode-check-during-fla.patch +# For bz#1651474 - RHEL8.0 Beta - [4.18.0-32.el8.ppc64le] Guest VM crashes during vcpu hotplug with specific numa configuration (kvm) +Patch844: kvm-pseries-do-not-allow-memory-less-cpu-less-NUMA-node.patch +# For bz#1719127 - [Intel 8.2 Bug] warning shown when boot VM with “–cpu host” or “–cpu other mode” on ICX platform (physical) +Patch845: kvm-i386-Don-t-print-warning-if-phys-bits-was-set-automa.patch +# For bz#1693140 - aarch64: qemu: remove smbus_eeprom and i2c from config +Patch846: kvm-Disable-CONFIG_I2C-and-CONFIG_IOH3420.patch +# For bz#1757482 - Fail to migrate a rhel6.10-mt7.6 guest with dimm device +Patch847: kvm-usb-drop-unnecessary-usb_device_post_load-checks.patch +# For bz#1664376 - [IBM 8.2 FEAT] CCW IPL Support (kvm) - qemu part +Patch848: kvm-pc-bios-s390-ccw-define-loadparm-length.patch +# For bz#1664376 - [IBM 8.2 FEAT] CCW IPL Support (kvm) - qemu part +Patch849: kvm-pc-bios-s390-ccw-net-Use-diag308-to-reset-machine-be.patch +# For bz#1664376 - [IBM 8.2 FEAT] CCW IPL Support (kvm) - qemu part +Patch850: kvm-s390-bios-decouple-cio-setup-from-virtio.patch +# For bz#1664376 - [IBM 8.2 FEAT] CCW IPL Support (kvm) - qemu part +Patch851: kvm-s390-bios-decouple-common-boot-logic-from-virtio.patch +# For bz#1664376 - [IBM 8.2 FEAT] CCW IPL Support (kvm) - qemu part +Patch852: kvm-s390-bios-Clean-up-cio.h.patch +# For bz#1664376 - [IBM 8.2 FEAT] CCW IPL Support (kvm) - qemu part +Patch853: kvm-s390-bios-Decouple-channel-i-o-logic-from-virtio.patch +# For bz#1664376 - [IBM 8.2 FEAT] CCW IPL Support (kvm) - qemu part +Patch854: kvm-s390-bios-Map-low-core-memory.patch +# For bz#1664376 - [IBM 8.2 FEAT] CCW IPL Support (kvm) - qemu part +Patch855: kvm-s390-bios-ptr2u32-and-u32toptr.patch +# For bz#1664376 - [IBM 8.2 FEAT] CCW IPL Support (kvm) - qemu part +Patch856: kvm-s390-bios-Support-for-running-format-0-1-channel-pro.patch +# For bz#1664376 - [IBM 8.2 FEAT] CCW IPL Support (kvm) - qemu part +Patch857: kvm-s390-bios-cio-error-handling.patch +# For bz#1664376 - [IBM 8.2 FEAT] CCW IPL Support (kvm) - qemu part +Patch858: kvm-s390-bios-Extend-find_dev-for-non-virtio-devices.patch +# For bz#1664376 - [IBM 8.2 FEAT] CCW IPL Support (kvm) - qemu part +Patch859: kvm-s390-bios-Factor-finding-boot-device-out-of-virtio-c.patch +# For bz#1664376 - [IBM 8.2 FEAT] CCW IPL Support (kvm) - qemu part +Patch860: kvm-s390-bios-Refactor-virtio-to-run-channel-programs-vi.patch +# For bz#1664376 - [IBM 8.2 FEAT] CCW IPL Support (kvm) - qemu part +Patch861: kvm-s390-bios-Use-control-unit-type-to-determine-boot-me.patch +# For bz#1664376 - [IBM 8.2 FEAT] CCW IPL Support (kvm) - qemu part +Patch862: kvm-s390-bios-Add-channel-command-codes-structs-needed-f.patch +# For bz#1664376 - [IBM 8.2 FEAT] CCW IPL Support (kvm) - qemu part +Patch863: kvm-s390-bios-Support-booting-from-real-dasd-device.patch +# For bz#1664376 - [IBM 8.2 FEAT] CCW IPL Support (kvm) - qemu part +Patch864: kvm-s390-bios-Use-control-unit-type-to-find-bootable-dev.patch +# For bz#1660906 - [IBM 8.2 FEAT] KVM s390x: Crypto Passthrough Hotplug - qemu part +Patch865: kvm-s390x-vfio-ap-Implement-hot-plug-unplug-of-vfio-ap-d.patch +# For bz#1730969 - [ppc] qmp: The 'arch' value returned by the command 'query-cpus-fast' does not match +Patch866: kvm-qapi-fill-in-CpuInfoFast.arch-in-query-cpus-fast.patch +# For bz#1744602 - qemu-img gets stuck when stream-converting from http +Patch867: kvm-curl-Keep-pointer-to-the-CURLState-in-CURLSocket.patch +# For bz#1744602 - qemu-img gets stuck when stream-converting from http +Patch868: kvm-curl-Keep-socket-until-the-end-of-curl_sock_cb.patch +# For bz#1744602 - qemu-img gets stuck when stream-converting from http +Patch869: kvm-curl-Check-completion-in-curl_multi_do.patch +# For bz#1744602 - qemu-img gets stuck when stream-converting from http +Patch870: kvm-curl-Pass-CURLSocket-to-curl_multi_do.patch +# For bz#1744602 - qemu-img gets stuck when stream-converting from http +Patch871: kvm-curl-Report-only-ready-sockets.patch +# For bz#1744602 - qemu-img gets stuck when stream-converting from http +Patch872: kvm-curl-Handle-success-in-multi_check_completion.patch +# For bz#1744602 - qemu-img gets stuck when stream-converting from http +Patch873: kvm-curl-Check-curl_multi_add_handle-s-return-code.patch +# For bz#1689270 - Nested KVM: limit VMX features according to CPU models - Slow Train +Patch874: kvm-x86-cpu-use-FeatureWordArray-to-define-filtered_feat.patch +# For bz#1689270 - Nested KVM: limit VMX features according to CPU models - Slow Train +Patch875: kvm-i386-Add-x-force-features-option-for-testing.patch +# For bz#1689270 - Nested KVM: limit VMX features according to CPU models - Slow Train +Patch876: kvm-target-i386-define-a-new-MSR-based-feature-word-FEAT.patch +# For bz#1689270 - Nested KVM: limit VMX features according to CPU models - Slow Train +Patch877: kvm-i386-display-known-CPUID-features-linewrapped-in-alp.patch +# For bz#1689270 - Nested KVM: limit VMX features according to CPU models - Slow Train +Patch878: kvm-target-i386-kvm-kvm_get_supported_msrs-cleanup.patch +# For bz#1689270 - Nested KVM: limit VMX features according to CPU models - Slow Train +Patch879: kvm-target-i386-handle-filtered_features-in-a-new-functi.patch +# For bz#1689270 - Nested KVM: limit VMX features according to CPU models - Slow Train +Patch880: kvm-target-i386-introduce-generic-feature-dependency-mec.patch +# For bz#1689270 - Nested KVM: limit VMX features according to CPU models - Slow Train +Patch881: kvm-target-i386-expand-feature-words-to-64-bits.patch +# For bz#1689270 - Nested KVM: limit VMX features according to CPU models - Slow Train +Patch882: kvm-target-i386-add-VMX-definitions.patch +# For bz#1689270 - Nested KVM: limit VMX features according to CPU models - Slow Train +Patch883: kvm-vmxcap-correct-the-name-of-the-variables.patch +# For bz#1689270 - Nested KVM: limit VMX features according to CPU models - Slow Train +Patch884: kvm-target-i386-add-VMX-features.patch +# For bz#1689270 - Nested KVM: limit VMX features according to CPU models - Slow Train +Patch885: kvm-target-i386-work-around-KVM_GET_MSRS-bug-for-seconda.patch +# For bz#1689270 - Nested KVM: limit VMX features according to CPU models - Slow Train +Patch886: kvm-target-i386-adjust-for-missing-VMX-features.patch +# For bz#1689270 - Nested KVM: limit VMX features according to CPU models - Slow Train +Patch887: kvm-target-i386-add-VMX-features-to-named-CPU-models.patch +# For bz#1689270 - Nested KVM: limit VMX features according to CPU models - Slow Train +Patch888: kvm-target-i386-add-VMX-features-to-named-CPU-models-RHE.patch +# For bz#1776808 - qemu-kvm crashes when Windows VM is migrated with multiqueue +Patch889: kvm-vhost-fix-vhost_log-size-overflow-during-migration.patch +# For bz#1771971 - CVE-2019-11135 virt:rhel/qemu-kvm: hw: TSX Transaction Asynchronous Abort (TAA) [rhel-8.2.0] +Patch890: kvm-target-i386-Export-TAA_NO-bit-to-guests.patch +# For bz#1771971 - CVE-2019-11135 virt:rhel/qemu-kvm: hw: TSX Transaction Asynchronous Abort (TAA) [rhel-8.2.0] +Patch891: kvm-target-i386-add-support-for-MSR_IA32_TSX_CTRL.patch +# For bz#1539282 - [Intel 8.2 Feature][Crystal Ridge] Support MAP_SYNC - qemu-kvm +Patch892: kvm-util-mmap-alloc-Add-a-is_pmem-parameter-to-qemu_ram_.patch +# For bz#1539282 - [Intel 8.2 Feature][Crystal Ridge] Support MAP_SYNC - qemu-kvm +Patch893: kvm-mmap-alloc-unfold-qemu_ram_mmap.patch +# For bz#1539282 - [Intel 8.2 Feature][Crystal Ridge] Support MAP_SYNC - qemu-kvm +Patch894: kvm-mmap-alloc-fix-hugetlbfs-misaligned-length-in-ppc64.patch +# For bz#1539282 - [Intel 8.2 Feature][Crystal Ridge] Support MAP_SYNC - qemu-kvm +Patch895: kvm-util-mmap-alloc-support-MAP_SYNC-in-qemu_ram_mmap.patch +# For bz#1634827 - [Intel 8.2 Feat] KVM Enable SnowRidge Accelerator Interface Architecture (AIA) - qemu +Patch896: kvm-x86-cpu-Enable-MOVDIRI-cpu-feature.patch +# For bz#1634827 - [Intel 8.2 Feat] KVM Enable SnowRidge Accelerator Interface Architecture (AIA) - qemu +Patch897: kvm-x86-cpu-Enable-MOVDIR64B-cpu-feature.patch +# For bz#1634827 - [Intel 8.2 Feat] KVM Enable SnowRidge Accelerator Interface Architecture (AIA) - qemu +Patch898: kvm-add-call-to-qemu_add_opts-for-overcommit-option.patch +# For bz#1634827 - [Intel 8.2 Feat] KVM Enable SnowRidge Accelerator Interface Architecture (AIA) - qemu +Patch899: kvm-support-overcommit-cpu-pm-on-off.patch +Patch900: kvm-i386-cpu-make-cpu-host-support-monitor-mwait.patch +# For bz#1634827 - [Intel 8.2 Feat] KVM Enable SnowRidge Accelerator Interface Architecture (AIA) - qemu +Patch901: kvm-x86-cpu-Add-support-for-UMONITOR-UMWAIT-TPAUSE.patch +# For bz#1634827 - [Intel 8.2 Feat] KVM Enable SnowRidge Accelerator Interface Architecture (AIA) - qemu +Patch902: kvm-target-i386-Add-support-for-save-load-IA32_UMWAIT_CO.patch BuildRequires: zlib-devel BuildRequires: glib2-devel @@ -1546,7 +1869,7 @@ BuildRequires: nss-devel BuildRequires: libseccomp-devel >= 2.4.0 # For network block driver BuildRequires: libcurl-devel -BuildRequires: libssh2-devel +BuildRequires: libssh-devel BuildRequires: librados-devel BuildRequires: librbd-devel %if %{have_gluster} @@ -1890,7 +2213,7 @@ buildldflags="VL_LDFLAGS=-Wl,--build-id" --enable-kvm \ --enable-libiscsi \ --disable-libnfs \ - --enable-libssh2 \ + --enable-libssh \ --enable-libusb \ --disable-bzip2 \ --enable-linux-aio \ @@ -2219,12 +2542,6 @@ chmod +x $RPM_BUILD_ROOT%{_libdir}/qemu-kvm/block-*.so %check export DIFF=diff; make check V=1 -pushd tests/qemu-iotests -./check -v -raw 001 002 003 004 005 008 009 010 011 012 021 025 032 033 048 052 063 077 086 101 104 106 120 140 143 145 150 157 159 160 162 170 171 175 178 181 184 221 226 232 -./check -v -qcow2 001 002 003 004 005 007 008 009 010 011 012 013 017 018 019 020 021 022 024 025 027 028 029 032 033 034 035 037 038 042 043 046 047 048 049 050 052 053 058 062 063 066 068 069 072 073 074 085 086 087 089 090 091 095 097 098 102 103 104 105 107 108 110 111 117 120 126 127 130 133 134 138 140 141 142 143 144 145 150 156 157 158 162 170 174 177 179 181 184 187 188 189 190 195 198 201 204 209 214 217 226 232 -./check -v -luks 001 002 003 004 005 008 009 010 011 012 021 025 032 033 048 052 140 143 145 157 162 174 181 184 -./check -v -nbd 001 002 003 004 005 008 009 010 011 021 032 033 077 094 104 119 123 143 145 162 184 -popd %post -n qemu-kvm-core # load kvm modules now, so we can make sure no reboot is needed. @@ -2409,6 +2726,305 @@ useradd -r -u 107 -g qemu -G kvm -d / -s /sbin/nologin \ %changelog +* Wed Dec 18 2019 Danilo Cesar Lemes de Paula - 2.12.0-94.el8 +- kvm-util-mmap-alloc-Add-a-is_pmem-parameter-to-qemu_ram_.patch [bz#1539282] +- kvm-mmap-alloc-unfold-qemu_ram_mmap.patch [bz#1539282] +- kvm-mmap-alloc-fix-hugetlbfs-misaligned-length-in-ppc64.patch [bz#1539282] +- kvm-util-mmap-alloc-support-MAP_SYNC-in-qemu_ram_mmap.patch [bz#1539282] +- kvm-x86-cpu-Enable-MOVDIRI-cpu-feature.patch [bz#1634827] +- kvm-x86-cpu-Enable-MOVDIR64B-cpu-feature.patch [bz#1634827] +- kvm-add-call-to-qemu_add_opts-for-overcommit-option.patch [bz#1634827] +- kvm-support-overcommit-cpu-pm-on-off.patch [bz#1634827] +- kvm-i386-cpu-make-cpu-host-support-monitor-mwait.patch [] +- kvm-x86-cpu-Add-support-for-UMONITOR-UMWAIT-TPAUSE.patch [bz#1634827] +- kvm-target-i386-Add-support-for-save-load-IA32_UMWAIT_CO.patch [bz#1634827] +- Resolves: bz#1539282 + ([Intel 8.2 Feature][Crystal Ridge] Support MAP_SYNC - qemu-kvm) +- Resolves: bz#1634827 + ([Intel 8.2 Feat] KVM Enable SnowRidge Accelerator Interface Architecture (AIA) - qemu) + +* Wed Dec 11 2019 Danilo Cesar Lemes de Paula - 2.12.0-93.el8 +- kvm-target-i386-Export-TAA_NO-bit-to-guests.patch [bz#1771971] +- kvm-target-i386-add-support-for-MSR_IA32_TSX_CTRL.patch [bz#1771971] +- Resolves: bz#1771971 + (CVE-2019-11135 virt:rhel/qemu-kvm: hw: TSX Transaction Asynchronous Abort (TAA) [rhel-8.2.0]) + +* Mon Dec 02 2019 Danilo Cesar Lemes de Paula - 2.12.0-92.el8 +- kvm-x86-cpu-use-FeatureWordArray-to-define-filtered_feat.patch [bz#1689270] +- kvm-i386-Add-x-force-features-option-for-testing.patch [bz#1689270] +- kvm-target-i386-define-a-new-MSR-based-feature-word-FEAT.patch [bz#1689270] +- kvm-i386-display-known-CPUID-features-linewrapped-in-alp.patch [bz#1689270] +- kvm-target-i386-kvm-kvm_get_supported_msrs-cleanup.patch [bz#1689270] +- kvm-target-i386-handle-filtered_features-in-a-new-functi.patch [bz#1689270] +- kvm-target-i386-introduce-generic-feature-dependency-mec.patch [bz#1689270] +- kvm-target-i386-expand-feature-words-to-64-bits.patch [bz#1689270] +- kvm-target-i386-add-VMX-definitions.patch [bz#1689270] +- kvm-vmxcap-correct-the-name-of-the-variables.patch [bz#1689270] +- kvm-target-i386-add-VMX-features.patch [bz#1689270] +- kvm-target-i386-work-around-KVM_GET_MSRS-bug-for-seconda.patch [bz#1689270] +- kvm-target-i386-adjust-for-missing-VMX-features.patch [bz#1689270] +- kvm-target-i386-add-VMX-features-to-named-CPU-models.patch [bz#1689270] +- kvm-target-i386-add-VMX-features-to-named-CPU-models-RHE.patch [bz#1689270] +- kvm-vhost-fix-vhost_log-size-overflow-during-migration.patch [bz#1776808] +- Resolves: bz#1689270 + (Nested KVM: limit VMX features according to CPU models - Slow Train) +- Resolves: bz#1776808 + (qemu-kvm crashes when Windows VM is migrated with multiqueue) + +* Wed Nov 27 2019 Danilo Cesar Lemes de Paula - 2.12.0-91.el8 +- kvm-qapi-fill-in-CpuInfoFast.arch-in-query-cpus-fast.patch [bz#1730969] +- kvm-curl-Keep-pointer-to-the-CURLState-in-CURLSocket.patch [bz#1744602] +- kvm-curl-Keep-socket-until-the-end-of-curl_sock_cb.patch [bz#1744602] +- kvm-curl-Check-completion-in-curl_multi_do.patch [bz#1744602] +- kvm-curl-Pass-CURLSocket-to-curl_multi_do.patch [bz#1744602] +- kvm-curl-Report-only-ready-sockets.patch [bz#1744602] +- kvm-curl-Handle-success-in-multi_check_completion.patch [bz#1744602] +- kvm-curl-Check-curl_multi_add_handle-s-return-code.patch [bz#1744602] +- Resolves: bz#1730969 + ([ppc] qmp: The 'arch' value returned by the command 'query-cpus-fast' does not match) +- Resolves: bz#1744602 + (qemu-img gets stuck when stream-converting from http) + +* Tue Nov 12 2019 Danilo Cesar Lemes de Paula - 2.12.0-90.el8 +- kvm-i386-Don-t-print-warning-if-phys-bits-was-set-automa.patch [bz#1719127] +- kvm-Disable-CONFIG_I2C-and-CONFIG_IOH3420.patch [bz#1693140] +- kvm-usb-drop-unnecessary-usb_device_post_load-checks.patch [bz#1757482] +- kvm-pc-bios-s390-ccw-define-loadparm-length.patch [bz#1664376] +- kvm-pc-bios-s390-ccw-net-Use-diag308-to-reset-machine-be.patch [bz#1664376] +- kvm-s390-bios-decouple-cio-setup-from-virtio.patch [bz#1664376] +- kvm-s390-bios-decouple-common-boot-logic-from-virtio.patch [bz#1664376] +- kvm-s390-bios-Clean-up-cio.h.patch [bz#1664376] +- kvm-s390-bios-Decouple-channel-i-o-logic-from-virtio.patch [bz#1664376] +- kvm-s390-bios-Map-low-core-memory.patch [bz#1664376] +- kvm-s390-bios-ptr2u32-and-u32toptr.patch [bz#1664376] +- kvm-s390-bios-Support-for-running-format-0-1-channel-pro.patch [bz#1664376] +- kvm-s390-bios-cio-error-handling.patch [bz#1664376] +- kvm-s390-bios-Extend-find_dev-for-non-virtio-devices.patch [bz#1664376] +- kvm-s390-bios-Factor-finding-boot-device-out-of-virtio-c.patch [bz#1664376] +- kvm-s390-bios-Refactor-virtio-to-run-channel-programs-vi.patch [bz#1664376] +- kvm-s390-bios-Use-control-unit-type-to-determine-boot-me.patch [bz#1664376] +- kvm-s390-bios-Add-channel-command-codes-structs-needed-f.patch [bz#1664376] +- kvm-s390-bios-Support-booting-from-real-dasd-device.patch [bz#1664376] +- kvm-s390-bios-Use-control-unit-type-to-find-bootable-dev.patch [bz#1664376] +- kvm-s390x-vfio-ap-Implement-hot-plug-unplug-of-vfio-ap-d.patch [bz#1660906] +- Resolves: bz#1660906 + ([IBM 8.2 FEAT] KVM s390x: Crypto Passthrough Hotplug - qemu part) +- Resolves: bz#1664376 + ([IBM 8.2 FEAT] CCW IPL Support (kvm) - qemu part) +- Resolves: bz#1693140 + (aarch64: qemu: remove smbus_eeprom and i2c from config) +- Resolves: bz#1719127 + ([Intel 8.2 Bug] warning shown when boot VM with “–cpu host” or “–cpu other mode” on ICX platform (physical)) +- Resolves: bz#1757482 + (Fail to migrate a rhel6.10-mt7.6 guest with dimm device) + +* Mon Oct 14 2019 Danilo Cesar Lemes de Paula - 2.12.0-89.el8 +- kvm-accel-use-g_strsplit-for-parsing-accelerator-names.patch [bz#1749022] +- kvm-opts-don-t-silently-truncate-long-parameter-keys.patch [bz#1749022] +- kvm-opts-don-t-silently-truncate-long-option-values.patch [bz#1749022] +- kvm-i386-fix-regression-parsing-multiboot-initrd-modules.patch [bz#1749022] +- kvm-i386-only-parse-the-initrd_filename-once-for-multibo.patch [bz#1749022] +- kvm-opts-remove-redundant-check-for-NULL-parameter.patch [bz#1749022] +- kvm-Using-ip_deq-after-m_free-might-read-pointers-from-a.patch [bz#1749724] +- kvm-virtio-blk-Cancel-the-pending-BH-when-the-dataplane-.patch [bz#1708459] +- kvm-s390x-cpumodel-Rework-CPU-feature-definition.patch [bz#1660909] +- kvm-s390x-cpumodel-Set-up-CPU-model-for-AQIC-interceptio.patch [bz#1660909] +- kvm-ccid-Fix-dwProtocols-advertisement-of-T-0.patch [bz#1746361] +- kvm-s390-PCI-fix-IOMMU-region-init.patch [bz#1754643] +- kvm-fw_cfg-Improve-error-message-when-can-t-load-splash-.patch [bz#1607367] +- kvm-fw_cfg-Fix-boot-bootsplash-error-checking.patch [bz#1607367] +- kvm-fw_cfg-Fix-boot-reboot-timeout-error-checking.patch [bz#1607367] +- kvm-hw-nvram-fw_cfg-Store-reboot-timeout-as-little-endia.patch [bz#1607367] +- kvm-intel_iommu-Correct-caching-mode-error-message.patch [bz#1738440] +- kvm-intel_iommu-Sanity-check-vfio-pci-config-on-machine-.patch [bz#1738440] +- kvm-qdev-machine-Introduce-hotplug_allowed-hook.patch [bz#1738440] +- kvm-pc-q35-Disallow-vfio-pci-hotplug-without-VT-d-cachin.patch [bz#1738440] +- kvm-intel_iommu-Remove-the-caching-mode-check-during-fla.patch [bz#1738440] +- kvm-pseries-do-not-allow-memory-less-cpu-less-NUMA-node.patch [bz#1651474] +- Resolves: bz#1607367 + (After boot failed, guest should not reboot when set reboot-timeout < -1) +- Resolves: bz#1651474 + (RHEL8.0 Beta - [4.18.0-32.el8.ppc64le] Guest VM crashes during vcpu hotplug with specific numa configuration (kvm)) +- Resolves: bz#1660909 + ([IBM 8.2 FEAT] KVM s390x: Crypto Passthrough Interrupt Support - qemu part) +- Resolves: bz#1708459 + (qemu-kvm core dumped when repeat "system_reset" multiple times during guest boot) +- Resolves: bz#1738440 + (For intel-iommu, qemu shows conflict behaviors between booting a guest with vfio and hot plugging vfio device) +- Resolves: bz#1746361 + (ccid: Fix incorrect dwProtocol advertisement of T=0) +- Resolves: bz#1749022 + (Please backport 950c4e6c94b1 ("opts: don't silently truncate long option values", 2018-05-09)) +- Resolves: bz#1749724 + (CVE-2019-15890 qemu-kvm: QEMU: Slirp: use-after-free during packet reassembly [rhel-8]) +- Resolves: bz#1754643 + (RHEL8.1 Snapshot3 - Passthrough PCI card goes into error state if used in domain (kvm)) + +* Fri Sep 13 2019 Danilo Cesar Lemes de Paula - 2.12.0-88.el8 +- Revert fix for bz#1749724 - this got delayed to 8.2 + (CVE-2019-15890 qemu-kvm: QEMU: Slirp: use-after-free during packet reassembly [rhel-8]) + +* Tue Sep 03 2019 Danilo Cesar Lemes de Paula - 2.12.0-86.el8 +- kvm-Do-not-run-iotests-on-brew-build.patch [bz#1742819] +- kvm-target-ppc-spapr-Add-workaround-option-to-SPAPR_CAP_.patch [bz#1744415] +- kvm-target-ppc-spapr-Add-SPAPR_CAP_CCF_ASSIST.patch [bz#1744415] +- kvm-i386-x86_cpu_list_feature_names-function.patch [bz#1747185] +- kvm-i386-unavailable-features-QOM-property.patch [bz#1747185] +- kvm-file-posix-Handle-undetectable-alignment.patch [bz#1738839] +- kvm-iotests-Tweak-221-sizing-for-different-hole-granular.patch [bz#1738839] +- kvm-iotests-Filter-175-s-allocation-information.patch [bz#1738839] +- kvm-block-posix-Always-allocate-the-first-block.patch [bz#1738839] +- kvm-iotests-Test-allocate_first_block-with-O_DIRECT.patch [bz#1738839] +- Resolves: bz#1738839 + (I/O error when virtio-blk disk is backed by a raw image on 4k disk) +- Resolves: bz#1742819 + (Remove iotests from qemu-kvm builds [RHEL 8.1.0]) +- Resolves: bz#1744415 + (Backport support for count cache flush Spectre v2 mitigation [slow train]) +- Resolves: bz#1747185 + ("filtered-features" QOM property is not available) + +* Mon Aug 19 2019 Danilo Cesar Lemes de Paula - 2.12.0-85.el8 +- kvm-console-Avoid-segfault-in-screendump.patch [bz#1684383] +- kvm-usb-hub-clear-suspend-on-detach.patch [bz#1619661] +- kvm-qemu-img-fix-regression-copying-secrets-during-conve.patch [bz#1727821] +- Resolves: bz#1619661 + (the attach hub on one hub still exits in device manager after unhotplug) +- Resolves: bz#1684383 + (qemu crashed when take screenshot for 2nd head of virtio video device if the display not opened by virt-viewer) +- Resolves: bz#1727821 + (Failed to convert a source image to the qcow2 image encrypted by luks) + +* Fri Aug 16 2019 Danilo Cesar Lemes de Paula - 2.12.0-84.el8 +- kvm-vnc-detect-and-optimize-pageflips.patch [bz#1727033] +- kvm-block-backend-Make-blk_inc-dec_in_flight-public.patch [bz#1716349] +- kvm-virtio-blk-Increase-in_flight-for-request-restart-BH.patch [bz#1716349] +- kvm-block-Fix-AioContext-switch-for-drained-node.patch [bz#1716349] +- kvm-test-bdrv-drain-AioContext-switch-in-drained-section.patch [bz#1716349] +- kvm-block-Use-normal-drain-for-bdrv_set_aio_context.patch [bz#1716349] +- kvm-block-Fix-AioContext-switch-for-bs-drv-NULL.patch [bz#1716347] +- kvm-iothread-fix-crash-with-invalid-properties.patch [bz#1687541] +- kvm-iothread-replace-init_done_cond-with-a-semaphore.patch [bz#1687541] +- kvm-RHEL-disable-hostmem-memfd.patch [bz#1740797] +- Resolves: bz#1687541 + (qemu aborted when start guest with a big iothreads) +- Resolves: bz#1716347 + (Qemu Core dump when quit vm that's in status "paused(io-error)" with data plane enabled) +- Resolves: bz#1716349 + (qemu with iothreads enabled crashes on resume after enospc pause for disk extension) +- Resolves: bz#1727033 + (vnc server should detect page-flips and avoid sending fullscreen updates then.) +- Resolves: bz#1740797 + (Disable memfd in QEMU) + +* Thu Aug 01 2019 Danilo Cesar Lemes de Paula - 2.12.0-83.el8 +- kvm-hw-block-pflash_cfi01-Add-missing-DeviceReset-handle.patch [bz#1707192] +- kvm-block-file-posix-Unaligned-O_DIRECT-block-status.patch [bz#1678979] +- kvm-iotests-Test-unaligned-raw-images-with-O_DIRECT.patch [bz#1678979] +- kvm-nbd-client-Lower-min_block-for-block-status-unaligne.patch [bz#1678979] +- kvm-nbd-client-Reject-inaccessible-tail-of-inconsistent-.patch [bz#1678979] +- kvm-nbd-client-Support-qemu-img-convert-from-unaligned-s.patch [bz#1678979] +- kvm-block-Add-bdrv_get_request_alignment.patch [bz#1678979] +- kvm-nbd-server-Advertise-actual-minimum-block-size.patch [bz#1678979] +- kvm-slirp-check-sscanf-result-when-emulating-ident.patch [bz#1727642] +- kvm-slirp-fix-big-little-endian-conversion-in-ident-prot.patch [bz#1727642] +- kvm-slirp-ensure-there-is-enough-space-in-mbuf-to-null-t.patch [bz#1727642] +- kvm-slirp-don-t-manipulate-so_rcv-in-tcp_emu.patch [bz#1727642] +- kvm-tap-set-vhostfd-passed-from-qemu-cli-to-non-blocking.patch [bz#1732642] +- kvm-Fix-heap-overflow-in-ip_reass-on-big-packet-input.patch [bz#1734751] +- Resolves: bz#1678979 + (qemu-img convert abort when converting image with unaligned size (qemu-img: block/io.c:2134: bdrv_co_block_status: Assertion `*pnum && (((*pnum) % (align)) == 0) && align > offset - aligned_offset\' failed)) +- Resolves: bz#1707192 + (implement missing reset handler for cfi.pflash01 - slow train) +- Resolves: bz#1727642 + (CVE-2019-6778 qemu-kvm: QEMU: slirp: heap buffer overflow in tcp_emu()) +- Resolves: bz#1732642 + (enable the virtio-net frontend to work with the vhost-net backend in SEV guests) +- Resolves: bz#1734751 + (CVE-2019-14378 qemu-kvm: QEMU: slirp: heap buffer overflow during packet reassembly [rhel-8.1.0]) + +* Tue Jul 23 2019 Danilo Cesar Lemes de Paula - 2.12.0-82.el8 +- kvm-i386-Add-new-model-of-Cascadelake-Server.patch [bz#1629906] +- kvm-i386-Update-stepping-of-Cascadelake-Server.patch [bz#1629906] +- kvm-target-i386-Disable-MPX-support-on-named-CPU-models.patch [bz#1629906] +- kvm-i386-remove-the-INTEL_PT-CPUID-bit-from-named-CPU-NEW.patch [bz#1629906] +- kvm-i386-Disable-OSPKE-on-CPU-model-definitions-NEW.patch [bz#1629906] +- kvm-block-ssh-Convert-from-DPRINTF-macro-to-trace-events.patch [bz#1513367] +- kvm-block-ssh-Do-not-report-read-write-flush-errors-to-t.patch [bz#1513367] +- kvm-qemu-iotests-Fix-paths-for-NFS.patch [bz#1513367] +- kvm-qemu-iotests-Filter-NFS-paths.patch [bz#1513367] +- kvm-iotests-Filter-SSH-paths.patch [bz#1513367] +- kvm-block-ssh-Implement-.bdrv_refresh_filename.patch [bz#1513367] +- kvm-iotests-Use-Python-byte-strings-where-appropriate.patch [bz#1513367] +- kvm-iotests-Unify-log-outputs-between-Python-2-and-3.patch [bz#1513367] +- kvm-ssh-switch-from-libssh2-to-libssh.patch [bz#1513367] +- kvm-redhat-switch-from-libssh2-to-libssh.patch [bz#1513367] +- kvm-block-gluster-limit-the-transfer-size-to-512-MiB.patch [bz#1728657] +- kvm-s390-cpumodel-fix-description-for-the-new-vector-fac.patch [bz#1729975] +- kvm-s390x-cpumodel-remove-esort-from-the-default-model.patch [bz#1729975] +- kvm-s390x-cpumodel-also-change-name-of-vxbeh.patch [bz#1729975] +- kvm-s390x-cpumodel-change-internal-name-of-vxpdeh-to-mat.patch [bz#1729975] +- kvm-target-i386-sev-Do-not-unpin-ram-device-memory-regio.patch [bz#1728958] +- kvm-i386-Save-EFER-for-32-bit-targets.patch [bz#1689269] +- kvm-target-i386-rename-HF_SVMI_MASK-to-HF_GUEST_MASK.patch [bz#1689269] +- kvm-target-i386-kvm-add-VMX-migration-blocker.patch [bz#1689269] +- kvm-target-i386-kvm-just-return-after-migrate_add_blocke.patch [bz#1689269] +- kvm-target-i386-kvm-Delete-VMX-migration-blocker-on-vCPU.patch [bz#1689269] +- kvm-Introduce-kvm_arch_destroy_vcpu.patch [bz#1689269] +- kvm-target-i386-kvm-Use-symbolic-constant-for-DB-BP-exce.patch [bz#1689269] +- kvm-target-i386-kvm-Re-inject-DB-to-guest-with-updated-D.patch [bz#1689269] +- kvm-target-i386-kvm-Block-migration-for-vCPUs-exposed-wi.patch [bz#1689269] +- kvm-target-i386-kvm-do-not-initialize-padding-fields.patch [bz#1689269] +- kvm-linux-headers-synchronize-generic-and-x86-KVM-header.patch [bz#1689269] +- kvm-vmstate-Add-support-for-kernel-integer-types.patch [bz#1689269] +- kvm-target-i386-kvm-Add-support-for-save-and-restore-nes.patch [bz#1689269] +- kvm-target-i386-kvm-Add-support-for-KVM_CAP_EXCEPTION_PA.patch [bz#1689269] +- kvm-target-i386-kvm-Add-nested-migration-blocker-only-wh.patch [bz#1689269] +- kvm-target-i386-kvm-Demand-nested-migration-kernel-capab.patch [bz#1689269] +- kvm-target-i386-skip-KVM_GET-SET_NESTED_STATE-if-VMX-dis.patch [bz#1689269] +- kvm-i386-kvm-Do-not-sync-nested-state-during-runtime.patch [bz#1689269] +- Resolves: bz#1513367 + (qemu with libssh) +- Resolves: bz#1629906 + ([Intel 8.1 Feat] qemu-kvm Introduce Cascade Lake (CLX) cpu model) +- Resolves: bz#1689269 + (Nested KVM: support for migration of nested hypervisors - Slow Train) +- Resolves: bz#1728657 + ('qemu-io write' to a raw image over libgfapi fails) +- Resolves: bz#1728958 + (Hot unplug vfio-pci NIC devices from sev guest will cause qemu-kvm: sev_ram_block_removed: failed to unregister region) +- Resolves: bz#1729975 + (RHEL 8.1 Pre-Beta - Fix for hardware CPU Model) + +* Mon Jul 08 2019 Miroslav Rezanina - 2.12.0-81.el8 +- kvm-target-i386-add-MDS-NO-feature.patch [bz#1714792] +- kvm-virtio-gpu-pass-down-VirtIOGPU-pointer-to-a-bunch-of.patch [bz#1531543] +- kvm-virtio-gpu-add-iommu-support.patch [bz#1531543] +- kvm-virtio-gpu-fix-unmap-in-error-path.patch [bz#1531543] +- Resolves: bz#1531543 + ([RFE] add iommu support to virtio-gpu) +- Resolves: bz#1714792 + ([Intel 8.1 FEAT] MDS_NO exposure to guest) + +* Tue Jul 02 2019 Danilo Cesar Lemes de Paula - 2.12.0-80.el8 +- kvm-qxl-check-release-info-object.patch [bz#1712705] +- kvm-iotests-Make-182-do-without-device_add.patch [bz#1707598] +- Resolves: bz#1707598 + (qemu-iotest 182 fails without device hotplugging support) +- Resolves: bz#1712705 + (CVE-2019-12155 qemu-kvm: QEMU: qxl: null pointer dereference while releasing spice resources [rhel-8]) + +* Fri Jun 28 2019 Danilo de Paula - 15:2.12.0-79 +- Rebuild all virt packages to fix RHEL's upgrade path +- Resolves: rhbz#1695587 + (Ensure modular RPM upgrade path) + +* Thu Jun 20 2019 Miroslav Rezanina - 2.12.0-78.el8 +- kvm-gluster-Handle-changed-glfs_ftruncate-signature.patch [bz#1721983] +- kvm-gluster-the-glfs_io_cbk-callback-function-pointer-ad.patch [bz#1721983] +- Resolves: bz#1721983 + (qemu-kvm can't be build with new gluster version (6.0.6)) + * Thu Jun 13 2019 Danilo Cesar Lemes de Paula - 2.12.0-77.el8 - kvm-i386-Make-arch_capabilities-migratable.patch [bz#1709970] - kvm-spapr-Fix-ibm-max-associativity-domains-property-num.patch [bz#1710662]