diff --git a/SOURCES/kvm-ACPI-add-expected-files-for-HMAT-tests-acpihmat.patch b/SOURCES/kvm-ACPI-add-expected-files-for-HMAT-tests-acpihmat.patch new file mode 100644 index 0000000..7310f17 --- /dev/null +++ b/SOURCES/kvm-ACPI-add-expected-files-for-HMAT-tests-acpihmat.patch @@ -0,0 +1,41 @@ +From ff8529dcbf86b3a086d64dd630cf6a687603c571 Mon Sep 17 00:00:00 2001 +From: "plai@redhat.com" +Date: Thu, 21 May 2020 23:56:55 +0100 +Subject: [PATCH 12/12] ACPI: add expected files for HMAT tests (acpihmat) + +RH-Author: plai@redhat.com +Message-id: <20200521235655.27141-12-plai@redhat.com> +Patchwork-id: 96742 +O-Subject: [RHEL8.2.1 AV qemu-kvm PATCH 11/11] ACPI: add expected files for HMAT tests (acpihmat) +Bugzilla: 1600217 +RH-Acked-by: Michael S. Tsirkin +RH-Acked-by: Igor Mammedov +RH-Acked-by: Eduardo Habkost + +From: "Michael S. Tsirkin" + +Signed-off-by: Michael S. Tsirkin +(cherry picked from commit 48892c6c8def6624a0ed57e2bd6c2a0a9878b973) +Signed-off-by: Paul Lai +Signed-off-by: Danilo C. L. de Paula +--- + tests/bios-tables-test-allowed-diff.h | 8 -------- + 1 file changed, 8 deletions(-) + +diff --git a/tests/bios-tables-test-allowed-diff.h b/tests/bios-tables-test-allowed-diff.h +index 3c9e0c9..dfb8523 100644 +--- a/tests/bios-tables-test-allowed-diff.h ++++ b/tests/bios-tables-test-allowed-diff.h +@@ -1,9 +1 @@ + /* List of comma-separated changed AML files to ignore */ +-"tests/data/acpi/pc/APIC.acpihmat", +-"tests/data/acpi/pc/SRAT.acpihmat", +-"tests/data/acpi/pc/HMAT.acpihmat", +-"tests/data/acpi/pc/DSDT.acpihmat", +-"tests/data/acpi/q35/APIC.acpihmat", +-"tests/data/acpi/q35/SRAT.acpihmat", +-"tests/data/acpi/q35/HMAT.acpihmat", +-"tests/data/acpi/q35/DSDT.acpihmat", +-- +1.8.3.1 + diff --git a/SOURCES/kvm-Don-t-leak-memory-when-reallocation-fails.patch b/SOURCES/kvm-Don-t-leak-memory-when-reallocation-fails.patch new file mode 100644 index 0000000..5747672 --- /dev/null +++ b/SOURCES/kvm-Don-t-leak-memory-when-reallocation-fails.patch @@ -0,0 +1,58 @@ +From bcb6107f98d7b1edf687d7afd552a4528b7e673b Mon Sep 17 00:00:00 2001 +From: jmaloy +Date: Tue, 12 May 2020 21:15:13 +0100 +Subject: [PATCH 2/7] Don't leak memory when reallocation fails. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: jmaloy +Message-id: <20200512211514.1398384-2-jmaloy@redhat.com> +Patchwork-id: 96412 +O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH 1/2] Don't leak memory when reallocation fails. +Bugzilla: 1749737 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Thomas Huth +RH-Acked-by: Philippe Mathieu-Daudé + +From: Jindrich Novy + +Signed-off-by: Jindrich Novy +[ Marc-André - modified to use a temporary variable ] +Signed-off-by: Marc-André Lureau +(cherry picked from libslirp commit d171af3732a0610a25334b06b77fa547bd677918) +Signed-off-by: Jon Maloy + +Signed-off-by: Danilo C. L. de Paula +--- + slirp/src/sbuf.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +diff --git a/slirp/src/sbuf.c b/slirp/src/sbuf.c +index abced48..0569c34 100644 +--- a/slirp/src/sbuf.c ++++ b/slirp/src/sbuf.c +@@ -39,13 +39,16 @@ void sbreserve(struct sbuf *sb, int size) + if (sb->sb_data) { + /* Already alloced, realloc if necessary */ + if (sb->sb_datalen != size) { +- sb->sb_wptr = sb->sb_rptr = sb->sb_data = +- (char *)realloc(sb->sb_data, size); ++ char *new = realloc(sb->sb_data, size); + sb->sb_cc = 0; +- if (sb->sb_wptr) ++ if (new) { ++ sb->sb_data = sb->sb_wptr = sb->sb_rptr = new; + sb->sb_datalen = size; +- else ++ } else { ++ free(sb->sb_data); ++ sb->sb_data = sb->sb_wptr = sb->sb_rptr = NULL; + sb->sb_datalen = 0; ++ } + } + } else { + sb->sb_wptr = sb->sb_rptr = sb->sb_data = (char *)malloc(size); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-Fix-use-afte-free-in-ip_reass-CVE-2020-1983.patch b/SOURCES/kvm-Fix-use-afte-free-in-ip_reass-CVE-2020-1983.patch new file mode 100644 index 0000000..535c3af --- /dev/null +++ b/SOURCES/kvm-Fix-use-afte-free-in-ip_reass-CVE-2020-1983.patch @@ -0,0 +1,60 @@ +From a33ea192428d9c9307f1140f3e25631a6ef7657c Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Sat, 20 Jun 2020 15:02:59 -0400 +Subject: [PATCH 12/12] Fix use-afte-free in ip_reass() (CVE-2020-1983) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Jon Maloy +Message-id: <20200620150259.3352467-2-jmaloy@redhat.com> +Patchwork-id: 97678 +O-Subject: [RHEL-8.3.0 qemu-kvm PATCH 1/1] Fix use-afte-free in ip_reass() (CVE-2020-1983) +Bugzilla: 1838070 +RH-Acked-by: Stefan Hajnoczi + +From: Marc-André Lureau + +The q pointer is updated when the mbuf data is moved from m_dat to +m_ext. + +m_ext buffer may also be realloc()'ed and moved during m_cat(): +q should also be updated in this case. + +Reported-by: Aviv Sasson +Signed-off-by: Marc-André Lureau +Reviewed-by: Samuel Thibault + +(cherry picked from libslirp commit 9bd6c5913271eabcb7768a58197ed3301fe19f2d) +Signed-off-by: Jon Maloy +Signed-off-by: Danilo C. L. de Paula +--- + slirp/src/ip_input.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/slirp/src/ip_input.c b/slirp/src/ip_input.c +index df1c846ade..0f5d522ec1 100644 +--- a/slirp/src/ip_input.c ++++ b/slirp/src/ip_input.c +@@ -329,7 +329,7 @@ insert: + q = fp->frag_link.next; + m = dtom(slirp, q); + +- int was_ext = m->m_flags & M_EXT; ++ int delta = (char *)q - (m->m_flags & M_EXT ? m->m_ext : m->m_dat); + + q = (struct ipasfrag *)q->ipf_next; + while (q != (struct ipasfrag *)&fp->frag_link) { +@@ -353,8 +353,7 @@ insert: + * the old buffer (in the mbuf), so we must point ip + * into the new buffer. + */ +- if (!was_ext && m->m_flags & M_EXT) { +- int delta = (char *)q - m->m_dat; ++ if (m->m_flags & M_EXT) { + q = (struct ipasfrag *)(m->m_ext + delta); + } + +-- +2.27.0 + diff --git a/SOURCES/kvm-MAINTAINERS-fix-qcow2-bitmap.c-under-Dirty-Bitmaps-h.patch b/SOURCES/kvm-MAINTAINERS-fix-qcow2-bitmap.c-under-Dirty-Bitmaps-h.patch new file mode 100644 index 0000000..dce89d9 --- /dev/null +++ b/SOURCES/kvm-MAINTAINERS-fix-qcow2-bitmap.c-under-Dirty-Bitmaps-h.patch @@ -0,0 +1,55 @@ +From e3bec8c83459a68ae0c08e2ae0f1dbef24872d59 Mon Sep 17 00:00:00 2001 +From: Eric Blake +Date: Tue, 2 Jun 2020 02:34:09 +0100 +Subject: [PATCH 04/26] MAINTAINERS: fix qcow2-bitmap.c under Dirty Bitmaps + header + +RH-Author: Eric Blake +Message-id: <20200602023420.2133649-2-eblake@redhat.com> +Patchwork-id: 97068 +O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH 01/12] MAINTAINERS: fix qcow2-bitmap.c under Dirty Bitmaps header +Bugzilla: 1779893 1779904 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Max Reitz +RH-Acked-by: Kevin Wolf + +From: Vladimir Sementsov-Ogievskiy + +Somehow I wrote not full path to the file. Fix that. + +Also, while being here, rearrange entries, so that includes go first, +then block, than migration, than util. + +Fixes: 052db8e71444d +Signed-off-by: Vladimir Sementsov-Ogievskiy +Signed-off-by: Kevin Wolf +(cherry picked from commit 00637c6b0b67694127cc01dd75f3626da23acdaa) +Signed-off-by: Eric Blake +Signed-off-by: Danilo C. L. de Paula +--- + MAINTAINERS | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/MAINTAINERS b/MAINTAINERS +index d1b3e26..3a81ac9 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -1873,12 +1873,12 @@ M: John Snow + R: Vladimir Sementsov-Ogievskiy + L: qemu-block@nongnu.org + S: Supported +-F: util/hbitmap.c +-F: block/dirty-bitmap.c + F: include/qemu/hbitmap.h + F: include/block/dirty-bitmap.h +-F: qcow2-bitmap.c ++F: block/dirty-bitmap.c ++F: block/qcow2-bitmap.c + F: migration/block-dirty-bitmap.c ++F: util/hbitmap.c + F: tests/test-hbitmap.c + F: docs/interop/bitmaps.rst + T: git https://github.com/jnsnow/qemu.git bitmaps +-- +1.8.3.1 + diff --git a/SOURCES/kvm-Replace-remaining-malloc-free-user-with-glib.patch b/SOURCES/kvm-Replace-remaining-malloc-free-user-with-glib.patch new file mode 100644 index 0000000..71e6e47 --- /dev/null +++ b/SOURCES/kvm-Replace-remaining-malloc-free-user-with-glib.patch @@ -0,0 +1,118 @@ +From c012dc9b501d96a2ff54a8a7a182726043b69aeb Mon Sep 17 00:00:00 2001 +From: jmaloy +Date: Tue, 12 May 2020 21:15:14 +0100 +Subject: [PATCH 3/7] Replace remaining malloc/free user with glib +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: jmaloy +Message-id: <20200512211514.1398384-3-jmaloy@redhat.com> +Patchwork-id: 96413 +O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH 2/2] Replace remaining malloc/free user with glib +Bugzilla: 1749737 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Thomas Huth +RH-Acked-by: Philippe Mathieu-Daudé + +From: Marc-André Lureau + +glib mem functions are already used in various places. Let's not mix +the two, and instead abort on OOM conditions. + +Signed-off-by: Marc-André Lureau +(cherry picked from libslirp commit 3a494648526be4eb96cba739a816a60e933ffd14) +Signed-off-by: Jon Maloy + +Signed-off-by: Danilo C. L. de Paula +--- + slirp/src/sbuf.c | 21 ++++++--------------- + slirp/src/socket.c | 2 +- + slirp/src/tcp_subr.c | 8 ++------ + 3 files changed, 9 insertions(+), 22 deletions(-) + +diff --git a/slirp/src/sbuf.c b/slirp/src/sbuf.c +index 0569c34..eab87f3 100644 +--- a/slirp/src/sbuf.c ++++ b/slirp/src/sbuf.c +@@ -9,7 +9,7 @@ static void sbappendsb(struct sbuf *sb, struct mbuf *m); + + void sbfree(struct sbuf *sb) + { +- free(sb->sb_data); ++ g_free(sb->sb_data); + } + + bool sbdrop(struct sbuf *sb, int num) +@@ -39,24 +39,15 @@ void sbreserve(struct sbuf *sb, int size) + if (sb->sb_data) { + /* Already alloced, realloc if necessary */ + if (sb->sb_datalen != size) { +- char *new = realloc(sb->sb_data, size); ++ char *new = g_realloc(sb->sb_data, size); + sb->sb_cc = 0; +- if (new) { +- sb->sb_data = sb->sb_wptr = sb->sb_rptr = new; +- sb->sb_datalen = size; +- } else { +- free(sb->sb_data); +- sb->sb_data = sb->sb_wptr = sb->sb_rptr = NULL; +- sb->sb_datalen = 0; +- } ++ sb->sb_data = sb->sb_wptr = sb->sb_rptr = new; ++ sb->sb_datalen = size; + } + } else { +- sb->sb_wptr = sb->sb_rptr = sb->sb_data = (char *)malloc(size); ++ sb->sb_wptr = sb->sb_rptr = sb->sb_data = g_malloc(size); + sb->sb_cc = 0; +- if (sb->sb_wptr) +- sb->sb_datalen = size; +- else +- sb->sb_datalen = 0; ++ sb->sb_datalen = size; + } + } + +diff --git a/slirp/src/socket.c b/slirp/src/socket.c +index 34daffc..ace18bf 100644 +--- a/slirp/src/socket.c ++++ b/slirp/src/socket.c +@@ -95,7 +95,7 @@ void sofree(struct socket *so) + remque(so); /* crashes if so is not in a queue */ + + if (so->so_tcpcb) { +- free(so->so_tcpcb); ++ g_free(so->so_tcpcb); + } + g_free(so); + } +diff --git a/slirp/src/tcp_subr.c b/slirp/src/tcp_subr.c +index 26d4ead..4e5a801 100644 +--- a/slirp/src/tcp_subr.c ++++ b/slirp/src/tcp_subr.c +@@ -255,11 +255,7 @@ struct tcpcb *tcp_newtcpcb(struct socket *so) + { + register struct tcpcb *tp; + +- tp = (struct tcpcb *)malloc(sizeof(*tp)); +- if (tp == NULL) +- return ((struct tcpcb *)0); +- +- memset((char *)tp, 0, sizeof(struct tcpcb)); ++ tp = g_new0(struct tcpcb, 1); + tp->seg_next = tp->seg_prev = (struct tcpiphdr *)tp; + tp->t_maxseg = (so->so_ffamily == AF_INET) ? TCP_MSS : TCP6_MSS; + +@@ -330,7 +326,7 @@ struct tcpcb *tcp_close(struct tcpcb *tp) + remque(tcpiphdr2qlink(tcpiphdr_prev(t))); + m_free(m); + } +- free(tp); ++ g_free(tp); + so->so_tcpcb = NULL; + /* clobber input socket cache if we're closing the cached connection */ + if (so == slirp->tcp_last_so) +-- +1.8.3.1 + diff --git a/SOURCES/kvm-Revert-RHEL-disable-hostmem-memfd.patch b/SOURCES/kvm-Revert-RHEL-disable-hostmem-memfd.patch new file mode 100644 index 0000000..f959752 --- /dev/null +++ b/SOURCES/kvm-Revert-RHEL-disable-hostmem-memfd.patch @@ -0,0 +1,58 @@ +From 559d5899473dea180ced39a32bfbfbf2310c6e04 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= +Date: Mon, 25 May 2020 15:33:06 +0100 +Subject: [PATCH 4/7] Revert "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: <20200525153306.15373-1-marcandre.lureau@redhat.com> +Patchwork-id: 96747 +O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH] Revert "RHEL: disable hostmem-memfd" +Bugzilla: 1839030 +RH-Acked-by: Daniel P. Berrange +RH-Acked-by: Sergio Lopez Pascual +RH-Acked-by: Stefano Garzarella + +BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1839030 +BRANCH: rhel-av-8.2.1 +UPSTREAM: RHEL-only +BREW: http://brewweb.devel.redhat.com/brew/taskinfo?taskID=28817132 + +This reverts commit f7587ddb9a2731bf678a24156b6285dda79a4b2b. + +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, 2 insertions(+), 3 deletions(-) + +diff --git a/backends/Makefile.objs b/backends/Makefile.objs +index f328d40..f069111 100644 +--- a/backends/Makefile.objs ++++ b/backends/Makefile.objs +@@ -16,5 +16,4 @@ endif + + common-obj-$(call land,$(CONFIG_VHOST_USER),$(CONFIG_VIRTIO)) += vhost-user.o + +-# RHEL: disable memfd +-# common-obj-$(CONFIG_LINUX) += hostmem-memfd.o ++common-obj-$(CONFIG_LINUX) += hostmem-memfd.o +diff --git a/util/memfd.c b/util/memfd.c +index 3303ec9..4a3c07e 100644 +--- a/util/memfd.c ++++ b/util/memfd.c +@@ -193,7 +193,7 @@ bool qemu_memfd_alloc_check(void) + */ + bool qemu_memfd_check(unsigned int flags) + { +-#if 0 /* RHEL: memfd support disabled */ ++#ifdef CONFIG_LINUX + int mfd = memfd_create("test", flags | MFD_CLOEXEC); + + if (mfd >= 0) { +-- +1.8.3.1 + diff --git a/SOURCES/kvm-backup-Improve-error-for-bdrv_getlength-failure.patch b/SOURCES/kvm-backup-Improve-error-for-bdrv_getlength-failure.patch new file mode 100644 index 0000000..8fa2629 --- /dev/null +++ b/SOURCES/kvm-backup-Improve-error-for-bdrv_getlength-failure.patch @@ -0,0 +1,51 @@ +From fba183faf8ce819262a1a47f8531ea68051cdce7 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Wed, 3 Jun 2020 16:03:19 +0100 +Subject: [PATCH 20/26] backup: Improve error for bdrv_getlength() failure + +RH-Author: Kevin Wolf +Message-id: <20200603160325.67506-6-kwolf@redhat.com> +Patchwork-id: 97103 +O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH v2 05/11] backup: Improve error for bdrv_getlength() failure +Bugzilla: 1778593 +RH-Acked-by: Eric Blake +RH-Acked-by: Max Reitz +RH-Acked-by: Stefano Garzarella + +bdrv_get_device_name() will be an empty string with modern management +tools that don't use -drive. Use bdrv_get_device_or_node_name() instead +so that the node name is used if the BlockBackend is anonymous. + +While at it, start with upper case to make the message consistent with +the rest of the function. + +Signed-off-by: Kevin Wolf +Reviewed-by: Vladimir Sementsov-Ogievskiy +Reviewed-by: Alberto Garcia +Message-Id: <20200430142755.315494-3-kwolf@redhat.com> +Signed-off-by: Kevin Wolf +(cherry picked from commit 58226634c4b02af7b10862f7fbd3610a344bfb7f) +Signed-off-by: Kevin Wolf +Signed-off-by: Danilo C. L. de Paula +--- + block/backup.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/block/backup.c b/block/backup.c +index ec50946..7c6ddd2 100644 +--- a/block/backup.c ++++ b/block/backup.c +@@ -408,8 +408,8 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs, + + len = bdrv_getlength(bs); + if (len < 0) { +- error_setg_errno(errp, -len, "unable to get length for '%s'", +- bdrv_get_device_name(bs)); ++ error_setg_errno(errp, -len, "Unable to get length for '%s'", ++ bdrv_get_device_or_node_name(bs)); + goto error; + } + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-backup-Make-sure-that-source-and-target-size-match.patch b/SOURCES/kvm-backup-Make-sure-that-source-and-target-size-match.patch new file mode 100644 index 0000000..05b5d10 --- /dev/null +++ b/SOURCES/kvm-backup-Make-sure-that-source-and-target-size-match.patch @@ -0,0 +1,124 @@ +From e56abd782be8bb41bb07c0317d008f95ec9a8ee5 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Wed, 3 Jun 2020 16:03:20 +0100 +Subject: [PATCH 21/26] backup: Make sure that source and target size match + +RH-Author: Kevin Wolf +Message-id: <20200603160325.67506-7-kwolf@redhat.com> +Patchwork-id: 97107 +O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH v2 06/11] backup: Make sure that source and target size match +Bugzilla: 1778593 +RH-Acked-by: Eric Blake +RH-Acked-by: Max Reitz +RH-Acked-by: Stefano Garzarella + +Since the introduction of a backup filter node in commit 00e30f05d, the +backup block job crashes when the target image is smaller than the +source image because it will try to write after the end of the target +node without having BLK_PERM_RESIZE. (Previously, the BlockBackend layer +would have caught this and errored out gracefully.) + +We can fix this and even do better than the old behaviour: Check that +source and target have the same image size at the start of the block job +and unshare BLK_PERM_RESIZE. (This permission was already unshared +before the same commit 00e30f05d, but the BlockBackend that was used to +make the restriction was removed without a replacement.) This will +immediately error out when starting the job instead of only when writing +to a block that doesn't exist in the target. + +Longer target than source would technically work because we would never +write to blocks that don't exist, but semantically these are invalid, +too, because a backup is supposed to create a copy, not just an image +that starts with a copy. + +Fixes: 00e30f05de1d19586345ec373970ef4c192c6270 +Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1778593 +Cc: qemu-stable@nongnu.org +Signed-off-by: Kevin Wolf +Message-Id: <20200430142755.315494-4-kwolf@redhat.com> +Reviewed-by: Vladimir Sementsov-Ogievskiy +Signed-off-by: Kevin Wolf +(cherry picked from commit 958a04bd32af18d9a207bcc78046e56a202aebc2) +Signed-off-by: Kevin Wolf +Signed-off-by: Danilo C. L. de Paula +--- + block/backup-top.c | 14 +++++++++----- + block/backup.c | 14 +++++++++++++- + 2 files changed, 22 insertions(+), 6 deletions(-) + +diff --git a/block/backup-top.c b/block/backup-top.c +index b8d863f..6756091 100644 +--- a/block/backup-top.c ++++ b/block/backup-top.c +@@ -143,8 +143,10 @@ static void backup_top_child_perm(BlockDriverState *bs, BdrvChild *c, + * + * Share write to target (child_file), to not interfere + * with guest writes to its disk which may be in target backing chain. ++ * Can't resize during a backup block job because we check the size ++ * only upfront. + */ +- *nshared = BLK_PERM_ALL; ++ *nshared = BLK_PERM_ALL & ~BLK_PERM_RESIZE; + *nperm = BLK_PERM_WRITE; + } else { + /* Source child */ +@@ -154,7 +156,7 @@ static void backup_top_child_perm(BlockDriverState *bs, BdrvChild *c, + if (perm & BLK_PERM_WRITE) { + *nperm = *nperm | BLK_PERM_CONSISTENT_READ; + } +- *nshared &= ~BLK_PERM_WRITE; ++ *nshared &= ~(BLK_PERM_WRITE | BLK_PERM_RESIZE); + } + } + +@@ -187,10 +189,12 @@ BlockDriverState *bdrv_backup_top_append(BlockDriverState *source, + { + Error *local_err = NULL; + BDRVBackupTopState *state; +- BlockDriverState *top = bdrv_new_open_driver(&bdrv_backup_top_filter, +- filter_node_name, +- BDRV_O_RDWR, errp); ++ BlockDriverState *top; ++ ++ assert(source->total_sectors == target->total_sectors); + ++ top = bdrv_new_open_driver(&bdrv_backup_top_filter, filter_node_name, ++ BDRV_O_RDWR, errp); + if (!top) { + return NULL; + } +diff --git a/block/backup.c b/block/backup.c +index 7c6ddd2..821c9fb 100644 +--- a/block/backup.c ++++ b/block/backup.c +@@ -348,7 +348,7 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs, + BlockCompletionFunc *cb, void *opaque, + JobTxn *txn, Error **errp) + { +- int64_t len; ++ int64_t len, target_len; + BackupBlockJob *job = NULL; + int64_t cluster_size; + BdrvRequestFlags write_flags; +@@ -413,6 +413,18 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs, + goto error; + } + ++ target_len = bdrv_getlength(target); ++ if (target_len < 0) { ++ error_setg_errno(errp, -target_len, "Unable to get length for '%s'", ++ bdrv_get_device_or_node_name(bs)); ++ goto error; ++ } ++ ++ if (target_len != len) { ++ error_setg(errp, "Source and target image have different sizes"); ++ goto error; ++ } ++ + cluster_size = backup_calculate_cluster_size(target, errp); + if (cluster_size < 0) { + goto error; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-block-Add-flags-to-BlockDriver.bdrv_co_truncate.patch b/SOURCES/kvm-block-Add-flags-to-BlockDriver.bdrv_co_truncate.patch new file mode 100644 index 0000000..bc67279 --- /dev/null +++ b/SOURCES/kvm-block-Add-flags-to-BlockDriver.bdrv_co_truncate.patch @@ -0,0 +1,283 @@ +From 13e2076f5c4adbc9a3f96c8978150aa5e423e14a Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Mon, 8 Jun 2020 15:01:30 +0100 +Subject: [PATCH 02/17] block: Add flags to BlockDriver.bdrv_co_truncate() + +RH-Author: Kevin Wolf +Message-id: <20200608150140.38218-2-kwolf@redhat.com> +Patchwork-id: 97448 +O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH 01/11] block: Add flags to BlockDriver.bdrv_co_truncate() +Bugzilla: 1780574 +RH-Acked-by: Sergio Lopez Pascual +RH-Acked-by: Eric Blake +RH-Acked-by: Max Reitz + +This adds a new BdrvRequestFlags parameter to the .bdrv_co_truncate() +driver callbacks, and a supported_truncate_flags field in +BlockDriverState that allows drivers to advertise support for request +flags in the context of truncate. + +For now, we always pass 0 and no drivers declare support for any flag. + +Signed-off-by: Kevin Wolf +Reviewed-by: Vladimir Sementsov-Ogievskiy +Reviewed-by: Alberto Garcia +Reviewed-by: Max Reitz +Message-Id: <20200424125448.63318-2-kwolf@redhat.com> +Signed-off-by: Kevin Wolf +(cherry picked from commit 92b92799dc8662b6f71809100a4aabc1ae408ebb) +Signed-off-by: Kevin Wolf +Signed-off-by: Danilo C. L. de Paula +--- + block/crypto.c | 3 ++- + block/file-posix.c | 2 +- + block/file-win32.c | 2 +- + block/gluster.c | 1 + + block/io.c | 8 +++++++- + block/iscsi.c | 2 +- + block/nfs.c | 3 ++- + block/qcow2.c | 2 +- + block/qed.c | 1 + + block/raw-format.c | 2 +- + block/rbd.c | 1 + + block/sheepdog.c | 4 ++-- + block/ssh.c | 2 +- + include/block/block_int.h | 10 +++++++++- + tests/test-block-iothread.c | 3 ++- + 15 files changed, 33 insertions(+), 13 deletions(-) + +diff --git a/block/crypto.c b/block/crypto.c +index 5e3b15c..6e4b726 100644 +--- a/block/crypto.c ++++ b/block/crypto.c +@@ -299,7 +299,8 @@ static int block_crypto_co_create_generic(BlockDriverState *bs, + + static int coroutine_fn + block_crypto_co_truncate(BlockDriverState *bs, int64_t offset, bool exact, +- PreallocMode prealloc, Error **errp) ++ PreallocMode prealloc, BdrvRequestFlags flags, ++ Error **errp) + { + BlockCrypto *crypto = bs->opaque; + uint64_t payload_offset = +diff --git a/block/file-posix.c b/block/file-posix.c +index 1609598..7551e8d 100644 +--- a/block/file-posix.c ++++ b/block/file-posix.c +@@ -2021,7 +2021,7 @@ raw_regular_truncate(BlockDriverState *bs, int fd, int64_t offset, + + static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset, + bool exact, PreallocMode prealloc, +- Error **errp) ++ BdrvRequestFlags flags, Error **errp) + { + BDRVRawState *s = bs->opaque; + struct stat st; +diff --git a/block/file-win32.c b/block/file-win32.c +index 1585983..a6b0dda 100644 +--- a/block/file-win32.c ++++ b/block/file-win32.c +@@ -469,7 +469,7 @@ static void raw_close(BlockDriverState *bs) + + static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset, + bool exact, PreallocMode prealloc, +- Error **errp) ++ BdrvRequestFlags flags, Error **errp) + { + BDRVRawState *s = bs->opaque; + LONG low, high; +diff --git a/block/gluster.c b/block/gluster.c +index 0aa1f2c..d06df90 100644 +--- a/block/gluster.c ++++ b/block/gluster.c +@@ -1228,6 +1228,7 @@ static coroutine_fn int qemu_gluster_co_truncate(BlockDriverState *bs, + int64_t offset, + bool exact, + PreallocMode prealloc, ++ BdrvRequestFlags flags, + Error **errp) + { + BDRVGlusterState *s = bs->opaque; +diff --git a/block/io.c b/block/io.c +index f75777f..549e5a4 100644 +--- a/block/io.c ++++ b/block/io.c +@@ -3320,6 +3320,7 @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact, + BlockDriverState *bs = child->bs; + BlockDriver *drv = bs->drv; + BdrvTrackedRequest req; ++ BdrvRequestFlags flags = 0; + int64_t old_size, new_bytes; + int ret; + +@@ -3370,7 +3371,12 @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact, + } + + if (drv->bdrv_co_truncate) { +- ret = drv->bdrv_co_truncate(bs, offset, exact, prealloc, errp); ++ if (flags & ~bs->supported_truncate_flags) { ++ error_setg(errp, "Block driver does not support requested flags"); ++ ret = -ENOTSUP; ++ goto out; ++ } ++ ret = drv->bdrv_co_truncate(bs, offset, exact, prealloc, flags, errp); + } else if (bs->file && drv->is_filter) { + ret = bdrv_co_truncate(bs->file, offset, exact, prealloc, errp); + } else { +diff --git a/block/iscsi.c b/block/iscsi.c +index 16b0716..0bea2d3 100644 +--- a/block/iscsi.c ++++ b/block/iscsi.c +@@ -2125,7 +2125,7 @@ static void iscsi_reopen_commit(BDRVReopenState *reopen_state) + + static int coroutine_fn iscsi_co_truncate(BlockDriverState *bs, int64_t offset, + bool exact, PreallocMode prealloc, +- Error **errp) ++ BdrvRequestFlags flags, Error **errp) + { + IscsiLun *iscsilun = bs->opaque; + int64_t cur_length; +diff --git a/block/nfs.c b/block/nfs.c +index cc2413d..2393fbf 100644 +--- a/block/nfs.c ++++ b/block/nfs.c +@@ -755,7 +755,8 @@ static int64_t nfs_get_allocated_file_size(BlockDriverState *bs) + + static int coroutine_fn + nfs_file_co_truncate(BlockDriverState *bs, int64_t offset, bool exact, +- PreallocMode prealloc, Error **errp) ++ PreallocMode prealloc, BdrvRequestFlags flags, ++ Error **errp) + { + NFSClient *client = bs->opaque; + int ret; +diff --git a/block/qcow2.c b/block/qcow2.c +index dbd870a..977445e 100644 +--- a/block/qcow2.c ++++ b/block/qcow2.c +@@ -3948,7 +3948,7 @@ fail: + + static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset, + bool exact, PreallocMode prealloc, +- Error **errp) ++ BdrvRequestFlags flags, Error **errp) + { + BDRVQcow2State *s = bs->opaque; + uint64_t old_length; +diff --git a/block/qed.c b/block/qed.c +index 1af9b3c..fb6100b 100644 +--- a/block/qed.c ++++ b/block/qed.c +@@ -1467,6 +1467,7 @@ static int coroutine_fn bdrv_qed_co_truncate(BlockDriverState *bs, + int64_t offset, + bool exact, + PreallocMode prealloc, ++ BdrvRequestFlags flags, + Error **errp) + { + BDRVQEDState *s = bs->opaque; +diff --git a/block/raw-format.c b/block/raw-format.c +index 4bb54f4..f994c4a 100644 +--- a/block/raw-format.c ++++ b/block/raw-format.c +@@ -371,7 +371,7 @@ static void raw_refresh_limits(BlockDriverState *bs, Error **errp) + + static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset, + bool exact, PreallocMode prealloc, +- Error **errp) ++ BdrvRequestFlags flags, Error **errp) + { + BDRVRawState *s = bs->opaque; + +diff --git a/block/rbd.c b/block/rbd.c +index 8847259..fcdb60a 100644 +--- a/block/rbd.c ++++ b/block/rbd.c +@@ -1090,6 +1090,7 @@ static int coroutine_fn qemu_rbd_co_truncate(BlockDriverState *bs, + int64_t offset, + bool exact, + PreallocMode prealloc, ++ BdrvRequestFlags flags, + Error **errp) + { + int r; +diff --git a/block/sheepdog.c b/block/sheepdog.c +index a8a7e32..077aed8 100644 +--- a/block/sheepdog.c ++++ b/block/sheepdog.c +@@ -2288,7 +2288,7 @@ static int64_t sd_getlength(BlockDriverState *bs) + + static int coroutine_fn sd_co_truncate(BlockDriverState *bs, int64_t offset, + bool exact, PreallocMode prealloc, +- Error **errp) ++ BdrvRequestFlags flags, Error **errp) + { + BDRVSheepdogState *s = bs->opaque; + int ret, fd; +@@ -2604,7 +2604,7 @@ static coroutine_fn int sd_co_writev(BlockDriverState *bs, int64_t sector_num, + + assert(!flags); + if (offset > s->inode.vdi_size) { +- ret = sd_co_truncate(bs, offset, false, PREALLOC_MODE_OFF, NULL); ++ ret = sd_co_truncate(bs, offset, false, PREALLOC_MODE_OFF, 0, NULL); + if (ret < 0) { + return ret; + } +diff --git a/block/ssh.c b/block/ssh.c +index 84e9282..9eb33df 100644 +--- a/block/ssh.c ++++ b/block/ssh.c +@@ -1298,7 +1298,7 @@ static int64_t ssh_getlength(BlockDriverState *bs) + + static int coroutine_fn ssh_co_truncate(BlockDriverState *bs, int64_t offset, + bool exact, PreallocMode prealloc, +- Error **errp) ++ BdrvRequestFlags flags, Error **errp) + { + BDRVSSHState *s = bs->opaque; + +diff --git a/include/block/block_int.h b/include/block/block_int.h +index 876a83d..41f13ec 100644 +--- a/include/block/block_int.h ++++ b/include/block/block_int.h +@@ -356,7 +356,7 @@ struct BlockDriver { + */ + int coroutine_fn (*bdrv_co_truncate)(BlockDriverState *bs, int64_t offset, + bool exact, PreallocMode prealloc, +- Error **errp); ++ BdrvRequestFlags flags, Error **errp); + + int64_t (*bdrv_getlength)(BlockDriverState *bs); + bool has_variable_length; +@@ -849,6 +849,14 @@ struct BlockDriverState { + /* Flags honored during pwrite_zeroes (so far: BDRV_REQ_FUA, + * BDRV_REQ_MAY_UNMAP, BDRV_REQ_WRITE_UNCHANGED) */ + unsigned int supported_zero_flags; ++ /* ++ * Flags honoured during truncate (so far: BDRV_REQ_ZERO_WRITE). ++ * ++ * If BDRV_REQ_ZERO_WRITE is given, the truncate operation must make sure ++ * that any added space reads as all zeros. If this can't be guaranteed, ++ * the operation must fail. ++ */ ++ unsigned int supported_truncate_flags; + + /* the following member gives a name to every node on the bs graph. */ + char node_name[32]; +diff --git a/tests/test-block-iothread.c b/tests/test-block-iothread.c +index 0c86180..2f3b763 100644 +--- a/tests/test-block-iothread.c ++++ b/tests/test-block-iothread.c +@@ -46,7 +46,8 @@ static int coroutine_fn bdrv_test_co_pdiscard(BlockDriverState *bs, + + static int coroutine_fn + bdrv_test_co_truncate(BlockDriverState *bs, int64_t offset, bool exact, +- PreallocMode prealloc, Error **errp) ++ PreallocMode prealloc, BdrvRequestFlags flags, ++ Error **errp) + { + return 0; + } +-- +1.8.3.1 + diff --git a/SOURCES/kvm-block-Add-flags-to-bdrv-_co-_truncate.patch b/SOURCES/kvm-block-Add-flags-to-bdrv-_co-_truncate.patch new file mode 100644 index 0000000..3da05ff --- /dev/null +++ b/SOURCES/kvm-block-Add-flags-to-bdrv-_co-_truncate.patch @@ -0,0 +1,353 @@ +From 50127f0ff9e13a15fd5bfeb2662e2404ff20f364 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Mon, 8 Jun 2020 15:01:31 +0100 +Subject: [PATCH 03/17] block: Add flags to bdrv(_co)_truncate() + +RH-Author: Kevin Wolf +Message-id: <20200608150140.38218-3-kwolf@redhat.com> +Patchwork-id: 97445 +O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH 02/11] block: Add flags to bdrv(_co)_truncate() +Bugzilla: 1780574 +RH-Acked-by: Sergio Lopez Pascual +RH-Acked-by: Eric Blake +RH-Acked-by: Max Reitz + +Now that block drivers can support flags for .bdrv_co_truncate, expose +the parameter in the node level interfaces bdrv_co_truncate() and +bdrv_truncate(). + +Signed-off-by: Kevin Wolf +Reviewed-by: Vladimir Sementsov-Ogievskiy +Reviewed-by: Alberto Garcia +Reviewed-by: Max Reitz +Message-Id: <20200424125448.63318-3-kwolf@redhat.com> +Signed-off-by: Kevin Wolf +(cherry picked from commit 7b8e4857426f2e2de2441749996c6161b550bada) +Signed-off-by: Kevin Wolf +Signed-off-by: Danilo C. L. de Paula +--- + block/block-backend.c | 2 +- + block/crypto.c | 2 +- + block/io.c | 12 +++++++----- + block/parallels.c | 6 +++--- + block/qcow.c | 4 ++-- + block/qcow2-refcount.c | 2 +- + block/qcow2.c | 15 +++++++++------ + block/raw-format.c | 2 +- + block/vhdx-log.c | 2 +- + block/vhdx.c | 2 +- + block/vmdk.c | 2 +- + include/block/block.h | 5 +++-- + tests/test-block-iothread.c | 6 +++--- + 13 files changed, 34 insertions(+), 28 deletions(-) + +diff --git a/block/block-backend.c b/block/block-backend.c +index 38ae413..8be2006 100644 +--- a/block/block-backend.c ++++ b/block/block-backend.c +@@ -2144,7 +2144,7 @@ int blk_truncate(BlockBackend *blk, int64_t offset, bool exact, + return -ENOMEDIUM; + } + +- return bdrv_truncate(blk->root, offset, exact, prealloc, errp); ++ return bdrv_truncate(blk->root, offset, exact, prealloc, 0, errp); + } + + int blk_save_vmstate(BlockBackend *blk, const uint8_t *buf, +diff --git a/block/crypto.c b/block/crypto.c +index 6e4b726..fcb4a97 100644 +--- a/block/crypto.c ++++ b/block/crypto.c +@@ -313,7 +313,7 @@ block_crypto_co_truncate(BlockDriverState *bs, int64_t offset, bool exact, + + offset += payload_offset; + +- return bdrv_co_truncate(bs->file, offset, exact, prealloc, errp); ++ return bdrv_co_truncate(bs->file, offset, exact, prealloc, 0, errp); + } + + static void block_crypto_close(BlockDriverState *bs) +diff --git a/block/io.c b/block/io.c +index 549e5a4..3235ce5 100644 +--- a/block/io.c ++++ b/block/io.c +@@ -3315,12 +3315,12 @@ static void bdrv_parent_cb_resize(BlockDriverState *bs) + * 'offset' bytes in length. + */ + int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact, +- PreallocMode prealloc, Error **errp) ++ PreallocMode prealloc, BdrvRequestFlags flags, ++ Error **errp) + { + BlockDriverState *bs = child->bs; + BlockDriver *drv = bs->drv; + BdrvTrackedRequest req; +- BdrvRequestFlags flags = 0; + int64_t old_size, new_bytes; + int ret; + +@@ -3378,7 +3378,7 @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact, + } + ret = drv->bdrv_co_truncate(bs, offset, exact, prealloc, flags, errp); + } else if (bs->file && drv->is_filter) { +- ret = bdrv_co_truncate(bs->file, offset, exact, prealloc, errp); ++ ret = bdrv_co_truncate(bs->file, offset, exact, prealloc, flags, errp); + } else { + error_setg(errp, "Image format driver does not support resize"); + ret = -ENOTSUP; +@@ -3411,6 +3411,7 @@ typedef struct TruncateCo { + int64_t offset; + bool exact; + PreallocMode prealloc; ++ BdrvRequestFlags flags; + Error **errp; + int ret; + } TruncateCo; +@@ -3419,12 +3420,12 @@ static void coroutine_fn bdrv_truncate_co_entry(void *opaque) + { + TruncateCo *tco = opaque; + tco->ret = bdrv_co_truncate(tco->child, tco->offset, tco->exact, +- tco->prealloc, tco->errp); ++ tco->prealloc, tco->flags, tco->errp); + aio_wait_kick(); + } + + int bdrv_truncate(BdrvChild *child, int64_t offset, bool exact, +- PreallocMode prealloc, Error **errp) ++ PreallocMode prealloc, BdrvRequestFlags flags, Error **errp) + { + Coroutine *co; + TruncateCo tco = { +@@ -3432,6 +3433,7 @@ int bdrv_truncate(BdrvChild *child, int64_t offset, bool exact, + .offset = offset, + .exact = exact, + .prealloc = prealloc, ++ .flags = flags, + .errp = errp, + .ret = NOT_DONE, + }; +diff --git a/block/parallels.c b/block/parallels.c +index 6d4ed77..2be92cf 100644 +--- a/block/parallels.c ++++ b/block/parallels.c +@@ -203,7 +203,7 @@ static int64_t allocate_clusters(BlockDriverState *bs, int64_t sector_num, + } else { + ret = bdrv_truncate(bs->file, + (s->data_end + space) << BDRV_SECTOR_BITS, +- false, PREALLOC_MODE_OFF, NULL); ++ false, PREALLOC_MODE_OFF, 0, NULL); + } + if (ret < 0) { + return ret; +@@ -493,7 +493,7 @@ static int coroutine_fn parallels_co_check(BlockDriverState *bs, + * That means we have to pass exact=true. + */ + ret = bdrv_truncate(bs->file, res->image_end_offset, true, +- PREALLOC_MODE_OFF, &local_err); ++ PREALLOC_MODE_OFF, 0, &local_err); + if (ret < 0) { + error_report_err(local_err); + res->check_errors++; +@@ -889,7 +889,7 @@ static void parallels_close(BlockDriverState *bs) + + /* errors are ignored, so we might as well pass exact=true */ + bdrv_truncate(bs->file, s->data_end << BDRV_SECTOR_BITS, true, +- PREALLOC_MODE_OFF, NULL); ++ PREALLOC_MODE_OFF, 0, NULL); + } + + g_free(s->bat_dirty_bmap); +diff --git a/block/qcow.c b/block/qcow.c +index 8973e4e..6b5f226 100644 +--- a/block/qcow.c ++++ b/block/qcow.c +@@ -480,7 +480,7 @@ static int get_cluster_offset(BlockDriverState *bs, + return -E2BIG; + } + ret = bdrv_truncate(bs->file, cluster_offset + s->cluster_size, +- false, PREALLOC_MODE_OFF, NULL); ++ false, PREALLOC_MODE_OFF, 0, NULL); + if (ret < 0) { + return ret; + } +@@ -1035,7 +1035,7 @@ static int qcow_make_empty(BlockDriverState *bs) + l1_length) < 0) + return -1; + ret = bdrv_truncate(bs->file, s->l1_table_offset + l1_length, false, +- PREALLOC_MODE_OFF, NULL); ++ PREALLOC_MODE_OFF, 0, NULL); + if (ret < 0) + return ret; + +diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c +index f67ac6b..3a90d75 100644 +--- a/block/qcow2-refcount.c ++++ b/block/qcow2-refcount.c +@@ -2017,7 +2017,7 @@ static int check_refblocks(BlockDriverState *bs, BdrvCheckResult *res, + } + + ret = bdrv_truncate(bs->file, offset + s->cluster_size, false, +- PREALLOC_MODE_OFF, &local_err); ++ PREALLOC_MODE_OFF, 0, &local_err); + if (ret < 0) { + error_report_err(local_err); + goto resize_fail; +diff --git a/block/qcow2.c b/block/qcow2.c +index 977445e..c0fdcb9 100644 +--- a/block/qcow2.c ++++ b/block/qcow2.c +@@ -3082,7 +3082,7 @@ static int coroutine_fn preallocate_co(BlockDriverState *bs, uint64_t offset, + mode = PREALLOC_MODE_OFF; + } + ret = bdrv_co_truncate(s->data_file, host_offset + cur_bytes, false, +- mode, errp); ++ mode, 0, errp); + if (ret < 0) { + return ret; + } +@@ -4044,7 +4044,7 @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset, + * always fulfilled, so there is no need to pass it on.) + */ + bdrv_co_truncate(bs->file, (last_cluster + 1) * s->cluster_size, +- false, PREALLOC_MODE_OFF, &local_err); ++ false, PREALLOC_MODE_OFF, 0, &local_err); + if (local_err) { + warn_reportf_err(local_err, + "Failed to truncate the tail of the image: "); +@@ -4066,7 +4066,8 @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset, + * file should be resized to the exact target size, too, + * so we pass @exact here. + */ +- ret = bdrv_co_truncate(s->data_file, offset, exact, prealloc, errp); ++ ret = bdrv_co_truncate(s->data_file, offset, exact, prealloc, 0, ++ errp); + if (ret < 0) { + goto fail; + } +@@ -4152,7 +4153,8 @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset, + new_file_size = allocation_start + + nb_new_data_clusters * s->cluster_size; + /* Image file grows, so @exact does not matter */ +- ret = bdrv_co_truncate(bs->file, new_file_size, false, prealloc, errp); ++ ret = bdrv_co_truncate(bs->file, new_file_size, false, prealloc, 0, ++ errp); + if (ret < 0) { + error_prepend(errp, "Failed to resize underlying file: "); + qcow2_free_clusters(bs, allocation_start, +@@ -4255,7 +4257,8 @@ qcow2_co_pwritev_compressed_part(BlockDriverState *bs, + if (len < 0) { + return len; + } +- return bdrv_co_truncate(bs->file, len, false, PREALLOC_MODE_OFF, NULL); ++ return bdrv_co_truncate(bs->file, len, false, PREALLOC_MODE_OFF, 0, ++ NULL); + } + + if (offset_into_cluster(s, offset)) { +@@ -4493,7 +4496,7 @@ static int make_completely_empty(BlockDriverState *bs) + } + + ret = bdrv_truncate(bs->file, (3 + l1_clusters) * s->cluster_size, false, +- PREALLOC_MODE_OFF, &local_err); ++ PREALLOC_MODE_OFF, 0, &local_err); + if (ret < 0) { + error_report_err(local_err); + goto fail; +diff --git a/block/raw-format.c b/block/raw-format.c +index f994c4a..c3acf9a 100644 +--- a/block/raw-format.c ++++ b/block/raw-format.c +@@ -387,7 +387,7 @@ static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset, + + s->size = offset; + offset += s->offset; +- return bdrv_co_truncate(bs->file, offset, exact, prealloc, errp); ++ return bdrv_co_truncate(bs->file, offset, exact, prealloc, 0, errp); + } + + static void raw_eject(BlockDriverState *bs, bool eject_flag) +diff --git a/block/vhdx-log.c b/block/vhdx-log.c +index 13a49c2..404fb5f 100644 +--- a/block/vhdx-log.c ++++ b/block/vhdx-log.c +@@ -558,7 +558,7 @@ static int vhdx_log_flush(BlockDriverState *bs, BDRVVHDXState *s, + goto exit; + } + ret = bdrv_truncate(bs->file, new_file_size, false, +- PREALLOC_MODE_OFF, NULL); ++ PREALLOC_MODE_OFF, 0, NULL); + if (ret < 0) { + goto exit; + } +diff --git a/block/vhdx.c b/block/vhdx.c +index 33e57cd..5dfbb20 100644 +--- a/block/vhdx.c ++++ b/block/vhdx.c +@@ -1264,7 +1264,7 @@ static int vhdx_allocate_block(BlockDriverState *bs, BDRVVHDXState *s, + } + + return bdrv_truncate(bs->file, *new_offset + s->block_size, false, +- PREALLOC_MODE_OFF, NULL); ++ PREALLOC_MODE_OFF, 0, NULL); + } + + /* +diff --git a/block/vmdk.c b/block/vmdk.c +index eb726f2..1bbf937 100644 +--- a/block/vmdk.c ++++ b/block/vmdk.c +@@ -2077,7 +2077,7 @@ vmdk_co_pwritev_compressed(BlockDriverState *bs, uint64_t offset, + } + length = QEMU_ALIGN_UP(length, BDRV_SECTOR_SIZE); + ret = bdrv_truncate(s->extents[i].file, length, false, +- PREALLOC_MODE_OFF, NULL); ++ PREALLOC_MODE_OFF, 0, NULL); + if (ret < 0) { + return ret; + } +diff --git a/include/block/block.h b/include/block/block.h +index b2a3074..4913596 100644 +--- a/include/block/block.h ++++ b/include/block/block.h +@@ -348,9 +348,10 @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs, + void bdrv_refresh_filename(BlockDriverState *bs); + + int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact, +- PreallocMode prealloc, Error **errp); ++ PreallocMode prealloc, BdrvRequestFlags flags, ++ Error **errp); + int bdrv_truncate(BdrvChild *child, int64_t offset, bool exact, +- PreallocMode prealloc, Error **errp); ++ PreallocMode prealloc, BdrvRequestFlags flags, Error **errp); + + int64_t bdrv_nb_sectors(BlockDriverState *bs); + int64_t bdrv_getlength(BlockDriverState *bs); +diff --git a/tests/test-block-iothread.c b/tests/test-block-iothread.c +index 2f3b763..71e9bce 100644 +--- a/tests/test-block-iothread.c ++++ b/tests/test-block-iothread.c +@@ -186,18 +186,18 @@ static void test_sync_op_truncate(BdrvChild *c) + int ret; + + /* Normal success path */ +- ret = bdrv_truncate(c, 65536, false, PREALLOC_MODE_OFF, NULL); ++ ret = bdrv_truncate(c, 65536, false, PREALLOC_MODE_OFF, 0, NULL); + g_assert_cmpint(ret, ==, 0); + + /* Early error: Negative offset */ +- ret = bdrv_truncate(c, -2, false, PREALLOC_MODE_OFF, NULL); ++ ret = bdrv_truncate(c, -2, false, PREALLOC_MODE_OFF, 0, NULL); + g_assert_cmpint(ret, ==, -EINVAL); + + /* Error: Read-only image */ + c->bs->read_only = true; + c->bs->open_flags &= ~BDRV_O_RDWR; + +- ret = bdrv_truncate(c, 65536, false, PREALLOC_MODE_OFF, NULL); ++ ret = bdrv_truncate(c, 65536, false, PREALLOC_MODE_OFF, 0, NULL); + g_assert_cmpint(ret, ==, -EACCES); + + c->bs->read_only = false; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-block-Call-attention-to-truncation-of-long-NBD-expor.patch b/SOURCES/kvm-block-Call-attention-to-truncation-of-long-NBD-expor.patch new file mode 100644 index 0000000..190826f --- /dev/null +++ b/SOURCES/kvm-block-Call-attention-to-truncation-of-long-NBD-expor.patch @@ -0,0 +1,105 @@ +From c8ecaea34f03b8ddda7d2b41b0d6f397469c8959 Mon Sep 17 00:00:00 2001 +From: Eric Blake +Date: Wed, 10 Jun 2020 18:32:02 -0400 +Subject: [PATCH 2/2] block: Call attention to truncation of long NBD exports + +RH-Author: Eric Blake +Message-id: <20200610183202.3780750-3-eblake@redhat.com> +Patchwork-id: 97495 +O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH 2/2] block: Call attention to truncation of long NBD exports +Bugzilla: 1845384 +RH-Acked-by: Sergio Lopez Pascual +RH-Acked-by: Max Reitz +RH-Acked-by: Stefan Hajnoczi + +Commit 93676c88 relaxed our NBD client code to request export names up +to the NBD protocol maximum of 4096 bytes without NUL terminator, even +though the block layer can't store anything longer than 4096 bytes +including NUL terminator for display to the user. Since this means +there are some export names where we have to truncate things, we can +at least try to make the truncation a bit more obvious for the user. +Note that in spite of the truncated display name, we can still +communicate with an NBD server using such a long export name; this was +deemed nicer than refusing to even connect to such a server (since the +server may not be under our control, and since determining our actual +length limits gets tricky when nbd://host:port/export and +nbd+unix:///export?socket=/path are themselves variable-length +expansions beyond the export name but count towards the block layer +name length). + +Reported-by: Xueqiang Wei +Fixes: https://bugzilla.redhat.com/1843684 +Signed-off-by: Eric Blake +Reviewed-by: Vladimir Sementsov-Ogievskiy +Message-Id: <20200610163741.3745251-3-eblake@redhat.com> +(cherry picked from commit 5c86bdf1208916ece0b87e1151c9b48ee54faa3e) +Signed-off-by: Eric Blake +Signed-off-by: Eduardo Lima (Etrunko) +--- + block.c | 7 +++++-- + block/nbd.c | 21 +++++++++++++-------- + 2 files changed, 18 insertions(+), 10 deletions(-) + +diff --git a/block.c b/block.c +index 12c8941879..57740d312e 100644 +--- a/block.c ++++ b/block.c +@@ -6683,8 +6683,11 @@ void bdrv_refresh_filename(BlockDriverState *bs) + pstrcpy(bs->filename, sizeof(bs->filename), bs->exact_filename); + } else { + QString *json = qobject_to_json(QOBJECT(bs->full_open_options)); +- snprintf(bs->filename, sizeof(bs->filename), "json:%s", +- qstring_get_str(json)); ++ if (snprintf(bs->filename, sizeof(bs->filename), "json:%s", ++ qstring_get_str(json)) >= sizeof(bs->filename)) { ++ /* Give user a hint if we truncated things. */ ++ strcpy(bs->filename + sizeof(bs->filename) - 4, "..."); ++ } + qobject_unref(json); + } + } +diff --git a/block/nbd.c b/block/nbd.c +index 927915d93d..5bb154017d 100644 +--- a/block/nbd.c ++++ b/block/nbd.c +@@ -1978,6 +1978,7 @@ static void nbd_refresh_filename(BlockDriverState *bs) + { + BDRVNBDState *s = bs->opaque; + const char *host = NULL, *port = NULL, *path = NULL; ++ size_t len = 0; + + if (s->saddr->type == SOCKET_ADDRESS_TYPE_INET) { + const InetSocketAddress *inet = &s->saddr->u.inet; +@@ -1990,17 +1991,21 @@ static void nbd_refresh_filename(BlockDriverState *bs) + } /* else can't represent as pseudo-filename */ + + if (path && s->export) { +- snprintf(bs->exact_filename, sizeof(bs->exact_filename), +- "nbd+unix:///%s?socket=%s", s->export, path); ++ len = snprintf(bs->exact_filename, sizeof(bs->exact_filename), ++ "nbd+unix:///%s?socket=%s", s->export, path); + } else if (path && !s->export) { +- snprintf(bs->exact_filename, sizeof(bs->exact_filename), +- "nbd+unix://?socket=%s", path); ++ len = snprintf(bs->exact_filename, sizeof(bs->exact_filename), ++ "nbd+unix://?socket=%s", path); + } else if (host && s->export) { +- snprintf(bs->exact_filename, sizeof(bs->exact_filename), +- "nbd://%s:%s/%s", host, port, s->export); ++ len = snprintf(bs->exact_filename, sizeof(bs->exact_filename), ++ "nbd://%s:%s/%s", host, port, s->export); + } else if (host && !s->export) { +- snprintf(bs->exact_filename, sizeof(bs->exact_filename), +- "nbd://%s:%s", host, port); ++ len = snprintf(bs->exact_filename, sizeof(bs->exact_filename), ++ "nbd://%s:%s", host, port); ++ } ++ if (len > sizeof(bs->exact_filename)) { ++ /* Name is too long to represent exactly, so leave it empty. */ ++ bs->exact_filename[0] = '\0'; + } + } + +-- +2.27.0 + diff --git a/SOURCES/kvm-block-Make-it-easier-to-learn-which-BDS-support-bitm.patch b/SOURCES/kvm-block-Make-it-easier-to-learn-which-BDS-support-bitm.patch new file mode 100644 index 0000000..0d4a000 --- /dev/null +++ b/SOURCES/kvm-block-Make-it-easier-to-learn-which-BDS-support-bitm.patch @@ -0,0 +1,145 @@ +From 41d6c207c482093df8669f7cdcdb49bb25dba741 Mon Sep 17 00:00:00 2001 +From: Eric Blake +Date: Tue, 2 Jun 2020 02:34:12 +0100 +Subject: [PATCH 07/26] block: Make it easier to learn which BDS support + bitmaps +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Eric Blake +Message-id: <20200602023420.2133649-5-eblake@redhat.com> +Patchwork-id: 97071 +O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH 04/12] block: Make it easier to learn which BDS support bitmaps +Bugzilla: 1779893 1779904 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Max Reitz +RH-Acked-by: Kevin Wolf + +Upcoming patches will enhance bitmap support in qemu-img, but in doing +so, it turns out to be nice to suppress output when persistent bitmaps +make no sense (such as on a qcow2 v2 image). Add a hook to make this +easier to query. + +This patch adds a new callback .bdrv_supports_persistent_dirty_bitmap, +rather than trying to shoehorn the answer in via existing callbacks. +In particular, while it might have been possible to overload +.bdrv_co_can_store_new_dirty_bitmap to special-case a NULL input to +answer whether any persistent bitmaps are supported, that is at odds +with whether a particular bitmap can be stored (for example, even on +an image that supports persistent bitmaps but has currently filled up +the maximum number of bitmaps, attempts to store another one should +fail); and the new functionality doesn't require coroutine safety. +Similarly, we could have added one more piece of information to +.bdrv_get_info, but then again, most callers to that function tend to +already discard extraneous information, and making it a catch-all +rather than a series of dedicated scalar queries hasn't really +simplified life. + +In the future, when we improve the ability to look up bitmaps through +a filter, we will probably also want to teach the block layer to +automatically let filters pass this request on through. + +Signed-off-by: Eric Blake +Message-Id: <20200513011648.166876-4-eblake@redhat.com> +Reviewed-by: Vladimir Sementsov-Ogievskiy +(cherry picked from commit ef893b5c84f3199d777e33966dc28839f71b1a5c) +Signed-off-by: Eric Blake +Signed-off-by: Danilo C. L. de Paula +--- + block/dirty-bitmap.c | 9 +++++++++ + block/qcow2-bitmap.c | 7 +++++++ + block/qcow2.c | 2 ++ + block/qcow2.h | 1 + + include/block/block_int.h | 1 + + include/block/dirty-bitmap.h | 1 + + 6 files changed, 21 insertions(+) + +diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c +index 7039e82..2f96acc 100644 +--- a/block/dirty-bitmap.c ++++ b/block/dirty-bitmap.c +@@ -478,6 +478,15 @@ int bdrv_remove_persistent_dirty_bitmap(BlockDriverState *bs, const char *name, + } + } + ++bool ++bdrv_supports_persistent_dirty_bitmap(BlockDriverState *bs) ++{ ++ if (bs->drv && bs->drv->bdrv_supports_persistent_dirty_bitmap) { ++ return bs->drv->bdrv_supports_persistent_dirty_bitmap(bs); ++ } ++ return false; ++} ++ + static bool coroutine_fn + bdrv_co_can_store_new_dirty_bitmap(BlockDriverState *bs, const char *name, + uint32_t granularity, Error **errp) +diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c +index c6c8ebb..cbac905 100644 +--- a/block/qcow2-bitmap.c ++++ b/block/qcow2-bitmap.c +@@ -1759,3 +1759,10 @@ fail: + name, bdrv_get_device_or_node_name(bs)); + return false; + } ++ ++bool qcow2_supports_persistent_dirty_bitmap(BlockDriverState *bs) ++{ ++ BDRVQcow2State *s = bs->opaque; ++ ++ return s->qcow_version >= 3; ++} +diff --git a/block/qcow2.c b/block/qcow2.c +index af0ad4a..36b0f7d 100644 +--- a/block/qcow2.c ++++ b/block/qcow2.c +@@ -5551,6 +5551,8 @@ BlockDriver bdrv_qcow2 = { + .bdrv_detach_aio_context = qcow2_detach_aio_context, + .bdrv_attach_aio_context = qcow2_attach_aio_context, + ++ .bdrv_supports_persistent_dirty_bitmap = ++ qcow2_supports_persistent_dirty_bitmap, + .bdrv_co_can_store_new_dirty_bitmap = qcow2_co_can_store_new_dirty_bitmap, + .bdrv_co_remove_persistent_dirty_bitmap = + qcow2_co_remove_persistent_dirty_bitmap, +diff --git a/block/qcow2.h b/block/qcow2.h +index 0942126..ceb1ceb 100644 +--- a/block/qcow2.h ++++ b/block/qcow2.h +@@ -767,6 +767,7 @@ bool qcow2_co_can_store_new_dirty_bitmap(BlockDriverState *bs, + int qcow2_co_remove_persistent_dirty_bitmap(BlockDriverState *bs, + const char *name, + Error **errp); ++bool qcow2_supports_persistent_dirty_bitmap(BlockDriverState *bs); + + ssize_t coroutine_fn + qcow2_co_compress(BlockDriverState *bs, void *dest, size_t dest_size, +diff --git a/include/block/block_int.h b/include/block/block_int.h +index 562dca1..cc18e8d 100644 +--- a/include/block/block_int.h ++++ b/include/block/block_int.h +@@ -568,6 +568,7 @@ struct BlockDriver { + uint64_t parent_perm, uint64_t parent_shared, + uint64_t *nperm, uint64_t *nshared); + ++ bool (*bdrv_supports_persistent_dirty_bitmap)(BlockDriverState *bs); + bool (*bdrv_co_can_store_new_dirty_bitmap)(BlockDriverState *bs, + const char *name, + uint32_t granularity, +diff --git a/include/block/dirty-bitmap.h b/include/block/dirty-bitmap.h +index e2b20ec..f6e9a38 100644 +--- a/include/block/dirty-bitmap.h ++++ b/include/block/dirty-bitmap.h +@@ -16,6 +16,7 @@ typedef enum BitmapCheckFlags { + + #define BDRV_BITMAP_MAX_NAME_SIZE 1023 + ++bool bdrv_supports_persistent_dirty_bitmap(BlockDriverState *bs); + BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs, + uint32_t granularity, + const char *name, +-- +1.8.3.1 + diff --git a/SOURCES/kvm-block-always-fill-entire-LUKS-header-space-with-zero.patch b/SOURCES/kvm-block-always-fill-entire-LUKS-header-space-with-zero.patch new file mode 100644 index 0000000..d1511d2 --- /dev/null +++ b/SOURCES/kvm-block-always-fill-entire-LUKS-header-space-with-zero.patch @@ -0,0 +1,308 @@ +From 67f36d057aa71ca56ebc17ef28a7cb70bac6c6b6 Mon Sep 17 00:00:00 2001 +From: "Daniel P. Berrange" +Date: Tue, 5 May 2020 16:46:01 +0100 +Subject: [PATCH 01/12] block: always fill entire LUKS header space with zeros +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Daniel P. Berrange +Message-id: <20200505164601.1059974-2-berrange@redhat.com> +Patchwork-id: 96277 +O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH 1/1] block: always fill entire LUKS header space with zeros +Bugzilla: 1775462 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: John Snow +RH-Acked-by: Stefan Hajnoczi + +When initializing the LUKS header the size with default encryption +parameters will currently be 2068480 bytes. This is rounded up to +a multiple of the cluster size, 2081792, with 64k sectors. If the +end of the header is not the same as the end of the cluster we fill +the extra space with zeros. This was forgetting that not even the +space allocated for the header will be fully initialized, as we +only write key material for the first key slot. The space left +for the other 7 slots is never written to. + +An optimization to the ref count checking code: + + commit a5fff8d4b4d928311a5005efa12d0991fe3b66f9 (refs/bisect/bad) + Author: Vladimir Sementsov-Ogievskiy + Date: Wed Feb 27 16:14:30 2019 +0300 + + qcow2-refcount: avoid eating RAM + +made the assumption that every cluster which was allocated would +have at least some data written to it. This was violated by way +the LUKS header is only partially written, with much space simply +reserved for future use. + +Depending on the cluster size this problem was masked by the +logic which wrote zeros between the end of the LUKS header and +the end of the cluster. + +$ qemu-img create --object secret,id=cluster_encrypt0,data=123456 \ + -f qcow2 -o cluster_size=2k,encrypt.iter-time=1,\ + encrypt.format=luks,encrypt.key-secret=cluster_encrypt0 \ + cluster_size_check.qcow2 100M + Formatting 'cluster_size_check.qcow2', fmt=qcow2 size=104857600 + encrypt.format=luks encrypt.key-secret=cluster_encrypt0 + encrypt.iter-time=1 cluster_size=2048 lazy_refcounts=off refcount_bits=16 + +$ qemu-img check --object secret,id=cluster_encrypt0,data=redhat \ + 'json:{"driver": "qcow2", "encrypt.format": "luks", \ + "encrypt.key-secret": "cluster_encrypt0", \ + "file.driver": "file", "file.filename": "cluster_size_check.qcow2"}' +ERROR: counting reference for region exceeding the end of the file by one cluster or more: offset 0x2000 size 0x1f9000 +Leaked cluster 4 refcount=1 reference=0 +...snip... +Leaked cluster 130 refcount=1 reference=0 + +1 errors were found on the image. +Data may be corrupted, or further writes to the image may corrupt it. + +127 leaked clusters were found on the image. +This means waste of disk space, but no harm to data. +Image end offset: 268288 + +The problem only exists when the disk image is entirely empty. Writing +data to the disk image payload will solve the problem by causing the +end of the file to be extended further. + +The change fixes it by ensuring that the entire allocated LUKS header +region is fully initialized with zeros. The qemu-img check will still +fail for any pre-existing disk images created prior to this change, +unless at least 1 byte of the payload is written to. + +Fully writing zeros to the entire LUKS header is a good idea regardless +as it ensures that space has been allocated on the host filesystem (or +whatever block storage backend is used). + +Signed-off-by: Daniel P. Berrangé +Message-Id: <20200207135520.2669430-1-berrange@redhat.com> +Reviewed-by: Eric Blake +Signed-off-by: Max Reitz +(cherry picked from commit 087ab8e775f48766068e65de1bc99d03b40d1670) +Signed-off-by: Danilo C. L. de Paula + +Conflicts: + tests/qemu-iotests/group: no test 283 in downstream + +Signed-off-by: Danilo C. L. de Paula +--- + block/qcow2.c | 11 ++++-- + tests/qemu-iotests/284 | 97 ++++++++++++++++++++++++++++++++++++++++++++++ + tests/qemu-iotests/284.out | 62 +++++++++++++++++++++++++++++ + tests/qemu-iotests/group | 1 + + 4 files changed, 167 insertions(+), 4 deletions(-) + create mode 100755 tests/qemu-iotests/284 + create mode 100644 tests/qemu-iotests/284.out + +diff --git a/block/qcow2.c b/block/qcow2.c +index 71067c6..af0ad4a 100644 +--- a/block/qcow2.c ++++ b/block/qcow2.c +@@ -135,13 +135,16 @@ static ssize_t qcow2_crypto_hdr_init_func(QCryptoBlock *block, size_t headerlen, + s->crypto_header.length = headerlen; + s->crypto_header.offset = ret; + +- /* Zero fill remaining space in cluster so it has predictable +- * content in case of future spec changes */ ++ /* ++ * Zero fill all space in cluster so it has predictable ++ * content, as we may not initialize some regions of the ++ * header (eg only 1 out of 8 key slots will be initialized) ++ */ + clusterlen = size_to_clusters(s, headerlen) * s->cluster_size; + assert(qcow2_pre_write_overlap_check(bs, 0, ret, clusterlen, false) == 0); + ret = bdrv_pwrite_zeroes(bs->file, +- ret + headerlen, +- clusterlen - headerlen, 0); ++ ret, ++ clusterlen, 0); + if (ret < 0) { + error_setg_errno(errp, -ret, "Could not zero fill encryption header"); + return -1; +diff --git a/tests/qemu-iotests/284 b/tests/qemu-iotests/284 +new file mode 100755 +index 0000000..071e89b +--- /dev/null ++++ b/tests/qemu-iotests/284 +@@ -0,0 +1,97 @@ ++#!/usr/bin/env bash ++# ++# Test ref count checks on encrypted images ++# ++# 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 . ++# ++ ++# creator ++owner=berrange@redhat.com ++ ++seq=`basename $0` ++echo "QA output created by $seq" ++ ++status=1 # failure is the default! ++ ++_cleanup() ++{ ++ _cleanup_test_img ++} ++trap "_cleanup; exit \$status" 0 1 2 3 15 ++ ++# get standard environment, filters and checks ++. ./common.rc ++. ./common.filter ++ ++_supported_fmt qcow2 ++_supported_proto generic ++_supported_os Linux ++ ++ ++size=1M ++ ++SECRET="secret,id=sec0,data=astrochicken" ++ ++IMGSPEC="driver=$IMGFMT,file.filename=$TEST_IMG,encrypt.key-secret=sec0" ++QEMU_IO_OPTIONS=$QEMU_IO_OPTIONS_NO_FMT ++ ++_run_test() ++{ ++ IMGOPTSSYNTAX=true ++ OLD_TEST_IMG="$TEST_IMG" ++ TEST_IMG="driver=$IMGFMT,file.filename=$TEST_IMG,encrypt.key-secret=sec0" ++ QEMU_IMG_EXTRA_ARGS="--image-opts --object $SECRET" ++ ++ echo ++ echo "== cluster size $csize" ++ echo "== checking image refcounts ==" ++ _check_test_img ++ ++ echo ++ echo "== writing some data ==" ++ $QEMU_IO -c "write -P 0x9 0 1" $QEMU_IMG_EXTRA_ARGS $TEST_IMG | _filter_qemu_io | _filter_testdir ++ echo ++ echo "== rechecking image refcounts ==" ++ _check_test_img ++ ++ echo ++ echo "== writing some more data ==" ++ $QEMU_IO -c "write -P 0x9 $csize 1" $QEMU_IMG_EXTRA_ARGS $TEST_IMG | _filter_qemu_io | _filter_testdir ++ echo ++ echo "== rechecking image refcounts ==" ++ _check_test_img ++ ++ TEST_IMG="$OLD_TEST_IMG" ++ QEMU_IMG_EXTRA_ARGS= ++ IMGOPTSSYNTAX= ++} ++ ++ ++echo ++echo "testing LUKS qcow2 encryption" ++echo ++ ++for csize in 512 2048 32768 ++do ++ _make_test_img --object $SECRET -o "encrypt.format=luks,encrypt.key-secret=sec0,encrypt.iter-time=10,cluster_size=$csize" $size ++ _run_test ++ _cleanup_test_img ++done ++ ++# success, all done ++echo "*** done" ++rm -f $seq.full ++status=0 +diff --git a/tests/qemu-iotests/284.out b/tests/qemu-iotests/284.out +new file mode 100644 +index 0000000..48216f5 +--- /dev/null ++++ b/tests/qemu-iotests/284.out +@@ -0,0 +1,62 @@ ++QA output created by 284 ++ ++testing LUKS qcow2 encryption ++ ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 encrypt.format=luks encrypt.key-secret=sec0 encrypt.iter-time=10 ++ ++== cluster size 512 ++== checking image refcounts == ++No errors were found on the image. ++ ++== writing some data == ++wrote 1/1 bytes at offset 0 ++1 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++== rechecking image refcounts == ++No errors were found on the image. ++ ++== writing some more data == ++wrote 1/1 bytes at offset 512 ++1 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++== rechecking image refcounts == ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 encrypt.format=luks encrypt.key-secret=sec0 encrypt.iter-time=10 ++ ++== cluster size 2048 ++== checking image refcounts == ++No errors were found on the image. ++ ++== writing some data == ++wrote 1/1 bytes at offset 0 ++1 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++== rechecking image refcounts == ++No errors were found on the image. ++ ++== writing some more data == ++wrote 1/1 bytes at offset 2048 ++1 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++== rechecking image refcounts == ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 encrypt.format=luks encrypt.key-secret=sec0 encrypt.iter-time=10 ++ ++== cluster size 32768 ++== checking image refcounts == ++No errors were found on the image. ++ ++== writing some data == ++wrote 1/1 bytes at offset 0 ++1 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++== rechecking image refcounts == ++No errors were found on the image. ++ ++== writing some more data == ++wrote 1/1 bytes at offset 32768 ++1 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++== rechecking image refcounts == ++No errors were found on the image. ++*** done +diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group +index e47cbfc..9c565cf 100644 +--- a/tests/qemu-iotests/group ++++ b/tests/qemu-iotests/group +@@ -289,3 +289,4 @@ + 277 rw quick + 280 rw migration quick + 281 rw quick ++284 rw +-- +1.8.3.1 + diff --git a/SOURCES/kvm-block-backend-Add-flags-to-blk_truncate.patch b/SOURCES/kvm-block-backend-Add-flags-to-blk_truncate.patch new file mode 100644 index 0000000..5b212fc --- /dev/null +++ b/SOURCES/kvm-block-backend-Add-flags-to-blk_truncate.patch @@ -0,0 +1,294 @@ +From 07a93e74efa4861f54dd3d4bec01885f7af2fee3 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Mon, 8 Jun 2020 17:01:32 +0200 +Subject: [PATCH 04/17] block-backend: Add flags to blk_truncate() + +RH-Author: Kevin Wolf +Message-id: <20200608150140.38218-4-kwolf@redhat.com> +Patchwork-id: 97450 +O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH 03/11] block-backend: Add flags to blk_truncate() +Bugzilla: 1780574 +RH-Acked-by: Sergio Lopez Pascual +RH-Acked-by: Eric Blake +RH-Acked-by: Max Reitz + +Now that node level interface bdrv_truncate() supports passing request +flags to the block driver, expose this on the BlockBackend level, too. + +Signed-off-by: Kevin Wolf +Reviewed-by: Vladimir Sementsov-Ogievskiy +Reviewed-by: Alberto Garcia +Reviewed-by: Max Reitz +Message-Id: <20200424125448.63318-4-kwolf@redhat.com> +Signed-off-by: Kevin Wolf +(cherry picked from commit 8c6242b6f383e43fd11d2c50f8bcdd2bba1100fc) +Signed-off-by: Kevin Wolf +Signed-off-by: Danilo C. L. de Paula +--- + block.c | 3 ++- + block/block-backend.c | 4 ++-- + block/commit.c | 4 ++-- + block/crypto.c | 2 +- + block/mirror.c | 2 +- + block/qcow2.c | 4 ++-- + block/qed.c | 2 +- + block/vdi.c | 2 +- + block/vhdx.c | 4 ++-- + block/vmdk.c | 6 +++--- + block/vpc.c | 2 +- + blockdev.c | 2 +- + include/sysemu/block-backend.h | 2 +- + qemu-img.c | 2 +- + qemu-io-cmds.c | 2 +- + 15 files changed, 22 insertions(+), 21 deletions(-) + +diff --git a/block.c b/block.c +index d6a05da..12c8941 100644 +--- a/block.c ++++ b/block.c +@@ -547,7 +547,8 @@ static int64_t create_file_fallback_truncate(BlockBackend *blk, + int64_t size; + int ret; + +- ret = blk_truncate(blk, minimum_size, false, PREALLOC_MODE_OFF, &local_err); ++ ret = blk_truncate(blk, minimum_size, false, PREALLOC_MODE_OFF, 0, ++ &local_err); + if (ret < 0 && ret != -ENOTSUP) { + error_propagate(errp, local_err); + return ret; +diff --git a/block/block-backend.c b/block/block-backend.c +index 8be2006..17ed6d8 100644 +--- a/block/block-backend.c ++++ b/block/block-backend.c +@@ -2137,14 +2137,14 @@ int blk_pwrite_compressed(BlockBackend *blk, int64_t offset, const void *buf, + } + + int blk_truncate(BlockBackend *blk, int64_t offset, bool exact, +- PreallocMode prealloc, Error **errp) ++ PreallocMode prealloc, BdrvRequestFlags flags, Error **errp) + { + if (!blk_is_available(blk)) { + error_setg(errp, "No medium inserted"); + return -ENOMEDIUM; + } + +- return bdrv_truncate(blk->root, offset, exact, prealloc, 0, errp); ++ return bdrv_truncate(blk->root, offset, exact, prealloc, flags, errp); + } + + int blk_save_vmstate(BlockBackend *blk, const uint8_t *buf, +diff --git a/block/commit.c b/block/commit.c +index 23c90b3..075ebf8 100644 +--- a/block/commit.c ++++ b/block/commit.c +@@ -155,7 +155,7 @@ static int coroutine_fn commit_run(Job *job, Error **errp) + } + + if (base_len < len) { +- ret = blk_truncate(s->base, len, false, PREALLOC_MODE_OFF, NULL); ++ ret = blk_truncate(s->base, len, false, PREALLOC_MODE_OFF, 0, NULL); + if (ret) { + goto out; + } +@@ -471,7 +471,7 @@ int bdrv_commit(BlockDriverState *bs) + * grow the backing file image if possible. If not possible, + * we must return an error */ + if (length > backing_length) { +- ret = blk_truncate(backing, length, false, PREALLOC_MODE_OFF, ++ ret = blk_truncate(backing, length, false, PREALLOC_MODE_OFF, 0, + &local_err); + if (ret < 0) { + error_report_err(local_err); +diff --git a/block/crypto.c b/block/crypto.c +index fcb4a97..83a8fc0 100644 +--- a/block/crypto.c ++++ b/block/crypto.c +@@ -115,7 +115,7 @@ static ssize_t block_crypto_init_func(QCryptoBlock *block, + * which will be used by the crypto header + */ + return blk_truncate(data->blk, data->size + headerlen, false, +- data->prealloc, errp); ++ data->prealloc, 0, errp); + } + + +diff --git a/block/mirror.c b/block/mirror.c +index 0d32fca..c8028cd 100644 +--- a/block/mirror.c ++++ b/block/mirror.c +@@ -886,7 +886,7 @@ static int coroutine_fn mirror_run(Job *job, Error **errp) + if (s->base == blk_bs(s->target)) { + if (s->bdev_length > target_length) { + ret = blk_truncate(s->target, s->bdev_length, false, +- PREALLOC_MODE_OFF, NULL); ++ PREALLOC_MODE_OFF, 0, NULL); + if (ret < 0) { + goto immediate_exit; + } +diff --git a/block/qcow2.c b/block/qcow2.c +index c0fdcb9..86aa74a 100644 +--- a/block/qcow2.c ++++ b/block/qcow2.c +@@ -3497,7 +3497,7 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp) + + /* Okay, now that we have a valid image, let's give it the right size */ + ret = blk_truncate(blk, qcow2_opts->size, false, qcow2_opts->preallocation, +- errp); ++ 0, errp); + if (ret < 0) { + error_prepend(errp, "Could not resize image: "); + goto out; +@@ -5347,7 +5347,7 @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts, + * Amending image options should ensure that the image has + * exactly the given new values, so pass exact=true here. + */ +- ret = blk_truncate(blk, new_size, true, PREALLOC_MODE_OFF, errp); ++ ret = blk_truncate(blk, new_size, true, PREALLOC_MODE_OFF, 0, errp); + blk_unref(blk); + if (ret < 0) { + return ret; +diff --git a/block/qed.c b/block/qed.c +index fb6100b..b0fdb8f 100644 +--- a/block/qed.c ++++ b/block/qed.c +@@ -677,7 +677,7 @@ static int coroutine_fn bdrv_qed_co_create(BlockdevCreateOptions *opts, + * The QED format associates file length with allocation status, + * so a new file (which is empty) must have a length of 0. + */ +- ret = blk_truncate(blk, 0, true, PREALLOC_MODE_OFF, errp); ++ ret = blk_truncate(blk, 0, true, PREALLOC_MODE_OFF, 0, errp); + if (ret < 0) { + goto out; + } +diff --git a/block/vdi.c b/block/vdi.c +index e1a11f2..0c7835a 100644 +--- a/block/vdi.c ++++ b/block/vdi.c +@@ -875,7 +875,7 @@ static int coroutine_fn vdi_co_do_create(BlockdevCreateOptions *create_options, + + if (image_type == VDI_TYPE_STATIC) { + ret = blk_truncate(blk, offset + blocks * block_size, false, +- PREALLOC_MODE_OFF, errp); ++ PREALLOC_MODE_OFF, 0, errp); + if (ret < 0) { + error_prepend(errp, "Failed to statically allocate file"); + goto exit; +diff --git a/block/vhdx.c b/block/vhdx.c +index 5dfbb20..21497f7 100644 +--- a/block/vhdx.c ++++ b/block/vhdx.c +@@ -1703,13 +1703,13 @@ static int vhdx_create_bat(BlockBackend *blk, BDRVVHDXState *s, + /* All zeroes, so we can just extend the file - the end of the BAT + * is the furthest thing we have written yet */ + ret = blk_truncate(blk, data_file_offset, false, PREALLOC_MODE_OFF, +- errp); ++ 0, errp); + if (ret < 0) { + goto exit; + } + } else if (type == VHDX_TYPE_FIXED) { + ret = blk_truncate(blk, data_file_offset + image_size, false, +- PREALLOC_MODE_OFF, errp); ++ PREALLOC_MODE_OFF, 0, errp); + if (ret < 0) { + goto exit; + } +diff --git a/block/vmdk.c b/block/vmdk.c +index 1bbf937..1bd3991 100644 +--- a/block/vmdk.c ++++ b/block/vmdk.c +@@ -2118,7 +2118,7 @@ static int vmdk_init_extent(BlockBackend *blk, + int gd_buf_size; + + if (flat) { +- ret = blk_truncate(blk, filesize, false, PREALLOC_MODE_OFF, errp); ++ ret = blk_truncate(blk, filesize, false, PREALLOC_MODE_OFF, 0, errp); + goto exit; + } + magic = cpu_to_be32(VMDK4_MAGIC); +@@ -2182,7 +2182,7 @@ static int vmdk_init_extent(BlockBackend *blk, + } + + ret = blk_truncate(blk, le64_to_cpu(header.grain_offset) << 9, false, +- PREALLOC_MODE_OFF, errp); ++ PREALLOC_MODE_OFF, 0, errp); + if (ret < 0) { + goto exit; + } +@@ -2523,7 +2523,7 @@ static int coroutine_fn vmdk_co_do_create(int64_t size, + /* bdrv_pwrite write padding zeros to align to sector, we don't need that + * for description file */ + if (desc_offset == 0) { +- ret = blk_truncate(blk, desc_len, false, PREALLOC_MODE_OFF, errp); ++ ret = blk_truncate(blk, desc_len, false, PREALLOC_MODE_OFF, 0, errp); + if (ret < 0) { + goto exit; + } +diff --git a/block/vpc.c b/block/vpc.c +index 6df75e2..d5e7dc8 100644 +--- a/block/vpc.c ++++ b/block/vpc.c +@@ -898,7 +898,7 @@ static int create_fixed_disk(BlockBackend *blk, uint8_t *buf, + /* Add footer to total size */ + total_size += HEADER_SIZE; + +- ret = blk_truncate(blk, total_size, false, PREALLOC_MODE_OFF, errp); ++ ret = blk_truncate(blk, total_size, false, PREALLOC_MODE_OFF, 0, errp); + if (ret < 0) { + return ret; + } +diff --git a/blockdev.c b/blockdev.c +index 5128c9b..6dde52a 100644 +--- a/blockdev.c ++++ b/blockdev.c +@@ -3055,7 +3055,7 @@ void qmp_block_resize(bool has_device, const char *device, + } + + bdrv_drained_begin(bs); +- ret = blk_truncate(blk, size, false, PREALLOC_MODE_OFF, errp); ++ ret = blk_truncate(blk, size, false, PREALLOC_MODE_OFF, 0, errp); + bdrv_drained_end(bs); + + out: +diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h +index 9bbdbd6..34de7fa 100644 +--- a/include/sysemu/block-backend.h ++++ b/include/sysemu/block-backend.h +@@ -237,7 +237,7 @@ int coroutine_fn blk_co_pwrite_zeroes(BlockBackend *blk, int64_t offset, + int blk_pwrite_compressed(BlockBackend *blk, int64_t offset, const void *buf, + int bytes); + int blk_truncate(BlockBackend *blk, int64_t offset, bool exact, +- PreallocMode prealloc, Error **errp); ++ PreallocMode prealloc, BdrvRequestFlags flags, Error **errp); + int blk_pdiscard(BlockBackend *blk, int64_t offset, int bytes); + int blk_save_vmstate(BlockBackend *blk, const uint8_t *buf, + int64_t pos, int size); +diff --git a/qemu-img.c b/qemu-img.c +index 6dc881b..a27ad70 100644 +--- a/qemu-img.c ++++ b/qemu-img.c +@@ -3939,7 +3939,7 @@ static int img_resize(int argc, char **argv) + * resizing, so pass @exact=true. It is of no use to report + * success when the image has not actually been resized. + */ +- ret = blk_truncate(blk, total_size, true, prealloc, &err); ++ ret = blk_truncate(blk, total_size, true, prealloc, 0, &err); + if (!ret) { + qprintf(quiet, "Image resized.\n"); + } else { +diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c +index 1b7e700..851f07e 100644 +--- a/qemu-io-cmds.c ++++ b/qemu-io-cmds.c +@@ -1715,7 +1715,7 @@ static int truncate_f(BlockBackend *blk, int argc, char **argv) + * exact=true. It is better to err on the "emit more errors" side + * than to be overly permissive. + */ +- ret = blk_truncate(blk, offset, true, PREALLOC_MODE_OFF, &local_err); ++ ret = blk_truncate(blk, offset, true, PREALLOC_MODE_OFF, 0, &local_err); + if (ret < 0) { + error_report_err(local_err); + return ret; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-block-curl-HTTP-header-field-names-are-case-insensit.patch b/SOURCES/kvm-block-curl-HTTP-header-field-names-are-case-insensit.patch new file mode 100644 index 0000000..a974a18 --- /dev/null +++ b/SOURCES/kvm-block-curl-HTTP-header-field-names-are-case-insensit.patch @@ -0,0 +1,55 @@ +From 5e5ca17e1e09cfe9a780c556528bbde23c93fc4e Mon Sep 17 00:00:00 2001 +From: Richard Jones +Date: Thu, 28 May 2020 14:27:37 +0100 +Subject: [PATCH 03/26] block/curl: HTTP header field names are case + insensitive +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Richard Jones +Message-id: <20200528142737.17318-3-rjones@redhat.com> +Patchwork-id: 96895 +O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH 2/2] block/curl: HTTP header field names are case insensitive +Bugzilla: 1841038 +RH-Acked-by: Eric Blake +RH-Acked-by: Max Reitz +RH-Acked-by: Philippe Mathieu-Daudé + +From: David Edmondson + +RFC 7230 section 3.2 indicates that HTTP header field names are case +insensitive. + +Signed-off-by: David Edmondson +Message-Id: <20200224101310.101169-3-david.edmondson@oracle.com> +Reviewed-by: Max Reitz +Signed-off-by: Max Reitz +(cherry picked from commit 69032253c33ae1774233c63cedf36d32242a85fc) +Signed-off-by: Danilo C. L. de Paula +--- + block/curl.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/block/curl.c b/block/curl.c +index f9ffb7f..6e32590 100644 +--- a/block/curl.c ++++ b/block/curl.c +@@ -216,11 +216,12 @@ static size_t curl_header_cb(void *ptr, size_t size, size_t nmemb, void *opaque) + size_t realsize = size * nmemb; + const char *header = (char *)ptr; + const char *end = header + realsize; +- const char *accept_ranges = "Accept-Ranges:"; ++ const char *accept_ranges = "accept-ranges:"; + const char *bytes = "bytes"; + + if (realsize >= strlen(accept_ranges) +- && strncmp(header, accept_ranges, strlen(accept_ranges)) == 0) { ++ && g_ascii_strncasecmp(header, accept_ranges, ++ strlen(accept_ranges)) == 0) { + + char *p = strchr(header, ':') + 1; + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-block-curl-HTTP-header-fields-allow-whitespace-aroun.patch b/SOURCES/kvm-block-curl-HTTP-header-fields-allow-whitespace-aroun.patch new file mode 100644 index 0000000..c09a1e2 --- /dev/null +++ b/SOURCES/kvm-block-curl-HTTP-header-fields-allow-whitespace-aroun.patch @@ -0,0 +1,76 @@ +From e5ac775de83d3d22f13c74ab198780b8b579f684 Mon Sep 17 00:00:00 2001 +From: Richard Jones +Date: Thu, 28 May 2020 14:27:36 +0100 +Subject: [PATCH 02/26] block/curl: HTTP header fields allow whitespace around + values + +RH-Author: Richard Jones +Message-id: <20200528142737.17318-2-rjones@redhat.com> +Patchwork-id: 96894 +O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH 1/2] block/curl: HTTP header fields allow whitespace around values +Bugzilla: 1841038 +RH-Acked-by: Eric Blake +RH-Acked-by: Max Reitz +RH-Acked-by: Danilo de Paula + +From: David Edmondson + +RFC 7230 section 3.2 indicates that whitespace is permitted between +the field name and field value and after the field value. + +Signed-off-by: David Edmondson +Message-Id: <20200224101310.101169-2-david.edmondson@oracle.com> +Reviewed-by: Max Reitz +Signed-off-by: Max Reitz +(cherry picked from commit 7788a319399f17476ff1dd43164c869e320820a2) +Signed-off-by: Danilo C. L. de Paula +--- + block/curl.c | 31 +++++++++++++++++++++++++++---- + 1 file changed, 27 insertions(+), 4 deletions(-) + +diff --git a/block/curl.c b/block/curl.c +index f862993..f9ffb7f 100644 +--- a/block/curl.c ++++ b/block/curl.c +@@ -214,11 +214,34 @@ static size_t curl_header_cb(void *ptr, size_t size, size_t nmemb, void *opaque) + { + BDRVCURLState *s = opaque; + size_t realsize = size * nmemb; +- const char *accept_line = "Accept-Ranges: bytes"; ++ const char *header = (char *)ptr; ++ const char *end = header + realsize; ++ const char *accept_ranges = "Accept-Ranges:"; ++ const char *bytes = "bytes"; + +- if (realsize >= strlen(accept_line) +- && strncmp((char *)ptr, accept_line, strlen(accept_line)) == 0) { +- s->accept_range = true; ++ if (realsize >= strlen(accept_ranges) ++ && strncmp(header, accept_ranges, strlen(accept_ranges)) == 0) { ++ ++ char *p = strchr(header, ':') + 1; ++ ++ /* Skip whitespace between the header name and value. */ ++ while (p < end && *p && g_ascii_isspace(*p)) { ++ p++; ++ } ++ ++ if (end - p >= strlen(bytes) ++ && strncmp(p, bytes, strlen(bytes)) == 0) { ++ ++ /* Check that there is nothing but whitespace after the value. */ ++ p += strlen(bytes); ++ while (p < end && *p && g_ascii_isspace(*p)) { ++ p++; ++ } ++ ++ if (p == end || !*p) { ++ s->accept_range = true; ++ } ++ } + } + + return realsize; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-block-introducing-bdrv_co_delete_file-interface.patch b/SOURCES/kvm-block-introducing-bdrv_co_delete_file-interface.patch new file mode 100644 index 0000000..9d5e659 --- /dev/null +++ b/SOURCES/kvm-block-introducing-bdrv_co_delete_file-interface.patch @@ -0,0 +1,99 @@ +From 9581770f48911cbe68cfa1a7fa125df2a0a27d02 Mon Sep 17 00:00:00 2001 +From: Maxim Levitsky +Date: Sun, 31 May 2020 16:40:33 +0100 +Subject: [PATCH 5/7] block: introducing 'bdrv_co_delete_file' interface +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Maxim Levitsky +Message-id: <20200531164035.34188-2-mlevitsk@redhat.com> +Patchwork-id: 97057 +O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH 1/3] block: introducing 'bdrv_co_delete_file' interface +Bugzilla: 1827630 +RH-Acked-by: Sergio Lopez Pascual +RH-Acked-by: John Snow +RH-Acked-by: Eric Blake + +From: Daniel Henrique Barboza + +Adding to Block Drivers the capability of being able to clean up +its created files can be useful in certain situations. For the +LUKS driver, for instance, a failure in one of its authentication +steps can leave files in the host that weren't there before. + +This patch adds the 'bdrv_co_delete_file' interface to block +drivers and add it to the 'file' driver in file-posix.c. The +implementation is given by 'raw_co_delete_file'. + +Suggested-by: Daniel P. Berrangé +Signed-off-by: Daniel Henrique Barboza +Message-Id: <20200130213907.2830642-2-danielhb413@gmail.com> +Signed-off-by: Kevin Wolf +(cherry picked from commit 9bffae14df879255329473a7bd578643af2d4c9c) +Signed-off-by: Maxim Levitsky +Signed-off-by: Danilo C. L. de Paula +--- + block/file-posix.c | 23 +++++++++++++++++++++++ + include/block/block_int.h | 4 ++++ + 2 files changed, 27 insertions(+) + +diff --git a/block/file-posix.c b/block/file-posix.c +index dd18d40..1609598 100644 +--- a/block/file-posix.c ++++ b/block/file-posix.c +@@ -2388,6 +2388,28 @@ static int coroutine_fn raw_co_create_opts(BlockDriver *drv, + return raw_co_create(&options, errp); + } + ++static int coroutine_fn raw_co_delete_file(BlockDriverState *bs, ++ Error **errp) ++{ ++ struct stat st; ++ int ret; ++ ++ if (!(stat(bs->filename, &st) == 0) || !S_ISREG(st.st_mode)) { ++ error_setg_errno(errp, ENOENT, "%s is not a regular file", ++ bs->filename); ++ return -ENOENT; ++ } ++ ++ ret = unlink(bs->filename); ++ if (ret < 0) { ++ ret = -errno; ++ error_setg_errno(errp, -ret, "Error when deleting file %s", ++ bs->filename); ++ } ++ ++ return ret; ++} ++ + /* + * Find allocation range in @bs around offset @start. + * May change underlying file descriptor's file offset. +@@ -3019,6 +3041,7 @@ BlockDriver bdrv_file = { + .bdrv_co_block_status = raw_co_block_status, + .bdrv_co_invalidate_cache = raw_co_invalidate_cache, + .bdrv_co_pwrite_zeroes = raw_co_pwrite_zeroes, ++ .bdrv_co_delete_file = raw_co_delete_file, + + .bdrv_co_preadv = raw_co_preadv, + .bdrv_co_pwritev = raw_co_pwritev, +diff --git a/include/block/block_int.h b/include/block/block_int.h +index 529f153..562dca1 100644 +--- a/include/block/block_int.h ++++ b/include/block/block_int.h +@@ -316,6 +316,10 @@ struct BlockDriver { + */ + int coroutine_fn (*bdrv_co_flush)(BlockDriverState *bs); + ++ /* Delete a created file. */ ++ int coroutine_fn (*bdrv_co_delete_file)(BlockDriverState *bs, ++ Error **errp); ++ + /* + * Flushes all data that was already written to the OS all the way down to + * the disk (for example file-posix.c calls fsync()). +-- +1.8.3.1 + diff --git a/SOURCES/kvm-block-truncate-Don-t-make-backing-file-data-visible.patch b/SOURCES/kvm-block-truncate-Don-t-make-backing-file-data-visible.patch new file mode 100644 index 0000000..114e1b7 --- /dev/null +++ b/SOURCES/kvm-block-truncate-Don-t-make-backing-file-data-visible.patch @@ -0,0 +1,94 @@ +From d84b9b93755ece6618ed98fa84386beeb1a0e40b Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Mon, 8 Jun 2020 15:01:36 +0100 +Subject: [PATCH 08/17] block: truncate: Don't make backing file data visible + +RH-Author: Kevin Wolf +Message-id: <20200608150140.38218-8-kwolf@redhat.com> +Patchwork-id: 97454 +O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH 07/11] block: truncate: Don't make backing file data visible +Bugzilla: 1780574 +RH-Acked-by: Sergio Lopez Pascual +RH-Acked-by: Eric Blake +RH-Acked-by: Max Reitz + +When extending the size of an image that has a backing file larger than +its old size, make sure that the backing file data doesn't become +visible in the guest, but the added area is properly zeroed out. + +Consider the following scenario where the overlay is shorter than its +backing file: + + base.qcow2: AAAAAAAA + overlay.qcow2: BBBB + +When resizing (extending) overlay.qcow2, the new blocks should not stay +unallocated and make the additional As from base.qcow2 visible like +before this patch, but zeros should be read. + +A similar case happens with the various variants of a commit job when an +intermediate file is short (- for unallocated): + + base.qcow2: A-A-AAAA + mid.qcow2: BB-B + top.qcow2: C--C--C- + +After commit top.qcow2 to mid.qcow2, the following happens: + + mid.qcow2: CB-C00C0 (correct result) + mid.qcow2: CB-C--C- (before this fix) + +Without the fix, blocks that previously read as zeros on top.qcow2 +suddenly turn into A. + +Signed-off-by: Kevin Wolf +Reviewed-by: Vladimir Sementsov-Ogievskiy +Message-Id: <20200424125448.63318-8-kwolf@redhat.com> +Reviewed-by: Max Reitz +Signed-off-by: Kevin Wolf +(cherry picked from commit 955c7d6687fefcd903900a1e597fcbc896c661cd) +Signed-off-by: Kevin Wolf +Signed-off-by: Danilo C. L. de Paula +--- + block/io.c | 25 +++++++++++++++++++++++++ + 1 file changed, 25 insertions(+) + +diff --git a/block/io.c b/block/io.c +index 3235ce5..6c70b56 100644 +--- a/block/io.c ++++ b/block/io.c +@@ -3370,6 +3370,31 @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact, + goto out; + } + ++ /* ++ * If the image has a backing file that is large enough that it would ++ * provide data for the new area, we cannot leave it unallocated because ++ * then the backing file content would become visible. Instead, zero-fill ++ * the new area. ++ * ++ * Note that if the image has a backing file, but was opened without the ++ * backing file, taking care of keeping things consistent with that backing ++ * file is the user's responsibility. ++ */ ++ if (new_bytes && bs->backing) { ++ int64_t backing_len; ++ ++ backing_len = bdrv_getlength(backing_bs(bs)); ++ if (backing_len < 0) { ++ ret = backing_len; ++ error_setg_errno(errp, -ret, "Could not get backing file size"); ++ goto out; ++ } ++ ++ if (backing_len > old_size) { ++ flags |= BDRV_REQ_ZERO_WRITE; ++ } ++ } ++ + if (drv->bdrv_co_truncate) { + if (flags & ~bs->supported_truncate_flags) { + error_setg(errp, "Block driver does not support requested flags"); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-block.c-adding-bdrv_co_delete_file.patch b/SOURCES/kvm-block.c-adding-bdrv_co_delete_file.patch new file mode 100644 index 0000000..91c3cd1 --- /dev/null +++ b/SOURCES/kvm-block.c-adding-bdrv_co_delete_file.patch @@ -0,0 +1,92 @@ +From 23b92512d7f11b3a38cf24a5c2fe7848f1e550e8 Mon Sep 17 00:00:00 2001 +From: Maxim Levitsky +Date: Sun, 31 May 2020 16:40:34 +0100 +Subject: [PATCH 6/7] block.c: adding bdrv_co_delete_file +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Maxim Levitsky +Message-id: <20200531164035.34188-3-mlevitsk@redhat.com> +Patchwork-id: 97058 +O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH 2/3] block.c: adding bdrv_co_delete_file +Bugzilla: 1827630 +RH-Acked-by: Sergio Lopez Pascual +RH-Acked-by: John Snow +RH-Acked-by: Eric Blake + +From: Daniel Henrique Barboza + +Using the new 'bdrv_co_delete_file' interface, a pure co_routine function +'bdrv_co_delete_file' inside block.c can can be used in a way similar of +the existing bdrv_create_file to to clean up a created file. + +We're creating a pure co_routine because the only caller of +'bdrv_co_delete_file' will be already in co_routine context, thus there +is no need to add all the machinery to check for qemu_in_coroutine() and +create a separated co_routine to do the job. + +Suggested-by: Daniel P. Berrangé +Signed-off-by: Daniel Henrique Barboza +Message-Id: <20200130213907.2830642-3-danielhb413@gmail.com> +Signed-off-by: Kevin Wolf +(cherry picked from commit e1d7f8bb1ec0c6911dcea81641ce6139dbded02d) +Signed-off-by: Maxim Levitsky +Signed-off-by: Danilo C. L. de Paula +--- + block.c | 26 ++++++++++++++++++++++++++ + include/block/block.h | 1 + + 2 files changed, 27 insertions(+) + +diff --git a/block.c b/block.c +index ba3b40d7..d6a05da 100644 +--- a/block.c ++++ b/block.c +@@ -672,6 +672,32 @@ int bdrv_create_file(const char *filename, QemuOpts *opts, Error **errp) + return bdrv_create(drv, filename, opts, errp); + } + ++int coroutine_fn bdrv_co_delete_file(BlockDriverState *bs, Error **errp) ++{ ++ Error *local_err = NULL; ++ int ret; ++ ++ assert(bs != NULL); ++ ++ if (!bs->drv) { ++ error_setg(errp, "Block node '%s' is not opened", bs->filename); ++ return -ENOMEDIUM; ++ } ++ ++ if (!bs->drv->bdrv_co_delete_file) { ++ error_setg(errp, "Driver '%s' does not support image deletion", ++ bs->drv->format_name); ++ return -ENOTSUP; ++ } ++ ++ ret = bs->drv->bdrv_co_delete_file(bs, &local_err); ++ if (ret < 0) { ++ error_propagate(errp, local_err); ++ } ++ ++ return ret; ++} ++ + /** + * Try to get @bs's logical and physical block size. + * On success, store them in @bsz struct and return 0. +diff --git a/include/block/block.h b/include/block/block.h +index 92685d2..b2a3074 100644 +--- a/include/block/block.h ++++ b/include/block/block.h +@@ -373,6 +373,7 @@ bool bdrv_is_backing_chain_frozen(BlockDriverState *bs, BlockDriverState *base, + int bdrv_freeze_backing_chain(BlockDriverState *bs, BlockDriverState *base, + Error **errp); + void bdrv_unfreeze_backing_chain(BlockDriverState *bs, BlockDriverState *base); ++int coroutine_fn bdrv_co_delete_file(BlockDriverState *bs, Error **errp); + + + typedef struct BdrvCheckResult { +-- +1.8.3.1 + diff --git a/SOURCES/kvm-blockdev-Promote-several-bitmap-functions-to-non-sta.patch b/SOURCES/kvm-blockdev-Promote-several-bitmap-functions-to-non-sta.patch new file mode 100644 index 0000000..8cb1700 --- /dev/null +++ b/SOURCES/kvm-blockdev-Promote-several-bitmap-functions-to-non-sta.patch @@ -0,0 +1,179 @@ +From 0c8ba0a96a7d0cbf371f1a5fbee543e8b2cb2595 Mon Sep 17 00:00:00 2001 +From: Eric Blake +Date: Tue, 2 Jun 2020 02:34:13 +0100 +Subject: [PATCH 08/26] blockdev: Promote several bitmap functions to + non-static +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Eric Blake +Message-id: <20200602023420.2133649-6-eblake@redhat.com> +Patchwork-id: 97077 +O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH 05/12] blockdev: Promote several bitmap functions to non-static +Bugzilla: 1779893 1779904 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Max Reitz +RH-Acked-by: Kevin Wolf + +The next patch will split blockdev.c, which will require accessing +some previously-static functions from more than one .c file. But part +of promoting a function to public is picking a naming scheme that does +not reek of exposing too many internals (two of the three functions +were named starting with 'do_'). To make future code motion easier, +perform the function rename and non-static promotion into its own +patch. + +Signed-off-by: Eric Blake +Reviewed-by: Max Reitz +Message-Id: <20200513011648.166876-5-eblake@redhat.com> +Reviewed-by: Vladimir Sementsov-Ogievskiy +(cherry picked from commit c6996cf9a6c759c29919642be9a73ac64b38301b) +Signed-off-by: Eric Blake +Signed-off-by: Danilo C. L. de Paula +--- + blockdev.c | 47 +++++++++++++++++++---------------------------- + include/block/block_int.h | 12 ++++++++++++ + 2 files changed, 31 insertions(+), 28 deletions(-) + +diff --git a/blockdev.c b/blockdev.c +index 86eb115..3958058 100644 +--- a/blockdev.c ++++ b/blockdev.c +@@ -1262,10 +1262,10 @@ out_aio_context: + * + * @return: A bitmap object on success, or NULL on failure. + */ +-static BdrvDirtyBitmap *block_dirty_bitmap_lookup(const char *node, +- const char *name, +- BlockDriverState **pbs, +- Error **errp) ++BdrvDirtyBitmap *block_dirty_bitmap_lookup(const char *node, ++ const char *name, ++ BlockDriverState **pbs, ++ Error **errp) + { + BlockDriverState *bs; + BdrvDirtyBitmap *bitmap; +@@ -2241,11 +2241,6 @@ static void block_dirty_bitmap_disable_abort(BlkActionState *common) + } + } + +-static BdrvDirtyBitmap *do_block_dirty_bitmap_merge( +- const char *node, const char *target, +- BlockDirtyBitmapMergeSourceList *bitmaps, +- HBitmap **backup, Error **errp); +- + static void block_dirty_bitmap_merge_prepare(BlkActionState *common, + Error **errp) + { +@@ -2259,15 +2254,11 @@ static void block_dirty_bitmap_merge_prepare(BlkActionState *common, + + action = common->action->u.block_dirty_bitmap_merge.data; + +- state->bitmap = do_block_dirty_bitmap_merge(action->node, action->target, +- action->bitmaps, &state->backup, +- errp); ++ state->bitmap = block_dirty_bitmap_merge(action->node, action->target, ++ action->bitmaps, &state->backup, ++ errp); + } + +-static BdrvDirtyBitmap *do_block_dirty_bitmap_remove( +- const char *node, const char *name, bool release, +- BlockDriverState **bitmap_bs, Error **errp); +- + static void block_dirty_bitmap_remove_prepare(BlkActionState *common, + Error **errp) + { +@@ -2281,8 +2272,8 @@ static void block_dirty_bitmap_remove_prepare(BlkActionState *common, + + action = common->action->u.block_dirty_bitmap_remove.data; + +- state->bitmap = do_block_dirty_bitmap_remove(action->node, action->name, +- false, &state->bs, errp); ++ state->bitmap = block_dirty_bitmap_remove(action->node, action->name, ++ false, &state->bs, errp); + if (state->bitmap) { + bdrv_dirty_bitmap_skip_store(state->bitmap, true); + bdrv_dirty_bitmap_set_busy(state->bitmap, true); +@@ -3046,9 +3037,10 @@ out: + aio_context_release(aio_context); + } + +-static BdrvDirtyBitmap *do_block_dirty_bitmap_remove( +- const char *node, const char *name, bool release, +- BlockDriverState **bitmap_bs, Error **errp) ++BdrvDirtyBitmap *block_dirty_bitmap_remove(const char *node, const char *name, ++ bool release, ++ BlockDriverState **bitmap_bs, ++ Error **errp) + { + BlockDriverState *bs; + BdrvDirtyBitmap *bitmap; +@@ -3090,7 +3082,7 @@ static BdrvDirtyBitmap *do_block_dirty_bitmap_remove( + void qmp_block_dirty_bitmap_remove(const char *node, const char *name, + Error **errp) + { +- do_block_dirty_bitmap_remove(node, name, true, NULL, errp); ++ block_dirty_bitmap_remove(node, name, true, NULL, errp); + } + + /** +@@ -3151,10 +3143,9 @@ void qmp_block_dirty_bitmap_disable(const char *node, const char *name, + bdrv_disable_dirty_bitmap(bitmap); + } + +-static BdrvDirtyBitmap *do_block_dirty_bitmap_merge( +- const char *node, const char *target, +- BlockDirtyBitmapMergeSourceList *bitmaps, +- HBitmap **backup, Error **errp) ++BdrvDirtyBitmap *block_dirty_bitmap_merge(const char *node, const char *target, ++ BlockDirtyBitmapMergeSourceList *bms, ++ HBitmap **backup, Error **errp) + { + BlockDriverState *bs; + BdrvDirtyBitmap *dst, *src, *anon; +@@ -3172,7 +3163,7 @@ static BdrvDirtyBitmap *do_block_dirty_bitmap_merge( + return NULL; + } + +- for (lst = bitmaps; lst; lst = lst->next) { ++ for (lst = bms; lst; lst = lst->next) { + switch (lst->value->type) { + const char *name, *node; + case QTYPE_QSTRING: +@@ -3217,7 +3208,7 @@ void qmp_block_dirty_bitmap_merge(const char *node, const char *target, + BlockDirtyBitmapMergeSourceList *bitmaps, + Error **errp) + { +- do_block_dirty_bitmap_merge(node, target, bitmaps, NULL, errp); ++ block_dirty_bitmap_merge(node, target, bitmaps, NULL, errp); + } + + BlockDirtyBitmapSha256 *qmp_x_debug_block_dirty_bitmap_sha256(const char *node, +diff --git a/include/block/block_int.h b/include/block/block_int.h +index cc18e8d..876a83d 100644 +--- a/include/block/block_int.h ++++ b/include/block/block_int.h +@@ -1341,4 +1341,16 @@ int coroutine_fn bdrv_co_create_opts_simple(BlockDriver *drv, + Error **errp); + extern QemuOptsList bdrv_create_opts_simple; + ++BdrvDirtyBitmap *block_dirty_bitmap_lookup(const char *node, ++ const char *name, ++ BlockDriverState **pbs, ++ Error **errp); ++BdrvDirtyBitmap *block_dirty_bitmap_merge(const char *node, const char *target, ++ BlockDirtyBitmapMergeSourceList *bms, ++ HBitmap **backup, Error **errp); ++BdrvDirtyBitmap *block_dirty_bitmap_remove(const char *node, const char *name, ++ bool release, ++ BlockDriverState **bitmap_bs, ++ Error **errp); ++ + #endif /* BLOCK_INT_H */ +-- +1.8.3.1 + diff --git a/SOURCES/kvm-blockdev-Split-off-basic-bitmap-operations-for-qemu-.patch b/SOURCES/kvm-blockdev-Split-off-basic-bitmap-operations-for-qemu-.patch new file mode 100644 index 0000000..d977922 --- /dev/null +++ b/SOURCES/kvm-blockdev-Split-off-basic-bitmap-operations-for-qemu-.patch @@ -0,0 +1,720 @@ +From 2afa718d59ef86879a9e34b4601a1f2658afa9ba Mon Sep 17 00:00:00 2001 +From: Eric Blake +Date: Tue, 2 Jun 2020 02:34:14 +0100 +Subject: [PATCH 09/26] blockdev: Split off basic bitmap operations for + qemu-img + +RH-Author: Eric Blake +Message-id: <20200602023420.2133649-7-eblake@redhat.com> +Patchwork-id: 97073 +O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH 06/12] blockdev: Split off basic bitmap operations for qemu-img +Bugzilla: 1779893 1779904 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Max Reitz +RH-Acked-by: Kevin Wolf + +Upcoming patches want to add some basic bitmap manipulation abilities +to qemu-img. But blockdev.o is too heavyweight to link into qemu-img +(among other things, it would drag in block jobs and transaction +support - qemu-img does offline manipulation, where atomicity is less +important because there are no concurrent modifications to compete +with), so it's time to split off the bare bones of what we will need +into a new file block/monitor/bitmap-qmp-cmds.o. + +This is sufficient to expose 6 QMP commands for use by qemu-img (add, +remove, clear, enable, disable, merge), as well as move the three +helper functions touched in the previous patch. Regarding +MAINTAINERS, the new file is automatically part of block core, but +also makes sense as related to other dirty bitmap files. + +Signed-off-by: Eric Blake +Reviewed-by: Max Reitz +Message-Id: <20200513011648.166876-6-eblake@redhat.com> +Reviewed-by: Vladimir Sementsov-Ogievskiy +(cherry picked from commit bb4e58c6137e80129b955789dd4b66c1504f20dc) + +Signed-off-by: Danilo C. L. de Paula + +Conflicts: + Makefile.objs - comment context + block/monitor/Makefile.objs - context: a2dde2f2 not backported + blockdev.c - context +Signed-off-by: Eric Blake + +Signed-off-by: Danilo C. L. de Paula +--- + MAINTAINERS | 1 + + Makefile.objs | 3 +- + block/monitor/Makefile.objs | 1 + + block/monitor/bitmap-qmp-cmds.c | 321 ++++++++++++++++++++++++++++++++++++++++ + blockdev.c | 284 ----------------------------------- + 5 files changed, 324 insertions(+), 286 deletions(-) + create mode 100644 block/monitor/Makefile.objs + create mode 100644 block/monitor/bitmap-qmp-cmds.c + +diff --git a/MAINTAINERS b/MAINTAINERS +index 3a81ac9..49d5d44 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -1875,6 +1875,7 @@ L: qemu-block@nongnu.org + S: Supported + F: include/qemu/hbitmap.h + F: include/block/dirty-bitmap.h ++F: block/monitor/bitmap-qmp-cmds.c + F: block/dirty-bitmap.c + F: block/qcow2-bitmap.c + F: migration/block-dirty-bitmap.c +diff --git a/Makefile.objs b/Makefile.objs +index 1a8f288..7404ef0 100644 +--- a/Makefile.objs ++++ b/Makefile.objs +@@ -13,9 +13,8 @@ authz-obj-y = authz/ + ####################################################################### + # block-obj-y is code used by both qemu system emulation and qemu-img + +-block-obj-y = nbd/ ++block-obj-y = block/ block/monitor/ nbd/ scsi/ + block-obj-y += block.o blockjob.o job.o +-block-obj-y += block/ scsi/ + block-obj-y += qemu-io-cmds.o + block-obj-$(CONFIG_REPLICATION) += replication.o + +diff --git a/block/monitor/Makefile.objs b/block/monitor/Makefile.objs +new file mode 100644 +index 0000000..f0c7642 +--- /dev/null ++++ b/block/monitor/Makefile.objs +@@ -0,0 +1 @@ ++block-obj-y += bitmap-qmp-cmds.o +diff --git a/block/monitor/bitmap-qmp-cmds.c b/block/monitor/bitmap-qmp-cmds.c +new file mode 100644 +index 0000000..9f11dee +--- /dev/null ++++ b/block/monitor/bitmap-qmp-cmds.c +@@ -0,0 +1,321 @@ ++/* ++ * QEMU block dirty bitmap QMP commands ++ * ++ * Copyright (c) 2003-2008 Fabrice Bellard ++ * ++ * This work is licensed under the terms of the GNU GPL, version 2 or ++ * later. See the COPYING file in the top-level directory. ++ * ++ * This file incorporates work covered by the following copyright and ++ * permission notice: ++ * ++ * Copyright (c) 2003-2008 Fabrice Bellard ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ++ * THE SOFTWARE. ++ */ ++ ++#include "qemu/osdep.h" ++ ++#include "block/block_int.h" ++#include "qapi/qapi-commands-block.h" ++#include "qapi/error.h" ++ ++/** ++ * block_dirty_bitmap_lookup: ++ * Return a dirty bitmap (if present), after validating ++ * the node reference and bitmap names. ++ * ++ * @node: The name of the BDS node to search for bitmaps ++ * @name: The name of the bitmap to search for ++ * @pbs: Output pointer for BDS lookup, if desired. Can be NULL. ++ * @errp: Output pointer for error information. Can be NULL. ++ * ++ * @return: A bitmap object on success, or NULL on failure. ++ */ ++BdrvDirtyBitmap *block_dirty_bitmap_lookup(const char *node, ++ const char *name, ++ BlockDriverState **pbs, ++ Error **errp) ++{ ++ BlockDriverState *bs; ++ BdrvDirtyBitmap *bitmap; ++ ++ if (!node) { ++ error_setg(errp, "Node cannot be NULL"); ++ return NULL; ++ } ++ if (!name) { ++ error_setg(errp, "Bitmap name cannot be NULL"); ++ return NULL; ++ } ++ bs = bdrv_lookup_bs(node, node, NULL); ++ if (!bs) { ++ error_setg(errp, "Node '%s' not found", node); ++ return NULL; ++ } ++ ++ bitmap = bdrv_find_dirty_bitmap(bs, name); ++ if (!bitmap) { ++ error_setg(errp, "Dirty bitmap '%s' not found", name); ++ return NULL; ++ } ++ ++ if (pbs) { ++ *pbs = bs; ++ } ++ ++ return bitmap; ++} ++ ++void qmp_block_dirty_bitmap_add(const char *node, const char *name, ++ bool has_granularity, uint32_t granularity, ++ bool has_persistent, bool persistent, ++ bool has_disabled, bool disabled, ++ Error **errp) ++{ ++ BlockDriverState *bs; ++ BdrvDirtyBitmap *bitmap; ++ AioContext *aio_context; ++ ++ if (!name || name[0] == '\0') { ++ error_setg(errp, "Bitmap name cannot be empty"); ++ return; ++ } ++ ++ bs = bdrv_lookup_bs(node, node, errp); ++ if (!bs) { ++ return; ++ } ++ ++ aio_context = bdrv_get_aio_context(bs); ++ aio_context_acquire(aio_context); ++ ++ if (has_granularity) { ++ if (granularity < 512 || !is_power_of_2(granularity)) { ++ error_setg(errp, "Granularity must be power of 2 " ++ "and at least 512"); ++ goto out; ++ } ++ } else { ++ /* Default to cluster size, if available: */ ++ granularity = bdrv_get_default_bitmap_granularity(bs); ++ } ++ ++ if (!has_persistent) { ++ persistent = false; ++ } ++ ++ if (!has_disabled) { ++ disabled = false; ++ } ++ ++ if (persistent && ++ !bdrv_can_store_new_dirty_bitmap(bs, name, granularity, errp)) ++ { ++ goto out; ++ } ++ ++ bitmap = bdrv_create_dirty_bitmap(bs, granularity, name, errp); ++ if (bitmap == NULL) { ++ goto out; ++ } ++ ++ if (disabled) { ++ bdrv_disable_dirty_bitmap(bitmap); ++ } ++ ++ bdrv_dirty_bitmap_set_persistence(bitmap, persistent); ++ ++out: ++ aio_context_release(aio_context); ++} ++ ++BdrvDirtyBitmap *block_dirty_bitmap_remove(const char *node, const char *name, ++ bool release, ++ BlockDriverState **bitmap_bs, ++ Error **errp) ++{ ++ BlockDriverState *bs; ++ BdrvDirtyBitmap *bitmap; ++ AioContext *aio_context; ++ ++ bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp); ++ if (!bitmap || !bs) { ++ return NULL; ++ } ++ ++ aio_context = bdrv_get_aio_context(bs); ++ aio_context_acquire(aio_context); ++ ++ if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_BUSY | BDRV_BITMAP_RO, ++ errp)) { ++ aio_context_release(aio_context); ++ return NULL; ++ } ++ ++ if (bdrv_dirty_bitmap_get_persistence(bitmap) && ++ bdrv_remove_persistent_dirty_bitmap(bs, name, errp) < 0) ++ { ++ aio_context_release(aio_context); ++ return NULL; ++ } ++ ++ if (release) { ++ bdrv_release_dirty_bitmap(bitmap); ++ } ++ ++ if (bitmap_bs) { ++ *bitmap_bs = bs; ++ } ++ ++ aio_context_release(aio_context); ++ return release ? NULL : bitmap; ++} ++ ++void qmp_block_dirty_bitmap_remove(const char *node, const char *name, ++ Error **errp) ++{ ++ block_dirty_bitmap_remove(node, name, true, NULL, errp); ++} ++ ++/** ++ * Completely clear a bitmap, for the purposes of synchronizing a bitmap ++ * immediately after a full backup operation. ++ */ ++void qmp_block_dirty_bitmap_clear(const char *node, const char *name, ++ Error **errp) ++{ ++ BdrvDirtyBitmap *bitmap; ++ BlockDriverState *bs; ++ ++ bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp); ++ if (!bitmap || !bs) { ++ return; ++ } ++ ++ if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_DEFAULT, errp)) { ++ return; ++ } ++ ++ bdrv_clear_dirty_bitmap(bitmap, NULL); ++} ++ ++void qmp_block_dirty_bitmap_enable(const char *node, const char *name, ++ Error **errp) ++{ ++ BlockDriverState *bs; ++ BdrvDirtyBitmap *bitmap; ++ ++ bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp); ++ if (!bitmap) { ++ return; ++ } ++ ++ if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_ALLOW_RO, errp)) { ++ return; ++ } ++ ++ bdrv_enable_dirty_bitmap(bitmap); ++} ++ ++void qmp_block_dirty_bitmap_disable(const char *node, const char *name, ++ Error **errp) ++{ ++ BlockDriverState *bs; ++ BdrvDirtyBitmap *bitmap; ++ ++ bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp); ++ if (!bitmap) { ++ return; ++ } ++ ++ if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_ALLOW_RO, errp)) { ++ return; ++ } ++ ++ bdrv_disable_dirty_bitmap(bitmap); ++} ++ ++BdrvDirtyBitmap *block_dirty_bitmap_merge(const char *node, const char *target, ++ BlockDirtyBitmapMergeSourceList *bms, ++ HBitmap **backup, Error **errp) ++{ ++ BlockDriverState *bs; ++ BdrvDirtyBitmap *dst, *src, *anon; ++ BlockDirtyBitmapMergeSourceList *lst; ++ Error *local_err = NULL; ++ ++ dst = block_dirty_bitmap_lookup(node, target, &bs, errp); ++ if (!dst) { ++ return NULL; ++ } ++ ++ anon = bdrv_create_dirty_bitmap(bs, bdrv_dirty_bitmap_granularity(dst), ++ NULL, errp); ++ if (!anon) { ++ return NULL; ++ } ++ ++ for (lst = bms; lst; lst = lst->next) { ++ switch (lst->value->type) { ++ const char *name, *node; ++ case QTYPE_QSTRING: ++ name = lst->value->u.local; ++ src = bdrv_find_dirty_bitmap(bs, name); ++ if (!src) { ++ error_setg(errp, "Dirty bitmap '%s' not found", name); ++ dst = NULL; ++ goto out; ++ } ++ break; ++ case QTYPE_QDICT: ++ node = lst->value->u.external.node; ++ name = lst->value->u.external.name; ++ src = block_dirty_bitmap_lookup(node, name, NULL, errp); ++ if (!src) { ++ dst = NULL; ++ goto out; ++ } ++ break; ++ default: ++ abort(); ++ } ++ ++ bdrv_merge_dirty_bitmap(anon, src, NULL, &local_err); ++ if (local_err) { ++ error_propagate(errp, local_err); ++ dst = NULL; ++ goto out; ++ } ++ } ++ ++ /* Merge into dst; dst is unchanged on failure. */ ++ bdrv_merge_dirty_bitmap(dst, anon, backup, errp); ++ ++ out: ++ bdrv_release_dirty_bitmap(anon); ++ return dst; ++} ++ ++void qmp_block_dirty_bitmap_merge(const char *node, const char *target, ++ BlockDirtyBitmapMergeSourceList *bitmaps, ++ Error **errp) ++{ ++ block_dirty_bitmap_merge(node, target, bitmaps, NULL, errp); ++} +diff --git a/blockdev.c b/blockdev.c +index 3958058..5128c9b 100644 +--- a/blockdev.c ++++ b/blockdev.c +@@ -1250,53 +1250,6 @@ out_aio_context: + return NULL; + } + +-/** +- * block_dirty_bitmap_lookup: +- * Return a dirty bitmap (if present), after validating +- * the node reference and bitmap names. +- * +- * @node: The name of the BDS node to search for bitmaps +- * @name: The name of the bitmap to search for +- * @pbs: Output pointer for BDS lookup, if desired. Can be NULL. +- * @errp: Output pointer for error information. Can be NULL. +- * +- * @return: A bitmap object on success, or NULL on failure. +- */ +-BdrvDirtyBitmap *block_dirty_bitmap_lookup(const char *node, +- const char *name, +- BlockDriverState **pbs, +- Error **errp) +-{ +- BlockDriverState *bs; +- BdrvDirtyBitmap *bitmap; +- +- if (!node) { +- error_setg(errp, "Node cannot be NULL"); +- return NULL; +- } +- if (!name) { +- error_setg(errp, "Bitmap name cannot be NULL"); +- return NULL; +- } +- bs = bdrv_lookup_bs(node, node, NULL); +- if (!bs) { +- error_setg(errp, "Node '%s' not found", node); +- return NULL; +- } +- +- bitmap = bdrv_find_dirty_bitmap(bs, name); +- if (!bitmap) { +- error_setg(errp, "Dirty bitmap '%s' not found", name); +- return NULL; +- } +- +- if (pbs) { +- *pbs = bs; +- } +- +- return bitmap; +-} +- + /* New and old BlockDriverState structs for atomic group operations */ + + typedef struct BlkActionState BlkActionState; +@@ -2974,243 +2927,6 @@ out: + aio_context_release(aio_context); + } + +-void qmp_block_dirty_bitmap_add(const char *node, const char *name, +- bool has_granularity, uint32_t granularity, +- bool has_persistent, bool persistent, +- bool has_disabled, bool disabled, +- Error **errp) +-{ +- BlockDriverState *bs; +- BdrvDirtyBitmap *bitmap; +- AioContext *aio_context; +- +- if (!name || name[0] == '\0') { +- error_setg(errp, "Bitmap name cannot be empty"); +- return; +- } +- +- bs = bdrv_lookup_bs(node, node, errp); +- if (!bs) { +- return; +- } +- +- aio_context = bdrv_get_aio_context(bs); +- aio_context_acquire(aio_context); +- +- if (has_granularity) { +- if (granularity < 512 || !is_power_of_2(granularity)) { +- error_setg(errp, "Granularity must be power of 2 " +- "and at least 512"); +- goto out; +- } +- } else { +- /* Default to cluster size, if available: */ +- granularity = bdrv_get_default_bitmap_granularity(bs); +- } +- +- if (!has_persistent) { +- persistent = false; +- } +- +- if (!has_disabled) { +- disabled = false; +- } +- +- if (persistent && +- !bdrv_can_store_new_dirty_bitmap(bs, name, granularity, errp)) +- { +- goto out; +- } +- +- bitmap = bdrv_create_dirty_bitmap(bs, granularity, name, errp); +- if (bitmap == NULL) { +- goto out; +- } +- +- if (disabled) { +- bdrv_disable_dirty_bitmap(bitmap); +- } +- +- bdrv_dirty_bitmap_set_persistence(bitmap, persistent); +- +-out: +- aio_context_release(aio_context); +-} +- +-BdrvDirtyBitmap *block_dirty_bitmap_remove(const char *node, const char *name, +- bool release, +- BlockDriverState **bitmap_bs, +- Error **errp) +-{ +- BlockDriverState *bs; +- BdrvDirtyBitmap *bitmap; +- AioContext *aio_context; +- +- bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp); +- if (!bitmap || !bs) { +- return NULL; +- } +- +- aio_context = bdrv_get_aio_context(bs); +- aio_context_acquire(aio_context); +- +- if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_BUSY | BDRV_BITMAP_RO, +- errp)) { +- aio_context_release(aio_context); +- return NULL; +- } +- +- if (bdrv_dirty_bitmap_get_persistence(bitmap) && +- bdrv_remove_persistent_dirty_bitmap(bs, name, errp) < 0) +- { +- aio_context_release(aio_context); +- return NULL; +- } +- +- if (release) { +- bdrv_release_dirty_bitmap(bitmap); +- } +- +- if (bitmap_bs) { +- *bitmap_bs = bs; +- } +- +- aio_context_release(aio_context); +- return release ? NULL : bitmap; +-} +- +-void qmp_block_dirty_bitmap_remove(const char *node, const char *name, +- Error **errp) +-{ +- block_dirty_bitmap_remove(node, name, true, NULL, errp); +-} +- +-/** +- * Completely clear a bitmap, for the purposes of synchronizing a bitmap +- * immediately after a full backup operation. +- */ +-void qmp_block_dirty_bitmap_clear(const char *node, const char *name, +- Error **errp) +-{ +- BdrvDirtyBitmap *bitmap; +- BlockDriverState *bs; +- +- bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp); +- if (!bitmap || !bs) { +- return; +- } +- +- if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_DEFAULT, errp)) { +- return; +- } +- +- bdrv_clear_dirty_bitmap(bitmap, NULL); +-} +- +-void qmp_block_dirty_bitmap_enable(const char *node, const char *name, +- Error **errp) +-{ +- BlockDriverState *bs; +- BdrvDirtyBitmap *bitmap; +- +- bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp); +- if (!bitmap) { +- return; +- } +- +- if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_ALLOW_RO, errp)) { +- return; +- } +- +- bdrv_enable_dirty_bitmap(bitmap); +-} +- +-void qmp_block_dirty_bitmap_disable(const char *node, const char *name, +- Error **errp) +-{ +- BlockDriverState *bs; +- BdrvDirtyBitmap *bitmap; +- +- bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp); +- if (!bitmap) { +- return; +- } +- +- if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_ALLOW_RO, errp)) { +- return; +- } +- +- bdrv_disable_dirty_bitmap(bitmap); +-} +- +-BdrvDirtyBitmap *block_dirty_bitmap_merge(const char *node, const char *target, +- BlockDirtyBitmapMergeSourceList *bms, +- HBitmap **backup, Error **errp) +-{ +- BlockDriverState *bs; +- BdrvDirtyBitmap *dst, *src, *anon; +- BlockDirtyBitmapMergeSourceList *lst; +- Error *local_err = NULL; +- +- dst = block_dirty_bitmap_lookup(node, target, &bs, errp); +- if (!dst) { +- return NULL; +- } +- +- anon = bdrv_create_dirty_bitmap(bs, bdrv_dirty_bitmap_granularity(dst), +- NULL, errp); +- if (!anon) { +- return NULL; +- } +- +- for (lst = bms; lst; lst = lst->next) { +- switch (lst->value->type) { +- const char *name, *node; +- case QTYPE_QSTRING: +- name = lst->value->u.local; +- src = bdrv_find_dirty_bitmap(bs, name); +- if (!src) { +- error_setg(errp, "Dirty bitmap '%s' not found", name); +- dst = NULL; +- goto out; +- } +- break; +- case QTYPE_QDICT: +- node = lst->value->u.external.node; +- name = lst->value->u.external.name; +- src = block_dirty_bitmap_lookup(node, name, NULL, errp); +- if (!src) { +- dst = NULL; +- goto out; +- } +- break; +- default: +- abort(); +- } +- +- bdrv_merge_dirty_bitmap(anon, src, NULL, &local_err); +- if (local_err) { +- error_propagate(errp, local_err); +- dst = NULL; +- goto out; +- } +- } +- +- /* Merge into dst; dst is unchanged on failure. */ +- bdrv_merge_dirty_bitmap(dst, anon, backup, errp); +- +- out: +- bdrv_release_dirty_bitmap(anon); +- return dst; +-} +- +-void qmp_block_dirty_bitmap_merge(const char *node, const char *target, +- BlockDirtyBitmapMergeSourceList *bitmaps, +- Error **errp) +-{ +- block_dirty_bitmap_merge(node, target, bitmaps, NULL, errp); +-} +- + BlockDirtyBitmapSha256 *qmp_x_debug_block_dirty_bitmap_sha256(const char *node, + const char *name, + Error **errp) +-- +1.8.3.1 + diff --git a/SOURCES/kvm-compat-disable-edid-for-virtio-gpu-ccw.patch b/SOURCES/kvm-compat-disable-edid-for-virtio-gpu-ccw.patch new file mode 100644 index 0000000..e000534 --- /dev/null +++ b/SOURCES/kvm-compat-disable-edid-for-virtio-gpu-ccw.patch @@ -0,0 +1,50 @@ +From 8f9f4d8d52ebb7878543ac0b84cc372477041e33 Mon Sep 17 00:00:00 2001 +From: Cornelia Huck +Date: Wed, 1 Apr 2020 16:13:50 -0400 +Subject: [PATCH 2/2] compat: disable 'edid' for virtio-gpu-ccw + +RH-Author: Cornelia Huck +Message-id: <20200401161350.20462-1-cohuck@redhat.com> +Patchwork-id: 94523 +O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH v2] compat: disable 'edid' for virtio-gpu-ccw +Bugzilla: 1816793 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Markus Armbruster +RH-Acked-by: Dr. David Alan Gilbert + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1816793 +Branch: rhel-av-8.2.1 +Brew: https://brewweb.engineering.redhat.com/brew/taskinfo?taskID=27629804 +Upstream: downstream only +Tested: verified that for a virtio-gpu-ccw device 'edid' is false with + a s390-ccw-virtio-rhel7.6.0 machine and true with a + s390-ccw-virtio-rhel8.2.0 (s390x does not have the 8.0 or 8.1 + machine types) + +hw_compat_rhel_8_0 copied the original upstream version of +disabling 'edid' for virtio-gpu-pci only (not following later +changes). Switch it to virtio-gpu-device, following upstream +02501fc39381 ("compat: disable edid on correct virtio-gpu device"). + +Signed-off-by: Cornelia Huck +Signed-off-by: Jon Maloy +--- + hw/core/machine.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/core/machine.c b/hw/core/machine.c +index e0e0eec8bf..5a025d1af2 100644 +--- a/hw/core/machine.c ++++ b/hw/core/machine.c +@@ -72,7 +72,7 @@ GlobalProperty hw_compat_rhel_8_0[] = { + /* hw_compat_rhel_8_0 from hw_compat_4_0 */ + { "virtio-vga", "edid", "false" }, + /* hw_compat_rhel_8_0 from hw_compat_4_0 */ +- { "virtio-gpu-pci", "edid", "false" }, ++ { "virtio-gpu-device", "edid", "false" }, + /* hw_compat_rhel_8_0 from hw_compat_4_0 */ + { "virtio-device", "use-started", "false" }, + /* hw_compat_rhel_8_0 from hw_compat_3_1 - that was added in 4.1 */ +-- +2.18.2 + diff --git a/SOURCES/kvm-config-enable-VFIO_CCW.patch b/SOURCES/kvm-config-enable-VFIO_CCW.patch new file mode 100644 index 0000000..44af9cf --- /dev/null +++ b/SOURCES/kvm-config-enable-VFIO_CCW.patch @@ -0,0 +1,39 @@ +From f3e80771c921560a58c30020781fa01a54be8eb0 Mon Sep 17 00:00:00 2001 +From: Cornelia Huck +Date: Tue, 23 Jun 2020 09:25:43 -0400 +Subject: [PATCH 09/12] config: enable VFIO_CCW + +RH-Author: Cornelia Huck +Message-id: <20200623092543.358315-10-cohuck@redhat.com> +Patchwork-id: 97699 +O-Subject: [RHEL-8.3.0 qemu-kvm PATCH 9/9] config: enable VFIO_CCW +Bugzilla: 1660916 +RH-Acked-by: Claudio Imbrenda +RH-Acked-by: David Hildenbrand +RH-Acked-by: Thomas Huth + +Enable vfio-ccw in RHEL builds. + +Upstream: n/a + +Signed-off-by: Cornelia Huck +Signed-off-by: Danilo C. L. de Paula +--- + default-configs/s390x-rh-devices.mak | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/default-configs/s390x-rh-devices.mak b/default-configs/s390x-rh-devices.mak +index c3c73fe752..08a15f3e01 100644 +--- a/default-configs/s390x-rh-devices.mak ++++ b/default-configs/s390x-rh-devices.mak +@@ -9,6 +9,7 @@ CONFIG_SCSI=y + CONFIG_TERMINAL3270=y + CONFIG_VFIO=y + CONFIG_VFIO_AP=y ++CONFIG_VFIO_CCW=y + CONFIG_VFIO_PCI=y + CONFIG_VHOST_USER=y + CONFIG_VIRTIO_CCW=y +-- +2.27.0 + diff --git a/SOURCES/kvm-crypto.c-cleanup-created-file-when-block_crypto_co_c.patch b/SOURCES/kvm-crypto.c-cleanup-created-file-when-block_crypto_co_c.patch new file mode 100644 index 0000000..891b866 --- /dev/null +++ b/SOURCES/kvm-crypto.c-cleanup-created-file-when-block_crypto_co_c.patch @@ -0,0 +1,98 @@ +From 043decff5812c1f46ed44dd0f82099e3b8bb6a28 Mon Sep 17 00:00:00 2001 +From: Maxim Levitsky +Date: Sun, 31 May 2020 16:40:35 +0100 +Subject: [PATCH 7/7] crypto.c: cleanup created file when + block_crypto_co_create_opts_luks fails + +RH-Author: Maxim Levitsky +Message-id: <20200531164035.34188-4-mlevitsk@redhat.com> +Patchwork-id: 97060 +O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH 3/3] crypto.c: cleanup created file when block_crypto_co_create_opts_luks fails +Bugzilla: 1827630 +RH-Acked-by: Sergio Lopez Pascual +RH-Acked-by: John Snow +RH-Acked-by: Eric Blake + +From: Daniel Henrique Barboza + +When using a non-UTF8 secret to create a volume using qemu-img, the +following error happens: + +$ qemu-img create -f luks --object secret,id=vol_1_encrypt0,file=vol_resize_pool.vol_1.secret.qzVQrI -o key-secret=vol_1_encrypt0 /var/tmp/pool_target/vol_1 10240K + +Formatting '/var/tmp/pool_target/vol_1', fmt=luks size=10485760 key-secret=vol_1_encrypt0 +qemu-img: /var/tmp/pool_target/vol_1: Data from secret vol_1_encrypt0 is not valid UTF-8 + +However, the created file '/var/tmp/pool_target/vol_1' is left behind in the +file system after the failure. This behavior can be observed when creating +the volume using Libvirt, via 'virsh vol-create', and then getting "volume +target path already exist" errors when trying to re-create the volume. + +The volume file is created inside block_crypto_co_create_opts_luks(), in +block/crypto.c. If the bdrv_create_file() call is successful but any +succeeding step fails*, the existing 'fail' label does not take into +account the created file, leaving it behind. + +This patch changes block_crypto_co_create_opts_luks() to delete +'filename' in case of failure. A failure in this point means that +the volume is now truncated/corrupted, so even if 'filename' was an +existing volume before calling qemu-img, it is now unusable. Deleting +the file it is not much worse than leaving it in the filesystem in +this scenario, and we don't have to deal with checking the file +pre-existence in the code. + +* in our case, block_crypto_co_create_generic calls qcrypto_block_create, +which calls qcrypto_block_luks_create, and this function fails when +calling qcrypto_secret_lookup_as_utf8. + +Reported-by: Srikanth Aithal +Suggested-by: Kevin Wolf +Signed-off-by: Daniel Henrique Barboza +Message-Id: <20200130213907.2830642-4-danielhb413@gmail.com> +Signed-off-by: Kevin Wolf +(cherry picked from commit 1bba30da24e1124ceeb0693c81382a0d77e20ca5) +Signed-off-by: Maxim Levitsky +Signed-off-by: Danilo C. L. de Paula +--- + block/crypto.c | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +diff --git a/block/crypto.c b/block/crypto.c +index 970d463..5e3b15c 100644 +--- a/block/crypto.c ++++ b/block/crypto.c +@@ -30,6 +30,7 @@ + #include "qapi/error.h" + #include "qemu/module.h" + #include "qemu/option.h" ++#include "qemu/cutils.h" + #include "crypto.h" + + typedef struct BlockCrypto BlockCrypto; +@@ -597,6 +598,23 @@ static int coroutine_fn block_crypto_co_create_opts_luks(BlockDriver *drv, + + ret = 0; + fail: ++ /* ++ * If an error occurred, delete 'filename'. Even if the file existed ++ * beforehand, it has been truncated and corrupted in the process. ++ */ ++ if (ret && bs) { ++ Error *local_delete_err = NULL; ++ int r_del = bdrv_co_delete_file(bs, &local_delete_err); ++ /* ++ * ENOTSUP will happen if the block driver doesn't support ++ * the 'bdrv_co_delete_file' interface. This is a predictable ++ * scenario and shouldn't be reported back to the user. ++ */ ++ if ((r_del < 0) && (r_del != -ENOTSUP)) { ++ error_report_err(local_delete_err); ++ } ++ } ++ + bdrv_unref(bs); + qapi_free_QCryptoBlockCreateOptions(create_opts); + qobject_unref(cryptoopts); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-enable-ramfb.patch b/SOURCES/kvm-enable-ramfb.patch new file mode 100644 index 0000000..fa2fe11 --- /dev/null +++ b/SOURCES/kvm-enable-ramfb.patch @@ -0,0 +1,72 @@ +From 441128e2f13a56d4949b70971edd2f6902772959 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Wed, 3 Jun 2020 15:15:56 +0100 +Subject: [PATCH 01/17] enable ramfb + +RH-Author: Gerd Hoffmann +Message-id: <20200603151556.1195-2-kraxel@redhat.com> +Patchwork-id: 97097 +O-Subject: [RHEL-AV-8.2.0.z qemu-kvm PATCH 1/1] enable ramfb +Bugzilla: 1841068 +RH-Acked-by: Danilo de Paula +RH-Acked-by: Kevin Wolf +RH-Acked-by: Stefan Hajnoczi + +--- + hw/vfio/pci.c | 5 ----- + hw/display/Makefile.objs | 5 ++--- + 2 files changed, 2 insertions(+), 8 deletions(-) + +Signed-off-by: Danilo C. L. de Paula +--- + hw/display/Makefile.objs | 5 ++--- + hw/vfio/pci.c | 5 ----- + 2 files changed, 2 insertions(+), 8 deletions(-) + +diff --git a/hw/display/Makefile.objs b/hw/display/Makefile.objs +index 3d0cda1..f2182e3 100644 +--- a/hw/display/Makefile.objs ++++ b/hw/display/Makefile.objs +@@ -1,9 +1,8 @@ + common-obj-$(CONFIG_DDC) += i2c-ddc.o + common-obj-$(CONFIG_EDID) += edid-generate.o edid-region.o + +-# Disabled for Red Hat Enterprise Linux +-#common-obj-$(CONFIG_FW_CFG_DMA) += ramfb.o +-#common-obj-$(CONFIG_FW_CFG_DMA) += ramfb-standalone.o ++common-obj-$(CONFIG_FW_CFG_DMA) += ramfb.o ++common-obj-$(CONFIG_FW_CFG_DMA) += ramfb-standalone.o + + common-obj-$(CONFIG_ADS7846) += ads7846.o + common-obj-$(CONFIG_VGA_CIRRUS) += cirrus_vga.o +diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c +index d717520..f191904 100644 +--- a/hw/vfio/pci.c ++++ b/hw/vfio/pci.c +@@ -3249,7 +3249,6 @@ static const TypeInfo vfio_pci_dev_info = { + }, + }; + +-#if 0 /* Disabled for Red Hat Enterprise Linux */ + static Property vfio_pci_dev_nohotplug_properties[] = { + DEFINE_PROP_BOOL("ramfb", VFIOPCIDevice, enable_ramfb, false), + DEFINE_PROP_END_OF_LIST(), +@@ -3269,15 +3268,11 @@ static const TypeInfo vfio_pci_nohotplug_dev_info = { + .instance_size = sizeof(VFIOPCIDevice), + .class_init = vfio_pci_nohotplug_dev_class_init, + }; +-#endif + + static void register_vfio_pci_dev_type(void) + { + type_register_static(&vfio_pci_dev_info); +- +-#if 0 /* Disabled for Red Hat Enterprise Linux */ + type_register_static(&vfio_pci_nohotplug_dev_info); +-#endif + } + + type_init(register_vfio_pci_dev_type) +-- +1.8.3.1 + diff --git a/SOURCES/kvm-file-posix-Support-BDRV_REQ_ZERO_WRITE-for-truncate.patch b/SOURCES/kvm-file-posix-Support-BDRV_REQ_ZERO_WRITE-for-truncate.patch new file mode 100644 index 0000000..efdf16b --- /dev/null +++ b/SOURCES/kvm-file-posix-Support-BDRV_REQ_ZERO_WRITE-for-truncate.patch @@ -0,0 +1,48 @@ +From 55bfda3a0e077b822f57e8ed901f0cee848bc471 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Mon, 8 Jun 2020 15:01:35 +0100 +Subject: [PATCH 07/17] file-posix: Support BDRV_REQ_ZERO_WRITE for truncate + +RH-Author: Kevin Wolf +Message-id: <20200608150140.38218-7-kwolf@redhat.com> +Patchwork-id: 97452 +O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH 06/11] file-posix: Support BDRV_REQ_ZERO_WRITE for truncate +Bugzilla: 1780574 +RH-Acked-by: Sergio Lopez Pascual +RH-Acked-by: Eric Blake +RH-Acked-by: Max Reitz + +For regular files, we always get BDRV_REQ_ZERO_WRITE behaviour from the +OS, so we can advertise the flag and just ignore it. + +Signed-off-by: Kevin Wolf +Reviewed-by: Vladimir Sementsov-Ogievskiy +Reviewed-by: Alberto Garcia +Reviewed-by: Max Reitz +Message-Id: <20200424125448.63318-7-kwolf@redhat.com> +Signed-off-by: Kevin Wolf +(cherry picked from commit 2f0c6e7a650de133eccd94e9bb6cf7b2070f07f1) +Signed-off-by: Kevin Wolf +Signed-off-by: Danilo C. L. de Paula +--- + block/file-posix.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/block/file-posix.c b/block/file-posix.c +index 7551e8d..adafbfa 100644 +--- a/block/file-posix.c ++++ b/block/file-posix.c +@@ -674,6 +674,10 @@ static int raw_open_common(BlockDriverState *bs, QDict *options, + #endif + + bs->supported_zero_flags = BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK; ++ if (S_ISREG(st.st_mode)) { ++ /* When extending regular files, we get zeros from the OS */ ++ bs->supported_truncate_flags = BDRV_REQ_ZERO_WRITE; ++ } + ret = 0; + fail: + if (filename && (bdrv_flags & BDRV_O_TEMPORARY)) { +-- +1.8.3.1 + diff --git a/SOURCES/kvm-hmat-acpi-Build-Memory-Proximity-Domain-Attributes-S.patch b/SOURCES/kvm-hmat-acpi-Build-Memory-Proximity-Domain-Attributes-S.patch new file mode 100644 index 0000000..e34f576 --- /dev/null +++ b/SOURCES/kvm-hmat-acpi-Build-Memory-Proximity-Domain-Attributes-S.patch @@ -0,0 +1,275 @@ +From a0816e4374759048cb24b9b3549a093a2ccb6240 Mon Sep 17 00:00:00 2001 +From: "plai@redhat.com" +Date: Thu, 21 May 2020 23:56:50 +0100 +Subject: [PATCH 07/12] hmat acpi: Build Memory Proximity Domain Attributes + Structure(s) + +RH-Author: plai@redhat.com +Message-id: <20200521235655.27141-7-plai@redhat.com> +Patchwork-id: 96734 +O-Subject: [RHEL8.2.1 AV qemu-kvm PATCH 06/11] hmat acpi: Build Memory Proximity Domain Attributes Structure(s) +Bugzilla: 1600217 +RH-Acked-by: Michael S. Tsirkin +RH-Acked-by: Igor Mammedov +RH-Acked-by: Eduardo Habkost + +From: Liu Jingqi + +HMAT is defined in ACPI 6.3: 5.2.27 Heterogeneous Memory Attribute Table +(HMAT). The specification references below link: +http://www.uefi.org/sites/default/files/resources/ACPI_6_3_final_Jan30.pdf + +It describes the memory attributes, such as memory side cache +attributes and bandwidth and latency details, related to the +Memory Proximity Domain. The software is +expected to use this information as hint for optimization. + +This structure describes Memory Proximity Domain Attributes by memory +subsystem and its associativity with processor proximity domain as well as +hint for memory usage. + +In the linux kernel, the codes in drivers/acpi/hmat/hmat.c parse and report +the platform's HMAT tables. + +Acked-by: Markus Armbruster +Reviewed-by: Igor Mammedov +Reviewed-by: Daniel Black +Reviewed-by: Jonathan Cameron +Signed-off-by: Liu Jingqi +Signed-off-by: Tao Xu +Message-Id: <20191213011929.2520-5-tao3.xu@intel.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +(cherry picked from commit e6f123c3b81241be33f1b763d0ff8b36d1ae9c1e) +Signed-off-by: Paul Lai +Signed-off-by: Danilo C. L. de Paula +--- + hw/acpi/Kconfig | 7 ++-- + hw/acpi/Makefile.objs | 1 + + hw/acpi/hmat.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++++++ + hw/acpi/hmat.h | 42 ++++++++++++++++++++++ + hw/i386/acpi-build.c | 5 +++ + 5 files changed, 152 insertions(+), 2 deletions(-) + create mode 100644 hw/acpi/hmat.c + create mode 100644 hw/acpi/hmat.h + +diff --git a/hw/acpi/Kconfig b/hw/acpi/Kconfig +index 12e3f1e..54209c6 100644 +--- a/hw/acpi/Kconfig ++++ b/hw/acpi/Kconfig +@@ -7,6 +7,7 @@ config ACPI_X86 + select ACPI_NVDIMM + select ACPI_CPU_HOTPLUG + select ACPI_MEMORY_HOTPLUG ++ select ACPI_HMAT + + config ACPI_X86_ICH + bool +@@ -23,6 +24,10 @@ config ACPI_NVDIMM + bool + depends on ACPI + ++config ACPI_HMAT ++ bool ++ depends on ACPI ++ + config ACPI_PCI + bool + depends on ACPI && PCI +@@ -33,5 +38,3 @@ config ACPI_VMGENID + depends on PC + + config ACPI_HW_REDUCED +- bool +- depends on ACPI +diff --git a/hw/acpi/Makefile.objs b/hw/acpi/Makefile.objs +index 655a9c1..517bd88 100644 +--- a/hw/acpi/Makefile.objs ++++ b/hw/acpi/Makefile.objs +@@ -7,6 +7,7 @@ common-obj-$(CONFIG_ACPI_CPU_HOTPLUG) += cpu.o + common-obj-$(CONFIG_ACPI_NVDIMM) += nvdimm.o + common-obj-$(CONFIG_ACPI_VMGENID) += vmgenid.o + common-obj-$(CONFIG_ACPI_HW_REDUCED) += generic_event_device.o ++common-obj-$(CONFIG_ACPI_HMAT) += hmat.o + common-obj-$(call lnot,$(CONFIG_ACPI_X86)) += acpi-stub.o + + common-obj-y += acpi_interface.o +diff --git a/hw/acpi/hmat.c b/hw/acpi/hmat.c +new file mode 100644 +index 0000000..9ff7930 +--- /dev/null ++++ b/hw/acpi/hmat.c +@@ -0,0 +1,99 @@ ++/* ++ * HMAT ACPI Implementation ++ * ++ * Copyright(C) 2019 Intel Corporation. ++ * ++ * Author: ++ * Liu jingqi ++ * Tao Xu ++ * ++ * HMAT is defined in ACPI 6.3: 5.2.27 Heterogeneous Memory Attribute Table ++ * (HMAT) ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2 of the License, or (at your option) any later version. ++ * ++ * This library 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, see ++ */ ++ ++#include "qemu/osdep.h" ++#include "sysemu/numa.h" ++#include "hw/acpi/hmat.h" ++ ++/* ++ * ACPI 6.3: ++ * 5.2.27.3 Memory Proximity Domain Attributes Structure: Table 5-145 ++ */ ++static void build_hmat_mpda(GArray *table_data, uint16_t flags, ++ uint32_t initiator, uint32_t mem_node) ++{ ++ ++ /* Memory Proximity Domain Attributes Structure */ ++ /* Type */ ++ build_append_int_noprefix(table_data, 0, 2); ++ /* Reserved */ ++ build_append_int_noprefix(table_data, 0, 2); ++ /* Length */ ++ build_append_int_noprefix(table_data, 40, 4); ++ /* Flags */ ++ build_append_int_noprefix(table_data, flags, 2); ++ /* Reserved */ ++ build_append_int_noprefix(table_data, 0, 2); ++ /* Proximity Domain for the Attached Initiator */ ++ build_append_int_noprefix(table_data, initiator, 4); ++ /* Proximity Domain for the Memory */ ++ build_append_int_noprefix(table_data, mem_node, 4); ++ /* Reserved */ ++ build_append_int_noprefix(table_data, 0, 4); ++ /* ++ * Reserved: ++ * Previously defined as the Start Address of the System Physical ++ * Address Range. Deprecated since ACPI Spec 6.3. ++ */ ++ build_append_int_noprefix(table_data, 0, 8); ++ /* ++ * Reserved: ++ * Previously defined as the Range Length of the region in bytes. ++ * Deprecated since ACPI Spec 6.3. ++ */ ++ build_append_int_noprefix(table_data, 0, 8); ++} ++ ++/* Build HMAT sub table structures */ ++static void hmat_build_table_structs(GArray *table_data, NumaState *numa_state) ++{ ++ uint16_t flags; ++ int i; ++ ++ for (i = 0; i < numa_state->num_nodes; i++) { ++ flags = 0; ++ ++ if (numa_state->nodes[i].initiator < MAX_NODES) { ++ flags |= HMAT_PROXIMITY_INITIATOR_VALID; ++ } ++ ++ build_hmat_mpda(table_data, flags, numa_state->nodes[i].initiator, i); ++ } ++} ++ ++void build_hmat(GArray *table_data, BIOSLinker *linker, NumaState *numa_state) ++{ ++ int hmat_start = table_data->len; ++ ++ /* reserve space for HMAT header */ ++ acpi_data_push(table_data, 40); ++ ++ hmat_build_table_structs(table_data, numa_state); ++ ++ build_header(linker, table_data, ++ (void *)(table_data->data + hmat_start), ++ "HMAT", table_data->len - hmat_start, 2, NULL, NULL); ++} +diff --git a/hw/acpi/hmat.h b/hw/acpi/hmat.h +new file mode 100644 +index 0000000..437dbc6 +--- /dev/null ++++ b/hw/acpi/hmat.h +@@ -0,0 +1,42 @@ ++/* ++ * HMAT ACPI Implementation Header ++ * ++ * Copyright(C) 2019 Intel Corporation. ++ * ++ * Author: ++ * Liu jingqi ++ * Tao Xu ++ * ++ * HMAT is defined in ACPI 6.3: 5.2.27 Heterogeneous Memory Attribute Table ++ * (HMAT) ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2 of the License, or (at your option) any later version. ++ * ++ * This library 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, see ++ */ ++ ++#ifndef HMAT_H ++#define HMAT_H ++ ++#include "hw/acpi/aml-build.h" ++ ++/* ++ * ACPI 6.3: 5.2.27.3 Memory Proximity Domain Attributes Structure, ++ * Table 5-145, Field "flag", Bit [0]: set to 1 to indicate that data in ++ * the Proximity Domain for the Attached Initiator field is valid. ++ * Other bits reserved. ++ */ ++#define HMAT_PROXIMITY_INITIATOR_VALID 0x1 ++ ++void build_hmat(GArray *table_data, BIOSLinker *linker, NumaState *numa_state); ++ ++#endif +diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c +index 6400189..b1f8c55 100644 +--- a/hw/i386/acpi-build.c ++++ b/hw/i386/acpi-build.c +@@ -67,6 +67,7 @@ + #include "hw/i386/intel_iommu.h" + + #include "hw/acpi/ipmi.h" ++#include "hw/acpi/hmat.h" + + /* These are used to size the ACPI tables for -M pc-i440fx-1.7 and + * -M pc-i440fx-2.0. Even if the actual amount of AML generated grows +@@ -2837,6 +2838,10 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine) + acpi_add_table(table_offsets, tables_blob); + build_slit(tables_blob, tables->linker, machine); + } ++ if (machine->numa_state->hmat_enabled) { ++ acpi_add_table(table_offsets, tables_blob); ++ build_hmat(tables_blob, tables->linker, machine->numa_state); ++ } + } + if (acpi_get_mcfg(&mcfg)) { + acpi_add_table(table_offsets, tables_blob); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-hmat-acpi-Build-Memory-Side-Cache-Information-Struct.patch b/SOURCES/kvm-hmat-acpi-Build-Memory-Side-Cache-Information-Struct.patch new file mode 100644 index 0000000..01ef4ce --- /dev/null +++ b/SOURCES/kvm-hmat-acpi-Build-Memory-Side-Cache-Information-Struct.patch @@ -0,0 +1,137 @@ +From d00453667cb972dc2fe1242081d3b39313a6a925 Mon Sep 17 00:00:00 2001 +From: "plai@redhat.com" +Date: Thu, 21 May 2020 23:56:52 +0100 +Subject: [PATCH 09/12] hmat acpi: Build Memory Side Cache Information + Structure(s) + +RH-Author: plai@redhat.com +Message-id: <20200521235655.27141-9-plai@redhat.com> +Patchwork-id: 96741 +O-Subject: [RHEL8.2.1 AV qemu-kvm PATCH 08/11] hmat acpi: Build Memory Side Cache Information Structure(s) +Bugzilla: 1600217 +RH-Acked-by: Michael S. Tsirkin +RH-Acked-by: Igor Mammedov +RH-Acked-by: Eduardo Habkost + +From: Liu Jingqi + +This structure describes memory side cache information for memory +proximity domains if the memory side cache is present and the +physical device forms the memory side cache. +The software could use this information to effectively place +the data in memory to maximize the performance of the system +memory that use the memory side cache. + +Acked-by: Markus Armbruster +Reviewed-by: Igor Mammedov +Reviewed-by: Daniel Black +Reviewed-by: Jonathan Cameron +Signed-off-by: Liu Jingqi +Signed-off-by: Tao Xu +Message-Id: <20191213011929.2520-7-tao3.xu@intel.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +(cherry picked from commit a9c2b841af002db6e21e1297c9026b63fc22c875) +Signed-off-by: Paul Lai +Signed-off-by: Danilo C. L. de Paula +--- + hw/acpi/hmat.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 68 insertions(+), 1 deletion(-) + +diff --git a/hw/acpi/hmat.c b/hw/acpi/hmat.c +index 4635d45..7c24bb5 100644 +--- a/hw/acpi/hmat.c ++++ b/hw/acpi/hmat.c +@@ -143,14 +143,62 @@ static void build_hmat_lb(GArray *table_data, HMAT_LB_Info *hmat_lb, + g_free(entry_list); + } + ++/* ACPI 6.3: 5.2.27.5 Memory Side Cache Information Structure: Table 5-147 */ ++static void build_hmat_cache(GArray *table_data, uint8_t total_levels, ++ NumaHmatCacheOptions *hmat_cache) ++{ ++ /* ++ * Cache Attributes: Bits [3:0] – Total Cache Levels ++ * for this Memory Proximity Domain ++ */ ++ uint32_t cache_attr = total_levels; ++ ++ /* Bits [7:4] : Cache Level described in this structure */ ++ cache_attr |= (uint32_t) hmat_cache->level << 4; ++ ++ /* Bits [11:8] - Cache Associativity */ ++ cache_attr |= (uint32_t) hmat_cache->associativity << 8; ++ ++ /* Bits [15:12] - Write Policy */ ++ cache_attr |= (uint32_t) hmat_cache->policy << 12; ++ ++ /* Bits [31:16] - Cache Line size in bytes */ ++ cache_attr |= (uint32_t) hmat_cache->line << 16; ++ ++ /* Type */ ++ build_append_int_noprefix(table_data, 2, 2); ++ /* Reserved */ ++ build_append_int_noprefix(table_data, 0, 2); ++ /* Length */ ++ build_append_int_noprefix(table_data, 32, 4); ++ /* Proximity Domain for the Memory */ ++ build_append_int_noprefix(table_data, hmat_cache->node_id, 4); ++ /* Reserved */ ++ build_append_int_noprefix(table_data, 0, 4); ++ /* Memory Side Cache Size */ ++ build_append_int_noprefix(table_data, hmat_cache->size, 8); ++ /* Cache Attributes */ ++ build_append_int_noprefix(table_data, cache_attr, 4); ++ /* Reserved */ ++ build_append_int_noprefix(table_data, 0, 2); ++ /* ++ * Number of SMBIOS handles (n) ++ * Linux kernel uses Memory Side Cache Information Structure ++ * without SMBIOS entries for now, so set Number of SMBIOS handles ++ * as 0. ++ */ ++ build_append_int_noprefix(table_data, 0, 2); ++} ++ + /* Build HMAT sub table structures */ + static void hmat_build_table_structs(GArray *table_data, NumaState *numa_state) + { + uint16_t flags; + uint32_t num_initiator = 0; + uint32_t initiator_list[MAX_NODES]; +- int i, hierarchy, type; ++ int i, hierarchy, type, cache_level, total_levels; + HMAT_LB_Info *hmat_lb; ++ NumaHmatCacheOptions *hmat_cache; + + for (i = 0; i < numa_state->num_nodes; i++) { + flags = 0; +@@ -184,6 +232,25 @@ static void hmat_build_table_structs(GArray *table_data, NumaState *numa_state) + } + } + } ++ ++ /* ++ * ACPI 6.3: 5.2.27.5 Memory Side Cache Information Structure: ++ * Table 5-147 ++ */ ++ for (i = 0; i < numa_state->num_nodes; i++) { ++ total_levels = 0; ++ for (cache_level = 1; cache_level < HMAT_LB_LEVELS; cache_level++) { ++ if (numa_state->hmat_cache[i][cache_level]) { ++ total_levels++; ++ } ++ } ++ for (cache_level = 0; cache_level <= total_levels; cache_level++) { ++ hmat_cache = numa_state->hmat_cache[i][cache_level]; ++ if (hmat_cache) { ++ build_hmat_cache(table_data, total_levels, hmat_cache); ++ } ++ } ++ } + } + + void build_hmat(GArray *table_data, BIOSLinker *linker, NumaState *numa_state) +-- +1.8.3.1 + diff --git a/SOURCES/kvm-hmat-acpi-Build-System-Locality-Latency-and-Bandwidt.patch b/SOURCES/kvm-hmat-acpi-Build-System-Locality-Latency-and-Bandwidt.patch new file mode 100644 index 0000000..a7120d7 --- /dev/null +++ b/SOURCES/kvm-hmat-acpi-Build-System-Locality-Latency-and-Bandwidt.patch @@ -0,0 +1,173 @@ +From f55b8b251c323856087baf2380d93fbf2da15db7 Mon Sep 17 00:00:00 2001 +From: "plai@redhat.com" +Date: Thu, 21 May 2020 23:56:51 +0100 +Subject: [PATCH 08/12] hmat acpi: Build System Locality Latency and Bandwidth + Information Structure(s) + +RH-Author: plai@redhat.com +Message-id: <20200521235655.27141-8-plai@redhat.com> +Patchwork-id: 96733 +O-Subject: [RHEL8.2.1 AV qemu-kvm PATCH 07/11] hmat acpi: Build System Locality Latency and Bandwidth Information Structure(s) +Bugzilla: 1600217 +RH-Acked-by: Michael S. Tsirkin +RH-Acked-by: Igor Mammedov +RH-Acked-by: Eduardo Habkost + +From: Liu Jingqi + +This structure describes the memory access latency and bandwidth +information from various memory access initiator proximity domains. +The latency and bandwidth numbers represented in this structure +correspond to rated latency and bandwidth for the platform. +The software could use this information as hint for optimization. + +Acked-by: Markus Armbruster +Reviewed-by: Igor Mammedov +Signed-off-by: Liu Jingqi +Signed-off-by: Tao Xu +Message-Id: <20191213011929.2520-6-tao3.xu@intel.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +(cherry picked from commit 4586a2cb833f80b19c80ebe364a005ac2fa0974a) +Signed-off-by: Paul Lai +Signed-off-by: Danilo C. L. de Paula +--- + hw/acpi/hmat.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 103 insertions(+), 1 deletion(-) + +diff --git a/hw/acpi/hmat.c b/hw/acpi/hmat.c +index 9ff7930..4635d45 100644 +--- a/hw/acpi/hmat.c ++++ b/hw/acpi/hmat.c +@@ -25,6 +25,7 @@ + */ + + #include "qemu/osdep.h" ++#include "qemu/units.h" + #include "sysemu/numa.h" + #include "hw/acpi/hmat.h" + +@@ -67,11 +68,89 @@ static void build_hmat_mpda(GArray *table_data, uint16_t flags, + build_append_int_noprefix(table_data, 0, 8); + } + ++/* ++ * ACPI 6.3: 5.2.27.4 System Locality Latency and Bandwidth Information ++ * Structure: Table 5-146 ++ */ ++static void build_hmat_lb(GArray *table_data, HMAT_LB_Info *hmat_lb, ++ uint32_t num_initiator, uint32_t num_target, ++ uint32_t *initiator_list) ++{ ++ int i, index; ++ HMAT_LB_Data *lb_data; ++ uint16_t *entry_list; ++ uint32_t base; ++ /* Length in bytes for entire structure */ ++ uint32_t lb_length ++ = 32 /* Table length upto and including Entry Base Unit */ ++ + 4 * num_initiator /* Initiator Proximity Domain List */ ++ + 4 * num_target /* Target Proximity Domain List */ ++ + 2 * num_initiator * num_target; /* Latency or Bandwidth Entries */ ++ ++ /* Type */ ++ build_append_int_noprefix(table_data, 1, 2); ++ /* Reserved */ ++ build_append_int_noprefix(table_data, 0, 2); ++ /* Length */ ++ build_append_int_noprefix(table_data, lb_length, 4); ++ /* Flags: Bits [3:0] Memory Hierarchy, Bits[7:4] Reserved */ ++ assert(!(hmat_lb->hierarchy >> 4)); ++ build_append_int_noprefix(table_data, hmat_lb->hierarchy, 1); ++ /* Data Type */ ++ build_append_int_noprefix(table_data, hmat_lb->data_type, 1); ++ /* Reserved */ ++ build_append_int_noprefix(table_data, 0, 2); ++ /* Number of Initiator Proximity Domains (s) */ ++ build_append_int_noprefix(table_data, num_initiator, 4); ++ /* Number of Target Proximity Domains (t) */ ++ build_append_int_noprefix(table_data, num_target, 4); ++ /* Reserved */ ++ build_append_int_noprefix(table_data, 0, 4); ++ ++ /* Entry Base Unit */ ++ if (hmat_lb->data_type <= HMAT_LB_DATA_WRITE_LATENCY) { ++ /* Convert latency base from nanoseconds to picosecond */ ++ base = hmat_lb->base * 1000; ++ } else { ++ /* Convert bandwidth base from Byte to Megabyte */ ++ base = hmat_lb->base / MiB; ++ } ++ build_append_int_noprefix(table_data, base, 8); ++ ++ /* Initiator Proximity Domain List */ ++ for (i = 0; i < num_initiator; i++) { ++ build_append_int_noprefix(table_data, initiator_list[i], 4); ++ } ++ ++ /* Target Proximity Domain List */ ++ for (i = 0; i < num_target; i++) { ++ build_append_int_noprefix(table_data, i, 4); ++ } ++ ++ /* Latency or Bandwidth Entries */ ++ entry_list = g_malloc0(num_initiator * num_target * sizeof(uint16_t)); ++ for (i = 0; i < hmat_lb->list->len; i++) { ++ lb_data = &g_array_index(hmat_lb->list, HMAT_LB_Data, i); ++ index = lb_data->initiator * num_target + lb_data->target; ++ ++ entry_list[index] = (uint16_t)(lb_data->data / hmat_lb->base); ++ } ++ ++ for (i = 0; i < num_initiator * num_target; i++) { ++ build_append_int_noprefix(table_data, entry_list[i], 2); ++ } ++ ++ g_free(entry_list); ++} ++ + /* Build HMAT sub table structures */ + static void hmat_build_table_structs(GArray *table_data, NumaState *numa_state) + { + uint16_t flags; +- int i; ++ uint32_t num_initiator = 0; ++ uint32_t initiator_list[MAX_NODES]; ++ int i, hierarchy, type; ++ HMAT_LB_Info *hmat_lb; + + for (i = 0; i < numa_state->num_nodes; i++) { + flags = 0; +@@ -82,6 +161,29 @@ static void hmat_build_table_structs(GArray *table_data, NumaState *numa_state) + + build_hmat_mpda(table_data, flags, numa_state->nodes[i].initiator, i); + } ++ ++ for (i = 0; i < numa_state->num_nodes; i++) { ++ if (numa_state->nodes[i].has_cpu) { ++ initiator_list[num_initiator++] = i; ++ } ++ } ++ ++ /* ++ * ACPI 6.3: 5.2.27.4 System Locality Latency and Bandwidth Information ++ * Structure: Table 5-146 ++ */ ++ for (hierarchy = HMAT_LB_MEM_MEMORY; ++ hierarchy <= HMAT_LB_MEM_CACHE_3RD_LEVEL; hierarchy++) { ++ for (type = HMAT_LB_DATA_ACCESS_LATENCY; ++ type <= HMAT_LB_DATA_WRITE_BANDWIDTH; type++) { ++ hmat_lb = numa_state->hmat_lb[hierarchy][type]; ++ ++ if (hmat_lb && hmat_lb->list->len) { ++ build_hmat_lb(table_data, hmat_lb, num_initiator, ++ numa_state->num_nodes, initiator_list); ++ } ++ } ++ } + } + + void build_hmat(GArray *table_data, BIOSLinker *linker, NumaState *numa_state) +-- +1.8.3.1 + diff --git a/SOURCES/kvm-hw-pci-pcie-Forbid-hot-plug-if-it-s-disabled-on-the-.patch b/SOURCES/kvm-hw-pci-pcie-Forbid-hot-plug-if-it-s-disabled-on-the-.patch new file mode 100644 index 0000000..2f4f6dd --- /dev/null +++ b/SOURCES/kvm-hw-pci-pcie-Forbid-hot-plug-if-it-s-disabled-on-the-.patch @@ -0,0 +1,77 @@ +From fe8a9f211fba3588d60507b3d2f48c41d8ee3c79 Mon Sep 17 00:00:00 2001 +From: Julia Suvorova +Date: Mon, 4 May 2020 21:25:04 +0100 +Subject: [PATCH 1/9] hw/pci/pcie: Forbid hot-plug if it's disabled on the slot + +RH-Author: Julia Suvorova +Message-id: <20200504212505.15977-2-jusual@redhat.com> +Patchwork-id: 96257 +O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH 1/2] hw/pci/pcie: Forbid hot-plug if it's disabled on the slot +Bugzilla: 1820531 +RH-Acked-by: Michael S. Tsirkin +RH-Acked-by: Igor Mammedov +RH-Acked-by: Peter Xu + +Raise an error when trying to hot-plug/unplug a device through QMP to a device +with disabled hot-plug capability. This makes the device behaviour more +consistent and provides an explanation of the failure in the case of +asynchronous unplug. + +Signed-off-by: Julia Suvorova +Message-Id: <20200427182440.92433-2-jusual@redhat.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Reviewed-by: Marcel Apfelbaum +(cherry picked from commit 0501e1aa1d32a6e02dd06a79bba97fbe9d557cb5) +Signed-off-by: Danilo C. L. de Paula +--- + hw/pci/pcie.c | 19 +++++++++++++++++++ + 1 file changed, 19 insertions(+) + +diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c +index 0eb3a2a..6b48d04 100644 +--- a/hw/pci/pcie.c ++++ b/hw/pci/pcie.c +@@ -415,6 +415,7 @@ void pcie_cap_slot_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, + { + PCIDevice *hotplug_pdev = PCI_DEVICE(hotplug_dev); + uint8_t *exp_cap = hotplug_pdev->config + hotplug_pdev->exp.exp_cap; ++ uint32_t sltcap = pci_get_word(exp_cap + PCI_EXP_SLTCAP); + PCIDevice *pci_dev = PCI_DEVICE(dev); + + /* Don't send event when device is enabled during qemu machine creation: +@@ -430,6 +431,13 @@ void pcie_cap_slot_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, + return; + } + ++ /* Check if hot-plug is disabled on the slot */ ++ if ((sltcap & PCI_EXP_SLTCAP_HPC) == 0) { ++ error_setg(errp, "Hot-plug failed: unsupported by the port device '%s'", ++ DEVICE(hotplug_pdev)->id); ++ return; ++ } ++ + /* To enable multifunction hot-plug, we just ensure the function + * 0 added last. When function 0 is added, we set the sltsta and + * inform OS via event notification. +@@ -470,6 +478,17 @@ void pcie_cap_slot_unplug_request_cb(HotplugHandler *hotplug_dev, + Error *local_err = NULL; + PCIDevice *pci_dev = PCI_DEVICE(dev); + PCIBus *bus = pci_get_bus(pci_dev); ++ PCIDevice *hotplug_pdev = PCI_DEVICE(hotplug_dev); ++ uint8_t *exp_cap = hotplug_pdev->config + hotplug_pdev->exp.exp_cap; ++ uint32_t sltcap = pci_get_word(exp_cap + PCI_EXP_SLTCAP); ++ ++ /* Check if hot-unplug is disabled on the slot */ ++ if ((sltcap & PCI_EXP_SLTCAP_HPC) == 0) { ++ error_setg(errp, "Hot-unplug failed: " ++ "unsupported by the port device '%s'", ++ DEVICE(hotplug_pdev)->id); ++ return; ++ } + + pcie_cap_slot_plug_common(PCI_DEVICE(hotplug_dev), dev, &local_err); + if (local_err) { +-- +1.8.3.1 + diff --git a/SOURCES/kvm-hw-pci-pcie-Move-hot-plug-capability-check-to-pre_pl.patch b/SOURCES/kvm-hw-pci-pcie-Move-hot-plug-capability-check-to-pre_pl.patch new file mode 100644 index 0000000..0c44c77 --- /dev/null +++ b/SOURCES/kvm-hw-pci-pcie-Move-hot-plug-capability-check-to-pre_pl.patch @@ -0,0 +1,90 @@ +From 035f8aaabf2c31cd6206bff6da23a12fee69d1b7 Mon Sep 17 00:00:00 2001 +From: Julia Suvorova +Date: Tue, 16 Jun 2020 12:25:36 -0400 +Subject: [PATCH 1/3] hw/pci/pcie: Move hot plug capability check to pre_plug + callback + +RH-Author: Julia Suvorova +Message-id: <20200616122536.1027685-1-jusual@redhat.com> +Patchwork-id: 97548 +O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH 1/1] hw/pci/pcie: Move hot plug capability check to pre_plug callback +Bugzilla: 1820531 +RH-Acked-by: Danilo de Paula +RH-Acked-by: Auger Eric +RH-Acked-by: Sergio Lopez Pascual + +BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1820531 +BRANCH: rhel-av-8.2.1 +UPSTREAM: merged +BREW: 29422092 + +Check for hot plug capability earlier to avoid removing devices attached +during the initialization process. + +Run qemu with an unattached drive: + -drive file=$FILE,if=none,id=drive0 \ + -device pcie-root-port,id=rp0,slot=3,bus=pcie.0,hotplug=off +Hotplug a block device: + device_add virtio-blk-pci,id=blk0,drive=drive0,bus=rp0 +If hotplug fails on plug_cb, drive0 will be deleted. + +Fixes: 0501e1aa1d32a6 ("hw/pci/pcie: Forbid hot-plug if it's disabled on the slot") + +Acked-by: Igor Mammedov +Signed-off-by: Julia Suvorova +Message-Id: <20200604125947.881210-1-jusual@redhat.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +(cherry picked from commit 0dabc0f6544f2c0310546f6d6cf3b68979580a9c) +Signed-off-by: Eduardo Lima (Etrunko) +--- + hw/pci/pcie.c | 19 +++++++++++-------- + 1 file changed, 11 insertions(+), 8 deletions(-) + +diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c +index abc99b6eff..1386dd228c 100644 +--- a/hw/pci/pcie.c ++++ b/hw/pci/pcie.c +@@ -407,6 +407,17 @@ static void pcie_cap_slot_plug_common(PCIDevice *hotplug_dev, DeviceState *dev, + void pcie_cap_slot_pre_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, + Error **errp) + { ++ PCIDevice *hotplug_pdev = PCI_DEVICE(hotplug_dev); ++ uint8_t *exp_cap = hotplug_pdev->config + hotplug_pdev->exp.exp_cap; ++ uint32_t sltcap = pci_get_word(exp_cap + PCI_EXP_SLTCAP); ++ ++ /* Check if hot-plug is disabled on the slot */ ++ if (dev->hotplugged && (sltcap & PCI_EXP_SLTCAP_HPC) == 0) { ++ error_setg(errp, "Hot-plug failed: unsupported by the port device '%s'", ++ DEVICE(hotplug_pdev)->id); ++ return; ++ } ++ + pcie_cap_slot_plug_common(PCI_DEVICE(hotplug_dev), dev, errp); + } + +@@ -415,7 +426,6 @@ void pcie_cap_slot_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, + { + PCIDevice *hotplug_pdev = PCI_DEVICE(hotplug_dev); + uint8_t *exp_cap = hotplug_pdev->config + hotplug_pdev->exp.exp_cap; +- uint32_t sltcap = pci_get_word(exp_cap + PCI_EXP_SLTCAP); + PCIDevice *pci_dev = PCI_DEVICE(dev); + + /* Don't send event when device is enabled during qemu machine creation: +@@ -431,13 +441,6 @@ void pcie_cap_slot_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, + return; + } + +- /* Check if hot-plug is disabled on the slot */ +- if ((sltcap & PCI_EXP_SLTCAP_HPC) == 0) { +- error_setg(errp, "Hot-plug failed: unsupported by the port device '%s'", +- DEVICE(hotplug_pdev)->id); +- return; +- } +- + /* To enable multifunction hot-plug, we just ensure the function + * 0 added last. When function 0 is added, we set the sltsta and + * inform OS via event notification. +-- +2.27.0 + diff --git a/SOURCES/kvm-hw-pci-pcie-Replace-PCI_DEVICE-casts-with-existing-v.patch b/SOURCES/kvm-hw-pci-pcie-Replace-PCI_DEVICE-casts-with-existing-v.patch new file mode 100644 index 0000000..51a587f --- /dev/null +++ b/SOURCES/kvm-hw-pci-pcie-Replace-PCI_DEVICE-casts-with-existing-v.patch @@ -0,0 +1,62 @@ +From f98a1fdad0aa53337925ac46b73a3e6ad36f6295 Mon Sep 17 00:00:00 2001 +From: Julia Suvorova +Date: Mon, 4 May 2020 21:25:05 +0100 +Subject: [PATCH 2/9] hw/pci/pcie: Replace PCI_DEVICE() casts with existing + variable + +RH-Author: Julia Suvorova +Message-id: <20200504212505.15977-3-jusual@redhat.com> +Patchwork-id: 96259 +O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH 2/2] hw/pci/pcie: Replace PCI_DEVICE() casts with existing variable +Bugzilla: 1820531 +RH-Acked-by: Michael S. Tsirkin +RH-Acked-by: Igor Mammedov +RH-Acked-by: Peter Xu + +A little cleanup is possible because of hotplug_pdev introduction. + +Signed-off-by: Julia Suvorova +Message-Id: <20200427182440.92433-3-jusual@redhat.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Reviewed-by: Marcel Apfelbaum +(cherry picked from commit 6a1e073378353eb6ac0565e0dc649b3db76ed5dc) +Signed-off-by: Danilo C. L. de Paula +--- + hw/pci/pcie.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c +index 6b48d04..abc99b6 100644 +--- a/hw/pci/pcie.c ++++ b/hw/pci/pcie.c +@@ -449,7 +449,7 @@ void pcie_cap_slot_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, + pci_word_test_and_set_mask(exp_cap + PCI_EXP_LNKSTA, + PCI_EXP_LNKSTA_DLLLA); + } +- pcie_cap_slot_event(PCI_DEVICE(hotplug_dev), ++ pcie_cap_slot_event(hotplug_pdev, + PCI_EXP_HP_EV_PDC | PCI_EXP_HP_EV_ABP); + } + } +@@ -490,7 +490,7 @@ void pcie_cap_slot_unplug_request_cb(HotplugHandler *hotplug_dev, + return; + } + +- pcie_cap_slot_plug_common(PCI_DEVICE(hotplug_dev), dev, &local_err); ++ pcie_cap_slot_plug_common(hotplug_pdev, dev, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; +@@ -509,7 +509,7 @@ void pcie_cap_slot_unplug_request_cb(HotplugHandler *hotplug_dev, + return; + } + +- pcie_cap_slot_push_attention_button(PCI_DEVICE(hotplug_dev)); ++ pcie_cap_slot_push_attention_button(hotplug_pdev); + } + + /* pci express slot for pci express root/downstream port +-- +1.8.3.1 + diff --git a/SOURCES/kvm-i386-Add-MSR-feature-bit-for-MDS-NO.patch b/SOURCES/kvm-i386-Add-MSR-feature-bit-for-MDS-NO.patch new file mode 100644 index 0000000..823ff0c --- /dev/null +++ b/SOURCES/kvm-i386-Add-MSR-feature-bit-for-MDS-NO.patch @@ -0,0 +1,46 @@ +From cdafcc1d68110ed172c09c9e6bba42ee15b5a6df Mon Sep 17 00:00:00 2001 +From: "plai@redhat.com" +Date: Fri, 15 May 2020 18:02:40 +0100 +Subject: [PATCH 13/17] i386: Add MSR feature bit for MDS-NO + +RH-Author: plai@redhat.com +Message-id: <20200515180243.17488-2-plai@redhat.com> +Patchwork-id: 96609 +O-Subject: [RHEL8.2.1 AV qemu-kvm PATCH 1/4] i386: Add MSR feature bit for MDS-NO +Bugzilla: 1769912 +RH-Acked-by: Igor Mammedov +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Dr. David Alan Gilbert + +From: Cathy Zhang + +Define MSR_ARCH_CAP_MDS_NO in the IA32_ARCH_CAPABILITIES MSR to allow +CPU models to report the feature when host supports it. + +Signed-off-by: Cathy Zhang +Reviewed-by: Xiaoyao Li +Reviewed-by: Tao Xu +Message-Id: <1571729728-23284-2-git-send-email-cathy.zhang@intel.com> +Signed-off-by: Eduardo Habkost +(cherry picked from commit 77b168d221191156c47fcd8d1c47329dfdb9439e) +Signed-off-by: Paul Lai +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.h | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index 4441061..60304cc 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -839,6 +839,7 @@ typedef uint64_t FeatureWordArray[FEATURE_WORDS]; + #define MSR_ARCH_CAP_RSBA (1U << 2) + #define MSR_ARCH_CAP_SKIP_L1DFL_VMENTRY (1U << 3) + #define MSR_ARCH_CAP_SSB_NO (1U << 4) ++#define MSR_ARCH_CAP_MDS_NO (1U << 5) + + #define MSR_CORE_CAP_SPLIT_LOCK_DETECT (1U << 5) + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-i386-Add-macro-for-stibp.patch b/SOURCES/kvm-i386-Add-macro-for-stibp.patch new file mode 100644 index 0000000..17dd149 --- /dev/null +++ b/SOURCES/kvm-i386-Add-macro-for-stibp.patch @@ -0,0 +1,49 @@ +From 00f916987589f114f42ce20b138c00c47b9e4df7 Mon Sep 17 00:00:00 2001 +From: "plai@redhat.com" +Date: Fri, 15 May 2020 18:02:41 +0100 +Subject: [PATCH 14/17] i386: Add macro for stibp + +RH-Author: plai@redhat.com +Message-id: <20200515180243.17488-3-plai@redhat.com> +Patchwork-id: 96610 +O-Subject: [RHEL8.2.1 AV qemu-kvm PATCH 2/4] i386: Add macro for stibp +Bugzilla: 1769912 +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Igor Mammedov +RH-Acked-by: Eduardo Habkost + +From: Cathy Zhang + +stibp feature is already added through the following commit. +https://github.com/qemu/qemu/commit/0e8916582991b9fd0b94850a8444b8b80d0a0955 + +Add a macro for it to allow CPU models to report it when host supports. + +Signed-off-by: Cathy Zhang +Reviewed-by: Xiaoyao Li +Reviewed-by: Tao Xu +Message-Id: <1571729728-23284-3-git-send-email-cathy.zhang@intel.com> +Signed-off-by: Eduardo Habkost +(cherry picked from commit 5af514d0cb314f43bc53f2aefb437f6451d64d0c) +Signed-off-by: Paul Lai +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.h | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index 60304cc..e77d101 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -772,6 +772,8 @@ typedef uint64_t FeatureWordArray[FEATURE_WORDS]; + #define CPUID_7_0_EDX_AVX512_4FMAPS (1U << 3) + /* Speculation Control */ + #define CPUID_7_0_EDX_SPEC_CTRL (1U << 26) ++/* Single Thread Indirect Branch Predictors */ ++#define CPUID_7_0_EDX_STIBP (1U << 27) + /* Arch Capabilities */ + #define CPUID_7_0_EDX_ARCH_CAPABILITIES (1U << 29) + /* Core Capability */ +-- +1.8.3.1 + diff --git a/SOURCES/kvm-i386-Add-new-CPU-model-Cooperlake.patch b/SOURCES/kvm-i386-Add-new-CPU-model-Cooperlake.patch new file mode 100644 index 0000000..289d1e3 --- /dev/null +++ b/SOURCES/kvm-i386-Add-new-CPU-model-Cooperlake.patch @@ -0,0 +1,108 @@ +From cf62577aed781b2515ea97b9f42285c2f608a7bf Mon Sep 17 00:00:00 2001 +From: "plai@redhat.com" +Date: Fri, 15 May 2020 18:02:42 +0100 +Subject: [PATCH 16/17] i386: Add new CPU model Cooperlake + +RH-Author: plai@redhat.com +Message-id: <20200515180243.17488-4-plai@redhat.com> +Patchwork-id: 96608 +O-Subject: [RHEL8.2.1 AV qemu-kvm PATCH 3/4] i386: Add new CPU model Cooperlake +Bugzilla: 1769912 +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Igor Mammedov +RH-Acked-by: Eduardo Habkost + +From: Cathy Zhang + +Cooper Lake is intel's successor to Cascade Lake, the new +CPU model inherits features from Cascadelake-Server, while +add one platform associated new feature: AVX512_BF16. Meanwhile, +add STIBP for speculative execution. + +Signed-off-by: Cathy Zhang +Reviewed-by: Xiaoyao Li +Reviewed-by: Tao Xu +Message-Id: <1571729728-23284-4-git-send-email-cathy.zhang@intel.com> +Reviewed-by: Bruce Rogers +Signed-off-by: Eduardo Habkost +(cherry picked from commit 22a866b6166db5caa4abaa6e656c2a431fa60726) +Signed-off-by: Paul Lai +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 60 insertions(+) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 0f0a2db..996a74f 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -3161,6 +3161,66 @@ static X86CPUDefinition builtin_x86_defs[] = { + } + }, + { ++ .name = "Cooperlake", ++ .level = 0xd, ++ .vendor = CPUID_VENDOR_INTEL, ++ .family = 6, ++ .model = 85, ++ .stepping = 10, ++ .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_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, ++ .features[FEAT_7_0_ECX] = ++ 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_STIBP | ++ CPUID_7_0_EDX_SPEC_CTRL_SSBD | CPUID_7_0_EDX_ARCH_CAPABILITIES, ++ .features[FEAT_ARCH_CAPABILITIES] = ++ MSR_ARCH_CAP_RDCL_NO | MSR_ARCH_CAP_IBRS_ALL | ++ MSR_ARCH_CAP_SKIP_L1DFL_VMENTRY | MSR_ARCH_CAP_MDS_NO, ++ .features[FEAT_7_1_EAX] = ++ CPUID_7_1_EAX_AVX512_BF16, ++ /* ++ * 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 (Cooperlake)", ++ }, ++ { + .name = "Icelake-Client", + .level = 0xd, + .vendor = CPUID_VENDOR_INTEL, +-- +1.8.3.1 + diff --git a/SOURCES/kvm-introduce-kvm_kernel_irqchip_-functions.patch b/SOURCES/kvm-introduce-kvm_kernel_irqchip_-functions.patch new file mode 100644 index 0000000..b171749 --- /dev/null +++ b/SOURCES/kvm-introduce-kvm_kernel_irqchip_-functions.patch @@ -0,0 +1,281 @@ +From 3899672db472c1ca530badd49d17726a1057f8af Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 5 Jun 2020 07:41:10 -0400 +Subject: [PATCH 40/42] kvm: introduce kvm_kernel_irqchip_* functions +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Thomas Huth +Message-id: <20200605074111.2185-3-thuth@redhat.com> +Patchwork-id: 97369 +O-Subject: [RHEL-8.3.0 qemu-kvm PATCH 2/3] kvm: introduce kvm_kernel_irqchip_* functions +Bugzilla: 1756946 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand + +From: Paolo Bonzini + +The KVMState struct is opaque, so provide accessors for the fields +that will be moved from current_machine to the accelerator. For now +they just forward to the machine object, but this will change. + +Signed-off-by: Paolo Bonzini +(cherry picked from commit 4376c40dedb22530738eeb104a603e94ed03f719) + +Conflicts: + accel/kvm/kvm-all.c + (contextual conflict due to missing other commits in downstream) +Signed-off-by: Thomas Huth +Signed-off-by: Danilo C. L. de Paula +--- + accel/kvm/kvm-all.c | 23 +++++++++++++++++++---- + hw/ppc/e500.c | 5 ++--- + hw/ppc/spapr_irq.c | 16 ++++------------ + include/sysemu/kvm.h | 7 +++++-- + target/arm/kvm.c | 8 ++++---- + target/i386/kvm.c | 4 ++-- + target/mips/kvm.c | 2 +- + target/ppc/kvm.c | 2 +- + target/s390x/kvm.c | 2 +- + 9 files changed, 39 insertions(+), 30 deletions(-) + +diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c +index 5007bdad96..b0250209f5 100644 +--- a/accel/kvm/kvm-all.c ++++ b/accel/kvm/kvm-all.c +@@ -1772,7 +1772,7 @@ void kvm_irqchip_set_qemuirq_gsi(KVMState *s, qemu_irq irq, int gsi) + g_hash_table_insert(s->gsimap, irq, GINT_TO_POINTER(gsi)); + } + +-static void kvm_irqchip_create(MachineState *machine, KVMState *s) ++static void kvm_irqchip_create(KVMState *s) + { + int ret; + +@@ -1790,9 +1790,9 @@ static void kvm_irqchip_create(MachineState *machine, KVMState *s) + + /* First probe and see if there's a arch-specific hook to create the + * in-kernel irqchip for us */ +- ret = kvm_arch_irqchip_create(machine, s); ++ ret = kvm_arch_irqchip_create(s); + if (ret == 0) { +- if (machine_kernel_irqchip_split(machine)) { ++ if (kvm_kernel_irqchip_split()) { + perror("Split IRQ chip mode not supported."); + exit(1); + } else { +@@ -2076,7 +2076,7 @@ static int kvm_init(MachineState *ms) + } + + if (machine_kernel_irqchip_allowed(ms)) { +- kvm_irqchip_create(ms, s); ++ kvm_irqchip_create(s); + } + + if (kvm_eventfds_allowed) { +@@ -2966,6 +2966,21 @@ static bool kvm_accel_has_memory(MachineState *ms, AddressSpace *as, + return false; + } + ++bool kvm_kernel_irqchip_allowed(void) ++{ ++ return machine_kernel_irqchip_allowed(current_machine); ++} ++ ++bool kvm_kernel_irqchip_required(void) ++{ ++ return machine_kernel_irqchip_required(current_machine); ++} ++ ++bool kvm_kernel_irqchip_split(void) ++{ ++ return machine_kernel_irqchip_split(current_machine); ++} ++ + static void kvm_accel_class_init(ObjectClass *oc, void *data) + { + AccelClass *ac = ACCEL_CLASS(oc); +diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c +index 91cd4c26f9..12b6a5b2a8 100644 +--- a/hw/ppc/e500.c ++++ b/hw/ppc/e500.c +@@ -793,7 +793,6 @@ static DeviceState *ppce500_init_mpic(PPCE500MachineState *pms, + MemoryRegion *ccsr, + IrqLines *irqs) + { +- MachineState *machine = MACHINE(pms); + const PPCE500MachineClass *pmc = PPCE500_MACHINE_GET_CLASS(pms); + DeviceState *dev = NULL; + SysBusDevice *s; +@@ -801,10 +800,10 @@ static DeviceState *ppce500_init_mpic(PPCE500MachineState *pms, + if (kvm_enabled()) { + Error *err = NULL; + +- if (machine_kernel_irqchip_allowed(machine)) { ++ if (kvm_kernel_irqchip_allowed()) { + dev = ppce500_init_mpic_kvm(pmc, irqs, &err); + } +- if (machine_kernel_irqchip_required(machine) && !dev) { ++ if (kvm_kernel_irqchip_required() && !dev) { + error_reportf_err(err, + "kernel_irqchip requested but unavailable: "); + exit(1); +diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c +index 9da423658a..f388d07bf9 100644 +--- a/hw/ppc/spapr_irq.c ++++ b/hw/ppc/spapr_irq.c +@@ -75,12 +75,11 @@ int spapr_irq_init_kvm(SpaprInterruptControllerInitKvm fn, + uint32_t nr_servers, + Error **errp) + { +- MachineState *machine = MACHINE(qdev_get_machine()); + Error *local_err = NULL; + +- if (kvm_enabled() && machine_kernel_irqchip_allowed(machine)) { ++ if (kvm_enabled() && kvm_kernel_irqchip_allowed()) { + if (fn(intc, nr_servers, &local_err) < 0) { +- if (machine_kernel_irqchip_required(machine)) { ++ if (kvm_kernel_irqchip_required()) { + error_prepend(&local_err, + "kernel_irqchip requested but unavailable: "); + error_propagate(errp, local_err); +@@ -185,7 +184,7 @@ static int spapr_irq_check(SpaprMachineState *spapr, Error **errp) + */ + if (kvm_enabled() && + spapr->irq == &spapr_irq_dual && +- machine_kernel_irqchip_required(machine) && ++ kvm_kernel_irqchip_required() && + xics_kvm_has_broken_disconnect(spapr)) { + error_setg(errp, "KVM is too old to support ic-mode=dual,kernel-irqchip=on"); + return -1; +@@ -288,20 +287,13 @@ uint32_t spapr_irq_nr_msis(SpaprMachineState *spapr) + + void spapr_irq_init(SpaprMachineState *spapr, Error **errp) + { +- MachineState *machine = MACHINE(spapr); + SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr); + +- if (machine_kernel_irqchip_split(machine)) { ++ if (kvm_enabled() && kvm_kernel_irqchip_split()) { + error_setg(errp, "kernel_irqchip split mode not supported on pseries"); + return; + } + +- if (!kvm_enabled() && machine_kernel_irqchip_required(machine)) { +- error_setg(errp, +- "kernel_irqchip requested but only available with KVM"); +- return; +- } +- + if (spapr_irq_check(spapr, errp) < 0) { + return; + } +diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h +index 9fe233b9bf..aaf2a502e8 100644 +--- a/include/sysemu/kvm.h ++++ b/include/sysemu/kvm.h +@@ -519,10 +519,13 @@ void kvm_pc_gsi_handler(void *opaque, int n, int level); + void kvm_pc_setup_irq_routing(bool pci_enabled); + void kvm_init_irq_routing(KVMState *s); + ++bool kvm_kernel_irqchip_allowed(void); ++bool kvm_kernel_irqchip_required(void); ++bool kvm_kernel_irqchip_split(void); ++ + /** + * kvm_arch_irqchip_create: + * @KVMState: The KVMState pointer +- * @MachineState: The MachineState pointer + * + * Allow architectures to create an in-kernel irq chip themselves. + * +@@ -530,7 +533,7 @@ void kvm_init_irq_routing(KVMState *s); + * 0: irq chip was not created + * > 0: irq chip was created + */ +-int kvm_arch_irqchip_create(MachineState *ms, KVMState *s); ++int kvm_arch_irqchip_create(KVMState *s); + + /** + * kvm_set_one_reg - set a register value in KVM via KVM_SET_ONE_REG ioctl +diff --git a/target/arm/kvm.c b/target/arm/kvm.c +index 4be9497402..418bcedc3e 100644 +--- a/target/arm/kvm.c ++++ b/target/arm/kvm.c +@@ -861,11 +861,11 @@ void kvm_arch_init_irq_routing(KVMState *s) + { + } + +-int kvm_arch_irqchip_create(MachineState *ms, KVMState *s) ++int kvm_arch_irqchip_create(KVMState *s) + { +- if (machine_kernel_irqchip_split(ms)) { +- perror("-machine kernel_irqchip=split is not supported on ARM."); +- exit(1); ++ if (kvm_kernel_irqchip_split()) { ++ perror("-machine kernel_irqchip=split is not supported on ARM."); ++ exit(1); + } + + /* If we can create the VGIC using the newer device control API, we +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index fcc8f7d1f3..f5c17e0028 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -4532,10 +4532,10 @@ void kvm_arch_init_irq_routing(KVMState *s) + } + } + +-int kvm_arch_irqchip_create(MachineState *ms, KVMState *s) ++int kvm_arch_irqchip_create(KVMState *s) + { + int ret; +- if (machine_kernel_irqchip_split(ms)) { ++ if (kvm_kernel_irqchip_split()) { + ret = kvm_vm_enable_cap(s, KVM_CAP_SPLIT_IRQCHIP, 0, 24); + if (ret) { + error_report("Could not enable split irqchip mode: %s", +diff --git a/target/mips/kvm.c b/target/mips/kvm.c +index 578bc14625..de3e26ef1f 100644 +--- a/target/mips/kvm.c ++++ b/target/mips/kvm.c +@@ -57,7 +57,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s) + return 0; + } + +-int kvm_arch_irqchip_create(MachineState *ms, KVMState *s) ++int kvm_arch_irqchip_create(KVMState *s) + { + return 0; + } +diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c +index c77f9848ec..461dc6dae1 100644 +--- a/target/ppc/kvm.c ++++ b/target/ppc/kvm.c +@@ -152,7 +152,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s) + return 0; + } + +-int kvm_arch_irqchip_create(MachineState *ms, KVMState *s) ++int kvm_arch_irqchip_create(KVMState *s) + { + return 0; + } +diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c +index 84d7cadd09..c589ef9034 100644 +--- a/target/s390x/kvm.c ++++ b/target/s390x/kvm.c +@@ -386,7 +386,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s) + return 0; + } + +-int kvm_arch_irqchip_create(MachineState *ms, KVMState *s) ++int kvm_arch_irqchip_create(KVMState *s) + { + return 0; + } +-- +2.27.0 + diff --git a/SOURCES/kvm-iotests-055-refactor-compressed-backup-to-vmdk.patch b/SOURCES/kvm-iotests-055-refactor-compressed-backup-to-vmdk.patch new file mode 100644 index 0000000..401f39f --- /dev/null +++ b/SOURCES/kvm-iotests-055-refactor-compressed-backup-to-vmdk.patch @@ -0,0 +1,176 @@ +From a5bf39550e82dbbe18f8debe07fa5d968a3fcf51 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Wed, 3 Jun 2020 16:03:17 +0100 +Subject: [PATCH 18/26] iotests/055: refactor compressed backup to vmdk + +RH-Author: Kevin Wolf +Message-id: <20200603160325.67506-4-kwolf@redhat.com> +Patchwork-id: 97104 +O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH v2 03/11] iotests/055: refactor compressed backup to vmdk +Bugzilla: 1778593 +RH-Acked-by: Eric Blake +RH-Acked-by: Max Reitz +RH-Acked-by: Stefano Garzarella + +From: Vladimir Sementsov-Ogievskiy + +Instead of looping in each test, let's better refactor vmdk target case +as a subclass. + +Signed-off-by: Vladimir Sementsov-Ogievskiy +Message-Id: <20200430124713.3067-6-vsementsov@virtuozzo.com> +Signed-off-by: Kevin Wolf +(cherry picked from commit 8e8372944e5e097e98844b4db10f867689065e16) +Signed-off-by: Kevin Wolf +Signed-off-by: Danilo C. L. de Paula +--- + tests/qemu-iotests/055 | 70 ++++++++++++++++++++++++---------------------- + tests/qemu-iotests/055.out | 4 +-- + 2 files changed, 39 insertions(+), 35 deletions(-) + +diff --git a/tests/qemu-iotests/055 b/tests/qemu-iotests/055 +index eb50c9f..8666601 100755 +--- a/tests/qemu-iotests/055 ++++ b/tests/qemu-iotests/055 +@@ -450,10 +450,9 @@ class TestSingleTransaction(iotests.QMPTestCase): + self.assert_no_active_block_jobs() + + +-class TestDriveCompression(iotests.QMPTestCase): ++class TestCompressedToQcow2(iotests.QMPTestCase): + image_len = 64 * 1024 * 1024 # MB +- fmt_supports_compression = [{'type': 'qcow2', 'args': ()}, +- {'type': 'vmdk', 'args': ('-o', 'subformat=streamOptimized')}] ++ target_fmt = {'type': 'qcow2', 'args': ()} + + def tearDown(self): + self.vm.shutdown() +@@ -463,19 +462,20 @@ class TestDriveCompression(iotests.QMPTestCase): + except OSError: + pass + +- def do_prepare_drives(self, fmt, args, attach_target): ++ def do_prepare_drives(self, attach_target): + self.vm = iotests.VM().add_drive('blkdebug::' + test_img) + +- qemu_img('create', '-f', fmt, blockdev_target_img, +- str(TestDriveCompression.image_len), *args) ++ qemu_img('create', '-f', self.target_fmt['type'], blockdev_target_img, ++ str(self.image_len), *self.target_fmt['args']) + if attach_target: + self.vm.add_drive(blockdev_target_img, +- img_format=fmt, interface="none") ++ img_format=self.target_fmt['type'], ++ interface="none") + + self.vm.launch() + +- def do_test_compress_complete(self, cmd, format, attach_target, **args): +- self.do_prepare_drives(format['type'], format['args'], attach_target) ++ def do_test_compress_complete(self, cmd, attach_target, **args): ++ self.do_prepare_drives(attach_target) + + self.assert_no_active_block_jobs() + +@@ -486,21 +486,21 @@ class TestDriveCompression(iotests.QMPTestCase): + + self.vm.shutdown() + self.assertTrue(iotests.compare_images(test_img, blockdev_target_img, +- iotests.imgfmt, format['type']), ++ iotests.imgfmt, ++ self.target_fmt['type']), + 'target image does not match source after backup') + + def test_complete_compress_drive_backup(self): +- for format in TestDriveCompression.fmt_supports_compression: +- self.do_test_compress_complete('drive-backup', format, False, +- target=blockdev_target_img, mode='existing') ++ self.do_test_compress_complete('drive-backup', False, ++ target=blockdev_target_img, ++ mode='existing') + + def test_complete_compress_blockdev_backup(self): +- for format in TestDriveCompression.fmt_supports_compression: +- self.do_test_compress_complete('blockdev-backup', format, True, +- target='drive1') ++ self.do_test_compress_complete('blockdev-backup', ++ True, target='drive1') + +- def do_test_compress_cancel(self, cmd, format, attach_target, **args): +- self.do_prepare_drives(format['type'], format['args'], attach_target) ++ def do_test_compress_cancel(self, cmd, attach_target, **args): ++ self.do_prepare_drives(attach_target) + + self.assert_no_active_block_jobs() + +@@ -514,17 +514,16 @@ class TestDriveCompression(iotests.QMPTestCase): + self.vm.shutdown() + + def test_compress_cancel_drive_backup(self): +- for format in TestDriveCompression.fmt_supports_compression: +- self.do_test_compress_cancel('drive-backup', format, False, +- target=blockdev_target_img, mode='existing') ++ self.do_test_compress_cancel('drive-backup', False, ++ target=blockdev_target_img, ++ mode='existing') + + def test_compress_cancel_blockdev_backup(self): +- for format in TestDriveCompression.fmt_supports_compression: +- self.do_test_compress_cancel('blockdev-backup', format, True, +- target='drive1') ++ self.do_test_compress_cancel('blockdev-backup', True, ++ target='drive1') + +- def do_test_compress_pause(self, cmd, format, attach_target, **args): +- self.do_prepare_drives(format['type'], format['args'], attach_target) ++ def do_test_compress_pause(self, cmd, attach_target, **args): ++ self.do_prepare_drives(attach_target) + + self.assert_no_active_block_jobs() + +@@ -550,18 +549,23 @@ class TestDriveCompression(iotests.QMPTestCase): + + self.vm.shutdown() + self.assertTrue(iotests.compare_images(test_img, blockdev_target_img, +- iotests.imgfmt, format['type']), ++ iotests.imgfmt, ++ self.target_fmt['type']), + 'target image does not match source after backup') + + def test_compress_pause_drive_backup(self): +- for format in TestDriveCompression.fmt_supports_compression: +- self.do_test_compress_pause('drive-backup', format, False, +- target=blockdev_target_img, mode='existing') ++ self.do_test_compress_pause('drive-backup', False, ++ target=blockdev_target_img, ++ mode='existing') + + def test_compress_pause_blockdev_backup(self): +- for format in TestDriveCompression.fmt_supports_compression: +- self.do_test_compress_pause('blockdev-backup', format, True, +- target='drive1') ++ self.do_test_compress_pause('blockdev-backup', True, ++ target='drive1') ++ ++ ++class TestCompressedToVmdk(TestCompressedToQcow2): ++ target_fmt = {'type': 'vmdk', 'args': ('-o', 'subformat=streamOptimized')} ++ + + if __name__ == '__main__': + iotests.main(supported_fmts=['raw', 'qcow2'], +diff --git a/tests/qemu-iotests/055.out b/tests/qemu-iotests/055.out +index 5ce2f9a..5c26d15 100644 +--- a/tests/qemu-iotests/055.out ++++ b/tests/qemu-iotests/055.out +@@ -1,5 +1,5 @@ +-.............................. ++.................................... + ---------------------------------------------------------------------- +-Ran 30 tests ++Ran 36 tests + + OK +-- +1.8.3.1 + diff --git a/SOURCES/kvm-iotests-055-skip-vmdk-target-tests-if-vmdk-is-not-wh.patch b/SOURCES/kvm-iotests-055-skip-vmdk-target-tests-if-vmdk-is-not-wh.patch new file mode 100644 index 0000000..260d511 --- /dev/null +++ b/SOURCES/kvm-iotests-055-skip-vmdk-target-tests-if-vmdk-is-not-wh.patch @@ -0,0 +1,45 @@ +From 9a0ca4797cbd029dab9209d88f8c81b78ded8fd0 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Wed, 3 Jun 2020 16:03:18 +0100 +Subject: [PATCH 19/26] iotests/055: skip vmdk target tests if vmdk is not + whitelisted + +RH-Author: Kevin Wolf +Message-id: <20200603160325.67506-5-kwolf@redhat.com> +Patchwork-id: 97101 +O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH v2 04/11] iotests/055: skip vmdk target tests if vmdk is not whitelisted +Bugzilla: 1778593 +RH-Acked-by: Eric Blake +RH-Acked-by: Max Reitz +RH-Acked-by: Stefano Garzarella + +From: Vladimir Sementsov-Ogievskiy + +Signed-off-by: Vladimir Sementsov-Ogievskiy +Message-Id: <20200430124713.3067-7-vsementsov@virtuozzo.com> +Signed-off-by: Kevin Wolf +(cherry picked from commit 761cd2e791eae38c3d08ea5f83309ce58bb85ff7) +Signed-off-by: Kevin Wolf +Signed-off-by: Danilo C. L. de Paula +--- + tests/qemu-iotests/055 | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/tests/qemu-iotests/055 b/tests/qemu-iotests/055 +index 8666601..c9cdc06 100755 +--- a/tests/qemu-iotests/055 ++++ b/tests/qemu-iotests/055 +@@ -566,6 +566,10 @@ class TestCompressedToQcow2(iotests.QMPTestCase): + class TestCompressedToVmdk(TestCompressedToQcow2): + target_fmt = {'type': 'vmdk', 'args': ('-o', 'subformat=streamOptimized')} + ++ @iotests.skip_if_unsupported(['vmdk']) ++ def setUp(self): ++ pass ++ + + if __name__ == '__main__': + iotests.main(supported_fmts=['raw', 'qcow2'], +-- +1.8.3.1 + diff --git a/SOURCES/kvm-iotests-109-Don-t-mirror-with-mismatched-size.patch b/SOURCES/kvm-iotests-109-Don-t-mirror-with-mismatched-size.patch new file mode 100644 index 0000000..c71bcba --- /dev/null +++ b/SOURCES/kvm-iotests-109-Don-t-mirror-with-mismatched-size.patch @@ -0,0 +1,387 @@ +From 2202321b549dda551190d919a5a1cbee0fab8c90 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Wed, 3 Jun 2020 16:03:22 +0100 +Subject: [PATCH 23/26] iotests/109: Don't mirror with mismatched size + +RH-Author: Kevin Wolf +Message-id: <20200603160325.67506-9-kwolf@redhat.com> +Patchwork-id: 97105 +O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH v2 08/11] iotests/109: Don't mirror with mismatched size +Bugzilla: 1778593 +RH-Acked-by: Eric Blake +RH-Acked-by: Max Reitz +RH-Acked-by: Stefano Garzarella + +This patch makes the raw image the same size as the file in a different +format that is mirrored as raw to it to avoid errors when mirror starts +to enforce that source and target are the same size. + +We check only that the first 512 bytes are zeroed (instead of 64k) +because some image formats create image files that are smaller than 64k, +so trying to read 64k would result in I/O errors. Apart from this, 512 +is more appropriate anyway because the raw format driver protects +specifically the first 512 bytes. + +Signed-off-by: Kevin Wolf +Message-Id: <20200511135825.219437-2-kwolf@redhat.com> +Reviewed-by: Max Reitz +Reviewed-by: Vladimir Sementsov-Ogievskiy +Signed-off-by: Kevin Wolf +(cherry picked from commit ffa41a62d0b0e6d91f2071328befa046d56993e1) +Signed-off-by: Kevin Wolf +Signed-off-by: Danilo C. L. de Paula +--- + tests/qemu-iotests/109 | 10 +++--- + tests/qemu-iotests/109.out | 74 +++++++++++++++++----------------------- + tests/qemu-iotests/common.filter | 5 +++ + 3 files changed, 41 insertions(+), 48 deletions(-) + +diff --git a/tests/qemu-iotests/109 b/tests/qemu-iotests/109 +index 9897ceb..190c35e 100755 +--- a/tests/qemu-iotests/109 ++++ b/tests/qemu-iotests/109 +@@ -76,14 +76,14 @@ for fmt in qcow qcow2 qed vdi vmdk vpc; do + echo "=== Writing a $fmt header into raw ===" + echo + +- _make_test_img 64M + TEST_IMG="$TEST_IMG.src" IMGFMT=$fmt _make_test_img 64M ++ _make_test_img $(du -b "$TEST_IMG.src" | cut -f1) | _filter_img_create_size + + # This first test should fail: The image format was probed, we may not + # write an image header at the start of the image + run_qemu "$TEST_IMG" "$TEST_IMG.src" "" "BLOCK_JOB_ERROR" | + _filter_block_job_len +- $QEMU_IO -c 'read -P 0 0 64k' "$TEST_IMG" | _filter_qemu_io ++ $QEMU_IO -c 'read -P 0 0 512' "$TEST_IMG" | _filter_qemu_io + + + # When raw was explicitly specified, the same must succeed +@@ -102,12 +102,12 @@ for sample_img in empty.bochs iotest-dirtylog-10G-4M.vhdx parallels-v1 \ + + # Can't use _use_sample_img because that isn't designed to be used multiple + # times and it overwrites $TEST_IMG (both breaks cleanup) +- _make_test_img 64M + bzcat "$SAMPLE_IMG_DIR/$sample_img.bz2" > "$TEST_IMG.src" ++ _make_test_img $(du -b "$TEST_IMG.src" | cut -f1) | _filter_img_create_size + + run_qemu "$TEST_IMG" "$TEST_IMG.src" "" "BLOCK_JOB_ERROR" | + _filter_block_job_offset | _filter_block_job_len +- $QEMU_IO -c 'read -P 0 0 64k' "$TEST_IMG" | _filter_qemu_io ++ $QEMU_IO -c 'read -P 0 0 512' "$TEST_IMG" | _filter_qemu_io + + run_qemu "$TEST_IMG" "$TEST_IMG.src" "'format': 'raw'," "BLOCK_JOB_READY" + $QEMU_IMG compare -f raw -F raw "$TEST_IMG" "$TEST_IMG.src" +@@ -118,8 +118,8 @@ echo "=== Write legitimate MBR into raw ===" + echo + + for sample_img in grub_mbr.raw; do +- _make_test_img 64M + bzcat "$SAMPLE_IMG_DIR/$sample_img.bz2" > "$TEST_IMG.src" ++ _make_test_img $(du -b "$TEST_IMG.src" | cut -f1) | _filter_img_create_size + + run_qemu "$TEST_IMG" "$TEST_IMG.src" "" "BLOCK_JOB_READY" + $QEMU_IMG compare -f raw -F raw "$TEST_IMG" "$TEST_IMG.src" +diff --git a/tests/qemu-iotests/109.out b/tests/qemu-iotests/109.out +index 884f65f..ad739df 100644 +--- a/tests/qemu-iotests/109.out ++++ b/tests/qemu-iotests/109.out +@@ -2,8 +2,8 @@ QA output created by 109 + + === Writing a qcow header into raw === + +-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 + Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864 ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE + { 'execute': 'qmp_capabilities' } + {"return": {}} + {'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}} +@@ -23,8 +23,8 @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed + {"execute":"quit"} + {"return": {}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +-read 65536/65536 bytes at offset 0 +-64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++read 512/512 bytes at offset 0 ++512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + { 'execute': 'qmp_capabilities' } + {"return": {}} + {'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}} +@@ -43,13 +43,12 @@ read 65536/65536 bytes at offset 0 + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 1024, "offset": 1024, "speed": 0, "type": "mirror"}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}} +-Warning: Image size mismatch! + Images are identical. + + === Writing a qcow2 header into raw === + +-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 + Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864 ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE + { 'execute': 'qmp_capabilities' } + {"return": {}} + {'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}} +@@ -69,8 +68,8 @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed + {"execute":"quit"} + {"return": {}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +-read 65536/65536 bytes at offset 0 +-64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++read 512/512 bytes at offset 0 ++512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + { 'execute': 'qmp_capabilities' } + {"return": {}} + {'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}} +@@ -89,13 +88,12 @@ read 65536/65536 bytes at offset 0 + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 197120, "offset": 197120, "speed": 0, "type": "mirror"}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}} +-Warning: Image size mismatch! + Images are identical. + + === Writing a qed header into raw === + +-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 + Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864 ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE + { 'execute': 'qmp_capabilities' } + {"return": {}} + {'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}} +@@ -115,8 +113,8 @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed + {"execute":"quit"} + {"return": {}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +-read 65536/65536 bytes at offset 0 +-64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++read 512/512 bytes at offset 0 ++512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + { 'execute': 'qmp_capabilities' } + {"return": {}} + {'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}} +@@ -135,13 +133,12 @@ read 65536/65536 bytes at offset 0 + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 327680, "offset": 327680, "speed": 0, "type": "mirror"}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}} +-Warning: Image size mismatch! + Images are identical. + + === Writing a vdi header into raw === + +-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 + Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864 ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE + { 'execute': 'qmp_capabilities' } + {"return": {}} + {'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}} +@@ -161,8 +158,8 @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed + {"execute":"quit"} + {"return": {}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +-read 65536/65536 bytes at offset 0 +-64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++read 512/512 bytes at offset 0 ++512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + { 'execute': 'qmp_capabilities' } + {"return": {}} + {'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}} +@@ -181,13 +178,12 @@ read 65536/65536 bytes at offset 0 + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 1024, "offset": 1024, "speed": 0, "type": "mirror"}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}} +-Warning: Image size mismatch! + Images are identical. + + === Writing a vmdk header into raw === + +-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 + Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864 ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE + { 'execute': 'qmp_capabilities' } + {"return": {}} + {'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}} +@@ -207,8 +203,8 @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed + {"execute":"quit"} + {"return": {}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +-read 65536/65536 bytes at offset 0 +-64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++read 512/512 bytes at offset 0 ++512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + { 'execute': 'qmp_capabilities' } + {"return": {}} + {'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}} +@@ -227,13 +223,12 @@ read 65536/65536 bytes at offset 0 + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 65536, "offset": 65536, "speed": 0, "type": "mirror"}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}} +-Warning: Image size mismatch! + Images are identical. + + === Writing a vpc header into raw === + +-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 + Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864 ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE + { 'execute': 'qmp_capabilities' } + {"return": {}} + {'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}} +@@ -253,8 +248,8 @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed + {"execute":"quit"} + {"return": {}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +-read 65536/65536 bytes at offset 0 +-64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++read 512/512 bytes at offset 0 ++512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + { 'execute': 'qmp_capabilities' } + {"return": {}} + {'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}} +@@ -273,12 +268,11 @@ read 65536/65536 bytes at offset 0 + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 2560, "offset": 2560, "speed": 0, "type": "mirror"}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}} +-Warning: Image size mismatch! + Images are identical. + + === Copying sample image empty.bochs into raw === + +-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE + { 'execute': 'qmp_capabilities' } + {"return": {}} + {'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}} +@@ -298,8 +292,8 @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed + {"execute":"quit"} + {"return": {}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +-read 65536/65536 bytes at offset 0 +-64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++read 512/512 bytes at offset 0 ++512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + { 'execute': 'qmp_capabilities' } + {"return": {}} + {'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}} +@@ -318,12 +312,11 @@ read 65536/65536 bytes at offset 0 + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 2560, "offset": 2560, "speed": 0, "type": "mirror"}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}} +-Warning: Image size mismatch! + Images are identical. + + === Copying sample image iotest-dirtylog-10G-4M.vhdx into raw === + +-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE + { 'execute': 'qmp_capabilities' } + {"return": {}} + {'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}} +@@ -343,8 +336,8 @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed + {"execute":"quit"} + {"return": {}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +-read 65536/65536 bytes at offset 0 +-64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++read 512/512 bytes at offset 0 ++512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + { 'execute': 'qmp_capabilities' } + {"return": {}} + {'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}} +@@ -363,12 +356,11 @@ read 65536/65536 bytes at offset 0 + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 31457280, "offset": 31457280, "speed": 0, "type": "mirror"}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}} +-Warning: Image size mismatch! + Images are identical. + + === Copying sample image parallels-v1 into raw === + +-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE + { 'execute': 'qmp_capabilities' } + {"return": {}} + {'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}} +@@ -388,8 +380,8 @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed + {"execute":"quit"} + {"return": {}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +-read 65536/65536 bytes at offset 0 +-64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++read 512/512 bytes at offset 0 ++512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + { 'execute': 'qmp_capabilities' } + {"return": {}} + {'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}} +@@ -408,12 +400,11 @@ read 65536/65536 bytes at offset 0 + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 327680, "offset": 327680, "speed": 0, "type": "mirror"}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}} +-Warning: Image size mismatch! + Images are identical. + + === Copying sample image simple-pattern.cloop into raw === + +-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE + { 'execute': 'qmp_capabilities' } + {"return": {}} + {'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}} +@@ -433,8 +424,8 @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed + {"execute":"quit"} + {"return": {}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +-read 65536/65536 bytes at offset 0 +-64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++read 512/512 bytes at offset 0 ++512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + { 'execute': 'qmp_capabilities' } + {"return": {}} + {'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}} +@@ -453,12 +444,11 @@ read 65536/65536 bytes at offset 0 + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 2048, "offset": 2048, "speed": 0, "type": "mirror"}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}} +-Warning: Image size mismatch! + Images are identical. + + === Write legitimate MBR into raw === + +-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE + { 'execute': 'qmp_capabilities' } + {"return": {}} + {'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}} +@@ -480,7 +470,6 @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 512, "offset": 512, "speed": 0, "type": "mirror"}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}} +-Warning: Image size mismatch! + Images are identical. + { 'execute': 'qmp_capabilities' } + {"return": {}} +@@ -500,6 +489,5 @@ Images are identical. + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 512, "offset": 512, "speed": 0, "type": "mirror"}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}} +-Warning: Image size mismatch! + Images are identical. + *** done +diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter +index 5367dee..c8e8663 100644 +--- a/tests/qemu-iotests/common.filter ++++ b/tests/qemu-iotests/common.filter +@@ -149,6 +149,11 @@ _filter_img_create() + -e "s# force_size=\\(on\\|off\\)##g" + } + ++_filter_img_create_size() ++{ ++ $SED -e "s# size=[0-9]\\+# size=SIZE#g" ++} ++ + _filter_img_info() + { + if [[ "$1" == "--format-specific" ]]; then +-- +1.8.3.1 + diff --git a/SOURCES/kvm-iotests-229-Use-blkdebug-to-inject-an-error.patch b/SOURCES/kvm-iotests-229-Use-blkdebug-to-inject-an-error.patch new file mode 100644 index 0000000..ef8807c --- /dev/null +++ b/SOURCES/kvm-iotests-229-Use-blkdebug-to-inject-an-error.patch @@ -0,0 +1,120 @@ +From 104c8f6210bf573cf39c2a14cdb0b081baaaa3f0 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Wed, 3 Jun 2020 16:03:23 +0100 +Subject: [PATCH 24/26] iotests/229: Use blkdebug to inject an error + +RH-Author: Kevin Wolf +Message-id: <20200603160325.67506-10-kwolf@redhat.com> +Patchwork-id: 97108 +O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH v2 09/11] iotests/229: Use blkdebug to inject an error +Bugzilla: 1778593 +RH-Acked-by: Eric Blake +RH-Acked-by: Max Reitz +RH-Acked-by: Stefano Garzarella + +229 relies on the mirror running into an I/O error when the target is +smaller than the source. After changing mirror to catch this condition +while starting the job, this test case won't get a job that is paused +for an I/O error any more. Use blkdebug instead to inject an error. + +Signed-off-by: Kevin Wolf +Reviewed-by: Eric Blake +Message-Id: <20200511135825.219437-3-kwolf@redhat.com> +Reviewed-by: Max Reitz +Reviewed-by: Vladimir Sementsov-Ogievskiy +Signed-off-by: Kevin Wolf +(cherry picked from commit d89ac3cf305b28c024a76805a84d75c0ee1e786f) +Signed-off-by: Kevin Wolf +Signed-off-by: Danilo C. L. de Paula +--- + tests/qemu-iotests/229 | 18 +++++++++++++----- + tests/qemu-iotests/229.out | 6 +++--- + 2 files changed, 16 insertions(+), 8 deletions(-) + +diff --git a/tests/qemu-iotests/229 b/tests/qemu-iotests/229 +index e18a464..511fbc0 100755 +--- a/tests/qemu-iotests/229 ++++ b/tests/qemu-iotests/229 +@@ -32,6 +32,7 @@ _cleanup() + _cleanup_qemu + _cleanup_test_img + rm -f "$TEST_IMG" "$DEST_IMG" ++ rm -f "$TEST_DIR/blkdebug.conf" + } + trap "_cleanup; exit \$status" 0 1 2 3 15 + +@@ -48,11 +49,10 @@ _supported_os Linux + + DEST_IMG="$TEST_DIR/d.$IMGFMT" + TEST_IMG="$TEST_DIR/b.$IMGFMT" ++BLKDEBUG_CONF="$TEST_DIR/blkdebug.conf" + + _make_test_img 2M +- +-# destination for mirror will be too small, causing error +-TEST_IMG=$DEST_IMG _make_test_img 1M ++TEST_IMG=$DEST_IMG _make_test_img 2M + + $QEMU_IO -c 'write 0 2M' "$TEST_IMG" | _filter_qemu_io + +@@ -66,11 +66,18 @@ echo + echo '=== Starting drive-mirror, causing error & stop ===' + echo + ++cat > "$BLKDEBUG_CONF" < +Date: Wed, 3 Jun 2020 16:03:15 +0100 +Subject: [PATCH 16/26] iotests: Add more "skip_if_unsupported" statements to + the python tests + +RH-Author: Kevin Wolf +Message-id: <20200603160325.67506-2-kwolf@redhat.com> +Patchwork-id: 97099 +O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH v2 01/11] iotests: Add more "skip_if_unsupported" statements to the python tests +Bugzilla: 1778593 +RH-Acked-by: Eric Blake +RH-Acked-by: Max Reitz +RH-Acked-by: Stefano Garzarella + +From: Thomas Huth + +The python code already contains a possibility to skip tests if the +corresponding driver is not available in the qemu binary - use it +in more spots to avoid that the tests are failing if the driver has +been disabled. + +While we're at it, we can now also remove some of the old checks that +were using iotests.supports_quorum() - and which were apparently not +working as expected since the tests aborted instead of being skipped +when "quorum" was missing in the QEMU binary. + +Signed-off-by: Thomas Huth +Signed-off-by: Kevin Wolf +(cherry picked from commit 9442bebe6e67a5d038bbf2572b79e7b59d202a23) +Signed-off-by: Kevin Wolf +Signed-off-by: Danilo C. L. de Paula +--- + tests/qemu-iotests/030 | 4 +--- + tests/qemu-iotests/040 | 2 ++ + tests/qemu-iotests/041 | 39 +++------------------------------------ + tests/qemu-iotests/245 | 2 ++ + 4 files changed, 8 insertions(+), 39 deletions(-) + +diff --git a/tests/qemu-iotests/030 b/tests/qemu-iotests/030 +index f3766f2..bddbb30 100755 +--- a/tests/qemu-iotests/030 ++++ b/tests/qemu-iotests/030 +@@ -530,6 +530,7 @@ class TestQuorum(iotests.QMPTestCase): + children = [] + backing = [] + ++ @iotests.skip_if_unsupported(['quorum']) + def setUp(self): + opts = ['driver=quorum', 'vote-threshold=2'] + +@@ -560,9 +561,6 @@ class TestQuorum(iotests.QMPTestCase): + os.remove(img) + + def test_stream_quorum(self): +- if not iotests.supports_quorum(): +- return +- + self.assertNotEqual(qemu_io('-f', iotests.imgfmt, '-rU', '-c', 'map', self.children[0]), + qemu_io('-f', iotests.imgfmt, '-rU', '-c', 'map', self.backing[0]), + 'image file map matches backing file before streaming') +diff --git a/tests/qemu-iotests/040 b/tests/qemu-iotests/040 +index 762ad1e..74f62c3 100755 +--- a/tests/qemu-iotests/040 ++++ b/tests/qemu-iotests/040 +@@ -106,6 +106,7 @@ class TestSingleDrive(ImageCommitTestCase): + self.assertEqual(-1, qemu_io('-f', 'raw', '-c', 'read -P 0xab 0 524288', backing_img).find("verification failed")) + self.assertEqual(-1, qemu_io('-f', 'raw', '-c', 'read -P 0xef 524288 524288', backing_img).find("verification failed")) + ++ @iotests.skip_if_unsupported(['throttle']) + def test_commit_with_filter_and_quit(self): + result = self.vm.qmp('object-add', qom_type='throttle-group', id='tg') + self.assert_qmp(result, 'return', {}) +@@ -125,6 +126,7 @@ class TestSingleDrive(ImageCommitTestCase): + self.has_quit = True + + # Same as above, but this time we add the filter after starting the job ++ @iotests.skip_if_unsupported(['throttle']) + def test_commit_plus_filter_and_quit(self): + result = self.vm.qmp('object-add', qom_type='throttle-group', id='tg') + self.assert_qmp(result, 'return', {}) +diff --git a/tests/qemu-iotests/041 b/tests/qemu-iotests/041 +index 8568426..a543b15 100755 +--- a/tests/qemu-iotests/041 ++++ b/tests/qemu-iotests/041 +@@ -871,6 +871,7 @@ class TestRepairQuorum(iotests.QMPTestCase): + image_len = 1 * 1024 * 1024 # MB + IMAGES = [ quorum_img1, quorum_img2, quorum_img3 ] + ++ @iotests.skip_if_unsupported(['quorum']) + def setUp(self): + self.vm = iotests.VM() + +@@ -891,9 +892,8 @@ class TestRepairQuorum(iotests.QMPTestCase): + #assemble the quorum block device from the individual files + args = { "driver": "quorum", "node-name": "quorum0", + "vote-threshold": 2, "children": [ "img0", "img1", "img2" ] } +- if iotests.supports_quorum(): +- result = self.vm.qmp("blockdev-add", **args) +- self.assert_qmp(result, 'return', {}) ++ result = self.vm.qmp("blockdev-add", **args) ++ self.assert_qmp(result, 'return', {}) + + + def tearDown(self): +@@ -906,9 +906,6 @@ class TestRepairQuorum(iotests.QMPTestCase): + pass + + def test_complete(self): +- if not iotests.supports_quorum(): +- return +- + self.assert_no_active_block_jobs() + + result = self.vm.qmp('drive-mirror', job_id='job0', device='quorum0', +@@ -925,9 +922,6 @@ class TestRepairQuorum(iotests.QMPTestCase): + 'target image does not match source after mirroring') + + def test_cancel(self): +- if not iotests.supports_quorum(): +- return +- + self.assert_no_active_block_jobs() + + result = self.vm.qmp('drive-mirror', job_id='job0', device='quorum0', +@@ -942,9 +936,6 @@ class TestRepairQuorum(iotests.QMPTestCase): + self.vm.shutdown() + + def test_cancel_after_ready(self): +- if not iotests.supports_quorum(): +- return +- + self.assert_no_active_block_jobs() + + result = self.vm.qmp('drive-mirror', job_id='job0', device='quorum0', +@@ -961,9 +952,6 @@ class TestRepairQuorum(iotests.QMPTestCase): + 'target image does not match source after mirroring') + + def test_pause(self): +- if not iotests.supports_quorum(): +- return +- + self.assert_no_active_block_jobs() + + result = self.vm.qmp('drive-mirror', job_id='job0', device='quorum0', +@@ -989,9 +977,6 @@ class TestRepairQuorum(iotests.QMPTestCase): + 'target image does not match source after mirroring') + + def test_medium_not_found(self): +- if not iotests.supports_quorum(): +- return +- + if iotests.qemu_default_machine != 'pc': + return + +@@ -1003,9 +988,6 @@ class TestRepairQuorum(iotests.QMPTestCase): + self.assert_qmp(result, 'error/class', 'GenericError') + + def test_image_not_found(self): +- if not iotests.supports_quorum(): +- return +- + result = self.vm.qmp('drive-mirror', job_id='job0', device='quorum0', + sync='full', node_name='repair0', replaces='img1', + mode='existing', target=quorum_repair_img, +@@ -1013,9 +995,6 @@ class TestRepairQuorum(iotests.QMPTestCase): + self.assert_qmp(result, 'error/class', 'GenericError') + + def test_device_not_found(self): +- if not iotests.supports_quorum(): +- return +- + result = self.vm.qmp('drive-mirror', job_id='job0', + device='nonexistent', sync='full', + node_name='repair0', +@@ -1024,9 +1003,6 @@ class TestRepairQuorum(iotests.QMPTestCase): + self.assert_qmp(result, 'error/class', 'GenericError') + + def test_wrong_sync_mode(self): +- if not iotests.supports_quorum(): +- return +- + result = self.vm.qmp('drive-mirror', device='quorum0', job_id='job0', + node_name='repair0', + replaces='img1', +@@ -1034,27 +1010,18 @@ class TestRepairQuorum(iotests.QMPTestCase): + self.assert_qmp(result, 'error/class', 'GenericError') + + def test_no_node_name(self): +- if not iotests.supports_quorum(): +- return +- + result = self.vm.qmp('drive-mirror', job_id='job0', device='quorum0', + sync='full', replaces='img1', + target=quorum_repair_img, format=iotests.imgfmt) + self.assert_qmp(result, 'error/class', 'GenericError') + + def test_nonexistent_replaces(self): +- if not iotests.supports_quorum(): +- return +- + result = self.vm.qmp('drive-mirror', job_id='job0', device='quorum0', + sync='full', node_name='repair0', replaces='img77', + target=quorum_repair_img, format=iotests.imgfmt) + self.assert_qmp(result, 'error/class', 'GenericError') + + def test_after_a_quorum_snapshot(self): +- if not iotests.supports_quorum(): +- return +- + result = self.vm.qmp('blockdev-snapshot-sync', node_name='img1', + snapshot_file=quorum_snapshot_file, + snapshot_node_name="snap1"); +diff --git a/tests/qemu-iotests/245 b/tests/qemu-iotests/245 +index 919131d..ed972f9 100644 +--- a/tests/qemu-iotests/245 ++++ b/tests/qemu-iotests/245 +@@ -478,6 +478,7 @@ class TestBlockdevReopen(iotests.QMPTestCase): + # This test verifies that we can't change the children of a block + # device during a reopen operation in a way that would create + # cycles in the node graph ++ @iotests.skip_if_unsupported(['blkverify']) + def test_graph_cycles(self): + opts = [] + +@@ -534,6 +535,7 @@ class TestBlockdevReopen(iotests.QMPTestCase): + self.assert_qmp(result, 'return', {}) + + # Misc reopen tests with different block drivers ++ @iotests.skip_if_unsupported(['quorum', 'throttle']) + def test_misc_drivers(self): + #################### + ###### quorum ###### +-- +1.8.3.1 + diff --git a/SOURCES/kvm-iotests-Add-qemu_io_log.patch b/SOURCES/kvm-iotests-Add-qemu_io_log.patch new file mode 100644 index 0000000..a65bc5a --- /dev/null +++ b/SOURCES/kvm-iotests-Add-qemu_io_log.patch @@ -0,0 +1,48 @@ +From 2be333e847c01397bb6a92b2e4c60e904957675d Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Mon, 8 Jun 2020 15:01:37 +0100 +Subject: [PATCH 09/17] iotests: Add qemu_io_log() + +RH-Author: Kevin Wolf +Message-id: <20200608150140.38218-9-kwolf@redhat.com> +Patchwork-id: 97451 +O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH 08/11] iotests: Add qemu_io_log() +Bugzilla: 1780574 +RH-Acked-by: Sergio Lopez Pascual +RH-Acked-by: Eric Blake +RH-Acked-by: Max Reitz + +Add a function that runs qemu-io and logs the output with the +appropriate filters applied. + +Signed-off-by: Kevin Wolf +Reviewed-by: Eric Blake +Reviewed-by: Vladimir Sementsov-Ogievskiy +Reviewed-by: Alberto Garcia +Reviewed-by: Stefan Hajnoczi +(cherry picked from commit a96f0350e3d95c98f2bff1863d14493af5c1d360) +Signed-off-by: Kevin Wolf +Signed-off-by: Danilo C. L. de Paula +--- + tests/qemu-iotests/iotests.py | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py +index be20d56..7a9c779 100644 +--- a/tests/qemu-iotests/iotests.py ++++ b/tests/qemu-iotests/iotests.py +@@ -162,6 +162,11 @@ def qemu_io(*args): + sys.stderr.write('qemu-io received signal %i: %s\n' % (-exitcode, ' '.join(args))) + return subp.communicate()[0] + ++def qemu_io_log(*args): ++ result = qemu_io(*args) ++ log(result, filters=[filter_testfiles, filter_qemu_io]) ++ return result ++ + def qemu_io_silent(*args): + '''Run qemu-io and return the exit code, suppressing stdout''' + args = qemu_io_args + list(args) +-- +1.8.3.1 + diff --git a/SOURCES/kvm-iotests-Add-test-291-to-for-qemu-img-bitmap-coverage.patch b/SOURCES/kvm-iotests-Add-test-291-to-for-qemu-img-bitmap-coverage.patch new file mode 100644 index 0000000..6144043 --- /dev/null +++ b/SOURCES/kvm-iotests-Add-test-291-to-for-qemu-img-bitmap-coverage.patch @@ -0,0 +1,253 @@ +From eccae2f252513d2965ef919022c3ed068da275bd Mon Sep 17 00:00:00 2001 +From: Eric Blake +Date: Tue, 2 Jun 2020 02:34:20 +0100 +Subject: [PATCH 15/26] iotests: Add test 291 to for qemu-img bitmap coverage + +RH-Author: Eric Blake +Message-id: <20200602023420.2133649-13-eblake@redhat.com> +Patchwork-id: 97079 +O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH 12/12] iotests: Add test 291 to for qemu-img bitmap coverage +Bugzilla: 1779893 1779904 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Max Reitz +RH-Acked-by: Kevin Wolf + +Add a new test covering the 'qemu-img bitmap' subcommand, as well as +'qemu-img convert --bitmaps', both added in recent patches. + +Signed-off-by: Eric Blake +Reviewed-by: Max Reitz +Reviewed-by: Vladimir Sementsov-Ogievskiy +Message-Id: <20200521192137.1120211-6-eblake@redhat.com> +(cherry picked from commit cf2d1203dcfc2bf964453d83a2302231ce77f2dc) + +Signed-off-by: Danilo C. L. de Paula + +Conflicts: + tests/qemu-iotests/group - context: other tests not backported + tests/qemu-iotests/291.out - zstd compression not backported +Signed-off-by: Eric Blake + +Signed-off-by: Danilo C. L. de Paula +--- + tests/qemu-iotests/291 | 112 +++++++++++++++++++++++++++++++++++++++++++++ + tests/qemu-iotests/291.out | 78 +++++++++++++++++++++++++++++++ + tests/qemu-iotests/group | 1 + + 3 files changed, 191 insertions(+) + create mode 100755 tests/qemu-iotests/291 + create mode 100644 tests/qemu-iotests/291.out + +diff --git a/tests/qemu-iotests/291 b/tests/qemu-iotests/291 +new file mode 100755 +index 0000000..3ca83b9 +--- /dev/null ++++ b/tests/qemu-iotests/291 +@@ -0,0 +1,112 @@ ++#!/usr/bin/env bash ++# ++# Test qemu-img bitmap handling ++# ++# Copyright (C) 2018-2020 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 ++ nbd_server_stop ++} ++trap "_cleanup; exit \$status" 0 1 2 3 15 ++ ++# get standard environment, filters and checks ++. ./common.rc ++. ./common.filter ++. ./common.nbd ++ ++_supported_fmt qcow2 ++_supported_proto file ++_supported_os Linux ++_require_command QEMU_NBD ++ ++echo ++echo "=== Initial image setup ===" ++echo ++ ++# Create backing image with one bitmap ++TEST_IMG="$TEST_IMG.base" _make_test_img 10M ++$QEMU_IMG bitmap --add -f $IMGFMT "$TEST_IMG.base" b0 ++$QEMU_IO -c 'w 3M 1M' -f $IMGFMT "$TEST_IMG.base" | _filter_qemu_io ++ ++# Create initial image and populate two bitmaps: one active, one inactive. ++ORIG_IMG=$TEST_IMG ++TEST_IMG=$TEST_IMG.orig ++_make_test_img -b "$ORIG_IMG.base" -F $IMGFMT 10M ++$QEMU_IO -c 'w 0 1M' -f $IMGFMT "$TEST_IMG" | _filter_qemu_io ++$QEMU_IMG bitmap --add -g 512k -f $IMGFMT "$TEST_IMG" b1 ++$QEMU_IMG bitmap --add --disable -f $IMGFMT "$TEST_IMG" b2 ++$QEMU_IO -c 'w 3M 1M' -f $IMGFMT "$TEST_IMG" | _filter_qemu_io ++$QEMU_IMG bitmap --clear -f $IMGFMT "$TEST_IMG" b1 ++$QEMU_IO -c 'w 1M 1M' -f $IMGFMT "$TEST_IMG" | _filter_qemu_io ++$QEMU_IMG bitmap --disable -f $IMGFMT "$TEST_IMG" b1 ++$QEMU_IMG bitmap --enable -f $IMGFMT "$TEST_IMG" b2 ++$QEMU_IO -c 'w 2M 1M' -f $IMGFMT "$TEST_IMG" | _filter_qemu_io ++ ++echo ++echo "=== Bitmap preservation not possible to non-qcow2 ===" ++echo ++ ++TEST_IMG=$ORIG_IMG ++$QEMU_IMG convert --bitmaps -O raw "$TEST_IMG.orig" "$TEST_IMG" && ++ echo "unexpected success" ++ ++echo ++echo "=== Convert with bitmap preservation ===" ++echo ++ ++# Only bitmaps from the active layer are copied ++$QEMU_IMG convert --bitmaps -O qcow2 "$TEST_IMG.orig" "$TEST_IMG" ++$QEMU_IMG info "$TEST_IMG" | _filter_img_info --format-specific ++# But we can also merge in bitmaps from other layers. This test is a bit ++# contrived to cover more code paths, in reality, you could merge directly ++# into b0 without going through tmp ++$QEMU_IMG bitmap --add --disable -f $IMGFMT "$TEST_IMG" b0 ++$QEMU_IMG bitmap --add --merge b0 -b "$TEST_IMG.base" -F $IMGFMT \ ++ -f $IMGFMT "$TEST_IMG" tmp ++$QEMU_IMG bitmap --merge tmp -f $IMGFMT "$TEST_IMG" b0 ++$QEMU_IMG bitmap --remove --image-opts \ ++ driver=$IMGFMT,file.driver=file,file.filename="$TEST_IMG" tmp ++$QEMU_IMG info "$TEST_IMG" | _filter_img_info --format-specific ++ ++echo ++echo "=== Check bitmap contents ===" ++echo ++ ++# x-dirty-bitmap is a hack for reading bitmaps; it abuses block status to ++# report "data":false for portions of the bitmap which are set ++IMG="driver=nbd,server.type=unix,server.path=$nbd_unix_socket" ++nbd_server_start_unix_socket -r -f qcow2 -B b0 "$TEST_IMG" ++$QEMU_IMG map --output=json --image-opts \ ++ "$IMG,x-dirty-bitmap=qemu:dirty-bitmap:b0" | _filter_qemu_img_map ++nbd_server_start_unix_socket -r -f qcow2 -B b1 "$TEST_IMG" ++$QEMU_IMG map --output=json --image-opts \ ++ "$IMG,x-dirty-bitmap=qemu:dirty-bitmap:b1" | _filter_qemu_img_map ++nbd_server_start_unix_socket -r -f qcow2 -B b2 "$TEST_IMG" ++$QEMU_IMG map --output=json --image-opts \ ++ "$IMG,x-dirty-bitmap=qemu:dirty-bitmap:b2" | _filter_qemu_img_map ++ ++# success, all done ++echo '*** done' ++rm -f $seq.full ++status=0 +diff --git a/tests/qemu-iotests/291.out b/tests/qemu-iotests/291.out +new file mode 100644 +index 0000000..14e5cfc +--- /dev/null ++++ b/tests/qemu-iotests/291.out +@@ -0,0 +1,78 @@ ++QA output created by 291 ++ ++=== Initial image setup === ++ ++Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=10485760 ++wrote 1048576/1048576 bytes at offset 3145728 ++1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++Formatting 'TEST_DIR/t.IMGFMT.orig', fmt=IMGFMT size=10485760 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT ++wrote 1048576/1048576 bytes at offset 0 ++1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++wrote 1048576/1048576 bytes at offset 3145728 ++1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++wrote 1048576/1048576 bytes at offset 1048576 ++1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++wrote 1048576/1048576 bytes at offset 2097152 ++1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++=== Bitmap preservation not possible to non-qcow2 === ++ ++qemu-img: Format driver 'raw' does not support bitmaps ++ ++=== Convert with bitmap preservation === ++ ++image: TEST_DIR/t.IMGFMT ++file format: IMGFMT ++virtual size: 10 MiB (10485760 bytes) ++disk size: 4.39 MiB ++Format specific information: ++ compat: 1.1 ++ lazy refcounts: false ++ bitmaps: ++ [0]: ++ flags: ++ name: b1 ++ granularity: 524288 ++ [1]: ++ flags: ++ [0]: auto ++ name: b2 ++ granularity: 65536 ++ refcount bits: 16 ++ corrupt: false ++image: TEST_DIR/t.IMGFMT ++file format: IMGFMT ++virtual size: 10 MiB (10485760 bytes) ++disk size: 4.48 MiB ++Format specific information: ++ compat: 1.1 ++ lazy refcounts: false ++ bitmaps: ++ [0]: ++ flags: ++ name: b1 ++ granularity: 524288 ++ [1]: ++ flags: ++ [0]: auto ++ name: b2 ++ granularity: 65536 ++ [2]: ++ flags: ++ name: b0 ++ granularity: 65536 ++ refcount bits: 16 ++ corrupt: false ++ ++=== Check bitmap contents === ++ ++[{ "start": 0, "length": 3145728, "depth": 0, "zero": false, "data": true, "offset": OFFSET}, ++{ "start": 3145728, "length": 1048576, "depth": 0, "zero": false, "data": false}, ++{ "start": 4194304, "length": 6291456, "depth": 0, "zero": false, "data": true, "offset": OFFSET}] ++[{ "start": 0, "length": 1048576, "depth": 0, "zero": false, "data": true, "offset": OFFSET}, ++{ "start": 1048576, "length": 1048576, "depth": 0, "zero": false, "data": false}, ++{ "start": 2097152, "length": 8388608, "depth": 0, "zero": false, "data": true, "offset": OFFSET}] ++[{ "start": 0, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET}, ++{ "start": 2097152, "length": 1048576, "depth": 0, "zero": false, "data": false}, ++{ "start": 3145728, "length": 7340032, "depth": 0, "zero": false, "data": true, "offset": OFFSET}] ++*** done +diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group +index 9c565cf..033b54d 100644 +--- a/tests/qemu-iotests/group ++++ b/tests/qemu-iotests/group +@@ -290,3 +290,4 @@ + 280 rw migration quick + 281 rw quick + 284 rw ++291 rw quick +-- +1.8.3.1 + diff --git a/SOURCES/kvm-iotests-Backup-with-different-source-target-size.patch b/SOURCES/kvm-iotests-Backup-with-different-source-target-size.patch new file mode 100644 index 0000000..4008413 --- /dev/null +++ b/SOURCES/kvm-iotests-Backup-with-different-source-target-size.patch @@ -0,0 +1,105 @@ +From 456c5e79c32e3f2f9319a7d1452fe523aded7835 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Wed, 3 Jun 2020 16:03:21 +0100 +Subject: [PATCH 22/26] iotests: Backup with different source/target size + +RH-Author: Kevin Wolf +Message-id: <20200603160325.67506-8-kwolf@redhat.com> +Patchwork-id: 97106 +O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH v2 07/11] iotests: Backup with different source/target size +Bugzilla: 1778593 +RH-Acked-by: Eric Blake +RH-Acked-by: Max Reitz +RH-Acked-by: Stefano Garzarella + +This tests that the backup job catches situations where the target node +has a different size than the source node. It must also forbid resize +operations when the job is already running. + +Signed-off-by: Kevin Wolf +Message-Id: <20200430142755.315494-5-kwolf@redhat.com> +Reviewed-by: Vladimir Sementsov-Ogievskiy +Signed-off-by: Kevin Wolf +(cherry picked from commit 0a82a9273062d05764e3df3637b3aa95ad8291c6) +Signed-off-by: Kevin Wolf +Signed-off-by: Danilo C. L. de Paula +--- + tests/qemu-iotests/055 | 42 ++++++++++++++++++++++++++++++++++++++++-- + tests/qemu-iotests/055.out | 4 ++-- + 2 files changed, 42 insertions(+), 4 deletions(-) + +diff --git a/tests/qemu-iotests/055 b/tests/qemu-iotests/055 +index c9cdc06..1c70389 100755 +--- a/tests/qemu-iotests/055 ++++ b/tests/qemu-iotests/055 +@@ -48,8 +48,10 @@ class TestSingleDrive(iotests.QMPTestCase): + def setUp(self): + qemu_img('create', '-f', iotests.imgfmt, blockdev_target_img, str(image_len)) + +- self.vm = iotests.VM().add_drive('blkdebug::' + test_img) +- self.vm.add_drive(blockdev_target_img, interface="none") ++ self.vm = iotests.VM() ++ self.vm.add_drive('blkdebug::' + test_img, 'node-name=source') ++ self.vm.add_drive(blockdev_target_img, 'node-name=target', ++ interface="none") + if iotests.qemu_default_machine == 'pc': + self.vm.add_drive(None, 'media=cdrom', 'ide') + self.vm.launch() +@@ -112,6 +114,42 @@ class TestSingleDrive(iotests.QMPTestCase): + def test_pause_blockdev_backup(self): + self.do_test_pause('blockdev-backup', 'drive1', blockdev_target_img) + ++ def do_test_resize_blockdev_backup(self, device, node): ++ def pre_finalize(): ++ result = self.vm.qmp('block_resize', device=device, size=65536) ++ self.assert_qmp(result, 'error/class', 'GenericError') ++ ++ result = self.vm.qmp('block_resize', node_name=node, size=65536) ++ self.assert_qmp(result, 'error/class', 'GenericError') ++ ++ result = self.vm.qmp('blockdev-backup', job_id='job0', device='drive0', ++ target='drive1', sync='full', auto_finalize=False, ++ auto_dismiss=False) ++ self.assert_qmp(result, 'return', {}) ++ ++ self.vm.run_job('job0', auto_finalize=False, pre_finalize=pre_finalize, ++ use_log=False) ++ ++ def test_source_resize_blockdev_backup(self): ++ self.do_test_resize_blockdev_backup('drive0', 'source') ++ ++ def test_target_resize_blockdev_backup(self): ++ self.do_test_resize_blockdev_backup('drive1', 'target') ++ ++ def do_test_target_size(self, size): ++ result = self.vm.qmp('block_resize', device='drive1', size=size) ++ self.assert_qmp(result, 'return', {}) ++ ++ result = self.vm.qmp('blockdev-backup', job_id='job0', device='drive0', ++ target='drive1', sync='full') ++ self.assert_qmp(result, 'error/class', 'GenericError') ++ ++ def test_small_target(self): ++ self.do_test_target_size(image_len // 2) ++ ++ def test_large_target(self): ++ self.do_test_target_size(image_len * 2) ++ + def test_medium_not_found(self): + if iotests.qemu_default_machine != 'pc': + return +diff --git a/tests/qemu-iotests/055.out b/tests/qemu-iotests/055.out +index 5c26d15..0a5e958 100644 +--- a/tests/qemu-iotests/055.out ++++ b/tests/qemu-iotests/055.out +@@ -1,5 +1,5 @@ +-.................................... ++........................................ + ---------------------------------------------------------------------- +-Ran 36 tests ++Ran 40 tests + + OK +-- +1.8.3.1 + diff --git a/SOURCES/kvm-iotests-Filter-testfiles-out-in-filter_img_info.patch b/SOURCES/kvm-iotests-Filter-testfiles-out-in-filter_img_info.patch new file mode 100644 index 0000000..60c08ec --- /dev/null +++ b/SOURCES/kvm-iotests-Filter-testfiles-out-in-filter_img_info.patch @@ -0,0 +1,52 @@ +From 8dc8a17d4e98aae41db01cbc073e69de44291b63 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Mon, 8 Jun 2020 15:01:38 +0100 +Subject: [PATCH 10/17] iotests: Filter testfiles out in filter_img_info() + +RH-Author: Kevin Wolf +Message-id: <20200608150140.38218-10-kwolf@redhat.com> +Patchwork-id: 97455 +O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH 09/11] iotests: Filter testfiles out in filter_img_info() +Bugzilla: 1780574 +RH-Acked-by: Sergio Lopez Pascual +RH-Acked-by: Eric Blake +RH-Acked-by: Max Reitz + +We want to keep TEST_IMG for the full path of the main test image, but +filter_testfiles() must be called for other test images before replacing +other things like the image format because the test directory path could +contain the format as a substring. + +Insert a filter_testfiles() call between both. + +Signed-off-by: Kevin Wolf +Reviewed-by: Max Reitz +Reviewed-by: Vladimir Sementsov-Ogievskiy +Message-Id: <20200424125448.63318-9-kwolf@redhat.com> +Signed-off-by: Kevin Wolf +(cherry picked from commit fd586ce8bee50d98773436214dc9e644ddda54aa) +Signed-off-by: Kevin Wolf +Signed-off-by: Danilo C. L. de Paula +--- + tests/qemu-iotests/iotests.py | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py +index 7a9c779..cd5df36 100644 +--- a/tests/qemu-iotests/iotests.py ++++ b/tests/qemu-iotests/iotests.py +@@ -335,8 +335,9 @@ def filter_img_info(output, filename): + for line in output.split('\n'): + if 'disk size' in line or 'actual-size' in line: + continue +- line = line.replace(filename, 'TEST_IMG') \ +- .replace(imgfmt, 'IMGFMT') ++ line = line.replace(filename, 'TEST_IMG') ++ line = filter_testfiles(line) ++ line = line.replace(imgfmt, 'IMGFMT') + line = re.sub('iters: [0-9]+', 'iters: XXX', line) + line = re.sub('uuid: [-a-f0-9]+', 'uuid: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX', line) + line = re.sub('cid: [0-9]+', 'cid: XXXXXXXXXX', line) +-- +1.8.3.1 + diff --git a/SOURCES/kvm-iotests-Fix-test-178.patch b/SOURCES/kvm-iotests-Fix-test-178.patch new file mode 100644 index 0000000..5e54daa --- /dev/null +++ b/SOURCES/kvm-iotests-Fix-test-178.patch @@ -0,0 +1,59 @@ +From a04d324e41a40a6893bc94109994afc017f17192 Mon Sep 17 00:00:00 2001 +From: Eric Blake +Date: Tue, 2 Jun 2020 02:34:16 +0100 +Subject: [PATCH 11/26] iotests: Fix test 178 + +RH-Author: Eric Blake +Message-id: <20200602023420.2133649-9-eblake@redhat.com> +Patchwork-id: 97075 +O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH 08/12] iotests: Fix test 178 +Bugzilla: 1779893 1779904 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Max Reitz +RH-Acked-by: Kevin Wolf + +A recent change to qemu-img changed expected error message output, but +178 takes long enough to execute that it does not get run by 'make +check' or './check -g quick'. + +Fixes: 43d589b074 +Signed-off-by: Eric Blake +Reviewed-by: Vladimir Sementsov-Ogievskiy +Message-Id: <20200521192137.1120211-2-eblake@redhat.com> +(cherry picked from commit ca01b7a641527052e3e8961845b40b81706ce5f9) +Signed-off-by: Eric Blake +Signed-off-by: Danilo C. L. de Paula +--- + tests/qemu-iotests/178.out.qcow2 | 2 +- + tests/qemu-iotests/178.out.raw | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/tests/qemu-iotests/178.out.qcow2 b/tests/qemu-iotests/178.out.qcow2 +index 9e7d8c4..345eab3 100644 +--- a/tests/qemu-iotests/178.out.qcow2 ++++ b/tests/qemu-iotests/178.out.qcow2 +@@ -13,7 +13,7 @@ qemu-img: Invalid option list: , + qemu-img: Invalid parameter 'snapshot.foo' + qemu-img: Failed in parsing snapshot param 'snapshot.foo' + qemu-img: --output must be used with human or json as argument. +-qemu-img: Image size must be less than 8 EiB! ++qemu-img: Invalid image size specified. Must be between 0 and 9223372036854775807. + qemu-img: Unknown file format 'foo' + + == Size calculation for a new file (human) == +diff --git a/tests/qemu-iotests/178.out.raw b/tests/qemu-iotests/178.out.raw +index 6478365..15da915 100644 +--- a/tests/qemu-iotests/178.out.raw ++++ b/tests/qemu-iotests/178.out.raw +@@ -13,7 +13,7 @@ qemu-img: Invalid option list: , + qemu-img: Invalid parameter 'snapshot.foo' + qemu-img: Failed in parsing snapshot param 'snapshot.foo' + qemu-img: --output must be used with human or json as argument. +-qemu-img: Image size must be less than 8 EiB! ++qemu-img: Invalid image size specified. Must be between 0 and 9223372036854775807. + qemu-img: Unknown file format 'foo' + + == Size calculation for a new file (human) == +-- +1.8.3.1 + diff --git a/SOURCES/kvm-iotests-Let-_make_test_img-parse-its-parameters.patch b/SOURCES/kvm-iotests-Let-_make_test_img-parse-its-parameters.patch new file mode 100644 index 0000000..d24f5e7 --- /dev/null +++ b/SOURCES/kvm-iotests-Let-_make_test_img-parse-its-parameters.patch @@ -0,0 +1,91 @@ +From 3c96dbd74fb67e2ae1a116b2771290b192041707 Mon Sep 17 00:00:00 2001 +From: Eric Blake +Date: Tue, 2 Jun 2020 02:34:10 +0100 +Subject: [PATCH 05/26] iotests: Let _make_test_img parse its parameters + +RH-Author: Eric Blake +Message-id: <20200602023420.2133649-3-eblake@redhat.com> +Patchwork-id: 97070 +O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH 02/12] iotests: Let _make_test_img parse its parameters +Bugzilla: 1779893 1779904 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Max Reitz +RH-Acked-by: Kevin Wolf + +From: Max Reitz + +This will allow us to add more options than just -b. + +Signed-off-by: Max Reitz +Reviewed-by: Maxim Levitsky +Message-id: 20191107163708.833192-9-mreitz@redhat.com +Signed-off-by: Max Reitz +(cherry picked from commit eea871d047701b563cfd66c1566b9ff6d163882b) +Signed-off-by: Eric Blake +Signed-off-by: Danilo C. L. de Paula +--- + tests/qemu-iotests/common.rc | 28 ++++++++++++++++++++-------- + 1 file changed, 20 insertions(+), 8 deletions(-) + +diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc +index 0cc8acc..99fef4d 100644 +--- a/tests/qemu-iotests/common.rc ++++ b/tests/qemu-iotests/common.rc +@@ -302,12 +302,12 @@ _make_test_img() + # extra qemu-img options can be added by tests + # at least one argument (the image size) needs to be added + local extra_img_options="" +- local image_size=$* + local optstr="" + local img_name="" + local use_backing=0 + local backing_file="" + local object_options="" ++ local misc_params=() + + if [ -n "$TEST_IMG_FILE" ]; then + img_name=$TEST_IMG_FILE +@@ -323,11 +323,23 @@ _make_test_img() + optstr=$(_optstr_add "$optstr" "key-secret=keysec0") + fi + +- if [ "$1" = "-b" ]; then +- use_backing=1 +- backing_file=$2 +- image_size=$3 +- fi ++ for param; do ++ if [ "$use_backing" = "1" -a -z "$backing_file" ]; then ++ backing_file=$param ++ continue ++ fi ++ ++ case "$param" in ++ -b) ++ use_backing=1 ++ ;; ++ ++ *) ++ misc_params=("${misc_params[@]}" "$param") ++ ;; ++ esac ++ done ++ + if [ \( "$IMGFMT" = "qcow2" -o "$IMGFMT" = "qed" \) -a -n "$CLUSTER_SIZE" ]; then + optstr=$(_optstr_add "$optstr" "cluster_size=$CLUSTER_SIZE") + fi +@@ -343,9 +355,9 @@ _make_test_img() + # XXX(hch): have global image options? + ( + if [ $use_backing = 1 ]; then +- $QEMU_IMG create $object_options -f $IMGFMT $extra_img_options -b "$backing_file" "$img_name" $image_size 2>&1 ++ $QEMU_IMG create $object_options -f $IMGFMT $extra_img_options -b "$backing_file" "$img_name" "${misc_params[@]}" 2>&1 + else +- $QEMU_IMG create $object_options -f $IMGFMT $extra_img_options "$img_name" $image_size 2>&1 ++ $QEMU_IMG create $object_options -f $IMGFMT $extra_img_options "$img_name" "${misc_params[@]}" 2>&1 + fi + ) | _filter_img_create + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-iotests-Mirror-with-different-source-target-size.patch b/SOURCES/kvm-iotests-Mirror-with-different-source-target-size.patch new file mode 100644 index 0000000..7757632 --- /dev/null +++ b/SOURCES/kvm-iotests-Mirror-with-different-source-target-size.patch @@ -0,0 +1,110 @@ +From aff543186ff316d66b2c7acb434c6c17bdb8da78 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Wed, 3 Jun 2020 16:03:25 +0100 +Subject: [PATCH 26/26] iotests: Mirror with different source/target size + +RH-Author: Kevin Wolf +Message-id: <20200603160325.67506-12-kwolf@redhat.com> +Patchwork-id: 97109 +O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH v2 11/11] iotests: Mirror with different source/target size +Bugzilla: 1778593 +RH-Acked-by: Eric Blake +RH-Acked-by: Max Reitz +RH-Acked-by: Stefano Garzarella + +This tests that the mirror job catches situations where the target node +has a different size than the source node. It must also forbid resize +operations when the job is already running. + +Signed-off-by: Kevin Wolf +Reviewed-by: Eric Blake +Message-Id: <20200511135825.219437-5-kwolf@redhat.com> +Reviewed-by: Max Reitz +Reviewed-by: Vladimir Sementsov-Ogievskiy +Signed-off-by: Kevin Wolf +(cherry picked from commit 16cea4ee1c8e5a69a058e76f426b2e17974d8d7d) +Signed-off-by: Kevin Wolf +Signed-off-by: Danilo C. L. de Paula +--- + tests/qemu-iotests/041 | 45 +++++++++++++++++++++++++++++++++++++++++++++ + tests/qemu-iotests/041.out | 4 ++-- + 2 files changed, 47 insertions(+), 2 deletions(-) + +diff --git a/tests/qemu-iotests/041 b/tests/qemu-iotests/041 +index a543b15..20fb68a 100755 +--- a/tests/qemu-iotests/041 ++++ b/tests/qemu-iotests/041 +@@ -240,6 +240,49 @@ class TestSingleBlockdev(TestSingleDrive): + target=self.qmp_target) + self.assert_qmp(result, 'error/class', 'GenericError') + ++ def do_test_resize(self, device, node): ++ def pre_finalize(): ++ if device: ++ result = self.vm.qmp('block_resize', device=device, size=65536) ++ self.assert_qmp(result, 'error/class', 'GenericError') ++ ++ result = self.vm.qmp('block_resize', node_name=node, size=65536) ++ self.assert_qmp(result, 'error/class', 'GenericError') ++ ++ result = self.vm.qmp(self.qmp_cmd, job_id='job0', device='drive0', ++ sync='full', target=self.qmp_target, ++ auto_finalize=False, auto_dismiss=False) ++ self.assert_qmp(result, 'return', {}) ++ ++ result = self.vm.run_job('job0', auto_finalize=False, ++ pre_finalize=pre_finalize, use_log=False) ++ self.assertEqual(result, None) ++ ++ def test_source_resize(self): ++ self.do_test_resize('drive0', 'top') ++ ++ def test_target_resize(self): ++ self.do_test_resize(None, self.qmp_target) ++ ++ def do_test_target_size(self, size): ++ result = self.vm.qmp('block_resize', node_name=self.qmp_target, ++ size=size) ++ self.assert_qmp(result, 'return', {}) ++ ++ result = self.vm.qmp(self.qmp_cmd, job_id='job0', ++ device='drive0', sync='full', auto_dismiss=False, ++ target=self.qmp_target) ++ self.assert_qmp(result, 'return', {}) ++ ++ result = self.vm.run_job('job0', use_log=False) ++ self.assertEqual(result, 'Source and target image have different sizes') ++ ++ def test_small_target(self): ++ self.do_test_target_size(self.image_len // 2) ++ ++ def test_large_target(self): ++ self.do_test_target_size(self.image_len * 2) ++ + test_large_cluster = None + test_image_not_found = None + test_small_buffer2 = None +@@ -251,6 +294,8 @@ class TestSingleDriveZeroLength(TestSingleDrive): + + class TestSingleBlockdevZeroLength(TestSingleBlockdev): + image_len = 0 ++ test_small_target = None ++ test_large_target = None + + class TestSingleDriveUnalignedLength(TestSingleDrive): + image_len = 1025 * 1024 +diff --git a/tests/qemu-iotests/041.out b/tests/qemu-iotests/041.out +index 2c448b4..3ea6aa4 100644 +--- a/tests/qemu-iotests/041.out ++++ b/tests/qemu-iotests/041.out +@@ -1,5 +1,5 @@ +-.......................................................................................... ++.................................................................................................... + ---------------------------------------------------------------------- +-Ran 90 tests ++Ran 100 tests + + OK +-- +1.8.3.1 + diff --git a/SOURCES/kvm-iotests-Test-committing-to-short-backing-file.patch b/SOURCES/kvm-iotests-Test-committing-to-short-backing-file.patch new file mode 100644 index 0000000..fbbaac6 --- /dev/null +++ b/SOURCES/kvm-iotests-Test-committing-to-short-backing-file.patch @@ -0,0 +1,480 @@ +From e2a1b3fd32be8bb730656a6f22eb4f543b120c9d Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Mon, 8 Jun 2020 15:01:39 +0100 +Subject: [PATCH 11/17] iotests: Test committing to short backing file + +RH-Author: Kevin Wolf +Message-id: <20200608150140.38218-11-kwolf@redhat.com> +Patchwork-id: 97453 +O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH 10/11] iotests: Test committing to short backing file +Bugzilla: 1780574 +RH-Acked-by: Sergio Lopez Pascual +RH-Acked-by: Eric Blake +RH-Acked-by: Max Reitz + +Signed-off-by: Kevin Wolf +Message-Id: <20200424125448.63318-10-kwolf@redhat.com> +Reviewed-by: Max Reitz +Reviewed-by: Vladimir Sementsov-Ogievskiy +Signed-off-by: Kevin Wolf +(cherry picked from commit bf03dede475e29a16f9188ea85a4d77cd3dcf2b7) +Signed-off-by: Kevin Wolf +Signed-off-by: Danilo C. L. de Paula +--- + tests/qemu-iotests/274 | 155 ++++++++++++++++++++++++++ + tests/qemu-iotests/274.out | 268 +++++++++++++++++++++++++++++++++++++++++++++ + tests/qemu-iotests/group | 1 + + 3 files changed, 424 insertions(+) + create mode 100755 tests/qemu-iotests/274 + create mode 100644 tests/qemu-iotests/274.out + +diff --git a/tests/qemu-iotests/274 b/tests/qemu-iotests/274 +new file mode 100755 +index 0000000..e951f72 +--- /dev/null ++++ b/tests/qemu-iotests/274 +@@ -0,0 +1,155 @@ ++#!/usr/bin/env python3 ++# ++# 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 . ++# ++# Creator/Owner: Kevin Wolf ++# ++# Some tests for short backing files and short overlays ++ ++import iotests ++ ++iotests.verify_image_format(supported_fmts=['qcow2']) ++iotests.verify_platform(['linux']) ++ ++size_short = 1 * 1024 * 1024 ++size_long = 2 * 1024 * 1024 ++size_diff = size_long - size_short ++ ++def create_chain() -> None: ++ iotests.qemu_img_log('create', '-f', iotests.imgfmt, base, ++ str(size_long)) ++ iotests.qemu_img_log('create', '-f', iotests.imgfmt, '-b', base, mid, ++ str(size_short)) ++ iotests.qemu_img_log('create', '-f', iotests.imgfmt, '-b', mid, top, ++ str(size_long)) ++ ++ iotests.qemu_io_log('-c', 'write -P 1 0 %d' % size_long, base) ++ ++def create_vm() -> iotests.VM: ++ vm = iotests.VM() ++ vm.add_blockdev('file,filename=%s,node-name=base-file' % base) ++ vm.add_blockdev('%s,file=base-file,node-name=base' % iotests.imgfmt) ++ vm.add_blockdev('file,filename=%s,node-name=mid-file' % mid) ++ vm.add_blockdev('%s,file=mid-file,node-name=mid,backing=base' ++ % iotests.imgfmt) ++ vm.add_drive(top, 'backing=mid,node-name=top') ++ return vm ++ ++with iotests.FilePath('base') as base, \ ++ iotests.FilePath('mid') as mid, \ ++ iotests.FilePath('top') as top: ++ ++ iotests.log('== Commit tests ==') ++ ++ create_chain() ++ ++ iotests.log('=== Check visible data ===') ++ ++ iotests.qemu_io_log('-c', 'read -P 1 0 %d' % size_short, top) ++ iotests.qemu_io_log('-c', 'read -P 0 %d %d' % (size_short, size_diff), top) ++ ++ iotests.log('=== Checking allocation status ===') ++ ++ iotests.qemu_io_log('-c', 'alloc 0 %d' % size_short, ++ '-c', 'alloc %d %d' % (size_short, size_diff), ++ base) ++ ++ iotests.qemu_io_log('-c', 'alloc 0 %d' % size_short, ++ '-c', 'alloc %d %d' % (size_short, size_diff), ++ mid) ++ ++ iotests.qemu_io_log('-c', 'alloc 0 %d' % size_short, ++ '-c', 'alloc %d %d' % (size_short, size_diff), ++ top) ++ ++ iotests.log('=== Checking map ===') ++ ++ iotests.qemu_img_log('map', '--output=json', base) ++ iotests.qemu_img_log('map', '--output=human', base) ++ iotests.qemu_img_log('map', '--output=json', mid) ++ iotests.qemu_img_log('map', '--output=human', mid) ++ iotests.qemu_img_log('map', '--output=json', top) ++ iotests.qemu_img_log('map', '--output=human', top) ++ ++ iotests.log('=== Testing qemu-img commit (top -> mid) ===') ++ ++ iotests.qemu_img_log('commit', top) ++ iotests.img_info_log(mid) ++ iotests.qemu_io_log('-c', 'read -P 1 0 %d' % size_short, mid) ++ iotests.qemu_io_log('-c', 'read -P 0 %d %d' % (size_short, size_diff), mid) ++ ++ iotests.log('=== Testing HMP commit (top -> mid) ===') ++ ++ create_chain() ++ with create_vm() as vm: ++ vm.launch() ++ vm.qmp_log('human-monitor-command', command_line='commit drive0') ++ ++ iotests.img_info_log(mid) ++ iotests.qemu_io_log('-c', 'read -P 1 0 %d' % size_short, mid) ++ iotests.qemu_io_log('-c', 'read -P 0 %d %d' % (size_short, size_diff), mid) ++ ++ iotests.log('=== Testing QMP active commit (top -> mid) ===') ++ ++ create_chain() ++ with create_vm() as vm: ++ vm.launch() ++ vm.qmp_log('block-commit', device='top', base_node='mid', ++ job_id='job0', auto_dismiss=False) ++ vm.run_job('job0', wait=5) ++ ++ iotests.img_info_log(mid) ++ iotests.qemu_io_log('-c', 'read -P 1 0 %d' % size_short, mid) ++ iotests.qemu_io_log('-c', 'read -P 0 %d %d' % (size_short, size_diff), mid) ++ ++ ++ iotests.log('== Resize tests ==') ++ ++ # Use different sizes for different allocation modes: ++ # ++ # We want to have at least one test where 32 bit truncation in the size of ++ # the overlapping area becomes visible. This is covered by the ++ # prealloc='off' case (1G to 6G is an overlap of 5G). ++ # ++ # However, we can only do this for modes that don't preallocate data ++ # because otherwise we might run out of space on the test host. ++ # ++ # We also want to test some unaligned combinations. ++ for (prealloc, base_size, top_size_old, top_size_new, off) in [ ++ ('off', '6G', '1G', '8G', '5G'), ++ ('metadata', '32G', '30G', '33G', '31G'), ++ ('falloc', '10M', '5M', '15M', '9M'), ++ ('full', '16M', '8M', '12M', '11M'), ++ ('off', '384k', '253k', '512k', '253k'), ++ ('off', '400k', '256k', '512k', '336k'), ++ ('off', '512k', '256k', '500k', '436k')]: ++ ++ iotests.log('=== preallocation=%s ===' % prealloc) ++ iotests.qemu_img_log('create', '-f', iotests.imgfmt, base, base_size) ++ iotests.qemu_img_log('create', '-f', iotests.imgfmt, '-b', base, top, ++ top_size_old) ++ iotests.qemu_io_log('-c', 'write -P 1 %s 64k' % off, base) ++ ++ # After this, top_size_old to base_size should be allocated/zeroed. ++ # ++ # In theory, leaving base_size to top_size_new unallocated would be ++ # correct, but in practice, if we zero out anything, we zero out ++ # everything up to top_size_new. ++ iotests.qemu_img_log('resize', '-f', iotests.imgfmt, ++ '--preallocation', prealloc, top, top_size_new) ++ iotests.qemu_io_log('-c', 'read -P 0 %s 64k' % off, top) ++ iotests.qemu_io_log('-c', 'map', top) ++ iotests.qemu_img_log('map', '--output=json', top) +diff --git a/tests/qemu-iotests/274.out b/tests/qemu-iotests/274.out +new file mode 100644 +index 0000000..1a796fd +--- /dev/null ++++ b/tests/qemu-iotests/274.out +@@ -0,0 +1,268 @@ ++== Commit tests == ++Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=2097152 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++ ++Formatting 'TEST_DIR/PID-mid', fmt=qcow2 size=1048576 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++ ++Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=2097152 backing_file=TEST_DIR/PID-mid cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++ ++wrote 2097152/2097152 bytes at offset 0 ++2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++=== Check visible data === ++read 1048576/1048576 bytes at offset 0 ++1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++read 1048576/1048576 bytes at offset 1048576 ++1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++=== Checking allocation status === ++1048576/1048576 bytes allocated at offset 0 bytes ++1048576/1048576 bytes allocated at offset 1 MiB ++ ++0/1048576 bytes allocated at offset 0 bytes ++0/0 bytes allocated at offset 1 MiB ++ ++0/1048576 bytes allocated at offset 0 bytes ++0/1048576 bytes allocated at offset 1 MiB ++ ++=== Checking map === ++[{ "start": 0, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": 327680}] ++ ++Offset Length Mapped to File ++0 0x200000 0x50000 TEST_DIR/PID-base ++ ++[{ "start": 0, "length": 1048576, "depth": 1, "zero": false, "data": true, "offset": 327680}] ++ ++Offset Length Mapped to File ++0 0x100000 0x50000 TEST_DIR/PID-base ++ ++[{ "start": 0, "length": 1048576, "depth": 2, "zero": false, "data": true, "offset": 327680}, ++{ "start": 1048576, "length": 1048576, "depth": 0, "zero": true, "data": false}] ++ ++Offset Length Mapped to File ++0 0x100000 0x50000 TEST_DIR/PID-base ++ ++=== Testing qemu-img commit (top -> mid) === ++Image committed. ++ ++image: TEST_IMG ++file format: IMGFMT ++virtual size: 2 MiB (2097152 bytes) ++cluster_size: 65536 ++backing file: TEST_DIR/PID-base ++Format specific information: ++ compat: 1.1 ++ lazy refcounts: false ++ refcount bits: 16 ++ corrupt: false ++ ++read 1048576/1048576 bytes at offset 0 ++1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++read 1048576/1048576 bytes at offset 1048576 ++1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++=== Testing HMP commit (top -> mid) === ++Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=2097152 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++ ++Formatting 'TEST_DIR/PID-mid', fmt=qcow2 size=1048576 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++ ++Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=2097152 backing_file=TEST_DIR/PID-mid cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++ ++wrote 2097152/2097152 bytes at offset 0 ++2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++{"execute": "human-monitor-command", "arguments": {"command-line": "commit drive0"}} ++{"return": ""} ++image: TEST_IMG ++file format: IMGFMT ++virtual size: 2 MiB (2097152 bytes) ++cluster_size: 65536 ++backing file: TEST_DIR/PID-base ++Format specific information: ++ compat: 1.1 ++ lazy refcounts: false ++ refcount bits: 16 ++ corrupt: false ++ ++read 1048576/1048576 bytes at offset 0 ++1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++read 1048576/1048576 bytes at offset 1048576 ++1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++=== Testing QMP active commit (top -> mid) === ++Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=2097152 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++ ++Formatting 'TEST_DIR/PID-mid', fmt=qcow2 size=1048576 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++ ++Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=2097152 backing_file=TEST_DIR/PID-mid cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++ ++wrote 2097152/2097152 bytes at offset 0 ++2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++{"execute": "block-commit", "arguments": {"auto-dismiss": false, "base-node": "mid", "device": "top", "job-id": "job0"}} ++{"return": {}} ++{"execute": "job-complete", "arguments": {"id": "job0"}} ++{"return": {}} ++{"data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}, "event": "BLOCK_JOB_READY", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} ++image: TEST_IMG ++file format: IMGFMT ++virtual size: 2 MiB (2097152 bytes) ++cluster_size: 65536 ++backing file: TEST_DIR/PID-base ++Format specific information: ++ compat: 1.1 ++ lazy refcounts: false ++ refcount bits: 16 ++ corrupt: false ++ ++read 1048576/1048576 bytes at offset 0 ++1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++read 1048576/1048576 bytes at offset 1048576 ++1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++== Resize tests == ++=== preallocation=off === ++Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=6442450944 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++ ++Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=1073741824 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++ ++wrote 65536/65536 bytes at offset 5368709120 ++64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++Image resized. ++ ++read 65536/65536 bytes at offset 5368709120 ++64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++1 GiB (0x40000000) bytes not allocated at offset 0 bytes (0x0) ++7 GiB (0x1c0000000) bytes allocated at offset 1 GiB (0x40000000) ++ ++[{ "start": 0, "length": 1073741824, "depth": 1, "zero": true, "data": false}, ++{ "start": 1073741824, "length": 7516192768, "depth": 0, "zero": true, "data": false}] ++ ++=== preallocation=metadata === ++Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=34359738368 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++ ++Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=32212254720 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++ ++wrote 65536/65536 bytes at offset 33285996544 ++64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++Image resized. ++ ++read 65536/65536 bytes at offset 33285996544 ++64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++30 GiB (0x780000000) bytes not allocated at offset 0 bytes (0x0) ++3 GiB (0xc0000000) bytes allocated at offset 30 GiB (0x780000000) ++ ++[{ "start": 0, "length": 32212254720, "depth": 1, "zero": true, "data": false}, ++{ "start": 32212254720, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 327680}, ++{ "start": 32749125632, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 537264128}, ++{ "start": 33285996544, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 1074200576}, ++{ "start": 33822867456, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 1611137024}, ++{ "start": 34359738368, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 2148139008}, ++{ "start": 34896609280, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 2685075456}] ++ ++=== preallocation=falloc === ++Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=10485760 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++ ++Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=5242880 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++ ++wrote 65536/65536 bytes at offset 9437184 ++64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++Image resized. ++ ++read 65536/65536 bytes at offset 9437184 ++64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++5 MiB (0x500000) bytes not allocated at offset 0 bytes (0x0) ++10 MiB (0xa00000) bytes allocated at offset 5 MiB (0x500000) ++ ++[{ "start": 0, "length": 5242880, "depth": 1, "zero": true, "data": false}, ++{ "start": 5242880, "length": 10485760, "depth": 0, "zero": true, "data": false, "offset": 327680}] ++ ++=== preallocation=full === ++Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=16777216 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++ ++Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=8388608 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++ ++wrote 65536/65536 bytes at offset 11534336 ++64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++Image resized. ++ ++read 65536/65536 bytes at offset 11534336 ++64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++8 MiB (0x800000) bytes not allocated at offset 0 bytes (0x0) ++4 MiB (0x400000) bytes allocated at offset 8 MiB (0x800000) ++ ++[{ "start": 0, "length": 8388608, "depth": 1, "zero": true, "data": false}, ++{ "start": 8388608, "length": 4194304, "depth": 0, "zero": true, "data": false, "offset": 327680}] ++ ++=== preallocation=off === ++Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=393216 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++ ++Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=259072 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++ ++wrote 65536/65536 bytes at offset 259072 ++64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++Image resized. ++ ++read 65536/65536 bytes at offset 259072 ++64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++192 KiB (0x30000) bytes not allocated at offset 0 bytes (0x0) ++320 KiB (0x50000) bytes allocated at offset 192 KiB (0x30000) ++ ++[{ "start": 0, "length": 196608, "depth": 1, "zero": true, "data": false}, ++{ "start": 196608, "length": 65536, "depth": 0, "zero": false, "data": true, "offset": 327680}, ++{ "start": 262144, "length": 262144, "depth": 0, "zero": true, "data": false}] ++ ++=== preallocation=off === ++Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=409600 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++ ++Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=262144 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++ ++wrote 65536/65536 bytes at offset 344064 ++64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++Image resized. ++ ++read 65536/65536 bytes at offset 344064 ++64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++256 KiB (0x40000) bytes not allocated at offset 0 bytes (0x0) ++256 KiB (0x40000) bytes allocated at offset 256 KiB (0x40000) ++ ++[{ "start": 0, "length": 262144, "depth": 1, "zero": true, "data": false}, ++{ "start": 262144, "length": 262144, "depth": 0, "zero": true, "data": false}] ++ ++=== preallocation=off === ++Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=524288 cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++ ++Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=262144 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++ ++wrote 65536/65536 bytes at offset 446464 ++64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++Image resized. ++ ++read 65536/65536 bytes at offset 446464 ++64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++256 KiB (0x40000) bytes not allocated at offset 0 bytes (0x0) ++244 KiB (0x3d000) bytes allocated at offset 256 KiB (0x40000) ++ ++[{ "start": 0, "length": 262144, "depth": 1, "zero": true, "data": false}, ++{ "start": 262144, "length": 249856, "depth": 0, "zero": true, "data": false}] ++ +diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group +index 033b54d..cddae00 100644 +--- a/tests/qemu-iotests/group ++++ b/tests/qemu-iotests/group +@@ -286,6 +286,7 @@ + 270 rw backing quick + 272 rw + 273 backing quick ++274 rw backing + 277 rw quick + 280 rw migration quick + 281 rw quick +-- +1.8.3.1 + diff --git a/SOURCES/kvm-iotests-don-t-use-format-for-drive_add.patch b/SOURCES/kvm-iotests-don-t-use-format-for-drive_add.patch new file mode 100644 index 0000000..f95e17a --- /dev/null +++ b/SOURCES/kvm-iotests-don-t-use-format-for-drive_add.patch @@ -0,0 +1,81 @@ +From 127360c2fa0fefa18ff828bfec3985e04791d665 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Wed, 3 Jun 2020 16:03:16 +0100 +Subject: [PATCH 17/26] iotests: don't use 'format' for drive_add +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Kevin Wolf +Message-id: <20200603160325.67506-3-kwolf@redhat.com> +Patchwork-id: 97102 +O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH v2 02/11] iotests: don't use 'format' for drive_add +Bugzilla: 1778593 +RH-Acked-by: Eric Blake +RH-Acked-by: Max Reitz +RH-Acked-by: Stefano Garzarella + +From: John Snow + +It shadows (with a different type) the built-in format. +Use something else. + +Signed-off-by: John Snow +Reviewed-by: Philippe Mathieu-Daudé +Reviewed-by: Max Reitz +Message-Id: <20200331000014.11581-3-jsnow@redhat.com> +Reviewed-by: Kevin Wolf +Signed-off-by: Max Reitz +(cherry picked from commit 1d3d4b630c6ea8b19420c097f0c448b6ded95072) +Signed-off-by: Kevin Wolf +Signed-off-by: Danilo C. L. de Paula +--- + tests/qemu-iotests/055 | 3 ++- + tests/qemu-iotests/iotests.py | 6 +++--- + 2 files changed, 5 insertions(+), 4 deletions(-) + +diff --git a/tests/qemu-iotests/055 b/tests/qemu-iotests/055 +index c732a11..eb50c9f 100755 +--- a/tests/qemu-iotests/055 ++++ b/tests/qemu-iotests/055 +@@ -469,7 +469,8 @@ class TestDriveCompression(iotests.QMPTestCase): + qemu_img('create', '-f', fmt, blockdev_target_img, + str(TestDriveCompression.image_len), *args) + if attach_target: +- self.vm.add_drive(blockdev_target_img, format=fmt, interface="none") ++ self.vm.add_drive(blockdev_target_img, ++ img_format=fmt, interface="none") + + self.vm.launch() + +diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py +index 46f880c..be20d56 100644 +--- a/tests/qemu-iotests/iotests.py ++++ b/tests/qemu-iotests/iotests.py +@@ -481,20 +481,20 @@ class VM(qtest.QEMUQtestMachine): + self._args.append(opts) + return self + +- def add_drive(self, path, opts='', interface='virtio', format=imgfmt): ++ def add_drive(self, path, opts='', interface='virtio', img_format=imgfmt): + '''Add a virtio-blk drive to the VM''' + options = ['if=%s' % interface, + 'id=drive%d' % self._num_drives] + + if path is not None: + options.append('file=%s' % path) +- options.append('format=%s' % format) ++ options.append('format=%s' % img_format) + options.append('cache=%s' % cachemode) + + if opts: + options.append(opts) + +- if format == 'luks' and 'key-secret' not in opts: ++ if img_format == 'luks' and 'key-secret' not in opts: + # default luks support + if luks_default_secret_object not in self._args: + self.add_object(luks_default_secret_object) +-- +1.8.3.1 + diff --git a/SOURCES/kvm-linux-headers-support-vfio-ccw-features.patch b/SOURCES/kvm-linux-headers-support-vfio-ccw-features.patch new file mode 100644 index 0000000..4eb95bf --- /dev/null +++ b/SOURCES/kvm-linux-headers-support-vfio-ccw-features.patch @@ -0,0 +1,77 @@ +From 1da0eecb9f2086c880fdaf1260ae775bbfbf5f02 Mon Sep 17 00:00:00 2001 +From: Cornelia Huck +Date: Tue, 23 Jun 2020 09:25:37 -0400 +Subject: [PATCH 03/12] linux-headers: support vfio-ccw features + +RH-Author: Cornelia Huck +Message-id: <20200623092543.358315-4-cohuck@redhat.com> +Patchwork-id: 97696 +O-Subject: [RHEL-8.3.0 qemu-kvm PATCH 3/9] linux-headers: support vfio-ccw features +Bugzilla: 1660916 +RH-Acked-by: Claudio Imbrenda +RH-Acked-by: David Hildenbrand +RH-Acked-by: Thomas Huth + +Partial update to support CRW and SCHIB regions. + +Upstream: n/a + +Signed-off-by: Cornelia Huck +Signed-off-by: Danilo C. L. de Paula +--- + linux-headers/linux/vfio.h | 3 +++ + linux-headers/linux/vfio_ccw.h | 19 +++++++++++++++++++ + 2 files changed, 22 insertions(+) + +diff --git a/linux-headers/linux/vfio.h b/linux-headers/linux/vfio.h +index fb10370d29..9e227348b3 100644 +--- a/linux-headers/linux/vfio.h ++++ b/linux-headers/linux/vfio.h +@@ -378,6 +378,8 @@ struct vfio_region_gfx_edid { + + /* sub-types for VFIO_REGION_TYPE_CCW */ + #define VFIO_REGION_SUBTYPE_CCW_ASYNC_CMD (1) ++#define VFIO_REGION_SUBTYPE_CCW_SCHIB (2) ++#define VFIO_REGION_SUBTYPE_CCW_CRW (3) + + /* + * The MSIX mappable capability informs that MSIX data of a BAR can be mmapped +@@ -577,6 +579,7 @@ enum { + + enum { + VFIO_CCW_IO_IRQ_INDEX, ++ VFIO_CCW_CRW_IRQ_INDEX, + VFIO_CCW_NUM_IRQS + }; + +diff --git a/linux-headers/linux/vfio_ccw.h b/linux-headers/linux/vfio_ccw.h +index fcc3e69ef5..6375d6ff25 100644 +--- a/linux-headers/linux/vfio_ccw.h ++++ b/linux-headers/linux/vfio_ccw.h +@@ -34,4 +34,23 @@ struct ccw_cmd_region { + __u32 ret_code; + } __attribute__((packed)); + ++/* ++ * Used for processing commands that read the subchannel-information block ++ * Reading this region triggers a stsch() to hardware ++ * Note: this is controlled by a capability ++ */ ++struct ccw_schib_region { ++#define SCHIB_AREA_SIZE 52 ++ __u8 schib_area[SCHIB_AREA_SIZE]; ++} __attribute__((packed)); ++ ++/* ++ * Used for returning a Channel Report Word to userspace. ++ * Note: this is controlled by a capability ++ */ ++struct ccw_crw_region { ++ __u32 crw; ++ __u32 pad; ++} __attribute__((packed)); ++ + #endif +-- +2.27.0 + diff --git a/SOURCES/kvm-linux-headers-update-kvm.h.patch b/SOURCES/kvm-linux-headers-update-kvm.h.patch new file mode 100644 index 0000000..1834e33 --- /dev/null +++ b/SOURCES/kvm-linux-headers-update-kvm.h.patch @@ -0,0 +1,119 @@ +From 9d1b94d3739567245578f30866facc13edb3be92 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 29 May 2020 05:53:44 -0400 +Subject: [PATCH 02/42] linux-headers: update kvm.h + +RH-Author: Thomas Huth +Message-id: <20200529055420.16855-3-thuth@redhat.com> +Patchwork-id: 97020 +O-Subject: [RHEL-8.3.0 qemu-kvm PATCH v2 02/38] linux-headers: update kvm.h +Bugzilla: 1828317 +RH-Acked-by: Claudio Imbrenda +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand + +Upstream-status: n/a + +Update kvm.h for the upcoming new s390x reset and protected virtualization +ioctls. This patch is based on commit ddda37483dd17c9936fdde9ebf8f6ca2692b3842 +and commit dc6f8d458a4ccc360723993f31d310d06469f55f, but I dropped all +(unrequired) changes to the other linux-header files. + +Signed-off-by: Thomas Huth +Signed-off-by: Danilo C. L. de Paula +--- + linux-headers/linux/kvm.h | 55 +++++++++++++++++++++++++++++++++++++-- + 1 file changed, 53 insertions(+), 2 deletions(-) + +diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h +index 3d9b18f7f8..578cd97c0d 100644 +--- a/linux-headers/linux/kvm.h ++++ b/linux-headers/linux/kvm.h +@@ -468,12 +468,17 @@ struct kvm_s390_mem_op { + __u32 size; /* amount of bytes */ + __u32 op; /* type of operation */ + __u64 buf; /* buffer in userspace */ +- __u8 ar; /* the access register number */ +- __u8 reserved[31]; /* should be set to 0 */ ++ union { ++ __u8 ar; /* the access register number */ ++ __u32 sida_offset; /* offset into the sida */ ++ __u8 reserved[32]; /* should be set to 0 */ ++ }; + }; + /* types for kvm_s390_mem_op->op */ + #define KVM_S390_MEMOP_LOGICAL_READ 0 + #define KVM_S390_MEMOP_LOGICAL_WRITE 1 ++#define KVM_S390_MEMOP_SIDA_READ 2 ++#define KVM_S390_MEMOP_SIDA_WRITE 3 + /* flags for kvm_s390_mem_op->flags */ + #define KVM_S390_MEMOP_F_CHECK_ONLY (1ULL << 0) + #define KVM_S390_MEMOP_F_INJECT_EXCEPTION (1ULL << 1) +@@ -1000,6 +1005,12 @@ struct kvm_ppc_resize_hpt { + #define KVM_CAP_PMU_EVENT_FILTER 173 + #define KVM_CAP_ARM_IRQ_LINE_LAYOUT_2 174 + #define KVM_CAP_HYPERV_DIRECT_TLBFLUSH 175 ++#define KVM_CAP_PPC_GUEST_DEBUG_SSTEP 176 ++#define KVM_CAP_ARM_NISV_TO_USER 177 ++#define KVM_CAP_ARM_INJECT_EXT_DABT 178 ++#define KVM_CAP_S390_VCPU_RESETS 179 ++#define KVM_CAP_S390_PROTECTED 180 ++#define KVM_CAP_PPC_SECURE_GUEST 181 + + #ifdef KVM_CAP_IRQ_ROUTING + +@@ -1461,6 +1472,43 @@ struct kvm_enc_region { + /* Available with KVM_CAP_ARM_SVE */ + #define KVM_ARM_VCPU_FINALIZE _IOW(KVMIO, 0xc2, int) + ++/* Available with KVM_CAP_S390_VCPU_RESETS */ ++#define KVM_S390_NORMAL_RESET _IO(KVMIO, 0xc3) ++#define KVM_S390_CLEAR_RESET _IO(KVMIO, 0xc4) ++ ++struct kvm_s390_pv_sec_parm { ++ __u64 origin; ++ __u64 length; ++}; ++ ++struct kvm_s390_pv_unp { ++ __u64 addr; ++ __u64 size; ++ __u64 tweak; ++}; ++ ++enum pv_cmd_id { ++ KVM_PV_ENABLE, ++ KVM_PV_DISABLE, ++ KVM_PV_SET_SEC_PARMS, ++ KVM_PV_UNPACK, ++ KVM_PV_VERIFY, ++ KVM_PV_PREP_RESET, ++ KVM_PV_UNSHARE_ALL, ++}; ++ ++struct kvm_pv_cmd { ++ __u32 cmd; /* Command to be executed */ ++ __u16 rc; /* Ultravisor return code */ ++ __u16 rrc; /* Ultravisor return reason code */ ++ __u64 data; /* Data or address */ ++ __u32 flags; /* flags for future extensions. Must be 0 for now */ ++ __u32 reserved[3]; ++}; ++ ++/* Available with KVM_CAP_S390_PROTECTED */ ++#define KVM_S390_PV_COMMAND _IOWR(KVMIO, 0xc5, struct kvm_pv_cmd) ++ + /* Secure Encrypted Virtualization command */ + enum sev_cmd_id { + /* Guest initialization commands */ +@@ -1611,4 +1659,7 @@ struct kvm_hyperv_eventfd { + #define KVM_HYPERV_CONN_ID_MASK 0x00ffffff + #define KVM_HYPERV_EVENTFD_DEASSIGN (1 << 0) + ++#define KVM_DIRTY_LOG_MANUAL_PROTECT_ENABLE (1 << 0) ++#define KVM_DIRTY_LOG_INITIALLY_SET (1 << 1) ++ + #endif /* __LINUX_KVM_H */ +-- +2.27.0 + diff --git a/SOURCES/kvm-mirror-Make-sure-that-source-and-target-size-match.patch b/SOURCES/kvm-mirror-Make-sure-that-source-and-target-size-match.patch new file mode 100644 index 0000000..09d1152 --- /dev/null +++ b/SOURCES/kvm-mirror-Make-sure-that-source-and-target-size-match.patch @@ -0,0 +1,89 @@ +From 98bf67db979927a5c7bbdc4a17c35d60b5f38e71 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Wed, 3 Jun 2020 16:03:24 +0100 +Subject: [PATCH 25/26] mirror: Make sure that source and target size match + +RH-Author: Kevin Wolf +Message-id: <20200603160325.67506-11-kwolf@redhat.com> +Patchwork-id: 97110 +O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH v2 10/11] mirror: Make sure that source and target size match +Bugzilla: 1778593 +RH-Acked-by: Eric Blake +RH-Acked-by: Max Reitz +RH-Acked-by: Stefano Garzarella + +If the target is shorter than the source, mirror would copy data until +it reaches the end of the target and then fail with an I/O error when +trying to write past the end. + +If the target is longer than the source, the mirror job would complete +successfully, but the target wouldn't actually be an accurate copy of +the source image (it would contain some additional garbage at the end). + +Fix this by checking that both images have the same size when the job +starts. + +Signed-off-by: Kevin Wolf +Reviewed-by: Eric Blake +Message-Id: <20200511135825.219437-4-kwolf@redhat.com> +Reviewed-by: Max Reitz +Reviewed-by: Vladimir Sementsov-Ogievskiy +Signed-off-by: Kevin Wolf +(cherry picked from commit e83dd6808c6e0975970f37b49b27cc37bb54eea8) +Signed-off-by: Kevin Wolf +Signed-off-by: Danilo C. L. de Paula +--- + block/mirror.c | 21 ++++++++++++--------- + 1 file changed, 12 insertions(+), 9 deletions(-) + +diff --git a/block/mirror.c b/block/mirror.c +index 5e5a521..0d32fca 100644 +--- a/block/mirror.c ++++ b/block/mirror.c +@@ -859,6 +859,7 @@ static int coroutine_fn mirror_run(Job *job, Error **errp) + BlockDriverState *target_bs = blk_bs(s->target); + bool need_drain = true; + int64_t length; ++ int64_t target_length; + BlockDriverInfo bdi; + char backing_filename[2]; /* we only need 2 characters because we are only + checking for a NULL string */ +@@ -874,24 +875,26 @@ static int coroutine_fn mirror_run(Job *job, Error **errp) + goto immediate_exit; + } + ++ target_length = blk_getlength(s->target); ++ if (target_length < 0) { ++ ret = target_length; ++ goto immediate_exit; ++ } ++ + /* Active commit must resize the base image if its size differs from the + * active layer. */ + if (s->base == blk_bs(s->target)) { +- int64_t base_length; +- +- base_length = blk_getlength(s->target); +- if (base_length < 0) { +- ret = base_length; +- goto immediate_exit; +- } +- +- if (s->bdev_length > base_length) { ++ if (s->bdev_length > target_length) { + ret = blk_truncate(s->target, s->bdev_length, false, + PREALLOC_MODE_OFF, NULL); + if (ret < 0) { + goto immediate_exit; + } + } ++ } else if (s->bdev_length != target_length) { ++ error_setg(errp, "Source and target image have different sizes"); ++ ret = -EINVAL; ++ goto immediate_exit; + } + + if (s->bdev_length == 0) { +-- +1.8.3.1 + diff --git a/SOURCES/kvm-nbd-server-Avoid-long-error-message-assertions-CVE-2.patch b/SOURCES/kvm-nbd-server-Avoid-long-error-message-assertions-CVE-2.patch new file mode 100644 index 0000000..94d2c98 --- /dev/null +++ b/SOURCES/kvm-nbd-server-Avoid-long-error-message-assertions-CVE-2.patch @@ -0,0 +1,161 @@ +From f49ff2ed5675f1d0cddc404842e9d6e4e572d5a7 Mon Sep 17 00:00:00 2001 +From: Eric Blake +Date: Wed, 10 Jun 2020 18:32:01 -0400 +Subject: [PATCH 1/2] nbd/server: Avoid long error message assertions + CVE-2020-10761 + +RH-Author: Eric Blake +Message-id: <20200610183202.3780750-2-eblake@redhat.com> +Patchwork-id: 97494 +O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH 1/2] nbd/server: Avoid long error message assertions CVE-2020-10761 +Bugzilla: 1845384 +RH-Acked-by: Sergio Lopez Pascual +RH-Acked-by: Max Reitz +RH-Acked-by: Stefan Hajnoczi + +Ever since commit 36683283 (v2.8), the server code asserts that error +strings sent to the client are well-formed per the protocol by not +exceeding the maximum string length of 4096. At the time the server +first started sending error messages, the assertion could not be +triggered, because messages were completely under our control. +However, over the years, we have added latent scenarios where a client +could trigger the server to attempt an error message that would +include the client's information if it passed other checks first: + +- requesting NBD_OPT_INFO/GO on an export name that is not present + (commit 0cfae925 in v2.12 echoes the name) + +- requesting NBD_OPT_LIST/SET_META_CONTEXT on an export name that is + not present (commit e7b1948d in v2.12 echoes the name) + +At the time, those were still safe because we flagged names larger +than 256 bytes with a different message; but that changed in commit +93676c88 (v4.2) when we raised the name limit to 4096 to match the NBD +string limit. (That commit also failed to change the magic number +4096 in nbd_negotiate_send_rep_err to the just-introduced named +constant.) So with that commit, long client names appended to server +text can now trigger the assertion, and thus be used as a denial of +service attack against a server. As a mitigating factor, if the +server requires TLS, the client cannot trigger the problematic paths +unless it first supplies TLS credentials, and such trusted clients are +less likely to try to intentionally crash the server. + +We may later want to further sanitize the user-supplied strings we +place into our error messages, such as scrubbing out control +characters, but that is less important to the CVE fix, so it can be a +later patch to the new nbd_sanitize_name. + +Consideration was given to changing the assertion in +nbd_negotiate_send_rep_verr to instead merely log a server error and +truncate the message, to avoid leaving a latent path that could +trigger a future CVE DoS on any new error message. However, this +merely complicates the code for something that is already (correctly) +flagging coding errors, and now that we are aware of the long message +pitfall, we are less likely to introduce such errors in the future, +which would make such error handling dead code. + +Reported-by: Xueqiang Wei +CC: qemu-stable@nongnu.org +Fixes: https://bugzilla.redhat.com/1843684 CVE-2020-10761 +Fixes: 93676c88d7 +Signed-off-by: Eric Blake +Message-Id: <20200610163741.3745251-2-eblake@redhat.com> +Reviewed-by: Vladimir Sementsov-Ogievskiy +(cherry picked from commit 5c4fe018c025740fef4a0a4421e8162db0c3eefd) +Signed-off-by: Eric Blake +Signed-off-by: Eduardo Lima (Etrunko) +--- + nbd/server.c | 23 ++++++++++++++++++++--- + tests/qemu-iotests/143 | 4 ++++ + tests/qemu-iotests/143.out | 2 ++ + 3 files changed, 26 insertions(+), 3 deletions(-) + +diff --git a/nbd/server.c b/nbd/server.c +index 24ebc1a805..d5b9df092c 100644 +--- a/nbd/server.c ++++ b/nbd/server.c +@@ -217,7 +217,7 @@ nbd_negotiate_send_rep_verr(NBDClient *client, uint32_t type, + + msg = g_strdup_vprintf(fmt, va); + len = strlen(msg); +- assert(len < 4096); ++ assert(len < NBD_MAX_STRING_SIZE); + trace_nbd_negotiate_send_rep_err(msg); + ret = nbd_negotiate_send_rep_len(client, type, len, errp); + if (ret < 0) { +@@ -231,6 +231,19 @@ nbd_negotiate_send_rep_verr(NBDClient *client, uint32_t type, + return 0; + } + ++/* ++ * Return a malloc'd copy of @name suitable for use in an error reply. ++ */ ++static char * ++nbd_sanitize_name(const char *name) ++{ ++ if (strnlen(name, 80) < 80) { ++ return g_strdup(name); ++ } ++ /* XXX Should we also try to sanitize any control characters? */ ++ return g_strdup_printf("%.80s...", name); ++} ++ + /* Send an error reply. + * Return -errno on error, 0 on success. */ + static int GCC_FMT_ATTR(4, 5) +@@ -595,9 +608,11 @@ static int nbd_negotiate_handle_info(NBDClient *client, Error **errp) + + exp = nbd_export_find(name); + if (!exp) { ++ g_autofree char *sane_name = nbd_sanitize_name(name); ++ + return nbd_negotiate_send_rep_err(client, NBD_REP_ERR_UNKNOWN, + errp, "export '%s' not present", +- name); ++ sane_name); + } + + /* Don't bother sending NBD_INFO_NAME unless client requested it */ +@@ -995,8 +1010,10 @@ static int nbd_negotiate_meta_queries(NBDClient *client, + + meta->exp = nbd_export_find(export_name); + if (meta->exp == NULL) { ++ g_autofree char *sane_name = nbd_sanitize_name(export_name); ++ + return nbd_opt_drop(client, NBD_REP_ERR_UNKNOWN, errp, +- "export '%s' not present", export_name); ++ "export '%s' not present", sane_name); + } + + ret = nbd_opt_read(client, &nb_queries, sizeof(nb_queries), errp); +diff --git a/tests/qemu-iotests/143 b/tests/qemu-iotests/143 +index f649b36195..d2349903b1 100755 +--- a/tests/qemu-iotests/143 ++++ b/tests/qemu-iotests/143 +@@ -58,6 +58,10 @@ _send_qemu_cmd $QEMU_HANDLE \ + $QEMU_IO_PROG -f raw -c quit \ + "nbd+unix:///no_such_export?socket=$SOCK_DIR/nbd" 2>&1 \ + | _filter_qemu_io | _filter_nbd ++# Likewise, with longest possible name permitted in NBD protocol ++$QEMU_IO_PROG -f raw -c quit \ ++ "nbd+unix:///$(printf %4096d 1 | tr ' ' a)?socket=$SOCK_DIR/nbd" 2>&1 \ ++ | _filter_qemu_io | _filter_nbd | sed 's/aaaa*aa/aa--aa/' + + _send_qemu_cmd $QEMU_HANDLE \ + "{ 'execute': 'quit' }" \ +diff --git a/tests/qemu-iotests/143.out b/tests/qemu-iotests/143.out +index 1f4001c601..fc9c0a761f 100644 +--- a/tests/qemu-iotests/143.out ++++ b/tests/qemu-iotests/143.out +@@ -5,6 +5,8 @@ QA output created by 143 + {"return": {}} + qemu-io: can't open device nbd+unix:///no_such_export?socket=SOCK_DIR/nbd: Requested export not available + server reported: export 'no_such_export' not present ++qemu-io: can't open device nbd+unix:///aa--aa1?socket=SOCK_DIR/nbd: Requested export not available ++server reported: export 'aa--aa...' not present + { 'execute': 'quit' } + {"return": {}} + {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +-- +2.27.0 + diff --git a/SOURCES/kvm-numa-Extend-CLI-to-provide-initiator-information-for.patch b/SOURCES/kvm-numa-Extend-CLI-to-provide-initiator-information-for.patch new file mode 100644 index 0000000..6d9382c --- /dev/null +++ b/SOURCES/kvm-numa-Extend-CLI-to-provide-initiator-information-for.patch @@ -0,0 +1,318 @@ +From 70f8bbb27f9f357ea83ff6639fc00aa60fc902b9 Mon Sep 17 00:00:00 2001 +From: "plai@redhat.com" +Date: Thu, 21 May 2020 23:56:47 +0100 +Subject: [PATCH 04/12] numa: Extend CLI to provide initiator information for + numa nodes + +RH-Author: plai@redhat.com +Message-id: <20200521235655.27141-4-plai@redhat.com> +Patchwork-id: 96736 +O-Subject: [RHEL8.2.1 AV qemu-kvm PATCH 03/11] numa: Extend CLI to provide initiator information for numa nodes +Bugzilla: 1600217 +RH-Acked-by: Michael S. Tsirkin +RH-Acked-by: Igor Mammedov +RH-Acked-by: Eduardo Habkost + +From: Tao Xu + +In ACPI 6.3 chapter 5.2.27 Heterogeneous Memory Attribute Table (HMAT), +The initiator represents processor which access to memory. And in 5.2.27.3 +Memory Proximity Domain Attributes Structure, the attached initiator is +defined as where the memory controller responsible for a memory proximity +domain. With attached initiator information, the topology of heterogeneous +memory can be described. Add new machine property 'hmat' to enable all +HMAT specific options. + +Extend CLI of "-numa node" option to indicate the initiator numa node-id. +In the linux kernel, the codes in drivers/acpi/hmat/hmat.c parse and report +the platform's HMAT tables. Before using initiator option, enable HMAT with +-machine hmat=on. + +Acked-by: Markus Armbruster +Reviewed-by: Igor Mammedov +Reviewed-by: Jingqi Liu +Suggested-by: Dan Williams +Signed-off-by: Tao Xu +Message-Id: <20191213011929.2520-2-tao3.xu@intel.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +(cherry picked from commit 244b3f4485a07c7ce4b7123d6ce9d8c6012756e8) +Signed-off-by: Paul Lai +Signed-off-by: Danilo C. L. de Paula +--- + hw/core/machine.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++ + hw/core/numa.c | 23 ++++++++++++++++++ + include/sysemu/numa.h | 5 ++++ + qapi/machine.json | 10 +++++++- + qemu-options.hx | 35 ++++++++++++++++++++++++---- + 5 files changed, 131 insertions(+), 6 deletions(-) + +diff --git a/hw/core/machine.c b/hw/core/machine.c +index 19c78c6..cb21ae1 100644 +--- a/hw/core/machine.c ++++ b/hw/core/machine.c +@@ -688,6 +688,20 @@ static void machine_set_nvdimm(Object *obj, bool value, Error **errp) + ms->nvdimms_state->is_enabled = value; + } + ++static bool machine_get_hmat(Object *obj, Error **errp) ++{ ++ MachineState *ms = MACHINE(obj); ++ ++ return ms->numa_state->hmat_enabled; ++} ++ ++static void machine_set_hmat(Object *obj, bool value, Error **errp) ++{ ++ MachineState *ms = MACHINE(obj); ++ ++ ms->numa_state->hmat_enabled = value; ++} ++ + static char *machine_get_nvdimm_persistence(Object *obj, Error **errp) + { + MachineState *ms = MACHINE(obj); +@@ -815,6 +829,7 @@ void machine_set_cpu_numa_node(MachineState *machine, + const CpuInstanceProperties *props, Error **errp) + { + MachineClass *mc = MACHINE_GET_CLASS(machine); ++ NodeInfo *numa_info = machine->numa_state->nodes; + bool match = false; + int i; + +@@ -884,6 +899,17 @@ void machine_set_cpu_numa_node(MachineState *machine, + match = true; + slot->props.node_id = props->node_id; + slot->props.has_node_id = props->has_node_id; ++ ++ if (machine->numa_state->hmat_enabled) { ++ if ((numa_info[props->node_id].initiator < MAX_NODES) && ++ (props->node_id != numa_info[props->node_id].initiator)) { ++ error_setg(errp, "The initiator of CPU NUMA node %" PRId64 ++ " should be itself", props->node_id); ++ return; ++ } ++ numa_info[props->node_id].has_cpu = true; ++ numa_info[props->node_id].initiator = props->node_id; ++ } + } + + if (!match) { +@@ -1130,6 +1156,13 @@ static void machine_initfn(Object *obj) + + if (mc->cpu_index_to_instance_props && mc->get_default_cpu_node_id) { + ms->numa_state = g_new0(NumaState, 1); ++ object_property_add_bool(obj, "hmat", ++ machine_get_hmat, machine_set_hmat, ++ &error_abort); ++ object_property_set_description(obj, "hmat", ++ "Set on/off to enable/disable " ++ "ACPI Heterogeneous Memory Attribute " ++ "Table (HMAT)", NULL); + } + + /* Register notifier when init is done for sysbus sanity checks */ +@@ -1218,6 +1251,32 @@ static char *cpu_slot_to_string(const CPUArchId *cpu) + return g_string_free(s, false); + } + ++static void numa_validate_initiator(NumaState *numa_state) ++{ ++ int i; ++ NodeInfo *numa_info = numa_state->nodes; ++ ++ for (i = 0; i < numa_state->num_nodes; i++) { ++ if (numa_info[i].initiator == MAX_NODES) { ++ error_report("The initiator of NUMA node %d is missing, use " ++ "'-numa node,initiator' option to declare it", i); ++ exit(1); ++ } ++ ++ if (!numa_info[numa_info[i].initiator].present) { ++ error_report("NUMA node %" PRIu16 " is missing, use " ++ "'-numa node' option to declare it first", ++ numa_info[i].initiator); ++ exit(1); ++ } ++ ++ if (!numa_info[numa_info[i].initiator].has_cpu) { ++ error_report("The initiator of NUMA node %d is invalid", i); ++ exit(1); ++ } ++ } ++} ++ + static void machine_numa_finish_cpu_init(MachineState *machine) + { + int i; +@@ -1258,6 +1317,11 @@ static void machine_numa_finish_cpu_init(MachineState *machine) + machine_set_cpu_numa_node(machine, &props, &error_fatal); + } + } ++ ++ if (machine->numa_state->hmat_enabled) { ++ numa_validate_initiator(machine->numa_state); ++ } ++ + if (s->len && !qtest_enabled()) { + warn_report("CPU(s) not present in any NUMA nodes: %s", + s->str); +diff --git a/hw/core/numa.c b/hw/core/numa.c +index 19f082d..a07eef9 100644 +--- a/hw/core/numa.c ++++ b/hw/core/numa.c +@@ -129,6 +129,29 @@ static void parse_numa_node(MachineState *ms, NumaNodeOptions *node, + numa_info[nodenr].node_mem = object_property_get_uint(o, "size", NULL); + numa_info[nodenr].node_memdev = MEMORY_BACKEND(o); + } ++ ++ /* ++ * If not set the initiator, set it to MAX_NODES. And if ++ * HMAT is enabled and this node has no cpus, QEMU will raise error. ++ */ ++ numa_info[nodenr].initiator = MAX_NODES; ++ if (node->has_initiator) { ++ if (!ms->numa_state->hmat_enabled) { ++ error_setg(errp, "ACPI Heterogeneous Memory Attribute Table " ++ "(HMAT) is disabled, enable it with -machine hmat=on " ++ "before using any of hmat specific options"); ++ return; ++ } ++ ++ if (node->initiator >= MAX_NODES) { ++ error_report("The initiator id %" PRIu16 " expects an integer " ++ "between 0 and %d", node->initiator, ++ MAX_NODES - 1); ++ return; ++ } ++ ++ numa_info[nodenr].initiator = node->initiator; ++ } + numa_info[nodenr].present = true; + max_numa_nodeid = MAX(max_numa_nodeid, nodenr + 1); + ms->numa_state->num_nodes++; +diff --git a/include/sysemu/numa.h b/include/sysemu/numa.h +index ae9c41d..788cbec 100644 +--- a/include/sysemu/numa.h ++++ b/include/sysemu/numa.h +@@ -18,6 +18,8 @@ struct NodeInfo { + uint64_t node_mem; + struct HostMemoryBackend *node_memdev; + bool present; ++ bool has_cpu; ++ uint16_t initiator; + uint8_t distance[MAX_NODES]; + }; + +@@ -33,6 +35,9 @@ struct NumaState { + /* Allow setting NUMA distance for different NUMA nodes */ + bool have_numa_distance; + ++ /* Detect if HMAT support is enabled. */ ++ bool hmat_enabled; ++ + /* NUMA nodes information */ + NodeInfo nodes[MAX_NODES]; + }; +diff --git a/qapi/machine.json b/qapi/machine.json +index ca26779..27d0e37 100644 +--- a/qapi/machine.json ++++ b/qapi/machine.json +@@ -463,6 +463,13 @@ + # @memdev: memory backend object. If specified for one node, + # it must be specified for all nodes. + # ++# @initiator: defined in ACPI 6.3 Chapter 5.2.27.3 Table 5-145, ++# points to the nodeid which has the memory controller ++# responsible for this NUMA node. This field provides ++# additional information as to the initiator node that ++# is closest (as in directly attached) to this node, and ++# therefore has the best performance (since 5.0) ++# + # Since: 2.1 + ## + { 'struct': 'NumaNodeOptions', +@@ -470,7 +477,8 @@ + '*nodeid': 'uint16', + '*cpus': ['uint16'], + '*mem': 'size', +- '*memdev': 'str' }} ++ '*memdev': 'str', ++ '*initiator': 'uint16' }} + + ## + # @NumaDistOptions: +diff --git a/qemu-options.hx b/qemu-options.hx +index df1d27b..e2ce754 100644 +--- a/qemu-options.hx ++++ b/qemu-options.hx +@@ -43,7 +43,8 @@ DEF("machine", HAS_ARG, QEMU_OPTION_machine, \ + " suppress-vmdesc=on|off disables self-describing migration (default=off)\n" + " nvdimm=on|off controls NVDIMM support (default=off)\n" + " enforce-config-section=on|off enforce configuration section migration (default=off)\n" +- " memory-encryption=@var{} memory encryption object to use (default=none)\n", ++ " memory-encryption=@var{} memory encryption object to use (default=none)\n" ++ " hmat=on|off controls ACPI HMAT support (default=off)\n", + QEMU_ARCH_ALL) + STEXI + @item -machine [type=]@var{name}[,prop=@var{value}[,...]] +@@ -103,6 +104,9 @@ NOTE: this parameter is deprecated. Please use @option{-global} + @option{migration.send-configuration}=@var{on|off} instead. + @item memory-encryption=@var{} + Memory encryption object to use. The default is none. ++@item hmat=on|off ++Enables or disables ACPI Heterogeneous Memory Attribute Table (HMAT) support. ++The default is off. + @end table + ETEXI + +@@ -161,14 +165,14 @@ If any on the three values is given, the total number of CPUs @var{n} can be omi + ETEXI + + DEF("numa", HAS_ARG, QEMU_OPTION_numa, +- "-numa node[,mem=size][,cpus=firstcpu[-lastcpu]][,nodeid=node]\n" +- "-numa node[,memdev=id][,cpus=firstcpu[-lastcpu]][,nodeid=node]\n" ++ "-numa node[,mem=size][,cpus=firstcpu[-lastcpu]][,nodeid=node][,initiator=node]\n" ++ "-numa node[,memdev=id][,cpus=firstcpu[-lastcpu]][,nodeid=node][,initiator=node]\n" + "-numa dist,src=source,dst=destination,val=distance\n" + "-numa cpu,node-id=node[,socket-id=x][,core-id=y][,thread-id=z]\n", + QEMU_ARCH_ALL) + STEXI +-@item -numa node[,mem=@var{size}][,cpus=@var{firstcpu}[-@var{lastcpu}]][,nodeid=@var{node}] +-@itemx -numa node[,memdev=@var{id}][,cpus=@var{firstcpu}[-@var{lastcpu}]][,nodeid=@var{node}] ++@item -numa node[,mem=@var{size}][,cpus=@var{firstcpu}[-@var{lastcpu}]][,nodeid=@var{node}][,initiator=@var{initiator}] ++@itemx -numa node[,memdev=@var{id}][,cpus=@var{firstcpu}[-@var{lastcpu}]][,nodeid=@var{node}][,initiator=@var{initiator}] + @itemx -numa dist,src=@var{source},dst=@var{destination},val=@var{distance} + @itemx -numa cpu,node-id=@var{node}[,socket-id=@var{x}][,core-id=@var{y}][,thread-id=@var{z}] + @findex -numa +@@ -215,6 +219,27 @@ split equally between them. + @samp{mem} and @samp{memdev} are mutually exclusive. Furthermore, + if one node uses @samp{memdev}, all of them have to use it. + ++@samp{initiator} is an additional option that points to an @var{initiator} ++NUMA node that has best performance (the lowest latency or largest bandwidth) ++to this NUMA @var{node}. Note that this option can be set only when ++the machine property 'hmat' is set to 'on'. ++ ++Following example creates a machine with 2 NUMA nodes, node 0 has CPU. ++node 1 has only memory, and its initiator is node 0. Note that because ++node 0 has CPU, by default the initiator of node 0 is itself and must be ++itself. ++@example ++-machine hmat=on \ ++-m 2G,slots=2,maxmem=4G \ ++-object memory-backend-ram,size=1G,id=m0 \ ++-object memory-backend-ram,size=1G,id=m1 \ ++-numa node,nodeid=0,memdev=m0 \ ++-numa node,nodeid=1,memdev=m1,initiator=0 \ ++-smp 2,sockets=2,maxcpus=2 \ ++-numa cpu,node-id=0,socket-id=0 \ ++-numa cpu,node-id=0,socket-id=1 ++@end example ++ + @var{source} and @var{destination} are NUMA node IDs. + @var{distance} is the NUMA distance from @var{source} to @var{destination}. + The distance from a node to itself is always 10. If any pair of nodes is +-- +1.8.3.1 + diff --git a/SOURCES/kvm-numa-Extend-CLI-to-provide-memory-latency-and-bandwi.patch b/SOURCES/kvm-numa-Extend-CLI-to-provide-memory-latency-and-bandwi.patch new file mode 100644 index 0000000..306abeb --- /dev/null +++ b/SOURCES/kvm-numa-Extend-CLI-to-provide-memory-latency-and-bandwi.patch @@ -0,0 +1,545 @@ +From 32341d8cf680625def040b44d70b197f2399bbdb Mon Sep 17 00:00:00 2001 +From: "plai@redhat.com" +Date: Thu, 21 May 2020 23:56:48 +0100 +Subject: [PATCH 05/12] numa: Extend CLI to provide memory latency and + bandwidth information + +RH-Author: plai@redhat.com +Message-id: <20200521235655.27141-5-plai@redhat.com> +Patchwork-id: 96731 +O-Subject: [RHEL8.2.1 AV qemu-kvm PATCH 04/11] numa: Extend CLI to provide memory latency and bandwidth information +Bugzilla: 1600217 +RH-Acked-by: Michael S. Tsirkin +RH-Acked-by: Igor Mammedov +RH-Acked-by: Eduardo Habkost + +From: Liu Jingqi + +Add -numa hmat-lb option to provide System Locality Latency and +Bandwidth Information. These memory attributes help to build +System Locality Latency and Bandwidth Information Structure(s) +in ACPI Heterogeneous Memory Attribute Table (HMAT). Before using +hmat-lb option, enable HMAT with -machine hmat=on. + +Acked-by: Markus Armbruster +Signed-off-by: Liu Jingqi +Signed-off-by: Tao Xu +Message-Id: <20191213011929.2520-3-tao3.xu@intel.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Reviewed-by: Igor Mammedov +(cherry picked from commit 9b12dfa03a94d7f7a4b54eb67229a31e58193384) +Signed-off-by: Paul Lai +Signed-off-by: Danilo C. L. de Paula +--- + hw/core/numa.c | 194 ++++++++++++++++++++++++++++++++++++++++++++++++++ + include/sysemu/numa.h | 53 ++++++++++++++ + qapi/machine.json | 93 +++++++++++++++++++++++- + qemu-options.hx | 47 +++++++++++- + 4 files changed, 384 insertions(+), 3 deletions(-) + +diff --git a/hw/core/numa.c b/hw/core/numa.c +index a07eef9..58fe713 100644 +--- a/hw/core/numa.c ++++ b/hw/core/numa.c +@@ -23,6 +23,7 @@ + */ + + #include "qemu/osdep.h" ++#include "qemu/units.h" + #include "sysemu/hostmem.h" + #include "sysemu/numa.h" + #include "sysemu/sysemu.h" +@@ -194,6 +195,186 @@ void parse_numa_distance(MachineState *ms, NumaDistOptions *dist, Error **errp) + ms->numa_state->have_numa_distance = true; + } + ++void parse_numa_hmat_lb(NumaState *numa_state, NumaHmatLBOptions *node, ++ Error **errp) ++{ ++ int i, first_bit, last_bit; ++ uint64_t max_entry, temp_base, bitmap_copy; ++ NodeInfo *numa_info = numa_state->nodes; ++ HMAT_LB_Info *hmat_lb = ++ numa_state->hmat_lb[node->hierarchy][node->data_type]; ++ HMAT_LB_Data lb_data = {}; ++ HMAT_LB_Data *lb_temp; ++ ++ /* Error checking */ ++ if (node->initiator > numa_state->num_nodes) { ++ error_setg(errp, "Invalid initiator=%d, it should be less than %d", ++ node->initiator, numa_state->num_nodes); ++ return; ++ } ++ if (node->target > numa_state->num_nodes) { ++ error_setg(errp, "Invalid target=%d, it should be less than %d", ++ node->target, numa_state->num_nodes); ++ return; ++ } ++ if (!numa_info[node->initiator].has_cpu) { ++ error_setg(errp, "Invalid initiator=%d, it isn't an " ++ "initiator proximity domain", node->initiator); ++ return; ++ } ++ if (!numa_info[node->target].present) { ++ error_setg(errp, "The target=%d should point to an existing node", ++ node->target); ++ return; ++ } ++ ++ if (!hmat_lb) { ++ hmat_lb = g_malloc0(sizeof(*hmat_lb)); ++ numa_state->hmat_lb[node->hierarchy][node->data_type] = hmat_lb; ++ hmat_lb->list = g_array_new(false, true, sizeof(HMAT_LB_Data)); ++ } ++ hmat_lb->hierarchy = node->hierarchy; ++ hmat_lb->data_type = node->data_type; ++ lb_data.initiator = node->initiator; ++ lb_data.target = node->target; ++ ++ if (node->data_type <= HMATLB_DATA_TYPE_WRITE_LATENCY) { ++ /* Input latency data */ ++ ++ if (!node->has_latency) { ++ error_setg(errp, "Missing 'latency' option"); ++ return; ++ } ++ if (node->has_bandwidth) { ++ error_setg(errp, "Invalid option 'bandwidth' since " ++ "the data type is latency"); ++ return; ++ } ++ ++ /* Detect duplicate configuration */ ++ for (i = 0; i < hmat_lb->list->len; i++) { ++ lb_temp = &g_array_index(hmat_lb->list, HMAT_LB_Data, i); ++ ++ if (node->initiator == lb_temp->initiator && ++ node->target == lb_temp->target) { ++ error_setg(errp, "Duplicate configuration of the latency for " ++ "initiator=%d and target=%d", node->initiator, ++ node->target); ++ return; ++ } ++ } ++ ++ hmat_lb->base = hmat_lb->base ? hmat_lb->base : UINT64_MAX; ++ ++ if (node->latency) { ++ /* Calculate the temporary base and compressed latency */ ++ max_entry = node->latency; ++ temp_base = 1; ++ while (QEMU_IS_ALIGNED(max_entry, 10)) { ++ max_entry /= 10; ++ temp_base *= 10; ++ } ++ ++ /* Calculate the max compressed latency */ ++ temp_base = MIN(hmat_lb->base, temp_base); ++ max_entry = node->latency / hmat_lb->base; ++ max_entry = MAX(hmat_lb->range_bitmap, max_entry); ++ ++ /* ++ * For latency hmat_lb->range_bitmap record the max compressed ++ * latency which should be less than 0xFFFF (UINT16_MAX) ++ */ ++ if (max_entry >= UINT16_MAX) { ++ error_setg(errp, "Latency %" PRIu64 " between initiator=%d and " ++ "target=%d should not differ from previously entered " ++ "min or max values on more than %d", node->latency, ++ node->initiator, node->target, UINT16_MAX - 1); ++ return; ++ } else { ++ hmat_lb->base = temp_base; ++ hmat_lb->range_bitmap = max_entry; ++ } ++ ++ /* ++ * Set lb_info_provided bit 0 as 1, ++ * latency information is provided ++ */ ++ numa_info[node->target].lb_info_provided |= BIT(0); ++ } ++ lb_data.data = node->latency; ++ } else if (node->data_type >= HMATLB_DATA_TYPE_ACCESS_BANDWIDTH) { ++ /* Input bandwidth data */ ++ if (!node->has_bandwidth) { ++ error_setg(errp, "Missing 'bandwidth' option"); ++ return; ++ } ++ if (node->has_latency) { ++ error_setg(errp, "Invalid option 'latency' since " ++ "the data type is bandwidth"); ++ return; ++ } ++ if (!QEMU_IS_ALIGNED(node->bandwidth, MiB)) { ++ error_setg(errp, "Bandwidth %" PRIu64 " between initiator=%d and " ++ "target=%d should be 1MB aligned", node->bandwidth, ++ node->initiator, node->target); ++ return; ++ } ++ ++ /* Detect duplicate configuration */ ++ for (i = 0; i < hmat_lb->list->len; i++) { ++ lb_temp = &g_array_index(hmat_lb->list, HMAT_LB_Data, i); ++ ++ if (node->initiator == lb_temp->initiator && ++ node->target == lb_temp->target) { ++ error_setg(errp, "Duplicate configuration of the bandwidth for " ++ "initiator=%d and target=%d", node->initiator, ++ node->target); ++ return; ++ } ++ } ++ ++ hmat_lb->base = hmat_lb->base ? hmat_lb->base : 1; ++ ++ if (node->bandwidth) { ++ /* Keep bitmap unchanged when bandwidth out of range */ ++ bitmap_copy = hmat_lb->range_bitmap; ++ bitmap_copy |= node->bandwidth; ++ first_bit = ctz64(bitmap_copy); ++ temp_base = UINT64_C(1) << first_bit; ++ max_entry = node->bandwidth / temp_base; ++ last_bit = 64 - clz64(bitmap_copy); ++ ++ /* ++ * For bandwidth, first_bit record the base unit of bandwidth bits, ++ * last_bit record the last bit of the max bandwidth. The max ++ * compressed bandwidth should be less than 0xFFFF (UINT16_MAX) ++ */ ++ if ((last_bit - first_bit) > UINT16_BITS || ++ max_entry >= UINT16_MAX) { ++ error_setg(errp, "Bandwidth %" PRIu64 " between initiator=%d " ++ "and target=%d should not differ from previously " ++ "entered values on more than %d", node->bandwidth, ++ node->initiator, node->target, UINT16_MAX - 1); ++ return; ++ } else { ++ hmat_lb->base = temp_base; ++ hmat_lb->range_bitmap = bitmap_copy; ++ } ++ ++ /* ++ * Set lb_info_provided bit 1 as 1, ++ * bandwidth information is provided ++ */ ++ numa_info[node->target].lb_info_provided |= BIT(1); ++ } ++ lb_data.data = node->bandwidth; ++ } else { ++ assert(0); ++ } ++ ++ g_array_append_val(hmat_lb->list, lb_data); ++} ++ + void set_numa_options(MachineState *ms, NumaOptions *object, Error **errp) + { + Error *err = NULL; +@@ -231,6 +412,19 @@ void set_numa_options(MachineState *ms, NumaOptions *object, Error **errp) + machine_set_cpu_numa_node(ms, qapi_NumaCpuOptions_base(&object->u.cpu), + &err); + break; ++ case NUMA_OPTIONS_TYPE_HMAT_LB: ++ if (!ms->numa_state->hmat_enabled) { ++ error_setg(errp, "ACPI Heterogeneous Memory Attribute Table " ++ "(HMAT) is disabled, enable it with -machine hmat=on " ++ "before using any of hmat specific options"); ++ return; ++ } ++ ++ parse_numa_hmat_lb(ms->numa_state, &object->u.hmat_lb, &err); ++ if (err) { ++ goto end; ++ } ++ break; + default: + abort(); + } +diff --git a/include/sysemu/numa.h b/include/sysemu/numa.h +index 788cbec..70f93c8 100644 +--- a/include/sysemu/numa.h ++++ b/include/sysemu/numa.h +@@ -14,11 +14,34 @@ struct CPUArchId; + #define NUMA_DISTANCE_MAX 254 + #define NUMA_DISTANCE_UNREACHABLE 255 + ++/* the value of AcpiHmatLBInfo flags */ ++enum { ++ HMAT_LB_MEM_MEMORY = 0, ++ HMAT_LB_MEM_CACHE_1ST_LEVEL = 1, ++ HMAT_LB_MEM_CACHE_2ND_LEVEL = 2, ++ HMAT_LB_MEM_CACHE_3RD_LEVEL = 3, ++ HMAT_LB_LEVELS /* must be the last entry */ ++}; ++ ++/* the value of AcpiHmatLBInfo data type */ ++enum { ++ HMAT_LB_DATA_ACCESS_LATENCY = 0, ++ HMAT_LB_DATA_READ_LATENCY = 1, ++ HMAT_LB_DATA_WRITE_LATENCY = 2, ++ HMAT_LB_DATA_ACCESS_BANDWIDTH = 3, ++ HMAT_LB_DATA_READ_BANDWIDTH = 4, ++ HMAT_LB_DATA_WRITE_BANDWIDTH = 5, ++ HMAT_LB_TYPES /* must be the last entry */ ++}; ++ ++#define UINT16_BITS 16 ++ + struct NodeInfo { + uint64_t node_mem; + struct HostMemoryBackend *node_memdev; + bool present; + bool has_cpu; ++ uint8_t lb_info_provided; + uint16_t initiator; + uint8_t distance[MAX_NODES]; + }; +@@ -28,6 +51,31 @@ struct NumaNodeMem { + uint64_t node_plugged_mem; + }; + ++struct HMAT_LB_Data { ++ uint8_t initiator; ++ uint8_t target; ++ uint64_t data; ++}; ++typedef struct HMAT_LB_Data HMAT_LB_Data; ++ ++struct HMAT_LB_Info { ++ /* Indicates it's memory or the specified level memory side cache. */ ++ uint8_t hierarchy; ++ ++ /* Present the type of data, access/read/write latency or bandwidth. */ ++ uint8_t data_type; ++ ++ /* The range bitmap of bandwidth for calculating common base */ ++ uint64_t range_bitmap; ++ ++ /* The common base unit for latencies or bandwidths */ ++ uint64_t base; ++ ++ /* Array to store the latencies or bandwidths */ ++ GArray *list; ++}; ++typedef struct HMAT_LB_Info HMAT_LB_Info; ++ + struct NumaState { + /* Number of NUMA nodes */ + int num_nodes; +@@ -40,11 +88,16 @@ struct NumaState { + + /* NUMA nodes information */ + NodeInfo nodes[MAX_NODES]; ++ ++ /* NUMA nodes HMAT Locality Latency and Bandwidth Information */ ++ HMAT_LB_Info *hmat_lb[HMAT_LB_LEVELS][HMAT_LB_TYPES]; + }; + typedef struct NumaState NumaState; + + void set_numa_options(MachineState *ms, NumaOptions *object, Error **errp); + void parse_numa_opts(MachineState *ms); ++void parse_numa_hmat_lb(NumaState *numa_state, NumaHmatLBOptions *node, ++ Error **errp); + void numa_complete_configuration(MachineState *ms); + void query_numa_node_mem(NumaNodeMem node_mem[], MachineState *ms); + extern QemuOptsList qemu_numa_opts; +diff --git a/qapi/machine.json b/qapi/machine.json +index 27d0e37..cf8faf5 100644 +--- a/qapi/machine.json ++++ b/qapi/machine.json +@@ -426,10 +426,12 @@ + # + # @cpu: property based CPU(s) to node mapping (Since: 2.10) + # ++# @hmat-lb: memory latency and bandwidth information (Since: 5.0) ++# + # Since: 2.1 + ## + { 'enum': 'NumaOptionsType', +- 'data': [ 'node', 'dist', 'cpu' ] } ++ 'data': [ 'node', 'dist', 'cpu', 'hmat-lb' ] } + + ## + # @NumaOptions: +@@ -444,7 +446,8 @@ + 'data': { + 'node': 'NumaNodeOptions', + 'dist': 'NumaDistOptions', +- 'cpu': 'NumaCpuOptions' }} ++ 'cpu': 'NumaCpuOptions', ++ 'hmat-lb': 'NumaHmatLBOptions' }} + + ## + # @NumaNodeOptions: +@@ -558,6 +561,92 @@ + 'data' : {} } + + ## ++# @HmatLBMemoryHierarchy: ++# ++# The memory hierarchy in the System Locality Latency and Bandwidth ++# Information Structure of HMAT (Heterogeneous Memory Attribute Table) ++# ++# For more information about @HmatLBMemoryHierarchy, see chapter ++# 5.2.27.4: Table 5-146: Field "Flags" of ACPI 6.3 spec. ++# ++# @memory: the structure represents the memory performance ++# ++# @first-level: first level of memory side cache ++# ++# @second-level: second level of memory side cache ++# ++# @third-level: third level of memory side cache ++# ++# Since: 5.0 ++## ++{ 'enum': 'HmatLBMemoryHierarchy', ++ 'data': [ 'memory', 'first-level', 'second-level', 'third-level' ] } ++ ++## ++# @HmatLBDataType: ++# ++# Data type in the System Locality Latency and Bandwidth ++# Information Structure of HMAT (Heterogeneous Memory Attribute Table) ++# ++# For more information about @HmatLBDataType, see chapter ++# 5.2.27.4: Table 5-146: Field "Data Type" of ACPI 6.3 spec. ++# ++# @access-latency: access latency (nanoseconds) ++# ++# @read-latency: read latency (nanoseconds) ++# ++# @write-latency: write latency (nanoseconds) ++# ++# @access-bandwidth: access bandwidth (Bytes per second) ++# ++# @read-bandwidth: read bandwidth (Bytes per second) ++# ++# @write-bandwidth: write bandwidth (Bytes per second) ++# ++# Since: 5.0 ++## ++{ 'enum': 'HmatLBDataType', ++ 'data': [ 'access-latency', 'read-latency', 'write-latency', ++ 'access-bandwidth', 'read-bandwidth', 'write-bandwidth' ] } ++ ++## ++# @NumaHmatLBOptions: ++# ++# Set the system locality latency and bandwidth information ++# between Initiator and Target proximity Domains. ++# ++# For more information about @NumaHmatLBOptions, see chapter ++# 5.2.27.4: Table 5-146 of ACPI 6.3 spec. ++# ++# @initiator: the Initiator Proximity Domain. ++# ++# @target: the Target Proximity Domain. ++# ++# @hierarchy: the Memory Hierarchy. Indicates the performance ++# of memory or side cache. ++# ++# @data-type: presents the type of data, access/read/write ++# latency or hit latency. ++# ++# @latency: the value of latency from @initiator to @target ++# proximity domain, the latency unit is "ns(nanosecond)". ++# ++# @bandwidth: the value of bandwidth between @initiator and @target ++# proximity domain, the bandwidth unit is ++# "Bytes per second". ++# ++# Since: 5.0 ++## ++{ 'struct': 'NumaHmatLBOptions', ++ 'data': { ++ 'initiator': 'uint16', ++ 'target': 'uint16', ++ 'hierarchy': 'HmatLBMemoryHierarchy', ++ 'data-type': 'HmatLBDataType', ++ '*latency': 'uint64', ++ '*bandwidth': 'size' }} ++ ++## + # @HostMemPolicy: + # + # Host memory policy types +diff --git a/qemu-options.hx b/qemu-options.hx +index e2ce754..86d9d8a 100644 +--- a/qemu-options.hx ++++ b/qemu-options.hx +@@ -168,16 +168,19 @@ DEF("numa", HAS_ARG, QEMU_OPTION_numa, + "-numa node[,mem=size][,cpus=firstcpu[-lastcpu]][,nodeid=node][,initiator=node]\n" + "-numa node[,memdev=id][,cpus=firstcpu[-lastcpu]][,nodeid=node][,initiator=node]\n" + "-numa dist,src=source,dst=destination,val=distance\n" +- "-numa cpu,node-id=node[,socket-id=x][,core-id=y][,thread-id=z]\n", ++ "-numa cpu,node-id=node[,socket-id=x][,core-id=y][,thread-id=z]\n" ++ "-numa hmat-lb,initiator=node,target=node,hierarchy=memory|first-level|second-level|third-level,data-type=access-latency|read-latency|write-latency[,latency=lat][,bandwidth=bw]\n", + QEMU_ARCH_ALL) + STEXI + @item -numa node[,mem=@var{size}][,cpus=@var{firstcpu}[-@var{lastcpu}]][,nodeid=@var{node}][,initiator=@var{initiator}] + @itemx -numa node[,memdev=@var{id}][,cpus=@var{firstcpu}[-@var{lastcpu}]][,nodeid=@var{node}][,initiator=@var{initiator}] + @itemx -numa dist,src=@var{source},dst=@var{destination},val=@var{distance} + @itemx -numa cpu,node-id=@var{node}[,socket-id=@var{x}][,core-id=@var{y}][,thread-id=@var{z}] ++@itemx -numa hmat-lb,initiator=@var{node},target=@var{node},hierarchy=@var{hierarchy},data-type=@var{tpye}[,latency=@var{lat}][,bandwidth=@var{bw}] + @findex -numa + Define a NUMA node and assign RAM and VCPUs to it. + Set the NUMA distance from a source node to a destination node. ++Set the ACPI Heterogeneous Memory Attributes for the given nodes. + + Legacy VCPU assignment uses @samp{cpus} option where + @var{firstcpu} and @var{lastcpu} are CPU indexes. Each +@@ -256,6 +259,48 @@ specified resources, it just assigns existing resources to NUMA + nodes. This means that one still has to use the @option{-m}, + @option{-smp} options to allocate RAM and VCPUs respectively. + ++Use @samp{hmat-lb} to set System Locality Latency and Bandwidth Information ++between initiator and target NUMA nodes in ACPI Heterogeneous Attribute Memory Table (HMAT). ++Initiator NUMA node can create memory requests, usually it has one or more processors. ++Target NUMA node contains addressable memory. ++ ++In @samp{hmat-lb} option, @var{node} are NUMA node IDs. @var{hierarchy} is the memory ++hierarchy of the target NUMA node: if @var{hierarchy} is 'memory', the structure ++represents the memory performance; if @var{hierarchy} is 'first-level|second-level|third-level', ++this structure represents aggregated performance of memory side caches for each domain. ++@var{type} of 'data-type' is type of data represented by this structure instance: ++if 'hierarchy' is 'memory', 'data-type' is 'access|read|write' latency or 'access|read|write' ++bandwidth of the target memory; if 'hierarchy' is 'first-level|second-level|third-level', ++'data-type' is 'access|read|write' hit latency or 'access|read|write' hit bandwidth of the ++target memory side cache. ++ ++@var{lat} is latency value in nanoseconds. @var{bw} is bandwidth value, ++the possible value and units are NUM[M|G|T], mean that the bandwidth value are ++NUM byte per second (or MB/s, GB/s or TB/s depending on used suffix). ++Note that if latency or bandwidth value is 0, means the corresponding latency or ++bandwidth information is not provided. ++ ++For example, the following options describe 2 NUMA nodes. Node 0 has 2 cpus and ++a ram, node 1 has only a ram. The processors in node 0 access memory in node ++0 with access-latency 5 nanoseconds, access-bandwidth is 200 MB/s; ++The processors in NUMA node 0 access memory in NUMA node 1 with access-latency 10 ++nanoseconds, access-bandwidth is 100 MB/s. ++@example ++-machine hmat=on \ ++-m 2G \ ++-object memory-backend-ram,size=1G,id=m0 \ ++-object memory-backend-ram,size=1G,id=m1 \ ++-smp 2 \ ++-numa node,nodeid=0,memdev=m0 \ ++-numa node,nodeid=1,memdev=m1,initiator=0 \ ++-numa cpu,node-id=0,socket-id=0 \ ++-numa cpu,node-id=0,socket-id=1 \ ++-numa hmat-lb,initiator=0,target=0,hierarchy=memory,data-type=access-latency,latency=5 \ ++-numa hmat-lb,initiator=0,target=0,hierarchy=memory,data-type=access-bandwidth,bandwidth=200M \ ++-numa hmat-lb,initiator=0,target=1,hierarchy=memory,data-type=access-latency,latency=10 \ ++-numa hmat-lb,initiator=0,target=1,hierarchy=memory,data-type=access-bandwidth,bandwidth=100M ++@end example ++ + ETEXI + + DEF("add-fd", HAS_ARG, QEMU_OPTION_add_fd, +-- +1.8.3.1 + diff --git a/SOURCES/kvm-numa-Extend-CLI-to-provide-memory-side-cache-informa.patch b/SOURCES/kvm-numa-Extend-CLI-to-provide-memory-side-cache-informa.patch new file mode 100644 index 0000000..a17db22 --- /dev/null +++ b/SOURCES/kvm-numa-Extend-CLI-to-provide-memory-side-cache-informa.patch @@ -0,0 +1,326 @@ +From 8cd3544b1347b248b9d04eb3d6c9b9bde3a13655 Mon Sep 17 00:00:00 2001 +From: "plai@redhat.com" +Date: Thu, 21 May 2020 23:56:49 +0100 +Subject: [PATCH 06/12] numa: Extend CLI to provide memory side cache + information + +RH-Author: plai@redhat.com +Message-id: <20200521235655.27141-6-plai@redhat.com> +Patchwork-id: 96740 +O-Subject: [RHEL8.2.1 AV qemu-kvm PATCH 05/11] numa: Extend CLI to provide memory side cache information +Bugzilla: 1600217 +RH-Acked-by: Michael S. Tsirkin +RH-Acked-by: Igor Mammedov +RH-Acked-by: Eduardo Habkost + +From: Liu Jingqi + +Add -numa hmat-cache option to provide Memory Side Cache Information. +These memory attributes help to build Memory Side Cache Information +Structure(s) in ACPI Heterogeneous Memory Attribute Table (HMAT). +Before using hmat-cache option, enable HMAT with -machine hmat=on. + +Acked-by: Markus Armbruster +Signed-off-by: Liu Jingqi +Signed-off-by: Tao Xu +Message-Id: <20191213011929.2520-4-tao3.xu@intel.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Reviewed-by: Igor Mammedov +(cherry picked from commit c412a48d4d91e8f8b89aae02de0f44f1f0b729e5) +Signed-off-by: Paul Lai +Signed-off-by: Danilo C. L. de Paula +--- + hw/core/numa.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++ + include/sysemu/numa.h | 5 ++++ + qapi/machine.json | 81 +++++++++++++++++++++++++++++++++++++++++++++++++-- + qemu-options.hx | 17 +++++++++-- + 4 files changed, 179 insertions(+), 4 deletions(-) + +diff --git a/hw/core/numa.c b/hw/core/numa.c +index 58fe713..0d1b4be 100644 +--- a/hw/core/numa.c ++++ b/hw/core/numa.c +@@ -375,6 +375,73 @@ void parse_numa_hmat_lb(NumaState *numa_state, NumaHmatLBOptions *node, + g_array_append_val(hmat_lb->list, lb_data); + } + ++void parse_numa_hmat_cache(MachineState *ms, NumaHmatCacheOptions *node, ++ Error **errp) ++{ ++ int nb_numa_nodes = ms->numa_state->num_nodes; ++ NodeInfo *numa_info = ms->numa_state->nodes; ++ NumaHmatCacheOptions *hmat_cache = NULL; ++ ++ if (node->node_id >= nb_numa_nodes) { ++ error_setg(errp, "Invalid node-id=%" PRIu32 ", it should be less " ++ "than %d", node->node_id, nb_numa_nodes); ++ return; ++ } ++ ++ if (numa_info[node->node_id].lb_info_provided != (BIT(0) | BIT(1))) { ++ error_setg(errp, "The latency and bandwidth information of " ++ "node-id=%" PRIu32 " should be provided before memory side " ++ "cache attributes", node->node_id); ++ return; ++ } ++ ++ if (node->level < 1 || node->level >= HMAT_LB_LEVELS) { ++ error_setg(errp, "Invalid level=%" PRIu8 ", it should be larger than 0 " ++ "and less than or equal to %d", node->level, ++ HMAT_LB_LEVELS - 1); ++ return; ++ } ++ ++ assert(node->associativity < HMAT_CACHE_ASSOCIATIVITY__MAX); ++ assert(node->policy < HMAT_CACHE_WRITE_POLICY__MAX); ++ if (ms->numa_state->hmat_cache[node->node_id][node->level]) { ++ error_setg(errp, "Duplicate configuration of the side cache for " ++ "node-id=%" PRIu32 " and level=%" PRIu8, ++ node->node_id, node->level); ++ return; ++ } ++ ++ if ((node->level > 1) && ++ ms->numa_state->hmat_cache[node->node_id][node->level - 1] && ++ (node->size >= ++ ms->numa_state->hmat_cache[node->node_id][node->level - 1]->size)) { ++ error_setg(errp, "Invalid size=%" PRIu64 ", the size of level=%" PRIu8 ++ " should be less than the size(%" PRIu64 ") of " ++ "level=%u", node->size, node->level, ++ ms->numa_state->hmat_cache[node->node_id] ++ [node->level - 1]->size, ++ node->level - 1); ++ return; ++ } ++ ++ if ((node->level < HMAT_LB_LEVELS - 1) && ++ ms->numa_state->hmat_cache[node->node_id][node->level + 1] && ++ (node->size <= ++ ms->numa_state->hmat_cache[node->node_id][node->level + 1]->size)) { ++ error_setg(errp, "Invalid size=%" PRIu64 ", the size of level=%" PRIu8 ++ " should be larger than the size(%" PRIu64 ") of " ++ "level=%u", node->size, node->level, ++ ms->numa_state->hmat_cache[node->node_id] ++ [node->level + 1]->size, ++ node->level + 1); ++ return; ++ } ++ ++ hmat_cache = g_malloc0(sizeof(*hmat_cache)); ++ memcpy(hmat_cache, node, sizeof(*hmat_cache)); ++ ms->numa_state->hmat_cache[node->node_id][node->level] = hmat_cache; ++} ++ + void set_numa_options(MachineState *ms, NumaOptions *object, Error **errp) + { + Error *err = NULL; +@@ -425,6 +492,19 @@ void set_numa_options(MachineState *ms, NumaOptions *object, Error **errp) + goto end; + } + break; ++ case NUMA_OPTIONS_TYPE_HMAT_CACHE: ++ if (!ms->numa_state->hmat_enabled) { ++ error_setg(errp, "ACPI Heterogeneous Memory Attribute Table " ++ "(HMAT) is disabled, enable it with -machine hmat=on " ++ "before using any of hmat specific options"); ++ return; ++ } ++ ++ parse_numa_hmat_cache(ms, &object->u.hmat_cache, &err); ++ if (err) { ++ goto end; ++ } ++ break; + default: + abort(); + } +diff --git a/include/sysemu/numa.h b/include/sysemu/numa.h +index 70f93c8..ba693cc 100644 +--- a/include/sysemu/numa.h ++++ b/include/sysemu/numa.h +@@ -91,6 +91,9 @@ struct NumaState { + + /* NUMA nodes HMAT Locality Latency and Bandwidth Information */ + HMAT_LB_Info *hmat_lb[HMAT_LB_LEVELS][HMAT_LB_TYPES]; ++ ++ /* Memory Side Cache Information Structure */ ++ NumaHmatCacheOptions *hmat_cache[MAX_NODES][HMAT_LB_LEVELS]; + }; + typedef struct NumaState NumaState; + +@@ -98,6 +101,8 @@ void set_numa_options(MachineState *ms, NumaOptions *object, Error **errp); + void parse_numa_opts(MachineState *ms); + void parse_numa_hmat_lb(NumaState *numa_state, NumaHmatLBOptions *node, + Error **errp); ++void parse_numa_hmat_cache(MachineState *ms, NumaHmatCacheOptions *node, ++ Error **errp); + void numa_complete_configuration(MachineState *ms); + void query_numa_node_mem(NumaNodeMem node_mem[], MachineState *ms); + extern QemuOptsList qemu_numa_opts; +diff --git a/qapi/machine.json b/qapi/machine.json +index cf8faf5..b3d30bc 100644 +--- a/qapi/machine.json ++++ b/qapi/machine.json +@@ -428,10 +428,12 @@ + # + # @hmat-lb: memory latency and bandwidth information (Since: 5.0) + # ++# @hmat-cache: memory side cache information (Since: 5.0) ++# + # Since: 2.1 + ## + { 'enum': 'NumaOptionsType', +- 'data': [ 'node', 'dist', 'cpu', 'hmat-lb' ] } ++ 'data': [ 'node', 'dist', 'cpu', 'hmat-lb', 'hmat-cache' ] } + + ## + # @NumaOptions: +@@ -447,7 +449,8 @@ + 'node': 'NumaNodeOptions', + 'dist': 'NumaDistOptions', + 'cpu': 'NumaCpuOptions', +- 'hmat-lb': 'NumaHmatLBOptions' }} ++ 'hmat-lb': 'NumaHmatLBOptions', ++ 'hmat-cache': 'NumaHmatCacheOptions' }} + + ## + # @NumaNodeOptions: +@@ -647,6 +650,80 @@ + '*bandwidth': 'size' }} + + ## ++# @HmatCacheAssociativity: ++# ++# Cache associativity in the Memory Side Cache Information Structure ++# of HMAT ++# ++# For more information of @HmatCacheAssociativity, see chapter ++# 5.2.27.5: Table 5-147 of ACPI 6.3 spec. ++# ++# @none: None (no memory side cache in this proximity domain, ++# or cache associativity unknown) ++# ++# @direct: Direct Mapped ++# ++# @complex: Complex Cache Indexing (implementation specific) ++# ++# Since: 5.0 ++## ++{ 'enum': 'HmatCacheAssociativity', ++ 'data': [ 'none', 'direct', 'complex' ] } ++ ++## ++# @HmatCacheWritePolicy: ++# ++# Cache write policy in the Memory Side Cache Information Structure ++# of HMAT ++# ++# For more information of @HmatCacheWritePolicy, see chapter ++# 5.2.27.5: Table 5-147: Field "Cache Attributes" of ACPI 6.3 spec. ++# ++# @none: None (no memory side cache in this proximity domain, ++# or cache write policy unknown) ++# ++# @write-back: Write Back (WB) ++# ++# @write-through: Write Through (WT) ++# ++# Since: 5.0 ++## ++{ 'enum': 'HmatCacheWritePolicy', ++ 'data': [ 'none', 'write-back', 'write-through' ] } ++ ++## ++# @NumaHmatCacheOptions: ++# ++# Set the memory side cache information for a given memory domain. ++# ++# For more information of @NumaHmatCacheOptions, see chapter ++# 5.2.27.5: Table 5-147: Field "Cache Attributes" of ACPI 6.3 spec. ++# ++# @node-id: the memory proximity domain to which the memory belongs. ++# ++# @size: the size of memory side cache in bytes. ++# ++# @level: the cache level described in this structure. ++# ++# @associativity: the cache associativity, ++# none/direct-mapped/complex(complex cache indexing). ++# ++# @policy: the write policy, none/write-back/write-through. ++# ++# @line: the cache Line size in bytes. ++# ++# Since: 5.0 ++## ++{ 'struct': 'NumaHmatCacheOptions', ++ 'data': { ++ 'node-id': 'uint32', ++ 'size': 'size', ++ 'level': 'uint8', ++ 'associativity': 'HmatCacheAssociativity', ++ 'policy': 'HmatCacheWritePolicy', ++ 'line': 'uint16' }} ++ ++## + # @HostMemPolicy: + # + # Host memory policy types +diff --git a/qemu-options.hx b/qemu-options.hx +index 86d9d8a..8fe05b6 100644 +--- a/qemu-options.hx ++++ b/qemu-options.hx +@@ -169,7 +169,8 @@ DEF("numa", HAS_ARG, QEMU_OPTION_numa, + "-numa node[,memdev=id][,cpus=firstcpu[-lastcpu]][,nodeid=node][,initiator=node]\n" + "-numa dist,src=source,dst=destination,val=distance\n" + "-numa cpu,node-id=node[,socket-id=x][,core-id=y][,thread-id=z]\n" +- "-numa hmat-lb,initiator=node,target=node,hierarchy=memory|first-level|second-level|third-level,data-type=access-latency|read-latency|write-latency[,latency=lat][,bandwidth=bw]\n", ++ "-numa hmat-lb,initiator=node,target=node,hierarchy=memory|first-level|second-level|third-level,data-type=access-latency|read-latency|write-latency[,latency=lat][,bandwidth=bw]\n" ++ "-numa hmat-cache,node-id=node,size=size,level=level[,associativity=none|direct|complex][,policy=none|write-back|write-through][,line=size]\n", + QEMU_ARCH_ALL) + STEXI + @item -numa node[,mem=@var{size}][,cpus=@var{firstcpu}[-@var{lastcpu}]][,nodeid=@var{node}][,initiator=@var{initiator}] +@@ -177,6 +178,7 @@ STEXI + @itemx -numa dist,src=@var{source},dst=@var{destination},val=@var{distance} + @itemx -numa cpu,node-id=@var{node}[,socket-id=@var{x}][,core-id=@var{y}][,thread-id=@var{z}] + @itemx -numa hmat-lb,initiator=@var{node},target=@var{node},hierarchy=@var{hierarchy},data-type=@var{tpye}[,latency=@var{lat}][,bandwidth=@var{bw}] ++@itemx -numa hmat-cache,node-id=@var{node},size=@var{size},level=@var{level}[,associativity=@var{str}][,policy=@var{str}][,line=@var{size}] + @findex -numa + Define a NUMA node and assign RAM and VCPUs to it. + Set the NUMA distance from a source node to a destination node. +@@ -280,11 +282,20 @@ NUM byte per second (or MB/s, GB/s or TB/s depending on used suffix). + Note that if latency or bandwidth value is 0, means the corresponding latency or + bandwidth information is not provided. + ++In @samp{hmat-cache} option, @var{node-id} is the NUMA-id of the memory belongs. ++@var{size} is the size of memory side cache in bytes. @var{level} is the cache ++level described in this structure, note that the cache level 0 should not be used ++with @samp{hmat-cache} option. @var{associativity} is the cache associativity, ++the possible value is 'none/direct(direct-mapped)/complex(complex cache indexing)'. ++@var{policy} is the write policy. @var{line} is the cache Line size in bytes. ++ + For example, the following options describe 2 NUMA nodes. Node 0 has 2 cpus and + a ram, node 1 has only a ram. The processors in node 0 access memory in node + 0 with access-latency 5 nanoseconds, access-bandwidth is 200 MB/s; + The processors in NUMA node 0 access memory in NUMA node 1 with access-latency 10 + nanoseconds, access-bandwidth is 100 MB/s. ++And for memory side cache information, NUMA node 0 and 1 both have 1 level memory ++cache, size is 10KB, policy is write-back, the cache Line size is 8 bytes: + @example + -machine hmat=on \ + -m 2G \ +@@ -298,7 +309,9 @@ nanoseconds, access-bandwidth is 100 MB/s. + -numa hmat-lb,initiator=0,target=0,hierarchy=memory,data-type=access-latency,latency=5 \ + -numa hmat-lb,initiator=0,target=0,hierarchy=memory,data-type=access-bandwidth,bandwidth=200M \ + -numa hmat-lb,initiator=0,target=1,hierarchy=memory,data-type=access-latency,latency=10 \ +--numa hmat-lb,initiator=0,target=1,hierarchy=memory,data-type=access-bandwidth,bandwidth=100M ++-numa hmat-lb,initiator=0,target=1,hierarchy=memory,data-type=access-bandwidth,bandwidth=100M \ ++-numa hmat-cache,node-id=0,size=10K,level=1,associativity=direct,policy=write-back,line=8 \ ++-numa hmat-cache,node-id=1,size=10K,level=1,associativity=direct,policy=write-back,line=8 + @end example + + ETEXI +-- +1.8.3.1 + diff --git a/SOURCES/kvm-numa-properly-check-if-numa-is-supported.patch b/SOURCES/kvm-numa-properly-check-if-numa-is-supported.patch new file mode 100644 index 0000000..c602256 --- /dev/null +++ b/SOURCES/kvm-numa-properly-check-if-numa-is-supported.patch @@ -0,0 +1,81 @@ +From e3a1c2ff0d7b930b1782d59d093fd15471d3aee1 Mon Sep 17 00:00:00 2001 +From: "plai@redhat.com" +Date: Thu, 21 May 2020 23:56:46 +0100 +Subject: [PATCH 03/12] numa: properly check if numa is supported + +RH-Author: plai@redhat.com +Message-id: <20200521235655.27141-3-plai@redhat.com> +Patchwork-id: 96732 +O-Subject: [RHEL8.2.1 AV qemu-kvm PATCH 02/11] numa: properly check if numa is supported +Bugzilla: 1600217 +RH-Acked-by: Michael S. Tsirkin +RH-Acked-by: Igor Mammedov +RH-Acked-by: Eduardo Habkost + +From: Igor Mammedov + +Commit aa57020774b, by mistake used MachineClass::numa_mem_supported +to check if NUMA is supported by machine and also as unrelated change +set it to true for sbsa-ref board. + +Luckily change didn't break machines that support NUMA, as the field +is set to true for them. + +But the field is not intended for checking if NUMA is supported and +will be flipped to false within this release for new machine types. + +Fix it: + - by using previously used condition + !mc->cpu_index_to_instance_props || !mc->get_default_cpu_node_id + the first time and then use MachineState::numa_state down the road + to check if NUMA is supported + - dropping stray sbsa-ref chunk + +Fixes: aa57020774b690a22be72453b8e91c9b5a68c516 +Signed-off-by: Igor Mammedov +Message-Id: <1576154936-178362-3-git-send-email-imammedo@redhat.com> +Signed-off-by: Eduardo Habkost +(cherry picked from commit fcd3f2cc124600385dba46c69a80626985c15b50) +Signed-off-by: Danilo C. L. de Paula +--- + hw/arm/sbsa-ref.c | 1 - + hw/core/machine.c | 4 ++-- + 2 files changed, 2 insertions(+), 3 deletions(-) + +diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c +index 27046cc..c6261d4 100644 +--- a/hw/arm/sbsa-ref.c ++++ b/hw/arm/sbsa-ref.c +@@ -791,7 +791,6 @@ static void sbsa_ref_class_init(ObjectClass *oc, void *data) + mc->possible_cpu_arch_ids = sbsa_ref_possible_cpu_arch_ids; + mc->cpu_index_to_instance_props = sbsa_ref_cpu_index_to_props; + mc->get_default_cpu_node_id = sbsa_ref_get_default_cpu_node_id; +- mc->numa_mem_supported = true; + } + + static const TypeInfo sbsa_ref_info = { +diff --git a/hw/core/machine.c b/hw/core/machine.c +index 5a025d1..19c78c6 100644 +--- a/hw/core/machine.c ++++ b/hw/core/machine.c +@@ -1128,7 +1128,7 @@ static void machine_initfn(Object *obj) + NULL); + } + +- if (mc->numa_mem_supported) { ++ if (mc->cpu_index_to_instance_props && mc->get_default_cpu_node_id) { + ms->numa_state = g_new0(NumaState, 1); + } + +@@ -1272,7 +1272,7 @@ void machine_run_board_init(MachineState *machine) + { + MachineClass *machine_class = MACHINE_GET_CLASS(machine); + +- if (machine_class->numa_mem_supported) { ++ if (machine->numa_state) { + numa_complete_configuration(machine); + if (machine->numa_state->num_nodes) { + machine_numa_finish_cpu_init(machine); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-numa-remove-not-needed-check.patch b/SOURCES/kvm-numa-remove-not-needed-check.patch new file mode 100644 index 0000000..cbe677f --- /dev/null +++ b/SOURCES/kvm-numa-remove-not-needed-check.patch @@ -0,0 +1,59 @@ +From 348115bbd0d60fada6f7d9fa27848044690a4bc3 Mon Sep 17 00:00:00 2001 +From: "plai@redhat.com" +Date: Thu, 21 May 2020 23:56:45 +0100 +Subject: [PATCH 02/12] numa: remove not needed check + +RH-Author: plai@redhat.com +Message-id: <20200521235655.27141-2-plai@redhat.com> +Patchwork-id: 96738 +O-Subject: [RHEL8.2.1 AV qemu-kvm PATCH 01/11] numa: remove not needed check +Bugzilla: 1600217 +RH-Acked-by: Michael S. Tsirkin +RH-Acked-by: Igor Mammedov +RH-Acked-by: Eduardo Habkost + +From: Igor Mammedov + +Currently parse_numa_node() is always called from already numa +enabled context. +Drop unnecessary check if numa is supported. + +Signed-off-by: Igor Mammedov +Message-Id: <1576154936-178362-2-git-send-email-imammedo@redhat.com> +Signed-off-by: Eduardo Habkost +(cherry picked from commit 5275db59aa7ff8a26bd6aa5d07cb4d53de5cfab5) +Signed-off-by: Paul Lai +Signed-off-by: Danilo C. L. de Paula +--- + hw/core/numa.c | 7 +------ + 1 file changed, 1 insertion(+), 6 deletions(-) + +diff --git a/hw/core/numa.c b/hw/core/numa.c +index e3332a9..19f082d 100644 +--- a/hw/core/numa.c ++++ b/hw/core/numa.c +@@ -83,10 +83,6 @@ static void parse_numa_node(MachineState *ms, NumaNodeOptions *node, + return; + } + +- if (!mc->cpu_index_to_instance_props || !mc->get_default_cpu_node_id) { +- error_setg(errp, "NUMA is not supported by this machine-type"); +- return; +- } + for (cpus = node->cpus; cpus; cpus = cpus->next) { + CpuInstanceProperties props; + if (cpus->value >= max_cpus) { +@@ -178,9 +174,8 @@ void parse_numa_distance(MachineState *ms, NumaDistOptions *dist, Error **errp) + void set_numa_options(MachineState *ms, NumaOptions *object, Error **errp) + { + Error *err = NULL; +- MachineClass *mc = MACHINE_GET_CLASS(ms); + +- if (!mc->numa_mem_supported) { ++ if (!ms->numa_state) { + error_setg(errp, "NUMA is not supported by this machine-type"); + goto end; + } +-- +1.8.3.1 + diff --git a/SOURCES/kvm-pc-bios-s390x-Fix-reset-psw-mask.patch b/SOURCES/kvm-pc-bios-s390x-Fix-reset-psw-mask.patch new file mode 100644 index 0000000..9c45e92 --- /dev/null +++ b/SOURCES/kvm-pc-bios-s390x-Fix-reset-psw-mask.patch @@ -0,0 +1,75 @@ +From 38ba55dd27a3b8308f0ce2e82a4c3eba3f197d20 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 29 May 2020 05:53:53 -0400 +Subject: [PATCH 11/42] pc-bios/s390x: Fix reset psw mask + +RH-Author: Thomas Huth +Message-id: <20200529055420.16855-12-thuth@redhat.com> +Patchwork-id: 97034 +O-Subject: [RHEL-8.3.0 qemu-kvm PATCH v2 11/38] pc-bios/s390x: Fix reset psw mask +Bugzilla: 1828317 +RH-Acked-by: Claudio Imbrenda +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand + +From: Janosch Frank + +We need to set the short psw indication bit in the reset psw, as it is +a short psw. + +Exposed by "s390x: Properly fetch and test the short psw on diag308 +subc 0/1". + +Fixes: 962982329029 ("pc-bios/s390-ccw: do a subsystem reset before running the guest") +Signed-off-by: Janosch Frank +Message-Id: <20191203132813.2734-5-frankja@linux.ibm.com> +Acked-by: Christian Borntraeger +Signed-off-by: Cornelia Huck +(cherry picked from commit 5c6f0d5f46a77d77460dfb518cf1e1e4145c276e) +Signed-off-by: Danilo C. L. de Paula +--- + pc-bios/s390-ccw/jump2ipl.c | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +diff --git a/pc-bios/s390-ccw/jump2ipl.c b/pc-bios/s390-ccw/jump2ipl.c +index 266f1502b9..da13c43cc0 100644 +--- a/pc-bios/s390-ccw/jump2ipl.c ++++ b/pc-bios/s390-ccw/jump2ipl.c +@@ -12,11 +12,11 @@ + #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 PSW_MASK_SHORTPSW 0x0008000000000000ULL ++#define RESET_PSW_MASK (PSW_MASK_SHORTPSW | PSW_MASK_32 | PSW_MASK_64) + + typedef struct ResetInfo { +- uint32_t ipl_mask; +- uint32_t ipl_addr; ++ uint64_t ipl_psw; + uint32_t ipl_continue; + } ResetInfo; + +@@ -50,7 +50,9 @@ void jump_to_IPL_code(uint64_t address) + ResetInfo *current = 0; + + save = *current; +- current->ipl_addr = (uint32_t) (uint64_t) &jump_to_IPL_2; ++ ++ current->ipl_psw = (uint64_t) &jump_to_IPL_2; ++ current->ipl_psw |= RESET_PSW_MASK; + current->ipl_continue = address & 0x7fffffff; + + debug_print_int("set IPL addr to", current->ipl_continue); +@@ -82,7 +84,7 @@ void jump_to_low_kernel(void) + } + + /* Trying to get PSW at zero address */ +- if (*((uint64_t *)0) & IPL_PSW_MASK) { ++ if (*((uint64_t *)0) & RESET_PSW_MASK) { + jump_to_IPL_code((*((uint64_t *)0)) & 0x7fffffff); + } + +-- +2.27.0 + diff --git a/SOURCES/kvm-pc-bios-s390x-Save-iplb-location-in-lowcore.patch b/SOURCES/kvm-pc-bios-s390x-Save-iplb-location-in-lowcore.patch new file mode 100644 index 0000000..2db2f93 --- /dev/null +++ b/SOURCES/kvm-pc-bios-s390x-Save-iplb-location-in-lowcore.patch @@ -0,0 +1,145 @@ +From 8350ad9c0f54519a06ec396c2997330615f4b470 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 29 May 2020 05:53:58 -0400 +Subject: [PATCH 16/42] pc-bios: s390x: Save iplb location in lowcore + +RH-Author: Thomas Huth +Message-id: <20200529055420.16855-17-thuth@redhat.com> +Patchwork-id: 97027 +O-Subject: [RHEL-8.3.0 qemu-kvm PATCH v2 16/38] pc-bios: s390x: Save iplb location in lowcore +Bugzilla: 1828317 +RH-Acked-by: Claudio Imbrenda +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand + +From: Janosch Frank + +The POP states that for a list directed IPL the IPLB is stored into +memory by the machine loader and its address is stored at offset 0x14 +of the lowcore. + +ZIPL currently uses the address in offset 0x14 to access the IPLB and +acquire flags about secure boot. If the IPLB address points into +memory which has an unsupported mix of flags set, ZIPL will panic +instead of booting the OS. + +As the lowcore can have quite a high entropy for a guest that did drop +out of protected mode (i.e. rebooted) we encountered the ZIPL panic +quite often. + +Signed-off-by: Janosch Frank +Tested-by: Marc Hartmayer +Message-Id: <20200304114231.23493-19-frankja@linux.ibm.com> +Reviewed-by: Christian Borntraeger +Reviewed-by: David Hildenbrand +Signed-off-by: Christian Borntraeger +(cherry picked from commit 9bfc04f9ef6802fff0fc77130ff345a541783363) +Signed-off-by: Danilo C. L. de Paula +--- + pc-bios/s390-ccw/jump2ipl.c | 1 + + pc-bios/s390-ccw/main.c | 8 +++++++- + pc-bios/s390-ccw/netmain.c | 1 + + pc-bios/s390-ccw/s390-arch.h | 10 ++++++++-- + pc-bios/s390-ccw/s390-ccw.h | 1 + + 5 files changed, 18 insertions(+), 3 deletions(-) + +diff --git a/pc-bios/s390-ccw/jump2ipl.c b/pc-bios/s390-ccw/jump2ipl.c +index da13c43cc0..4eba2510b0 100644 +--- a/pc-bios/s390-ccw/jump2ipl.c ++++ b/pc-bios/s390-ccw/jump2ipl.c +@@ -35,6 +35,7 @@ void jump_to_IPL_code(uint64_t address) + { + /* store the subsystem information _after_ the bootmap was loaded */ + write_subsystem_identification(); ++ write_iplb_location(); + + /* prevent unknown IPL types in the guest */ + if (iplb.pbt == S390_IPL_TYPE_QEMU_SCSI) { +diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c +index a21b386280..4e65b411e1 100644 +--- a/pc-bios/s390-ccw/main.c ++++ b/pc-bios/s390-ccw/main.c +@@ -9,6 +9,7 @@ + */ + + #include "libc.h" ++#include "helper.h" + #include "s390-arch.h" + #include "s390-ccw.h" + #include "cio.h" +@@ -22,7 +23,7 @@ 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 */ ++LowCore *lowcore; /* Yes, this *is* a pointer to address 0 */ + + #define LOADPARM_PROMPT "PROMPT " + #define LOADPARM_EMPTY " " +@@ -42,6 +43,11 @@ void write_subsystem_identification(void) + *zeroes = 0; + } + ++void write_iplb_location(void) ++{ ++ lowcore->ptr_iplb = ptr2u32(&iplb); ++} ++ + void panic(const char *string) + { + sclp_print(string); +diff --git a/pc-bios/s390-ccw/netmain.c b/pc-bios/s390-ccw/netmain.c +index f2dcc01e27..309ffa30d9 100644 +--- a/pc-bios/s390-ccw/netmain.c ++++ b/pc-bios/s390-ccw/netmain.c +@@ -40,6 +40,7 @@ + #define DEFAULT_TFTP_RETRIES 20 + + extern char _start[]; ++void write_iplb_location(void) {} + + #define KERNEL_ADDR ((void *)0L) + #define KERNEL_MAX_SIZE ((long)_start) +diff --git a/pc-bios/s390-ccw/s390-arch.h b/pc-bios/s390-ccw/s390-arch.h +index 504fc7c2f0..5f36361c02 100644 +--- a/pc-bios/s390-ccw/s390-arch.h ++++ b/pc-bios/s390-ccw/s390-arch.h +@@ -36,7 +36,13 @@ typedef struct LowCore { + /* prefix area: defined by architecture */ + PSWLegacy ipl_psw; /* 0x000 */ + uint32_t ccw1[2]; /* 0x008 */ +- uint32_t ccw2[2]; /* 0x010 */ ++ union { ++ uint32_t ccw2[2]; /* 0x010 */ ++ struct { ++ uint32_t reserved10; ++ uint32_t ptr_iplb; ++ }; ++ }; + uint8_t pad1[0x80 - 0x18]; /* 0x018 */ + uint32_t ext_params; /* 0x080 */ + uint16_t cpu_addr; /* 0x084 */ +@@ -85,7 +91,7 @@ typedef struct LowCore { + PSW io_new_psw; /* 0x1f0 */ + } __attribute__((packed, aligned(8192))) LowCore; + +-extern LowCore const *lowcore; ++extern LowCore *lowcore; + + static inline void set_prefix(uint32_t address) + { +diff --git a/pc-bios/s390-ccw/s390-ccw.h b/pc-bios/s390-ccw/s390-ccw.h +index 11bce7d73c..21f27e7990 100644 +--- a/pc-bios/s390-ccw/s390-ccw.h ++++ b/pc-bios/s390-ccw/s390-ccw.h +@@ -57,6 +57,7 @@ void consume_io_int(void); + /* main.c */ + void panic(const char *string); + void write_subsystem_identification(void); ++void write_iplb_location(void); + extern char stack[PAGE_SIZE * 8] __attribute__((__aligned__(PAGE_SIZE))); + unsigned int get_loadparm_index(void); + +-- +2.27.0 + diff --git a/SOURCES/kvm-pcie_root_port-Add-hotplug-disabling-option.patch b/SOURCES/kvm-pcie_root_port-Add-hotplug-disabling-option.patch new file mode 100644 index 0000000..57f3c3b --- /dev/null +++ b/SOURCES/kvm-pcie_root_port-Add-hotplug-disabling-option.patch @@ -0,0 +1,153 @@ +From 8587278a20283851081d4d282d11ef6bafd17dc2 Mon Sep 17 00:00:00 2001 +From: Julia Suvorova +Date: Tue, 17 Mar 2020 13:56:39 -0400 +Subject: [PATCH 1/2] pcie_root_port: Add hotplug disabling option +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Julia Suvorova +Message-id: <20200317135639.65085-1-jusual@redhat.com> +Patchwork-id: 94367 +O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH 1/1] pcie_root_port: Add hotplug disabling option +Bugzilla: 1790899 +RH-Acked-by: Stefano Garzarella +RH-Acked-by: Michael S. Tsirkin +RH-Acked-by: Peter Xu + +BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1790899 +BRANCH: rhel-av-8.2.1 +UPSTREAM: merged +BREW: https://brewweb.engineering.redhat.com/brew/taskinfo?taskID=27302449 + +Make hot-plug/hot-unplug on PCIe Root Ports optional to allow libvirt +manage it and restrict unplug for the whole machine. This is going to +prevent user-initiated unplug in guests (Windows mostly). +Hotplug is enabled by default. +Usage: + -device pcie-root-port,hotplug=off,... + +If you want to disable hot-unplug on some downstream ports of one +switch, disable hot-unplug on PCIe Root Port connected to the upstream +port as well as on the selected downstream ports. + +Discussion related: + https://lists.gnu.org/archive/html/qemu-devel/2020-02/msg00530.html + +Signed-off-by: Julia Suvorova +Message-Id: <20200226174607.205941-1-jusual@redhat.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Reviewed-by: Ján Tomko +(cherry picked from commit 530a0963184e57e71a5b538e9161f115df533e96) +Signed-off-by: Jon Maloy +--- + hw/pci-bridge/pcie_root_port.c | 2 +- + hw/pci-bridge/xio3130_downstream.c | 2 +- + hw/pci/pcie.c | 11 +++++++---- + hw/pci/pcie_port.c | 1 + + include/hw/pci/pcie.h | 2 +- + include/hw/pci/pcie_port.h | 3 +++ + 6 files changed, 14 insertions(+), 7 deletions(-) + +diff --git a/hw/pci-bridge/pcie_root_port.c b/hw/pci-bridge/pcie_root_port.c +index 012c2cb12c..db80e2ec23 100644 +--- a/hw/pci-bridge/pcie_root_port.c ++++ b/hw/pci-bridge/pcie_root_port.c +@@ -94,7 +94,7 @@ static void rp_realize(PCIDevice *d, Error **errp) + + pcie_cap_arifwd_init(d); + pcie_cap_deverr_init(d); +- pcie_cap_slot_init(d, s->slot); ++ pcie_cap_slot_init(d, s); + pcie_cap_root_init(d); + + pcie_chassis_create(s->chassis); +diff --git a/hw/pci-bridge/xio3130_downstream.c b/hw/pci-bridge/xio3130_downstream.c +index a9f084b863..4489ce4a40 100644 +--- a/hw/pci-bridge/xio3130_downstream.c ++++ b/hw/pci-bridge/xio3130_downstream.c +@@ -94,7 +94,7 @@ static void xio3130_downstream_realize(PCIDevice *d, Error **errp) + } + pcie_cap_flr_init(d); + pcie_cap_deverr_init(d); +- pcie_cap_slot_init(d, s->slot); ++ pcie_cap_slot_init(d, s); + pcie_cap_arifwd_init(d); + + pcie_chassis_create(s->chassis); +diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c +index 08718188bb..0eb3a2a5d2 100644 +--- a/hw/pci/pcie.c ++++ b/hw/pci/pcie.c +@@ -495,7 +495,7 @@ void pcie_cap_slot_unplug_request_cb(HotplugHandler *hotplug_dev, + + /* pci express slot for pci express root/downstream port + PCI express capability slot registers */ +-void pcie_cap_slot_init(PCIDevice *dev, uint16_t slot) ++void pcie_cap_slot_init(PCIDevice *dev, PCIESlot *s) + { + uint32_t pos = dev->exp.exp_cap; + +@@ -505,13 +505,16 @@ void pcie_cap_slot_init(PCIDevice *dev, uint16_t slot) + pci_long_test_and_clear_mask(dev->config + pos + PCI_EXP_SLTCAP, + ~PCI_EXP_SLTCAP_PSN); + pci_long_test_and_set_mask(dev->config + pos + PCI_EXP_SLTCAP, +- (slot << PCI_EXP_SLTCAP_PSN_SHIFT) | ++ (s->slot << PCI_EXP_SLTCAP_PSN_SHIFT) | + PCI_EXP_SLTCAP_EIP | +- PCI_EXP_SLTCAP_HPS | +- PCI_EXP_SLTCAP_HPC | + PCI_EXP_SLTCAP_PIP | + PCI_EXP_SLTCAP_AIP | + PCI_EXP_SLTCAP_ABP); ++ if (s->hotplug) { ++ pci_long_test_and_set_mask(dev->config + pos + PCI_EXP_SLTCAP, ++ PCI_EXP_SLTCAP_HPS | ++ PCI_EXP_SLTCAP_HPC); ++ } + + if (dev->cap_present & QEMU_PCIE_SLTCAP_PCP) { + pci_long_test_and_set_mask(dev->config + pos + PCI_EXP_SLTCAP, +diff --git a/hw/pci/pcie_port.c b/hw/pci/pcie_port.c +index c19a9be592..36dac33d98 100644 +--- a/hw/pci/pcie_port.c ++++ b/hw/pci/pcie_port.c +@@ -147,6 +147,7 @@ static const TypeInfo pcie_port_type_info = { + static Property pcie_slot_props[] = { + DEFINE_PROP_UINT8("chassis", PCIESlot, chassis, 0), + DEFINE_PROP_UINT16("slot", PCIESlot, slot, 0), ++ DEFINE_PROP_BOOL("hotplug", PCIESlot, hotplug, true), + DEFINE_PROP_END_OF_LIST() + }; + +diff --git a/include/hw/pci/pcie.h b/include/hw/pci/pcie.h +index 7064875835..14c58ebdb6 100644 +--- a/include/hw/pci/pcie.h ++++ b/include/hw/pci/pcie.h +@@ -104,7 +104,7 @@ void pcie_cap_deverr_reset(PCIDevice *dev); + void pcie_cap_lnkctl_init(PCIDevice *dev); + void pcie_cap_lnkctl_reset(PCIDevice *dev); + +-void pcie_cap_slot_init(PCIDevice *dev, uint16_t slot); ++void pcie_cap_slot_init(PCIDevice *dev, PCIESlot *s); + void pcie_cap_slot_reset(PCIDevice *dev); + void pcie_cap_slot_get(PCIDevice *dev, uint16_t *slt_ctl, uint16_t *slt_sta); + void pcie_cap_slot_write_config(PCIDevice *dev, +diff --git a/include/hw/pci/pcie_port.h b/include/hw/pci/pcie_port.h +index 7515430087..7072cc8731 100644 +--- a/include/hw/pci/pcie_port.h ++++ b/include/hw/pci/pcie_port.h +@@ -55,6 +55,9 @@ struct PCIESlot { + + /* Disable ACS (really for a pcie_root_port) */ + bool disable_acs; ++ ++ /* Indicates whether hot-plug is enabled on the slot */ ++ bool hotplug; + QLIST_ENTRY(PCIESlot) next; + }; + +-- +2.18.2 + diff --git a/SOURCES/kvm-qcow2-Expose-bitmaps-size-during-measure.patch b/SOURCES/kvm-qcow2-Expose-bitmaps-size-during-measure.patch new file mode 100644 index 0000000..48c15c5 --- /dev/null +++ b/SOURCES/kvm-qcow2-Expose-bitmaps-size-during-measure.patch @@ -0,0 +1,495 @@ +From af4d66e07c86d7593f7d18ae4b6a2151123b529b Mon Sep 17 00:00:00 2001 +From: Eric Blake +Date: Tue, 2 Jun 2020 02:34:17 +0100 +Subject: [PATCH 12/26] qcow2: Expose bitmaps' size during measure + +RH-Author: Eric Blake +Message-id: <20200602023420.2133649-10-eblake@redhat.com> +Patchwork-id: 97072 +O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH 09/12] qcow2: Expose bitmaps' size during measure +Bugzilla: 1779893 1779904 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Max Reitz +RH-Acked-by: Kevin Wolf + +It's useful to know how much space can be occupied by qcow2 persistent +bitmaps, even though such metadata is unrelated to the guest-visible +data. Report this value as an additional QMP field, present when +measuring an existing image and output format that both support +bitmaps. Update iotest 178 and 190 to updated output, as well as new +coverage in 190 demonstrating non-zero values made possible with the +recently-added qemu-img bitmap command (see 3b51ab4b). + +The new 'bitmaps size:' field is displayed automatically as part of +'qemu-img measure' any time it is present in QMP (that is, any time +both the source image being measured and destination format support +bitmaps, even if the measurement is 0 because there are no bitmaps +present). If the field is absent, it means that no bitmaps can be +copied (source, destination, or both lack bitmaps, including when +measuring based on size rather than on a source image). This behavior +is compatible with an upcoming patch adding 'qemu-img convert +--bitmaps': that command will fail in the same situations where this +patch omits the field. + +The addition of a new field demonstrates why we should always +zero-initialize qapi C structs; while the qcow2 driver still fully +populates all fields, the raw and crypto drivers had to be tweaked to +avoid uninitialized data. + +Consideration was also given towards having a 'qemu-img measure +--bitmaps' which errors out when bitmaps are not possible, and +otherwise sums the bitmaps into the existing allocation totals rather +than displaying as a separate field, as a potential convenience +factor. But this was ultimately decided to be more complexity than +necessary when the QMP interface was sufficient enough with bitmaps +remaining a separate field. + +See also: https://bugzilla.redhat.com/1779904 + +Reported-by: Nir Soffer +Signed-off-by: Eric Blake +Message-Id: <20200521192137.1120211-3-eblake@redhat.com> +Reviewed-by: Vladimir Sementsov-Ogievskiy +(cherry picked from commit 5d72c68b49769c927e90b78af6d90f6a384b26ac) + +Signed-off-by: Danilo C. L. de Paula + +Conflicts: + block/crypto.c - commit a9da6e49 not present (no measure support) + docs/tools/qemu-img.rst - changes in qemu-img.texi instead +Signed-off-by: Eric Blake + +Signed-off-by: Danilo C. L. de Paula +--- + block/qcow2-bitmap.c | 36 ++++++++++++++++++++++++++++++ + block/qcow2.c | 14 +++++++++--- + block/qcow2.h | 2 ++ + block/raw-format.c | 2 +- + qapi/block-core.json | 16 +++++++++----- + qemu-img.c | 3 +++ + qemu-img.texi | 7 ++++++ + tests/qemu-iotests/178.out.qcow2 | 16 ++++++++++++++ + tests/qemu-iotests/190 | 47 ++++++++++++++++++++++++++++++++++++++-- + tests/qemu-iotests/190.out | 27 ++++++++++++++++++++++- + 10 files changed, 158 insertions(+), 12 deletions(-) + +diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c +index cbac905..10d1297 100644 +--- a/block/qcow2-bitmap.c ++++ b/block/qcow2-bitmap.c +@@ -1766,3 +1766,39 @@ bool qcow2_supports_persistent_dirty_bitmap(BlockDriverState *bs) + + return s->qcow_version >= 3; + } ++ ++/* ++ * Compute the space required for bitmaps in @bs. ++ * ++ * The computation is based as if copying to a new image with the ++ * given @cluster_size, which may differ from the cluster size in @bs. ++ */ ++uint64_t qcow2_get_persistent_dirty_bitmap_size(BlockDriverState *bs, ++ uint32_t cluster_size) ++{ ++ uint64_t bitmaps_size = 0; ++ BdrvDirtyBitmap *bm; ++ size_t bitmap_dir_size = 0; ++ ++ FOR_EACH_DIRTY_BITMAP(bs, bm) { ++ if (bdrv_dirty_bitmap_get_persistence(bm)) { ++ const char *name = bdrv_dirty_bitmap_name(bm); ++ uint32_t granularity = bdrv_dirty_bitmap_granularity(bm); ++ uint64_t bmbytes = ++ get_bitmap_bytes_needed(bdrv_dirty_bitmap_size(bm), ++ granularity); ++ uint64_t bmclusters = DIV_ROUND_UP(bmbytes, cluster_size); ++ ++ /* Assume the entire bitmap is allocated */ ++ bitmaps_size += bmclusters * cluster_size; ++ /* Also reserve space for the bitmap table entries */ ++ bitmaps_size += ROUND_UP(bmclusters * sizeof(uint64_t), ++ cluster_size); ++ /* And space for contribution to bitmap directory size */ ++ bitmap_dir_size += calc_dir_entry_size(strlen(name), 0); ++ } ++ } ++ bitmaps_size += ROUND_UP(bitmap_dir_size, cluster_size); ++ ++ return bitmaps_size; ++} +diff --git a/block/qcow2.c b/block/qcow2.c +index 36b0f7d..dbd870a 100644 +--- a/block/qcow2.c ++++ b/block/qcow2.c +@@ -4751,16 +4751,24 @@ static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, BlockDriverState *in_bs, + required = virtual_size; + } + +- info = g_new(BlockMeasureInfo, 1); ++ info = g_new0(BlockMeasureInfo, 1); + info->fully_allocated = + qcow2_calc_prealloc_size(virtual_size, cluster_size, + ctz32(refcount_bits)) + luks_payload_size; + +- /* Remove data clusters that are not required. This overestimates the ++ /* ++ * Remove data clusters that are not required. This overestimates the + * required size because metadata needed for the fully allocated file is +- * still counted. ++ * still counted. Show bitmaps only if both source and destination ++ * would support them. + */ + info->required = info->fully_allocated - virtual_size + required; ++ info->has_bitmaps = version >= 3 && in_bs && ++ bdrv_supports_persistent_dirty_bitmap(in_bs); ++ if (info->has_bitmaps) { ++ info->bitmaps = qcow2_get_persistent_dirty_bitmap_size(in_bs, ++ cluster_size); ++ } + return info; + + err: +diff --git a/block/qcow2.h b/block/qcow2.h +index ceb1ceb..3297e6b 100644 +--- a/block/qcow2.h ++++ b/block/qcow2.h +@@ -768,6 +768,8 @@ int qcow2_co_remove_persistent_dirty_bitmap(BlockDriverState *bs, + const char *name, + Error **errp); + bool qcow2_supports_persistent_dirty_bitmap(BlockDriverState *bs); ++uint64_t qcow2_get_persistent_dirty_bitmap_size(BlockDriverState *bs, ++ uint32_t cluster_size); + + ssize_t coroutine_fn + qcow2_co_compress(BlockDriverState *bs, void *dest, size_t dest_size, +diff --git a/block/raw-format.c b/block/raw-format.c +index 93b25e1..4bb54f4 100644 +--- a/block/raw-format.c ++++ b/block/raw-format.c +@@ -346,7 +346,7 @@ static BlockMeasureInfo *raw_measure(QemuOpts *opts, BlockDriverState *in_bs, + BDRV_SECTOR_SIZE); + } + +- info = g_new(BlockMeasureInfo, 1); ++ info = g_new0(BlockMeasureInfo, 1); + info->required = required; + + /* Unallocated sectors count towards the file size in raw images */ +diff --git a/qapi/block-core.json b/qapi/block-core.json +index a64ad81..2893209 100644 +--- a/qapi/block-core.json ++++ b/qapi/block-core.json +@@ -689,18 +689,24 @@ + # efficiently so file size may be smaller than virtual disk size. + # + # The values are upper bounds that are guaranteed to fit the new image file. +-# Subsequent modification, such as internal snapshot or bitmap creation, may +-# require additional space and is not covered here. ++# Subsequent modification, such as internal snapshot or further bitmap ++# creation, may require additional space and is not covered here. + # +-# @required: Size required for a new image file, in bytes. ++# @required: Size required for a new image file, in bytes, when copying just ++# allocated guest-visible contents. + # + # @fully-allocated: Image file size, in bytes, once data has been written +-# to all sectors. ++# to all sectors, when copying just guest-visible contents. ++# ++# @bitmaps: Additional size required if all the top-level bitmap metadata ++# in the source image were to be copied to the destination, ++# present only when source and destination both support ++# persistent bitmaps. (since 5.1) + # + # Since: 2.10 + ## + { 'struct': 'BlockMeasureInfo', +- 'data': {'required': 'int', 'fully-allocated': 'int'} } ++ 'data': {'required': 'int', 'fully-allocated': 'int', '*bitmaps': 'int'} } + + ## + # @query-block: +diff --git a/qemu-img.c b/qemu-img.c +index 11a4537..b57856e 100644 +--- a/qemu-img.c ++++ b/qemu-img.c +@@ -5212,6 +5212,9 @@ static int img_measure(int argc, char **argv) + if (output_format == OFORMAT_HUMAN) { + printf("required size: %" PRIu64 "\n", info->required); + printf("fully allocated size: %" PRIu64 "\n", info->fully_allocated); ++ if (info->has_bitmaps) { ++ printf("bitmaps size: %" PRIu64 "\n", info->bitmaps); ++ } + } else { + dump_json_block_measure_info(info); + } +diff --git a/qemu-img.texi b/qemu-img.texi +index abf2771..3670b96 100644 +--- a/qemu-img.texi ++++ b/qemu-img.texi +@@ -576,6 +576,7 @@ The following fields are reported: + @example + required size: 524288 + fully allocated size: 1074069504 ++bitmaps size: 0 + @end example + + The @code{required size} is the file size of the new image. It may be smaller +@@ -586,6 +587,12 @@ been written to all sectors. This is the maximum size that the image file can + occupy with the exception of internal snapshots, dirty bitmaps, vmstate data, + and other advanced image format features. + ++The @code{bitmaps size} is the additional size required in order to ++copy bitmaps from a source image in addition to the guest-visible ++data; the line is omitted if either source or destination lacks ++bitmap support, or 0 if bitmaps are supported but there is nothing to ++copy. ++ + @item snapshot [--object @var{objectdef}] [--image-opts] [-U] [-q] [-l | -a @var{snapshot} | -c @var{snapshot} | -d @var{snapshot}] @var{filename} + + List, apply, create or delete snapshots in image @var{filename}. +diff --git a/tests/qemu-iotests/178.out.qcow2 b/tests/qemu-iotests/178.out.qcow2 +index 345eab3..b9ed41b 100644 +--- a/tests/qemu-iotests/178.out.qcow2 ++++ b/tests/qemu-iotests/178.out.qcow2 +@@ -37,6 +37,7 @@ qemu-img: The image size is too large (try using a larger cluster size) + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=0 + required size: 196608 + fully allocated size: 196608 ++bitmaps size: 0 + + converted image file size in bytes: 196608 + +@@ -45,6 +46,7 @@ converted image file size in bytes: 196608 + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 + required size: 393216 + fully allocated size: 1074135040 ++bitmaps size: 0 + wrote 512/512 bytes at offset 512 + 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + wrote 65536/65536 bytes at offset 65536 +@@ -53,6 +55,7 @@ wrote 64512/64512 bytes at offset 134217728 + 63 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + required size: 589824 + fully allocated size: 1074135040 ++bitmaps size: 0 + + converted image file size in bytes: 524288 + +@@ -60,6 +63,7 @@ converted image file size in bytes: 524288 + + required size: 524288 + fully allocated size: 1074135040 ++bitmaps size: 0 + + converted image file size in bytes: 458752 + +@@ -67,16 +71,19 @@ converted image file size in bytes: 458752 + + required size: 1074135040 + fully allocated size: 1074135040 ++bitmaps size: 0 + + == qcow2 input image and LUKS encryption == + + required size: 2686976 + fully allocated size: 1076232192 ++bitmaps size: 0 + + == qcow2 input image and preallocation (human) == + + required size: 1074135040 + fully allocated size: 1074135040 ++bitmaps size: 0 + + converted image file size in bytes: 1074135040 + +@@ -87,6 +94,7 @@ wrote 8388608/8388608 bytes at offset 0 + 8 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + required size: 8716288 + fully allocated size: 8716288 ++bitmaps size: 0 + + converted image file size in bytes: 8716288 + +@@ -173,6 +181,7 @@ qemu-img: The image size is too large (try using a larger cluster size) + + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=0 + { ++ "bitmaps": 0, + "required": 196608, + "fully-allocated": 196608 + } +@@ -183,6 +192,7 @@ converted image file size in bytes: 196608 + + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 + { ++ "bitmaps": 0, + "required": 393216, + "fully-allocated": 1074135040 + } +@@ -193,6 +203,7 @@ wrote 65536/65536 bytes at offset 65536 + wrote 64512/64512 bytes at offset 134217728 + 63 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + { ++ "bitmaps": 0, + "required": 589824, + "fully-allocated": 1074135040 + } +@@ -202,6 +213,7 @@ converted image file size in bytes: 524288 + == qcow2 input image with internal snapshot (json) == + + { ++ "bitmaps": 0, + "required": 524288, + "fully-allocated": 1074135040 + } +@@ -211,6 +223,7 @@ converted image file size in bytes: 458752 + == qcow2 input image and a backing file (json) == + + { ++ "bitmaps": 0, + "required": 1074135040, + "fully-allocated": 1074135040 + } +@@ -218,6 +231,7 @@ converted image file size in bytes: 458752 + == qcow2 input image and LUKS encryption == + + { ++ "bitmaps": 0, + "required": 2686976, + "fully-allocated": 1076232192 + } +@@ -225,6 +239,7 @@ converted image file size in bytes: 458752 + == qcow2 input image and preallocation (json) == + + { ++ "bitmaps": 0, + "required": 1074135040, + "fully-allocated": 1074135040 + } +@@ -237,6 +252,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=8388608 + wrote 8388608/8388608 bytes at offset 0 + 8 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + { ++ "bitmaps": 0, + "required": 8716288, + "fully-allocated": 8716288 + } +diff --git a/tests/qemu-iotests/190 b/tests/qemu-iotests/190 +index eb766ad..5084ccd 100755 +--- a/tests/qemu-iotests/190 ++++ b/tests/qemu-iotests/190 +@@ -2,7 +2,7 @@ + # + # qemu-img measure sub-command tests on huge qcow2 files + # +-# Copyright (C) 2017 Red Hat, Inc. ++# Copyright (C) 2017-2020 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 +@@ -42,7 +42,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 + _supported_fmt qcow2 + _supported_proto file + +-echo "== Huge file ==" ++echo "== Huge file without bitmaps ==" + echo + + IMGOPTS='cluster_size=2M' _make_test_img 2T +@@ -51,6 +51,49 @@ $QEMU_IMG measure -O raw -f qcow2 "$TEST_IMG" + $QEMU_IMG measure -O qcow2 -o cluster_size=64k -f qcow2 "$TEST_IMG" + $QEMU_IMG measure -O qcow2 -o cluster_size=2M -f qcow2 "$TEST_IMG" + ++echo ++echo "== Huge file with bitmaps ==" ++echo ++ ++$QEMU_IMG bitmap --add --granularity 512 -f qcow2 "$TEST_IMG" b1 ++$QEMU_IMG bitmap --add -g 2M -f qcow2 "$TEST_IMG" b2 ++ ++# No bitmap without a source ++$QEMU_IMG measure -O qcow2 --size 10M ++# No bitmap output, since raw does not support it ++$QEMU_IMG measure -O raw -f qcow2 "$TEST_IMG" ++# No bitmap output, since no bitmaps on raw source. Munge required size, as ++# some filesystems store the qcow2 file with less sparseness than others ++$QEMU_IMG measure -O qcow2 -f raw "$TEST_IMG" | ++ sed '/^required size:/ s/[0-9][0-9]*/SIZE/' ++# No bitmap output, since v2 does not support it ++$QEMU_IMG measure -O qcow2 -o compat=0.10 -f qcow2 "$TEST_IMG" ++ ++# Compute expected output: bitmap clusters + bitmap tables + bitmaps directory ++echo ++val2T=$((2*1024*1024*1024*1024)) ++cluster=$((64*1024)) ++b1clusters=$(( (val2T/512/8 + cluster - 1) / cluster )) ++b2clusters=$(( (val2T/2/1024/1024/8 + cluster - 1) / cluster )) ++echo expected bitmap $((b1clusters * cluster + ++ (b1clusters * 8 + cluster - 1) / cluster * cluster + ++ b2clusters * cluster + ++ (b2clusters * 8 + cluster - 1) / cluster * cluster + ++ cluster)) ++$QEMU_IMG measure -O qcow2 -o cluster_size=64k -f qcow2 "$TEST_IMG" ++ ++# Compute expected output: bitmap clusters + bitmap tables + bitmaps directory ++echo ++cluster=$((2*1024*1024)) ++b1clusters=$(( (val2T/512/8 + cluster - 1) / cluster )) ++b2clusters=$(( (val2T/2/1024/1024/8 + cluster - 1) / cluster )) ++echo expected bitmap $((b1clusters * cluster + ++ (b1clusters * 8 + cluster - 1) / cluster * cluster + ++ b2clusters * cluster + ++ (b2clusters * 8 + cluster - 1) / cluster * cluster + ++ cluster)) ++$QEMU_IMG measure --output=json -O qcow2 -o cluster_size=2M -f qcow2 "$TEST_IMG" ++ + # success, all done + echo "*** done" + rm -f $seq.full +diff --git a/tests/qemu-iotests/190.out b/tests/qemu-iotests/190.out +index d001942..ed9d821 100644 +--- a/tests/qemu-iotests/190.out ++++ b/tests/qemu-iotests/190.out +@@ -1,11 +1,36 @@ + QA output created by 190 +-== Huge file == ++== Huge file without bitmaps == + + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2199023255552 + required size: 2199023255552 + fully allocated size: 2199023255552 + required size: 335806464 + fully allocated size: 2199359062016 ++bitmaps size: 0 + required size: 18874368 + fully allocated size: 2199042129920 ++bitmaps size: 0 ++ ++== Huge file with bitmaps == ++ ++required size: 327680 ++fully allocated size: 10813440 ++required size: 2199023255552 ++fully allocated size: 2199023255552 ++required size: SIZE ++fully allocated size: 17170432 ++required size: 335806464 ++fully allocated size: 2199359062016 ++ ++expected bitmap 537198592 ++required size: 335806464 ++fully allocated size: 2199359062016 ++bitmaps size: 537198592 ++ ++expected bitmap 545259520 ++{ ++ "bitmaps": 545259520, ++ "required": 18874368, ++ "fully-allocated": 2199042129920 ++} + *** done +-- +1.8.3.1 + diff --git a/SOURCES/kvm-qcow2-Forward-ZERO_WRITE-flag-for-full-preallocation.patch b/SOURCES/kvm-qcow2-Forward-ZERO_WRITE-flag-for-full-preallocation.patch new file mode 100644 index 0000000..522ba60 --- /dev/null +++ b/SOURCES/kvm-qcow2-Forward-ZERO_WRITE-flag-for-full-preallocation.patch @@ -0,0 +1,98 @@ +From 4290173219e15065e9a7c2e95774ac979b5fd869 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Mon, 8 Jun 2020 15:01:40 +0100 +Subject: [PATCH 12/17] qcow2: Forward ZERO_WRITE flag for full preallocation + +RH-Author: Kevin Wolf +Message-id: <20200608150140.38218-12-kwolf@redhat.com> +Patchwork-id: 97456 +O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH 11/11] qcow2: Forward ZERO_WRITE flag for full preallocation +Bugzilla: 1780574 +RH-Acked-by: Sergio Lopez Pascual +RH-Acked-by: Eric Blake +RH-Acked-by: Max Reitz + +The BDRV_REQ_ZERO_WRITE is currently implemented in a way that first the +image is possibly preallocated and then the zero flag is added to all +clusters. This means that a copy-on-write operation may be needed when +writing to these clusters, despite having used preallocation, negating +one of the major benefits of preallocation. + +Instead, try to forward the BDRV_REQ_ZERO_WRITE to the protocol driver, +and if the protocol driver can ensure that the new area reads as zeros, +we can skip setting the zero flag in the qcow2 layer. + +Unfortunately, the same approach doesn't work for metadata +preallocation, so we'll still set the zero flag there. + +Signed-off-by: Kevin Wolf +Reviewed-by: Max Reitz +Message-Id: <20200424142701.67053-1-kwolf@redhat.com> +Reviewed-by: Vladimir Sementsov-Ogievskiy +Signed-off-by: Kevin Wolf +(cherry picked from commit eb8a0cf3ba26611f3981f8f45ac6a868975a68cc) +Signed-off-by: Kevin Wolf +Signed-off-by: Danilo C. L. de Paula +--- + block/qcow2.c | 22 +++++++++++++++++++--- + tests/qemu-iotests/274.out | 4 ++-- + 2 files changed, 21 insertions(+), 5 deletions(-) + +diff --git a/block/qcow2.c b/block/qcow2.c +index f3d6cb0..b783662 100644 +--- a/block/qcow2.c ++++ b/block/qcow2.c +@@ -4153,9 +4153,25 @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset, + /* Allocate the data area */ + new_file_size = allocation_start + + nb_new_data_clusters * s->cluster_size; +- /* Image file grows, so @exact does not matter */ +- ret = bdrv_co_truncate(bs->file, new_file_size, false, prealloc, 0, +- errp); ++ /* ++ * Image file grows, so @exact does not matter. ++ * ++ * If we need to zero out the new area, try first whether the protocol ++ * driver can already take care of this. ++ */ ++ if (flags & BDRV_REQ_ZERO_WRITE) { ++ ret = bdrv_co_truncate(bs->file, new_file_size, false, prealloc, ++ BDRV_REQ_ZERO_WRITE, NULL); ++ if (ret >= 0) { ++ flags &= ~BDRV_REQ_ZERO_WRITE; ++ } ++ } else { ++ ret = -1; ++ } ++ if (ret < 0) { ++ ret = bdrv_co_truncate(bs->file, new_file_size, false, prealloc, 0, ++ errp); ++ } + if (ret < 0) { + error_prepend(errp, "Failed to resize underlying file: "); + qcow2_free_clusters(bs, allocation_start, +diff --git a/tests/qemu-iotests/274.out b/tests/qemu-iotests/274.out +index 1a796fd..9d6fdeb 100644 +--- a/tests/qemu-iotests/274.out ++++ b/tests/qemu-iotests/274.out +@@ -187,7 +187,7 @@ read 65536/65536 bytes at offset 9437184 + 10 MiB (0xa00000) bytes allocated at offset 5 MiB (0x500000) + + [{ "start": 0, "length": 5242880, "depth": 1, "zero": true, "data": false}, +-{ "start": 5242880, "length": 10485760, "depth": 0, "zero": true, "data": false, "offset": 327680}] ++{ "start": 5242880, "length": 10485760, "depth": 0, "zero": false, "data": true, "offset": 327680}] + + === preallocation=full === + Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=16777216 cluster_size=65536 lazy_refcounts=off refcount_bits=16 +@@ -206,7 +206,7 @@ read 65536/65536 bytes at offset 11534336 + 4 MiB (0x400000) bytes allocated at offset 8 MiB (0x800000) + + [{ "start": 0, "length": 8388608, "depth": 1, "zero": true, "data": false}, +-{ "start": 8388608, "length": 4194304, "depth": 0, "zero": true, "data": false, "offset": 327680}] ++{ "start": 8388608, "length": 4194304, "depth": 0, "zero": false, "data": true, "offset": 327680}] + + === preallocation=off === + Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=393216 cluster_size=65536 lazy_refcounts=off refcount_bits=16 +-- +1.8.3.1 + diff --git a/SOURCES/kvm-qcow2-Support-BDRV_REQ_ZERO_WRITE-for-truncate.patch b/SOURCES/kvm-qcow2-Support-BDRV_REQ_ZERO_WRITE-for-truncate.patch new file mode 100644 index 0000000..454759e --- /dev/null +++ b/SOURCES/kvm-qcow2-Support-BDRV_REQ_ZERO_WRITE-for-truncate.patch @@ -0,0 +1,101 @@ +From 3e603e344b81b3ecfea6fb9589ba91f70a22139d Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Mon, 8 Jun 2020 15:01:33 +0100 +Subject: [PATCH 05/17] qcow2: Support BDRV_REQ_ZERO_WRITE for truncate + +RH-Author: Kevin Wolf +Message-id: <20200608150140.38218-5-kwolf@redhat.com> +Patchwork-id: 97449 +O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH 04/11] qcow2: Support BDRV_REQ_ZERO_WRITE for truncate +Bugzilla: 1780574 +RH-Acked-by: Sergio Lopez Pascual +RH-Acked-by: Eric Blake +RH-Acked-by: Max Reitz + +If BDRV_REQ_ZERO_WRITE is set and we're extending the image, calling +qcow2_cluster_zeroize() with flags=0 does the right thing: It doesn't +undo any previous preallocation, but just adds the zero flag to all +relevant L2 entries. If an external data file is in use, a write_zeroes +request to the data file is made instead. + +Signed-off-by: Kevin Wolf +Message-Id: <20200424125448.63318-5-kwolf@redhat.com> +Reviewed-by: Eric Blake +Reviewed-by: Max Reitz +Signed-off-by: Kevin Wolf +(cherry picked from commit f01643fb8b47e8a70c04bbf45e0f12a9e5bc54de) +Signed-off-by: Kevin Wolf +Signed-off-by: Danilo C. L. de Paula +--- + block/qcow2-cluster.c | 2 +- + block/qcow2.c | 34 ++++++++++++++++++++++++++++++++++ + 2 files changed, 35 insertions(+), 1 deletion(-) + +diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c +index dc3c270..9d04f8d 100644 +--- a/block/qcow2-cluster.c ++++ b/block/qcow2-cluster.c +@@ -1784,7 +1784,7 @@ int qcow2_cluster_zeroize(BlockDriverState *bs, uint64_t offset, + /* Caller must pass aligned values, except at image end */ + assert(QEMU_IS_ALIGNED(offset, s->cluster_size)); + assert(QEMU_IS_ALIGNED(end_offset, s->cluster_size) || +- end_offset == bs->total_sectors << BDRV_SECTOR_BITS); ++ end_offset >= bs->total_sectors << BDRV_SECTOR_BITS); + + /* The zero flag is only supported by version 3 and newer */ + if (s->qcow_version < 3) { +diff --git a/block/qcow2.c b/block/qcow2.c +index 86aa74a..f3d6cb0 100644 +--- a/block/qcow2.c ++++ b/block/qcow2.c +@@ -1726,6 +1726,7 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options, + } + + bs->supported_zero_flags = header.version >= 3 ? BDRV_REQ_MAY_UNMAP : 0; ++ bs->supported_truncate_flags = BDRV_REQ_ZERO_WRITE; + + /* Repair image if dirty */ + if (!(flags & (BDRV_O_CHECK | BDRV_O_INACTIVE)) && !bs->read_only && +@@ -4197,6 +4198,39 @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset, + g_assert_not_reached(); + } + ++ if ((flags & BDRV_REQ_ZERO_WRITE) && offset > old_length) { ++ uint64_t zero_start = QEMU_ALIGN_UP(old_length, s->cluster_size); ++ ++ /* ++ * Use zero clusters as much as we can. qcow2_cluster_zeroize() ++ * requires a cluster-aligned start. The end may be unaligned if it is ++ * at the end of the image (which it is here). ++ */ ++ ret = qcow2_cluster_zeroize(bs, zero_start, offset - zero_start, 0); ++ if (ret < 0) { ++ error_setg_errno(errp, -ret, "Failed to zero out new clusters"); ++ goto fail; ++ } ++ ++ /* Write explicit zeros for the unaligned head */ ++ if (zero_start > old_length) { ++ uint64_t len = zero_start - old_length; ++ uint8_t *buf = qemu_blockalign0(bs, len); ++ QEMUIOVector qiov; ++ qemu_iovec_init_buf(&qiov, buf, len); ++ ++ qemu_co_mutex_unlock(&s->lock); ++ ret = qcow2_co_pwritev_part(bs, old_length, len, &qiov, 0, 0); ++ qemu_co_mutex_lock(&s->lock); ++ ++ qemu_vfree(buf); ++ if (ret < 0) { ++ error_setg_errno(errp, -ret, "Failed to zero out the new area"); ++ goto fail; ++ } ++ } ++ } ++ + if (prealloc != PREALLOC_MODE_OFF) { + /* Flush metadata before actually changing the image size */ + ret = qcow2_write_caches(bs); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-qemu-img-Add-bitmap-sub-command.patch b/SOURCES/kvm-qemu-img-Add-bitmap-sub-command.patch new file mode 100644 index 0000000..eb80188 --- /dev/null +++ b/SOURCES/kvm-qemu-img-Add-bitmap-sub-command.patch @@ -0,0 +1,398 @@ +From 53baacb72e8561391841363b2acbd85a783cbc66 Mon Sep 17 00:00:00 2001 +From: Eric Blake +Date: Tue, 2 Jun 2020 02:34:15 +0100 +Subject: [PATCH 10/26] qemu-img: Add bitmap sub-command + +RH-Author: Eric Blake +Message-id: <20200602023420.2133649-8-eblake@redhat.com> +Patchwork-id: 97074 +O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH 07/12] qemu-img: Add bitmap sub-command +Bugzilla: 1779893 1779904 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Max Reitz +RH-Acked-by: Kevin Wolf + +Include actions for --add, --remove, --clear, --enable, --disable, and +--merge (note that --clear is a bit of fluff, because the same can be +accomplished by removing a bitmap and then adding a new one in its +place, but it matches what QMP commands exist). Listing is omitted, +because it does not require a bitmap name and because it was already +possible with 'qemu-img info'. A single command line can play one or +more bitmap commands in sequence on the same bitmap name (although all +added bitmaps share the same granularity, and and all merged bitmaps +come from the same source file). Merge defaults to other bitmaps in +the primary image, but can also be told to merge bitmaps from a +distinct image. + +While this supports --image-opts for the file being modified, I did +not think it worth the extra complexity to support that for the source +file in a cross-file merges. Likewise, I chose to have --merge only +take a single source rather than following the QMP support for +multiple merges in one go (although you can still use more than one +--merge in the command line); in part because qemu-img is offline and +therefore atomicity is not an issue. + +Upcoming patches will add iotest coverage of these commands while +also testing other features. + +Signed-off-by: Eric Blake +Reviewed-by: Max Reitz +Message-Id: <20200513011648.166876-7-eblake@redhat.com> +Reviewed-by: Vladimir Sementsov-Ogievskiy +(cherry picked from commit 3b51ab4bf0f49a01cc2db7b954e0669e081719b5) + +Signed-off-by: Danilo C. L. de Paula + +Conflicts: + docs/tools/qemu-img.rst - lives in qemu-img.texi instead; plus + fix a typo in the text for --merge rather than waiting for + a one-line upstream followup patch + qemu-img-cmds.hx - context, use texi instead of rst + qemu-img.c - context +Signed-off-by: Eric Blake + +Signed-off-by: Danilo C. L. de Paula +--- + qemu-img-cmds.hx | 6 ++ + qemu-img.c | 248 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ + qemu-img.texi | 27 ++++++ + 3 files changed, 281 insertions(+) + +diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx +index 1c93e6d..1a6a8e9 100644 +--- a/qemu-img-cmds.hx ++++ b/qemu-img-cmds.hx +@@ -25,6 +25,12 @@ STEXI + @item bench [-c @var{count}] [-d @var{depth}] [-f @var{fmt}] [--flush-interval=@var{flush_interval}] [-n] [--no-drain] [-o @var{offset}] [--pattern=@var{pattern}] [-q] [-s @var{buffer_size}] [-S @var{step_size}] [-t @var{cache}] [-w] [-U] @var{filename} + ETEXI + ++DEF("bitmap", img_bitmap, ++ "bitmap (--merge SOURCE | --add | --remove | --clear | --enable | --disable)... [-b source_file [-F source_fmt]] [-g granularity] [--object objectdef] [--image-opts | -f fmt] filename bitmap") ++STEXI ++.. option:: bitmap (--merge @var{source} | --add | --remove | --clear | --enable | --disable)... [-b @var{source_file} [-F @var{source_fmt}]] [-g @var{granularity}] [--object @var{objectdef}] [--image-opts | -f @var{fmt}] @var{filename} @var{bitmap} ++ETEXI ++ + DEF("check", img_check, + "check [--object objectdef] [--image-opts] [-q] [-f fmt] [--output=ofmt] [-r [leaks | all]] [-T src_cache] [-U] filename") + STEXI +diff --git a/qemu-img.c b/qemu-img.c +index e69529b..11a4537 100644 +--- a/qemu-img.c ++++ b/qemu-img.c +@@ -28,6 +28,7 @@ + #include "qemu-common.h" + #include "qemu-version.h" + #include "qapi/error.h" ++#include "qapi/qapi-commands-block-core.h" + #include "qapi/qapi-visit-block-core.h" + #include "qapi/qobject-output-visitor.h" + #include "qapi/qmp/qjson.h" +@@ -70,6 +71,12 @@ enum { + OPTION_PREALLOCATION = 265, + OPTION_SHRINK = 266, + OPTION_SALVAGE = 267, ++ OPTION_ADD = 269, ++ OPTION_REMOVE = 270, ++ OPTION_CLEAR = 271, ++ OPTION_ENABLE = 272, ++ OPTION_DISABLE = 273, ++ OPTION_MERGE = 274, + }; + + typedef enum OutputFormat { +@@ -168,6 +175,14 @@ static void QEMU_NORETURN help(void) + " '-n' skips the target volume creation (useful if the volume is created\n" + " prior to running qemu-img)\n" + "\n" ++ "Parameters to bitmap subcommand:\n" ++ " 'bitmap' is the name of the bitmap to manipulate, through one or more\n" ++ " actions from '--add', '--remove', '--clear', '--enable', '--disable',\n" ++ " or '--merge source'\n" ++ " '-g granularity' sets the granularity for '--add' actions\n" ++ " '-b source' and '-F src_fmt' tell '--merge' actions to find the source\n" ++ " bitmaps from an alternative file\n" ++ "\n" + "Parameters to check subcommand:\n" + " '-r' tries to repair any inconsistencies that are found during the check.\n" + " '-r leaks' repairs only cluster leaks, whereas '-r all' fixes all\n" +@@ -4402,6 +4417,239 @@ out: + return 0; + } + ++enum ImgBitmapAct { ++ BITMAP_ADD, ++ BITMAP_REMOVE, ++ BITMAP_CLEAR, ++ BITMAP_ENABLE, ++ BITMAP_DISABLE, ++ BITMAP_MERGE, ++}; ++typedef struct ImgBitmapAction { ++ enum ImgBitmapAct act; ++ const char *src; /* only used for merge */ ++ QSIMPLEQ_ENTRY(ImgBitmapAction) next; ++} ImgBitmapAction; ++ ++static int img_bitmap(int argc, char **argv) ++{ ++ Error *err = NULL; ++ int c, ret = 1; ++ QemuOpts *opts = NULL; ++ const char *fmt = NULL, *src_fmt = NULL, *src_filename = NULL; ++ const char *filename, *bitmap; ++ BlockBackend *blk = NULL, *src = NULL; ++ BlockDriverState *bs = NULL, *src_bs = NULL; ++ bool image_opts = false; ++ int64_t granularity = 0; ++ bool add = false, merge = false; ++ QSIMPLEQ_HEAD(, ImgBitmapAction) actions; ++ ImgBitmapAction *act, *act_next; ++ const char *op; ++ ++ QSIMPLEQ_INIT(&actions); ++ ++ for (;;) { ++ static const struct option long_options[] = { ++ {"help", no_argument, 0, 'h'}, ++ {"object", required_argument, 0, OPTION_OBJECT}, ++ {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS}, ++ {"add", no_argument, 0, OPTION_ADD}, ++ {"remove", no_argument, 0, OPTION_REMOVE}, ++ {"clear", no_argument, 0, OPTION_CLEAR}, ++ {"enable", no_argument, 0, OPTION_ENABLE}, ++ {"disable", no_argument, 0, OPTION_DISABLE}, ++ {"merge", required_argument, 0, OPTION_MERGE}, ++ {"granularity", required_argument, 0, 'g'}, ++ {"source-file", required_argument, 0, 'b'}, ++ {"source-format", required_argument, 0, 'F'}, ++ {0, 0, 0, 0} ++ }; ++ c = getopt_long(argc, argv, ":b:f:F:g:h", long_options, NULL); ++ if (c == -1) { ++ break; ++ } ++ ++ switch (c) { ++ case ':': ++ missing_argument(argv[optind - 1]); ++ break; ++ case '?': ++ unrecognized_option(argv[optind - 1]); ++ break; ++ case 'h': ++ help(); ++ break; ++ case 'b': ++ src_filename = optarg; ++ break; ++ case 'f': ++ fmt = optarg; ++ break; ++ case 'F': ++ src_fmt = optarg; ++ break; ++ case 'g': ++ granularity = cvtnum("granularity", optarg); ++ if (granularity < 0) { ++ return 1; ++ } ++ break; ++ case OPTION_ADD: ++ act = g_new0(ImgBitmapAction, 1); ++ act->act = BITMAP_ADD; ++ QSIMPLEQ_INSERT_TAIL(&actions, act, next); ++ add = true; ++ break; ++ case OPTION_REMOVE: ++ act = g_new0(ImgBitmapAction, 1); ++ act->act = BITMAP_REMOVE; ++ QSIMPLEQ_INSERT_TAIL(&actions, act, next); ++ break; ++ case OPTION_CLEAR: ++ act = g_new0(ImgBitmapAction, 1); ++ act->act = BITMAP_CLEAR; ++ QSIMPLEQ_INSERT_TAIL(&actions, act, next); ++ break; ++ case OPTION_ENABLE: ++ act = g_new0(ImgBitmapAction, 1); ++ act->act = BITMAP_ENABLE; ++ QSIMPLEQ_INSERT_TAIL(&actions, act, next); ++ break; ++ case OPTION_DISABLE: ++ act = g_new0(ImgBitmapAction, 1); ++ act->act = BITMAP_DISABLE; ++ QSIMPLEQ_INSERT_TAIL(&actions, act, next); ++ break; ++ case OPTION_MERGE: ++ act = g_new0(ImgBitmapAction, 1); ++ act->act = BITMAP_MERGE; ++ act->src = optarg; ++ QSIMPLEQ_INSERT_TAIL(&actions, act, next); ++ merge = true; ++ break; ++ case OPTION_OBJECT: ++ opts = qemu_opts_parse_noisily(&qemu_object_opts, optarg, true); ++ if (!opts) { ++ goto out; ++ } ++ break; ++ case OPTION_IMAGE_OPTS: ++ image_opts = true; ++ break; ++ } ++ } ++ ++ if (qemu_opts_foreach(&qemu_object_opts, ++ user_creatable_add_opts_foreach, ++ qemu_img_object_print_help, &error_fatal)) { ++ goto out; ++ } ++ ++ if (QSIMPLEQ_EMPTY(&actions)) { ++ error_report("Need at least one of --add, --remove, --clear, " ++ "--enable, --disable, or --merge"); ++ goto out; ++ } ++ ++ if (granularity && !add) { ++ error_report("granularity only supported with --add"); ++ goto out; ++ } ++ if (src_fmt && !src_filename) { ++ error_report("-F only supported with -b"); ++ goto out; ++ } ++ if (src_filename && !merge) { ++ error_report("Merge bitmap source file only supported with " ++ "--merge"); ++ goto out; ++ } ++ ++ if (optind != argc - 2) { ++ error_report("Expecting filename and bitmap name"); ++ goto out; ++ } ++ ++ filename = argv[optind]; ++ bitmap = argv[optind + 1]; ++ ++ blk = img_open(image_opts, filename, fmt, BDRV_O_RDWR, false, false, ++ false); ++ if (!blk) { ++ goto out; ++ } ++ bs = blk_bs(blk); ++ if (src_filename) { ++ src = img_open(false, src_filename, src_fmt, 0, false, false, false); ++ if (!src) { ++ goto out; ++ } ++ src_bs = blk_bs(src); ++ } else { ++ src_bs = bs; ++ } ++ ++ QSIMPLEQ_FOREACH_SAFE(act, &actions, next, act_next) { ++ switch (act->act) { ++ case BITMAP_ADD: ++ qmp_block_dirty_bitmap_add(bs->node_name, bitmap, ++ !!granularity, granularity, true, true, ++ false, false, &err); ++ op = "add"; ++ break; ++ case BITMAP_REMOVE: ++ qmp_block_dirty_bitmap_remove(bs->node_name, bitmap, &err); ++ op = "remove"; ++ break; ++ case BITMAP_CLEAR: ++ qmp_block_dirty_bitmap_clear(bs->node_name, bitmap, &err); ++ op = "clear"; ++ break; ++ case BITMAP_ENABLE: ++ qmp_block_dirty_bitmap_enable(bs->node_name, bitmap, &err); ++ op = "enable"; ++ break; ++ case BITMAP_DISABLE: ++ qmp_block_dirty_bitmap_disable(bs->node_name, bitmap, &err); ++ op = "disable"; ++ break; ++ case BITMAP_MERGE: { ++ BlockDirtyBitmapMergeSource *merge_src; ++ BlockDirtyBitmapMergeSourceList *list; ++ ++ merge_src = g_new0(BlockDirtyBitmapMergeSource, 1); ++ merge_src->type = QTYPE_QDICT; ++ merge_src->u.external.node = g_strdup(src_bs->node_name); ++ merge_src->u.external.name = g_strdup(act->src); ++ list = g_new0(BlockDirtyBitmapMergeSourceList, 1); ++ list->value = merge_src; ++ qmp_block_dirty_bitmap_merge(bs->node_name, bitmap, list, &err); ++ qapi_free_BlockDirtyBitmapMergeSourceList(list); ++ op = "merge"; ++ break; ++ } ++ default: ++ g_assert_not_reached(); ++ } ++ ++ if (err) { ++ error_reportf_err(err, "Operation %s on bitmap %s failed: ", ++ op, bitmap); ++ goto out; ++ } ++ g_free(act); ++ } ++ ++ ret = 0; ++ ++ out: ++ blk_unref(src); ++ blk_unref(blk); ++ qemu_opts_del(opts); ++ return ret; ++} ++ + #define C_BS 01 + #define C_COUNT 02 + #define C_IF 04 +diff --git a/qemu-img.texi b/qemu-img.texi +index b5156d6..abf2771 100644 +--- a/qemu-img.texi ++++ b/qemu-img.texi +@@ -230,6 +230,33 @@ specified as well. + For write tests, by default a buffer filled with zeros is written. This can be + overridden with a pattern byte specified by @var{pattern}. + ++@item bitmap (--merge @var{source} | --add | --remove | --clear | --enable | --disable)... [-b @var{source_file} [-F @var{source_fmt}]] [-g @var{granularity}] [--object @var{objectdef}] [--image-opts | -f @var{fmt}] @var{filename} @var{bitmap} ++ ++Perform one or more modifications of the persistent bitmap @var{bitmap} ++in the disk image @var{filename}. The various modifications are: ++ ++@table @option ++@item add ++create @var{bitmap}, enabled to record future edits. ++@item remove ++remove @var{bitmap}. ++@item clear ++clear @var{bitmap}. ++@item enable ++change @var{bitmap} to start recording future edits. ++@item disable ++change @var{bitmap} to stop recording future edits. ++@item merge @var{source} ++merge the contents of the @var{source} bitmap into @var{bitmap}. ++@end table ++ ++Additional options include @option{-g} which sets a non-default ++@var{granularity} for @option{--add}, and @option{-b} and @option{-F} ++which select an alternative source file for all @var{source} bitmaps used by ++@option{--merge}. ++ ++To see what bitmaps are present in an image, use @code{qemu-img info}. ++ + @item check [--object @var{objectdef}] [--image-opts] [-q] [-f @var{fmt}] [--output=@var{ofmt}] [-r [leaks | all]] [-T @var{src_cache}] [-U] @var{filename} + + Perform a consistency check on the disk image @var{filename}. The command can +-- +1.8.3.1 + diff --git a/SOURCES/kvm-qemu-img-Add-convert-bitmaps-option.patch b/SOURCES/kvm-qemu-img-Add-convert-bitmaps-option.patch new file mode 100644 index 0000000..20eca9f --- /dev/null +++ b/SOURCES/kvm-qemu-img-Add-convert-bitmaps-option.patch @@ -0,0 +1,244 @@ +From f2add7d5955770318824c3eee774bec2dd850936 Mon Sep 17 00:00:00 2001 +From: Eric Blake +Date: Tue, 2 Jun 2020 02:34:19 +0100 +Subject: [PATCH 14/26] qemu-img: Add convert --bitmaps option + +RH-Author: Eric Blake +Message-id: <20200602023420.2133649-12-eblake@redhat.com> +Patchwork-id: 97076 +O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH 11/12] qemu-img: Add convert --bitmaps option +Bugzilla: 1779893 1779904 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Max Reitz +RH-Acked-by: Kevin Wolf + +Make it easier to copy all the persistent bitmaps of (the top layer +of) a source image along with its guest-visible contents, by adding a +boolean flag for use with qemu-img convert. This is basically +shorthand, as the same effect could be accomplished with a series of +'qemu-img bitmap --add' and 'qemu-img bitmap --merge -b source' +commands, or by their corresponding QMP commands. + +Note that this command will fail in the same scenarios where 'qemu-img +measure' omits a 'bitmaps size:' line, namely, when either the source +or the destination lacks persistent bitmap support altogether. + +See also https://bugzilla.redhat.com/show_bug.cgi?id=1779893 + +While touching this, clean up a couple coding issues spotted in the +same function: an extra blank line, and merging back-to-back 'if +(!skip_create)' blocks. + +Signed-off-by: Eric Blake +Message-Id: <20200521192137.1120211-5-eblake@redhat.com> +Reviewed-by: Vladimir Sementsov-Ogievskiy +(cherry picked from commit 15e39ad95078d528dfb9a75417453cab60332b77) + +Signed-off-by: Danilo C. L. de Paula + +Conflicts: + docs/tools/qemu-img.rst - qemu-img.texi instead + qemu-img.c - context: no --target-is-zero + qemu-img-cmds.hx - context: texi instead of rst +Signed-off-by: Eric Blake + +Signed-off-by: Danilo C. L. de Paula +--- + qemu-img-cmds.hx | 4 ++-- + qemu-img.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++--- + qemu-img.texi | 4 +++- + 3 files changed, 72 insertions(+), 6 deletions(-) + +diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx +index 1a6a8e9..48144aa 100644 +--- a/qemu-img-cmds.hx ++++ b/qemu-img-cmds.hx +@@ -50,9 +50,9 @@ STEXI + ETEXI + + DEF("convert", img_convert, +- "convert [--object objectdef] [--image-opts] [--target-image-opts] [-U] [-C] [-c] [-p] [-q] [-n] [-f fmt] [-t cache] [-T src_cache] [-O output_fmt] [-B backing_file] [-o options] [-l snapshot_param] [-S sparse_size] [-m num_coroutines] [-W] [--salvage] filename [filename2 [...]] output_filename") ++ "convert [--object objectdef] [--image-opts] [--target-image-opts] [--bitmaps] [-U] [-C] [-c] [-p] [-q] [-n] [-f fmt] [-t cache] [-T src_cache] [-O output_fmt] [-B backing_file] [-o options] [-l snapshot_param] [-S sparse_size] [-m num_coroutines] [-W] [--salvage] filename [filename2 [...]] output_filename") + STEXI +-@item convert [--object @var{objectdef}] [--image-opts] [--target-image-opts] [-U] [-C] [-c] [-p] [-q] [-n] [-f @var{fmt}] [-t @var{cache}] [-T @var{src_cache}] [-O @var{output_fmt}] [-B @var{backing_file}] [-o @var{options}] [-l @var{snapshot_param}] [-S @var{sparse_size}] [-m @var{num_coroutines}] [-W] [--salvage] @var{filename} [@var{filename2} [...]] @var{output_filename} ++@item convert [--object @var{objectdef}] [--image-opts] [--target-image-opts] [--bitmaps] [-U] [-C] [-c] [-p] [-q] [-n] [-f @var{fmt}] [-t @var{cache}] [-T @var{src_cache}] [-O @var{output_fmt}] [-B @var{backing_file}] [-o @var{options}] [-l @var{snapshot_param}] [-S @var{sparse_size}] [-m @var{num_coroutines}] [-W] [--salvage] @var{filename} [@var{filename2} [...]] @var{output_filename} + ETEXI + + DEF("create", img_create, +diff --git a/qemu-img.c b/qemu-img.c +index 39e1586..6dc881b 100644 +--- a/qemu-img.c ++++ b/qemu-img.c +@@ -77,6 +77,7 @@ enum { + OPTION_ENABLE = 272, + OPTION_DISABLE = 273, + OPTION_MERGE = 274, ++ OPTION_BITMAPS = 275, + }; + + typedef enum OutputFormat { +@@ -190,6 +191,7 @@ static void QEMU_NORETURN help(void) + " hiding corruption that has already occurred.\n" + "\n" + "Parameters to convert subcommand:\n" ++ " '--bitmaps' copies all top-level persistent bitmaps to destination\n" + " '-m' specifies how many coroutines work in parallel during the convert\n" + " process (defaults to 8)\n" + " '-W' allow to write to the target out of order rather than sequential\n" +@@ -2084,6 +2086,39 @@ static int convert_do_copy(ImgConvertState *s) + return s->ret; + } + ++static int convert_copy_bitmaps(BlockDriverState *src, BlockDriverState *dst) ++{ ++ BdrvDirtyBitmap *bm; ++ Error *err = NULL; ++ ++ FOR_EACH_DIRTY_BITMAP(src, bm) { ++ const char *name; ++ ++ if (!bdrv_dirty_bitmap_get_persistence(bm)) { ++ continue; ++ } ++ name = bdrv_dirty_bitmap_name(bm); ++ qmp_block_dirty_bitmap_add(dst->node_name, name, ++ true, bdrv_dirty_bitmap_granularity(bm), ++ true, true, ++ true, !bdrv_dirty_bitmap_enabled(bm), ++ &err); ++ if (err) { ++ error_reportf_err(err, "Failed to create bitmap %s: ", name); ++ return -1; ++ } ++ ++ do_dirty_bitmap_merge(dst->node_name, name, src->node_name, name, ++ &err); ++ if (err) { ++ error_reportf_err(err, "Failed to populate bitmap %s: ", name); ++ return -1; ++ } ++ } ++ ++ return 0; ++} ++ + #define MAX_BUF_SECTORS 32768 + + static int img_convert(int argc, char **argv) +@@ -2105,6 +2140,7 @@ static int img_convert(int argc, char **argv) + int64_t ret = -EINVAL; + bool force_share = false; + bool explict_min_sparse = false; ++ bool bitmaps = false; + + ImgConvertState s = (ImgConvertState) { + /* Need at least 4k of zeros for sparse detection */ +@@ -2123,6 +2159,7 @@ static int img_convert(int argc, char **argv) + {"force-share", no_argument, 0, 'U'}, + {"target-image-opts", no_argument, 0, OPTION_TARGET_IMAGE_OPTS}, + {"salvage", no_argument, 0, OPTION_SALVAGE}, ++ {"bitmaps", no_argument, 0, OPTION_BITMAPS}, + {0, 0, 0, 0} + }; + c = getopt_long(argc, argv, ":hf:O:B:Cco:l:S:pt:T:qnm:WU", +@@ -2248,6 +2285,9 @@ static int img_convert(int argc, char **argv) + case OPTION_TARGET_IMAGE_OPTS: + tgt_image_opts = true; + break; ++ case OPTION_BITMAPS: ++ bitmaps = true; ++ break; + } + } + +@@ -2304,7 +2344,6 @@ static int img_convert(int argc, char **argv) + goto fail_getopt; + } + +- + /* ret is still -EINVAL until here */ + ret = bdrv_parse_cache_mode(src_cache, &src_flags, &src_writethrough); + if (ret < 0) { +@@ -2458,6 +2497,20 @@ static int img_convert(int argc, char **argv) + } + } + ++ /* Determine if bitmaps need copying */ ++ if (bitmaps) { ++ if (s.src_num > 1) { ++ error_report("Copying bitmaps only possible with single source"); ++ ret = -1; ++ goto out; ++ } ++ if (!bdrv_supports_persistent_dirty_bitmap(blk_bs(s.src[0]))) { ++ error_report("Source lacks bitmap support"); ++ ret = -1; ++ goto out; ++ } ++ } ++ + /* + * The later open call will need any decryption secrets, and + * bdrv_create() will purge "opts", so extract them now before +@@ -2466,9 +2519,7 @@ static int img_convert(int argc, char **argv) + 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); + if (ret < 0) { +@@ -2506,6 +2557,13 @@ static int img_convert(int argc, char **argv) + } + out_bs = blk_bs(s.target); + ++ if (bitmaps && !bdrv_supports_persistent_dirty_bitmap(out_bs)) { ++ error_report("Format driver '%s' does not support bitmaps", ++ out_bs->drv->format_name); ++ ret = -1; ++ goto out; ++ } ++ + if (s.compressed && !block_driver_can_compress(out_bs->drv)) { + error_report("Compression not supported for this file format"); + ret = -1; +@@ -2565,6 +2623,12 @@ static int img_convert(int argc, char **argv) + } + + ret = convert_do_copy(&s); ++ ++ /* Now copy the bitmaps */ ++ if (bitmaps && ret == 0) { ++ ret = convert_copy_bitmaps(blk_bs(s.src[0]), out_bs); ++ } ++ + out: + if (!ret) { + qemu_progress_print(100, 0); +diff --git a/qemu-img.texi b/qemu-img.texi +index 3670b96..b95d019 100644 +--- a/qemu-img.texi ++++ b/qemu-img.texi +@@ -161,6 +161,8 @@ Parameters to convert subcommand: + + @table @option + ++@item --bitmaps ++Additionally copy all persistent bitmaps from the top layer of the source + @item -n + Skip the creation of the target volume + @item -m +@@ -357,7 +359,7 @@ Error on reading data + + @end table + +-@item convert [--object @var{objectdef}] [--image-opts] [--target-image-opts] [-U] [-C] [-c] [-p] [-q] [-n] [-f @var{fmt}] [-t @var{cache}] [-T @var{src_cache}] [-O @var{output_fmt}] [-B @var{backing_file}] [-o @var{options}] [-l @var{snapshot_param}] [-S @var{sparse_size}] [-m @var{num_coroutines}] [-W] @var{filename} [@var{filename2} [...]] @var{output_filename} ++@item convert [--object @var{objectdef}] [--image-opts] [--target-image-opts] [--bitmaps] [-U] [-C] [-c] [-p] [-q] [-n] [-f @var{fmt}] [-t @var{cache}] [-T @var{src_cache}] [-O @var{output_fmt}] [-B @var{backing_file}] [-o @var{options}] [-l @var{snapshot_param}] [-S @var{sparse_size}] [-m @var{num_coroutines}] [-W] @var{filename} [@var{filename2} [...]] @var{output_filename} + + Convert the disk image @var{filename} or a snapshot @var{snapshot_param} + to disk image @var{output_filename} using format @var{output_fmt}. It can be optionally compressed (@code{-c} +-- +1.8.3.1 + diff --git a/SOURCES/kvm-qemu-img-Factor-out-code-for-merging-bitmaps.patch b/SOURCES/kvm-qemu-img-Factor-out-code-for-merging-bitmaps.patch new file mode 100644 index 0000000..c4012b7 --- /dev/null +++ b/SOURCES/kvm-qemu-img-Factor-out-code-for-merging-bitmaps.patch @@ -0,0 +1,89 @@ +From 58816c3709e5058e8805333ca011cc4e793d67ff Mon Sep 17 00:00:00 2001 +From: Eric Blake +Date: Tue, 2 Jun 2020 02:34:18 +0100 +Subject: [PATCH 13/26] qemu-img: Factor out code for merging bitmaps +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Eric Blake +Message-id: <20200602023420.2133649-11-eblake@redhat.com> +Patchwork-id: 97078 +O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH 10/12] qemu-img: Factor out code for merging bitmaps +Bugzilla: 1779893 1779904 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Max Reitz +RH-Acked-by: Kevin Wolf + +The next patch will add another client that wants to merge dirty +bitmaps; it will be easier to refactor the code to construct the QAPI +struct correctly into a helper function. + +Signed-off-by: Eric Blake +Message-Id: <20200521192137.1120211-4-eblake@redhat.com> +Reviewed-by: Vladimir Sementsov-Ogievskiy +(cherry picked from commit 6c729dd832207d7347ecb074912f538e2942f269) +Signed-off-by: Eric Blake +Signed-off-by: Danilo C. L. de Paula +--- + qemu-img.c | 34 +++++++++++++++++++++------------- + 1 file changed, 21 insertions(+), 13 deletions(-) + +diff --git a/qemu-img.c b/qemu-img.c +index b57856e..39e1586 100644 +--- a/qemu-img.c ++++ b/qemu-img.c +@@ -1582,6 +1582,24 @@ out4: + return ret; + } + ++/* Convenience wrapper around qmp_block_dirty_bitmap_merge */ ++static void do_dirty_bitmap_merge(const char *dst_node, const char *dst_name, ++ const char *src_node, const char *src_name, ++ Error **errp) ++{ ++ BlockDirtyBitmapMergeSource *merge_src; ++ BlockDirtyBitmapMergeSourceList *list; ++ ++ merge_src = g_new0(BlockDirtyBitmapMergeSource, 1); ++ merge_src->type = QTYPE_QDICT; ++ merge_src->u.external.node = g_strdup(src_node); ++ merge_src->u.external.name = g_strdup(src_name); ++ list = g_new0(BlockDirtyBitmapMergeSourceList, 1); ++ list->value = merge_src; ++ qmp_block_dirty_bitmap_merge(dst_node, dst_name, list, errp); ++ qapi_free_BlockDirtyBitmapMergeSourceList(list); ++} ++ + enum ImgConvertBlockStatus { + BLK_DATA, + BLK_ZERO, +@@ -4614,21 +4632,11 @@ static int img_bitmap(int argc, char **argv) + qmp_block_dirty_bitmap_disable(bs->node_name, bitmap, &err); + op = "disable"; + break; +- case BITMAP_MERGE: { +- BlockDirtyBitmapMergeSource *merge_src; +- BlockDirtyBitmapMergeSourceList *list; +- +- merge_src = g_new0(BlockDirtyBitmapMergeSource, 1); +- merge_src->type = QTYPE_QDICT; +- merge_src->u.external.node = g_strdup(src_bs->node_name); +- merge_src->u.external.name = g_strdup(act->src); +- list = g_new0(BlockDirtyBitmapMergeSourceList, 1); +- list->value = merge_src; +- qmp_block_dirty_bitmap_merge(bs->node_name, bitmap, list, &err); +- qapi_free_BlockDirtyBitmapMergeSourceList(list); ++ case BITMAP_MERGE: ++ do_dirty_bitmap_merge(bs->node_name, bitmap, src_bs->node_name, ++ act->src, &err); + op = "merge"; + break; +- } + default: + g_assert_not_reached(); + } +-- +1.8.3.1 + diff --git a/SOURCES/kvm-qemu_img-add-cvtnum_full-to-print-error-reports.patch b/SOURCES/kvm-qemu_img-add-cvtnum_full-to-print-error-reports.patch new file mode 100644 index 0000000..b4180b9 --- /dev/null +++ b/SOURCES/kvm-qemu_img-add-cvtnum_full-to-print-error-reports.patch @@ -0,0 +1,241 @@ +From 1a8a4ece5def912e7cfa5ef8565fc8ecef6e72c3 Mon Sep 17 00:00:00 2001 +From: Eric Blake +Date: Tue, 2 Jun 2020 02:34:11 +0100 +Subject: [PATCH 06/26] qemu_img: add cvtnum_full to print error reports + +RH-Author: Eric Blake +Message-id: <20200602023420.2133649-4-eblake@redhat.com> +Patchwork-id: 97067 +O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH 03/12] qemu_img: add cvtnum_full to print error reports +Bugzilla: 1779893 1779904 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Max Reitz +RH-Acked-by: Kevin Wolf + +From: Eyal Moscovici + +All calls to cvtnum check the return value and print the same error +message more or less. And so error reporting moved to cvtnum_full to +reduce code duplication and provide a single error +message. Additionally, cvtnum now wraps cvtnum_full with the existing +default range of 0 to MAX_INT64. + +Acked-by: Mark Kanda +Signed-off-by: Eyal Moscovici +Message-Id: <20200513133629.18508-2-eyal.moscovici@oracle.com> +Reviewed-by: Eric Blake +[eblake: fix printf formatting, avoid trailing space, change error wording, +reformat commit message] +Signed-off-by: Eric Blake +(cherry picked from commit 43d589b074370ebc9b340340b5f641b385da9df8) +Signed-off-by: Eric Blake + +Signed-off-by: Danilo C. L. de Paula +--- + qemu-img.c | 76 +++++++++++++++++++++------------------------- + tests/qemu-iotests/049.out | 8 ++--- + 2 files changed, 38 insertions(+), 46 deletions(-) + +diff --git a/qemu-img.c b/qemu-img.c +index 95a24b9..e69529b 100644 +--- a/qemu-img.c ++++ b/qemu-img.c +@@ -422,19 +422,31 @@ static int add_old_style_options(const char *fmt, QemuOpts *opts, + return 0; + } + +-static int64_t cvtnum(const char *s) ++static int64_t cvtnum_full(const char *name, const char *value, int64_t min, ++ int64_t max) + { + int err; +- uint64_t value; +- +- err = qemu_strtosz(s, NULL, &value); +- if (err < 0) { ++ uint64_t res; ++ ++ err = qemu_strtosz(value, NULL, &res); ++ if (err < 0 && err != -ERANGE) { ++ error_report("Invalid %s specified. You may use " ++ "k, M, G, T, P or E suffixes for", name); ++ error_report("kilobytes, megabytes, gigabytes, terabytes, " ++ "petabytes and exabytes."); + return err; + } +- if (value > INT64_MAX) { ++ if (err == -ERANGE || res > max || res < min) { ++ error_report("Invalid %s specified. Must be between %" PRId64 ++ " and %" PRId64 ".", name, min, max); + return -ERANGE; + } +- return value; ++ return res; ++} ++ ++static int64_t cvtnum(const char *name, const char *value) ++{ ++ return cvtnum_full(name, value, 0, INT64_MAX); + } + + static int img_create(int argc, char **argv) +@@ -532,16 +544,8 @@ static int img_create(int argc, char **argv) + if (optind < argc) { + int64_t sval; + +- sval = cvtnum(argv[optind++]); ++ sval = cvtnum("image size", argv[optind++]); + if (sval < 0) { +- if (sval == -ERANGE) { +- error_report("Image size must be less than 8 EiB!"); +- } else { +- error_report("Invalid image size specified! You may use k, M, " +- "G, T, P or E suffixes for "); +- error_report("kilobytes, megabytes, gigabytes, terabytes, " +- "petabytes and exabytes."); +- } + goto fail; + } + img_size = (uint64_t)sval; +@@ -2148,8 +2152,10 @@ static int img_convert(int argc, char **argv) + { + int64_t sval; + +- sval = cvtnum(optarg); +- if (sval < 0 || !QEMU_IS_ALIGNED(sval, BDRV_SECTOR_SIZE) || ++ sval = cvtnum("buffer size for sparse output", optarg); ++ if (sval < 0) { ++ goto fail_getopt; ++ } else if (!QEMU_IS_ALIGNED(sval, BDRV_SECTOR_SIZE) || + sval / BDRV_SECTOR_SIZE > MAX_BUF_SECTORS) { + error_report("Invalid buffer size for sparse output specified. " + "Valid sizes are multiples of %llu up to %llu. Select " +@@ -4229,9 +4235,8 @@ static int img_bench(int argc, char **argv) + break; + case 'o': + { +- offset = cvtnum(optarg); ++ offset = cvtnum("offset", optarg); + if (offset < 0) { +- error_report("Invalid offset specified"); + return 1; + } + break; +@@ -4244,9 +4249,8 @@ static int img_bench(int argc, char **argv) + { + int64_t sval; + +- sval = cvtnum(optarg); +- if (sval < 0 || sval > INT_MAX) { +- error_report("Invalid buffer size specified"); ++ sval = cvtnum_full("buffer size", optarg, 0, INT_MAX); ++ if (sval < 0) { + return 1; + } + +@@ -4257,9 +4261,8 @@ static int img_bench(int argc, char **argv) + { + int64_t sval; + +- sval = cvtnum(optarg); +- if (sval < 0 || sval > INT_MAX) { +- error_report("Invalid step size specified"); ++ sval = cvtnum_full("step_size", optarg, 0, INT_MAX); ++ if (sval < 0) { + return 1; + } + +@@ -4429,10 +4432,9 @@ static int img_dd_bs(const char *arg, + { + int64_t res; + +- res = cvtnum(arg); ++ res = cvtnum_full("bs", arg, 1, INT_MAX); + +- if (res <= 0 || res > INT_MAX) { +- error_report("invalid number: '%s'", arg); ++ if (res < 0) { + return 1; + } + in->bsz = out->bsz = res; +@@ -4444,10 +4446,9 @@ static int img_dd_count(const char *arg, + struct DdIo *in, struct DdIo *out, + struct DdInfo *dd) + { +- dd->count = cvtnum(arg); ++ dd->count = cvtnum("count", arg); + + if (dd->count < 0) { +- error_report("invalid number: '%s'", arg); + return 1; + } + +@@ -4476,10 +4477,9 @@ static int img_dd_skip(const char *arg, + struct DdIo *in, struct DdIo *out, + struct DdInfo *dd) + { +- in->offset = cvtnum(arg); ++ in->offset = cvtnum("skip", arg); + + if (in->offset < 0) { +- error_report("invalid number: '%s'", arg); + return 1; + } + +@@ -4869,16 +4869,8 @@ static int img_measure(int argc, char **argv) + { + int64_t sval; + +- sval = cvtnum(optarg); ++ sval = cvtnum("image size", optarg); + if (sval < 0) { +- if (sval == -ERANGE) { +- error_report("Image size must be less than 8 EiB!"); +- } else { +- error_report("Invalid image size specified! You may use " +- "k, M, G, T, P or E suffixes for "); +- error_report("kilobytes, megabytes, gigabytes, terabytes, " +- "petabytes and exabytes."); +- } + goto out; + } + img_size = (uint64_t)sval; +diff --git a/tests/qemu-iotests/049.out b/tests/qemu-iotests/049.out +index 6b50540..8b35f3d 100644 +--- a/tests/qemu-iotests/049.out ++++ b/tests/qemu-iotests/049.out +@@ -92,19 +92,19 @@ Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1649267441664 cluster_size=65536 l + == 3. Invalid sizes == + + qemu-img create -f qcow2 TEST_DIR/t.qcow2 -- -1024 +-qemu-img: Image size must be less than 8 EiB! ++qemu-img: Invalid image size specified. Must be between 0 and 9223372036854775807. + + qemu-img create -f qcow2 -o size=-1024 TEST_DIR/t.qcow2 + qemu-img: TEST_DIR/t.qcow2: Value '-1024' is out of range for parameter 'size' + + qemu-img create -f qcow2 TEST_DIR/t.qcow2 -- -1k +-qemu-img: Image size must be less than 8 EiB! ++qemu-img: Invalid image size specified. Must be between 0 and 9223372036854775807. + + qemu-img create -f qcow2 -o size=-1k TEST_DIR/t.qcow2 + qemu-img: TEST_DIR/t.qcow2: Value '-1k' is out of range for parameter 'size' + + qemu-img create -f qcow2 TEST_DIR/t.qcow2 -- 1kilobyte +-qemu-img: Invalid image size specified! You may use k, M, G, T, P or E suffixes for ++qemu-img: Invalid image size specified. You may use k, M, G, T, P or E suffixes for + qemu-img: kilobytes, megabytes, gigabytes, terabytes, petabytes and exabytes. + + qemu-img create -f qcow2 -o size=1kilobyte TEST_DIR/t.qcow2 +@@ -113,7 +113,7 @@ Optional suffix k, M, G, T, P or E means kilo-, mega-, giga-, tera-, peta- + and exabytes, respectively. + + qemu-img create -f qcow2 TEST_DIR/t.qcow2 -- foobar +-qemu-img: Invalid image size specified! You may use k, M, G, T, P or E suffixes for ++qemu-img: Invalid image size specified. You may use k, M, G, T, P or E suffixes for + qemu-img: kilobytes, megabytes, gigabytes, terabytes, petabytes and exabytes. + + qemu-img create -f qcow2 -o size=foobar TEST_DIR/t.qcow2 +-- +1.8.3.1 + diff --git a/SOURCES/kvm-raw-format-Support-BDRV_REQ_ZERO_WRITE-for-truncate.patch b/SOURCES/kvm-raw-format-Support-BDRV_REQ_ZERO_WRITE-for-truncate.patch new file mode 100644 index 0000000..5384b51 --- /dev/null +++ b/SOURCES/kvm-raw-format-Support-BDRV_REQ_ZERO_WRITE-for-truncate.patch @@ -0,0 +1,55 @@ +From 5d590d354e42515ea074bf2110a2ab236dbabba1 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Mon, 8 Jun 2020 15:01:34 +0100 +Subject: [PATCH 06/17] raw-format: Support BDRV_REQ_ZERO_WRITE for truncate + +RH-Author: Kevin Wolf +Message-id: <20200608150140.38218-6-kwolf@redhat.com> +Patchwork-id: 97447 +O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH 05/11] raw-format: Support BDRV_REQ_ZERO_WRITE for truncate +Bugzilla: 1780574 +RH-Acked-by: Sergio Lopez Pascual +RH-Acked-by: Eric Blake +RH-Acked-by: Max Reitz + +The raw format driver can simply forward the flag and let its bs->file +child take care of actually providing the zeros. + +Signed-off-by: Kevin Wolf +Reviewed-by: Max Reitz +Reviewed-by: Eric Blake +Reviewed-by: Vladimir Sementsov-Ogievskiy +Message-Id: <20200424125448.63318-6-kwolf@redhat.com> +Signed-off-by: Kevin Wolf +(cherry picked from commit 1ddaabaecb7eaeb6d8948a32340af95db44c54a1) +Signed-off-by: Kevin Wolf +Signed-off-by: Danilo C. L. de Paula +--- + block/raw-format.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/block/raw-format.c b/block/raw-format.c +index c3acf9a..bdec466 100644 +--- a/block/raw-format.c ++++ b/block/raw-format.c +@@ -387,7 +387,7 @@ static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset, + + s->size = offset; + offset += s->offset; +- return bdrv_co_truncate(bs->file, offset, exact, prealloc, 0, errp); ++ return bdrv_co_truncate(bs->file, offset, exact, prealloc, flags, errp); + } + + static void raw_eject(BlockDriverState *bs, bool eject_flag) +@@ -445,6 +445,8 @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags, + bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED | + ((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) & + bs->file->bs->supported_zero_flags); ++ bs->supported_truncate_flags = bs->file->bs->supported_truncate_flags & ++ BDRV_REQ_ZERO_WRITE; + + if (bs->probed && !bdrv_is_read_only(bs)) { + bdrv_refresh_filename(bs->file->bs); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390-ipl-fix-off-by-one-in-update_machine_ipl_proper.patch b/SOURCES/kvm-s390-ipl-fix-off-by-one-in-update_machine_ipl_proper.patch new file mode 100644 index 0000000..c45158a --- /dev/null +++ b/SOURCES/kvm-s390-ipl-fix-off-by-one-in-update_machine_ipl_proper.patch @@ -0,0 +1,54 @@ +From 1769600e1e3bd5ca48450de8ce8a118bf0af96f3 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 29 May 2020 05:54:00 -0400 +Subject: [PATCH 18/42] s390/ipl: fix off-by-one in + update_machine_ipl_properties() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Thomas Huth +Message-id: <20200529055420.16855-19-thuth@redhat.com> +Patchwork-id: 97028 +O-Subject: [RHEL-8.3.0 qemu-kvm PATCH v2 18/38] s390/ipl: fix off-by-one in update_machine_ipl_properties() +Bugzilla: 1828317 +RH-Acked-by: Claudio Imbrenda +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand + +From: Halil Pasic + +In update_machine_ipl_properties() the array ascii_loadparm needs to +hold the 8 char loadparm and a string terminating zero char. + +Let's increase the size of ascii_loadparm accordingly. + +Signed-off-by: Halil Pasic +Fixes: 0a01e082a428 ("s390/ipl: sync back loadparm") +Fixes: Coverity CID 1421966 +Reported-by: Peter Maydell +Message-Id: <20200320143101.41764-1-pasic@linux.ibm.com> +Signed-off-by: Cornelia Huck +(cherry picked from commit 7722837369eb1c7e808021d79da68afa0c01c26f) +Signed-off-by: Danilo C. L. de Paula +--- + hw/s390x/ipl.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c +index f25339c503..fa0409dc23 100644 +--- a/hw/s390x/ipl.c ++++ b/hw/s390x/ipl.c +@@ -537,7 +537,7 @@ static void update_machine_ipl_properties(IplParameterBlock *iplb) + /* Sync loadparm */ + if (iplb->flags & DIAG308_FLAGS_LP_VALID) { + uint8_t *ebcdic_loadparm = iplb->loadparm; +- char ascii_loadparm[8]; ++ char ascii_loadparm[9]; + int i; + + for (i = 0; i < 8 && ebcdic_loadparm[i]; i++) { +-- +2.27.0 + diff --git a/SOURCES/kvm-s390-ipl-sync-back-loadparm.patch b/SOURCES/kvm-s390-ipl-sync-back-loadparm.patch new file mode 100644 index 0000000..49f4d3f --- /dev/null +++ b/SOURCES/kvm-s390-ipl-sync-back-loadparm.patch @@ -0,0 +1,91 @@ +From 53053ea2e6c757e5d044655c8b61c485e0aad4ed Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 29 May 2020 05:53:59 -0400 +Subject: [PATCH 17/42] s390/ipl: sync back loadparm +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Thomas Huth +Message-id: <20200529055420.16855-18-thuth@redhat.com> +Patchwork-id: 97039 +O-Subject: [RHEL-8.3.0 qemu-kvm PATCH v2 17/38] s390/ipl: sync back loadparm +Bugzilla: 1828317 +RH-Acked-by: Claudio Imbrenda +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand + +From: Halil Pasic + +We expose loadparm as a r/w machine property, but if loadparm is set by +the guest via DIAG 308, we don't update the property. Having a +disconnect between the guest view and the QEMU property is not nice in +itself, but things get even worse for SCSI, where under certain +circumstances (see 789b5a401b "s390: Ensure IPL from SCSI works as +expected" for details) we call s390_gen_initial_iplb() on resets +effectively overwriting the guest/user supplied loadparm with the stale +value. + +Signed-off-by: Halil Pasic +Fixes: 7104bae9de ("hw/s390x: provide loadparm property for the machine") +Reported-by: Marc Hartmayer +Reviewed-by: Janosch Frank +Reviewed-by: Viktor Mihajlovski +Tested-by: Marc Hartmayer +Reviewed-by: David Hildenbrand +Message-Id: <20200309133223.100491-1-pasic@linux.ibm.com> +[borntraeger@de.ibm.com: use reverse xmas tree] +Signed-off-by: Christian Borntraeger +(cherry picked from commit 0a01e082a428b921e48b5314881b1f23a7b0fe50) +Signed-off-by: Danilo C. L. de Paula +--- + hw/s390x/ipl.c | 25 +++++++++++++++++++++++++ + 1 file changed, 25 insertions(+) + +diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c +index 0b7548a549..f25339c503 100644 +--- a/hw/s390x/ipl.c ++++ b/hw/s390x/ipl.c +@@ -529,6 +529,30 @@ static bool is_virtio_scsi_device(IplParameterBlock *iplb) + return is_virtio_ccw_device_of_type(iplb, VIRTIO_ID_SCSI); + } + ++static void update_machine_ipl_properties(IplParameterBlock *iplb) ++{ ++ Object *machine = qdev_get_machine(); ++ Error *err = NULL; ++ ++ /* Sync loadparm */ ++ if (iplb->flags & DIAG308_FLAGS_LP_VALID) { ++ uint8_t *ebcdic_loadparm = iplb->loadparm; ++ char ascii_loadparm[8]; ++ int i; ++ ++ for (i = 0; i < 8 && ebcdic_loadparm[i]; i++) { ++ ascii_loadparm[i] = ebcdic2ascii[(uint8_t) ebcdic_loadparm[i]]; ++ } ++ ascii_loadparm[i] = 0; ++ object_property_set_str(machine, ascii_loadparm, "loadparm", &err); ++ } else { ++ object_property_set_str(machine, "", "loadparm", &err); ++ } ++ if (err) { ++ warn_report_err(err); ++ } ++} ++ + void s390_ipl_update_diag308(IplParameterBlock *iplb) + { + S390IPLState *ipl = get_ipl_device(); +@@ -536,6 +560,7 @@ void s390_ipl_update_diag308(IplParameterBlock *iplb) + ipl->iplb = *iplb; + ipl->iplb_valid = true; + ipl->netboot = is_virtio_net_device(iplb); ++ update_machine_ipl_properties(iplb); + } + + IplParameterBlock *s390_ipl_get_iplb(void) +-- +2.27.0 + diff --git a/SOURCES/kvm-s390-sclp-improve-special-wait-psw-logic.patch b/SOURCES/kvm-s390-sclp-improve-special-wait-psw-logic.patch new file mode 100644 index 0000000..2040d5c --- /dev/null +++ b/SOURCES/kvm-s390-sclp-improve-special-wait-psw-logic.patch @@ -0,0 +1,52 @@ +From cd7da3cf1b19fef0a497fd556562040a85e579a7 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 29 May 2020 05:53:57 -0400 +Subject: [PATCH 15/42] s390/sclp: improve special wait psw logic +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Thomas Huth +Message-id: <20200529055420.16855-16-thuth@redhat.com> +Patchwork-id: 97037 +O-Subject: [RHEL-8.3.0 qemu-kvm PATCH v2 15/38] s390/sclp: improve special wait psw logic +Bugzilla: 1828317 +RH-Acked-by: Claudio Imbrenda +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand + +From: Christian Borntraeger + +There is a special quiesce PSW that we check for "shutdown". Otherwise disabled +wait is detected as "crashed". Architecturally we must only check PSW bits +116-127. Fix this. + +Cc: qemu-stable@nongnu.org +Signed-off-by: Christian Borntraeger +Message-Id: <1582204582-22995-1-git-send-email-borntraeger@de.ibm.com> +Reviewed-by: David Hildenbrand +Acked-by: Janosch Frank +Signed-off-by: Cornelia Huck +(cherry picked from commit 8b51c0961cc13e55b26bb6665ec3a341abdc7658) +Signed-off-by: Danilo C. L. de Paula +--- + target/s390x/helper.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/target/s390x/helper.c b/target/s390x/helper.c +index a3a49164e4..6808dfda01 100644 +--- a/target/s390x/helper.c ++++ b/target/s390x/helper.c +@@ -89,7 +89,7 @@ hwaddr s390_cpu_get_phys_addr_debug(CPUState *cs, vaddr vaddr) + static inline bool is_special_wait_psw(uint64_t psw_addr) + { + /* signal quiesce */ +- return psw_addr == 0xfffUL; ++ return (psw_addr & 0xfffUL) == 0xfffUL; + } + + void s390_handle_wait(S390CPU *cpu) +-- +2.27.0 + diff --git a/SOURCES/kvm-s390x-Add-SIDA-memory-ops.patch b/SOURCES/kvm-s390x-Add-SIDA-memory-ops.patch new file mode 100644 index 0000000..1b566d7 --- /dev/null +++ b/SOURCES/kvm-s390x-Add-SIDA-memory-ops.patch @@ -0,0 +1,150 @@ +From ebcd74c2267d69fe09ca03cb8bfed7bef5ea3a85 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 29 May 2020 05:54:08 -0400 +Subject: [PATCH 26/42] s390x: Add SIDA memory ops + +RH-Author: Thomas Huth +Message-id: <20200529055420.16855-27-thuth@redhat.com> +Patchwork-id: 97033 +O-Subject: [RHEL-8.3.0 qemu-kvm PATCH v2 26/38] s390x: Add SIDA memory ops +Bugzilla: 1828317 +RH-Acked-by: Claudio Imbrenda +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand + +From: Janosch Frank + +Protected guests save the instruction control blocks in the SIDA +instead of QEMU/KVM directly accessing the guest's memory. + +Let's introduce new functions to access the SIDA. + +The memops for doing so are available with KVM_CAP_S390_PROTECTED, so +let's check for that. + +Signed-off-by: Janosch Frank +Reviewed-by: David Hildenbrand +Reviewed-by: Christian Borntraeger +Reviewed-by: Claudio Imbrenda +Reviewed-by: Cornelia Huck +Message-Id: <20200319131921.2367-8-frankja@linux.ibm.com> +Signed-off-by: Cornelia Huck +(cherry picked from commit 1cca8265499d394d9ed4bfb75bd6e7265b529f89) +Signed-off-by: Danilo C. L. de Paula +--- + target/s390x/cpu.h | 7 ++++++- + target/s390x/kvm.c | 26 ++++++++++++++++++++++++++ + target/s390x/kvm_s390x.h | 2 ++ + target/s390x/mmu_helper.c | 14 ++++++++++++++ + 4 files changed, 48 insertions(+), 1 deletion(-) + +diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h +index 1ff84e6b3a..edf8391504 100644 +--- a/target/s390x/cpu.h ++++ b/target/s390x/cpu.h +@@ -828,7 +828,12 @@ int s390_cpu_virt_mem_rw(S390CPU *cpu, vaddr laddr, uint8_t ar, void *hostbuf, + #define s390_cpu_virt_mem_check_write(cpu, laddr, ar, len) \ + s390_cpu_virt_mem_rw(cpu, laddr, ar, NULL, len, true) + void s390_cpu_virt_mem_handle_exc(S390CPU *cpu, uintptr_t ra); +- ++int s390_cpu_pv_mem_rw(S390CPU *cpu, unsigned int offset, void *hostbuf, ++ int len, bool is_write); ++#define s390_cpu_pv_mem_read(cpu, offset, dest, len) \ ++ s390_cpu_pv_mem_rw(cpu, offset, dest, len, false) ++#define s390_cpu_pv_mem_write(cpu, offset, dest, len) \ ++ s390_cpu_pv_mem_rw(cpu, offset, dest, len, true) + + /* sigp.c */ + int s390_cpu_restart(S390CPU *cpu); +diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c +index af50b2c253..f67bb5ce2c 100644 +--- a/target/s390x/kvm.c ++++ b/target/s390x/kvm.c +@@ -154,6 +154,7 @@ static int cap_ri; + static int cap_gs; + static int cap_hpage_1m; + static int cap_vcpu_resets; ++static int cap_protected; + + static int active_cmma; + +@@ -351,6 +352,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s) + cap_mem_op = kvm_check_extension(s, KVM_CAP_S390_MEM_OP); + cap_s390_irq = kvm_check_extension(s, KVM_CAP_S390_INJECT_IRQ); + cap_vcpu_resets = kvm_check_extension(s, KVM_CAP_S390_VCPU_RESETS); ++ cap_protected = kvm_check_extension(s, KVM_CAP_S390_PROTECTED); + + if (!kvm_check_extension(s, KVM_CAP_S390_GMAP) + || !kvm_check_extension(s, KVM_CAP_S390_COW)) { +@@ -848,6 +850,30 @@ int kvm_s390_mem_op(S390CPU *cpu, vaddr addr, uint8_t ar, void *hostbuf, + return ret; + } + ++int kvm_s390_mem_op_pv(S390CPU *cpu, uint64_t offset, void *hostbuf, ++ int len, bool is_write) ++{ ++ struct kvm_s390_mem_op mem_op = { ++ .sida_offset = offset, ++ .size = len, ++ .op = is_write ? KVM_S390_MEMOP_SIDA_WRITE ++ : KVM_S390_MEMOP_SIDA_READ, ++ .buf = (uint64_t)hostbuf, ++ }; ++ int ret; ++ ++ if (!cap_mem_op || !cap_protected) { ++ return -ENOSYS; ++ } ++ ++ ret = kvm_vcpu_ioctl(CPU(cpu), KVM_S390_MEM_OP, &mem_op); ++ if (ret < 0) { ++ error_report("KVM_S390_MEM_OP failed: %s", strerror(-ret)); ++ abort(); ++ } ++ return ret; ++} ++ + /* + * Legacy layout for s390: + * Older S390 KVM requires the topmost vma of the RAM to be +diff --git a/target/s390x/kvm_s390x.h b/target/s390x/kvm_s390x.h +index dea813f450..6ab17c81b7 100644 +--- a/target/s390x/kvm_s390x.h ++++ b/target/s390x/kvm_s390x.h +@@ -19,6 +19,8 @@ void kvm_s390_vcpu_interrupt(S390CPU *cpu, struct kvm_s390_irq *irq); + void kvm_s390_access_exception(S390CPU *cpu, uint16_t code, uint64_t te_code); + int kvm_s390_mem_op(S390CPU *cpu, vaddr addr, uint8_t ar, void *hostbuf, + int len, bool is_write); ++int kvm_s390_mem_op_pv(S390CPU *cpu, vaddr addr, void *hostbuf, int len, ++ bool is_write); + void kvm_s390_program_interrupt(S390CPU *cpu, uint16_t code); + int kvm_s390_set_cpu_state(S390CPU *cpu, uint8_t cpu_state); + void kvm_s390_vcpu_interrupt_pre_save(S390CPU *cpu); +diff --git a/target/s390x/mmu_helper.c b/target/s390x/mmu_helper.c +index c9f3f34750..ec8befbdc8 100644 +--- a/target/s390x/mmu_helper.c ++++ b/target/s390x/mmu_helper.c +@@ -474,6 +474,20 @@ static int translate_pages(S390CPU *cpu, vaddr addr, int nr_pages, + return 0; + } + ++int s390_cpu_pv_mem_rw(S390CPU *cpu, unsigned int offset, void *hostbuf, ++ int len, bool is_write) ++{ ++ int ret; ++ ++ if (kvm_enabled()) { ++ ret = kvm_s390_mem_op_pv(cpu, offset, hostbuf, len, is_write); ++ } else { ++ /* Protected Virtualization is a KVM/Hardware only feature */ ++ g_assert_not_reached(); ++ } ++ return ret; ++} ++ + /** + * s390_cpu_virt_mem_rw: + * @laddr: the logical start address +-- +2.27.0 + diff --git a/SOURCES/kvm-s390x-Add-missing-vcpu-reset-functions.patch b/SOURCES/kvm-s390x-Add-missing-vcpu-reset-functions.patch new file mode 100644 index 0000000..9ce071e --- /dev/null +++ b/SOURCES/kvm-s390x-Add-missing-vcpu-reset-functions.patch @@ -0,0 +1,176 @@ +From e11643b5363262e9f809762a1f2bb5c4a8f26c2a Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 29 May 2020 05:53:56 -0400 +Subject: [PATCH 14/42] s390x: Add missing vcpu reset functions +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Thomas Huth +Message-id: <20200529055420.16855-15-thuth@redhat.com> +Patchwork-id: 97023 +O-Subject: [RHEL-8.3.0 qemu-kvm PATCH v2 14/38] s390x: Add missing vcpu reset functions +Bugzilla: 1828317 +RH-Acked-by: Claudio Imbrenda +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand + +From: Janosch Frank + +Up to now we only had an ioctl to reset vcpu data QEMU couldn't reach +for the initial reset, which was also called for the clear reset. To +be architecture compliant, we also need to clear local interrupts on a +normal reset. + +Because of this and the upcoming protvirt support we need to add +ioctls for the missing clear and normal resets. + +Signed-off-by: Janosch Frank +Reviewed-by: Thomas Huth +Acked-by: David Hildenbrand +Message-Id: <20200214151636.8764-3-frankja@linux.ibm.com> +Signed-off-by: Cornelia Huck +(cherry picked from commit b91a03946e0f65ddd22927dd80ca1276bf89c5af) +Signed-off-by: Danilo C. L. de Paula +--- + target/s390x/cpu.c | 14 ++++++++++++-- + target/s390x/kvm-stub.c | 10 +++++++++- + target/s390x/kvm.c | 42 ++++++++++++++++++++++++++++++++-------- + target/s390x/kvm_s390x.h | 4 +++- + 4 files changed, 58 insertions(+), 12 deletions(-) + +diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c +index e538a4a3e2..c0dd502b84 100644 +--- a/target/s390x/cpu.c ++++ b/target/s390x/cpu.c +@@ -144,8 +144,18 @@ static void s390_cpu_reset(CPUState *s, cpu_reset_type type) + } + + /* Reset state inside the kernel that we cannot access yet from QEMU. */ +- if (kvm_enabled() && type != S390_CPU_RESET_NORMAL) { +- kvm_s390_reset_vcpu(cpu); ++ if (kvm_enabled()) { ++ switch (type) { ++ case S390_CPU_RESET_CLEAR: ++ kvm_s390_reset_vcpu_clear(cpu); ++ break; ++ case S390_CPU_RESET_INITIAL: ++ kvm_s390_reset_vcpu_initial(cpu); ++ break; ++ case S390_CPU_RESET_NORMAL: ++ kvm_s390_reset_vcpu_normal(cpu); ++ break; ++ } + } + } + +diff --git a/target/s390x/kvm-stub.c b/target/s390x/kvm-stub.c +index 5152e2bdf1..c4cd497f85 100644 +--- a/target/s390x/kvm-stub.c ++++ b/target/s390x/kvm-stub.c +@@ -83,7 +83,15 @@ void kvm_s390_cmma_reset(void) + { + } + +-void kvm_s390_reset_vcpu(S390CPU *cpu) ++void kvm_s390_reset_vcpu_initial(S390CPU *cpu) ++{ ++} ++ ++void kvm_s390_reset_vcpu_clear(S390CPU *cpu) ++{ ++} ++ ++void kvm_s390_reset_vcpu_normal(S390CPU *cpu) + { + } + +diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c +index 1c5bc7a2f9..75d82af6fc 100644 +--- a/target/s390x/kvm.c ++++ b/target/s390x/kvm.c +@@ -151,6 +151,7 @@ static int cap_s390_irq; + static int cap_ri; + static int cap_gs; + static int cap_hpage_1m; ++static int cap_vcpu_resets; + + static int active_cmma; + +@@ -342,6 +343,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s) + cap_async_pf = kvm_check_extension(s, KVM_CAP_ASYNC_PF); + cap_mem_op = kvm_check_extension(s, KVM_CAP_S390_MEM_OP); + cap_s390_irq = kvm_check_extension(s, KVM_CAP_S390_INJECT_IRQ); ++ cap_vcpu_resets = kvm_check_extension(s, KVM_CAP_S390_VCPU_RESETS); + + if (!kvm_check_extension(s, KVM_CAP_S390_GMAP) + || !kvm_check_extension(s, KVM_CAP_S390_COW)) { +@@ -403,17 +405,41 @@ int kvm_arch_destroy_vcpu(CPUState *cs) + return 0; + } + +-void kvm_s390_reset_vcpu(S390CPU *cpu) ++static void kvm_s390_reset_vcpu(S390CPU *cpu, unsigned long type) + { + CPUState *cs = CPU(cpu); + +- /* The initial reset call is needed here to reset in-kernel +- * vcpu data that we can't access directly from QEMU +- * (i.e. with older kernels which don't support sync_regs/ONE_REG). +- * Before this ioctl cpu_synchronize_state() is called in common kvm +- * code (kvm-all) */ +- if (kvm_vcpu_ioctl(cs, KVM_S390_INITIAL_RESET, NULL)) { +- error_report("Initial CPU reset failed on CPU %i", cs->cpu_index); ++ /* ++ * The reset call is needed here to reset in-kernel vcpu data that ++ * we can't access directly from QEMU (i.e. with older kernels ++ * which don't support sync_regs/ONE_REG). Before this ioctl ++ * cpu_synchronize_state() is called in common kvm code ++ * (kvm-all). ++ */ ++ if (kvm_vcpu_ioctl(cs, type)) { ++ error_report("CPU reset failed on CPU %i type %lx", ++ cs->cpu_index, type); ++ } ++} ++ ++void kvm_s390_reset_vcpu_initial(S390CPU *cpu) ++{ ++ kvm_s390_reset_vcpu(cpu, KVM_S390_INITIAL_RESET); ++} ++ ++void kvm_s390_reset_vcpu_clear(S390CPU *cpu) ++{ ++ if (cap_vcpu_resets) { ++ kvm_s390_reset_vcpu(cpu, KVM_S390_CLEAR_RESET); ++ } else { ++ kvm_s390_reset_vcpu(cpu, KVM_S390_INITIAL_RESET); ++ } ++} ++ ++void kvm_s390_reset_vcpu_normal(S390CPU *cpu) ++{ ++ if (cap_vcpu_resets) { ++ kvm_s390_reset_vcpu(cpu, KVM_S390_NORMAL_RESET); + } + } + +diff --git a/target/s390x/kvm_s390x.h b/target/s390x/kvm_s390x.h +index caf985955b..0b21789796 100644 +--- a/target/s390x/kvm_s390x.h ++++ b/target/s390x/kvm_s390x.h +@@ -34,7 +34,9 @@ int kvm_s390_assign_subch_ioeventfd(EventNotifier *notifier, uint32_t sch, + int vq, bool assign); + int kvm_s390_cmma_active(void); + void kvm_s390_cmma_reset(void); +-void kvm_s390_reset_vcpu(S390CPU *cpu); ++void kvm_s390_reset_vcpu_clear(S390CPU *cpu); ++void kvm_s390_reset_vcpu_normal(S390CPU *cpu); ++void kvm_s390_reset_vcpu_initial(S390CPU *cpu); + int kvm_s390_set_mem_limit(uint64_t new_limit, uint64_t *hw_limit); + void kvm_s390_set_max_pagesize(uint64_t pagesize, Error **errp); + void kvm_s390_crypto_reset(void); +-- +2.27.0 + diff --git a/SOURCES/kvm-s390x-Add-unpack-facility-feature-to-GA1.patch b/SOURCES/kvm-s390x-Add-unpack-facility-feature-to-GA1.patch new file mode 100644 index 0000000..8ffb7b0 --- /dev/null +++ b/SOURCES/kvm-s390x-Add-unpack-facility-feature-to-GA1.patch @@ -0,0 +1,76 @@ +From ab670456375f0d9b9b2d219fd497d04ec0009e1d Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 29 May 2020 05:54:16 -0400 +Subject: [PATCH 34/42] s390x: Add unpack facility feature to GA1 + +RH-Author: Thomas Huth +Message-id: <20200529055420.16855-35-thuth@redhat.com> +Patchwork-id: 97052 +O-Subject: [RHEL-8.3.0 qemu-kvm PATCH v2 34/38] s390x: Add unpack facility feature to GA1 +Bugzilla: 1828317 +RH-Acked-by: Claudio Imbrenda +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand + +From: Christian Borntraeger + +The unpack facility is an indication that diagnose 308 subcodes 8-10 +are available to the guest. That means, that the guest can put itself +into protected mode. + +Once it is in protected mode, the hardware stops any attempt of VM +introspection by the hypervisor. + +Some features are currently not supported in protected mode: + * vfio devices + * Migration + * Huge page backings + +Signed-off-by: Christian Borntraeger +Signed-off-by: Janosch Frank +Reviewed-by: David Hildenbrand +Reviewed-by: Claudio Imbrenda +Reviewed-by: Cornelia Huck +Message-Id: <20200319131921.2367-17-frankja@linux.ibm.com> +Signed-off-by: Cornelia Huck +(cherry picked from commit 572c0826615737f1c095b1b6d9e381ec40f72eb5) +Signed-off-by: Danilo C. L. de Paula +--- + target/s390x/gen-features.c | 1 + + target/s390x/kvm.c | 8 ++++++++ + 2 files changed, 9 insertions(+) + +diff --git a/target/s390x/gen-features.c b/target/s390x/gen-features.c +index 6278845b12..8ddeebc544 100644 +--- a/target/s390x/gen-features.c ++++ b/target/s390x/gen-features.c +@@ -562,6 +562,7 @@ static uint16_t full_GEN15_GA1[] = { + S390_FEAT_GROUP_MSA_EXT_9, + S390_FEAT_GROUP_MSA_EXT_9_PCKMO, + S390_FEAT_ETOKEN, ++ S390_FEAT_UNPACK, + }; + + /* Default features (in order of release) +diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c +index 56fe60c49c..84d7cadd09 100644 +--- a/target/s390x/kvm.c ++++ b/target/s390x/kvm.c +@@ -2407,6 +2407,14 @@ void kvm_s390_get_host_cpu_model(S390CPUModel *model, Error **errp) + clear_bit(S390_FEAT_BPB, model->features); + } + ++ /* ++ * If we have support for protected virtualization, indicate ++ * the protected virtualization IPL unpack facility. ++ */ ++ if (cap_protected) { ++ set_bit(S390_FEAT_UNPACK, model->features); ++ } ++ + /* We emulate a zPCI bus and AEN, therefore we don't need HW support */ + set_bit(S390_FEAT_ZPCI, model->features); + set_bit(S390_FEAT_ADAPTER_EVENT_NOTIFICATION, model->features); +-- +2.27.0 + diff --git a/SOURCES/kvm-s390x-Beautify-diag308-handling.patch b/SOURCES/kvm-s390x-Beautify-diag308-handling.patch new file mode 100644 index 0000000..2ffe6a3 --- /dev/null +++ b/SOURCES/kvm-s390x-Beautify-diag308-handling.patch @@ -0,0 +1,130 @@ +From da81f2b579987ea12929f0ec803716bc16a93df7 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 29 May 2020 05:53:49 -0400 +Subject: [PATCH 07/42] s390x: Beautify diag308 handling +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Thomas Huth +Message-id: <20200529055420.16855-8-thuth@redhat.com> +Patchwork-id: 97022 +O-Subject: [RHEL-8.3.0 qemu-kvm PATCH v2 07/38] s390x: Beautify diag308 handling +Bugzilla: 1828317 +RH-Acked-by: Claudio Imbrenda +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand + +From: Janosch Frank + +Let's improve readability by: +* Using constants for the subcodes +* Moving parameter checking into a function +* Removing subcode > 6 check as the default case catches that + +Signed-off-by: Janosch Frank +Reviewed-by: Cornelia Huck +Reviewed-by: Thomas Huth +Reviewed-by: David Hildenbrand +Message-Id: <20191127175046.4911-6-frankja@linux.ibm.com> +Signed-off-by: Cornelia Huck +(cherry picked from commit 0b7fd817e0f383760e37ca9286150d5816cf0594) +Signed-off-by: Danilo C. L. de Paula +--- + target/s390x/diag.c | 54 +++++++++++++++++++++++++++------------------ + 1 file changed, 32 insertions(+), 22 deletions(-) + +diff --git a/target/s390x/diag.c b/target/s390x/diag.c +index 53c2f81f2a..b5aec06d6b 100644 +--- a/target/s390x/diag.c ++++ b/target/s390x/diag.c +@@ -53,6 +53,29 @@ int handle_diag_288(CPUS390XState *env, uint64_t r1, uint64_t r3) + #define DIAG_308_RC_NO_CONF 0x0102 + #define DIAG_308_RC_INVALID 0x0402 + ++#define DIAG308_RESET_MOD_CLR 0 ++#define DIAG308_RESET_LOAD_NORM 1 ++#define DIAG308_LOAD_CLEAR 3 ++#define DIAG308_LOAD_NORMAL_DUMP 4 ++#define DIAG308_SET 5 ++#define DIAG308_STORE 6 ++ ++static int diag308_parm_check(CPUS390XState *env, uint64_t r1, uint64_t addr, ++ uintptr_t ra, bool write) ++{ ++ if ((r1 & 1) || (addr & ~TARGET_PAGE_MASK)) { ++ s390_program_interrupt(env, PGM_SPECIFICATION, ra); ++ return -1; ++ } ++ if (!address_space_access_valid(&address_space_memory, addr, ++ sizeof(IplParameterBlock), write, ++ MEMTXATTRS_UNSPECIFIED)) { ++ s390_program_interrupt(env, PGM_ADDRESSING, ra); ++ return -1; ++ } ++ return 0; ++} ++ + void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3, uintptr_t ra) + { + CPUState *cs = env_cpu(env); +@@ -65,30 +88,24 @@ void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3, uintptr_t ra) + return; + } + +- if ((subcode & ~0x0ffffULL) || (subcode > 6)) { ++ if (subcode & ~0x0ffffULL) { + s390_program_interrupt(env, PGM_SPECIFICATION, ra); + return; + } + + switch (subcode) { +- case 0: ++ case DIAG308_RESET_MOD_CLR: + s390_ipl_reset_request(cs, S390_RESET_MODIFIED_CLEAR); + break; +- case 1: ++ case DIAG308_RESET_LOAD_NORM: + s390_ipl_reset_request(cs, S390_RESET_LOAD_NORMAL); + break; +- case 3: ++ case DIAG308_LOAD_CLEAR: ++ /* Well we still lack the clearing bit... */ + s390_ipl_reset_request(cs, S390_RESET_REIPL); + break; +- case 5: +- if ((r1 & 1) || (addr & 0x0fffULL)) { +- s390_program_interrupt(env, PGM_SPECIFICATION, ra); +- return; +- } +- if (!address_space_access_valid(&address_space_memory, addr, +- sizeof(IplParameterBlock), false, +- MEMTXATTRS_UNSPECIFIED)) { +- s390_program_interrupt(env, PGM_ADDRESSING, ra); ++ case DIAG308_SET: ++ if (diag308_parm_check(env, r1, addr, ra, false)) { + return; + } + iplb = g_new0(IplParameterBlock, 1); +@@ -110,15 +127,8 @@ void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3, uintptr_t ra) + out: + g_free(iplb); + return; +- case 6: +- if ((r1 & 1) || (addr & 0x0fffULL)) { +- s390_program_interrupt(env, PGM_SPECIFICATION, ra); +- return; +- } +- if (!address_space_access_valid(&address_space_memory, addr, +- sizeof(IplParameterBlock), true, +- MEMTXATTRS_UNSPECIFIED)) { +- s390_program_interrupt(env, PGM_ADDRESSING, ra); ++ case DIAG308_STORE: ++ if (diag308_parm_check(env, r1, addr, ra, true)) { + return; + } + iplb = s390_ipl_get_iplb(); +-- +2.27.0 + diff --git a/SOURCES/kvm-s390x-Don-t-do-a-normal-reset-on-the-initial-cpu.patch b/SOURCES/kvm-s390x-Don-t-do-a-normal-reset-on-the-initial-cpu.patch new file mode 100644 index 0000000..dab8acc --- /dev/null +++ b/SOURCES/kvm-s390x-Don-t-do-a-normal-reset-on-the-initial-cpu.patch @@ -0,0 +1,52 @@ +From 511638161566d4944a572a31d787eb27bbc0bc8e Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 29 May 2020 05:53:45 -0400 +Subject: [PATCH 03/42] s390x: Don't do a normal reset on the initial cpu +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Thomas Huth +Message-id: <20200529055420.16855-4-thuth@redhat.com> +Patchwork-id: 97017 +O-Subject: [RHEL-8.3.0 qemu-kvm PATCH v2 03/38] s390x: Don't do a normal reset on the initial cpu +Bugzilla: 1828317 +RH-Acked-by: Claudio Imbrenda +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand + +From: Janosch Frank + +The initiating cpu needs to be reset with an initial reset. While +doing a normal reset followed by a initial reset is not wrong per se, +the Ultravisor will only allow the correct reset to be performed. + +Signed-off-by: Janosch Frank +Reviewed-by: David Hildenbrand +Reviewed-by: Cornelia Huck +Message-Id: <20191127175046.4911-2-frankja@linux.ibm.com> +Signed-off-by: Cornelia Huck +(cherry picked from commit ec9227339fce99412830d44a37eb0bd2fadd5f75) +Signed-off-by: Danilo C. L. de Paula +--- + hw/s390x/s390-virtio-ccw.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c +index c2c83d2fce..4ea01c53c0 100644 +--- a/hw/s390x/s390-virtio-ccw.c ++++ b/hw/s390x/s390-virtio-ccw.c +@@ -348,6 +348,9 @@ static void s390_machine_reset(MachineState *machine) + break; + case S390_RESET_LOAD_NORMAL: + CPU_FOREACH(t) { ++ if (t == cs) { ++ continue; ++ } + run_on_cpu(t, s390_do_cpu_reset, RUN_ON_CPU_NULL); + } + subsystem_reset(); +-- +2.27.0 + diff --git a/SOURCES/kvm-s390x-Fix-cpu-normal-reset-ri-clearing.patch b/SOURCES/kvm-s390x-Fix-cpu-normal-reset-ri-clearing.patch new file mode 100644 index 0000000..9b81586 --- /dev/null +++ b/SOURCES/kvm-s390x-Fix-cpu-normal-reset-ri-clearing.patch @@ -0,0 +1,101 @@ +From bdad28b11e36f657cb8909e7223a7d8fc0948c2e Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 29 May 2020 05:53:51 -0400 +Subject: [PATCH 09/42] s390x: Fix cpu normal reset ri clearing +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Thomas Huth +Message-id: <20200529055420.16855-10-thuth@redhat.com> +Patchwork-id: 97029 +O-Subject: [RHEL-8.3.0 qemu-kvm PATCH v2 09/38] s390x: Fix cpu normal reset ri clearing +Bugzilla: 1828317 +RH-Acked-by: Claudio Imbrenda +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand + +From: Janosch Frank + +As it turns out we need to clear the ri controls and PSW enablement +bit to be architecture compliant. + +Signed-off-by: Janosch Frank +Reviewed-by: Christian Borntraeger +Message-Id: <20191203132813.2734-4-frankja@linux.ibm.com> +Signed-off-by: Cornelia Huck +(cherry picked from commit e893baee70149896d1e43e341da4d6c614037d5d) +Signed-off-by: Danilo C. L. de Paula +--- + target/s390x/cpu.c | 7 ++++++- + target/s390x/cpu.h | 7 ++++++- + 2 files changed, 12 insertions(+), 2 deletions(-) + +diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c +index bd39cb54b7..99ea09085a 100644 +--- a/target/s390x/cpu.c ++++ b/target/s390x/cpu.c +@@ -100,7 +100,7 @@ static void s390_cpu_reset(CPUState *s, cpu_reset_type type) + case S390_CPU_RESET_INITIAL: + /* initial reset does not clear everything! */ + memset(&env->start_initial_reset_fields, 0, +- offsetof(CPUS390XState, end_reset_fields) - ++ offsetof(CPUS390XState, start_normal_reset_fields) - + offsetof(CPUS390XState, start_initial_reset_fields)); + + /* architectured initial value for Breaking-Event-Address register */ +@@ -123,6 +123,11 @@ static void s390_cpu_reset(CPUState *s, cpu_reset_type type) + &env->fpu_status); + /* fall through */ + case S390_CPU_RESET_NORMAL: ++ env->psw.mask &= ~PSW_MASK_RI; ++ memset(&env->start_normal_reset_fields, 0, ++ offsetof(CPUS390XState, end_reset_fields) - ++ offsetof(CPUS390XState, start_normal_reset_fields)); ++ + env->pfault_token = -1UL; + env->bpbc = false; + break; +diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h +index d2af13b345..7e1c18d596 100644 +--- a/target/s390x/cpu.h ++++ b/target/s390x/cpu.h +@@ -58,7 +58,6 @@ struct CPUS390XState { + */ + uint64_t vregs[32][2] QEMU_ALIGNED(16); /* vector registers */ + uint32_t aregs[16]; /* access registers */ +- uint8_t riccb[64]; /* runtime instrumentation control */ + uint64_t gscb[4]; /* guarded storage control */ + uint64_t etoken; /* etoken */ + uint64_t etoken_extension; /* etoken extension */ +@@ -114,6 +113,10 @@ struct CPUS390XState { + uint64_t gbea; + uint64_t pp; + ++ /* Fields up to this point are not cleared by normal CPU reset */ ++ struct {} start_normal_reset_fields; ++ uint8_t riccb[64]; /* runtime instrumentation control */ ++ + /* Fields up to this point are cleared by a CPU reset */ + struct {} end_reset_fields; + +@@ -252,6 +255,7 @@ extern const VMStateDescription vmstate_s390_cpu; + #undef PSW_SHIFT_ASC + #undef PSW_MASK_CC + #undef PSW_MASK_PM ++#undef PSW_MASK_RI + #undef PSW_SHIFT_MASK_PM + #undef PSW_MASK_64 + #undef PSW_MASK_32 +@@ -273,6 +277,7 @@ extern const VMStateDescription vmstate_s390_cpu; + #define PSW_MASK_CC 0x0000300000000000ULL + #define PSW_MASK_PM 0x00000F0000000000ULL + #define PSW_SHIFT_MASK_PM 40 ++#define PSW_MASK_RI 0x0000008000000000ULL + #define PSW_MASK_64 0x0000000100000000ULL + #define PSW_MASK_32 0x0000000080000000ULL + #define PSW_MASK_ESA_ADDR 0x000000007fffffffULL +-- +2.27.0 + diff --git a/SOURCES/kvm-s390x-Move-clear-reset.patch b/SOURCES/kvm-s390x-Move-clear-reset.patch new file mode 100644 index 0000000..7c1614c --- /dev/null +++ b/SOURCES/kvm-s390x-Move-clear-reset.patch @@ -0,0 +1,146 @@ +From f268cc7071ecb4322c03f3183acbcf90421da3c7 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 29 May 2020 05:53:48 -0400 +Subject: [PATCH 06/42] s390x: Move clear reset +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Thomas Huth +Message-id: <20200529055420.16855-7-thuth@redhat.com> +Patchwork-id: 97019 +O-Subject: [RHEL-8.3.0 qemu-kvm PATCH v2 06/38] s390x: Move clear reset +Bugzilla: 1828317 +RH-Acked-by: Claudio Imbrenda +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand + +From: Janosch Frank + +Let's also move the clear reset function into the reset handler. + +Signed-off-by: Janosch Frank +Message-Id: <20191127175046.4911-5-frankja@linux.ibm.com> +Reviewed-by: David Hildenbrand +Reviewed-by: Thomas Huth +Signed-off-by: Cornelia Huck +(cherry picked from commit eb8adcc3e9e3b8405c104ede72cf9f3bb2a5e226) +Signed-off-by: Danilo C. L. de Paula +--- + target/s390x/cpu-qom.h | 1 + + target/s390x/cpu.c | 58 +++++++++++++----------------------------- + 2 files changed, 18 insertions(+), 41 deletions(-) + +diff --git a/target/s390x/cpu-qom.h b/target/s390x/cpu-qom.h +index 6f0a12042e..dbe5346ec9 100644 +--- a/target/s390x/cpu-qom.h ++++ b/target/s390x/cpu-qom.h +@@ -37,6 +37,7 @@ typedef struct S390CPUDef S390CPUDef; + typedef enum cpu_reset_type { + S390_CPU_RESET_NORMAL, + S390_CPU_RESET_INITIAL, ++ S390_CPU_RESET_CLEAR, + } cpu_reset_type; + + /** +diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c +index ca62fe7685..bd39cb54b7 100644 +--- a/target/s390x/cpu.c ++++ b/target/s390x/cpu.c +@@ -94,6 +94,9 @@ static void s390_cpu_reset(CPUState *s, cpu_reset_type type) + s390_cpu_set_state(S390_CPU_STATE_STOPPED, cpu); + + switch (type) { ++ case S390_CPU_RESET_CLEAR: ++ memset(env, 0, offsetof(CPUS390XState, start_initial_reset_fields)); ++ /* fall through */ + case S390_CPU_RESET_INITIAL: + /* initial reset does not clear everything! */ + memset(&env->start_initial_reset_fields, 0, +@@ -107,6 +110,14 @@ static void s390_cpu_reset(CPUState *s, cpu_reset_type type) + env->cregs[0] = CR0_RESET; + env->cregs[14] = CR14_RESET; + ++#if defined(CONFIG_USER_ONLY) ++ /* user mode should always be allowed to use the full FPU */ ++ env->cregs[0] |= CR0_AFP; ++ if (s390_has_feat(S390_FEAT_VECTOR)) { ++ env->cregs[0] |= CR0_VECTOR; ++ } ++#endif ++ + /* tininess for underflow is detected before rounding */ + set_float_detect_tininess(float_tininess_before_rounding, + &env->fpu_status); +@@ -125,46 +136,6 @@ static void s390_cpu_reset(CPUState *s, cpu_reset_type type) + } + } + +-/* CPUClass:reset() */ +-static void s390_cpu_full_reset(CPUState *s) +-{ +- S390CPU *cpu = S390_CPU(s); +- S390CPUClass *scc = S390_CPU_GET_CLASS(cpu); +- CPUS390XState *env = &cpu->env; +- +- scc->parent_reset(s); +- cpu->env.sigp_order = 0; +- s390_cpu_set_state(S390_CPU_STATE_STOPPED, cpu); +- +- memset(env, 0, offsetof(CPUS390XState, end_reset_fields)); +- +- /* architectured initial values for CR 0 and 14 */ +- env->cregs[0] = CR0_RESET; +- env->cregs[14] = CR14_RESET; +- +-#if defined(CONFIG_USER_ONLY) +- /* user mode should always be allowed to use the full FPU */ +- env->cregs[0] |= CR0_AFP; +- if (s390_has_feat(S390_FEAT_VECTOR)) { +- env->cregs[0] |= CR0_VECTOR; +- } +-#endif +- +- /* architectured initial value for Breaking-Event-Address register */ +- env->gbea = 1; +- +- env->pfault_token = -1UL; +- +- /* tininess for underflow is detected before rounding */ +- set_float_detect_tininess(float_tininess_before_rounding, +- &env->fpu_status); +- +- /* Reset state inside the kernel that we cannot access yet from QEMU. */ +- if (kvm_enabled()) { +- kvm_s390_reset_vcpu(cpu); +- } +-} +- + #if !defined(CONFIG_USER_ONLY) + static void s390_cpu_machine_reset_cb(void *opaque) + { +@@ -456,6 +427,11 @@ static Property s390x_cpu_properties[] = { + DEFINE_PROP_END_OF_LIST() + }; + ++static void s390_cpu_reset_full(CPUState *s) ++{ ++ return s390_cpu_reset(s, S390_CPU_RESET_CLEAR); ++} ++ + static void s390_cpu_class_init(ObjectClass *oc, void *data) + { + S390CPUClass *scc = S390_CPU_CLASS(oc); +@@ -472,7 +448,7 @@ static void s390_cpu_class_init(ObjectClass *oc, void *data) + scc->load_normal = s390_cpu_load_normal; + #endif + scc->reset = s390_cpu_reset; +- cc->reset = s390_cpu_full_reset; ++ cc->reset = s390_cpu_reset_full; + cc->class_by_name = s390_cpu_class_by_name, + cc->has_work = s390_cpu_has_work; + #ifdef CONFIG_TCG +-- +2.27.0 + diff --git a/SOURCES/kvm-s390x-Move-diagnose-308-subcodes-and-rcs-into-ipl.h.patch b/SOURCES/kvm-s390x-Move-diagnose-308-subcodes-and-rcs-into-ipl.h.patch new file mode 100644 index 0000000..ac183cf --- /dev/null +++ b/SOURCES/kvm-s390x-Move-diagnose-308-subcodes-and-rcs-into-ipl.h.patch @@ -0,0 +1,83 @@ +From c9eee8aeed39976293e0d857039fcf729b821e83 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 29 May 2020 05:54:03 -0400 +Subject: [PATCH 21/42] s390x: Move diagnose 308 subcodes and rcs into ipl.h +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Thomas Huth +Message-id: <20200529055420.16855-22-thuth@redhat.com> +Patchwork-id: 97032 +O-Subject: [RHEL-8.3.0 qemu-kvm PATCH v2 21/38] s390x: Move diagnose 308 subcodes and rcs into ipl.h +Bugzilla: 1828317 +RH-Acked-by: Claudio Imbrenda +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand + +From: Janosch Frank + +They are part of the IPL process, so let's put them into the ipl +header. + +Signed-off-by: Janosch Frank +Reviewed-by: Cornelia Huck +Reviewed-by: Christian Borntraeger +Reviewed-by: David Hildenbrand +Message-Id: <20200319131921.2367-2-frankja@linux.ibm.com> +Signed-off-by: Cornelia Huck +(cherry picked from commit 9b39d29470e9dbef24ee842a44ea56bd92b855ea) +Signed-off-by: Danilo C. L. de Paula +--- + hw/s390x/ipl.h | 11 +++++++++++ + target/s390x/diag.c | 11 ----------- + 2 files changed, 11 insertions(+), 11 deletions(-) + +diff --git a/hw/s390x/ipl.h b/hw/s390x/ipl.h +index 3e44abe1c6..a5665e6bfd 100644 +--- a/hw/s390x/ipl.h ++++ b/hw/s390x/ipl.h +@@ -159,6 +159,17 @@ struct S390IPLState { + typedef struct S390IPLState S390IPLState; + QEMU_BUILD_BUG_MSG(offsetof(S390IPLState, iplb) & 3, "alignment of iplb wrong"); + ++#define DIAG_308_RC_OK 0x0001 ++#define DIAG_308_RC_NO_CONF 0x0102 ++#define DIAG_308_RC_INVALID 0x0402 ++ ++#define DIAG308_RESET_MOD_CLR 0 ++#define DIAG308_RESET_LOAD_NORM 1 ++#define DIAG308_LOAD_CLEAR 3 ++#define DIAG308_LOAD_NORMAL_DUMP 4 ++#define DIAG308_SET 5 ++#define DIAG308_STORE 6 ++ + #define S390_IPL_TYPE_FCP 0x00 + #define S390_IPL_TYPE_CCW 0x02 + #define S390_IPL_TYPE_QEMU_SCSI 0xff +diff --git a/target/s390x/diag.c b/target/s390x/diag.c +index 54e5670b3f..8aba6341f9 100644 +--- a/target/s390x/diag.c ++++ b/target/s390x/diag.c +@@ -49,17 +49,6 @@ int handle_diag_288(CPUS390XState *env, uint64_t r1, uint64_t r3) + return diag288_class->handle_timer(diag288, func, timeout); + } + +-#define DIAG_308_RC_OK 0x0001 +-#define DIAG_308_RC_NO_CONF 0x0102 +-#define DIAG_308_RC_INVALID 0x0402 +- +-#define DIAG308_RESET_MOD_CLR 0 +-#define DIAG308_RESET_LOAD_NORM 1 +-#define DIAG308_LOAD_CLEAR 3 +-#define DIAG308_LOAD_NORMAL_DUMP 4 +-#define DIAG308_SET 5 +-#define DIAG308_STORE 6 +- + static int diag308_parm_check(CPUS390XState *env, uint64_t r1, uint64_t addr, + uintptr_t ra, bool write) + { +-- +2.27.0 + diff --git a/SOURCES/kvm-s390x-Move-initial-reset.patch b/SOURCES/kvm-s390x-Move-initial-reset.patch new file mode 100644 index 0000000..0f2e9ab --- /dev/null +++ b/SOURCES/kvm-s390x-Move-initial-reset.patch @@ -0,0 +1,159 @@ +From 0d1c0adf25a323be0663863ebe44a6aefb5f7baf Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 29 May 2020 05:53:47 -0400 +Subject: [PATCH 05/42] s390x: Move initial reset +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Thomas Huth +Message-id: <20200529055420.16855-6-thuth@redhat.com> +Patchwork-id: 97024 +O-Subject: [RHEL-8.3.0 qemu-kvm PATCH v2 05/38] s390x: Move initial reset +Bugzilla: 1828317 +RH-Acked-by: Claudio Imbrenda +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand + +From: Janosch Frank + +Let's move the intial reset into the reset handler and cleanup +afterwards. + +Signed-off-by: Janosch Frank +Reviewed-by: David Hildenbrand +Message-Id: <20191128083723.11937-1-frankja@linux.ibm.com> +Reviewed-by: Thomas Huth +Signed-off-by: Cornelia Huck +(cherry picked from commit 81b9222358e5c8f666f0d86057c75e40531d804c) +Signed-off-by: Danilo C. L. de Paula +--- + target/s390x/cpu-qom.h | 2 +- + target/s390x/cpu.c | 46 +++++++++++++++++------------------------- + target/s390x/cpu.h | 2 +- + target/s390x/sigp.c | 2 +- + 4 files changed, 21 insertions(+), 31 deletions(-) + +diff --git a/target/s390x/cpu-qom.h b/target/s390x/cpu-qom.h +index f3b71bac67..6f0a12042e 100644 +--- a/target/s390x/cpu-qom.h ++++ b/target/s390x/cpu-qom.h +@@ -36,6 +36,7 @@ typedef struct S390CPUDef S390CPUDef; + + typedef enum cpu_reset_type { + S390_CPU_RESET_NORMAL, ++ S390_CPU_RESET_INITIAL, + } cpu_reset_type; + + /** +@@ -62,7 +63,6 @@ typedef struct S390CPUClass { + void (*parent_reset)(CPUState *cpu); + void (*load_normal)(CPUState *cpu); + void (*reset)(CPUState *cpu, cpu_reset_type type); +- void (*initial_cpu_reset)(CPUState *cpu); + } S390CPUClass; + + typedef struct S390CPU S390CPU; +diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c +index 67d6fbfa44..ca62fe7685 100644 +--- a/target/s390x/cpu.c ++++ b/target/s390x/cpu.c +@@ -94,6 +94,23 @@ static void s390_cpu_reset(CPUState *s, cpu_reset_type type) + s390_cpu_set_state(S390_CPU_STATE_STOPPED, cpu); + + switch (type) { ++ case S390_CPU_RESET_INITIAL: ++ /* initial reset does not clear everything! */ ++ memset(&env->start_initial_reset_fields, 0, ++ offsetof(CPUS390XState, end_reset_fields) - ++ offsetof(CPUS390XState, start_initial_reset_fields)); ++ ++ /* architectured initial value for Breaking-Event-Address register */ ++ env->gbea = 1; ++ ++ /* architectured initial values for CR 0 and 14 */ ++ env->cregs[0] = CR0_RESET; ++ env->cregs[14] = CR14_RESET; ++ ++ /* tininess for underflow is detected before rounding */ ++ set_float_detect_tininess(float_tininess_before_rounding, ++ &env->fpu_status); ++ /* fall through */ + case S390_CPU_RESET_NORMAL: + env->pfault_token = -1UL; + env->bpbc = false; +@@ -101,35 +118,9 @@ static void s390_cpu_reset(CPUState *s, cpu_reset_type type) + default: + g_assert_not_reached(); + } +-} +- +-/* S390CPUClass::initial_reset() */ +-static void s390_cpu_initial_reset(CPUState *s) +-{ +- S390CPU *cpu = S390_CPU(s); +- CPUS390XState *env = &cpu->env; +- +- s390_cpu_reset(s, S390_CPU_RESET_NORMAL); +- /* initial reset does not clear everything! */ +- memset(&env->start_initial_reset_fields, 0, +- offsetof(CPUS390XState, end_reset_fields) - +- offsetof(CPUS390XState, start_initial_reset_fields)); +- +- /* architectured initial values for CR 0 and 14 */ +- env->cregs[0] = CR0_RESET; +- env->cregs[14] = CR14_RESET; +- +- /* architectured initial value for Breaking-Event-Address register */ +- env->gbea = 1; +- +- env->pfault_token = -1UL; +- +- /* tininess for underflow is detected before rounding */ +- set_float_detect_tininess(float_tininess_before_rounding, +- &env->fpu_status); + + /* Reset state inside the kernel that we cannot access yet from QEMU. */ +- if (kvm_enabled()) { ++ if (kvm_enabled() && type != S390_CPU_RESET_NORMAL) { + kvm_s390_reset_vcpu(cpu); + } + } +@@ -481,7 +472,6 @@ static void s390_cpu_class_init(ObjectClass *oc, void *data) + scc->load_normal = s390_cpu_load_normal; + #endif + scc->reset = s390_cpu_reset; +- scc->initial_cpu_reset = s390_cpu_initial_reset; + cc->reset = s390_cpu_full_reset; + cc->class_by_name = s390_cpu_class_by_name, + cc->has_work = s390_cpu_has_work; +diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h +index 18123dfd5b..d2af13b345 100644 +--- a/target/s390x/cpu.h ++++ b/target/s390x/cpu.h +@@ -748,7 +748,7 @@ static inline void s390_do_cpu_initial_reset(CPUState *cs, run_on_cpu_data arg) + { + S390CPUClass *scc = S390_CPU_GET_CLASS(cs); + +- scc->initial_cpu_reset(cs); ++ scc->reset(cs, S390_CPU_RESET_INITIAL); + } + + static inline void s390_do_cpu_load_normal(CPUState *cs, run_on_cpu_data arg) +diff --git a/target/s390x/sigp.c b/target/s390x/sigp.c +index 850139b9cd..727875bb4a 100644 +--- a/target/s390x/sigp.c ++++ b/target/s390x/sigp.c +@@ -254,7 +254,7 @@ static void sigp_initial_cpu_reset(CPUState *cs, run_on_cpu_data arg) + SigpInfo *si = arg.host_ptr; + + cpu_synchronize_state(cs); +- scc->initial_cpu_reset(cs); ++ scc->reset(cs, S390_CPU_RESET_INITIAL); + cpu_synchronize_post_reset(cs); + si->cc = SIGP_CC_ORDER_CODE_ACCEPTED; + } +-- +2.27.0 + diff --git a/SOURCES/kvm-s390x-Move-reset-normal-to-shared-reset-handler.patch b/SOURCES/kvm-s390x-Move-reset-normal-to-shared-reset-handler.patch new file mode 100644 index 0000000..81a4368 --- /dev/null +++ b/SOURCES/kvm-s390x-Move-reset-normal-to-shared-reset-handler.patch @@ -0,0 +1,145 @@ +From 53b5a7f83f3e6b94c66cbbb97ea42bbf02cb96b4 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 29 May 2020 05:53:46 -0400 +Subject: [PATCH 04/42] s390x: Move reset normal to shared reset handler +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Thomas Huth +Message-id: <20200529055420.16855-5-thuth@redhat.com> +Patchwork-id: 97018 +O-Subject: [RHEL-8.3.0 qemu-kvm PATCH v2 04/38] s390x: Move reset normal to shared reset handler +Bugzilla: 1828317 +RH-Acked-by: Claudio Imbrenda +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand + +From: Janosch Frank + +Let's start moving the cpu reset functions into a single function with +a switch/case, so we can later use fallthroughs and share more code +between resets. + +This patch introduces the reset function by renaming cpu_reset(). + +Signed-off-by: Janosch Frank +Reviewed-by: David Hildenbrand +Message-Id: <20191127175046.4911-3-frankja@linux.ibm.com> +Reviewed-by: Thomas Huth +Signed-off-by: Cornelia Huck +(cherry picked from commit eac4f82791f1807c423e85670837db103b9d59b3) +Signed-off-by: Danilo C. L. de Paula +--- + target/s390x/cpu-qom.h | 6 +++++- + target/s390x/cpu.c | 19 +++++++++++++------ + target/s390x/cpu.h | 2 +- + target/s390x/sigp.c | 2 +- + 4 files changed, 20 insertions(+), 9 deletions(-) + +diff --git a/target/s390x/cpu-qom.h b/target/s390x/cpu-qom.h +index b809ec8418..f3b71bac67 100644 +--- a/target/s390x/cpu-qom.h ++++ b/target/s390x/cpu-qom.h +@@ -34,6 +34,10 @@ + typedef struct S390CPUModel S390CPUModel; + typedef struct S390CPUDef S390CPUDef; + ++typedef enum cpu_reset_type { ++ S390_CPU_RESET_NORMAL, ++} cpu_reset_type; ++ + /** + * S390CPUClass: + * @parent_realize: The parent class' realize handler. +@@ -57,7 +61,7 @@ typedef struct S390CPUClass { + DeviceRealize parent_realize; + void (*parent_reset)(CPUState *cpu); + void (*load_normal)(CPUState *cpu); +- void (*cpu_reset)(CPUState *cpu); ++ void (*reset)(CPUState *cpu, cpu_reset_type type); + void (*initial_cpu_reset)(CPUState *cpu); + } S390CPUClass; + +diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c +index 3abe7e80fd..67d6fbfa44 100644 +--- a/target/s390x/cpu.c ++++ b/target/s390x/cpu.c +@@ -82,18 +82,25 @@ static void s390_cpu_load_normal(CPUState *s) + } + #endif + +-/* S390CPUClass::cpu_reset() */ +-static void s390_cpu_reset(CPUState *s) ++/* S390CPUClass::reset() */ ++static void s390_cpu_reset(CPUState *s, cpu_reset_type type) + { + S390CPU *cpu = S390_CPU(s); + S390CPUClass *scc = S390_CPU_GET_CLASS(cpu); + CPUS390XState *env = &cpu->env; + +- env->pfault_token = -1UL; +- env->bpbc = false; + scc->parent_reset(s); + cpu->env.sigp_order = 0; + s390_cpu_set_state(S390_CPU_STATE_STOPPED, cpu); ++ ++ switch (type) { ++ case S390_CPU_RESET_NORMAL: ++ env->pfault_token = -1UL; ++ env->bpbc = false; ++ break; ++ default: ++ g_assert_not_reached(); ++ } + } + + /* S390CPUClass::initial_reset() */ +@@ -102,7 +109,7 @@ static void s390_cpu_initial_reset(CPUState *s) + S390CPU *cpu = S390_CPU(s); + CPUS390XState *env = &cpu->env; + +- s390_cpu_reset(s); ++ s390_cpu_reset(s, S390_CPU_RESET_NORMAL); + /* initial reset does not clear everything! */ + memset(&env->start_initial_reset_fields, 0, + offsetof(CPUS390XState, end_reset_fields) - +@@ -473,7 +480,7 @@ static void s390_cpu_class_init(ObjectClass *oc, void *data) + #if !defined(CONFIG_USER_ONLY) + scc->load_normal = s390_cpu_load_normal; + #endif +- scc->cpu_reset = s390_cpu_reset; ++ scc->reset = s390_cpu_reset; + scc->initial_cpu_reset = s390_cpu_initial_reset; + cc->reset = s390_cpu_full_reset; + cc->class_by_name = s390_cpu_class_by_name, +diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h +index 17460ed7b3..18123dfd5b 100644 +--- a/target/s390x/cpu.h ++++ b/target/s390x/cpu.h +@@ -741,7 +741,7 @@ static inline void s390_do_cpu_reset(CPUState *cs, run_on_cpu_data arg) + { + S390CPUClass *scc = S390_CPU_GET_CLASS(cs); + +- scc->cpu_reset(cs); ++ scc->reset(cs, S390_CPU_RESET_NORMAL); + } + + static inline void s390_do_cpu_initial_reset(CPUState *cs, run_on_cpu_data arg) +diff --git a/target/s390x/sigp.c b/target/s390x/sigp.c +index 2ce22d4dc1..850139b9cd 100644 +--- a/target/s390x/sigp.c ++++ b/target/s390x/sigp.c +@@ -266,7 +266,7 @@ static void sigp_cpu_reset(CPUState *cs, run_on_cpu_data arg) + SigpInfo *si = arg.host_ptr; + + cpu_synchronize_state(cs); +- scc->cpu_reset(cs); ++ scc->reset(cs, S390_CPU_RESET_NORMAL); + cpu_synchronize_post_reset(cs); + si->cc = SIGP_CC_ORDER_CODE_ACCEPTED; + } +-- +2.27.0 + diff --git a/SOURCES/kvm-s390x-Properly-fetch-and-test-the-short-psw-on-diag3.patch b/SOURCES/kvm-s390x-Properly-fetch-and-test-the-short-psw-on-diag3.patch new file mode 100644 index 0000000..9447240 --- /dev/null +++ b/SOURCES/kvm-s390x-Properly-fetch-and-test-the-short-psw-on-diag3.patch @@ -0,0 +1,70 @@ +From 7171a794e8a7d91805516174187addc3b8e6b423 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 29 May 2020 05:53:54 -0400 +Subject: [PATCH 12/42] s390x: Properly fetch and test the short psw on diag308 + subc 0/1 + +RH-Author: Thomas Huth +Message-id: <20200529055420.16855-13-thuth@redhat.com> +Patchwork-id: 97025 +O-Subject: [RHEL-8.3.0 qemu-kvm PATCH v2 12/38] s390x: Properly fetch and test the short psw on diag308 subc 0/1 +Bugzilla: 1828317 +RH-Acked-by: Claudio Imbrenda +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand + +From: Janosch Frank + +We need to actually fetch the cpu mask and set it. As we invert the +short psw indication in the mask, SIE will report a specification +exception, if it wasn't present in the reset psw. + +Signed-off-by: Janosch Frank +Reviewed-by: David Hildenbrand +Message-Id: <20191129142025.21453-2-frankja@linux.ibm.com> +Signed-off-by: Cornelia Huck +(cherry picked from commit 104130cb7c106378dab944397c6a455c4a6d552f) +Signed-off-by: Danilo C. L. de Paula +--- + target/s390x/cpu.c | 12 ++++++++++-- + target/s390x/cpu.h | 1 + + 2 files changed, 11 insertions(+), 2 deletions(-) + +diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c +index 99ea09085a..625daeedd1 100644 +--- a/target/s390x/cpu.c ++++ b/target/s390x/cpu.c +@@ -76,8 +76,16 @@ static bool s390_cpu_has_work(CPUState *cs) + static void s390_cpu_load_normal(CPUState *s) + { + S390CPU *cpu = S390_CPU(s); +- cpu->env.psw.addr = ldl_phys(s->as, 4) & PSW_MASK_ESA_ADDR; +- cpu->env.psw.mask = PSW_MASK_32 | PSW_MASK_64; ++ uint64_t spsw = ldq_phys(s->as, 0); ++ ++ cpu->env.psw.mask = spsw & 0xffffffff80000000ULL; ++ /* ++ * Invert short psw indication, so SIE will report a specification ++ * exception if it was not set. ++ */ ++ cpu->env.psw.mask ^= PSW_MASK_SHORTPSW; ++ cpu->env.psw.addr = spsw & 0x7fffffffULL; ++ + s390_cpu_set_state(S390_CPU_STATE_OPERATING, cpu); + } + #endif +diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h +index 7e1c18d596..7f5fa1d35b 100644 +--- a/target/s390x/cpu.h ++++ b/target/s390x/cpu.h +@@ -269,6 +269,7 @@ extern const VMStateDescription vmstate_s390_cpu; + #define PSW_MASK_EXT 0x0100000000000000ULL + #define PSW_MASK_KEY 0x00F0000000000000ULL + #define PSW_SHIFT_KEY 52 ++#define PSW_MASK_SHORTPSW 0x0008000000000000ULL + #define PSW_MASK_MCHECK 0x0004000000000000ULL + #define PSW_MASK_WAIT 0x0002000000000000ULL + #define PSW_MASK_PSTATE 0x0001000000000000ULL +-- +2.27.0 + diff --git a/SOURCES/kvm-s390x-Rename-and-use-constants-for-short-PSW-address.patch b/SOURCES/kvm-s390x-Rename-and-use-constants-for-short-PSW-address.patch new file mode 100644 index 0000000..b1c7e01 --- /dev/null +++ b/SOURCES/kvm-s390x-Rename-and-use-constants-for-short-PSW-address.patch @@ -0,0 +1,87 @@ +From 4bd5ae889376816238ecad1bce054b0e198cde2b Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 29 May 2020 05:53:55 -0400 +Subject: [PATCH 13/42] s390x: Rename and use constants for short PSW address + and mask + +RH-Author: Thomas Huth +Message-id: <20200529055420.16855-14-thuth@redhat.com> +Patchwork-id: 97050 +O-Subject: [RHEL-8.3.0 qemu-kvm PATCH v2 13/38] s390x: Rename and use constants for short PSW address and mask +Bugzilla: 1828317 +RH-Acked-by: Claudio Imbrenda +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand + +From: Janosch Frank + +Let's rename PSW_MASK_ESA_ADDR to PSW_MASK_SHORT_ADDR because we're +not working with a ESA PSW which would not support the extended +addressing bit. Also let's actually use it. + +Additionally we introduce PSW_MASK_SHORT_CTRL and use it throughout +the codebase. + +Signed-off-by: Janosch Frank +Reviewed-by: Christian Borntraeger +Reviewed-by: David Hildenbrand +Message-Id: <20200227092341.38558-1-frankja@linux.ibm.com> +Signed-off-by: Cornelia Huck +(cherry picked from commit b6c2dbd7214b0b2396e1dcf9668c8b48ab571115) +Signed-off-by: Danilo C. L. de Paula +--- + hw/s390x/ipl.c | 2 +- + target/s390x/cpu.c | 4 ++-- + target/s390x/cpu.h | 3 ++- + 3 files changed, 5 insertions(+), 4 deletions(-) + +diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c +index ca544d64c5..0b7548a549 100644 +--- a/hw/s390x/ipl.c ++++ b/hw/s390x/ipl.c +@@ -179,7 +179,7 @@ static void s390_ipl_realize(DeviceState *dev, Error **errp) + /* if not Linux load the address of the (short) IPL PSW */ + ipl_psw = rom_ptr(4, 4); + if (ipl_psw) { +- pentry = be32_to_cpu(*ipl_psw) & 0x7fffffffUL; ++ pentry = be32_to_cpu(*ipl_psw) & PSW_MASK_SHORT_ADDR; + } else { + error_setg(&err, "Could not get IPL PSW"); + goto error; +diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c +index 625daeedd1..e538a4a3e2 100644 +--- a/target/s390x/cpu.c ++++ b/target/s390x/cpu.c +@@ -78,13 +78,13 @@ static void s390_cpu_load_normal(CPUState *s) + S390CPU *cpu = S390_CPU(s); + uint64_t spsw = ldq_phys(s->as, 0); + +- cpu->env.psw.mask = spsw & 0xffffffff80000000ULL; ++ cpu->env.psw.mask = spsw & PSW_MASK_SHORT_CTRL; + /* + * Invert short psw indication, so SIE will report a specification + * exception if it was not set. + */ + cpu->env.psw.mask ^= PSW_MASK_SHORTPSW; +- cpu->env.psw.addr = spsw & 0x7fffffffULL; ++ cpu->env.psw.addr = spsw & PSW_MASK_SHORT_ADDR; + + s390_cpu_set_state(S390_CPU_STATE_OPERATING, cpu); + } +diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h +index 7f5fa1d35b..1ff84e6b3a 100644 +--- a/target/s390x/cpu.h ++++ b/target/s390x/cpu.h +@@ -281,7 +281,8 @@ extern const VMStateDescription vmstate_s390_cpu; + #define PSW_MASK_RI 0x0000008000000000ULL + #define PSW_MASK_64 0x0000000100000000ULL + #define PSW_MASK_32 0x0000000080000000ULL +-#define PSW_MASK_ESA_ADDR 0x000000007fffffffULL ++#define PSW_MASK_SHORT_ADDR 0x000000007fffffffULL ++#define PSW_MASK_SHORT_CTRL 0xffffffff80000000ULL + + #undef PSW_ASC_PRIMARY + #undef PSW_ASC_ACCREG +-- +2.27.0 + diff --git a/SOURCES/kvm-s390x-css-Refactor-the-css_queue_crw-routine.patch b/SOURCES/kvm-s390x-css-Refactor-the-css_queue_crw-routine.patch new file mode 100644 index 0000000..8ce7625 --- /dev/null +++ b/SOURCES/kvm-s390x-css-Refactor-the-css_queue_crw-routine.patch @@ -0,0 +1,119 @@ +From 04d4e7eda95316b64ea9dc0f4ca8801d531652e7 Mon Sep 17 00:00:00 2001 +From: Cornelia Huck +Date: Tue, 23 Jun 2020 09:25:41 -0400 +Subject: [PATCH 07/12] s390x/css: Refactor the css_queue_crw() routine + +RH-Author: Cornelia Huck +Message-id: <20200623092543.358315-8-cohuck@redhat.com> +Patchwork-id: 97700 +O-Subject: [RHEL-8.3.0 qemu-kvm PATCH 7/9] s390x/css: Refactor the css_queue_crw() routine +Bugzilla: 1660916 +RH-Acked-by: Claudio Imbrenda +RH-Acked-by: David Hildenbrand +RH-Acked-by: Thomas Huth + +From: Eric Farman + +We have a use case (vfio-ccw) where a CRW is already built and +ready to use. Rather than teasing out the components just to +reassemble it later, let's rework this code so we can queue a +fully-qualified CRW directly. + +Signed-off-by: Eric Farman +Reviewed-by: Cornelia Huck +Message-Id: <20200505125757.98209-6-farman@linux.ibm.com> +Signed-off-by: Cornelia Huck +(cherry picked from commit f6dde1b012e678aa64339520ef7519ec04026cf1) +Signed-off-by: Cornelia Huck +Signed-off-by: Danilo C. L. de Paula +--- + hw/s390x/css.c | 44 ++++++++++++++++++++++++++++-------------- + include/hw/s390x/css.h | 1 + + 2 files changed, 30 insertions(+), 15 deletions(-) + +diff --git a/hw/s390x/css.c b/hw/s390x/css.c +index 71fd3f9a00..a8de8a0c84 100644 +--- a/hw/s390x/css.c ++++ b/hw/s390x/css.c +@@ -2170,30 +2170,23 @@ void css_subch_assign(uint8_t cssid, uint8_t ssid, uint16_t schid, + } + } + +-void css_queue_crw(uint8_t rsc, uint8_t erc, int solicited, +- int chain, uint16_t rsid) ++void css_crw_add_to_queue(CRW crw) + { + CrwContainer *crw_cont; + +- trace_css_crw(rsc, erc, rsid, chain ? "(chained)" : ""); ++ trace_css_crw((crw.flags & CRW_FLAGS_MASK_RSC) >> 8, ++ crw.flags & CRW_FLAGS_MASK_ERC, ++ crw.rsid, ++ (crw.flags & CRW_FLAGS_MASK_C) ? "(chained)" : ""); ++ + /* TODO: Maybe use a static crw pool? */ + crw_cont = g_try_new0(CrwContainer, 1); + if (!crw_cont) { + channel_subsys.crws_lost = true; + return; + } +- crw_cont->crw.flags = (rsc << 8) | erc; +- if (solicited) { +- crw_cont->crw.flags |= CRW_FLAGS_MASK_S; +- } +- if (chain) { +- crw_cont->crw.flags |= CRW_FLAGS_MASK_C; +- } +- crw_cont->crw.rsid = rsid; +- if (channel_subsys.crws_lost) { +- crw_cont->crw.flags |= CRW_FLAGS_MASK_R; +- channel_subsys.crws_lost = false; +- } ++ ++ crw_cont->crw = crw; + + QTAILQ_INSERT_TAIL(&channel_subsys.pending_crws, crw_cont, sibling); + +@@ -2204,6 +2197,27 @@ void css_queue_crw(uint8_t rsc, uint8_t erc, int solicited, + } + } + ++void css_queue_crw(uint8_t rsc, uint8_t erc, int solicited, ++ int chain, uint16_t rsid) ++{ ++ CRW crw; ++ ++ crw.flags = (rsc << 8) | erc; ++ if (solicited) { ++ crw.flags |= CRW_FLAGS_MASK_S; ++ } ++ if (chain) { ++ crw.flags |= CRW_FLAGS_MASK_C; ++ } ++ crw.rsid = rsid; ++ if (channel_subsys.crws_lost) { ++ crw.flags |= CRW_FLAGS_MASK_R; ++ channel_subsys.crws_lost = false; ++ } ++ ++ css_crw_add_to_queue(crw); ++} ++ + void css_generate_sch_crws(uint8_t cssid, uint8_t ssid, uint16_t schid, + int hotplugged, int add) + { +diff --git a/include/hw/s390x/css.h b/include/hw/s390x/css.h +index 7e3a5e7433..08c869ab0a 100644 +--- a/include/hw/s390x/css.h ++++ b/include/hw/s390x/css.h +@@ -205,6 +205,7 @@ void copy_scsw_to_guest(SCSW *dest, const SCSW *src); + void css_inject_io_interrupt(SubchDev *sch); + void css_reset(void); + void css_reset_sch(SubchDev *sch); ++void css_crw_add_to_queue(CRW crw); + void css_queue_crw(uint8_t rsc, uint8_t erc, int solicited, + int chain, uint16_t rsid); + void css_generate_sch_crws(uint8_t cssid, uint8_t ssid, uint16_t schid, +-- +2.27.0 + diff --git a/SOURCES/kvm-s390x-ipl-Consolidate-iplb-validity-check-into-one-f.patch b/SOURCES/kvm-s390x-ipl-Consolidate-iplb-validity-check-into-one-f.patch new file mode 100644 index 0000000..8b9294e --- /dev/null +++ b/SOURCES/kvm-s390x-ipl-Consolidate-iplb-validity-check-into-one-f.patch @@ -0,0 +1,82 @@ +From 536b6081c0739bebbb33583370f62116d0cb42da Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 29 May 2020 05:54:01 -0400 +Subject: [PATCH 19/42] s390x: ipl: Consolidate iplb validity check into one + function +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Thomas Huth +Message-id: <20200529055420.16855-20-thuth@redhat.com> +Patchwork-id: 97038 +O-Subject: [RHEL-8.3.0 qemu-kvm PATCH v2 19/38] s390x: ipl: Consolidate iplb validity check into one function +Bugzilla: 1828317 +RH-Acked-by: Claudio Imbrenda +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand + +From: Janosch Frank + +It's nicer to just call one function than calling a function for each +possible iplb type. + +Signed-off-by: Janosch Frank +Reviewed-by: David Hildenbrand +Message-Id: <20200310090950.61172-1-frankja@linux.ibm.com> +Reviewed-by: Christian Borntraeger +Signed-off-by: Christian Borntraeger +(cherry picked from commit 94c21436e5a89143f8b9cb4d089d1a2f3f4fd377) +Signed-off-by: Danilo C. L. de Paula +--- + hw/s390x/ipl.h | 18 +++++++++--------- + target/s390x/diag.c | 2 +- + 2 files changed, 10 insertions(+), 10 deletions(-) + +diff --git a/hw/s390x/ipl.h b/hw/s390x/ipl.h +index d4813105db..3e44abe1c6 100644 +--- a/hw/s390x/ipl.h ++++ b/hw/s390x/ipl.h +@@ -173,16 +173,16 @@ static inline bool iplb_valid_len(IplParameterBlock *iplb) + return be32_to_cpu(iplb->len) <= sizeof(IplParameterBlock); + } + +-static inline bool iplb_valid_ccw(IplParameterBlock *iplb) ++static inline bool iplb_valid(IplParameterBlock *iplb) + { +- return be32_to_cpu(iplb->len) >= S390_IPLB_MIN_CCW_LEN && +- iplb->pbt == S390_IPL_TYPE_CCW; +-} +- +-static inline bool iplb_valid_fcp(IplParameterBlock *iplb) +-{ +- return be32_to_cpu(iplb->len) >= S390_IPLB_MIN_FCP_LEN && +- iplb->pbt == S390_IPL_TYPE_FCP; ++ switch (iplb->pbt) { ++ case S390_IPL_TYPE_FCP: ++ return be32_to_cpu(iplb->len) >= S390_IPLB_MIN_FCP_LEN; ++ case S390_IPL_TYPE_CCW: ++ return be32_to_cpu(iplb->len) >= S390_IPLB_MIN_CCW_LEN; ++ default: ++ return false; ++ } + } + + #endif +diff --git a/target/s390x/diag.c b/target/s390x/diag.c +index b5aec06d6b..54e5670b3f 100644 +--- a/target/s390x/diag.c ++++ b/target/s390x/diag.c +@@ -117,7 +117,7 @@ void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3, uintptr_t ra) + + cpu_physical_memory_read(addr, iplb, be32_to_cpu(iplb->len)); + +- if (!iplb_valid_ccw(iplb) && !iplb_valid_fcp(iplb)) { ++ if (!iplb_valid(iplb)) { + env->regs[r1 + 1] = DIAG_308_RC_INVALID; + goto out; + } +-- +2.27.0 + diff --git a/SOURCES/kvm-s390x-kvm-Make-kvm_sclp_service_call-void.patch b/SOURCES/kvm-s390x-kvm-Make-kvm_sclp_service_call-void.patch new file mode 100644 index 0000000..9882324 --- /dev/null +++ b/SOURCES/kvm-s390x-kvm-Make-kvm_sclp_service_call-void.patch @@ -0,0 +1,83 @@ +From 999cf62d870ff9aa8e9609fcbbcefef9ae1aceb6 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 29 May 2020 05:53:50 -0400 +Subject: [PATCH 08/42] s390x: kvm: Make kvm_sclp_service_call void +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Thomas Huth +Message-id: <20200529055420.16855-9-thuth@redhat.com> +Patchwork-id: 97030 +O-Subject: [RHEL-8.3.0 qemu-kvm PATCH v2 08/38] s390x: kvm: Make kvm_sclp_service_call void +Bugzilla: 1828317 +RH-Acked-by: Claudio Imbrenda +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand + +From: Janosch Frank + +It defaults to returning 0 anyway and that return value is not +necessary, as 0 is also the default rc that the caller would return. + +While doing that we can simplify the logic a bit and return early if +we inject a PGM exception. + +Signed-off-by: Janosch Frank +Reviewed-by: Thomas Huth +Message-Id: <20191129091713.4582-1-frankja@linux.ibm.com> +Reviewed-by: David Hildenbrand +Signed-off-by: Cornelia Huck +(cherry picked from commit 15b6c0370c3e2774fd9ffda5c10c6e36952e8eb6) +Signed-off-by: Danilo C. L. de Paula +--- + target/s390x/kvm.c | 12 +++++------- + 1 file changed, 5 insertions(+), 7 deletions(-) + +diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c +index a02d569537..1c5bc7a2f9 100644 +--- a/target/s390x/kvm.c ++++ b/target/s390x/kvm.c +@@ -1159,13 +1159,13 @@ void kvm_s390_access_exception(S390CPU *cpu, uint16_t code, uint64_t te_code) + kvm_s390_vcpu_interrupt(cpu, &irq); + } + +-static int kvm_sclp_service_call(S390CPU *cpu, struct kvm_run *run, ++static void kvm_sclp_service_call(S390CPU *cpu, struct kvm_run *run, + uint16_t ipbh0) + { + CPUS390XState *env = &cpu->env; + uint64_t sccb; + uint32_t code; +- int r = 0; ++ int r; + + sccb = env->regs[ipbh0 & 0xf]; + code = env->regs[(ipbh0 & 0xf0) >> 4]; +@@ -1173,11 +1173,9 @@ static int kvm_sclp_service_call(S390CPU *cpu, struct kvm_run *run, + r = sclp_service_call(env, sccb, code); + if (r < 0) { + kvm_s390_program_interrupt(cpu, -r); +- } else { +- setcc(cpu, r); ++ return; + } +- +- return 0; ++ setcc(cpu, r); + } + + static int handle_b2(S390CPU *cpu, struct kvm_run *run, uint8_t ipa1) +@@ -1240,7 +1238,7 @@ static int handle_b2(S390CPU *cpu, struct kvm_run *run, uint8_t ipa1) + setcc(cpu, 3); + break; + case PRIV_B2_SCLP_CALL: +- rc = kvm_sclp_service_call(cpu, run, ipbh0); ++ kvm_sclp_service_call(cpu, run, ipbh0); + break; + default: + rc = -1; +-- +2.27.0 + diff --git a/SOURCES/kvm-s390x-protvirt-Add-migration-blocker.patch b/SOURCES/kvm-s390x-protvirt-Add-migration-blocker.patch new file mode 100644 index 0000000..056f8d5 --- /dev/null +++ b/SOURCES/kvm-s390x-protvirt-Add-migration-blocker.patch @@ -0,0 +1,79 @@ +From 0ba8d4ea1cc34230356cc446dfa8d1cb52cbd2f3 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 29 May 2020 05:54:05 -0400 +Subject: [PATCH 23/42] s390x: protvirt: Add migration blocker + +RH-Author: Thomas Huth +Message-id: <20200529055420.16855-24-thuth@redhat.com> +Patchwork-id: 97043 +O-Subject: [RHEL-8.3.0 qemu-kvm PATCH v2 23/38] s390x: protvirt: Add migration blocker +Bugzilla: 1828317 +RH-Acked-by: Claudio Imbrenda +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand + +From: Janosch Frank + +Migration is not yet supported. + +Signed-off-by: Janosch Frank +Reviewed-by: David Hildenbrand +Reviewed-by: Christian Borntraeger +Reviewed-by: Claudio Imbrenda +Reviewed-by: Cornelia Huck +Message-Id: <20200319131921.2367-5-frankja@linux.ibm.com> +Signed-off-by: Cornelia Huck +(cherry picked from commit 0141e1b47707d90f5bd9d252da064ebdaca698a6) +Signed-off-by: Danilo C. L. de Paula +--- + hw/s390x/s390-virtio-ccw.c | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c +index 82da1d9ab5..dbd5125232 100644 +--- a/hw/s390x/s390-virtio-ccw.c ++++ b/hw/s390x/s390-virtio-ccw.c +@@ -44,6 +44,9 @@ + #include "sysemu/sysemu.h" + #include "hw/s390x/pv.h" + #include ++#include "migration/blocker.h" ++ ++static Error *pv_mig_blocker; + + S390CPU *s390_cpu_addr2state(uint16_t cpu_addr) + { +@@ -325,15 +328,30 @@ static void s390_machine_unprotect(S390CcwMachineState *ms) + { + s390_pv_vm_disable(); + ms->pv = false; ++ migrate_del_blocker(pv_mig_blocker); ++ error_free_or_abort(&pv_mig_blocker); + } + + static int s390_machine_protect(S390CcwMachineState *ms) + { ++ Error *local_err = NULL; + int rc; + ++ error_setg(&pv_mig_blocker, ++ "protected VMs are currently not migrateable."); ++ rc = migrate_add_blocker(pv_mig_blocker, &local_err); ++ if (rc) { ++ error_report_err(local_err); ++ error_free_or_abort(&pv_mig_blocker); ++ return rc; ++ } ++ + /* Create SE VM */ + rc = s390_pv_vm_enable(); + if (rc) { ++ error_report_err(local_err); ++ migrate_del_blocker(pv_mig_blocker); ++ error_free_or_abort(&pv_mig_blocker); + return rc; + } + +-- +2.27.0 + diff --git a/SOURCES/kvm-s390x-protvirt-Disable-address-checks-for-PV-guest-I.patch b/SOURCES/kvm-s390x-protvirt-Disable-address-checks-for-PV-guest-I.patch new file mode 100644 index 0000000..0cf75b0 --- /dev/null +++ b/SOURCES/kvm-s390x-protvirt-Disable-address-checks-for-PV-guest-I.patch @@ -0,0 +1,135 @@ +From 1cfcff169f392179258e4535e60d4ef9cabae3c6 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 29 May 2020 05:54:13 -0400 +Subject: [PATCH 31/42] s390x: protvirt: Disable address checks for PV guest IO + emulation + +RH-Author: Thomas Huth +Message-id: <20200529055420.16855-32-thuth@redhat.com> +Patchwork-id: 97044 +O-Subject: [RHEL-8.3.0 qemu-kvm PATCH v2 31/38] s390x: protvirt: Disable address checks for PV guest IO emulation +Bugzilla: 1828317 +RH-Acked-by: Claudio Imbrenda +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand + +From: Janosch Frank + +IO instruction data is routed through SIDAD for protected guests, so +adresses do not need to be checked, as this is kernel memory which is +always available. + +Also the instruction data always starts at offset 0 of the SIDAD. + +Signed-off-by: Janosch Frank +Reviewed-by: Thomas Huth +Reviewed-by: David Hildenbrand +Reviewed-by: Christian Borntraeger +Reviewed-by: Claudio Imbrenda +Reviewed-by: Cornelia Huck +Message-Id: <20200319131921.2367-13-frankja@linux.ibm.com> +Signed-off-by: Cornelia Huck +(cherry picked from commit c10b708752e5264a85b5c3afa0a0ccfcf6503ddf) +Signed-off-by: Danilo C. L. de Paula +--- + target/s390x/ioinst.c | 35 ++++++++++++++++++++++++++++------- + 1 file changed, 28 insertions(+), 7 deletions(-) + +diff --git a/target/s390x/ioinst.c b/target/s390x/ioinst.c +index c437a1d8c6..bbcccf6be2 100644 +--- a/target/s390x/ioinst.c ++++ b/target/s390x/ioinst.c +@@ -16,6 +16,25 @@ + #include "hw/s390x/ioinst.h" + #include "trace.h" + #include "hw/s390x/s390-pci-bus.h" ++#include "hw/s390x/pv.h" ++ ++/* All I/O instructions but chsc use the s format */ ++static uint64_t get_address_from_regs(CPUS390XState *env, uint32_t ipb, ++ uint8_t *ar) ++{ ++ /* ++ * Addresses for protected guests are all offsets into the ++ * satellite block which holds the IO control structures. Those ++ * control structures are always starting at offset 0 and are ++ * always aligned and accessible. So we can return 0 here which ++ * will pass the following address checks. ++ */ ++ if (s390_is_pv()) { ++ *ar = 0; ++ return 0; ++ } ++ return decode_basedisp_s(env, ipb, ar); ++} + + int ioinst_disassemble_sch_ident(uint32_t value, int *m, int *cssid, int *ssid, + int *schid) +@@ -114,7 +133,7 @@ void ioinst_handle_msch(S390CPU *cpu, uint64_t reg1, uint32_t ipb, uintptr_t ra) + CPUS390XState *env = &cpu->env; + uint8_t ar; + +- addr = decode_basedisp_s(env, ipb, &ar); ++ addr = get_address_from_regs(env, ipb, &ar); + if (addr & 3) { + s390_program_interrupt(env, PGM_SPECIFICATION, ra); + return; +@@ -171,7 +190,7 @@ void ioinst_handle_ssch(S390CPU *cpu, uint64_t reg1, uint32_t ipb, uintptr_t ra) + CPUS390XState *env = &cpu->env; + uint8_t ar; + +- addr = decode_basedisp_s(env, ipb, &ar); ++ addr = get_address_from_regs(env, ipb, &ar); + if (addr & 3) { + s390_program_interrupt(env, PGM_SPECIFICATION, ra); + return; +@@ -203,7 +222,7 @@ void ioinst_handle_stcrw(S390CPU *cpu, uint32_t ipb, uintptr_t ra) + CPUS390XState *env = &cpu->env; + uint8_t ar; + +- addr = decode_basedisp_s(env, ipb, &ar); ++ addr = get_address_from_regs(env, ipb, &ar); + if (addr & 3) { + s390_program_interrupt(env, PGM_SPECIFICATION, ra); + return; +@@ -234,7 +253,7 @@ void ioinst_handle_stsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb, + CPUS390XState *env = &cpu->env; + uint8_t ar; + +- addr = decode_basedisp_s(env, ipb, &ar); ++ addr = get_address_from_regs(env, ipb, &ar); + if (addr & 3) { + s390_program_interrupt(env, PGM_SPECIFICATION, ra); + return; +@@ -303,7 +322,7 @@ int ioinst_handle_tsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb, uintptr_t ra) + return -EIO; + } + trace_ioinst_sch_id("tsch", cssid, ssid, schid); +- addr = decode_basedisp_s(env, ipb, &ar); ++ addr = get_address_from_regs(env, ipb, &ar); + if (addr & 3) { + s390_program_interrupt(env, PGM_SPECIFICATION, ra); + return -EIO; +@@ -601,7 +620,7 @@ void ioinst_handle_chsc(S390CPU *cpu, uint32_t ipb, uintptr_t ra) + { + ChscReq *req; + ChscResp *res; +- uint64_t addr; ++ uint64_t addr = 0; + int reg; + uint16_t len; + uint16_t command; +@@ -610,7 +629,9 @@ void ioinst_handle_chsc(S390CPU *cpu, uint32_t ipb, uintptr_t ra) + + trace_ioinst("chsc"); + reg = (ipb >> 20) & 0x00f; +- addr = env->regs[reg]; ++ if (!s390_is_pv()) { ++ addr = env->regs[reg]; ++ } + /* Page boundary? */ + if (addr & 0xfff) { + s390_program_interrupt(env, PGM_SPECIFICATION, ra); +-- +2.27.0 + diff --git a/SOURCES/kvm-s390x-protvirt-Fix-stray-error_report_err-in-s390_ma.patch b/SOURCES/kvm-s390x-protvirt-Fix-stray-error_report_err-in-s390_ma.patch new file mode 100644 index 0000000..9857f28 --- /dev/null +++ b/SOURCES/kvm-s390x-protvirt-Fix-stray-error_report_err-in-s390_ma.patch @@ -0,0 +1,55 @@ +From b54e5e6df5d5bbe4dc0a206be9f6b6d971ce6f43 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 29 May 2020 05:54:17 -0400 +Subject: [PATCH 35/42] s390x: protvirt: Fix stray error_report_err in + s390_machine_protect +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Thomas Huth +Message-id: <20200529055420.16855-36-thuth@redhat.com> +Patchwork-id: 97042 +O-Subject: [RHEL-8.3.0 qemu-kvm PATCH v2 35/38] s390x: protvirt: Fix stray error_report_err in s390_machine_protect +Bugzilla: 1828317 +RH-Acked-by: Claudio Imbrenda +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand + +From: Janosch Frank + +In case the protection of the machine fails at s390_pv_vm_enable(), +we'll currently report the local_error variable. Problem is that +there's no migration blocker error that we can report at this point so +the pointer is always NULL which leads to a SEGFAULT. + +Let's remove the error report. + +Signed-off-by: Janosch Frank +Reported-by: Marc Hartmayer +Fixes: 0141e1b47707 ("s390x: protvirt: Add migration blocker") +Message-Id: <20200326140505.2432-1-frankja@linux.ibm.com> +Reviewed-by: David Hildenbrand +Signed-off-by: Cornelia Huck +(cherry picked from commit 7152c9ecc6530ea145c122b0a58cc28802f630c6) +Signed-off-by: Danilo C. L. de Paula +--- + hw/s390x/s390-virtio-ccw.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c +index b4ebe83766..c08e42bda1 100644 +--- a/hw/s390x/s390-virtio-ccw.c ++++ b/hw/s390x/s390-virtio-ccw.c +@@ -360,7 +360,6 @@ static int s390_machine_protect(S390CcwMachineState *ms) + rc = s390_pv_vm_enable(); + if (rc) { + qemu_balloon_inhibit(false); +- error_report_err(local_err); + migrate_del_blocker(pv_mig_blocker); + error_free_or_abort(&pv_mig_blocker); + return rc; +-- +2.27.0 + diff --git a/SOURCES/kvm-s390x-protvirt-Handle-SIGP-store-status-correctly.patch b/SOURCES/kvm-s390x-protvirt-Handle-SIGP-store-status-correctly.patch new file mode 100644 index 0000000..4d6a44b --- /dev/null +++ b/SOURCES/kvm-s390x-protvirt-Handle-SIGP-store-status-correctly.patch @@ -0,0 +1,61 @@ +From 680154545d1f9d75fb33615b1900661e7d09be4e Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 29 May 2020 05:54:15 -0400 +Subject: [PATCH 33/42] s390x: protvirt: Handle SIGP store status correctly + +RH-Author: Thomas Huth +Message-id: <20200529055420.16855-34-thuth@redhat.com> +Patchwork-id: 97054 +O-Subject: [RHEL-8.3.0 qemu-kvm PATCH v2 33/38] s390x: protvirt: Handle SIGP store status correctly +Bugzilla: 1828317 +RH-Acked-by: Claudio Imbrenda +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand + +From: Janosch Frank + +For protected VMs status storing is not done by QEMU anymore. + +Signed-off-by: Janosch Frank +Reviewed-by: Thomas Huth +Reviewed-by: David Hildenbrand +Reviewed-by: Christian Borntraeger +Reviewed-by: Claudio Imbrenda +Reviewed-by: Cornelia Huck +Message-Id: <20200319131921.2367-15-frankja@linux.ibm.com> +Signed-off-by: Cornelia Huck +(cherry picked from commit f2a2d9a2bae8f6fdc5e9a40c1241e9428f15b4df) +[thuth: fixed contextual conflict due to missing commit 44eaccd091a7365fd37) +Signed-off-by: Thomas Huth +Signed-off-by: Danilo C. L. de Paula +--- + target/s390x/helper.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/target/s390x/helper.c b/target/s390x/helper.c +index 6808dfda01..36b6d3d9d1 100644 +--- a/target/s390x/helper.c ++++ b/target/s390x/helper.c +@@ -25,6 +25,7 @@ + #include "qemu/timer.h" + #include "qemu/qemu-print.h" + #include "hw/s390x/ioinst.h" ++#include "hw/s390x/pv.h" + #include "sysemu/hw_accel.h" + #include "sysemu/runstate.h" + #ifndef CONFIG_USER_ONLY +@@ -246,6 +247,11 @@ int s390_store_status(S390CPU *cpu, hwaddr addr, bool store_arch) + hwaddr len = sizeof(*sa); + int i; + ++ /* For PVMs storing will occur when this cpu enters SIE again */ ++ if (s390_is_pv()) { ++ return 0; ++ } ++ + sa = cpu_physical_memory_map(addr, &len, 1); + if (!sa) { + return -EFAULT; +-- +2.27.0 + diff --git a/SOURCES/kvm-s390x-protvirt-Inhibit-balloon-when-switching-to-pro.patch b/SOURCES/kvm-s390x-protvirt-Inhibit-balloon-when-switching-to-pro.patch new file mode 100644 index 0000000..a843d03 --- /dev/null +++ b/SOURCES/kvm-s390x-protvirt-Inhibit-balloon-when-switching-to-pro.patch @@ -0,0 +1,104 @@ +From 095553f9dd1fec02869bf974e8cc07614d6587e5 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 29 May 2020 05:54:06 -0400 +Subject: [PATCH 24/42] s390x: protvirt: Inhibit balloon when switching to + protected mode +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Thomas Huth +Message-id: <20200529055420.16855-25-thuth@redhat.com> +Patchwork-id: 97036 +O-Subject: [RHEL-8.3.0 qemu-kvm PATCH v2 24/38] s390x: protvirt: Inhibit balloon when switching to protected mode +Bugzilla: 1828317 +RH-Acked-by: Claudio Imbrenda +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand + +From: Janosch Frank + +Ballooning in protected VMs can only be done when the guest shares the +pages it gives to the host. If pages are not shared, the integrity +checks will fail once those pages have been altered and are given back +to the guest. + +As we currently do not yet have a solution for this we will continue +like this: + +1. We block ballooning now in QEMU (with this patch). + +2. Later we will provide a change to virtio that removes the blocker +and adds VIRTIO_F_IOMMU_PLATFORM automatically by QEMU when doing the +protvirt switch. This is OK, as the balloon driver in Linux (the only +supported guest) will refuse to work with the IOMMU_PLATFORM feature +bit set. + +3. Later, we can fix the guest balloon driver to accept the IOMMU +feature bit and correctly exercise sharing and unsharing of balloon +pages. + +Signed-off-by: Janosch Frank +Reviewed-by: David Hildenbrand +Reviewed-by: Christian Borntraeger +Reviewed-by: Claudio Imbrenda +Reviewed-by: Cornelia Huck +Message-Id: <20200319131921.2367-6-frankja@linux.ibm.com> +Signed-off-by: Cornelia Huck +(cherry picked from commit b1697f63fd8f8201b1447bb55f595830b9cbde31) +Signed-off-by: Danilo C. L. de Paula +--- + hw/s390x/s390-virtio-ccw.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c +index dbd5125232..b4ebe83766 100644 +--- a/hw/s390x/s390-virtio-ccw.c ++++ b/hw/s390x/s390-virtio-ccw.c +@@ -42,6 +42,7 @@ + #include "hw/qdev-properties.h" + #include "hw/s390x/tod.h" + #include "sysemu/sysemu.h" ++#include "sysemu/balloon.h" + #include "hw/s390x/pv.h" + #include + #include "migration/blocker.h" +@@ -330,6 +331,7 @@ static void s390_machine_unprotect(S390CcwMachineState *ms) + ms->pv = false; + migrate_del_blocker(pv_mig_blocker); + error_free_or_abort(&pv_mig_blocker); ++ qemu_balloon_inhibit(false); + } + + static int s390_machine_protect(S390CcwMachineState *ms) +@@ -337,10 +339,18 @@ static int s390_machine_protect(S390CcwMachineState *ms) + Error *local_err = NULL; + int rc; + ++ /* ++ * Ballooning on protected VMs needs support in the guest for ++ * sharing and unsharing balloon pages. Block ballooning for ++ * now, until we have a solution to make at least Linux guests ++ * either support it or fail gracefully. ++ */ ++ qemu_balloon_inhibit(true); + error_setg(&pv_mig_blocker, + "protected VMs are currently not migrateable."); + rc = migrate_add_blocker(pv_mig_blocker, &local_err); + if (rc) { ++ qemu_balloon_inhibit(false); + error_report_err(local_err); + error_free_or_abort(&pv_mig_blocker); + return rc; +@@ -349,6 +359,7 @@ static int s390_machine_protect(S390CcwMachineState *ms) + /* Create SE VM */ + rc = s390_pv_vm_enable(); + if (rc) { ++ qemu_balloon_inhibit(false); + error_report_err(local_err); + migrate_del_blocker(pv_mig_blocker); + error_free_or_abort(&pv_mig_blocker); +-- +2.27.0 + diff --git a/SOURCES/kvm-s390x-protvirt-KVM-intercept-changes.patch b/SOURCES/kvm-s390x-protvirt-KVM-intercept-changes.patch new file mode 100644 index 0000000..2ac3d03 --- /dev/null +++ b/SOURCES/kvm-s390x-protvirt-KVM-intercept-changes.patch @@ -0,0 +1,75 @@ +From 10ed4f6ad687d98f0bfe06d75775e8c541da80a0 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 29 May 2020 05:54:07 -0400 +Subject: [PATCH 25/42] s390x: protvirt: KVM intercept changes + +RH-Author: Thomas Huth +Message-id: <20200529055420.16855-26-thuth@redhat.com> +Patchwork-id: 97035 +O-Subject: [RHEL-8.3.0 qemu-kvm PATCH v2 25/38] s390x: protvirt: KVM intercept changes +Bugzilla: 1828317 +RH-Acked-by: Claudio Imbrenda +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand + +From: Janosch Frank + +Protected VMs no longer intercept with code 4 for an instruction +interception. Instead they have codes 104 and 108 for protected +instruction interception and protected instruction notification +respectively. + +The 104 mirrors the 4 interception. + +The 108 is a notification interception to let KVM and QEMU know that +something changed and we need to update tracking information or +perform specific tasks. It's currently taken for the following +instructions: + +* spx (To inform about the changed prefix location) +* sclp (On incorrect SCCB values, so we can inject a IRQ) +* sigp (All but "stop and store status") +* diag308 (Subcodes 0/1) + +Of these exits only sclp errors, state changing sigps and diag308 will +reach QEMU. QEMU will do its parts of the job, while the ultravisor +has done the instruction part of the job. + +Signed-off-by: Janosch Frank +Reviewed-by: David Hildenbrand +Reviewed-by: Christian Borntraeger +Reviewed-by: Claudio Imbrenda +Reviewed-by: Cornelia Huck +Message-Id: <20200319131921.2367-7-frankja@linux.ibm.com> +Signed-off-by: Cornelia Huck +(cherry picked from commit 2585e507ffa1da01b57dbea26b1e1fe507d27198) +Signed-off-by: Danilo C. L. de Paula +--- + target/s390x/kvm.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c +index 9a0be13959..af50b2c253 100644 +--- a/target/s390x/kvm.c ++++ b/target/s390x/kvm.c +@@ -115,6 +115,8 @@ + #define ICPT_CPU_STOP 0x28 + #define ICPT_OPEREXC 0x2c + #define ICPT_IO 0x40 ++#define ICPT_PV_INSTR 0x68 ++#define ICPT_PV_INSTR_NOTIFICATION 0x6c + + #define NR_LOCAL_IRQS 32 + /* +@@ -1695,6 +1697,8 @@ static int handle_intercept(S390CPU *cpu) + (long)cs->kvm_run->psw_addr); + switch (icpt_code) { + case ICPT_INSTRUCTION: ++ case ICPT_PV_INSTR: ++ case ICPT_PV_INSTR_NOTIFICATION: + r = handle_instruction(cpu, run); + break; + case ICPT_PROGRAM: +-- +2.27.0 + diff --git a/SOURCES/kvm-s390x-protvirt-Move-IO-control-structures-over-SIDA.patch b/SOURCES/kvm-s390x-protvirt-Move-IO-control-structures-over-SIDA.patch new file mode 100644 index 0000000..0609546 --- /dev/null +++ b/SOURCES/kvm-s390x-protvirt-Move-IO-control-structures-over-SIDA.patch @@ -0,0 +1,171 @@ +From 8345b90f43b14435938fbbe0f3a510a60f5d0ded Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 29 May 2020 05:54:14 -0400 +Subject: [PATCH 32/42] s390x: protvirt: Move IO control structures over SIDA + +RH-Author: Thomas Huth +Message-id: <20200529055420.16855-33-thuth@redhat.com> +Patchwork-id: 97040 +O-Subject: [RHEL-8.3.0 qemu-kvm PATCH v2 32/38] s390x: protvirt: Move IO control structures over SIDA +Bugzilla: 1828317 +RH-Acked-by: Claudio Imbrenda +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand + +From: Janosch Frank + +For protected guests, we need to put the IO emulation results into the +SIDA, so SIE will write them into the guest at the next entry. + +Signed-off-by: Janosch Frank +Reviewed-by: David Hildenbrand +Reviewed-by: Cornelia Huck +Message-Id: <20200319131921.2367-14-frankja@linux.ibm.com> +Signed-off-by: Cornelia Huck +(cherry picked from commit fcc10c1470d6e9460ebcf4c30f5bbd37b921a041) +Signed-off-by: Danilo C. L. de Paula +--- + target/s390x/ioinst.c | 61 +++++++++++++++++++++++++++++++------------ + 1 file changed, 45 insertions(+), 16 deletions(-) + +diff --git a/target/s390x/ioinst.c b/target/s390x/ioinst.c +index bbcccf6be2..f40c35c6ff 100644 +--- a/target/s390x/ioinst.c ++++ b/target/s390x/ioinst.c +@@ -138,7 +138,9 @@ void ioinst_handle_msch(S390CPU *cpu, uint64_t reg1, uint32_t ipb, uintptr_t ra) + s390_program_interrupt(env, PGM_SPECIFICATION, ra); + return; + } +- if (s390_cpu_virt_mem_read(cpu, addr, ar, &schib, sizeof(schib))) { ++ if (s390_is_pv()) { ++ s390_cpu_pv_mem_read(cpu, addr, &schib, sizeof(schib)); ++ } else if (s390_cpu_virt_mem_read(cpu, addr, ar, &schib, sizeof(schib))) { + s390_cpu_virt_mem_handle_exc(cpu, ra); + return; + } +@@ -195,7 +197,9 @@ void ioinst_handle_ssch(S390CPU *cpu, uint64_t reg1, uint32_t ipb, uintptr_t ra) + s390_program_interrupt(env, PGM_SPECIFICATION, ra); + return; + } +- if (s390_cpu_virt_mem_read(cpu, addr, ar, &orig_orb, sizeof(orb))) { ++ if (s390_is_pv()) { ++ s390_cpu_pv_mem_read(cpu, addr, &orig_orb, sizeof(orb)); ++ } else if (s390_cpu_virt_mem_read(cpu, addr, ar, &orig_orb, sizeof(orb))) { + s390_cpu_virt_mem_handle_exc(cpu, ra); + return; + } +@@ -231,14 +235,19 @@ void ioinst_handle_stcrw(S390CPU *cpu, uint32_t ipb, uintptr_t ra) + cc = css_do_stcrw(&crw); + /* 0 - crw stored, 1 - zeroes stored */ + +- if (s390_cpu_virt_mem_write(cpu, addr, ar, &crw, sizeof(crw)) == 0) { ++ if (s390_is_pv()) { ++ s390_cpu_pv_mem_write(cpu, addr, &crw, sizeof(crw)); + setcc(cpu, cc); + } else { +- if (cc == 0) { +- /* Write failed: requeue CRW since STCRW is suppressing */ +- css_undo_stcrw(&crw); ++ if (s390_cpu_virt_mem_write(cpu, addr, ar, &crw, sizeof(crw)) == 0) { ++ setcc(cpu, cc); ++ } else { ++ if (cc == 0) { ++ /* Write failed: requeue CRW since STCRW is suppressing */ ++ css_undo_stcrw(&crw); ++ } ++ s390_cpu_virt_mem_handle_exc(cpu, ra); + } +- s390_cpu_virt_mem_handle_exc(cpu, ra); + } + } + +@@ -260,6 +269,13 @@ void ioinst_handle_stsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb, + } + + if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid)) { ++ /* ++ * The Ultravisor checks schid bit 16 to be one and bits 0-12 ++ * to be 0 and injects a operand exception itself. ++ * ++ * Hence we should never end up here. ++ */ ++ g_assert(!s390_is_pv()); + /* + * As operand exceptions have a lower priority than access exceptions, + * we check whether the memory area is writeable (injecting the +@@ -292,14 +308,17 @@ void ioinst_handle_stsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb, + } + } + if (cc != 3) { +- if (s390_cpu_virt_mem_write(cpu, addr, ar, &schib, +- sizeof(schib)) != 0) { ++ if (s390_is_pv()) { ++ s390_cpu_pv_mem_write(cpu, addr, &schib, sizeof(schib)); ++ } else if (s390_cpu_virt_mem_write(cpu, addr, ar, &schib, ++ sizeof(schib)) != 0) { + s390_cpu_virt_mem_handle_exc(cpu, ra); + return; + } + } else { + /* Access exceptions have a higher priority than cc3 */ +- if (s390_cpu_virt_mem_check_write(cpu, addr, ar, sizeof(schib)) != 0) { ++ if (!s390_is_pv() && ++ s390_cpu_virt_mem_check_write(cpu, addr, ar, sizeof(schib)) != 0) { + s390_cpu_virt_mem_handle_exc(cpu, ra); + return; + } +@@ -336,7 +355,9 @@ int ioinst_handle_tsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb, uintptr_t ra) + } + /* 0 - status pending, 1 - not status pending, 3 - not operational */ + if (cc != 3) { +- if (s390_cpu_virt_mem_write(cpu, addr, ar, &irb, irb_len) != 0) { ++ if (s390_is_pv()) { ++ s390_cpu_pv_mem_write(cpu, addr, &irb, irb_len); ++ } else if (s390_cpu_virt_mem_write(cpu, addr, ar, &irb, irb_len) != 0) { + s390_cpu_virt_mem_handle_exc(cpu, ra); + return -EFAULT; + } +@@ -344,7 +365,8 @@ int ioinst_handle_tsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb, uintptr_t ra) + } else { + irb_len = sizeof(irb) - sizeof(irb.emw); + /* Access exceptions have a higher priority than cc3 */ +- if (s390_cpu_virt_mem_check_write(cpu, addr, ar, irb_len) != 0) { ++ if (!s390_is_pv() && ++ s390_cpu_virt_mem_check_write(cpu, addr, ar, irb_len) != 0) { + s390_cpu_virt_mem_handle_exc(cpu, ra); + return -EFAULT; + } +@@ -642,7 +664,9 @@ void ioinst_handle_chsc(S390CPU *cpu, uint32_t ipb, uintptr_t ra) + * present CHSC sub-handlers ... if we ever need more, we should take + * care of req->len here first. + */ +- if (s390_cpu_virt_mem_read(cpu, addr, reg, buf, sizeof(ChscReq))) { ++ if (s390_is_pv()) { ++ s390_cpu_pv_mem_read(cpu, addr, buf, sizeof(ChscReq)); ++ } else if (s390_cpu_virt_mem_read(cpu, addr, reg, buf, sizeof(ChscReq))) { + s390_cpu_virt_mem_handle_exc(cpu, ra); + return; + } +@@ -675,11 +699,16 @@ void ioinst_handle_chsc(S390CPU *cpu, uint32_t ipb, uintptr_t ra) + break; + } + +- if (!s390_cpu_virt_mem_write(cpu, addr + len, reg, res, +- be16_to_cpu(res->len))) { ++ if (s390_is_pv()) { ++ s390_cpu_pv_mem_write(cpu, addr + len, res, be16_to_cpu(res->len)); + setcc(cpu, 0); /* Command execution complete */ + } else { +- s390_cpu_virt_mem_handle_exc(cpu, ra); ++ if (!s390_cpu_virt_mem_write(cpu, addr + len, reg, res, ++ be16_to_cpu(res->len))) { ++ setcc(cpu, 0); /* Command execution complete */ ++ } else { ++ s390_cpu_virt_mem_handle_exc(cpu, ra); ++ } + } + } + +-- +2.27.0 + diff --git a/SOURCES/kvm-s390x-protvirt-Move-STSI-data-over-SIDAD.patch b/SOURCES/kvm-s390x-protvirt-Move-STSI-data-over-SIDAD.patch new file mode 100644 index 0000000..1d60070 --- /dev/null +++ b/SOURCES/kvm-s390x-protvirt-Move-STSI-data-over-SIDAD.patch @@ -0,0 +1,70 @@ +From 27f5d8a3af2863e39b7c46a3128009988d772f15 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 29 May 2020 05:54:09 -0400 +Subject: [PATCH 27/42] s390x: protvirt: Move STSI data over SIDAD + +RH-Author: Thomas Huth +Message-id: <20200529055420.16855-28-thuth@redhat.com> +Patchwork-id: 97046 +O-Subject: [RHEL-8.3.0 qemu-kvm PATCH v2 27/38] s390x: protvirt: Move STSI data over SIDAD +Bugzilla: 1828317 +RH-Acked-by: Claudio Imbrenda +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand + +From: Janosch Frank + +For protected guests, we need to put the STSI emulation results into +the SIDA, so SIE will write them into the guest at the next entry. + +Signed-off-by: Janosch Frank +Reviewed-by: David Hildenbrand +Reviewed-by: Claudio Imbrenda +Reviewed-by: Cornelia Huck +Message-Id: <20200319131921.2367-9-frankja@linux.ibm.com> +Signed-off-by: Cornelia Huck +(cherry picked from commit 7c713b8acb70fb61f9650f8a7702dec546752bb6) +Signed-off-by: Danilo C. L. de Paula +--- + target/s390x/kvm.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c +index f67bb5ce2c..6809a5ac40 100644 +--- a/target/s390x/kvm.c ++++ b/target/s390x/kvm.c +@@ -50,6 +50,7 @@ + #include "exec/memattrs.h" + #include "hw/s390x/s390-virtio-ccw.h" + #include "hw/s390x/s390-virtio-hcall.h" ++#include "hw/s390x/pv.h" + + #ifndef DEBUG_KVM + #define DEBUG_KVM 0 +@@ -1803,7 +1804,9 @@ static void insert_stsi_3_2_2(S390CPU *cpu, __u64 addr, uint8_t ar) + SysIB_322 sysib; + int del; + +- if (s390_cpu_virt_mem_read(cpu, addr, ar, &sysib, sizeof(sysib))) { ++ if (s390_is_pv()) { ++ s390_cpu_pv_mem_read(cpu, 0, &sysib, sizeof(sysib)); ++ } else if (s390_cpu_virt_mem_read(cpu, addr, ar, &sysib, sizeof(sysib))) { + return; + } + /* Shift the stack of Extended Names to prepare for our own data */ +@@ -1843,7 +1846,11 @@ static void insert_stsi_3_2_2(S390CPU *cpu, __u64 addr, uint8_t ar) + /* Insert UUID */ + memcpy(sysib.vm[0].uuid, &qemu_uuid, sizeof(sysib.vm[0].uuid)); + +- s390_cpu_virt_mem_write(cpu, addr, ar, &sysib, sizeof(sysib)); ++ if (s390_is_pv()) { ++ s390_cpu_pv_mem_write(cpu, 0, &sysib, sizeof(sysib)); ++ } else { ++ s390_cpu_virt_mem_write(cpu, addr, ar, &sysib, sizeof(sysib)); ++ } + } + + static int handle_stsi(S390CPU *cpu) +-- +2.27.0 + diff --git a/SOURCES/kvm-s390x-protvirt-Move-diag-308-data-over-SIDA.patch b/SOURCES/kvm-s390x-protvirt-Move-diag-308-data-over-SIDA.patch new file mode 100644 index 0000000..1b22719 --- /dev/null +++ b/SOURCES/kvm-s390x-protvirt-Move-diag-308-data-over-SIDA.patch @@ -0,0 +1,93 @@ +From 33d4e21cfd236aecd9e4dbe8228d058fd1f22400 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 29 May 2020 05:54:12 -0400 +Subject: [PATCH 30/42] s390x: protvirt: Move diag 308 data over SIDA + +RH-Author: Thomas Huth +Message-id: <20200529055420.16855-31-thuth@redhat.com> +Patchwork-id: 97048 +O-Subject: [RHEL-8.3.0 qemu-kvm PATCH v2 30/38] s390x: protvirt: Move diag 308 data over SIDA +Bugzilla: 1828317 +RH-Acked-by: Claudio Imbrenda +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand + +From: Janosch Frank + +For protected guests the IPIB is written/read to/from the SIDA, so we +need those accesses to go through s390_cpu_pv_mem_read/write(). + +Signed-off-by: Janosch Frank +Reviewed-by: David Hildenbrand +Reviewed-by: Christian Borntraeger +Reviewed-by: Claudio Imbrenda +Reviewed-by: Cornelia Huck +Message-Id: <20200319131921.2367-12-frankja@linux.ibm.com> +Signed-off-by: Cornelia Huck +(cherry picked from commit 9c61e11238cfa8f70e3eb90aac5d3e5646e5432f) +Signed-off-by: Danilo C. L. de Paula +--- + target/s390x/diag.c | 25 ++++++++++++++++++++----- + 1 file changed, 20 insertions(+), 5 deletions(-) + +diff --git a/target/s390x/diag.c b/target/s390x/diag.c +index b2cbefb8cf..1a48429564 100644 +--- a/target/s390x/diag.c ++++ b/target/s390x/diag.c +@@ -75,6 +75,7 @@ void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3, uintptr_t ra) + { + bool valid; + CPUState *cs = env_cpu(env); ++ S390CPU *cpu = S390_CPU(cs); + uint64_t addr = env->regs[r1]; + uint64_t subcode = env->regs[r3]; + IplParameterBlock *iplb; +@@ -111,13 +112,22 @@ void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3, uintptr_t ra) + return; + } + iplb = g_new0(IplParameterBlock, 1); +- cpu_physical_memory_read(addr, iplb, sizeof(iplb->len)); ++ if (!s390_is_pv()) { ++ cpu_physical_memory_read(addr, iplb, sizeof(iplb->len)); ++ } else { ++ s390_cpu_pv_mem_read(cpu, 0, iplb, sizeof(iplb->len)); ++ } ++ + if (!iplb_valid_len(iplb)) { + env->regs[r1 + 1] = DIAG_308_RC_INVALID; + goto out; + } + +- cpu_physical_memory_read(addr, iplb, be32_to_cpu(iplb->len)); ++ if (!s390_is_pv()) { ++ cpu_physical_memory_read(addr, iplb, be32_to_cpu(iplb->len)); ++ } else { ++ s390_cpu_pv_mem_read(cpu, 0, iplb, be32_to_cpu(iplb->len)); ++ } + + valid = subcode == DIAG308_PV_SET ? iplb_valid_pv(iplb) : iplb_valid(iplb); + if (!valid) { +@@ -140,12 +150,17 @@ out: + } else { + iplb = s390_ipl_get_iplb(); + } +- if (iplb) { ++ if (!iplb) { ++ env->regs[r1 + 1] = DIAG_308_RC_NO_CONF; ++ return; ++ } ++ ++ if (!s390_is_pv()) { + cpu_physical_memory_write(addr, iplb, be32_to_cpu(iplb->len)); +- env->regs[r1 + 1] = DIAG_308_RC_OK; + } else { +- env->regs[r1 + 1] = DIAG_308_RC_NO_CONF; ++ s390_cpu_pv_mem_write(cpu, 0, iplb, be32_to_cpu(iplb->len)); + } ++ env->regs[r1 + 1] = DIAG_308_RC_OK; + return; + case DIAG308_PV_START: + iplb = s390_ipl_get_iplb_pv(); +-- +2.27.0 + diff --git a/SOURCES/kvm-s390x-protvirt-SCLP-interpretation.patch b/SOURCES/kvm-s390x-protvirt-SCLP-interpretation.patch new file mode 100644 index 0000000..10f1930 --- /dev/null +++ b/SOURCES/kvm-s390x-protvirt-SCLP-interpretation.patch @@ -0,0 +1,172 @@ +From 5a8b40c3fdafeb49072f8643210bea00ce1478c4 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 29 May 2020 05:54:10 -0400 +Subject: [PATCH 28/42] s390x: protvirt: SCLP interpretation + +RH-Author: Thomas Huth +Message-id: <20200529055420.16855-29-thuth@redhat.com> +Patchwork-id: 97053 +O-Subject: [RHEL-8.3.0 qemu-kvm PATCH v2 28/38] s390x: protvirt: SCLP interpretation +Bugzilla: 1828317 +RH-Acked-by: Claudio Imbrenda +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand + +From: Janosch Frank + +SCLP for a protected guest is done over the SIDAD, so we need to use +the s390_cpu_pv_mem_* functions to access the SIDAD instead of guest +memory when reading/writing SCBs. + +To not confuse the sclp emulation, we set 0x4000 as the SCCB address, +since the function that injects the sclp external interrupt would +reject a zero sccb address. + +Signed-off-by: Janosch Frank +Reviewed-by: David Hildenbrand +Reviewed-by: Claudio Imbrenda +Reviewed-by: Cornelia Huck +Reviewed-by: Christian Borntraeger +Message-Id: <20200319131921.2367-10-frankja@linux.ibm.com> +Signed-off-by: Cornelia Huck +(cherry picked from commit 0f73c5b30b8ba6c0828608be496d2f59a5427539) +Signed-off-by: Danilo C. L. de Paula +--- + hw/s390x/sclp.c | 56 +++++++++++++++++++++++++++++++++-------- + include/hw/s390x/sclp.h | 2 ++ + target/s390x/kvm.c | 25 ++++++++++++++---- + 3 files changed, 67 insertions(+), 16 deletions(-) + +diff --git a/hw/s390x/sclp.c b/hw/s390x/sclp.c +index f57ce7b739..1c380a49cc 100644 +--- a/hw/s390x/sclp.c ++++ b/hw/s390x/sclp.c +@@ -33,6 +33,22 @@ static inline SCLPDevice *get_sclp_device(void) + return sclp; + } + ++static inline bool sclp_command_code_valid(uint32_t code) ++{ ++ switch (code & SCLP_CMD_CODE_MASK) { ++ case SCLP_CMDW_READ_SCP_INFO: ++ case SCLP_CMDW_READ_SCP_INFO_FORCED: ++ case SCLP_CMDW_READ_CPU_INFO: ++ case SCLP_CMDW_CONFIGURE_IOA: ++ case SCLP_CMDW_DECONFIGURE_IOA: ++ case SCLP_CMD_READ_EVENT_DATA: ++ case SCLP_CMD_WRITE_EVENT_DATA: ++ case SCLP_CMD_WRITE_EVENT_MASK: ++ return true; ++ } ++ return false; ++} ++ + static void prepare_cpu_entries(SCLPDevice *sclp, CPUEntry *entry, int *count) + { + MachineState *ms = MACHINE(qdev_get_machine()); +@@ -193,6 +209,34 @@ static void sclp_execute(SCLPDevice *sclp, SCCB *sccb, uint32_t code) + } + } + ++/* ++ * We only need the address to have something valid for the ++ * service_interrupt call. ++ */ ++#define SCLP_PV_DUMMY_ADDR 0x4000 ++int sclp_service_call_protected(CPUS390XState *env, uint64_t sccb, ++ uint32_t code) ++{ ++ SCLPDevice *sclp = get_sclp_device(); ++ SCLPDeviceClass *sclp_c = SCLP_GET_CLASS(sclp); ++ SCCB work_sccb; ++ hwaddr sccb_len = sizeof(SCCB); ++ ++ s390_cpu_pv_mem_read(env_archcpu(env), 0, &work_sccb, sccb_len); ++ ++ if (!sclp_command_code_valid(code)) { ++ work_sccb.h.response_code = cpu_to_be16(SCLP_RC_INVALID_SCLP_COMMAND); ++ goto out_write; ++ } ++ ++ sclp_c->execute(sclp, &work_sccb, code); ++out_write: ++ s390_cpu_pv_mem_write(env_archcpu(env), 0, &work_sccb, ++ be16_to_cpu(work_sccb.h.length)); ++ sclp_c->service_interrupt(sclp, SCLP_PV_DUMMY_ADDR); ++ return 0; ++} ++ + int sclp_service_call(CPUS390XState *env, uint64_t sccb, uint32_t code) + { + SCLPDevice *sclp = get_sclp_device(); +@@ -230,17 +274,7 @@ int sclp_service_call(CPUS390XState *env, uint64_t sccb, uint32_t code) + goto out; + } + +- switch (code & SCLP_CMD_CODE_MASK) { +- case SCLP_CMDW_READ_SCP_INFO: +- case SCLP_CMDW_READ_SCP_INFO_FORCED: +- case SCLP_CMDW_READ_CPU_INFO: +- case SCLP_CMDW_CONFIGURE_IOA: +- case SCLP_CMDW_DECONFIGURE_IOA: +- case SCLP_CMD_READ_EVENT_DATA: +- case SCLP_CMD_WRITE_EVENT_DATA: +- case SCLP_CMD_WRITE_EVENT_MASK: +- break; +- default: ++ if (!sclp_command_code_valid(code)) { + work_sccb.h.response_code = cpu_to_be16(SCLP_RC_INVALID_SCLP_COMMAND); + goto out_write; + } +diff --git a/include/hw/s390x/sclp.h b/include/hw/s390x/sclp.h +index c54413b78c..c0a3faa37d 100644 +--- a/include/hw/s390x/sclp.h ++++ b/include/hw/s390x/sclp.h +@@ -217,5 +217,7 @@ void s390_sclp_init(void); + void sclp_service_interrupt(uint32_t sccb); + void raise_irq_cpu_hotplug(void); + int sclp_service_call(CPUS390XState *env, uint64_t sccb, uint32_t code); ++int sclp_service_call_protected(CPUS390XState *env, uint64_t sccb, ++ uint32_t code); + + #endif +diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c +index 6809a5ac40..56fe60c49c 100644 +--- a/target/s390x/kvm.c ++++ b/target/s390x/kvm.c +@@ -1230,12 +1230,27 @@ static void kvm_sclp_service_call(S390CPU *cpu, struct kvm_run *run, + sccb = env->regs[ipbh0 & 0xf]; + code = env->regs[(ipbh0 & 0xf0) >> 4]; + +- r = sclp_service_call(env, sccb, code); +- if (r < 0) { +- kvm_s390_program_interrupt(cpu, -r); +- return; ++ switch (run->s390_sieic.icptcode) { ++ case ICPT_PV_INSTR_NOTIFICATION: ++ g_assert(s390_is_pv()); ++ /* The notification intercepts are currently handled by KVM */ ++ error_report("unexpected SCLP PV notification"); ++ exit(1); ++ break; ++ case ICPT_PV_INSTR: ++ g_assert(s390_is_pv()); ++ sclp_service_call_protected(env, sccb, code); ++ /* Setting the CC is done by the Ultravisor. */ ++ break; ++ case ICPT_INSTRUCTION: ++ g_assert(!s390_is_pv()); ++ r = sclp_service_call(env, sccb, code); ++ if (r < 0) { ++ kvm_s390_program_interrupt(cpu, -r); ++ return; ++ } ++ setcc(cpu, r); + } +- setcc(cpu, r); + } + + static int handle_b2(S390CPU *cpu, struct kvm_run *run, uint8_t ipa1) +-- +2.27.0 + diff --git a/SOURCES/kvm-s390x-protvirt-Set-guest-IPL-PSW.patch b/SOURCES/kvm-s390x-protvirt-Set-guest-IPL-PSW.patch new file mode 100644 index 0000000..ef246c7 --- /dev/null +++ b/SOURCES/kvm-s390x-protvirt-Set-guest-IPL-PSW.patch @@ -0,0 +1,75 @@ +From d738b4336c79be68b6040f73427e089f46957728 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 29 May 2020 05:54:11 -0400 +Subject: [PATCH 29/42] s390x: protvirt: Set guest IPL PSW + +RH-Author: Thomas Huth +Message-id: <20200529055420.16855-30-thuth@redhat.com> +Patchwork-id: 97049 +O-Subject: [RHEL-8.3.0 qemu-kvm PATCH v2 29/38] s390x: protvirt: Set guest IPL PSW +Bugzilla: 1828317 +RH-Acked-by: Claudio Imbrenda +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand + +From: Janosch Frank + +Handling of CPU reset and setting of the IPL psw from guest storage at +offset 0 is done by a Ultravisor call. Let's only fetch it if +necessary. + +Signed-off-by: Janosch Frank +Reviewed-by: Thomas Huth +Reviewed-by: David Hildenbrand +Reviewed-by: Christian Borntraeger +Reviewed-by: Claudio Imbrenda +Reviewed-by: Cornelia Huck +Message-Id: <20200319131921.2367-11-frankja@linux.ibm.com> +Signed-off-by: Cornelia Huck +(cherry picked from commit 59181010a2ff82c3a97e9b5768ee87c38e4815f1) +Signed-off-by: Danilo C. L. de Paula +--- + target/s390x/cpu.c | 26 +++++++++++++++++--------- + 1 file changed, 17 insertions(+), 9 deletions(-) + +diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c +index 8f38cd8e6f..371b91b2d7 100644 +--- a/target/s390x/cpu.c ++++ b/target/s390x/cpu.c +@@ -77,16 +77,24 @@ static bool s390_cpu_has_work(CPUState *cs) + static void s390_cpu_load_normal(CPUState *s) + { + S390CPU *cpu = S390_CPU(s); +- uint64_t spsw = ldq_phys(s->as, 0); +- +- cpu->env.psw.mask = spsw & PSW_MASK_SHORT_CTRL; +- /* +- * Invert short psw indication, so SIE will report a specification +- * exception if it was not set. +- */ +- cpu->env.psw.mask ^= PSW_MASK_SHORTPSW; +- cpu->env.psw.addr = spsw & PSW_MASK_SHORT_ADDR; ++ uint64_t spsw; + ++ if (!s390_is_pv()) { ++ spsw = ldq_phys(s->as, 0); ++ cpu->env.psw.mask = spsw & PSW_MASK_SHORT_CTRL; ++ /* ++ * Invert short psw indication, so SIE will report a specification ++ * exception if it was not set. ++ */ ++ cpu->env.psw.mask ^= PSW_MASK_SHORTPSW; ++ cpu->env.psw.addr = spsw & PSW_MASK_SHORT_ADDR; ++ } else { ++ /* ++ * Firmware requires us to set the load state before we set ++ * the cpu to operating on protected guests. ++ */ ++ s390_cpu_set_state(S390_CPU_STATE_LOAD, cpu); ++ } + s390_cpu_set_state(S390_CPU_STATE_OPERATING, cpu); + } + #endif +-- +2.27.0 + diff --git a/SOURCES/kvm-s390x-protvirt-Support-unpack-facility.patch b/SOURCES/kvm-s390x-protvirt-Support-unpack-facility.patch new file mode 100644 index 0000000..204de2a --- /dev/null +++ b/SOURCES/kvm-s390x-protvirt-Support-unpack-facility.patch @@ -0,0 +1,886 @@ +From e6474080e3816e82e87c545a3d22db77c55ab053 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 29 May 2020 05:54:04 -0400 +Subject: [PATCH 22/42] s390x: protvirt: Support unpack facility + +RH-Author: Thomas Huth +Message-id: <20200529055420.16855-23-thuth@redhat.com> +Patchwork-id: 97045 +O-Subject: [RHEL-8.3.0 qemu-kvm PATCH v2 22/38] s390x: protvirt: Support unpack facility +Bugzilla: 1828317 +RH-Acked-by: Claudio Imbrenda +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand + +From: Janosch Frank + +The unpack facility provides the means to setup a protected guest. A +protected guest cannot be introspected by the hypervisor or any +user/administrator of the machine it is running on. + +Protected guests are encrypted at rest and need a special boot +mechanism via diag308 subcode 8 and 10. + +Code 8 sets the PV specific IPLB which is retained separately from +those set via code 5. + +Code 10 is used to unpack the VM into protected memory, verify its +integrity and start it. + +Signed-off-by: Janosch Frank +Co-developed-by: Christian Borntraeger [Changes +to machine] +Reviewed-by: David Hildenbrand +Reviewed-by: Claudio Imbrenda +Reviewed-by: Cornelia Huck +Message-Id: <20200323083606.24520-1-frankja@linux.ibm.com> +[CH: fixed up KVM_PV_VM_ -> KVM_PV_] +Signed-off-by: Cornelia Huck +(cherry picked from commit c3347ed0d2ee42a7dcf7bfe7f9c3884a9596727a) +Signed-off-by: Danilo C. L. de Paula +--- + MAINTAINERS | 2 + + hw/s390x/Makefile.objs | 1 + + hw/s390x/ipl.c | 59 +++++++++++++- + hw/s390x/ipl.h | 91 ++++++++++++++++++++- + hw/s390x/pv.c | 98 +++++++++++++++++++++++ + hw/s390x/s390-virtio-ccw.c | 119 +++++++++++++++++++++++++++- + include/hw/s390x/pv.h | 55 +++++++++++++ + include/hw/s390x/s390-virtio-ccw.h | 1 + + target/s390x/cpu.c | 1 + + target/s390x/cpu_features_def.inc.h | 1 + + target/s390x/diag.c | 39 ++++++++- + target/s390x/kvm-stub.c | 5 ++ + target/s390x/kvm.c | 5 ++ + target/s390x/kvm_s390x.h | 1 + + 14 files changed, 468 insertions(+), 10 deletions(-) + create mode 100644 hw/s390x/pv.c + create mode 100644 include/hw/s390x/pv.h + +diff --git a/MAINTAINERS b/MAINTAINERS +index 49d5d44edc..2742c95575 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -385,6 +385,8 @@ F: target/s390x/machine.c + F: target/s390x/sigp.c + F: target/s390x/cpu_features*.[ch] + F: target/s390x/cpu_models.[ch] ++F: hw/s390x/pv.c ++F: include/hw/s390x/pv.h + F: hw/intc/s390_flic.c + F: hw/intc/s390_flic_kvm.c + F: include/hw/s390x/s390_flic.h +diff --git a/hw/s390x/Makefile.objs b/hw/s390x/Makefile.objs +index e02ed80b68..a46a1c7894 100644 +--- a/hw/s390x/Makefile.objs ++++ b/hw/s390x/Makefile.objs +@@ -31,6 +31,7 @@ obj-y += tod-qemu.o + obj-$(CONFIG_KVM) += tod-kvm.o + obj-$(CONFIG_KVM) += s390-skeys-kvm.o + obj-$(CONFIG_KVM) += s390-stattrib-kvm.o ++obj-$(CONFIG_KVM) += pv.o + obj-y += s390-ccw.o + obj-y += ap-device.o + obj-y += ap-bridge.o +diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c +index fa0409dc23..586d95b5b6 100644 +--- a/hw/s390x/ipl.c ++++ b/hw/s390x/ipl.c +@@ -1,10 +1,11 @@ + /* + * bootloader support + * +- * Copyright IBM, Corp. 2012 ++ * Copyright IBM, Corp. 2012, 2020 + * + * Authors: + * Christian Borntraeger ++ * Janosch Frank + * + * 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. +@@ -27,6 +28,7 @@ + #include "hw/s390x/vfio-ccw.h" + #include "hw/s390x/css.h" + #include "hw/s390x/ebcdic.h" ++#include "hw/s390x/pv.h" + #include "ipl.h" + #include "qemu/error-report.h" + #include "qemu/config-file.h" +@@ -557,12 +559,31 @@ void s390_ipl_update_diag308(IplParameterBlock *iplb) + { + S390IPLState *ipl = get_ipl_device(); + +- ipl->iplb = *iplb; +- ipl->iplb_valid = true; ++ /* ++ * The IPLB set and retrieved by subcodes 8/9 is completely ++ * separate from the one managed via subcodes 5/6. ++ */ ++ if (iplb->pbt == S390_IPL_TYPE_PV) { ++ ipl->iplb_pv = *iplb; ++ ipl->iplb_valid_pv = true; ++ } else { ++ ipl->iplb = *iplb; ++ ipl->iplb_valid = true; ++ } + ipl->netboot = is_virtio_net_device(iplb); + update_machine_ipl_properties(iplb); + } + ++IplParameterBlock *s390_ipl_get_iplb_pv(void) ++{ ++ S390IPLState *ipl = get_ipl_device(); ++ ++ if (!ipl->iplb_valid_pv) { ++ return NULL; ++ } ++ return &ipl->iplb_pv; ++} ++ + IplParameterBlock *s390_ipl_get_iplb(void) + { + S390IPLState *ipl = get_ipl_device(); +@@ -651,6 +672,38 @@ static void s390_ipl_prepare_qipl(S390CPU *cpu) + cpu_physical_memory_unmap(addr, len, 1, len); + } + ++int s390_ipl_prepare_pv_header(void) ++{ ++ IplParameterBlock *ipib = s390_ipl_get_iplb_pv(); ++ IPLBlockPV *ipib_pv = &ipib->pv; ++ void *hdr = g_malloc(ipib_pv->pv_header_len); ++ int rc; ++ ++ cpu_physical_memory_read(ipib_pv->pv_header_addr, hdr, ++ ipib_pv->pv_header_len); ++ rc = s390_pv_set_sec_parms((uintptr_t)hdr, ++ ipib_pv->pv_header_len); ++ g_free(hdr); ++ return rc; ++} ++ ++int s390_ipl_pv_unpack(void) ++{ ++ IplParameterBlock *ipib = s390_ipl_get_iplb_pv(); ++ IPLBlockPV *ipib_pv = &ipib->pv; ++ int i, rc = 0; ++ ++ for (i = 0; i < ipib_pv->num_comp; i++) { ++ rc = s390_pv_unpack(ipib_pv->components[i].addr, ++ TARGET_PAGE_ALIGN(ipib_pv->components[i].size), ++ ipib_pv->components[i].tweak_pref); ++ if (rc) { ++ break; ++ } ++ } ++ return rc; ++} ++ + void s390_ipl_prepare_cpu(S390CPU *cpu) + { + S390IPLState *ipl = get_ipl_device(); +diff --git a/hw/s390x/ipl.h b/hw/s390x/ipl.h +index a5665e6bfd..89b3044d7a 100644 +--- a/hw/s390x/ipl.h ++++ b/hw/s390x/ipl.h +@@ -1,8 +1,9 @@ + /* + * s390 IPL device + * +- * Copyright 2015 IBM Corp. ++ * Copyright 2015, 2020 IBM Corp. + * Author(s): Zhang Fan ++ * Janosch Frank + * + * 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 +@@ -15,6 +16,24 @@ + #include "cpu.h" + #include "hw/qdev-core.h" + ++struct IPLBlockPVComp { ++ uint64_t tweak_pref; ++ uint64_t addr; ++ uint64_t size; ++} QEMU_PACKED; ++typedef struct IPLBlockPVComp IPLBlockPVComp; ++ ++struct IPLBlockPV { ++ uint8_t reserved18[87]; /* 0x18 */ ++ uint8_t version; /* 0x6f */ ++ uint32_t reserved70; /* 0x70 */ ++ uint32_t num_comp; /* 0x74 */ ++ uint64_t pv_header_addr; /* 0x78 */ ++ uint64_t pv_header_len; /* 0x80 */ ++ struct IPLBlockPVComp components[]; ++} QEMU_PACKED; ++typedef struct IPLBlockPV IPLBlockPV; ++ + struct IplBlockCcw { + uint8_t reserved0[85]; + uint8_t ssid; +@@ -71,6 +90,7 @@ union IplParameterBlock { + union { + IplBlockCcw ccw; + IplBlockFcp fcp; ++ IPLBlockPV pv; + IplBlockQemuScsi scsi; + }; + } QEMU_PACKED; +@@ -85,8 +105,11 @@ typedef union IplParameterBlock IplParameterBlock; + + int s390_ipl_set_loadparm(uint8_t *loadparm); + void s390_ipl_update_diag308(IplParameterBlock *iplb); ++int s390_ipl_prepare_pv_header(void); ++int s390_ipl_pv_unpack(void); + void s390_ipl_prepare_cpu(S390CPU *cpu); + IplParameterBlock *s390_ipl_get_iplb(void); ++IplParameterBlock *s390_ipl_get_iplb_pv(void); + + enum s390_reset { + /* default is a reset not triggered by a CPU e.g. issued by QMP */ +@@ -94,6 +117,7 @@ enum s390_reset { + S390_RESET_REIPL, + S390_RESET_MODIFIED_CLEAR, + S390_RESET_LOAD_NORMAL, ++ S390_RESET_PV, + }; + void s390_ipl_reset_request(CPUState *cs, enum s390_reset reset_type); + void s390_ipl_get_reset_request(CPUState **cs, enum s390_reset *reset_type); +@@ -133,6 +157,7 @@ struct S390IPLState { + /*< private >*/ + DeviceState parent_obj; + IplParameterBlock iplb; ++ IplParameterBlock iplb_pv; + QemuIplParameters qipl; + uint64_t start_addr; + uint64_t compat_start_addr; +@@ -140,6 +165,7 @@ struct S390IPLState { + uint64_t compat_bios_start_addr; + bool enforce_bios; + bool iplb_valid; ++ bool iplb_valid_pv; + bool netboot; + /* reset related properties don't have to be migrated or reset */ + enum s390_reset reset_type; +@@ -162,6 +188,8 @@ QEMU_BUILD_BUG_MSG(offsetof(S390IPLState, iplb) & 3, "alignment of iplb wrong"); + #define DIAG_308_RC_OK 0x0001 + #define DIAG_308_RC_NO_CONF 0x0102 + #define DIAG_308_RC_INVALID 0x0402 ++#define DIAG_308_RC_NO_PV_CONF 0x0902 ++#define DIAG_308_RC_INVAL_FOR_PV 0x0a02 + + #define DIAG308_RESET_MOD_CLR 0 + #define DIAG308_RESET_LOAD_NORM 1 +@@ -169,12 +197,17 @@ QEMU_BUILD_BUG_MSG(offsetof(S390IPLState, iplb) & 3, "alignment of iplb wrong"); + #define DIAG308_LOAD_NORMAL_DUMP 4 + #define DIAG308_SET 5 + #define DIAG308_STORE 6 ++#define DIAG308_PV_SET 8 ++#define DIAG308_PV_STORE 9 ++#define DIAG308_PV_START 10 + + #define S390_IPL_TYPE_FCP 0x00 + #define S390_IPL_TYPE_CCW 0x02 ++#define S390_IPL_TYPE_PV 0x05 + #define S390_IPL_TYPE_QEMU_SCSI 0xff + + #define S390_IPLB_HEADER_LEN 8 ++#define S390_IPLB_MIN_PV_LEN 148 + #define S390_IPLB_MIN_CCW_LEN 200 + #define S390_IPLB_MIN_FCP_LEN 384 + #define S390_IPLB_MIN_QEMU_SCSI_LEN 200 +@@ -184,6 +217,62 @@ static inline bool iplb_valid_len(IplParameterBlock *iplb) + return be32_to_cpu(iplb->len) <= sizeof(IplParameterBlock); + } + ++static inline bool ipl_valid_pv_components(IplParameterBlock *iplb) ++{ ++ IPLBlockPV *ipib_pv = &iplb->pv; ++ int i; ++ ++ if (ipib_pv->num_comp == 0) { ++ return false; ++ } ++ ++ for (i = 0; i < ipib_pv->num_comp; i++) { ++ /* Addr must be 4k aligned */ ++ if (ipib_pv->components[i].addr & ~TARGET_PAGE_MASK) { ++ return false; ++ } ++ ++ /* Tweak prefix is monotonically increasing with each component */ ++ if (i < ipib_pv->num_comp - 1 && ++ ipib_pv->components[i].tweak_pref >= ++ ipib_pv->components[i + 1].tweak_pref) { ++ return false; ++ } ++ } ++ return true; ++} ++ ++static inline bool ipl_valid_pv_header(IplParameterBlock *iplb) ++{ ++ IPLBlockPV *ipib_pv = &iplb->pv; ++ ++ if (ipib_pv->pv_header_len > 2 * TARGET_PAGE_SIZE) { ++ return false; ++ } ++ ++ if (!address_space_access_valid(&address_space_memory, ++ ipib_pv->pv_header_addr, ++ ipib_pv->pv_header_len, ++ false, ++ MEMTXATTRS_UNSPECIFIED)) { ++ return false; ++ } ++ ++ return true; ++} ++ ++static inline bool iplb_valid_pv(IplParameterBlock *iplb) ++{ ++ if (iplb->pbt != S390_IPL_TYPE_PV || ++ be32_to_cpu(iplb->len) < S390_IPLB_MIN_PV_LEN) { ++ return false; ++ } ++ if (!ipl_valid_pv_header(iplb)) { ++ return false; ++ } ++ return ipl_valid_pv_components(iplb); ++} ++ + static inline bool iplb_valid(IplParameterBlock *iplb) + { + switch (iplb->pbt) { +diff --git a/hw/s390x/pv.c b/hw/s390x/pv.c +new file mode 100644 +index 0000000000..a40a844806 +--- /dev/null ++++ b/hw/s390x/pv.c +@@ -0,0 +1,98 @@ ++/* ++ * Protected Virtualization functions ++ * ++ * Copyright IBM Corp. 2020 ++ * Author(s): ++ * Janosch Frank ++ * ++ * 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 "qemu/osdep.h" ++ ++#include ++ ++#include "qemu/error-report.h" ++#include "sysemu/kvm.h" ++#include "hw/s390x/pv.h" ++ ++static int __s390_pv_cmd(uint32_t cmd, const char *cmdname, void *data) ++{ ++ struct kvm_pv_cmd pv_cmd = { ++ .cmd = cmd, ++ .data = (uint64_t)data, ++ }; ++ int rc = kvm_vm_ioctl(kvm_state, KVM_S390_PV_COMMAND, &pv_cmd); ++ ++ if (rc) { ++ error_report("KVM PV command %d (%s) failed: header rc %x rrc %x " ++ "IOCTL rc: %d", cmd, cmdname, pv_cmd.rc, pv_cmd.rrc, ++ rc); ++ } ++ return rc; ++} ++ ++/* ++ * This macro lets us pass the command as a string to the function so ++ * we can print it on an error. ++ */ ++#define s390_pv_cmd(cmd, data) __s390_pv_cmd(cmd, #cmd, data); ++#define s390_pv_cmd_exit(cmd, data) \ ++{ \ ++ int rc; \ ++ \ ++ rc = __s390_pv_cmd(cmd, #cmd, data);\ ++ if (rc) { \ ++ exit(1); \ ++ } \ ++} ++ ++int s390_pv_vm_enable(void) ++{ ++ return s390_pv_cmd(KVM_PV_ENABLE, NULL); ++} ++ ++void s390_pv_vm_disable(void) ++{ ++ s390_pv_cmd_exit(KVM_PV_DISABLE, NULL); ++} ++ ++int s390_pv_set_sec_parms(uint64_t origin, uint64_t length) ++{ ++ struct kvm_s390_pv_sec_parm args = { ++ .origin = origin, ++ .length = length, ++ }; ++ ++ return s390_pv_cmd(KVM_PV_SET_SEC_PARMS, &args); ++} ++ ++/* ++ * Called for each component in the SE type IPL parameter block 0. ++ */ ++int s390_pv_unpack(uint64_t addr, uint64_t size, uint64_t tweak) ++{ ++ struct kvm_s390_pv_unp args = { ++ .addr = addr, ++ .size = size, ++ .tweak = tweak, ++ }; ++ ++ return s390_pv_cmd(KVM_PV_UNPACK, &args); ++} ++ ++void s390_pv_perf_clear_reset(void) ++{ ++ s390_pv_cmd_exit(KVM_PV_PREP_RESET, NULL); ++} ++ ++int s390_pv_verify(void) ++{ ++ return s390_pv_cmd(KVM_PV_VERIFY, NULL); ++} ++ ++void s390_pv_unshare(void) ++{ ++ s390_pv_cmd_exit(KVM_PV_UNSHARE_ALL, NULL); ++} +diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c +index 4ea01c53c0..82da1d9ab5 100644 +--- a/hw/s390x/s390-virtio-ccw.c ++++ b/hw/s390x/s390-virtio-ccw.c +@@ -1,9 +1,10 @@ + /* + * virtio ccw machine + * +- * Copyright 2012 IBM Corp. ++ * Copyright 2012, 2020 IBM Corp. + * Copyright (c) 2009 Alexander Graf + * Author(s): Cornelia Huck ++ * Janosch Frank + * + * 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 +@@ -41,6 +42,8 @@ + #include "hw/qdev-properties.h" + #include "hw/s390x/tod.h" + #include "sysemu/sysemu.h" ++#include "hw/s390x/pv.h" ++#include + + S390CPU *s390_cpu_addr2state(uint16_t cpu_addr) + { +@@ -318,10 +321,78 @@ static inline void s390_do_cpu_ipl(CPUState *cs, run_on_cpu_data arg) + s390_cpu_set_state(S390_CPU_STATE_OPERATING, cpu); + } + ++static void s390_machine_unprotect(S390CcwMachineState *ms) ++{ ++ s390_pv_vm_disable(); ++ ms->pv = false; ++} ++ ++static int s390_machine_protect(S390CcwMachineState *ms) ++{ ++ int rc; ++ ++ /* Create SE VM */ ++ rc = s390_pv_vm_enable(); ++ if (rc) { ++ return rc; ++ } ++ ++ ms->pv = true; ++ ++ /* Set SE header and unpack */ ++ rc = s390_ipl_prepare_pv_header(); ++ if (rc) { ++ goto out_err; ++ } ++ ++ /* Decrypt image */ ++ rc = s390_ipl_pv_unpack(); ++ if (rc) { ++ goto out_err; ++ } ++ ++ /* Verify integrity */ ++ rc = s390_pv_verify(); ++ if (rc) { ++ goto out_err; ++ } ++ return rc; ++ ++out_err: ++ s390_machine_unprotect(ms); ++ return rc; ++} ++ ++static void s390_machine_inject_pv_error(CPUState *cs) ++{ ++ int r1 = (cs->kvm_run->s390_sieic.ipa & 0x00f0) >> 4; ++ CPUS390XState *env = &S390_CPU(cs)->env; ++ ++ /* Report that we are unable to enter protected mode */ ++ env->regs[r1 + 1] = DIAG_308_RC_INVAL_FOR_PV; ++} ++ ++static void s390_pv_prepare_reset(S390CcwMachineState *ms) ++{ ++ CPUState *cs; ++ ++ if (!s390_is_pv()) { ++ return; ++ } ++ /* Unsharing requires all cpus to be stopped */ ++ CPU_FOREACH(cs) { ++ s390_cpu_set_state(S390_CPU_STATE_STOPPED, S390_CPU(cs)); ++ } ++ s390_pv_unshare(); ++ s390_pv_perf_clear_reset(); ++} ++ + static void s390_machine_reset(MachineState *machine) + { ++ S390CcwMachineState *ms = S390_CCW_MACHINE(machine); + enum s390_reset reset_type; + CPUState *cs, *t; ++ S390CPU *cpu; + + /* get the reset parameters, reset them once done */ + s390_ipl_get_reset_request(&cs, &reset_type); +@@ -329,9 +400,15 @@ static void s390_machine_reset(MachineState *machine) + /* all CPUs are paused and synchronized at this point */ + s390_cmma_reset(); + ++ cpu = S390_CPU(cs); ++ + switch (reset_type) { + case S390_RESET_EXTERNAL: + case S390_RESET_REIPL: ++ if (s390_is_pv()) { ++ s390_machine_unprotect(ms); ++ } ++ + qemu_devices_reset(); + s390_crypto_reset(); + +@@ -339,22 +416,56 @@ static void s390_machine_reset(MachineState *machine) + run_on_cpu(cs, s390_do_cpu_ipl, RUN_ON_CPU_NULL); + break; + case S390_RESET_MODIFIED_CLEAR: ++ /* ++ * Susbsystem reset needs to be done before we unshare memory ++ * and lose access to VIRTIO structures in guest memory. ++ */ ++ subsystem_reset(); ++ s390_crypto_reset(); ++ s390_pv_prepare_reset(ms); + CPU_FOREACH(t) { + run_on_cpu(t, s390_do_cpu_full_reset, RUN_ON_CPU_NULL); + } +- subsystem_reset(); +- s390_crypto_reset(); + run_on_cpu(cs, s390_do_cpu_load_normal, RUN_ON_CPU_NULL); + break; + case S390_RESET_LOAD_NORMAL: ++ /* ++ * Susbsystem reset needs to be done before we unshare memory ++ * and lose access to VIRTIO structures in guest memory. ++ */ ++ subsystem_reset(); ++ s390_pv_prepare_reset(ms); + CPU_FOREACH(t) { + if (t == cs) { + continue; + } + run_on_cpu(t, s390_do_cpu_reset, RUN_ON_CPU_NULL); + } +- subsystem_reset(); + run_on_cpu(cs, s390_do_cpu_initial_reset, RUN_ON_CPU_NULL); ++ run_on_cpu(cs, s390_do_cpu_load_normal, RUN_ON_CPU_NULL); ++ break; ++ case S390_RESET_PV: /* Subcode 10 */ ++ subsystem_reset(); ++ s390_crypto_reset(); ++ ++ CPU_FOREACH(t) { ++ if (t == cs) { ++ continue; ++ } ++ run_on_cpu(t, s390_do_cpu_full_reset, RUN_ON_CPU_NULL); ++ } ++ run_on_cpu(cs, s390_do_cpu_reset, RUN_ON_CPU_NULL); ++ ++ if (s390_machine_protect(ms)) { ++ s390_machine_inject_pv_error(cs); ++ /* ++ * Continue after the diag308 so the guest knows something ++ * went wrong. ++ */ ++ s390_cpu_set_state(S390_CPU_STATE_OPERATING, cpu); ++ return; ++ } ++ + run_on_cpu(cs, s390_do_cpu_load_normal, RUN_ON_CPU_NULL); + break; + default: +diff --git a/include/hw/s390x/pv.h b/include/hw/s390x/pv.h +new file mode 100644 +index 0000000000..c6cb360f2f +--- /dev/null ++++ b/include/hw/s390x/pv.h +@@ -0,0 +1,55 @@ ++/* ++ * Protected Virtualization header ++ * ++ * Copyright IBM Corp. 2020 ++ * Author(s): ++ * Janosch Frank ++ * ++ * 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 HW_S390_PV_H ++#define HW_S390_PV_H ++ ++#ifdef CONFIG_KVM ++#include "hw/s390x/s390-virtio-ccw.h" ++ ++static inline bool s390_is_pv(void) ++{ ++ static S390CcwMachineState *ccw; ++ Object *obj; ++ ++ if (ccw) { ++ return ccw->pv; ++ } ++ ++ /* we have to bail out for the "none" machine */ ++ obj = object_dynamic_cast(qdev_get_machine(), ++ TYPE_S390_CCW_MACHINE); ++ if (!obj) { ++ return false; ++ } ++ ccw = S390_CCW_MACHINE(obj); ++ return ccw->pv; ++} ++ ++int s390_pv_vm_enable(void); ++void s390_pv_vm_disable(void); ++int s390_pv_set_sec_parms(uint64_t origin, uint64_t length); ++int s390_pv_unpack(uint64_t addr, uint64_t size, uint64_t tweak); ++void s390_pv_perf_clear_reset(void); ++int s390_pv_verify(void); ++void s390_pv_unshare(void); ++#else /* CONFIG_KVM */ ++static inline bool s390_is_pv(void) { return false; } ++static inline int s390_pv_vm_enable(void) { return 0; } ++static inline void s390_pv_vm_disable(void) {} ++static inline int s390_pv_set_sec_parms(uint64_t origin, uint64_t length) { return 0; } ++static inline int s390_pv_unpack(uint64_t addr, uint64_t size, uint64_t tweak) { return 0; } ++static inline void s390_pv_perf_clear_reset(void) {} ++static inline int s390_pv_verify(void) { return 0; } ++static inline void s390_pv_unshare(void) {} ++#endif /* CONFIG_KVM */ ++ ++#endif /* HW_S390_PV_H */ +diff --git a/include/hw/s390x/s390-virtio-ccw.h b/include/hw/s390x/s390-virtio-ccw.h +index 8aa27199c9..cd1dccc6e3 100644 +--- a/include/hw/s390x/s390-virtio-ccw.h ++++ b/include/hw/s390x/s390-virtio-ccw.h +@@ -28,6 +28,7 @@ typedef struct S390CcwMachineState { + /*< public >*/ + bool aes_key_wrap; + bool dea_key_wrap; ++ bool pv; + uint8_t loadparm[8]; + } S390CcwMachineState; + +diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c +index c0dd502b84..8f38cd8e6f 100644 +--- a/target/s390x/cpu.c ++++ b/target/s390x/cpu.c +@@ -37,6 +37,7 @@ + #include "sysemu/hw_accel.h" + #include "hw/qdev-properties.h" + #ifndef CONFIG_USER_ONLY ++#include "hw/s390x/pv.h" + #include "hw/boards.h" + #include "sysemu/arch_init.h" + #include "sysemu/sysemu.h" +diff --git a/target/s390x/cpu_features_def.inc.h b/target/s390x/cpu_features_def.inc.h +index 31dff0d84e..60db28351d 100644 +--- a/target/s390x/cpu_features_def.inc.h ++++ b/target/s390x/cpu_features_def.inc.h +@@ -107,6 +107,7 @@ DEF_FEAT(DEFLATE_BASE, "deflate-base", STFL, 151, "Deflate-conversion facility ( + 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") ++DEF_FEAT(UNPACK, "unpack", STFL, 161, "Unpack 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") +diff --git a/target/s390x/diag.c b/target/s390x/diag.c +index 8aba6341f9..b2cbefb8cf 100644 +--- a/target/s390x/diag.c ++++ b/target/s390x/diag.c +@@ -20,6 +20,8 @@ + #include "sysemu/cpus.h" + #include "hw/s390x/ipl.h" + #include "hw/s390x/s390-virtio-ccw.h" ++#include "hw/s390x/pv.h" ++#include "kvm_s390x.h" + + int handle_diag_288(CPUS390XState *env, uint64_t r1, uint64_t r3) + { +@@ -52,6 +54,10 @@ int handle_diag_288(CPUS390XState *env, uint64_t r1, uint64_t r3) + static int diag308_parm_check(CPUS390XState *env, uint64_t r1, uint64_t addr, + uintptr_t ra, bool write) + { ++ /* Handled by the Ultravisor */ ++ if (s390_is_pv()) { ++ return 0; ++ } + if ((r1 & 1) || (addr & ~TARGET_PAGE_MASK)) { + s390_program_interrupt(env, PGM_SPECIFICATION, ra); + return -1; +@@ -67,6 +73,7 @@ static int diag308_parm_check(CPUS390XState *env, uint64_t r1, uint64_t addr, + + void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3, uintptr_t ra) + { ++ bool valid; + CPUState *cs = env_cpu(env); + uint64_t addr = env->regs[r1]; + uint64_t subcode = env->regs[r3]; +@@ -82,6 +89,11 @@ void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3, uintptr_t ra) + return; + } + ++ if (subcode >= DIAG308_PV_SET && !s390_has_feat(S390_FEAT_UNPACK)) { ++ s390_program_interrupt(env, PGM_SPECIFICATION, ra); ++ return; ++ } ++ + switch (subcode) { + case DIAG308_RESET_MOD_CLR: + s390_ipl_reset_request(cs, S390_RESET_MODIFIED_CLEAR); +@@ -94,6 +106,7 @@ void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3, uintptr_t ra) + s390_ipl_reset_request(cs, S390_RESET_REIPL); + break; + case DIAG308_SET: ++ case DIAG308_PV_SET: + if (diag308_parm_check(env, r1, addr, ra, false)) { + return; + } +@@ -106,7 +119,8 @@ void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3, uintptr_t ra) + + cpu_physical_memory_read(addr, iplb, be32_to_cpu(iplb->len)); + +- if (!iplb_valid(iplb)) { ++ valid = subcode == DIAG308_PV_SET ? iplb_valid_pv(iplb) : iplb_valid(iplb); ++ if (!valid) { + env->regs[r1 + 1] = DIAG_308_RC_INVALID; + goto out; + } +@@ -117,10 +131,15 @@ out: + g_free(iplb); + return; + case DIAG308_STORE: ++ case DIAG308_PV_STORE: + if (diag308_parm_check(env, r1, addr, ra, true)) { + return; + } +- iplb = s390_ipl_get_iplb(); ++ if (subcode == DIAG308_PV_STORE) { ++ iplb = s390_ipl_get_iplb_pv(); ++ } else { ++ iplb = s390_ipl_get_iplb(); ++ } + if (iplb) { + cpu_physical_memory_write(addr, iplb, be32_to_cpu(iplb->len)); + env->regs[r1 + 1] = DIAG_308_RC_OK; +@@ -128,6 +147,22 @@ out: + env->regs[r1 + 1] = DIAG_308_RC_NO_CONF; + } + return; ++ case DIAG308_PV_START: ++ iplb = s390_ipl_get_iplb_pv(); ++ if (!iplb) { ++ env->regs[r1 + 1] = DIAG_308_RC_NO_PV_CONF; ++ return; ++ } ++ ++ if (kvm_s390_get_hpage_1m()) { ++ error_report("Protected VMs can currently not be backed with " ++ "huge pages"); ++ env->regs[r1 + 1] = DIAG_308_RC_INVAL_FOR_PV; ++ return; ++ } ++ ++ s390_ipl_reset_request(cs, S390_RESET_PV); ++ break; + default: + s390_program_interrupt(env, PGM_SPECIFICATION, ra); + break; +diff --git a/target/s390x/kvm-stub.c b/target/s390x/kvm-stub.c +index c4cd497f85..aa185017a2 100644 +--- a/target/s390x/kvm-stub.c ++++ b/target/s390x/kvm-stub.c +@@ -39,6 +39,11 @@ int kvm_s390_vcpu_interrupt_post_load(S390CPU *cpu) + return 0; + } + ++int kvm_s390_get_hpage_1m(void) ++{ ++ return 0; ++} ++ + int kvm_s390_get_ri(void) + { + return 0; +diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c +index 75d82af6fc..9a0be13959 100644 +--- a/target/s390x/kvm.c ++++ b/target/s390x/kvm.c +@@ -321,6 +321,11 @@ void kvm_s390_set_max_pagesize(uint64_t pagesize, Error **errp) + cap_hpage_1m = 1; + } + ++int kvm_s390_get_hpage_1m(void) ++{ ++ return cap_hpage_1m; ++} ++ + static void ccw_machine_class_foreach(ObjectClass *oc, void *opaque) + { + MachineClass *mc = MACHINE_CLASS(oc); +diff --git a/target/s390x/kvm_s390x.h b/target/s390x/kvm_s390x.h +index 0b21789796..dea813f450 100644 +--- a/target/s390x/kvm_s390x.h ++++ b/target/s390x/kvm_s390x.h +@@ -23,6 +23,7 @@ void kvm_s390_program_interrupt(S390CPU *cpu, uint16_t code); + int kvm_s390_set_cpu_state(S390CPU *cpu, uint8_t cpu_state); + void kvm_s390_vcpu_interrupt_pre_save(S390CPU *cpu); + int kvm_s390_vcpu_interrupt_post_load(S390CPU *cpu); ++int kvm_s390_get_hpage_1m(void); + int kvm_s390_get_ri(void); + int kvm_s390_get_gs(void); + int kvm_s390_get_clock(uint8_t *tod_high, uint64_t *tod_clock); +-- +2.27.0 + diff --git a/SOURCES/kvm-s390x-pv-Fix-KVM_PV_PREP_RESET-command-wrapper-name.patch b/SOURCES/kvm-s390x-pv-Fix-KVM_PV_PREP_RESET-command-wrapper-name.patch new file mode 100644 index 0000000..764ceb1 --- /dev/null +++ b/SOURCES/kvm-s390x-pv-Fix-KVM_PV_PREP_RESET-command-wrapper-name.patch @@ -0,0 +1,92 @@ +From f3594f3d84a7442c194b1b9fd288e7414540ec0f Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 29 May 2020 05:54:20 -0400 +Subject: [PATCH 38/42] s390x: pv: Fix KVM_PV_PREP_RESET command wrapper name +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Thomas Huth +Message-id: <20200529055420.16855-39-thuth@redhat.com> +Patchwork-id: 97051 +O-Subject: [RHEL-8.3.0 qemu-kvm PATCH v2 38/38] s390x: pv: Fix KVM_PV_PREP_RESET command wrapper name +Bugzilla: 1828317 +RH-Acked-by: Claudio Imbrenda +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand + +From: Janosch Frank + +Upstream: Merged in https://github.com/cohuck/qemu/tree/s390-next + +s390_pv_perf_clear_reset() is not a very helpful name since that +function needs to be called for a normal and a clear reset via +diag308. + +Let's instead name it s390_pv_prep_reset() which reflects the purpose +of the function a bit better. + +Signed-off-by: Janosch Frank +Reviewed-by: David Hildenbrand +Message-Id: <20200505124159.24099-1-frankja@linux.ibm.com> +Signed-off-by: Cornelia Huck +(cherry picked from commit f9628f3f6db341751002dac3be18610fa77c01ad) +Signed-off-by: Danilo C. L. de Paula +--- + hw/s390x/pv.c | 2 +- + hw/s390x/s390-virtio-ccw.c | 2 +- + include/hw/s390x/pv.h | 4 ++-- + 3 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/hw/s390x/pv.c b/hw/s390x/pv.c +index f11868e865..ab3a2482aa 100644 +--- a/hw/s390x/pv.c ++++ b/hw/s390x/pv.c +@@ -88,7 +88,7 @@ int s390_pv_unpack(uint64_t addr, uint64_t size, uint64_t tweak) + return s390_pv_cmd(KVM_PV_UNPACK, &args); + } + +-void s390_pv_perf_clear_reset(void) ++void s390_pv_prep_reset(void) + { + s390_pv_cmd_exit(KVM_PV_PREP_RESET, NULL); + } +diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c +index 07773a12b2..e6ed13b649 100644 +--- a/hw/s390x/s390-virtio-ccw.c ++++ b/hw/s390x/s390-virtio-ccw.c +@@ -402,7 +402,7 @@ static void s390_pv_prepare_reset(S390CcwMachineState *ms) + s390_cpu_set_state(S390_CPU_STATE_STOPPED, S390_CPU(cs)); + } + s390_pv_unshare(); +- s390_pv_perf_clear_reset(); ++ s390_pv_prep_reset(); + } + + static void s390_machine_reset(MachineState *machine) +diff --git a/include/hw/s390x/pv.h b/include/hw/s390x/pv.h +index 522ca6a04e..aee758bc2d 100644 +--- a/include/hw/s390x/pv.h ++++ b/include/hw/s390x/pv.h +@@ -39,7 +39,7 @@ int s390_pv_vm_enable(void); + void s390_pv_vm_disable(void); + int s390_pv_set_sec_parms(uint64_t origin, uint64_t length); + int s390_pv_unpack(uint64_t addr, uint64_t size, uint64_t tweak); +-void s390_pv_perf_clear_reset(void); ++void s390_pv_prep_reset(void); + int s390_pv_verify(void); + void s390_pv_unshare(void); + void s390_pv_inject_reset_error(CPUState *cs); +@@ -49,7 +49,7 @@ static inline int s390_pv_vm_enable(void) { return 0; } + static inline void s390_pv_vm_disable(void) {} + static inline int s390_pv_set_sec_parms(uint64_t origin, uint64_t length) { return 0; } + static inline int s390_pv_unpack(uint64_t addr, uint64_t size, uint64_t tweak) { return 0; } +-static inline void s390_pv_perf_clear_reset(void) {} ++static inline void s390_pv_prep_reset(void) {} + static inline int s390_pv_verify(void) { return 0; } + static inline void s390_pv_unshare(void) {} + static inline void s390_pv_inject_reset_error(CPUState *cs) {}; +-- +2.27.0 + diff --git a/SOURCES/kvm-s390x-pv-Retry-ioctls-on-EINTR.patch b/SOURCES/kvm-s390x-pv-Retry-ioctls-on-EINTR.patch new file mode 100644 index 0000000..65208c7 --- /dev/null +++ b/SOURCES/kvm-s390x-pv-Retry-ioctls-on-EINTR.patch @@ -0,0 +1,57 @@ +From 1678288d945906d83d7adae109b842080aebaf19 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 29 May 2020 05:54:18 -0400 +Subject: [PATCH 36/42] s390x/pv: Retry ioctls on -EINTR +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Thomas Huth +Message-id: <20200529055420.16855-37-thuth@redhat.com> +Patchwork-id: 97055 +O-Subject: [RHEL-8.3.0 qemu-kvm PATCH v2 36/38] s390x/pv: Retry ioctls on -EINTR +Bugzilla: 1828317 +RH-Acked-by: Claudio Imbrenda +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand + +From: Christian Borntraeger + +PV_ENABLE (and maybe others) might return -EINTR when a signal is +pending. See the Linux kernel patch "s390/gmap: return proper error code +on ksm unsharing" for details. Let us retry the ioctl in that case. + +Fixes: c3347ed0d2ee ("s390x: protvirt: Support unpack facility") +Reported-by: Marc Hartmayer +Acked-by: Janosch Frank +Tested-by: Marc Hartmayer +Signed-off-by: Christian Borntraeger +Message-Id: <20200327124616.34866-1-borntraeger@de.ibm.com> +Signed-off-by: Cornelia Huck +(cherry picked from commit e8d12a55f6d3e577455b02f15907c460578c689b) +Signed-off-by: Danilo C. L. de Paula +--- + hw/s390x/pv.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/hw/s390x/pv.c b/hw/s390x/pv.c +index a40a844806..cb0dce4a4f 100644 +--- a/hw/s390x/pv.c ++++ b/hw/s390x/pv.c +@@ -23,7 +23,11 @@ static int __s390_pv_cmd(uint32_t cmd, const char *cmdname, void *data) + .cmd = cmd, + .data = (uint64_t)data, + }; +- int rc = kvm_vm_ioctl(kvm_state, KVM_S390_PV_COMMAND, &pv_cmd); ++ int rc; ++ ++ do { ++ rc = kvm_vm_ioctl(kvm_state, KVM_S390_PV_COMMAND, &pv_cmd); ++ } while (rc == -EINTR); + + if (rc) { + error_report("KVM PV command %d (%s) failed: header rc %x rrc %x " +-- +2.27.0 + diff --git a/SOURCES/kvm-s390x-s390-virtio-ccw-Fix-build-on-systems-without-K.patch b/SOURCES/kvm-s390x-s390-virtio-ccw-Fix-build-on-systems-without-K.patch new file mode 100644 index 0000000..e78f4da --- /dev/null +++ b/SOURCES/kvm-s390x-s390-virtio-ccw-Fix-build-on-systems-without-K.patch @@ -0,0 +1,150 @@ +From 0db8d909a2f3c53d12b0ae12307965f9a8193dbc Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 29 May 2020 05:54:19 -0400 +Subject: [PATCH 37/42] s390x/s390-virtio-ccw: Fix build on systems without KVM +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Thomas Huth +Message-id: <20200529055420.16855-38-thuth@redhat.com> +Patchwork-id: 97047 +O-Subject: [RHEL-8.3.0 qemu-kvm PATCH v2 37/38] s390x/s390-virtio-ccw: Fix build on systems without KVM +Bugzilla: 1828317 +RH-Acked-by: Claudio Imbrenda +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand + +From: Christian Borntraeger + +linux/kvm.h is not available on all platforms. Let us move +s390_machine_inject_pv_error into pv.c as it uses KVM structures. +Also rename the function to s390_pv_inject_reset_error. + +While at it, ipl.h needs an include for "exec/address-spaces.h" +as it uses address_space_memory. + +Fixes: c3347ed0d2ee ("s390x: protvirt: Support unpack facility") +Reported-by: Bruce Rogers +Signed-off-by: Christian Borntraeger +Message-Id: <20200406100158.5940-2-borntraeger@de.ibm.com> +Reviewed-by: David Hildenbrand +Signed-off-by: Cornelia Huck +(cherry picked from commit fbc1384ccd48fa7c0c38f950adf7992a4fb6042e) +Signed-off-by: Danilo C. L. de Paula +--- + hw/s390x/ipl.h | 1 + + hw/s390x/pv.c | 11 +++++++++++ + hw/s390x/s390-virtio-ccw.c | 12 +----------- + include/hw/s390x/pv.h | 3 +++ + 4 files changed, 16 insertions(+), 11 deletions(-) + +diff --git a/hw/s390x/ipl.h b/hw/s390x/ipl.h +index 89b3044d7a..53cc9eb5ac 100644 +--- a/hw/s390x/ipl.h ++++ b/hw/s390x/ipl.h +@@ -14,6 +14,7 @@ + #define HW_S390_IPL_H + + #include "cpu.h" ++#include "exec/address-spaces.h" + #include "hw/qdev-core.h" + + struct IPLBlockPVComp { +diff --git a/hw/s390x/pv.c b/hw/s390x/pv.c +index cb0dce4a4f..f11868e865 100644 +--- a/hw/s390x/pv.c ++++ b/hw/s390x/pv.c +@@ -13,8 +13,10 @@ + + #include + ++#include "cpu.h" + #include "qemu/error-report.h" + #include "sysemu/kvm.h" ++#include "hw/s390x/ipl.h" + #include "hw/s390x/pv.h" + + static int __s390_pv_cmd(uint32_t cmd, const char *cmdname, void *data) +@@ -100,3 +102,12 @@ void s390_pv_unshare(void) + { + s390_pv_cmd_exit(KVM_PV_UNSHARE_ALL, NULL); + } ++ ++void s390_pv_inject_reset_error(CPUState *cs) ++{ ++ int r1 = (cs->kvm_run->s390_sieic.ipa & 0x00f0) >> 4; ++ CPUS390XState *env = &S390_CPU(cs)->env; ++ ++ /* Report that we are unable to enter protected mode */ ++ env->regs[r1 + 1] = DIAG_308_RC_INVAL_FOR_PV; ++} +diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c +index c08e42bda1..07773a12b2 100644 +--- a/hw/s390x/s390-virtio-ccw.c ++++ b/hw/s390x/s390-virtio-ccw.c +@@ -44,7 +44,6 @@ + #include "sysemu/sysemu.h" + #include "sysemu/balloon.h" + #include "hw/s390x/pv.h" +-#include + #include "migration/blocker.h" + + static Error *pv_mig_blocker; +@@ -391,15 +390,6 @@ out_err: + return rc; + } + +-static void s390_machine_inject_pv_error(CPUState *cs) +-{ +- int r1 = (cs->kvm_run->s390_sieic.ipa & 0x00f0) >> 4; +- CPUS390XState *env = &S390_CPU(cs)->env; +- +- /* Report that we are unable to enter protected mode */ +- env->regs[r1 + 1] = DIAG_308_RC_INVAL_FOR_PV; +-} +- + static void s390_pv_prepare_reset(S390CcwMachineState *ms) + { + CPUState *cs; +@@ -485,7 +475,7 @@ static void s390_machine_reset(MachineState *machine) + run_on_cpu(cs, s390_do_cpu_reset, RUN_ON_CPU_NULL); + + if (s390_machine_protect(ms)) { +- s390_machine_inject_pv_error(cs); ++ s390_pv_inject_reset_error(cs); + /* + * Continue after the diag308 so the guest knows something + * went wrong. +diff --git a/include/hw/s390x/pv.h b/include/hw/s390x/pv.h +index c6cb360f2f..522ca6a04e 100644 +--- a/include/hw/s390x/pv.h ++++ b/include/hw/s390x/pv.h +@@ -13,6 +13,7 @@ + #define HW_S390_PV_H + + #ifdef CONFIG_KVM ++#include "cpu.h" + #include "hw/s390x/s390-virtio-ccw.h" + + static inline bool s390_is_pv(void) +@@ -41,6 +42,7 @@ int s390_pv_unpack(uint64_t addr, uint64_t size, uint64_t tweak); + void s390_pv_perf_clear_reset(void); + int s390_pv_verify(void); + void s390_pv_unshare(void); ++void s390_pv_inject_reset_error(CPUState *cs); + #else /* CONFIG_KVM */ + static inline bool s390_is_pv(void) { return false; } + static inline int s390_pv_vm_enable(void) { return 0; } +@@ -50,6 +52,7 @@ static inline int s390_pv_unpack(uint64_t addr, uint64_t size, uint64_t tweak) { + static inline void s390_pv_perf_clear_reset(void) {} + static inline int s390_pv_verify(void) { return 0; } + static inline void s390_pv_unshare(void) {} ++static inline void s390_pv_inject_reset_error(CPUState *cs) {}; + #endif /* CONFIG_KVM */ + + #endif /* HW_S390_PV_H */ +-- +2.27.0 + diff --git a/SOURCES/kvm-spapr-Pass-the-maximum-number-of-vCPUs-to-the-KVM-in.patch b/SOURCES/kvm-spapr-Pass-the-maximum-number-of-vCPUs-to-the-KVM-in.patch new file mode 100644 index 0000000..7c48718 --- /dev/null +++ b/SOURCES/kvm-spapr-Pass-the-maximum-number-of-vCPUs-to-the-KVM-in.patch @@ -0,0 +1,213 @@ +From 5aea41b56f07f586e0f56a5c8b3e8443e485cd77 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 5 Jun 2020 07:41:09 -0400 +Subject: [PATCH 39/42] spapr: Pass the maximum number of vCPUs to the KVM + interrupt controller +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Thomas Huth +Message-id: <20200605074111.2185-2-thuth@redhat.com> +Patchwork-id: 97368 +O-Subject: [RHEL-8.3.0 qemu-kvm PATCH 1/3] spapr: Pass the maximum number of vCPUs to the KVM interrupt controller +Bugzilla: 1756946 +RH-Acked-by: Greg Kurz +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand + +From: Greg Kurz + +The XIVE and XICS-on-XIVE KVM devices on POWER9 hosts can greatly reduce +their consumption of some scarce HW resources, namely Virtual Presenter +identifiers, if they know the maximum number of vCPUs that may run in the +VM. + +Prepare ground for this by passing the value down to xics_kvm_connect() +and kvmppc_xive_connect(). This is purely mechanical, no functional +change. + +Signed-off-by: Greg Kurz +Message-Id: <157478678301.67101.2717368060417156338.stgit@bahia.tlslab.ibm.com> +Reviewed-by: Cédric Le Goater +Signed-off-by: David Gibson +(cherry picked from commit 4ffb7496881ec361deaf1f51c41a933bde3cbf7b) +Signed-off-by: Danilo C. L. de Paula +--- + hw/intc/spapr_xive.c | 6 ++++-- + hw/intc/spapr_xive_kvm.c | 3 ++- + hw/intc/xics_kvm.c | 3 ++- + hw/intc/xics_spapr.c | 5 +++-- + hw/ppc/spapr_irq.c | 8 +++++--- + include/hw/ppc/spapr_irq.h | 10 ++++++++-- + include/hw/ppc/spapr_xive.h | 3 ++- + include/hw/ppc/xics_spapr.h | 3 ++- + 8 files changed, 28 insertions(+), 13 deletions(-) + +diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c +index 9cb8d38a3b..a570e6e90a 100644 +--- a/hw/intc/spapr_xive.c ++++ b/hw/intc/spapr_xive.c +@@ -651,12 +651,14 @@ static void spapr_xive_dt(SpaprInterruptController *intc, uint32_t nr_servers, + plat_res_int_priorities, sizeof(plat_res_int_priorities))); + } + +-static int spapr_xive_activate(SpaprInterruptController *intc, Error **errp) ++static int spapr_xive_activate(SpaprInterruptController *intc, ++ uint32_t nr_servers, Error **errp) + { + SpaprXive *xive = SPAPR_XIVE(intc); + + if (kvm_enabled()) { +- int rc = spapr_irq_init_kvm(kvmppc_xive_connect, intc, errp); ++ int rc = spapr_irq_init_kvm(kvmppc_xive_connect, intc, nr_servers, ++ errp); + if (rc < 0) { + return rc; + } +diff --git a/hw/intc/spapr_xive_kvm.c b/hw/intc/spapr_xive_kvm.c +index 08012ac7cd..c1c837a764 100644 +--- a/hw/intc/spapr_xive_kvm.c ++++ b/hw/intc/spapr_xive_kvm.c +@@ -740,7 +740,8 @@ static void *kvmppc_xive_mmap(SpaprXive *xive, int pgoff, size_t len, + * All the XIVE memory regions are now backed by mappings from the KVM + * XIVE device. + */ +-int kvmppc_xive_connect(SpaprInterruptController *intc, Error **errp) ++int kvmppc_xive_connect(SpaprInterruptController *intc, uint32_t nr_servers, ++ Error **errp) + { + SpaprXive *xive = SPAPR_XIVE(intc); + XiveSource *xsrc = &xive->source; +diff --git a/hw/intc/xics_kvm.c b/hw/intc/xics_kvm.c +index 954c424b36..a1f1b7b0d3 100644 +--- a/hw/intc/xics_kvm.c ++++ b/hw/intc/xics_kvm.c +@@ -342,7 +342,8 @@ void ics_kvm_set_irq(ICSState *ics, int srcno, int val) + } + } + +-int xics_kvm_connect(SpaprInterruptController *intc, Error **errp) ++int xics_kvm_connect(SpaprInterruptController *intc, uint32_t nr_servers, ++ Error **errp) + { + ICSState *ics = ICS_SPAPR(intc); + int rc; +diff --git a/hw/intc/xics_spapr.c b/hw/intc/xics_spapr.c +index b3705dab0e..8ae4f41459 100644 +--- a/hw/intc/xics_spapr.c ++++ b/hw/intc/xics_spapr.c +@@ -422,10 +422,11 @@ static int xics_spapr_post_load(SpaprInterruptController *intc, int version_id) + return 0; + } + +-static int xics_spapr_activate(SpaprInterruptController *intc, Error **errp) ++static int xics_spapr_activate(SpaprInterruptController *intc, ++ uint32_t nr_servers, Error **errp) + { + if (kvm_enabled()) { +- return spapr_irq_init_kvm(xics_kvm_connect, intc, errp); ++ return spapr_irq_init_kvm(xics_kvm_connect, intc, nr_servers, errp); + } + return 0; + } +diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c +index d6bb7fd2d6..9da423658a 100644 +--- a/hw/ppc/spapr_irq.c ++++ b/hw/ppc/spapr_irq.c +@@ -70,15 +70,16 @@ void spapr_irq_msi_free(SpaprMachineState *spapr, int irq, uint32_t num) + bitmap_clear(spapr->irq_map, irq - SPAPR_IRQ_MSI, num); + } + +-int spapr_irq_init_kvm(int (*fn)(SpaprInterruptController *, Error **), ++int spapr_irq_init_kvm(SpaprInterruptControllerInitKvm fn, + SpaprInterruptController *intc, ++ uint32_t nr_servers, + Error **errp) + { + MachineState *machine = MACHINE(qdev_get_machine()); + Error *local_err = NULL; + + if (kvm_enabled() && machine_kernel_irqchip_allowed(machine)) { +- if (fn(intc, &local_err) < 0) { ++ if (fn(intc, nr_servers, &local_err) < 0) { + if (machine_kernel_irqchip_required(machine)) { + error_prepend(&local_err, + "kernel_irqchip requested but unavailable: "); +@@ -495,6 +496,7 @@ static void set_active_intc(SpaprMachineState *spapr, + SpaprInterruptController *new_intc) + { + SpaprInterruptControllerClass *sicc; ++ uint32_t nr_servers = spapr_max_server_number(spapr); + + assert(new_intc); + +@@ -512,7 +514,7 @@ static void set_active_intc(SpaprMachineState *spapr, + + sicc = SPAPR_INTC_GET_CLASS(new_intc); + if (sicc->activate) { +- sicc->activate(new_intc, &error_fatal); ++ sicc->activate(new_intc, nr_servers, &error_fatal); + } + + spapr->active_intc = new_intc; +diff --git a/include/hw/ppc/spapr_irq.h b/include/hw/ppc/spapr_irq.h +index ff814d13de..ca8cb44213 100644 +--- a/include/hw/ppc/spapr_irq.h ++++ b/include/hw/ppc/spapr_irq.h +@@ -43,7 +43,8 @@ typedef struct SpaprInterruptController SpaprInterruptController; + typedef struct SpaprInterruptControllerClass { + InterfaceClass parent; + +- int (*activate)(SpaprInterruptController *intc, Error **errp); ++ int (*activate)(SpaprInterruptController *intc, uint32_t nr_servers, ++ Error **errp); + void (*deactivate)(SpaprInterruptController *intc); + + /* +@@ -98,8 +99,13 @@ qemu_irq spapr_qirq(SpaprMachineState *spapr, int irq); + int spapr_irq_post_load(SpaprMachineState *spapr, int version_id); + void spapr_irq_reset(SpaprMachineState *spapr, Error **errp); + int spapr_irq_get_phandle(SpaprMachineState *spapr, void *fdt, Error **errp); +-int spapr_irq_init_kvm(int (*fn)(SpaprInterruptController *, Error **), ++ ++typedef int (*SpaprInterruptControllerInitKvm)(SpaprInterruptController *, ++ uint32_t, Error **); ++ ++int spapr_irq_init_kvm(SpaprInterruptControllerInitKvm fn, + SpaprInterruptController *intc, ++ uint32_t nr_servers, + Error **errp); + + /* +diff --git a/include/hw/ppc/spapr_xive.h b/include/hw/ppc/spapr_xive.h +index 742b7e834f..3a103c224d 100644 +--- a/include/hw/ppc/spapr_xive.h ++++ b/include/hw/ppc/spapr_xive.h +@@ -66,7 +66,8 @@ int spapr_xive_end_to_target(uint8_t end_blk, uint32_t end_idx, + /* + * KVM XIVE device helpers + */ +-int kvmppc_xive_connect(SpaprInterruptController *intc, Error **errp); ++int kvmppc_xive_connect(SpaprInterruptController *intc, uint32_t nr_servers, ++ Error **errp); + void kvmppc_xive_disconnect(SpaprInterruptController *intc); + void kvmppc_xive_reset(SpaprXive *xive, Error **errp); + void kvmppc_xive_set_source_config(SpaprXive *xive, uint32_t lisn, XiveEAS *eas, +diff --git a/include/hw/ppc/xics_spapr.h b/include/hw/ppc/xics_spapr.h +index 28b87038c8..1c65c96e3c 100644 +--- a/include/hw/ppc/xics_spapr.h ++++ b/include/hw/ppc/xics_spapr.h +@@ -32,7 +32,8 @@ + #define TYPE_ICS_SPAPR "ics-spapr" + #define ICS_SPAPR(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS_SPAPR) + +-int xics_kvm_connect(SpaprInterruptController *intc, Error **errp); ++int xics_kvm_connect(SpaprInterruptController *intc, uint32_t nr_servers, ++ Error **errp); + void xics_kvm_disconnect(SpaprInterruptController *intc); + bool xics_kvm_has_broken_disconnect(SpaprMachineState *spapr); + +-- +2.27.0 + diff --git a/SOURCES/kvm-target-arm-Fix-PAuth-sbox-functions.patch b/SOURCES/kvm-target-arm-Fix-PAuth-sbox-functions.patch new file mode 100644 index 0000000..0e08184 --- /dev/null +++ b/SOURCES/kvm-target-arm-Fix-PAuth-sbox-functions.patch @@ -0,0 +1,65 @@ +From b8c8288a65146952cdfe7d5f0cd96734c9de8ee1 Mon Sep 17 00:00:00 2001 +From: jmaloy +Date: Thu, 7 May 2020 17:57:08 +0100 +Subject: [PATCH 1/7] target/arm: Fix PAuth sbox functions +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: jmaloy +Message-id: <20200507175708.1165177-2-jmaloy@redhat.com> +Patchwork-id: 96341 +O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH 1/1] target/arm: Fix PAuth sbox functions +Bugzilla: 1813940 +RH-Acked-by: Andrew Jones +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Stefano Garzarella + +From: Vincent Dehors + +In the PAC computation, sbox was applied over wrong bits. +As this is a 4-bit sbox, bit index should be incremented by 4 instead of 16. + +Test vector from QARMA paper (https://eprint.iacr.org/2016/444.pdf) was +used to verify one computation of the pauth_computepac() function which +uses sbox2. + +Launchpad: https://bugs.launchpad.net/bugs/1859713 +Reviewed-by: Richard Henderson +Signed-off-by: Vincent DEHORS +Signed-off-by: Adrien GRASSEIN +Message-id: 20200116230809.19078-2-richard.henderson@linaro.org +Reviewed-by: Peter Maydell +Signed-off-by: Peter Maydell +(cherry picked from commit de0b1bae6461f67243282555475f88b2384a1eb9) +Signed-off-by: Jon Maloy +Signed-off-by: Danilo C. L. de Paula +--- + target/arm/pauth_helper.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/target/arm/pauth_helper.c b/target/arm/pauth_helper.c +index d3194f2..0a5f41e 100644 +--- a/target/arm/pauth_helper.c ++++ b/target/arm/pauth_helper.c +@@ -89,7 +89,7 @@ static uint64_t pac_sub(uint64_t i) + uint64_t o = 0; + int b; + +- for (b = 0; b < 64; b += 16) { ++ for (b = 0; b < 64; b += 4) { + o |= (uint64_t)sub[(i >> b) & 0xf] << b; + } + return o; +@@ -104,7 +104,7 @@ static uint64_t pac_inv_sub(uint64_t i) + uint64_t o = 0; + int b; + +- for (b = 0; b < 64; b += 16) { ++ for (b = 0; b < 64; b += 4) { + o |= (uint64_t)inv_sub[(i >> b) & 0xf] << b; + } + return o; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-Add-ARCH_CAPABILITIES-related-bits-into-.patch b/SOURCES/kvm-target-i386-Add-ARCH_CAPABILITIES-related-bits-into-.patch new file mode 100644 index 0000000..ffb6ab7 --- /dev/null +++ b/SOURCES/kvm-target-i386-Add-ARCH_CAPABILITIES-related-bits-into-.patch @@ -0,0 +1,83 @@ +From 4c9201a83e3ff48d2a55e45a34eb27966a1e4ab0 Mon Sep 17 00:00:00 2001 +From: "plai@redhat.com" +Date: Fri, 5 Jun 2020 18:37:33 -0400 +Subject: [PATCH 3/3] target/i386: Add ARCH_CAPABILITIES related bits into + Icelake-Server CPU model +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: plai@redhat.com +Message-id: <20200605183733.8269-1-plai@redhat.com> +Patchwork-id: 97380 +O-Subject: [RHEL8.2.1 AV qemu-kvm PATCH] target/i386: Add ARCH_CAPABILITIES related bits into Icelake-Server CPU model +Bugzilla: 1840342 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Bandan Das +RH-Acked-by: Danilo de Paula +RH-Acked-by: Eduardo Habkost + +From: Xiaoyao Li + +BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1840342 +Brew: http://brewweb.devel.redhat.com/brew/taskinfo?taskID=28983822 +Branch: rhel-av-8.2.1 + +Tested on HOST: intel-whitley-09.khw1.lab.eng.bos.redhat.com + +1. qemu-kvm -cpu host … + VM guest does have arch_capabilities in cpuinfo/flags. + [Expected success] + +2. qemu-kvm -cpu Icelake-Server … + VM guest does NOT have arch_capabilities in cpuinfo/flags. + [Expected failure] + +3. qemu-kvm -cpu Icelake-Server-v3 … + VM guest does have arch_capabilities in cpuinfo/flags. + [Expected success] + +--- + +Current Icelake-Server CPU model lacks all the features enumerated by +MSR_IA32_ARCH_CAPABILITIES. + +Add them, so that guest of "Icelake-Server" can see all of them. + +Signed-off-by: Xiaoyao Li +Message-Id: <20200316095605.12318-1-xiaoyao.li@intel.com> +Signed-off-by: Eduardo Habkost +(cherry picked from commit d965dc35592d24c0c1519f1c566223c6277cb80e) +Signed-off-by: Paul Lai +Signed-off-by: Eduardo Lima (Etrunko) +--- + target/i386/cpu.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index b763adcdc5..7d7b016bb7 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -3496,6 +3496,19 @@ static X86CPUDefinition builtin_x86_defs[] = { + { /* end of list */ } + }, + }, ++ { ++ .version = 3, ++ .props = (PropValue[]) { ++ { "arch-capabilities", "on" }, ++ { "rdctl-no", "on" }, ++ { "ibrs-all", "on" }, ++ { "skip-l1dfl-vmentry", "on" }, ++ { "mds-no", "on" }, ++ { "pschange-mc-no", "on" }, ++ { "taa-no", "on" }, ++ { /* end of list */ } ++ }, ++ }, + { /* end of list */ } + } + }, +-- +2.27.0 + diff --git a/SOURCES/kvm-target-i386-Add-missed-features-to-Cooperlake-CPU-mo.patch b/SOURCES/kvm-target-i386-Add-missed-features-to-Cooperlake-CPU-mo.patch new file mode 100644 index 0000000..ef95ccf --- /dev/null +++ b/SOURCES/kvm-target-i386-Add-missed-features-to-Cooperlake-CPU-mo.patch @@ -0,0 +1,103 @@ +From 1ffeb321151b3878bcbb2229639456c0677305f5 Mon Sep 17 00:00:00 2001 +From: "plai@redhat.com" +Date: Fri, 15 May 2020 18:02:43 +0100 +Subject: [PATCH 17/17] target/i386: Add missed features to Cooperlake CPU + model + +RH-Author: plai@redhat.com +Message-id: <20200515180243.17488-5-plai@redhat.com> +Patchwork-id: 96611 +O-Subject: [RHEL8.2.1 AV qemu-kvm PATCH 4/4] target/i386: Add missed features to Cooperlake CPU model +Bugzilla: 1769912 +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Igor Mammedov +RH-Acked-by: Eduardo Habkost + +From: Xiaoyao Li + +It lacks VMX features and two security feature bits (disclosed recently) in +MSR_IA32_ARCH_CAPABILITIES in current Cooperlake CPU model, so add them. + +Fixes: 22a866b6166d ("i386: Add new CPU model Cooperlake") +Signed-off-by: Xiaoyao Li +Message-Id: <20191225063018.20038-3-xiaoyao.li@intel.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit 2dea9d9ca4ea7e9afe83d0b4153b21a16987e866) +Signed-off-by: Paul Lai +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 50 insertions(+), 1 deletion(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 996a74f..b763adc 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -3202,7 +3202,8 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_7_0_EDX_SPEC_CTRL_SSBD | CPUID_7_0_EDX_ARCH_CAPABILITIES, + .features[FEAT_ARCH_CAPABILITIES] = + MSR_ARCH_CAP_RDCL_NO | MSR_ARCH_CAP_IBRS_ALL | +- MSR_ARCH_CAP_SKIP_L1DFL_VMENTRY | MSR_ARCH_CAP_MDS_NO, ++ MSR_ARCH_CAP_SKIP_L1DFL_VMENTRY | MSR_ARCH_CAP_MDS_NO | ++ MSR_ARCH_CAP_PSCHANGE_MC_NO | MSR_ARCH_CAP_TAA_NO, + .features[FEAT_7_1_EAX] = + CPUID_7_1_EAX_AVX512_BF16, + /* +@@ -3217,6 +3218,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 (Cooperlake)", + }, +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-Add-new-bit-definitions-of-MSR_IA32_ARCH.patch b/SOURCES/kvm-target-i386-Add-new-bit-definitions-of-MSR_IA32_ARCH.patch new file mode 100644 index 0000000..ad2dd77 --- /dev/null +++ b/SOURCES/kvm-target-i386-Add-new-bit-definitions-of-MSR_IA32_ARCH.patch @@ -0,0 +1,62 @@ +From 6f0630299a3edbb8f5e5ac41eb9e1f1c363f1e3e Mon Sep 17 00:00:00 2001 +From: Danilo de Paula +Date: Tue, 9 Jun 2020 18:46:51 +0100 +Subject: [PATCH 15/17] target/i386: Add new bit definitions of + MSR_IA32_ARCH_CAPABILITIES + +RH-Author: Danilo de Paula +Message-id: <20200609184651.1328372-1-ddepaula@redhat.com> +Patchwork-id: 97489 +O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH 5/4] target/i386: Add new bit definitions of MSR_IA32_ARCH_CAPABILITIES +Bugzilla: 1769912 +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Eduardo Habkost + +From: Danilo de Paula + +redhat: builds with that series were failing. It complains about a undefined +MSR_ARCH_CAP_TAA_NO. + +The bit 6, 7 and 8 of MSR_IA32_ARCH_CAPABILITIES are recently disclosed +for some security issues. Add the definitions for them to be used by named +CPU models. + +Signed-off-by: Xiaoyao Li +Message-Id: <20191225063018.20038-2-xiaoyao.li@intel.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit 6c997b4adb300788d61d72e2b8bc67c03a584956) + +Signed-off-by: Paolo Bonzini +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.h | 13 ++++++++----- + 1 file changed, 8 insertions(+), 5 deletions(-) + +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index e77d101..7bfbf2a 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -836,12 +836,15 @@ typedef uint64_t FeatureWordArray[FEATURE_WORDS]; + #define CPUID_TOPOLOGY_LEVEL_DIE (5U << 8) + + /* MSR Feature Bits */ +-#define MSR_ARCH_CAP_RDCL_NO (1U << 0) +-#define MSR_ARCH_CAP_IBRS_ALL (1U << 1) +-#define MSR_ARCH_CAP_RSBA (1U << 2) ++#define MSR_ARCH_CAP_RDCL_NO (1U << 0) ++#define MSR_ARCH_CAP_IBRS_ALL (1U << 1) ++#define MSR_ARCH_CAP_RSBA (1U << 2) + #define MSR_ARCH_CAP_SKIP_L1DFL_VMENTRY (1U << 3) +-#define MSR_ARCH_CAP_SSB_NO (1U << 4) +-#define MSR_ARCH_CAP_MDS_NO (1U << 5) ++#define MSR_ARCH_CAP_SSB_NO (1U << 4) ++#define MSR_ARCH_CAP_MDS_NO (1U << 5) ++#define MSR_ARCH_CAP_PSCHANGE_MC_NO (1U << 6) ++#define MSR_ARCH_CAP_TSX_CTRL_MSR (1U << 7) ++#define MSR_ARCH_CAP_TAA_NO (1U << 8) + + #define MSR_CORE_CAP_SPLIT_LOCK_DETECT (1U << 5) + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-set-the-CPUID-level-to-0x14-on-old-machi.patch b/SOURCES/kvm-target-i386-set-the-CPUID-level-to-0x14-on-old-machi.patch new file mode 100644 index 0000000..49e54ba --- /dev/null +++ b/SOURCES/kvm-target-i386-set-the-CPUID-level-to-0x14-on-old-machi.patch @@ -0,0 +1,69 @@ +From 72a1827006be22791017ff2b671eac1c96be5d12 Mon Sep 17 00:00:00 2001 +From: "plai@redhat.com" +Date: Thu, 7 May 2020 22:09:23 +0100 +Subject: [PATCH 01/26] target/i386: set the CPUID level to 0x14 on old + machine-type + +RH-Author: plai@redhat.com +Message-id: <20200507220923.13723-1-plai@redhat.com> +Patchwork-id: 96347 +O-Subject: [RHEL8.2.1 AV qemu-kvm PATCH RESEND] target/i386: set the CPUID level to 0x14 on old machine-type +Bugzilla: 1513681 +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Igor Mammedov +RH-Acked-by: Danilo de Paula + +From: Luwei Kang + +BZ https://bugzilla.redhat.com/show_bug.cgi?id=1513681 +Brew: http://brewweb.devel.redhat.com/brew/taskinfo?taskID=28146304 +Branch: rhel-av-8.2.1 + +Tested on intel-icelake-y-01.ml3.eng.bos.redhat.com. + +The CPUID level need to be set to 0x14 manually on old +machine-type if Intel PT is enabled in guest. E.g. the +CPUID[0].EAX(level)=7 and CPUID[7].EBX[25](intel-pt)=1 when the +Qemu with "-machine pc-i440fx-3.1 -cpu qemu64,+intel-pt" parameter. + +Some Intel PT capabilities are exposed by leaf 0x14 and the +missing capabilities will cause some MSRs access failed. +This patch add a warning message to inform the user to extend +the CPUID level. + +Suggested-by: Eduardo Habkost +Signed-off-by: Luwei Kang +Message-Id: <1584031686-16444-1-git-send-email-luwei.kang@intel.com> +Signed-off-by: Eduardo Habkost +(cherry picked from commit ddc2fc9e4e42ebce48b088963dc7fbd1c08d5f33) +Signed-off-by: Paul Lai +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 1685a8c..0f0a2db 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -6206,9 +6206,14 @@ static void x86_cpu_expand_features(X86CPU *cpu, Error **errp) + x86_cpu_adjust_feat_level(cpu, FEAT_XSAVE); + + /* Intel Processor Trace requires CPUID[0x14] */ +- if ((env->features[FEAT_7_0_EBX] & CPUID_7_0_EBX_INTEL_PT) && +- kvm_enabled() && cpu->intel_pt_auto_level) { +- x86_cpu_adjust_level(cpu, &cpu->env.cpuid_min_level, 0x14); ++ if ((env->features[FEAT_7_0_EBX] & CPUID_7_0_EBX_INTEL_PT)) { ++ if (cpu->intel_pt_auto_level) { ++ x86_cpu_adjust_level(cpu, &cpu->env.cpuid_min_level, 0x14); ++ } else if (cpu->env.cpuid_min_level < 0x14) { ++ mark_unavailable_features(cpu, FEAT_7_0_EBX, ++ CPUID_7_0_EBX_INTEL_PT, ++ "Intel PT need CPUID leaf 0x14, please set by \"-cpu ...,+intel-pt,level=0x14\""); ++ } + } + + /* CPU topology with multi-dies support requires CPUID[0x1F] */ +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-s390x-kvm-Enable-adapter-interruption-suppres.patch b/SOURCES/kvm-target-s390x-kvm-Enable-adapter-interruption-suppres.patch new file mode 100644 index 0000000..38e5637 --- /dev/null +++ b/SOURCES/kvm-target-s390x-kvm-Enable-adapter-interruption-suppres.patch @@ -0,0 +1,60 @@ +From c4fe37ae6d75ed72e6a3bde01fea053eb508274c Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 5 Jun 2020 07:41:11 -0400 +Subject: [PATCH 41/42] target/s390x/kvm: Enable adapter interruption + suppression again +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Thomas Huth +Message-id: <20200605074111.2185-4-thuth@redhat.com> +Patchwork-id: 97370 +O-Subject: [RHEL-8.3.0 qemu-kvm PATCH 3/3] target/s390x/kvm: Enable adapter interruption suppression again +Bugzilla: 1756946 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand + +The AIS feature has been disabled late in the v2.10 development cycle since +there were some issues with migration (see commit 3f2d07b3b01ea61126b - +"s390x/ais: for 2.10 stable: disable ais facility"). We originally wanted +to enable it again for newer machine types, but apparently we forgot to do +this so far. Let's do it now for the machines that support proper CPU models. + +Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=1756946 +Signed-off-by: Thomas Huth +Message-Id: <20200122101437.5069-1-thuth@redhat.com> +Reviewed-by: David Hildenbrand +Tested-by: Matthew Rosato +Signed-off-by: Cornelia Huck +(cherry picked from commit a5c8617af6919515b84256978452edf07401c45e) +Signed-off-by: Danilo C. L. de Paula +--- + target/s390x/kvm.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c +index c589ef9034..0bbf8f81b0 100644 +--- a/target/s390x/kvm.c ++++ b/target/s390x/kvm.c +@@ -377,10 +377,13 @@ int kvm_arch_init(MachineState *ms, KVMState *s) + /* + * The migration interface for ais was introduced with kernel 4.13 + * but the capability itself had been active since 4.12. As migration +- * support is considered necessary let's disable ais in the 2.10 +- * machine. ++ * support is considered necessary, we only try to enable this for ++ * newer machine types if KVM_CAP_S390_AIS_MIGRATION is available. + */ +- /* kvm_vm_enable_cap(s, KVM_CAP_S390_AIS, 0); */ ++ if (cpu_model_allowed() && kvm_kernel_irqchip_allowed() && ++ kvm_check_extension(s, KVM_CAP_S390_AIS_MIGRATION)) { ++ kvm_vm_enable_cap(s, KVM_CAP_S390_AIS, 0); ++ } + + kvm_set_max_memslot_size(KVM_SLOT_MAX_BYTES); + return 0; +-- +2.27.0 + diff --git a/SOURCES/kvm-tests-bios-tables-test-add-test-cases-for-ACPI-HMAT.patch b/SOURCES/kvm-tests-bios-tables-test-add-test-cases-for-ACPI-HMAT.patch new file mode 100644 index 0000000..12df637 --- /dev/null +++ b/SOURCES/kvm-tests-bios-tables-test-add-test-cases-for-ACPI-HMAT.patch @@ -0,0 +1,127 @@ +From 6d549629becb69f315dd4213f730122d19c9c566 Mon Sep 17 00:00:00 2001 +From: "plai@redhat.com" +Date: Thu, 21 May 2020 23:56:54 +0100 +Subject: [PATCH 11/12] tests/bios-tables-test: add test cases for ACPI HMAT + +RH-Author: plai@redhat.com +Message-id: <20200521235655.27141-11-plai@redhat.com> +Patchwork-id: 96739 +O-Subject: [RHEL8.2.1 AV qemu-kvm PATCH 10/11] tests/bios-tables-test: add test cases for ACPI HMAT +Bugzilla: 1600217 +RH-Acked-by: Michael S. Tsirkin +RH-Acked-by: Igor Mammedov +RH-Acked-by: Eduardo Habkost + +From: Tao Xu + +ACPI table HMAT has been introduced, QEMU now builds HMAT tables for +Heterogeneous Memory with boot option '-numa node'. + +Add test cases on PC and Q35 machines with 2 numa nodes. +Because HMAT is generated when system enable numa, the +following tables need to be added for this test: + tests/data/acpi/pc/APIC.acpihmat + tests/data/acpi/pc/SRAT.acpihmat + tests/data/acpi/pc/HMAT.acpihmat + tests/data/acpi/pc/DSDT.acpihmat + tests/data/acpi/q35/APIC.acpihmat + tests/data/acpi/q35/SRAT.acpihmat + tests/data/acpi/q35/HMAT.acpihmat + tests/data/acpi/q35/DSDT.acpihmat + +Acked-by: Markus Armbruster +Reviewed-by: Igor Mammedov +Reviewed-by: Daniel Black +Reviewed-by: Jingqi Liu +Suggested-by: Igor Mammedov +Signed-off-by: Tao Xu +Message-Id: <20191213011929.2520-9-tao3.xu@intel.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +(cherry picked from commit 1c8f85d93d261dc555a0aad6f54f2b5e8009d859) +Signed-off-by: Paul Lai +Signed-off-by: Danilo C. L. de Paula +--- + tests/bios-tables-test-allowed-diff.h | 8 +++++++ + tests/bios-tables-test.c | 44 +++++++++++++++++++++++++++++++++++ + 2 files changed, 52 insertions(+) + +diff --git a/tests/bios-tables-test-allowed-diff.h b/tests/bios-tables-test-allowed-diff.h +index dfb8523..3c9e0c9 100644 +--- a/tests/bios-tables-test-allowed-diff.h ++++ b/tests/bios-tables-test-allowed-diff.h +@@ -1 +1,9 @@ + /* List of comma-separated changed AML files to ignore */ ++"tests/data/acpi/pc/APIC.acpihmat", ++"tests/data/acpi/pc/SRAT.acpihmat", ++"tests/data/acpi/pc/HMAT.acpihmat", ++"tests/data/acpi/pc/DSDT.acpihmat", ++"tests/data/acpi/q35/APIC.acpihmat", ++"tests/data/acpi/q35/SRAT.acpihmat", ++"tests/data/acpi/q35/HMAT.acpihmat", ++"tests/data/acpi/q35/DSDT.acpihmat", +diff --git a/tests/bios-tables-test.c b/tests/bios-tables-test.c +index 79f5da0..9823820 100644 +--- a/tests/bios-tables-test.c ++++ b/tests/bios-tables-test.c +@@ -947,6 +947,48 @@ static void test_acpi_virt_tcg_numamem(void) + + } + ++static void test_acpi_tcg_acpi_hmat(const char *machine) ++{ ++ test_data data; ++ ++ memset(&data, 0, sizeof(data)); ++ data.machine = machine; ++ data.variant = ".acpihmat"; ++ test_acpi_one(" -machine hmat=on" ++ " -smp 2,sockets=2" ++ " -m 128M,slots=2,maxmem=1G" ++ " -object memory-backend-ram,size=64M,id=m0" ++ " -object memory-backend-ram,size=64M,id=m1" ++ " -numa node,nodeid=0,memdev=m0" ++ " -numa node,nodeid=1,memdev=m1,initiator=0" ++ " -numa cpu,node-id=0,socket-id=0" ++ " -numa cpu,node-id=0,socket-id=1" ++ " -numa hmat-lb,initiator=0,target=0,hierarchy=memory," ++ "data-type=access-latency,latency=1" ++ " -numa hmat-lb,initiator=0,target=0,hierarchy=memory," ++ "data-type=access-bandwidth,bandwidth=65534M" ++ " -numa hmat-lb,initiator=0,target=1,hierarchy=memory," ++ "data-type=access-latency,latency=65534" ++ " -numa hmat-lb,initiator=0,target=1,hierarchy=memory," ++ "data-type=access-bandwidth,bandwidth=32767M" ++ " -numa hmat-cache,node-id=0,size=10K,level=1," ++ "associativity=direct,policy=write-back,line=8" ++ " -numa hmat-cache,node-id=1,size=10K,level=1," ++ "associativity=direct,policy=write-back,line=8", ++ &data); ++ free_test_data(&data); ++} ++ ++static void test_acpi_q35_tcg_acpi_hmat(void) ++{ ++ test_acpi_tcg_acpi_hmat(MACHINE_Q35); ++} ++ ++static void test_acpi_piix4_tcg_acpi_hmat(void) ++{ ++ test_acpi_tcg_acpi_hmat(MACHINE_PC); ++} ++ + static void test_acpi_virt_tcg(void) + { + test_data data = { +@@ -991,6 +1033,8 @@ int main(int argc, char *argv[]) + qtest_add_func("acpi/q35/numamem", test_acpi_q35_tcg_numamem); + qtest_add_func("acpi/piix4/dimmpxm", test_acpi_piix4_tcg_dimm_pxm); + qtest_add_func("acpi/q35/dimmpxm", test_acpi_q35_tcg_dimm_pxm); ++ qtest_add_func("acpi/piix4/acpihmat", test_acpi_piix4_tcg_acpi_hmat); ++ qtest_add_func("acpi/q35/acpihmat", test_acpi_q35_tcg_acpi_hmat); + } else if (strcmp(arch, "aarch64") == 0) { + qtest_add_func("acpi/virt", test_acpi_virt_tcg); + qtest_add_func("acpi/virt/numamem", test_acpi_virt_tcg_numamem); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-tests-boot-sector-Fix-the-bad-s390x-assembler-code.patch b/SOURCES/kvm-tests-boot-sector-Fix-the-bad-s390x-assembler-code.patch new file mode 100644 index 0000000..240c408 --- /dev/null +++ b/SOURCES/kvm-tests-boot-sector-Fix-the-bad-s390x-assembler-code.patch @@ -0,0 +1,60 @@ +From f73b18e03c6758500bf367b1575205772d1f878f Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 29 May 2020 05:53:52 -0400 +Subject: [PATCH 10/42] tests/boot-sector: Fix the bad s390x assembler code + +RH-Author: Thomas Huth +Message-id: <20200529055420.16855-11-thuth@redhat.com> +Patchwork-id: 97031 +O-Subject: [RHEL-8.3.0 qemu-kvm PATCH v2 10/38] tests/boot-sector: Fix the bad s390x assembler code +Bugzilla: 1828317 +RH-Acked-by: Claudio Imbrenda +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand + +There are currently two bugs in s390x_code[]: First, the initial jump +uses the wrong offset, so it was jumping to 0x10014 instead of 0x10010. +Second, LHI only loads the lower 32-bit of the register. + +Everything worked fine as long as the s390-ccw bios code was jumping +here with r3 containing zeroes in the uppermost 48 bit - which just +happened to be the case so far by accident. But we can not rely on this +fact, and indeed one of the recent suggested patches to jump2ipl.c cause +the newer GCCs to put different values into r3. In that case the code +from s390x_code[] crashes very ungracefully. + +Thus let's make sure to jump to the right instruction, and use LGHI +instead of LHI to make sure that we always zero out the upper bits +of the register. + +Signed-off-by: Thomas Huth +Message-Id: <20191217150642.27946-1-thuth@redhat.com> +Reviewed-by: Christian Borntraeger +Signed-off-by: Cornelia Huck +(cherry picked from commit 5afec76fbe2c07d03fd8c9ac525140059499637a) +Signed-off-by: Danilo C. L. de Paula +--- + tests/boot-sector.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/tests/boot-sector.c b/tests/boot-sector.c +index 7824286b9a..9e66c6d013 100644 +--- a/tests/boot-sector.c ++++ b/tests/boot-sector.c +@@ -75,11 +75,11 @@ static const uint8_t s390x_psw_and_magic[] = { + 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40 /* in the s390-ccw bios */ + }; + static const uint8_t s390x_code[] = { +- 0xa7, 0xf4, 0x00, 0x0a, /* j 0x10010 */ ++ 0xa7, 0xf4, 0x00, 0x08, /* j 0x10010 */ + 0x00, 0x00, 0x00, 0x00, + 'S', '3', '9', '0', + 'E', 'P', 0x00, 0x01, +- 0xa7, 0x38, HIGH(SIGNATURE_ADDR), LOW(SIGNATURE_ADDR), /* lhi r3,0x7c10 */ ++ 0xa7, 0x39, HIGH(SIGNATURE_ADDR), LOW(SIGNATURE_ADDR), /* lghi r3,0x7c10 */ + 0xa7, 0x48, LOW(SIGNATURE), HIGH(SIGNATURE), /* lhi r4,0xadde */ + 0x40, 0x40, 0x30, 0x00, /* sth r4,0(r3) */ + 0xa7, 0xf4, 0xff, 0xfa /* j 0x10010 */ +-- +2.27.0 + diff --git a/SOURCES/kvm-tests-numa-Add-case-for-QMP-build-HMAT.patch b/SOURCES/kvm-tests-numa-Add-case-for-QMP-build-HMAT.patch new file mode 100644 index 0000000..41ee71c --- /dev/null +++ b/SOURCES/kvm-tests-numa-Add-case-for-QMP-build-HMAT.patch @@ -0,0 +1,266 @@ +From 0f11aae02dcabd3a5ee0b5946aec39da6dddea52 Mon Sep 17 00:00:00 2001 +From: "plai@redhat.com" +Date: Thu, 21 May 2020 23:56:53 +0100 +Subject: [PATCH 10/12] tests/numa: Add case for QMP build HMAT + +RH-Author: plai@redhat.com +Message-id: <20200521235655.27141-10-plai@redhat.com> +Patchwork-id: 96735 +O-Subject: [RHEL8.2.1 AV qemu-kvm PATCH 09/11] tests/numa: Add case for QMP build HMAT +Bugzilla: 1600217 +RH-Acked-by: Michael S. Tsirkin +RH-Acked-by: Igor Mammedov +RH-Acked-by: Eduardo Habkost + +From: Tao Xu + +Check configuring HMAT usecase + +Acked-by: Markus Armbruster +Suggested-by: Igor Mammedov +Signed-off-by: Tao Xu +Message-Id: <20191213011929.2520-8-tao3.xu@intel.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Reviewed-by: Igor Mammedov +(cherry picked from commit d00817c944ed15fbe4a61d44fe7f9fe166c7df88) +Signed-off-by: Paul Lai +Signed-off-by: Danilo C. L. de Paula +--- + tests/numa-test.c | 213 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 213 insertions(+) + +diff --git a/tests/numa-test.c b/tests/numa-test.c +index 8de8581..17dd807 100644 +--- a/tests/numa-test.c ++++ b/tests/numa-test.c +@@ -327,6 +327,216 @@ static void pc_dynamic_cpu_cfg(const void *data) + qtest_quit(qs); + } + ++static void pc_hmat_build_cfg(const void *data) ++{ ++ QTestState *qs = qtest_initf("%s -nodefaults --preconfig -machine hmat=on " ++ "-smp 2,sockets=2 " ++ "-m 128M,slots=2,maxmem=1G " ++ "-object memory-backend-ram,size=64M,id=m0 " ++ "-object memory-backend-ram,size=64M,id=m1 " ++ "-numa node,nodeid=0,memdev=m0 " ++ "-numa node,nodeid=1,memdev=m1,initiator=0 " ++ "-numa cpu,node-id=0,socket-id=0 " ++ "-numa cpu,node-id=0,socket-id=1", ++ data ? (char *)data : ""); ++ ++ /* Fail: Initiator should be less than the number of nodes */ ++ g_assert_true(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node'," ++ " 'arguments': { 'type': 'hmat-lb', 'initiator': 2, 'target': 0," ++ " 'hierarchy': \"memory\", 'data-type': \"access-latency\" } }"))); ++ ++ /* Fail: Target should be less than the number of nodes */ ++ g_assert_true(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node'," ++ " 'arguments': { 'type': 'hmat-lb', 'initiator': 0, 'target': 2," ++ " 'hierarchy': \"memory\", 'data-type': \"access-latency\" } }"))); ++ ++ /* Fail: Initiator should contain cpu */ ++ g_assert_true(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node'," ++ " 'arguments': { 'type': 'hmat-lb', 'initiator': 1, 'target': 0," ++ " 'hierarchy': \"memory\", 'data-type': \"access-latency\" } }"))); ++ ++ /* Fail: Data-type mismatch */ ++ g_assert_true(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node'," ++ " 'arguments': { 'type': 'hmat-lb', 'initiator': 0, 'target': 0," ++ " 'hierarchy': \"memory\", 'data-type': \"write-latency\"," ++ " 'bandwidth': 524288000 } }"))); ++ g_assert_true(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node'," ++ " 'arguments': { 'type': 'hmat-lb', 'initiator': 0, 'target': 0," ++ " 'hierarchy': \"memory\", 'data-type': \"read-bandwidth\"," ++ " 'latency': 5 } }"))); ++ ++ /* Fail: Bandwidth should be 1MB (1048576) aligned */ ++ g_assert_true(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node'," ++ " 'arguments': { 'type': 'hmat-lb', 'initiator': 0, 'target': 0," ++ " 'hierarchy': \"memory\", 'data-type': \"access-bandwidth\"," ++ " 'bandwidth': 1048575 } }"))); ++ ++ /* Configuring HMAT bandwidth and latency details */ ++ g_assert_false(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node'," ++ " 'arguments': { 'type': 'hmat-lb', 'initiator': 0, 'target': 0," ++ " 'hierarchy': \"memory\", 'data-type': \"access-latency\"," ++ " 'latency': 1 } }"))); /* 1 ns */ ++ g_assert_true(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node'," ++ " 'arguments': { 'type': 'hmat-lb', 'initiator': 0, 'target': 0," ++ " 'hierarchy': \"memory\", 'data-type': \"access-latency\"," ++ " 'latency': 5 } }"))); /* Fail: Duplicate configuration */ ++ g_assert_false(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node'," ++ " 'arguments': { 'type': 'hmat-lb', 'initiator': 0, 'target': 0," ++ " 'hierarchy': \"memory\", 'data-type': \"access-bandwidth\"," ++ " 'bandwidth': 68717379584 } }"))); /* 65534 MB/s */ ++ g_assert_false(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node'," ++ " 'arguments': { 'type': 'hmat-lb', 'initiator': 0, 'target': 1," ++ " 'hierarchy': \"memory\", 'data-type': \"access-latency\"," ++ " 'latency': 65534 } }"))); /* 65534 ns */ ++ g_assert_false(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node'," ++ " 'arguments': { 'type': 'hmat-lb', 'initiator': 0, 'target': 1," ++ " 'hierarchy': \"memory\", 'data-type': \"access-bandwidth\"," ++ " 'bandwidth': 34358689792 } }"))); /* 32767 MB/s */ ++ ++ /* Fail: node_id should be less than the number of nodes */ ++ g_assert_true(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node'," ++ " 'arguments': { 'type': 'hmat-cache', 'node-id': 2, 'size': 10240," ++ " 'level': 1, 'associativity': \"direct\", 'policy': \"write-back\"," ++ " 'line': 8 } }"))); ++ ++ /* Fail: level should be less than HMAT_LB_LEVELS (4) */ ++ g_assert_true(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node'," ++ " 'arguments': { 'type': 'hmat-cache', 'node-id': 0, 'size': 10240," ++ " 'level': 4, 'associativity': \"direct\", 'policy': \"write-back\"," ++ " 'line': 8 } }"))); ++ ++ /* Fail: associativity option should be 'none', if level is 0 */ ++ g_assert_true(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node'," ++ " 'arguments': { 'type': 'hmat-cache', 'node-id': 0, 'size': 10240," ++ " 'level': 0, 'associativity': \"direct\", 'policy': \"none\"," ++ " 'line': 0 } }"))); ++ /* Fail: policy option should be 'none', if level is 0 */ ++ g_assert_true(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node'," ++ " 'arguments': { 'type': 'hmat-cache', 'node-id': 0, 'size': 10240," ++ " 'level': 0, 'associativity': \"none\", 'policy': \"write-back\"," ++ " 'line': 0 } }"))); ++ /* Fail: line option should be 0, if level is 0 */ ++ g_assert_true(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node'," ++ " 'arguments': { 'type': 'hmat-cache', 'node-id': 0, 'size': 10240," ++ " 'level': 0, 'associativity': \"none\", 'policy': \"none\"," ++ " 'line': 8 } }"))); ++ ++ /* Configuring HMAT memory side cache attributes */ ++ g_assert_false(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node'," ++ " 'arguments': { 'type': 'hmat-cache', 'node-id': 0, 'size': 10240," ++ " 'level': 1, 'associativity': \"direct\", 'policy': \"write-back\"," ++ " 'line': 8 } }"))); ++ g_assert_true(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node'," ++ " 'arguments': { 'type': 'hmat-cache', 'node-id': 0, 'size': 10240," ++ " 'level': 1, 'associativity': \"direct\", 'policy': \"write-back\"," ++ " 'line': 8 } }"))); /* Fail: Duplicate configuration */ ++ /* Fail: The size of level 2 size should be small than level 1 */ ++ g_assert_true(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node'," ++ " 'arguments': { 'type': 'hmat-cache', 'node-id': 0, 'size': 10240," ++ " 'level': 2, 'associativity': \"direct\", 'policy': \"write-back\"," ++ " 'line': 8 } }"))); ++ /* Fail: The size of level 0 size should be larger than level 1 */ ++ g_assert_true(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node'," ++ " 'arguments': { 'type': 'hmat-cache', 'node-id': 0, 'size': 10240," ++ " 'level': 0, 'associativity': \"direct\", 'policy': \"write-back\"," ++ " 'line': 8 } }"))); ++ g_assert_false(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node'," ++ " 'arguments': { 'type': 'hmat-cache', 'node-id': 1, 'size': 10240," ++ " 'level': 1, 'associativity': \"direct\", 'policy': \"write-back\"," ++ " 'line': 8 } }"))); ++ ++ /* let machine initialization to complete and run */ ++ g_assert_false(qmp_rsp_is_err(qtest_qmp(qs, ++ "{ 'execute': 'x-exit-preconfig' }"))); ++ qtest_qmp_eventwait(qs, "RESUME"); ++ ++ qtest_quit(qs); ++} ++ ++static void pc_hmat_off_cfg(const void *data) ++{ ++ QTestState *qs = qtest_initf("%s -nodefaults --preconfig " ++ "-smp 2,sockets=2 " ++ "-m 128M,slots=2,maxmem=1G " ++ "-object memory-backend-ram,size=64M,id=m0 " ++ "-object memory-backend-ram,size=64M,id=m1 " ++ "-numa node,nodeid=0,memdev=m0", ++ data ? (char *)data : ""); ++ ++ /* ++ * Fail: Enable HMAT with -machine hmat=on ++ * before using any of hmat specific options ++ */ ++ g_assert_true(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node'," ++ " 'arguments': { 'type': 'node', 'nodeid': 1, 'memdev': \"m1\"," ++ " 'initiator': 0 } }"))); ++ g_assert_false(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node'," ++ " 'arguments': { 'type': 'node', 'nodeid': 1, 'memdev': \"m1\" } }"))); ++ g_assert_true(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node'," ++ " 'arguments': { 'type': 'hmat-lb', 'initiator': 0, 'target': 0," ++ " 'hierarchy': \"memory\", 'data-type': \"access-latency\"," ++ " 'latency': 1 } }"))); ++ g_assert_true(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node'," ++ " 'arguments': { 'type': 'hmat-cache', 'node-id': 0, 'size': 10240," ++ " 'level': 1, 'associativity': \"direct\", 'policy': \"write-back\"," ++ " 'line': 8 } }"))); ++ ++ /* let machine initialization to complete and run */ ++ g_assert_false(qmp_rsp_is_err(qtest_qmp(qs, ++ "{ 'execute': 'x-exit-preconfig' }"))); ++ qtest_qmp_eventwait(qs, "RESUME"); ++ ++ qtest_quit(qs); ++} ++ ++static void pc_hmat_erange_cfg(const void *data) ++{ ++ QTestState *qs = qtest_initf("%s -nodefaults --preconfig -machine hmat=on " ++ "-smp 2,sockets=2 " ++ "-m 128M,slots=2,maxmem=1G " ++ "-object memory-backend-ram,size=64M,id=m0 " ++ "-object memory-backend-ram,size=64M,id=m1 " ++ "-numa node,nodeid=0,memdev=m0 " ++ "-numa node,nodeid=1,memdev=m1,initiator=0 " ++ "-numa cpu,node-id=0,socket-id=0 " ++ "-numa cpu,node-id=0,socket-id=1", ++ data ? (char *)data : ""); ++ ++ /* Can't store the compressed latency */ ++ g_assert_false(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node'," ++ " 'arguments': { 'type': 'hmat-lb', 'initiator': 0, 'target': 0," ++ " 'hierarchy': \"memory\", 'data-type': \"access-latency\"," ++ " 'latency': 1 } }"))); /* 1 ns */ ++ g_assert_true(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node'," ++ " 'arguments': { 'type': 'hmat-lb', 'initiator': 0, 'target': 1," ++ " 'hierarchy': \"memory\", 'data-type': \"access-latency\"," ++ " 'latency': 65535 } }"))); /* 65535 ns */ ++ ++ /* Test the 0 input (bandwidth not provided) */ ++ g_assert_false(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node'," ++ " 'arguments': { 'type': 'hmat-lb', 'initiator': 0, 'target': 0," ++ " 'hierarchy': \"memory\", 'data-type': \"access-bandwidth\"," ++ " 'bandwidth': 0 } }"))); /* 0 MB/s */ ++ /* Fail: bandwidth should be provided before memory side cache attributes */ ++ g_assert_true(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node'," ++ " 'arguments': { 'type': 'hmat-cache', 'node-id': 0, 'size': 10240," ++ " 'level': 1, 'associativity': \"direct\", 'policy': \"write-back\"," ++ " 'line': 8 } }"))); ++ ++ /* Can't store the compressed bandwidth */ ++ g_assert_true(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node'," ++ " 'arguments': { 'type': 'hmat-lb', 'initiator': 0, 'target': 1," ++ " 'hierarchy': \"memory\", 'data-type': \"access-bandwidth\"," ++ " 'bandwidth': 68718428160 } }"))); /* 65535 MB/s */ ++ ++ /* let machine initialization to complete and run */ ++ g_assert_false(qmp_rsp_is_err(qtest_qmp(qs, ++ "{ 'execute': 'x-exit-preconfig' }"))); ++ qtest_qmp_eventwait(qs, "RESUME"); ++ ++ qtest_quit(qs); ++} ++ + int main(int argc, char **argv) + { + const char *args = NULL; +@@ -346,6 +556,9 @@ int main(int argc, char **argv) + if (!strcmp(arch, "i386") || !strcmp(arch, "x86_64")) { + qtest_add_data_func("/numa/pc/cpu/explicit", args, pc_numa_cpu); + qtest_add_data_func("/numa/pc/dynamic/cpu", args, pc_dynamic_cpu_cfg); ++ qtest_add_data_func("/numa/pc/hmat/build", args, pc_hmat_build_cfg); ++ qtest_add_data_func("/numa/pc/hmat/off", args, pc_hmat_off_cfg); ++ qtest_add_data_func("/numa/pc/hmat/erange", args, pc_hmat_erange_cfg); + } + + if (!strcmp(arch, "ppc64")) { +-- +1.8.3.1 + diff --git a/SOURCES/kvm-tools-virtiofsd-passthrough_ll-Fix-double-close.patch b/SOURCES/kvm-tools-virtiofsd-passthrough_ll-Fix-double-close.patch new file mode 100644 index 0000000..6af549a --- /dev/null +++ b/SOURCES/kvm-tools-virtiofsd-passthrough_ll-Fix-double-close.patch @@ -0,0 +1,56 @@ +From 8ce8ccc2a22798a89bac06a37427c3a3cea91a62 Mon Sep 17 00:00:00 2001 +From: "Dr. David Alan Gilbert" +Date: Tue, 5 May 2020 16:35:54 +0100 +Subject: [PATCH 3/9] tools/virtiofsd/passthrough_ll: Fix double close() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Dr. David Alan Gilbert +Message-id: <20200505163600.22956-2-dgilbert@redhat.com> +Patchwork-id: 96269 +O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH 1/7] tools/virtiofsd/passthrough_ll: Fix double close() +Bugzilla: 1817445 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Max Reitz +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Michael S. Tsirkin + +From: Philippe Mathieu-Daudé + +On success, the fdopendir() call closes fd. Later on the error +path we try to close an already-closed fd. This can lead to +use-after-free. Fix by only closing the fd if the fdopendir() +call failed. + +Cc: qemu-stable@nongnu.org +Fixes: b39bce121b (add dirp_map to hide lo_dirp pointers) +Reported-by: Coverity (CID 1421933 USE_AFTER_FREE) +Suggested-by: Peter Maydell +Signed-off-by: Philippe Mathieu-Daudé +Message-Id: <20200321120654.7985-1-philmd@redhat.com> +Reviewed-by: Stefan Hajnoczi +Signed-off-by: Dr. David Alan Gilbert +(cherry picked from commit e1cd92d95cd4f97b3464c4e08cd5b22bf5ca05cb) +Signed-off-by: Danilo C. L. de Paula +--- + tools/virtiofsd/passthrough_ll.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c +index 9cba3f1..50ff672 100644 +--- a/tools/virtiofsd/passthrough_ll.c ++++ b/tools/virtiofsd/passthrough_ll.c +@@ -1524,8 +1524,7 @@ out_err: + if (d) { + if (d->dp) { + closedir(d->dp); +- } +- if (fd != -1) { ++ } else if (fd != -1) { + close(fd); + } + free(d); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-vfio-ccw-Add-support-for-the-CRW-region-and-IRQ.patch b/SOURCES/kvm-vfio-ccw-Add-support-for-the-CRW-region-and-IRQ.patch new file mode 100644 index 0000000..c515676 --- /dev/null +++ b/SOURCES/kvm-vfio-ccw-Add-support-for-the-CRW-region-and-IRQ.patch @@ -0,0 +1,175 @@ +From 58edd0fba4d9e98edfeb16139467d6035a1f4e61 Mon Sep 17 00:00:00 2001 +From: Cornelia Huck +Date: Tue, 23 Jun 2020 09:25:42 -0400 +Subject: [PATCH 08/12] vfio-ccw: Add support for the CRW region and IRQ + +RH-Author: Cornelia Huck +Message-id: <20200623092543.358315-9-cohuck@redhat.com> +Patchwork-id: 97698 +O-Subject: [RHEL-8.3.0 qemu-kvm PATCH 8/9] vfio-ccw: Add support for the CRW region and IRQ +Bugzilla: 1660916 +RH-Acked-by: Claudio Imbrenda +RH-Acked-by: David Hildenbrand +RH-Acked-by: Thomas Huth + +From: Farhan Ali + +The crw region can be used to obtain information about +Channel Report Words (CRW) from vfio-ccw driver. + +Currently only channel-path related CRWs are passed to +QEMU from vfio-ccw driver. + +Signed-off-by: Farhan Ali +Signed-off-by: Eric Farman +Reviewed-by: Cornelia Huck +Message-Id: <20200505125757.98209-7-farman@linux.ibm.com> +Signed-off-by: Cornelia Huck +(cherry picked from commit f030532f2ad6eeb200034915e9c6357cce81b538) +Signed-off-by: Cornelia Huck +Signed-off-by: Danilo C. L. de Paula +--- + hw/vfio/ccw.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 73 insertions(+) + +diff --git a/hw/vfio/ccw.c b/hw/vfio/ccw.c +index 94a0d9840d..b72a505893 100644 +--- a/hw/vfio/ccw.c ++++ b/hw/vfio/ccw.c +@@ -44,7 +44,11 @@ struct VFIOCCWDevice { + uint64_t schib_region_size; + uint64_t schib_region_offset; + struct ccw_schib_region *schib_region; ++ uint64_t crw_region_size; ++ uint64_t crw_region_offset; ++ struct ccw_crw_region *crw_region; + EventNotifier io_notifier; ++ EventNotifier crw_notifier; + bool force_orb_pfch; + bool warned_orb_pfch; + }; +@@ -254,6 +258,44 @@ static void vfio_ccw_reset(DeviceState *dev) + ioctl(vcdev->vdev.fd, VFIO_DEVICE_RESET); + } + ++static void vfio_ccw_crw_read(VFIOCCWDevice *vcdev) ++{ ++ struct ccw_crw_region *region = vcdev->crw_region; ++ CRW crw; ++ int size; ++ ++ /* Keep reading CRWs as long as data is returned */ ++ do { ++ memset(region, 0, sizeof(*region)); ++ size = pread(vcdev->vdev.fd, region, vcdev->crw_region_size, ++ vcdev->crw_region_offset); ++ ++ if (size == -1) { ++ error_report("vfio-ccw: Read crw region failed with errno=%d", ++ errno); ++ break; ++ } ++ ++ if (region->crw == 0) { ++ /* No more CRWs to queue */ ++ break; ++ } ++ ++ memcpy(&crw, ®ion->crw, sizeof(CRW)); ++ ++ css_crw_add_to_queue(crw); ++ } while (1); ++} ++ ++static void vfio_ccw_crw_notifier_handler(void *opaque) ++{ ++ VFIOCCWDevice *vcdev = opaque; ++ ++ while (event_notifier_test_and_clear(&vcdev->crw_notifier)) { ++ vfio_ccw_crw_read(vcdev); ++ } ++} ++ + static void vfio_ccw_io_notifier_handler(void *opaque) + { + VFIOCCWDevice *vcdev = opaque; +@@ -340,6 +382,10 @@ static void vfio_ccw_register_irq_notifier(VFIOCCWDevice *vcdev, + notifier = &vcdev->io_notifier; + fd_read = vfio_ccw_io_notifier_handler; + break; ++ case VFIO_CCW_CRW_IRQ_INDEX: ++ notifier = &vcdev->crw_notifier; ++ fd_read = vfio_ccw_crw_notifier_handler; ++ break; + default: + error_setg(errp, "vfio: Unsupported device irq(%d)", irq); + return; +@@ -391,6 +437,9 @@ static void vfio_ccw_unregister_irq_notifier(VFIOCCWDevice *vcdev, + case VFIO_CCW_IO_IRQ_INDEX: + notifier = &vcdev->io_notifier; + break; ++ case VFIO_CCW_CRW_IRQ_INDEX: ++ notifier = &vcdev->crw_notifier; ++ break; + default: + error_report("vfio: Unsupported device irq(%d)", irq); + return; +@@ -468,10 +517,24 @@ static void vfio_ccw_get_region(VFIOCCWDevice *vcdev, Error **errp) + vcdev->schib_region = g_malloc(info->size); + } + ++ ret = vfio_get_dev_region_info(vdev, VFIO_REGION_TYPE_CCW, ++ VFIO_REGION_SUBTYPE_CCW_CRW, &info); ++ ++ if (!ret) { ++ vcdev->crw_region_size = info->size; ++ if (sizeof(*vcdev->crw_region) != vcdev->crw_region_size) { ++ error_setg(errp, "vfio: Unexpected size of the CRW region"); ++ goto out_err; ++ } ++ vcdev->crw_region_offset = info->offset; ++ vcdev->crw_region = g_malloc(info->size); ++ } ++ + g_free(info); + return; + + out_err: ++ g_free(vcdev->crw_region); + g_free(vcdev->schib_region); + g_free(vcdev->async_cmd_region); + g_free(vcdev->io_region); +@@ -481,6 +544,7 @@ out_err: + + static void vfio_ccw_put_region(VFIOCCWDevice *vcdev) + { ++ g_free(vcdev->crw_region); + g_free(vcdev->schib_region); + g_free(vcdev->async_cmd_region); + g_free(vcdev->io_region); +@@ -596,6 +660,14 @@ static void vfio_ccw_realize(DeviceState *dev, Error **errp) + goto out_notifier_err; + } + ++ if (vcdev->crw_region) { ++ vfio_ccw_register_irq_notifier(vcdev, VFIO_CCW_CRW_IRQ_INDEX, &err); ++ if (err) { ++ vfio_ccw_unregister_irq_notifier(vcdev, VFIO_CCW_IO_IRQ_INDEX); ++ goto out_notifier_err; ++ } ++ } ++ + return; + + out_notifier_err: +@@ -620,6 +692,7 @@ static void vfio_ccw_unrealize(DeviceState *dev, Error **errp) + S390CCWDeviceClass *cdc = S390_CCW_DEVICE_GET_CLASS(cdev); + VFIOGroup *group = vcdev->vdev.group; + ++ vfio_ccw_unregister_irq_notifier(vcdev, VFIO_CCW_CRW_IRQ_INDEX); + vfio_ccw_unregister_irq_notifier(vcdev, VFIO_CCW_IO_IRQ_INDEX); + vfio_ccw_put_region(vcdev); + vfio_ccw_put_device(vcdev); +-- +2.27.0 + diff --git a/SOURCES/kvm-vfio-ccw-Add-support-for-the-schib-region.patch b/SOURCES/kvm-vfio-ccw-Add-support-for-the-schib-region.patch new file mode 100644 index 0000000..667e5cf --- /dev/null +++ b/SOURCES/kvm-vfio-ccw-Add-support-for-the-schib-region.patch @@ -0,0 +1,254 @@ +From b73e3e52f76db823d7bffe3f705f575ca413863b Mon Sep 17 00:00:00 2001 +From: Cornelia Huck +Date: Tue, 23 Jun 2020 09:25:39 -0400 +Subject: [PATCH 05/12] vfio-ccw: Add support for the schib region + +RH-Author: Cornelia Huck +Message-id: <20200623092543.358315-6-cohuck@redhat.com> +Patchwork-id: 97697 +O-Subject: [RHEL-8.3.0 qemu-kvm PATCH 5/9] vfio-ccw: Add support for the schib region +Bugzilla: 1660916 +RH-Acked-by: Claudio Imbrenda +RH-Acked-by: David Hildenbrand +RH-Acked-by: Thomas Huth + +From: Farhan Ali + +The schib region can be used to obtain the latest SCHIB from the host +passthrough subchannel. Since the guest SCHIB is virtualized, +we currently only update the path related information so that the +guest is aware of any path related changes when it issues the +'stsch' instruction. + +Signed-off-by: Farhan Ali +Signed-off-by: Eric Farman +Reviewed-by: Cornelia Huck +Message-Id: <20200505125757.98209-4-farman@linux.ibm.com> +Signed-off-by: Cornelia Huck +(cherry picked from commit 46ea3841edaff2a7657b8f6c7f474e5e3850cd62) +Signed-off-by: Cornelia Huck +Signed-off-by: Danilo C. L. de Paula +--- + hw/s390x/css.c | 13 ++++++-- + hw/s390x/s390-ccw.c | 21 +++++++++++++ + hw/vfio/ccw.c | 63 +++++++++++++++++++++++++++++++++++++ + include/hw/s390x/css.h | 3 +- + include/hw/s390x/s390-ccw.h | 1 + + target/s390x/ioinst.c | 3 +- + 6 files changed, 99 insertions(+), 5 deletions(-) + +diff --git a/hw/s390x/css.c b/hw/s390x/css.c +index 844caab408..71fd3f9a00 100644 +--- a/hw/s390x/css.c ++++ b/hw/s390x/css.c +@@ -1335,11 +1335,20 @@ static void copy_schib_to_guest(SCHIB *dest, const SCHIB *src) + } + } + +-int css_do_stsch(SubchDev *sch, SCHIB *schib) ++IOInstEnding css_do_stsch(SubchDev *sch, SCHIB *schib) + { ++ int ret; ++ ++ /* ++ * For some subchannels, we may want to update parts of ++ * the schib (e.g., update path masks from the host device ++ * for passthrough subchannels). ++ */ ++ ret = s390_ccw_store(sch); ++ + /* Use current status. */ + copy_schib_to_guest(schib, &sch->curr_status); +- return 0; ++ return ret; + } + + static void copy_pmcw_from_guest(PMCW *dest, const PMCW *src) +diff --git a/hw/s390x/s390-ccw.c b/hw/s390x/s390-ccw.c +index 0c5a5b60bd..75b788c95e 100644 +--- a/hw/s390x/s390-ccw.c ++++ b/hw/s390x/s390-ccw.c +@@ -51,6 +51,27 @@ int s390_ccw_clear(SubchDev *sch) + return cdc->handle_clear(sch); + } + ++IOInstEnding s390_ccw_store(SubchDev *sch) ++{ ++ S390CCWDeviceClass *cdc = NULL; ++ int ret = IOINST_CC_EXPECTED; ++ ++ /* ++ * This code is called for both virtual and passthrough devices, ++ * but only applies to to the latter. This ugly check makes that ++ * distinction for us. ++ */ ++ if (object_dynamic_cast(OBJECT(sch->driver_data), TYPE_S390_CCW)) { ++ cdc = S390_CCW_DEVICE_GET_CLASS(sch->driver_data); ++ } ++ ++ if (cdc && cdc->handle_store) { ++ ret = cdc->handle_store(sch); ++ } ++ ++ return ret; ++} ++ + static void s390_ccw_get_dev_info(S390CCWDevice *cdev, + char *sysfsdev, + Error **errp) +diff --git a/hw/vfio/ccw.c b/hw/vfio/ccw.c +index 17eb4c4048..859ad646f1 100644 +--- a/hw/vfio/ccw.c ++++ b/hw/vfio/ccw.c +@@ -41,6 +41,9 @@ struct VFIOCCWDevice { + uint64_t async_cmd_region_size; + uint64_t async_cmd_region_offset; + struct ccw_cmd_region *async_cmd_region; ++ uint64_t schib_region_size; ++ uint64_t schib_region_offset; ++ struct ccw_schib_region *schib_region; + EventNotifier io_notifier; + bool force_orb_pfch; + bool warned_orb_pfch; +@@ -116,6 +119,51 @@ again: + } + } + ++static IOInstEnding vfio_ccw_handle_store(SubchDev *sch) ++{ ++ S390CCWDevice *cdev = sch->driver_data; ++ VFIOCCWDevice *vcdev = DO_UPCAST(VFIOCCWDevice, cdev, cdev); ++ SCHIB *schib = &sch->curr_status; ++ struct ccw_schib_region *region = vcdev->schib_region; ++ SCHIB *s; ++ int ret; ++ ++ /* schib region not available so nothing else to do */ ++ if (!region) { ++ return IOINST_CC_EXPECTED; ++ } ++ ++ memset(region, 0, sizeof(*region)); ++ ret = pread(vcdev->vdev.fd, region, vcdev->schib_region_size, ++ vcdev->schib_region_offset); ++ ++ if (ret == -1) { ++ /* ++ * Device is probably damaged, but store subchannel does not ++ * have a nonzero cc defined for this scenario. Log an error, ++ * and presume things are otherwise fine. ++ */ ++ error_report("vfio-ccw: store region read failed with errno=%d", errno); ++ return IOINST_CC_EXPECTED; ++ } ++ ++ /* ++ * Selectively copy path-related bits of the SCHIB, ++ * rather than copying the entire struct. ++ */ ++ s = (SCHIB *)region->schib_area; ++ schib->pmcw.pnom = s->pmcw.pnom; ++ schib->pmcw.lpum = s->pmcw.lpum; ++ schib->pmcw.pam = s->pmcw.pam; ++ schib->pmcw.pom = s->pmcw.pom; ++ ++ if (s->scsw.flags & SCSW_FLAGS_MASK_PNO) { ++ schib->scsw.flags |= SCSW_FLAGS_MASK_PNO; ++ } ++ ++ return IOINST_CC_EXPECTED; ++} ++ + static int vfio_ccw_handle_clear(SubchDev *sch) + { + S390CCWDevice *cdev = sch->driver_data; +@@ -382,10 +430,23 @@ static void vfio_ccw_get_region(VFIOCCWDevice *vcdev, Error **errp) + vcdev->async_cmd_region = g_malloc0(info->size); + } + ++ ret = vfio_get_dev_region_info(vdev, VFIO_REGION_TYPE_CCW, ++ VFIO_REGION_SUBTYPE_CCW_SCHIB, &info); ++ if (!ret) { ++ vcdev->schib_region_size = info->size; ++ if (sizeof(*vcdev->schib_region) != vcdev->schib_region_size) { ++ error_setg(errp, "vfio: Unexpected size of the schib region"); ++ goto out_err; ++ } ++ vcdev->schib_region_offset = info->offset; ++ vcdev->schib_region = g_malloc(info->size); ++ } ++ + g_free(info); + return; + + out_err: ++ g_free(vcdev->schib_region); + g_free(vcdev->async_cmd_region); + g_free(vcdev->io_region); + g_free(info); +@@ -394,6 +455,7 @@ out_err: + + static void vfio_ccw_put_region(VFIOCCWDevice *vcdev) + { ++ g_free(vcdev->schib_region); + g_free(vcdev->async_cmd_region); + g_free(vcdev->io_region); + } +@@ -569,6 +631,7 @@ static void vfio_ccw_class_init(ObjectClass *klass, void *data) + cdc->handle_request = vfio_ccw_handle_request; + cdc->handle_halt = vfio_ccw_handle_halt; + cdc->handle_clear = vfio_ccw_handle_clear; ++ cdc->handle_store = vfio_ccw_handle_store; + } + + static const TypeInfo vfio_ccw_info = { +diff --git a/include/hw/s390x/css.h b/include/hw/s390x/css.h +index f46bcafb16..7e3a5e7433 100644 +--- a/include/hw/s390x/css.h ++++ b/include/hw/s390x/css.h +@@ -218,6 +218,7 @@ IOInstEnding do_subchannel_work_passthrough(SubchDev *sub); + + int s390_ccw_halt(SubchDev *sch); + int s390_ccw_clear(SubchDev *sch); ++IOInstEnding s390_ccw_store(SubchDev *sch); + + typedef enum { + CSS_IO_ADAPTER_VIRTIO = 0, +@@ -242,7 +243,7 @@ SubchDev *css_find_subch(uint8_t m, uint8_t cssid, uint8_t ssid, + uint16_t schid); + bool css_subch_visible(SubchDev *sch); + void css_conditional_io_interrupt(SubchDev *sch); +-int css_do_stsch(SubchDev *sch, SCHIB *schib); ++IOInstEnding css_do_stsch(SubchDev *sch, SCHIB *schib); + bool css_schid_final(int m, uint8_t cssid, uint8_t ssid, uint16_t schid); + IOInstEnding css_do_msch(SubchDev *sch, const SCHIB *schib); + IOInstEnding css_do_xsch(SubchDev *sch); +diff --git a/include/hw/s390x/s390-ccw.h b/include/hw/s390x/s390-ccw.h +index fffb54562f..4a43803ef2 100644 +--- a/include/hw/s390x/s390-ccw.h ++++ b/include/hw/s390x/s390-ccw.h +@@ -37,6 +37,7 @@ typedef struct S390CCWDeviceClass { + IOInstEnding (*handle_request) (SubchDev *sch); + int (*handle_halt) (SubchDev *sch); + int (*handle_clear) (SubchDev *sch); ++ IOInstEnding (*handle_store) (SubchDev *sch); + } S390CCWDeviceClass; + + #endif +diff --git a/target/s390x/ioinst.c b/target/s390x/ioinst.c +index f40c35c6ff..b6be300cc4 100644 +--- a/target/s390x/ioinst.c ++++ b/target/s390x/ioinst.c +@@ -292,8 +292,7 @@ void ioinst_handle_stsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb, + sch = css_find_subch(m, cssid, ssid, schid); + if (sch) { + if (css_subch_visible(sch)) { +- css_do_stsch(sch, &schib); +- cc = 0; ++ cc = css_do_stsch(sch, &schib); + } else { + /* Indicate no more subchannels in this css/ss */ + cc = 3; +-- +2.27.0 + diff --git a/SOURCES/kvm-vfio-ccw-Fix-error-message.patch b/SOURCES/kvm-vfio-ccw-Fix-error-message.patch new file mode 100644 index 0000000..86d2fdf --- /dev/null +++ b/SOURCES/kvm-vfio-ccw-Fix-error-message.patch @@ -0,0 +1,48 @@ +From 7258b1fabcd152c2ad9b61485b869a41d1bc64e2 Mon Sep 17 00:00:00 2001 +From: Cornelia Huck +Date: Tue, 23 Jun 2020 09:25:35 -0400 +Subject: [PATCH 01/12] vfio-ccw: Fix error message +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Cornelia Huck +Message-id: <20200623092543.358315-2-cohuck@redhat.com> +Patchwork-id: 97693 +O-Subject: [RHEL-8.3.0 qemu-kvm PATCH 1/9] vfio-ccw: Fix error message +Bugzilla: 1660916 +RH-Acked-by: Claudio Imbrenda +RH-Acked-by: David Hildenbrand +RH-Acked-by: Thomas Huth +RH-Acked-by: Philippe Mathieu-Daudé + +From: Boris Fiuczynski + +Signed-off-by: Boris Fiuczynski +Reviewed-by: Eric Farman +Message-Id: <20191128143015.5231-1-fiuczy@linux.ibm.com> +Reviewed-by: Philippe Mathieu-Daudé +Signed-off-by: Cornelia Huck +(cherry picked from commit 91f751dc111b270b1e81d80ac92cf479e7620fa4) +Signed-off-by: Cornelia Huck +Signed-off-by: Danilo C. L. de Paula +--- + hw/vfio/ccw.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/vfio/ccw.c b/hw/vfio/ccw.c +index 6863f6c69f..3b5520ae75 100644 +--- a/hw/vfio/ccw.c ++++ b/hw/vfio/ccw.c +@@ -102,7 +102,7 @@ again: + if (errno == EAGAIN) { + goto again; + } +- error_report("vfio-ccw: wirte I/O region failed with errno=%d", errno); ++ error_report("vfio-ccw: write I/O region failed with errno=%d", errno); + ret = -errno; + } else { + ret = region->ret_code; +-- +2.27.0 + diff --git a/SOURCES/kvm-vfio-ccw-Refactor-ccw-irq-handler.patch b/SOURCES/kvm-vfio-ccw-Refactor-ccw-irq-handler.patch new file mode 100644 index 0000000..8a3514d --- /dev/null +++ b/SOURCES/kvm-vfio-ccw-Refactor-ccw-irq-handler.patch @@ -0,0 +1,155 @@ +From ee9b03e774641fba8baaf85256706fcc5e8d8efa Mon Sep 17 00:00:00 2001 +From: Cornelia Huck +Date: Tue, 23 Jun 2020 09:25:40 -0400 +Subject: [PATCH 06/12] vfio-ccw: Refactor ccw irq handler + +RH-Author: Cornelia Huck +Message-id: <20200623092543.358315-7-cohuck@redhat.com> +Patchwork-id: 97695 +O-Subject: [RHEL-8.3.0 qemu-kvm PATCH 6/9] vfio-ccw: Refactor ccw irq handler +Bugzilla: 1660916 +RH-Acked-by: Claudio Imbrenda +RH-Acked-by: David Hildenbrand +RH-Acked-by: Thomas Huth + +From: Eric Farman + +Make it easier to add new ones in the future. + +Signed-off-by: Eric Farman +Reviewed-by: Cornelia Huck +Message-Id: <20200505125757.98209-5-farman@linux.ibm.com> +Signed-off-by: Cornelia Huck +(cherry picked from commit 690e29b91102ac69810b35fe72cd90bc9fa1fff7) +Signed-off-by: Cornelia Huck +Signed-off-by: Danilo C. L. de Paula +--- + hw/vfio/ccw.c | 58 +++++++++++++++++++++++++++++++++++++-------------- + 1 file changed, 42 insertions(+), 16 deletions(-) + +diff --git a/hw/vfio/ccw.c b/hw/vfio/ccw.c +index 859ad646f1..94a0d9840d 100644 +--- a/hw/vfio/ccw.c ++++ b/hw/vfio/ccw.c +@@ -324,22 +324,36 @@ read_err: + css_inject_io_interrupt(sch); + } + +-static void vfio_ccw_register_io_notifier(VFIOCCWDevice *vcdev, Error **errp) ++static void vfio_ccw_register_irq_notifier(VFIOCCWDevice *vcdev, ++ unsigned int irq, ++ Error **errp) + { + VFIODevice *vdev = &vcdev->vdev; + struct vfio_irq_info *irq_info; + size_t argsz; + int fd; ++ EventNotifier *notifier; ++ IOHandler *fd_read; ++ ++ switch (irq) { ++ case VFIO_CCW_IO_IRQ_INDEX: ++ notifier = &vcdev->io_notifier; ++ fd_read = vfio_ccw_io_notifier_handler; ++ break; ++ default: ++ error_setg(errp, "vfio: Unsupported device irq(%d)", irq); ++ return; ++ } + +- if (vdev->num_irqs < VFIO_CCW_IO_IRQ_INDEX + 1) { +- error_setg(errp, "vfio: unexpected number of io irqs %u", ++ if (vdev->num_irqs < irq + 1) { ++ error_setg(errp, "vfio: unexpected number of irqs %u", + vdev->num_irqs); + return; + } + + argsz = sizeof(*irq_info); + irq_info = g_malloc0(argsz); +- irq_info->index = VFIO_CCW_IO_IRQ_INDEX; ++ irq_info->index = irq; + irq_info->argsz = argsz; + if (ioctl(vdev->fd, VFIO_DEVICE_GET_IRQ_INFO, + irq_info) < 0 || irq_info->count < 1) { +@@ -347,37 +361,49 @@ static void vfio_ccw_register_io_notifier(VFIOCCWDevice *vcdev, Error **errp) + goto out_free_info; + } + +- if (event_notifier_init(&vcdev->io_notifier, 0)) { ++ if (event_notifier_init(notifier, 0)) { + error_setg_errno(errp, errno, +- "vfio: Unable to init event notifier for IO"); ++ "vfio: Unable to init event notifier for irq (%d)", ++ irq); + goto out_free_info; + } + +- fd = event_notifier_get_fd(&vcdev->io_notifier); +- qemu_set_fd_handler(fd, vfio_ccw_io_notifier_handler, NULL, vcdev); ++ fd = event_notifier_get_fd(notifier); ++ qemu_set_fd_handler(fd, fd_read, NULL, vcdev); + +- if (vfio_set_irq_signaling(vdev, VFIO_CCW_IO_IRQ_INDEX, 0, ++ if (vfio_set_irq_signaling(vdev, irq, 0, + VFIO_IRQ_SET_ACTION_TRIGGER, fd, errp)) { + qemu_set_fd_handler(fd, NULL, NULL, vcdev); +- event_notifier_cleanup(&vcdev->io_notifier); ++ event_notifier_cleanup(notifier); + } + + out_free_info: + g_free(irq_info); + } + +-static void vfio_ccw_unregister_io_notifier(VFIOCCWDevice *vcdev) ++static void vfio_ccw_unregister_irq_notifier(VFIOCCWDevice *vcdev, ++ unsigned int irq) + { + Error *err = NULL; ++ EventNotifier *notifier; ++ ++ switch (irq) { ++ case VFIO_CCW_IO_IRQ_INDEX: ++ notifier = &vcdev->io_notifier; ++ break; ++ default: ++ error_report("vfio: Unsupported device irq(%d)", irq); ++ return; ++ } + +- if (vfio_set_irq_signaling(&vcdev->vdev, VFIO_CCW_IO_IRQ_INDEX, 0, ++ if (vfio_set_irq_signaling(&vcdev->vdev, irq, 0, + VFIO_IRQ_SET_ACTION_TRIGGER, -1, &err)) { + error_reportf_err(err, VFIO_MSG_PREFIX, vcdev->vdev.name); + } + +- qemu_set_fd_handler(event_notifier_get_fd(&vcdev->io_notifier), ++ qemu_set_fd_handler(event_notifier_get_fd(notifier), + NULL, NULL, vcdev); +- event_notifier_cleanup(&vcdev->io_notifier); ++ event_notifier_cleanup(notifier); + } + + static void vfio_ccw_get_region(VFIOCCWDevice *vcdev, Error **errp) +@@ -565,7 +591,7 @@ static void vfio_ccw_realize(DeviceState *dev, Error **errp) + goto out_region_err; + } + +- vfio_ccw_register_io_notifier(vcdev, &err); ++ vfio_ccw_register_irq_notifier(vcdev, VFIO_CCW_IO_IRQ_INDEX, &err); + if (err) { + goto out_notifier_err; + } +@@ -594,7 +620,7 @@ static void vfio_ccw_unrealize(DeviceState *dev, Error **errp) + S390CCWDeviceClass *cdc = S390_CCW_DEVICE_GET_CLASS(cdev); + VFIOGroup *group = vcdev->vdev.group; + +- vfio_ccw_unregister_io_notifier(vcdev); ++ vfio_ccw_unregister_irq_notifier(vcdev, VFIO_CCW_IO_IRQ_INDEX); + vfio_ccw_put_region(vcdev); + vfio_ccw_put_device(vcdev); + vfio_put_group(group); +-- +2.27.0 + diff --git a/SOURCES/kvm-vfio-ccw-Refactor-cleanup-of-regions.patch b/SOURCES/kvm-vfio-ccw-Refactor-cleanup-of-regions.patch new file mode 100644 index 0000000..1741f4b --- /dev/null +++ b/SOURCES/kvm-vfio-ccw-Refactor-cleanup-of-regions.patch @@ -0,0 +1,73 @@ +From 30906c9c78af2710a2b86c096cc7b18bbc4b4e69 Mon Sep 17 00:00:00 2001 +From: Cornelia Huck +Date: Tue, 23 Jun 2020 09:25:38 -0400 +Subject: [PATCH 04/12] vfio-ccw: Refactor cleanup of regions + +RH-Author: Cornelia Huck +Message-id: <20200623092543.358315-5-cohuck@redhat.com> +Patchwork-id: 97694 +O-Subject: [RHEL-8.3.0 qemu-kvm PATCH 4/9] vfio-ccw: Refactor cleanup of regions +Bugzilla: 1660916 +RH-Acked-by: Claudio Imbrenda +RH-Acked-by: David Hildenbrand +RH-Acked-by: Thomas Huth + +From: Eric Farman + +While we're at it, add a g_free() for the async_cmd_region that +is the last thing currently created. g_free() knows how to handle +NULL pointers, so this makes it easier to remember what cleanups +need to be performed when new regions are added. + +Signed-off-by: Eric Farman +Reviewed-by: Cornelia Huck +Message-Id: <20200505125757.98209-3-farman@linux.ibm.com> +Signed-off-by: Cornelia Huck +(cherry picked from commit 2a3b9cbaa7b25a4db4cdcfe1c65279c5464f2923) +Signed-off-by: Cornelia Huck +Signed-off-by: Danilo C. L. de Paula +--- + hw/vfio/ccw.c | 14 +++++++++----- + 1 file changed, 9 insertions(+), 5 deletions(-) + +diff --git a/hw/vfio/ccw.c b/hw/vfio/ccw.c +index 6bc612b5b7..17eb4c4048 100644 +--- a/hw/vfio/ccw.c ++++ b/hw/vfio/ccw.c +@@ -363,8 +363,7 @@ static void vfio_ccw_get_region(VFIOCCWDevice *vcdev, Error **errp) + vcdev->io_region_size = info->size; + if (sizeof(*vcdev->io_region) != vcdev->io_region_size) { + error_setg(errp, "vfio: Unexpected size of the I/O region"); +- g_free(info); +- return; ++ goto out_err; + } + + vcdev->io_region_offset = info->offset; +@@ -377,15 +376,20 @@ static void vfio_ccw_get_region(VFIOCCWDevice *vcdev, Error **errp) + vcdev->async_cmd_region_size = info->size; + if (sizeof(*vcdev->async_cmd_region) != vcdev->async_cmd_region_size) { + error_setg(errp, "vfio: Unexpected size of the async cmd region"); +- g_free(vcdev->io_region); +- g_free(info); +- return; ++ goto out_err; + } + vcdev->async_cmd_region_offset = info->offset; + vcdev->async_cmd_region = g_malloc0(info->size); + } + + g_free(info); ++ return; ++ ++out_err: ++ g_free(vcdev->async_cmd_region); ++ g_free(vcdev->io_region); ++ g_free(info); ++ return; + } + + static void vfio_ccw_put_region(VFIOCCWDevice *vcdev) +-- +2.27.0 + diff --git a/SOURCES/kvm-vfio-ccw-allow-non-prefetch-ORBs.patch b/SOURCES/kvm-vfio-ccw-allow-non-prefetch-ORBs.patch new file mode 100644 index 0000000..da2fc5c --- /dev/null +++ b/SOURCES/kvm-vfio-ccw-allow-non-prefetch-ORBs.patch @@ -0,0 +1,61 @@ +From d5f5a307f3396064d29ef0d300c7377756dd165b Mon Sep 17 00:00:00 2001 +From: Cornelia Huck +Date: Tue, 23 Jun 2020 09:25:36 -0400 +Subject: [PATCH 02/12] vfio-ccw: allow non-prefetch ORBs + +RH-Author: Cornelia Huck +Message-id: <20200623092543.358315-3-cohuck@redhat.com> +Patchwork-id: 97692 +O-Subject: [RHEL-8.3.0 qemu-kvm PATCH 2/9] vfio-ccw: allow non-prefetch ORBs +Bugzilla: 1660916 +RH-Acked-by: Claudio Imbrenda +RH-Acked-by: David Hildenbrand +RH-Acked-by: Thomas Huth + +From: Jared Rossi + +Remove the explicit prefetch check when using vfio-ccw devices. +This check does not trigger in practice as all Linux channel programs +are intended to use prefetch. + +Newer Linux kernel versions do not require to force the PFCH flag with +vfio-ccw devices anymore. + +Signed-off-by: Jared Rossi +Reviewed-by: Eric Farman +Message-Id: <20200512181535.18630-2-jrossi@linux.ibm.com> +Signed-off-by: Cornelia Huck +(cherry picked from commit 24e58a7b1d411627e326144030a20dcf0093fed0) +Signed-off-by: Cornelia Huck +Signed-off-by: Danilo C. L. de Paula +--- + hw/vfio/ccw.c | 13 +++---------- + 1 file changed, 3 insertions(+), 10 deletions(-) + +diff --git a/hw/vfio/ccw.c b/hw/vfio/ccw.c +index 3b5520ae75..6bc612b5b7 100644 +--- a/hw/vfio/ccw.c ++++ b/hw/vfio/ccw.c +@@ -74,16 +74,9 @@ static IOInstEnding vfio_ccw_handle_request(SubchDev *sch) + struct ccw_io_region *region = vcdev->io_region; + int ret; + +- if (!(sch->orb.ctrl0 & ORB_CTRL0_MASK_PFCH)) { +- if (!(vcdev->force_orb_pfch)) { +- warn_once_pfch(vcdev, sch, "requires PFCH flag set"); +- sch_gen_unit_exception(sch); +- css_inject_io_interrupt(sch); +- return IOINST_CC_EXPECTED; +- } else { +- sch->orb.ctrl0 |= ORB_CTRL0_MASK_PFCH; +- warn_once_pfch(vcdev, sch, "PFCH flag forced"); +- } ++ if (!(sch->orb.ctrl0 & ORB_CTRL0_MASK_PFCH) && vcdev->force_orb_pfch) { ++ sch->orb.ctrl0 |= ORB_CTRL0_MASK_PFCH; ++ warn_once_pfch(vcdev, sch, "PFCH flag forced"); + } + + QEMU_BUILD_BUG_ON(sizeof(region->orb_area) != sizeof(ORB)); +-- +2.27.0 + diff --git a/SOURCES/kvm-vfio-nvlink-Remove-exec-permission-to-avoid-SELinux-.patch b/SOURCES/kvm-vfio-nvlink-Remove-exec-permission-to-avoid-SELinux-.patch new file mode 100644 index 0000000..81cf80e --- /dev/null +++ b/SOURCES/kvm-vfio-nvlink-Remove-exec-permission-to-avoid-SELinux-.patch @@ -0,0 +1,75 @@ +From f01098bb86c12f485895f38f7a24170ec84b60b6 Mon Sep 17 00:00:00 2001 +From: Greg Kurz +Date: Mon, 8 Jun 2020 16:25:21 -0400 +Subject: [PATCH 42/42] vfio/nvlink: Remove exec permission to avoid SELinux + AVCs +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Greg Kurz +Message-id: <20200608162521.382858-2-gkurz@redhat.com> +Patchwork-id: 97459 +O-Subject: [RHEL-8.3.0 qemu-kvm PATCH 1/1] vfio/nvlink: Remove exec permission to avoid SELinux AVCs +Bugzilla: 1823275 +RH-Acked-by: David Gibson +RH-Acked-by: Laurent Vivier +RH-Acked-by: Philippe Mathieu-Daudé + +From: Leonardo Bras + +If SELinux is setup without 'execmem' permission for qemu, all mmap +with (PROT_WRITE | PROT_EXEC) will fail and print a warning in +SELinux log. + +If "nvlink2-mr" memory allocation fails (fist diff), it will cause +guest NUMA nodes to not be correctly configured (V100 memory will +not be visible for guest, nor its NUMA nodes). + +Not having 'execmem' permission is intesting for virtual machines to +avoid buffer-overflow based attacks, and it's adopted in distros +like RHEL. + +So, removing the PROT_EXEC flag seems the right thing to do. + +Browsing some other code that mmaps memory for usage with +memory_region_init_ram_device_ptr, I could notice it's usual to +not have PROT_EXEC (only PROT_READ | PROT_WRITE), so it should be +no problem around this. + +Signed-off-by: Leonardo Bras +Message-Id: <20200501055448.286518-1-leobras.c@gmail.com> +Acked-by: Alex Williamson +Signed-off-by: David Gibson +(cherry picked from commit 9c7c0407028355ca83349b8a60fddfad46f2ebd8) +Signed-off-by: Greg Kurz +Signed-off-by: Danilo C. L. de Paula +--- + hw/vfio/pci-quirks.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/hw/vfio/pci-quirks.c b/hw/vfio/pci-quirks.c +index 4505ffe48a..1c5fe014cf 100644 +--- a/hw/vfio/pci-quirks.c ++++ b/hw/vfio/pci-quirks.c +@@ -2237,7 +2237,7 @@ int vfio_pci_nvidia_v100_ram_init(VFIOPCIDevice *vdev, Error **errp) + } + cap = (void *) hdr; + +- p = mmap(NULL, nv2reg->size, PROT_READ | PROT_WRITE | PROT_EXEC, ++ p = mmap(NULL, nv2reg->size, PROT_READ | PROT_WRITE, + MAP_SHARED, vdev->vbasedev.fd, nv2reg->offset); + if (p == MAP_FAILED) { + ret = -errno; +@@ -2297,7 +2297,7 @@ int vfio_pci_nvlink2_init(VFIOPCIDevice *vdev, Error **errp) + + /* Some NVLink bridges may not have assigned ATSD */ + if (atsdreg->size) { +- p = mmap(NULL, atsdreg->size, PROT_READ | PROT_WRITE | PROT_EXEC, ++ p = mmap(NULL, atsdreg->size, PROT_READ | PROT_WRITE, + MAP_SHARED, vdev->vbasedev.fd, atsdreg->offset); + if (p == MAP_FAILED) { + ret = -errno; +-- +2.27.0 + diff --git a/SOURCES/kvm-vhost-correctly-turn-on-VIRTIO_F_IOMMU_PLATFORM.patch b/SOURCES/kvm-vhost-correctly-turn-on-VIRTIO_F_IOMMU_PLATFORM.patch new file mode 100644 index 0000000..7e1353c --- /dev/null +++ b/SOURCES/kvm-vhost-correctly-turn-on-VIRTIO_F_IOMMU_PLATFORM.patch @@ -0,0 +1,69 @@ +From e06655cfe0fa9473b1e8b311571f36d787472834 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 29 May 2020 05:54:02 -0400 +Subject: [PATCH 20/42] vhost: correctly turn on VIRTIO_F_IOMMU_PLATFORM + +RH-Author: Thomas Huth +Message-id: <20200529055420.16855-21-thuth@redhat.com> +Patchwork-id: 97041 +O-Subject: [RHEL-8.3.0 qemu-kvm PATCH v2 20/38] vhost: correctly turn on VIRTIO_F_IOMMU_PLATFORM +Bugzilla: 1828317 +RH-Acked-by: Claudio Imbrenda +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand + +From: Jason Wang + +We turn on device IOTLB via VIRTIO_F_IOMMU_PLATFORM unconditionally on +platform without IOMMU support. This can lead unnecessary IOTLB +transactions which will damage the performance. + +Fixing this by check whether the device is backed by IOMMU and disable +device IOTLB. + +Reported-by: Halil Pasic +Tested-by: Halil Pasic +Reviewed-by: Halil Pasic +Signed-off-by: Jason Wang +Message-Id: <20200302042454.24814-1-jasowang@redhat.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +(cherry picked from commit f7ef7e6e3ba6e994e070cc609eb154339d1c4a11) +Signed-off-by: Danilo C. L. de Paula +--- + hw/virtio/vhost.c | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c +index 9edfadc81d..9182a00495 100644 +--- a/hw/virtio/vhost.c ++++ b/hw/virtio/vhost.c +@@ -290,7 +290,14 @@ static int vhost_dev_has_iommu(struct vhost_dev *dev) + { + VirtIODevice *vdev = dev->vdev; + +- return virtio_host_has_feature(vdev, VIRTIO_F_IOMMU_PLATFORM); ++ /* ++ * For vhost, VIRTIO_F_IOMMU_PLATFORM means the backend support ++ * incremental memory mapping API via IOTLB API. For platform that ++ * does not have IOMMU, there's no need to enable this feature ++ * which may cause unnecessary IOTLB miss/update trnasactions. ++ */ ++ return vdev->dma_as != &address_space_memory && ++ virtio_host_has_feature(vdev, VIRTIO_F_IOMMU_PLATFORM); + } + + static void *vhost_memory_map(struct vhost_dev *dev, hwaddr addr, +@@ -765,6 +772,9 @@ static int vhost_dev_set_features(struct vhost_dev *dev, + if (enable_log) { + features |= 0x1ULL << VHOST_F_LOG_ALL; + } ++ if (!vhost_dev_has_iommu(dev)) { ++ features &= ~(0x1ULL << VIRTIO_F_IOMMU_PLATFORM); ++ } + r = dev->vhost_ops->vhost_set_features(dev, features); + if (r < 0) { + VHOST_OPS_DEBUG("vhost_set_features failed"); +-- +2.27.0 + diff --git a/SOURCES/kvm-virtio-blk-On-restart-process-queued-requests-in-the.patch b/SOURCES/kvm-virtio-blk-On-restart-process-queued-requests-in-the.patch new file mode 100644 index 0000000..9e46be1 --- /dev/null +++ b/SOURCES/kvm-virtio-blk-On-restart-process-queued-requests-in-the.patch @@ -0,0 +1,203 @@ +From fdd1f3bf672ad8bb0a6db896ec8cbc797c31da1f Mon Sep 17 00:00:00 2001 +From: Sergio Lopez Pascual +Date: Wed, 24 Jun 2020 13:24:53 -0400 +Subject: [PATCH 11/12] virtio-blk: On restart, process queued requests in the + proper context + +RH-Author: Sergio Lopez Pascual +Message-id: <20200624132453.111276-3-slp@redhat.com> +Patchwork-id: 97798 +O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH 2/2] virtio-blk: On restart, process queued requests in the proper context +Bugzilla: +RH-Acked-by: John Snow +RH-Acked-by: Michael S. Tsirkin +RH-Acked-by: Kevin Wolf + +On restart, we were scheduling a BH to process queued requests, which +would run before starting up the data plane, leading to those requests +being assigned and started on coroutines on the main context. + +This could cause requests to be wrongly processed in parallel from +different threads (the main thread and the iothread managing the data +plane), potentially leading to multiple issues. + +For example, stopping and resuming a VM multiple times while the guest +is generating I/O on a virtio_blk device can trigger a crash with a +stack tracing looking like this one: + +<------> + Thread 2 (Thread 0x7ff736765700 (LWP 1062503)): + #0 0x00005567a13b99d6 in iov_memset + (iov=0x6563617073206f4e, iov_cnt=1717922848, offset=516096, fillc=0, bytes=7018105756081554803) + at util/iov.c:69 + #1 0x00005567a13bab73 in qemu_iovec_memset + (qiov=0x7ff73ec99748, offset=516096, fillc=0, bytes=7018105756081554803) at util/iov.c:530 + #2 0x00005567a12f411c in qemu_laio_process_completion (laiocb=0x7ff6512ee6c0) at block/linux-aio.c:86 + #3 0x00005567a12f42ff in qemu_laio_process_completions (s=0x7ff7182e8420) at block/linux-aio.c:217 + #4 0x00005567a12f480d in ioq_submit (s=0x7ff7182e8420) at block/linux-aio.c:323 + #5 0x00005567a12f43d9 in qemu_laio_process_completions_and_submit (s=0x7ff7182e8420) + at block/linux-aio.c:236 + #6 0x00005567a12f44c2 in qemu_laio_poll_cb (opaque=0x7ff7182e8430) at block/linux-aio.c:267 + #7 0x00005567a13aed83 in run_poll_handlers_once (ctx=0x5567a2b58c70, timeout=0x7ff7367645f8) + at util/aio-posix.c:520 + #8 0x00005567a13aee9f in run_poll_handlers (ctx=0x5567a2b58c70, max_ns=16000, timeout=0x7ff7367645f8) + at util/aio-posix.c:562 + #9 0x00005567a13aefde in try_poll_mode (ctx=0x5567a2b58c70, timeout=0x7ff7367645f8) + at util/aio-posix.c:597 + #10 0x00005567a13af115 in aio_poll (ctx=0x5567a2b58c70, blocking=true) at util/aio-posix.c:639 + #11 0x00005567a109acca in iothread_run (opaque=0x5567a2b29760) at iothread.c:75 + #12 0x00005567a13b2790 in qemu_thread_start (args=0x5567a2b694c0) at util/qemu-thread-posix.c:519 + #13 0x00007ff73eedf2de in start_thread () at /lib64/libpthread.so.0 + #14 0x00007ff73ec10e83 in clone () at /lib64/libc.so.6 + + Thread 1 (Thread 0x7ff743986f00 (LWP 1062500)): + #0 0x00005567a13b99d6 in iov_memset + (iov=0x6563617073206f4e, iov_cnt=1717922848, offset=516096, fillc=0, bytes=7018105756081554803) + at util/iov.c:69 + #1 0x00005567a13bab73 in qemu_iovec_memset + (qiov=0x7ff73ec99748, offset=516096, fillc=0, bytes=7018105756081554803) at util/iov.c:530 + #2 0x00005567a12f411c in qemu_laio_process_completion (laiocb=0x7ff6512ee6c0) at block/linux-aio.c:86 + #3 0x00005567a12f42ff in qemu_laio_process_completions (s=0x7ff7182e8420) at block/linux-aio.c:217 + #4 0x00005567a12f480d in ioq_submit (s=0x7ff7182e8420) at block/linux-aio.c:323 + #5 0x00005567a12f4a2f in laio_do_submit (fd=19, laiocb=0x7ff5f4ff9ae0, offset=472363008, type=2) + at block/linux-aio.c:375 + #6 0x00005567a12f4af2 in laio_co_submit + (bs=0x5567a2b8c460, s=0x7ff7182e8420, fd=19, offset=472363008, qiov=0x7ff5f4ff9ca0, type=2) + at block/linux-aio.c:394 + #7 0x00005567a12f1803 in raw_co_prw + (bs=0x5567a2b8c460, offset=472363008, bytes=20480, qiov=0x7ff5f4ff9ca0, type=2) + at block/file-posix.c:1892 + #8 0x00005567a12f1941 in raw_co_pwritev + (bs=0x5567a2b8c460, offset=472363008, bytes=20480, qiov=0x7ff5f4ff9ca0, flags=0) + at block/file-posix.c:1925 + #9 0x00005567a12fe3e1 in bdrv_driver_pwritev + (bs=0x5567a2b8c460, offset=472363008, bytes=20480, qiov=0x7ff5f4ff9ca0, qiov_offset=0, flags=0) + at block/io.c:1183 + #10 0x00005567a1300340 in bdrv_aligned_pwritev + (child=0x5567a2b5b070, req=0x7ff5f4ff9db0, offset=472363008, bytes=20480, align=512, qiov=0x7ff72c0425b8, qiov_offset=0, flags=0) at block/io.c:1980 + #11 0x00005567a1300b29 in bdrv_co_pwritev_part + (child=0x5567a2b5b070, offset=472363008, bytes=20480, qiov=0x7ff72c0425b8, qiov_offset=0, flags=0) + at block/io.c:2137 + #12 0x00005567a12baba1 in qcow2_co_pwritev_task + (bs=0x5567a2b92740, file_cluster_offset=472317952, offset=487305216, bytes=20480, qiov=0x7ff72c0425b8, qiov_offset=0, l2meta=0x0) at block/qcow2.c:2444 + #13 0x00005567a12bacdb in qcow2_co_pwritev_task_entry (task=0x5567a2b48540) at block/qcow2.c:2475 + #14 0x00005567a13167d8 in aio_task_co (opaque=0x5567a2b48540) at block/aio_task.c:45 + #15 0x00005567a13cf00c in coroutine_trampoline (i0=738245600, i1=32759) at util/coroutine-ucontext.c:115 + #16 0x00007ff73eb622e0 in __start_context () at /lib64/libc.so.6 + #17 0x00007ff6626f1350 in () + #18 0x0000000000000000 in () +<------> + +This is also known to cause crashes with this message (assertion +failed): + + aio_co_schedule: Co-routine was already scheduled in 'aio_co_schedule' + +RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=1812765 +Signed-off-by: Sergio Lopez +Message-Id: <20200603093240.40489-3-slp@redhat.com> +Signed-off-by: Kevin Wolf +(cherry picked from commit 49b44549ace7890fffdf027fd3695218ee7f1121) +Signed-off-by: Sergio Lopez +Signed-off-by: Danilo C. L. de Paula +--- + hw/block/dataplane/virtio-blk.c | 8 ++++++++ + hw/block/virtio-blk.c | 18 ++++++++++++------ + include/hw/virtio/virtio-blk.h | 2 +- + 3 files changed, 21 insertions(+), 7 deletions(-) + +diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c +index 119906a5fe..ac495fd72a 100644 +--- a/hw/block/dataplane/virtio-blk.c ++++ b/hw/block/dataplane/virtio-blk.c +@@ -220,6 +220,9 @@ int virtio_blk_data_plane_start(VirtIODevice *vdev) + goto fail_guest_notifiers; + } + ++ /* Process queued requests before the ones in vring */ ++ virtio_blk_process_queued_requests(vblk, false); ++ + /* Kick right away to begin processing requests already in vring */ + for (i = 0; i < nvqs; i++) { + VirtQueue *vq = virtio_get_queue(s->vdev, i); +@@ -239,6 +242,11 @@ int virtio_blk_data_plane_start(VirtIODevice *vdev) + return 0; + + fail_guest_notifiers: ++ /* ++ * If we failed to set up the guest notifiers queued requests will be ++ * processed on the main context. ++ */ ++ virtio_blk_process_queued_requests(vblk, false); + vblk->dataplane_disabled = true; + s->starting = false; + vblk->dataplane_started = true; +diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c +index 6ff29a05d6..493a263fa6 100644 +--- a/hw/block/virtio-blk.c ++++ b/hw/block/virtio-blk.c +@@ -819,7 +819,7 @@ static void virtio_blk_handle_output(VirtIODevice *vdev, VirtQueue *vq) + virtio_blk_handle_output_do(s, vq); + } + +-void virtio_blk_process_queued_requests(VirtIOBlock *s) ++void virtio_blk_process_queued_requests(VirtIOBlock *s, bool is_bh) + { + VirtIOBlockReq *req = s->rq; + MultiReqBuffer mrb = {}; +@@ -847,7 +847,9 @@ void virtio_blk_process_queued_requests(VirtIOBlock *s) + if (mrb.num_reqs) { + virtio_blk_submit_multireq(s->blk, &mrb); + } +- blk_dec_in_flight(s->conf.conf.blk); ++ if (is_bh) { ++ blk_dec_in_flight(s->conf.conf.blk); ++ } + aio_context_release(blk_get_aio_context(s->conf.conf.blk)); + } + +@@ -858,21 +860,25 @@ static void virtio_blk_dma_restart_bh(void *opaque) + qemu_bh_delete(s->bh); + s->bh = NULL; + +- virtio_blk_process_queued_requests(s); ++ virtio_blk_process_queued_requests(s, true); + } + + static void virtio_blk_dma_restart_cb(void *opaque, int running, + RunState state) + { + VirtIOBlock *s = opaque; ++ BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(s))); ++ VirtioBusState *bus = VIRTIO_BUS(qbus); + + if (!running) { + return; + } + +- if (!s->bh) { +- /* FIXME The data plane is not started yet, so these requests are +- * processed in the main thread. */ ++ /* ++ * If ioeventfd is enabled, don't schedule the BH here as queued ++ * requests will be processed while starting the data plane. ++ */ ++ if (!s->bh && !virtio_bus_ioeventfd_enabled(bus)) { + 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); +diff --git a/include/hw/virtio/virtio-blk.h b/include/hw/virtio/virtio-blk.h +index cf8eea2f58..e77f0db3b0 100644 +--- a/include/hw/virtio/virtio-blk.h ++++ b/include/hw/virtio/virtio-blk.h +@@ -84,6 +84,6 @@ typedef struct MultiReqBuffer { + } MultiReqBuffer; + + bool virtio_blk_handle_vq(VirtIOBlock *s, VirtQueue *vq); +-void virtio_blk_process_queued_requests(VirtIOBlock *s); ++void virtio_blk_process_queued_requests(VirtIOBlock *s, bool is_bh); + + #endif +-- +2.27.0 + diff --git a/SOURCES/kvm-virtio-blk-Refactor-the-code-that-processes-queued-r.patch b/SOURCES/kvm-virtio-blk-Refactor-the-code-that-processes-queued-r.patch new file mode 100644 index 0000000..148045d --- /dev/null +++ b/SOURCES/kvm-virtio-blk-Refactor-the-code-that-processes-queued-r.patch @@ -0,0 +1,83 @@ +From 73d83d8880e85eedc22c9651b67d1eacd5de5ff4 Mon Sep 17 00:00:00 2001 +From: Sergio Lopez Pascual +Date: Wed, 24 Jun 2020 13:24:52 -0400 +Subject: [PATCH 10/12] virtio-blk: Refactor the code that processes queued + requests + +RH-Author: Sergio Lopez Pascual +Message-id: <20200624132453.111276-2-slp@redhat.com> +Patchwork-id: 97797 +O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH 1/2] virtio-blk: Refactor the code that processes queued requests +Bugzilla: +RH-Acked-by: John Snow +RH-Acked-by: Michael S. Tsirkin +RH-Acked-by: Kevin Wolf + +Move the code that processes queued requests from +virtio_blk_dma_restart_bh() to its own, non-static, function. This +will allow us to call it from the virtio_blk_data_plane_start() in a +future patch. + +Signed-off-by: Sergio Lopez +Message-Id: <20200603093240.40489-2-slp@redhat.com> +Signed-off-by: Kevin Wolf +(cherry picked from commit 7aa1c247b466870b0704d3ccdc3755e5e7394dca) +Signed-off-by: Sergio Lopez +Signed-off-by: Danilo C. L. de Paula +--- + hw/block/virtio-blk.c | 16 +++++++++++----- + include/hw/virtio/virtio-blk.h | 1 + + 2 files changed, 12 insertions(+), 5 deletions(-) + +diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c +index c4e55fb3de..6ff29a05d6 100644 +--- a/hw/block/virtio-blk.c ++++ b/hw/block/virtio-blk.c +@@ -819,15 +819,11 @@ static void virtio_blk_handle_output(VirtIODevice *vdev, VirtQueue *vq) + virtio_blk_handle_output_do(s, vq); + } + +-static void virtio_blk_dma_restart_bh(void *opaque) ++void virtio_blk_process_queued_requests(VirtIOBlock *s) + { +- VirtIOBlock *s = opaque; + VirtIOBlockReq *req = s->rq; + MultiReqBuffer mrb = {}; + +- qemu_bh_delete(s->bh); +- s->bh = NULL; +- + s->rq = NULL; + + aio_context_acquire(blk_get_aio_context(s->conf.conf.blk)); +@@ -855,6 +851,16 @@ static void virtio_blk_dma_restart_bh(void *opaque) + aio_context_release(blk_get_aio_context(s->conf.conf.blk)); + } + ++static void virtio_blk_dma_restart_bh(void *opaque) ++{ ++ VirtIOBlock *s = opaque; ++ ++ qemu_bh_delete(s->bh); ++ s->bh = NULL; ++ ++ virtio_blk_process_queued_requests(s); ++} ++ + static void virtio_blk_dma_restart_cb(void *opaque, int running, + RunState state) + { +diff --git a/include/hw/virtio/virtio-blk.h b/include/hw/virtio/virtio-blk.h +index cddcfbebe9..cf8eea2f58 100644 +--- a/include/hw/virtio/virtio-blk.h ++++ b/include/hw/virtio/virtio-blk.h +@@ -84,5 +84,6 @@ typedef struct MultiReqBuffer { + } MultiReqBuffer; + + bool virtio_blk_handle_vq(VirtIOBlock *s, VirtQueue *vq); ++void virtio_blk_process_queued_requests(VirtIOBlock *s); + + #endif +-- +2.27.0 + diff --git a/SOURCES/kvm-virtiofsd-Show-submounts.patch b/SOURCES/kvm-virtiofsd-Show-submounts.patch new file mode 100644 index 0000000..d45a030 --- /dev/null +++ b/SOURCES/kvm-virtiofsd-Show-submounts.patch @@ -0,0 +1,51 @@ +From 717373379510cd6ecf8c6d0e1aae65edfac4551d Mon Sep 17 00:00:00 2001 +From: "Dr. David Alan Gilbert" +Date: Tue, 5 May 2020 16:35:58 +0100 +Subject: [PATCH 7/9] virtiofsd: Show submounts + +RH-Author: Dr. David Alan Gilbert +Message-id: <20200505163600.22956-6-dgilbert@redhat.com> +Patchwork-id: 96273 +O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH 5/7] virtiofsd: Show submounts +Bugzilla: 1817445 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Max Reitz +RH-Acked-by: Michael S. Tsirkin + +From: Max Reitz + +Currently, setup_mounts() bind-mounts the shared directory without +MS_REC. This makes all submounts disappear. + +Pass MS_REC so that the guest can see submounts again. + +Fixes: 5baa3b8e95064c2434bd9e2f312edd5e9ae275dc +Signed-off-by: Max Reitz +Message-Id: <20200424133516.73077-1-mreitz@redhat.com> +Reviewed-by: Dr. David Alan Gilbert +Signed-off-by: Dr. David Alan Gilbert + Changed Fixes to point to the commit with the problem rather than + the commit that turned it on +(cherry picked from commit ace0829c0d08f0e5f1451e402e94495bc2166772) + +Signed-off-by: Danilo C. L. de Paula +--- + tools/virtiofsd/passthrough_ll.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c +index 73d8405..614ba55 100644 +--- a/tools/virtiofsd/passthrough_ll.c ++++ b/tools/virtiofsd/passthrough_ll.c +@@ -2670,7 +2670,7 @@ static void setup_mounts(const char *source) + int oldroot; + int newroot; + +- if (mount(source, source, NULL, MS_BIND, NULL) < 0) { ++ if (mount(source, source, NULL, MS_BIND | MS_REC, NULL) < 0) { + fuse_log(FUSE_LOG_ERR, "mount(%s, %s, MS_BIND): %m\n", source, source); + exit(1); + } +-- +1.8.3.1 + diff --git a/SOURCES/kvm-virtiofsd-add-rlimit-nofile-NUM-option.patch b/SOURCES/kvm-virtiofsd-add-rlimit-nofile-NUM-option.patch new file mode 100644 index 0000000..a6a9cc9 --- /dev/null +++ b/SOURCES/kvm-virtiofsd-add-rlimit-nofile-NUM-option.patch @@ -0,0 +1,164 @@ +From 555ec3463b3dbfd6e08eac7840419d176f113e46 Mon Sep 17 00:00:00 2001 +From: "Dr. David Alan Gilbert" +Date: Tue, 5 May 2020 16:35:55 +0100 +Subject: [PATCH 4/9] virtiofsd: add --rlimit-nofile=NUM option +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Dr. David Alan Gilbert +Message-id: <20200505163600.22956-3-dgilbert@redhat.com> +Patchwork-id: 96270 +O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH 2/7] virtiofsd: add --rlimit-nofile=NUM option +Bugzilla: 1817445 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Max Reitz +RH-Acked-by: Michael S. Tsirkin + +From: Stefan Hajnoczi + +Make it possible to specify the RLIMIT_NOFILE on the command-line. +Users running multiple virtiofsd processes should allocate a certain +number to each process so that the system-wide limit can never be +exhausted. + +When this option is set to 0 the rlimit is left at its current value. +This is useful when a management tool wants to configure the rlimit +itself. + +The default behavior remains unchanged: try to set the limit to +1,000,000 file descriptors if the current rlimit is lower. + +Signed-off-by: Stefan Hajnoczi +Reviewed-by: Dr. David Alan Gilbert +Message-Id: <20200501140644.220940-2-stefanha@redhat.com> +Signed-off-by: Dr. David Alan Gilbert +(cherry picked from commit 6dbb716877728ce4eb51619885ef6ef4ada9565f) +Signed-off-by: Danilo C. L. de Paula +--- + tools/virtiofsd/fuse_lowlevel.h | 1 + + tools/virtiofsd/helper.c | 23 +++++++++++++++++++++++ + tools/virtiofsd/passthrough_ll.c | 22 ++++++++-------------- + 3 files changed, 32 insertions(+), 14 deletions(-) + +diff --git a/tools/virtiofsd/fuse_lowlevel.h b/tools/virtiofsd/fuse_lowlevel.h +index 8f6d705..562fd52 100644 +--- a/tools/virtiofsd/fuse_lowlevel.h ++++ b/tools/virtiofsd/fuse_lowlevel.h +@@ -1777,6 +1777,7 @@ struct fuse_cmdline_opts { + int syslog; + int log_level; + unsigned int max_idle_threads; ++ unsigned long rlimit_nofile; + }; + + /** +diff --git a/tools/virtiofsd/helper.c b/tools/virtiofsd/helper.c +index 0801cf7..9b3eddc 100644 +--- a/tools/virtiofsd/helper.c ++++ b/tools/virtiofsd/helper.c +@@ -23,6 +23,8 @@ + #include + #include + #include ++#include ++#include + #include + + #define FUSE_HELPER_OPT(t, p) \ +@@ -53,6 +55,7 @@ static const struct fuse_opt fuse_helper_opts[] = { + FUSE_HELPER_OPT("subtype=", nodefault_subtype), + FUSE_OPT_KEY("subtype=", FUSE_OPT_KEY_KEEP), + FUSE_HELPER_OPT("max_idle_threads=%u", max_idle_threads), ++ FUSE_HELPER_OPT("--rlimit-nofile=%lu", rlimit_nofile), + FUSE_HELPER_OPT("--syslog", syslog), + FUSE_HELPER_OPT_VALUE("log_level=debug", log_level, FUSE_LOG_DEBUG), + FUSE_HELPER_OPT_VALUE("log_level=info", log_level, FUSE_LOG_INFO), +@@ -171,6 +174,9 @@ void fuse_cmdline_help(void) + " default: no_writeback\n" + " -o xattr|no_xattr enable/disable xattr\n" + " default: no_xattr\n" ++ " --rlimit-nofile= set maximum number of file descriptors\n" ++ " (0 leaves rlimit unchanged)\n" ++ " default: 1,000,000 if the current rlimit is lower\n" + ); + } + +@@ -191,11 +197,28 @@ static int fuse_helper_opt_proc(void *data, const char *arg, int key, + } + } + ++static unsigned long get_default_rlimit_nofile(void) ++{ ++ rlim_t max_fds = 1000000; /* our default RLIMIT_NOFILE target */ ++ struct rlimit rlim; ++ ++ if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) { ++ fuse_log(FUSE_LOG_ERR, "getrlimit(RLIMIT_NOFILE): %m\n"); ++ exit(1); ++ } ++ ++ if (rlim.rlim_cur >= max_fds) { ++ return 0; /* we have more fds available than required! */ ++ } ++ return max_fds; ++} ++ + int fuse_parse_cmdline(struct fuse_args *args, struct fuse_cmdline_opts *opts) + { + memset(opts, 0, sizeof(struct fuse_cmdline_opts)); + + opts->max_idle_threads = 10; ++ opts->rlimit_nofile = get_default_rlimit_nofile(); + opts->foreground = 1; + + if (fuse_opt_parse(args, opts, fuse_helper_opts, fuse_helper_opt_proc) == +diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c +index 50ff672..184ad0f 100644 +--- a/tools/virtiofsd/passthrough_ll.c ++++ b/tools/virtiofsd/passthrough_ll.c +@@ -2711,24 +2711,18 @@ static void setup_sandbox(struct lo_data *lo, struct fuse_session *se, + setup_seccomp(enable_syslog); + } + +-/* Raise the maximum number of open file descriptors */ +-static void setup_nofile_rlimit(void) ++/* Set the maximum number of open file descriptors */ ++static void setup_nofile_rlimit(unsigned long rlimit_nofile) + { +- const rlim_t max_fds = 1000000; +- struct rlimit rlim; +- +- if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) { +- fuse_log(FUSE_LOG_ERR, "getrlimit(RLIMIT_NOFILE): %m\n"); +- exit(1); +- } ++ struct rlimit rlim = { ++ .rlim_cur = rlimit_nofile, ++ .rlim_max = rlimit_nofile, ++ }; + +- if (rlim.rlim_cur >= max_fds) { ++ if (rlimit_nofile == 0) { + return; /* nothing to do */ + } + +- rlim.rlim_cur = max_fds; +- rlim.rlim_max = max_fds; +- + if (setrlimit(RLIMIT_NOFILE, &rlim) < 0) { + /* Ignore SELinux denials */ + if (errno == EPERM) { +@@ -2981,7 +2975,7 @@ int main(int argc, char *argv[]) + + fuse_daemonize(opts.foreground); + +- setup_nofile_rlimit(); ++ setup_nofile_rlimit(opts.rlimit_nofile); + + /* Must be before sandbox since it wants /proc */ + setup_capng(); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-virtiofsd-drop-all-capabilities-in-the-wait-parent-p.patch b/SOURCES/kvm-virtiofsd-drop-all-capabilities-in-the-wait-parent-p.patch new file mode 100644 index 0000000..569096d --- /dev/null +++ b/SOURCES/kvm-virtiofsd-drop-all-capabilities-in-the-wait-parent-p.patch @@ -0,0 +1,67 @@ +From 78152453940967f9ece9fe3ffc5017c669d6ec28 Mon Sep 17 00:00:00 2001 +From: "Dr. David Alan Gilbert" +Date: Tue, 5 May 2020 16:36:00 +0100 +Subject: [PATCH 9/9] virtiofsd: drop all capabilities in the wait parent + process +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Dr. David Alan Gilbert +Message-id: <20200505163600.22956-8-dgilbert@redhat.com> +Patchwork-id: 96274 +O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH 7/7] virtiofsd: drop all capabilities in the wait parent process +Bugzilla: 1817445 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Max Reitz +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Michael S. Tsirkin + +From: Stefan Hajnoczi + +All this process does is wait for its child. No capabilities are +needed. + +Signed-off-by: Stefan Hajnoczi +Reviewed-by: Philippe Mathieu-Daudé +Signed-off-by: Dr. David Alan Gilbert +(cherry picked from commit 66502bbca37ca7a3bfa57e82cfc03b89a7a11eae) +Signed-off-by: Danilo C. L. de Paula +--- + tools/virtiofsd/passthrough_ll.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c +index 6358874..f41a6b0 100644 +--- a/tools/virtiofsd/passthrough_ll.c ++++ b/tools/virtiofsd/passthrough_ll.c +@@ -2535,6 +2535,17 @@ static void print_capabilities(void) + } + + /* ++ * Drop all Linux capabilities because the wait parent process only needs to ++ * sit in waitpid(2) and terminate. ++ */ ++static void setup_wait_parent_capabilities(void) ++{ ++ capng_setpid(syscall(SYS_gettid)); ++ capng_clear(CAPNG_SELECT_BOTH); ++ capng_apply(CAPNG_SELECT_BOTH); ++} ++ ++/* + * Move to a new mount, net, and pid namespaces to isolate this process. + */ + static void setup_namespaces(struct lo_data *lo, struct fuse_session *se) +@@ -2567,6 +2578,8 @@ static void setup_namespaces(struct lo_data *lo, struct fuse_session *se) + pid_t waited; + int wstatus; + ++ setup_wait_parent_capabilities(); ++ + /* The parent waits for the child */ + do { + waited = waitpid(child, &wstatus, 0); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-virtiofsd-jail-lo-proc_self_fd.patch b/SOURCES/kvm-virtiofsd-jail-lo-proc_self_fd.patch new file mode 100644 index 0000000..df69242 --- /dev/null +++ b/SOURCES/kvm-virtiofsd-jail-lo-proc_self_fd.patch @@ -0,0 +1,85 @@ +From 852a0a22d674b0594aecf0912a0885d197f34978 Mon Sep 17 00:00:00 2001 +From: "Dr. David Alan Gilbert" +Date: Tue, 5 May 2020 16:35:57 +0100 +Subject: [PATCH 6/9] virtiofsd: jail lo->proc_self_fd + +RH-Author: Dr. David Alan Gilbert +Message-id: <20200505163600.22956-5-dgilbert@redhat.com> +Patchwork-id: 96275 +O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH 4/7] virtiofsd: jail lo->proc_self_fd +Bugzilla: 1817445 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Max Reitz +RH-Acked-by: Michael S. Tsirkin + +From: Miklos Szeredi + +While it's not possible to escape the proc filesystem through +lo->proc_self_fd, it is possible to escape to the root of the proc +filesystem itself through "../..". + +Use a temporary mount for opening lo->proc_self_fd, that has it's root at +/proc/self/fd/, preventing access to the ancestor directories. + +Signed-off-by: Miklos Szeredi +Message-Id: <20200429124733.22488-1-mszeredi@redhat.com> +Reviewed-by: Stefan Hajnoczi +Signed-off-by: Dr. David Alan Gilbert +(cherry picked from commit 397ae982f4df46e7d4b2625c431062c9146f3b83) +Signed-off-by: Danilo C. L. de Paula +--- + tools/virtiofsd/passthrough_ll.c | 27 +++++++++++++++++++++++++-- + 1 file changed, 25 insertions(+), 2 deletions(-) + +diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c +index 184ad0f..73d8405 100644 +--- a/tools/virtiofsd/passthrough_ll.c ++++ b/tools/virtiofsd/passthrough_ll.c +@@ -2540,6 +2540,8 @@ static void print_capabilities(void) + static void setup_namespaces(struct lo_data *lo, struct fuse_session *se) + { + pid_t child; ++ char template[] = "virtiofsd-XXXXXX"; ++ char *tmpdir; + + /* + * Create a new pid namespace for *child* processes. We'll have to +@@ -2601,12 +2603,33 @@ static void setup_namespaces(struct lo_data *lo, struct fuse_session *se) + exit(1); + } + ++ tmpdir = mkdtemp(template); ++ if (!tmpdir) { ++ fuse_log(FUSE_LOG_ERR, "tmpdir(%s): %m\n", template); ++ exit(1); ++ } ++ ++ if (mount("/proc/self/fd", tmpdir, NULL, MS_BIND, NULL) < 0) { ++ fuse_log(FUSE_LOG_ERR, "mount(/proc/self/fd, %s, MS_BIND): %m\n", ++ tmpdir); ++ exit(1); ++ } ++ + /* Now we can get our /proc/self/fd directory file descriptor */ +- lo->proc_self_fd = open("/proc/self/fd", O_PATH); ++ lo->proc_self_fd = open(tmpdir, O_PATH); + if (lo->proc_self_fd == -1) { +- fuse_log(FUSE_LOG_ERR, "open(/proc/self/fd, O_PATH): %m\n"); ++ fuse_log(FUSE_LOG_ERR, "open(%s, O_PATH): %m\n", tmpdir); + exit(1); + } ++ ++ if (umount2(tmpdir, MNT_DETACH) < 0) { ++ fuse_log(FUSE_LOG_ERR, "umount2(%s, MNT_DETACH): %m\n", tmpdir); ++ exit(1); ++ } ++ ++ if (rmdir(tmpdir) < 0) { ++ fuse_log(FUSE_LOG_ERR, "rmdir(%s): %m\n", tmpdir); ++ } + } + + /* +-- +1.8.3.1 + diff --git a/SOURCES/kvm-virtiofsd-only-retain-file-system-capabilities.patch b/SOURCES/kvm-virtiofsd-only-retain-file-system-capabilities.patch new file mode 100644 index 0000000..15c8cd8 --- /dev/null +++ b/SOURCES/kvm-virtiofsd-only-retain-file-system-capabilities.patch @@ -0,0 +1,112 @@ +From 8727e4904e7a6588e39f231d837f4527f265e47e Mon Sep 17 00:00:00 2001 +From: "Dr. David Alan Gilbert" +Date: Tue, 5 May 2020 16:35:59 +0100 +Subject: [PATCH 8/9] virtiofsd: only retain file system capabilities + +RH-Author: Dr. David Alan Gilbert +Message-id: <20200505163600.22956-7-dgilbert@redhat.com> +Patchwork-id: 96272 +O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH 6/7] virtiofsd: only retain file system capabilities +Bugzilla: 1817445 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Max Reitz +RH-Acked-by: Michael S. Tsirkin + +From: Stefan Hajnoczi + +virtiofsd runs as root but only needs a subset of root's Linux +capabilities(7). As a file server its purpose is to create and access +files on behalf of a client. It needs to be able to access files with +arbitrary uid/gid owners. It also needs to be create device nodes. + +Introduce a Linux capabilities(7) whitelist and drop all capabilities +that we don't need, making the virtiofsd process less powerful than a +regular uid root process. + + # cat /proc/PID/status + ... + Before After + CapInh: 0000000000000000 0000000000000000 + CapPrm: 0000003fffffffff 00000000880000df + CapEff: 0000003fffffffff 00000000880000df + CapBnd: 0000003fffffffff 0000000000000000 + CapAmb: 0000000000000000 0000000000000000 + +Note that file capabilities cannot be used to achieve the same effect on +the virtiofsd executable because mount is used during sandbox setup. +Therefore we drop capabilities programmatically at the right point +during startup. + +This patch only affects the sandboxed child process. The parent process +that sits in waitpid(2) still has full root capabilities and will be +addressed in the next patch. + +Signed-off-by: Stefan Hajnoczi +Message-Id: <20200416164907.244868-2-stefanha@redhat.com> +Reviewed-by: Dr. David Alan Gilbert +Signed-off-by: Dr. David Alan Gilbert +(cherry picked from commit a59feb483b8fae24d043569ccfcc97ea23d54a02) +Signed-off-by: Danilo C. L. de Paula +--- + tools/virtiofsd/passthrough_ll.c | 38 ++++++++++++++++++++++++++++++++++++++ + 1 file changed, 38 insertions(+) + +diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c +index 614ba55..6358874 100644 +--- a/tools/virtiofsd/passthrough_ll.c ++++ b/tools/virtiofsd/passthrough_ll.c +@@ -2723,6 +2723,43 @@ static void setup_mounts(const char *source) + } + + /* ++ * Only keep whitelisted capabilities that are needed for file system operation ++ */ ++static void setup_capabilities(void) ++{ ++ pthread_mutex_lock(&cap.mutex); ++ capng_restore_state(&cap.saved); ++ ++ /* ++ * Whitelist file system-related capabilities that are needed for a file ++ * server to act like root. Drop everything else like networking and ++ * sysadmin capabilities. ++ * ++ * Exclusions: ++ * 1. CAP_LINUX_IMMUTABLE is not included because it's only used via ioctl ++ * and we don't support that. ++ * 2. CAP_MAC_OVERRIDE is not included because it only seems to be ++ * used by the Smack LSM. Omit it until there is demand for it. ++ */ ++ capng_setpid(syscall(SYS_gettid)); ++ capng_clear(CAPNG_SELECT_BOTH); ++ capng_updatev(CAPNG_ADD, CAPNG_PERMITTED | CAPNG_EFFECTIVE, ++ CAP_CHOWN, ++ CAP_DAC_OVERRIDE, ++ CAP_DAC_READ_SEARCH, ++ CAP_FOWNER, ++ CAP_FSETID, ++ CAP_SETGID, ++ CAP_SETUID, ++ CAP_MKNOD, ++ CAP_SETFCAP); ++ capng_apply(CAPNG_SELECT_BOTH); ++ ++ cap.saved = capng_save_state(); ++ pthread_mutex_unlock(&cap.mutex); ++} ++ ++/* + * Lock down this process to prevent access to other processes or files outside + * source directory. This reduces the impact of arbitrary code execution bugs. + */ +@@ -2732,6 +2769,7 @@ static void setup_sandbox(struct lo_data *lo, struct fuse_session *se, + setup_namespaces(lo, se); + setup_mounts(lo->source); + setup_seccomp(enable_syslog); ++ setup_capabilities(); + } + + /* Set the maximum number of open file descriptors */ +-- +1.8.3.1 + diff --git a/SOURCES/kvm-virtiofsd-stay-below-fs.file-max-sysctl-value-CVE-20.patch b/SOURCES/kvm-virtiofsd-stay-below-fs.file-max-sysctl-value-CVE-20.patch new file mode 100644 index 0000000..ce74f4d --- /dev/null +++ b/SOURCES/kvm-virtiofsd-stay-below-fs.file-max-sysctl-value-CVE-20.patch @@ -0,0 +1,88 @@ +From 301f19f2ebd617e43e3a8e7bdcf694de580fe689 Mon Sep 17 00:00:00 2001 +From: "Dr. David Alan Gilbert" +Date: Tue, 5 May 2020 16:35:56 +0100 +Subject: [PATCH 5/9] virtiofsd: stay below fs.file-max sysctl value + (CVE-2020-10717) + +RH-Author: Dr. David Alan Gilbert +Message-id: <20200505163600.22956-4-dgilbert@redhat.com> +Patchwork-id: 96271 +O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH 3/7] virtiofsd: stay below fs.file-max sysctl value (CVE-2020-10717) +Bugzilla: 1817445 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Max Reitz +RH-Acked-by: Michael S. Tsirkin + +From: Stefan Hajnoczi + +The system-wide fs.file-max sysctl value determines how many files can +be open. It defaults to a value calculated based on the machine's RAM +size. Previously virtiofsd would try to set RLIMIT_NOFILE to 1,000,000 +and this allowed the FUSE client to exhaust the number of open files +system-wide on Linux hosts with less than 10 GB of RAM! + +Take fs.file-max into account when choosing the default RLIMIT_NOFILE +value. + +Fixes: CVE-2020-10717 +Reported-by: Yuval Avrahami +Signed-off-by: Stefan Hajnoczi +Reviewed-by: Dr. David Alan Gilbert +Message-Id: <20200501140644.220940-3-stefanha@redhat.com> +Signed-off-by: Dr. David Alan Gilbert +(cherry picked from commit 8c1d353d107b4fc344e27f2f08ea7fa25de2eea2) +Signed-off-by: Danilo C. L. de Paula +--- + tools/virtiofsd/helper.c | 26 +++++++++++++++++++++++++- + 1 file changed, 25 insertions(+), 1 deletion(-) + +diff --git a/tools/virtiofsd/helper.c b/tools/virtiofsd/helper.c +index 9b3eddc..5b222ea 100644 +--- a/tools/virtiofsd/helper.c ++++ b/tools/virtiofsd/helper.c +@@ -176,7 +176,8 @@ void fuse_cmdline_help(void) + " default: no_xattr\n" + " --rlimit-nofile= set maximum number of file descriptors\n" + " (0 leaves rlimit unchanged)\n" +- " default: 1,000,000 if the current rlimit is lower\n" ++ " default: min(1000000, fs.file-max - 16384)\n" ++ " if the current rlimit is lower\n" + ); + } + +@@ -199,9 +200,32 @@ static int fuse_helper_opt_proc(void *data, const char *arg, int key, + + static unsigned long get_default_rlimit_nofile(void) + { ++ g_autofree gchar *file_max_str = NULL; ++ const rlim_t reserved_fds = 16384; /* leave at least this many fds free */ + rlim_t max_fds = 1000000; /* our default RLIMIT_NOFILE target */ ++ rlim_t file_max; + struct rlimit rlim; + ++ /* ++ * Reduce max_fds below the system-wide maximum, if necessary. This ++ * ensures there are fds available for other processes so we don't ++ * cause resource exhaustion. ++ */ ++ if (!g_file_get_contents("/proc/sys/fs/file-max", &file_max_str, ++ NULL, NULL)) { ++ fuse_log(FUSE_LOG_ERR, "can't read /proc/sys/fs/file-max\n"); ++ exit(1); ++ } ++ file_max = g_ascii_strtoull(file_max_str, NULL, 10); ++ if (file_max < 2 * reserved_fds) { ++ fuse_log(FUSE_LOG_ERR, ++ "The fs.file-max sysctl is too low (%lu) to allow a " ++ "reasonable number of open files.\n", ++ (unsigned long)file_max); ++ exit(1); ++ } ++ max_fds = MIN(file_max - reserved_fds, max_fds); ++ + if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) { + fuse_log(FUSE_LOG_ERR, "getrlimit(RLIMIT_NOFILE): %m\n"); + exit(1); +-- +1.8.3.1 + diff --git a/SPECS/qemu-kvm.spec b/SPECS/qemu-kvm.spec index ba806ba..9f52a1c 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: 4.2.0 -Release: 19%{?dist} +Release: 29%{?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 @@ -643,6 +643,276 @@ Patch246: kvm-block-Increase-BB.in_flight-for-coroutine-and-sync-i.patch Patch247: kvm-block-Fix-blk-in_flight-during-blk_wait_while_draine.patch # For bz#1822682 - QEMU-4.2 fails to start a VM on Azure Patch248: kvm-target-i386-do-not-set-unsupported-VMX-secondary-exe.patch +# For bz#1790899 - [RFE] QEMU devices should have the option to enable/disable hotplug/unplug +Patch249: kvm-pcie_root_port-Add-hotplug-disabling-option.patch +# For bz#1816793 - 'edid' compat handling missing for virtio-gpu-ccw +Patch250: kvm-compat-disable-edid-for-virtio-gpu-ccw.patch +# For bz#1820531 - qmp command query-pci get wrong result after hotplug device under hotplug=off controller +Patch251: kvm-hw-pci-pcie-Forbid-hot-plug-if-it-s-disabled-on-the-.patch +# For bz#1820531 - qmp command query-pci get wrong result after hotplug device under hotplug=off controller +Patch252: kvm-hw-pci-pcie-Replace-PCI_DEVICE-casts-with-existing-v.patch +# For bz#1817445 - CVE-2020-10717 virt:8.2/qemu-kvm: QEMU: virtiofsd: guest may open maximum file descriptor to cause DoS [rhel-av-8] +Patch253: kvm-tools-virtiofsd-passthrough_ll-Fix-double-close.patch +# For bz#1817445 - CVE-2020-10717 virt:8.2/qemu-kvm: QEMU: virtiofsd: guest may open maximum file descriptor to cause DoS [rhel-av-8] +Patch254: kvm-virtiofsd-add-rlimit-nofile-NUM-option.patch +# For bz#1817445 - CVE-2020-10717 virt:8.2/qemu-kvm: QEMU: virtiofsd: guest may open maximum file descriptor to cause DoS [rhel-av-8] +Patch255: kvm-virtiofsd-stay-below-fs.file-max-sysctl-value-CVE-20.patch +# For bz#1817445 - CVE-2020-10717 virt:8.2/qemu-kvm: QEMU: virtiofsd: guest may open maximum file descriptor to cause DoS [rhel-av-8] +Patch256: kvm-virtiofsd-jail-lo-proc_self_fd.patch +# For bz#1817445 - CVE-2020-10717 virt:8.2/qemu-kvm: QEMU: virtiofsd: guest may open maximum file descriptor to cause DoS [rhel-av-8] +Patch257: kvm-virtiofsd-Show-submounts.patch +# For bz#1817445 - CVE-2020-10717 virt:8.2/qemu-kvm: QEMU: virtiofsd: guest may open maximum file descriptor to cause DoS [rhel-av-8] +Patch258: kvm-virtiofsd-only-retain-file-system-capabilities.patch +# For bz#1817445 - CVE-2020-10717 virt:8.2/qemu-kvm: QEMU: virtiofsd: guest may open maximum file descriptor to cause DoS [rhel-av-8] +Patch259: kvm-virtiofsd-drop-all-capabilities-in-the-wait-parent-p.patch +# For bz#1775462 - Creating luks-inside-qcow2 images with cluster_size=2k/4k will get a corrupted image +Patch260: kvm-block-always-fill-entire-LUKS-header-space-with-zero.patch +# For bz#1600217 - [Intel 8.2.1 FEAT] KVM ACPI HMAT support - qemu-kvm Fast Train +Patch261: kvm-numa-remove-not-needed-check.patch +# For bz#1600217 - [Intel 8.2.1 FEAT] KVM ACPI HMAT support - qemu-kvm Fast Train +Patch262: kvm-numa-properly-check-if-numa-is-supported.patch +# For bz#1600217 - [Intel 8.2.1 FEAT] KVM ACPI HMAT support - qemu-kvm Fast Train +Patch263: kvm-numa-Extend-CLI-to-provide-initiator-information-for.patch +# For bz#1600217 - [Intel 8.2.1 FEAT] KVM ACPI HMAT support - qemu-kvm Fast Train +Patch264: kvm-numa-Extend-CLI-to-provide-memory-latency-and-bandwi.patch +# For bz#1600217 - [Intel 8.2.1 FEAT] KVM ACPI HMAT support - qemu-kvm Fast Train +Patch265: kvm-numa-Extend-CLI-to-provide-memory-side-cache-informa.patch +# For bz#1600217 - [Intel 8.2.1 FEAT] KVM ACPI HMAT support - qemu-kvm Fast Train +Patch266: kvm-hmat-acpi-Build-Memory-Proximity-Domain-Attributes-S.patch +# For bz#1600217 - [Intel 8.2.1 FEAT] KVM ACPI HMAT support - qemu-kvm Fast Train +Patch267: kvm-hmat-acpi-Build-System-Locality-Latency-and-Bandwidt.patch +# For bz#1600217 - [Intel 8.2.1 FEAT] KVM ACPI HMAT support - qemu-kvm Fast Train +Patch268: kvm-hmat-acpi-Build-Memory-Side-Cache-Information-Struct.patch +# For bz#1600217 - [Intel 8.2.1 FEAT] KVM ACPI HMAT support - qemu-kvm Fast Train +Patch269: kvm-tests-numa-Add-case-for-QMP-build-HMAT.patch +# For bz#1600217 - [Intel 8.2.1 FEAT] KVM ACPI HMAT support - qemu-kvm Fast Train +Patch270: kvm-tests-bios-tables-test-add-test-cases-for-ACPI-HMAT.patch +# For bz#1600217 - [Intel 8.2.1 FEAT] KVM ACPI HMAT support - qemu-kvm Fast Train +Patch271: kvm-ACPI-add-expected-files-for-HMAT-tests-acpihmat.patch +# For bz#1813940 - CVE-2020-10702 virt:8.1/qemu-kvm: qemu: weak signature generation in Pointer Authentication support for ARM [rhel-av-8] +Patch272: kvm-target-arm-Fix-PAuth-sbox-functions.patch +# For bz#1749737 - CVE-2019-15890 qemu-kvm: QEMU: Slirp: use-after-free during packet reassembly [rhel-av-8] +Patch273: kvm-Don-t-leak-memory-when-reallocation-fails.patch +# For bz#1749737 - CVE-2019-15890 qemu-kvm: QEMU: Slirp: use-after-free during packet reassembly [rhel-av-8] +Patch274: kvm-Replace-remaining-malloc-free-user-with-glib.patch +# For bz#1839030 - RFE: enable the "memfd" memory backend +Patch275: kvm-Revert-RHEL-disable-hostmem-memfd.patch +# For bz#1827630 - volume creation leaving uncleaned stuff behind on error (vol-clone/libvirt/qemu-kvm) +Patch276: kvm-block-introducing-bdrv_co_delete_file-interface.patch +# For bz#1827630 - volume creation leaving uncleaned stuff behind on error (vol-clone/libvirt/qemu-kvm) +Patch277: kvm-block.c-adding-bdrv_co_delete_file.patch +# For bz#1827630 - volume creation leaving uncleaned stuff behind on error (vol-clone/libvirt/qemu-kvm) +Patch278: kvm-crypto.c-cleanup-created-file-when-block_crypto_co_c.patch +# For bz#1513681 - [Intel 8.2.1 Feat] qemu-kvm PT VMX -- Fast Train +Patch279: kvm-target-i386-set-the-CPUID-level-to-0x14-on-old-machi.patch +# For bz#1841038 - qemu-img: /var/tmp/v2vovl56bced.qcow2: CURL: Error opening file: Server does not support 'range' (byte ranges) with HTTP/2 server in VMware ESXi 7 +Patch280: kvm-block-curl-HTTP-header-fields-allow-whitespace-aroun.patch +# For bz#1841038 - qemu-img: /var/tmp/v2vovl56bced.qcow2: CURL: Error opening file: Server does not support 'range' (byte ranges) with HTTP/2 server in VMware ESXi 7 +Patch281: kvm-block-curl-HTTP-header-field-names-are-case-insensit.patch +# For bz#1779893 - RFE: Copy bitmaps with qemu-img convert +# For bz#1779904 - RFE: ability to estimate bitmap space utilization for qcow2 +Patch282: kvm-MAINTAINERS-fix-qcow2-bitmap.c-under-Dirty-Bitmaps-h.patch +# For bz#1779893 - RFE: Copy bitmaps with qemu-img convert +# For bz#1779904 - RFE: ability to estimate bitmap space utilization for qcow2 +Patch283: kvm-iotests-Let-_make_test_img-parse-its-parameters.patch +# For bz#1779893 - RFE: Copy bitmaps with qemu-img convert +# For bz#1779904 - RFE: ability to estimate bitmap space utilization for qcow2 +Patch284: kvm-qemu_img-add-cvtnum_full-to-print-error-reports.patch +# For bz#1779893 - RFE: Copy bitmaps with qemu-img convert +# For bz#1779904 - RFE: ability to estimate bitmap space utilization for qcow2 +Patch285: kvm-block-Make-it-easier-to-learn-which-BDS-support-bitm.patch +# For bz#1779893 - RFE: Copy bitmaps with qemu-img convert +# For bz#1779904 - RFE: ability to estimate bitmap space utilization for qcow2 +Patch286: kvm-blockdev-Promote-several-bitmap-functions-to-non-sta.patch +# For bz#1779893 - RFE: Copy bitmaps with qemu-img convert +# For bz#1779904 - RFE: ability to estimate bitmap space utilization for qcow2 +Patch287: kvm-blockdev-Split-off-basic-bitmap-operations-for-qemu-.patch +# For bz#1779893 - RFE: Copy bitmaps with qemu-img convert +# For bz#1779904 - RFE: ability to estimate bitmap space utilization for qcow2 +Patch288: kvm-qemu-img-Add-bitmap-sub-command.patch +# For bz#1779893 - RFE: Copy bitmaps with qemu-img convert +# For bz#1779904 - RFE: ability to estimate bitmap space utilization for qcow2 +Patch289: kvm-iotests-Fix-test-178.patch +# For bz#1779893 - RFE: Copy bitmaps with qemu-img convert +# For bz#1779904 - RFE: ability to estimate bitmap space utilization for qcow2 +Patch290: kvm-qcow2-Expose-bitmaps-size-during-measure.patch +# For bz#1779893 - RFE: Copy bitmaps with qemu-img convert +# For bz#1779904 - RFE: ability to estimate bitmap space utilization for qcow2 +Patch291: kvm-qemu-img-Factor-out-code-for-merging-bitmaps.patch +# For bz#1779893 - RFE: Copy bitmaps with qemu-img convert +# For bz#1779904 - RFE: ability to estimate bitmap space utilization for qcow2 +Patch292: kvm-qemu-img-Add-convert-bitmaps-option.patch +# For bz#1779893 - RFE: Copy bitmaps with qemu-img convert +# For bz#1779904 - RFE: ability to estimate bitmap space utilization for qcow2 +Patch293: kvm-iotests-Add-test-291-to-for-qemu-img-bitmap-coverage.patch +# For bz#1778593 - Qemu coredump when backup to a existing small size image +Patch294: kvm-iotests-Add-more-skip_if_unsupported-statements-to-t.patch +# For bz#1778593 - Qemu coredump when backup to a existing small size image +Patch295: kvm-iotests-don-t-use-format-for-drive_add.patch +# For bz#1778593 - Qemu coredump when backup to a existing small size image +Patch296: kvm-iotests-055-refactor-compressed-backup-to-vmdk.patch +# For bz#1778593 - Qemu coredump when backup to a existing small size image +Patch297: kvm-iotests-055-skip-vmdk-target-tests-if-vmdk-is-not-wh.patch +# For bz#1778593 - Qemu coredump when backup to a existing small size image +Patch298: kvm-backup-Improve-error-for-bdrv_getlength-failure.patch +# For bz#1778593 - Qemu coredump when backup to a existing small size image +Patch299: kvm-backup-Make-sure-that-source-and-target-size-match.patch +# For bz#1778593 - Qemu coredump when backup to a existing small size image +Patch300: kvm-iotests-Backup-with-different-source-target-size.patch +# For bz#1778593 - Qemu coredump when backup to a existing small size image +Patch301: kvm-iotests-109-Don-t-mirror-with-mismatched-size.patch +# For bz#1778593 - Qemu coredump when backup to a existing small size image +Patch302: kvm-iotests-229-Use-blkdebug-to-inject-an-error.patch +# For bz#1778593 - Qemu coredump when backup to a existing small size image +Patch303: kvm-mirror-Make-sure-that-source-and-target-size-match.patch +# For bz#1778593 - Qemu coredump when backup to a existing small size image +Patch304: kvm-iotests-Mirror-with-different-source-target-size.patch +# For bz#1841068 - RFE: please support the "ramfb" display device model +Patch305: kvm-enable-ramfb.patch +# For bz#1780574 - Data corruption with resizing short overlay over longer backing files +Patch306: kvm-block-Add-flags-to-BlockDriver.bdrv_co_truncate.patch +# For bz#1780574 - Data corruption with resizing short overlay over longer backing files +Patch307: kvm-block-Add-flags-to-bdrv-_co-_truncate.patch +# For bz#1780574 - Data corruption with resizing short overlay over longer backing files +Patch308: kvm-block-backend-Add-flags-to-blk_truncate.patch +# For bz#1780574 - Data corruption with resizing short overlay over longer backing files +Patch309: kvm-qcow2-Support-BDRV_REQ_ZERO_WRITE-for-truncate.patch +# For bz#1780574 - Data corruption with resizing short overlay over longer backing files +Patch310: kvm-raw-format-Support-BDRV_REQ_ZERO_WRITE-for-truncate.patch +# For bz#1780574 - Data corruption with resizing short overlay over longer backing files +Patch311: kvm-file-posix-Support-BDRV_REQ_ZERO_WRITE-for-truncate.patch +# For bz#1780574 - Data corruption with resizing short overlay over longer backing files +Patch312: kvm-block-truncate-Don-t-make-backing-file-data-visible.patch +# For bz#1780574 - Data corruption with resizing short overlay over longer backing files +Patch313: kvm-iotests-Add-qemu_io_log.patch +# For bz#1780574 - Data corruption with resizing short overlay over longer backing files +Patch314: kvm-iotests-Filter-testfiles-out-in-filter_img_info.patch +# For bz#1780574 - Data corruption with resizing short overlay over longer backing files +Patch315: kvm-iotests-Test-committing-to-short-backing-file.patch +# For bz#1780574 - Data corruption with resizing short overlay over longer backing files +Patch316: kvm-qcow2-Forward-ZERO_WRITE-flag-for-full-preallocation.patch +# For bz#1769912 - [Intel 8.2.1 Feature] introduce Cooper Lake cpu model - qemu-kvm Fast Train +Patch317: kvm-i386-Add-MSR-feature-bit-for-MDS-NO.patch +# For bz#1769912 - [Intel 8.2.1 Feature] introduce Cooper Lake cpu model - qemu-kvm Fast Train +Patch318: kvm-i386-Add-macro-for-stibp.patch +# For bz#1769912 - [Intel 8.2.1 Feature] introduce Cooper Lake cpu model - qemu-kvm Fast Train +Patch319: kvm-target-i386-Add-new-bit-definitions-of-MSR_IA32_ARCH.patch +# For bz#1769912 - [Intel 8.2.1 Feature] introduce Cooper Lake cpu model - qemu-kvm Fast Train +Patch320: kvm-i386-Add-new-CPU-model-Cooperlake.patch +# For bz#1769912 - [Intel 8.2.1 Feature] introduce Cooper Lake cpu model - qemu-kvm Fast Train +Patch321: kvm-target-i386-Add-missed-features-to-Cooperlake-CPU-mo.patch +# For bz#1845384 - CVE-2020-10761 virt:8.2/qemu-kvm: QEMU: nbd: reachable assertion failure in nbd_negotiate_send_rep_verr via remote client [rhel-av-8] +Patch322: kvm-nbd-server-Avoid-long-error-message-assertions-CVE-2.patch +# For bz#1845384 - CVE-2020-10761 virt:8.2/qemu-kvm: QEMU: nbd: reachable assertion failure in nbd_negotiate_send_rep_verr via remote client [rhel-av-8] +Patch323: kvm-block-Call-attention-to-truncation-of-long-NBD-expor.patch +# For bz#1820531 - qmp command query-pci get wrong result after hotplug device under hotplug=off controller +Patch324: kvm-hw-pci-pcie-Move-hot-plug-capability-check-to-pre_pl.patch +# For bz#1840342 - [Intel 8.2.1 Bug] qemu-kvm Add ARCH_CAPABILITIES to Icelake-Server cpu model - Fast Train +Patch325: kvm-target-i386-Add-ARCH_CAPABILITIES-related-bits-into-.patch +# For bz#1828317 - [IBM 8.3 FEAT] s390x: Base KVM setup for secure guests - qemu part +Patch327: kvm-linux-headers-update-kvm.h.patch +# For bz#1828317 - [IBM 8.3 FEAT] s390x: Base KVM setup for secure guests - qemu part +Patch328: kvm-s390x-Don-t-do-a-normal-reset-on-the-initial-cpu.patch +# For bz#1828317 - [IBM 8.3 FEAT] s390x: Base KVM setup for secure guests - qemu part +Patch329: kvm-s390x-Move-reset-normal-to-shared-reset-handler.patch +# For bz#1828317 - [IBM 8.3 FEAT] s390x: Base KVM setup for secure guests - qemu part +Patch330: kvm-s390x-Move-initial-reset.patch +# For bz#1828317 - [IBM 8.3 FEAT] s390x: Base KVM setup for secure guests - qemu part +Patch331: kvm-s390x-Move-clear-reset.patch +# For bz#1828317 - [IBM 8.3 FEAT] s390x: Base KVM setup for secure guests - qemu part +Patch332: kvm-s390x-Beautify-diag308-handling.patch +# For bz#1828317 - [IBM 8.3 FEAT] s390x: Base KVM setup for secure guests - qemu part +Patch333: kvm-s390x-kvm-Make-kvm_sclp_service_call-void.patch +# For bz#1828317 - [IBM 8.3 FEAT] s390x: Base KVM setup for secure guests - qemu part +Patch334: kvm-s390x-Fix-cpu-normal-reset-ri-clearing.patch +# For bz#1828317 - [IBM 8.3 FEAT] s390x: Base KVM setup for secure guests - qemu part +Patch335: kvm-tests-boot-sector-Fix-the-bad-s390x-assembler-code.patch +# For bz#1828317 - [IBM 8.3 FEAT] s390x: Base KVM setup for secure guests - qemu part +Patch336: kvm-pc-bios-s390x-Fix-reset-psw-mask.patch +# For bz#1828317 - [IBM 8.3 FEAT] s390x: Base KVM setup for secure guests - qemu part +Patch337: kvm-s390x-Properly-fetch-and-test-the-short-psw-on-diag3.patch +# For bz#1828317 - [IBM 8.3 FEAT] s390x: Base KVM setup for secure guests - qemu part +Patch338: kvm-s390x-Rename-and-use-constants-for-short-PSW-address.patch +# For bz#1828317 - [IBM 8.3 FEAT] s390x: Base KVM setup for secure guests - qemu part +Patch339: kvm-s390x-Add-missing-vcpu-reset-functions.patch +# For bz#1828317 - [IBM 8.3 FEAT] s390x: Base KVM setup for secure guests - qemu part +Patch340: kvm-s390-sclp-improve-special-wait-psw-logic.patch +# For bz#1828317 - [IBM 8.3 FEAT] s390x: Base KVM setup for secure guests - qemu part +Patch341: kvm-pc-bios-s390x-Save-iplb-location-in-lowcore.patch +# For bz#1828317 - [IBM 8.3 FEAT] s390x: Base KVM setup for secure guests - qemu part +Patch342: kvm-s390-ipl-sync-back-loadparm.patch +# For bz#1828317 - [IBM 8.3 FEAT] s390x: Base KVM setup for secure guests - qemu part +Patch343: kvm-s390-ipl-fix-off-by-one-in-update_machine_ipl_proper.patch +# For bz#1828317 - [IBM 8.3 FEAT] s390x: Base KVM setup for secure guests - qemu part +Patch344: kvm-s390x-ipl-Consolidate-iplb-validity-check-into-one-f.patch +# For bz#1828317 - [IBM 8.3 FEAT] s390x: Base KVM setup for secure guests - qemu part +Patch345: kvm-vhost-correctly-turn-on-VIRTIO_F_IOMMU_PLATFORM.patch +# For bz#1828317 - [IBM 8.3 FEAT] s390x: Base KVM setup for secure guests - qemu part +Patch346: kvm-s390x-Move-diagnose-308-subcodes-and-rcs-into-ipl.h.patch +# For bz#1828317 - [IBM 8.3 FEAT] s390x: Base KVM setup for secure guests - qemu part +Patch347: kvm-s390x-protvirt-Support-unpack-facility.patch +# For bz#1828317 - [IBM 8.3 FEAT] s390x: Base KVM setup for secure guests - qemu part +Patch348: kvm-s390x-protvirt-Add-migration-blocker.patch +# For bz#1828317 - [IBM 8.3 FEAT] s390x: Base KVM setup for secure guests - qemu part +Patch349: kvm-s390x-protvirt-Inhibit-balloon-when-switching-to-pro.patch +# For bz#1828317 - [IBM 8.3 FEAT] s390x: Base KVM setup for secure guests - qemu part +Patch350: kvm-s390x-protvirt-KVM-intercept-changes.patch +# For bz#1828317 - [IBM 8.3 FEAT] s390x: Base KVM setup for secure guests - qemu part +Patch351: kvm-s390x-Add-SIDA-memory-ops.patch +# For bz#1828317 - [IBM 8.3 FEAT] s390x: Base KVM setup for secure guests - qemu part +Patch352: kvm-s390x-protvirt-Move-STSI-data-over-SIDAD.patch +# For bz#1828317 - [IBM 8.3 FEAT] s390x: Base KVM setup for secure guests - qemu part +Patch353: kvm-s390x-protvirt-SCLP-interpretation.patch +# For bz#1828317 - [IBM 8.3 FEAT] s390x: Base KVM setup for secure guests - qemu part +Patch354: kvm-s390x-protvirt-Set-guest-IPL-PSW.patch +# For bz#1828317 - [IBM 8.3 FEAT] s390x: Base KVM setup for secure guests - qemu part +Patch355: kvm-s390x-protvirt-Move-diag-308-data-over-SIDA.patch +# For bz#1828317 - [IBM 8.3 FEAT] s390x: Base KVM setup for secure guests - qemu part +Patch356: kvm-s390x-protvirt-Disable-address-checks-for-PV-guest-I.patch +# For bz#1828317 - [IBM 8.3 FEAT] s390x: Base KVM setup for secure guests - qemu part +Patch357: kvm-s390x-protvirt-Move-IO-control-structures-over-SIDA.patch +# For bz#1828317 - [IBM 8.3 FEAT] s390x: Base KVM setup for secure guests - qemu part +Patch358: kvm-s390x-protvirt-Handle-SIGP-store-status-correctly.patch +# For bz#1828317 - [IBM 8.3 FEAT] s390x: Base KVM setup for secure guests - qemu part +Patch359: kvm-s390x-Add-unpack-facility-feature-to-GA1.patch +# For bz#1828317 - [IBM 8.3 FEAT] s390x: Base KVM setup for secure guests - qemu part +Patch360: kvm-s390x-protvirt-Fix-stray-error_report_err-in-s390_ma.patch +# For bz#1828317 - [IBM 8.3 FEAT] s390x: Base KVM setup for secure guests - qemu part +Patch361: kvm-s390x-pv-Retry-ioctls-on-EINTR.patch +# For bz#1828317 - [IBM 8.3 FEAT] s390x: Base KVM setup for secure guests - qemu part +Patch362: kvm-s390x-s390-virtio-ccw-Fix-build-on-systems-without-K.patch +# For bz#1828317 - [IBM 8.3 FEAT] s390x: Base KVM setup for secure guests - qemu part +Patch363: kvm-s390x-pv-Fix-KVM_PV_PREP_RESET-command-wrapper-name.patch +# For bz#1756946 - [zKVM] Re-enable KVM_CAP_S390_AIS for new machine types +Patch364: kvm-spapr-Pass-the-maximum-number-of-vCPUs-to-the-KVM-in.patch +# For bz#1756946 - [zKVM] Re-enable KVM_CAP_S390_AIS for new machine types +Patch365: kvm-introduce-kvm_kernel_irqchip_-functions.patch +# For bz#1756946 - [zKVM] Re-enable KVM_CAP_S390_AIS for new machine types +Patch366: kvm-target-s390x-kvm-Enable-adapter-interruption-suppres.patch +# For bz#1823275 - RHEL8.1 - GPU Numa nodes not visible in guest post the pass-through. +Patch367: kvm-vfio-nvlink-Remove-exec-permission-to-avoid-SELinux-.patch +# For bz#1660916 - [IBM 8.3 FEAT] KVM s390x: DASD passthrough support - qemu part +Patch368: kvm-vfio-ccw-Fix-error-message.patch +# For bz#1660916 - [IBM 8.3 FEAT] KVM s390x: DASD passthrough support - qemu part +Patch369: kvm-vfio-ccw-allow-non-prefetch-ORBs.patch +# For bz#1660916 - [IBM 8.3 FEAT] KVM s390x: DASD passthrough support - qemu part +Patch370: kvm-linux-headers-support-vfio-ccw-features.patch +# For bz#1660916 - [IBM 8.3 FEAT] KVM s390x: DASD passthrough support - qemu part +Patch371: kvm-vfio-ccw-Refactor-cleanup-of-regions.patch +# For bz#1660916 - [IBM 8.3 FEAT] KVM s390x: DASD passthrough support - qemu part +Patch372: kvm-vfio-ccw-Add-support-for-the-schib-region.patch +# For bz#1660916 - [IBM 8.3 FEAT] KVM s390x: DASD passthrough support - qemu part +Patch373: kvm-vfio-ccw-Refactor-ccw-irq-handler.patch +# For bz#1660916 - [IBM 8.3 FEAT] KVM s390x: DASD passthrough support - qemu part +Patch374: kvm-s390x-css-Refactor-the-css_queue_crw-routine.patch +# For bz#1660916 - [IBM 8.3 FEAT] KVM s390x: DASD passthrough support - qemu part +Patch375: kvm-vfio-ccw-Add-support-for-the-CRW-region-and-IRQ.patch +# For bz#1660916 - [IBM 8.3 FEAT] KVM s390x: DASD passthrough support - qemu part +Patch376: kvm-config-enable-VFIO_CCW.patch +Patch377: kvm-virtio-blk-Refactor-the-code-that-processes-queued-r.patch +Patch378: kvm-virtio-blk-On-restart-process-queued-requests-in-the.patch +# For bz#1838070 - CVE-2020-1983 virt:rhel/qemu-kvm: QEMU: slirp: use-after-free in ip_reass() function in ip_input.c [rhel-8] +Patch379: kvm-Fix-use-afte-free-in-ip_reass-CVE-2020-1983.patch BuildRequires: wget BuildRequires: rpm-build @@ -1128,6 +1398,11 @@ cp -a %{kvm_target}-softmmu/qemu-system-%{kvm_target} qemu-kvm gcc %{SOURCE6} $RPM_OPT_FLAGS $RPM_LD_FLAGS -o ksmctl gcc %{SOURCE35} $RPM_OPT_FLAGS $RPM_LD_FLAGS -o udev-kvm-check +%ifarch s390x + # Copy the built new images into place for "make check": + cp pc-bios/s390-ccw/s390-ccw.img pc-bios/s390-ccw/s390-netboot.img pc-bios/ +%endif + %install %define _udevdir %(pkg-config --variable=udevdir udev) %define _udevrulesdir %{_udevdir}/rules.d @@ -1178,9 +1453,9 @@ install -p -m 0755 tests/Makefile.include $RPM_BUILD_ROOT%{testsdir}/tests/ # Install qemu-iotests cp -R tests/qemu-iotests/* $RPM_BUILD_ROOT%{testsdir}/tests/qemu-iotests/ # Avoid ambiguous 'python' interpreter name -find $RPM_BUILD_ROOT%{testsdir}/tests/qemu-iotests/* -maxdepth 1 -type f -exec sed -i -e '1 s+/usr/bin/env python+%{__python3}+' {} \; -find $RPM_BUILD_ROOT%{testsdir}/scripts/qmp/* -maxdepth 1 -type f -exec sed -i -e '1 s+/usr/bin/env python+%{__python3}+' {} \; -find $RPM_BUILD_ROOT%{testsdir}/scripts/qmp/* -maxdepth 1 -type f -exec sed -i -e '1 s+/usr/bin/python+%{__python3}+' {} \; +find $RPM_BUILD_ROOT%{testsdir}/tests/qemu-iotests/* -maxdepth 1 -type f -exec sed -i -e '1 s+/usr/bin/env \(python\|python3\)+%{__python3}+' {} \; +find $RPM_BUILD_ROOT%{testsdir}/scripts/qmp/* -maxdepth 1 -type f -exec sed -i -e '1 s+/usr/bin/env \(python\|python3\)+%{__python3}+' {} \; +find $RPM_BUILD_ROOT%{testsdir}/scripts/qmp/* -maxdepth 1 -type f -exec sed -i -e '1 s+/usr/bin/\(python\|python3\)+%{__python3}+' {} \; install -p -m 0644 %{SOURCE36} $RPM_BUILD_ROOT%{testsdir}/README @@ -1266,6 +1541,7 @@ rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{name}/qemu_vga.ndrv rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{name}/skiboot.lid rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{name}/s390-ccw.img +rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{name}/s390-netboot.img rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{name}/hppa-firmware.img rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{name}/canyonlands.dtb rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{name}/u-boot-sam460-20100605.bin @@ -1282,10 +1558,9 @@ rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{name}/qemu-nsis.bmp rm -rf ${RPM_BUILD_ROOT}%{_libdir}/qemu-kvm/ui-spice-app.so %ifarch s390x - # Use the s390-ccw.img that we've just built, not the pre-built one + # Use the s390-*.imgs that we've just built, not the pre-built ones install -m 0644 pc-bios/s390-ccw/s390-ccw.img $RPM_BUILD_ROOT%{_datadir}/%{name}/ -%else - rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{name}/s390-netboot.img + install -m 0644 pc-bios/s390-ccw/s390-netboot.img $RPM_BUILD_ROOT%{_datadir}/%{name}/ %endif %ifnarch x86_64 @@ -1570,6 +1845,88 @@ useradd -r -u 107 -g qemu -G kvm -d / -s /sbin/nologin \ %changelog +* Sun Jun 28 2020 Danilo Cesar Lemes de Paula - 4.2.0-29.el8 +- kvm-vfio-ccw-Fix-error-message.patch [bz#1660916] +- kvm-vfio-ccw-allow-non-prefetch-ORBs.patch [bz#1660916] +- kvm-linux-headers-support-vfio-ccw-features.patch [bz#1660916] +- kvm-vfio-ccw-Refactor-cleanup-of-regions.patch [bz#1660916] +- kvm-vfio-ccw-Add-support-for-the-schib-region.patch [bz#1660916] +- kvm-vfio-ccw-Refactor-ccw-irq-handler.patch [bz#1660916] +- kvm-s390x-css-Refactor-the-css_queue_crw-routine.patch [bz#1660916] +- kvm-vfio-ccw-Add-support-for-the-CRW-region-and-IRQ.patch [bz#1660916] +- kvm-config-enable-VFIO_CCW.patch [bz#1660916] +- kvm-virtio-blk-Refactor-the-code-that-processes-queued-r.patch [] +- kvm-virtio-blk-On-restart-process-queued-requests-in-the.patch [] +- kvm-Fix-use-afte-free-in-ip_reass-CVE-2020-1983.patch [bz#1838070] +- Resolves: bz#1660916 + ([IBM 8.3 FEAT] KVM s390x: DASD passthrough support - qemu part) +- Resolves: bz#1838070 + (CVE-2020-1983 virt:rhel/qemu-kvm: QEMU: slirp: use-after-free in ip_reass() function in ip_input.c [rhel-8]) + +* Fri Jun 19 2020 Danilo Cesar Lemes de Paula - 4.2.0-28.el8 +- kvm-redhat-Install-the-s390-netboot.img-that-we-ve-built.patch [bz#1828317] +- kvm-linux-headers-update-kvm.h.patch [bz#1828317] +- kvm-s390x-Don-t-do-a-normal-reset-on-the-initial-cpu.patch [bz#1828317] +- kvm-s390x-Move-reset-normal-to-shared-reset-handler.patch [bz#1828317] +- kvm-s390x-Move-initial-reset.patch [bz#1828317] +- kvm-s390x-Move-clear-reset.patch [bz#1828317] +- kvm-s390x-Beautify-diag308-handling.patch [bz#1828317] +- kvm-s390x-kvm-Make-kvm_sclp_service_call-void.patch [bz#1828317] +- kvm-s390x-Fix-cpu-normal-reset-ri-clearing.patch [bz#1828317] +- kvm-tests-boot-sector-Fix-the-bad-s390x-assembler-code.patch [bz#1828317] +- kvm-pc-bios-s390x-Fix-reset-psw-mask.patch [bz#1828317] +- kvm-s390x-Properly-fetch-and-test-the-short-psw-on-diag3.patch [bz#1828317] +- kvm-s390x-Rename-and-use-constants-for-short-PSW-address.patch [bz#1828317] +- kvm-s390x-Add-missing-vcpu-reset-functions.patch [bz#1828317] +- kvm-s390-sclp-improve-special-wait-psw-logic.patch [bz#1828317] +- kvm-pc-bios-s390x-Save-iplb-location-in-lowcore.patch [bz#1828317] +- kvm-s390-ipl-sync-back-loadparm.patch [bz#1828317] +- kvm-s390-ipl-fix-off-by-one-in-update_machine_ipl_proper.patch [bz#1828317] +- kvm-s390x-ipl-Consolidate-iplb-validity-check-into-one-f.patch [bz#1828317] +- kvm-vhost-correctly-turn-on-VIRTIO_F_IOMMU_PLATFORM.patch [bz#1828317] +- kvm-s390x-Move-diagnose-308-subcodes-and-rcs-into-ipl.h.patch [bz#1828317] +- kvm-s390x-protvirt-Support-unpack-facility.patch [bz#1828317] +- kvm-s390x-protvirt-Add-migration-blocker.patch [bz#1828317] +- kvm-s390x-protvirt-Inhibit-balloon-when-switching-to-pro.patch [bz#1828317] +- kvm-s390x-protvirt-KVM-intercept-changes.patch [bz#1828317] +- kvm-s390x-Add-SIDA-memory-ops.patch [bz#1828317] +- kvm-s390x-protvirt-Move-STSI-data-over-SIDAD.patch [bz#1828317] +- kvm-s390x-protvirt-SCLP-interpretation.patch [bz#1828317] +- kvm-s390x-protvirt-Set-guest-IPL-PSW.patch [bz#1828317] +- kvm-s390x-protvirt-Move-diag-308-data-over-SIDA.patch [bz#1828317] +- kvm-s390x-protvirt-Disable-address-checks-for-PV-guest-I.patch [bz#1828317] +- kvm-s390x-protvirt-Move-IO-control-structures-over-SIDA.patch [bz#1828317] +- kvm-s390x-protvirt-Handle-SIGP-store-status-correctly.patch [bz#1828317] +- kvm-s390x-Add-unpack-facility-feature-to-GA1.patch [bz#1828317] +- kvm-s390x-protvirt-Fix-stray-error_report_err-in-s390_ma.patch [bz#1828317] +- kvm-s390x-pv-Retry-ioctls-on-EINTR.patch [bz#1828317] +- kvm-s390x-s390-virtio-ccw-Fix-build-on-systems-without-K.patch [bz#1828317] +- kvm-s390x-pv-Fix-KVM_PV_PREP_RESET-command-wrapper-name.patch [bz#1828317] +- kvm-spapr-Pass-the-maximum-number-of-vCPUs-to-the-KVM-in.patch [bz#1756946] +- kvm-introduce-kvm_kernel_irqchip_-functions.patch [bz#1756946] +- kvm-target-s390x-kvm-Enable-adapter-interruption-suppres.patch [bz#1756946] +- kvm-vfio-nvlink-Remove-exec-permission-to-avoid-SELinux-.patch [bz#1823275] +- Resolves: bz#1756946 + ([zKVM] Re-enable KVM_CAP_S390_AIS for new machine types) +- Resolves: bz#1823275 + (RHEL8.1 - GPU Numa nodes not visible in guest post the pass-through.) +- Resolves: bz#1828317 + ([IBM 8.3 FEAT] s390x: Base KVM setup for secure guests - qemu part) + +* Fri Jun 19 2020 Danilo C. L. de Paula - 4.2.0 +- Resolves: bz#1810193 +(Upgrade components in virt:rhel module:stream for RHEL-8.3 release) + +* Tue Jun 09 2020 Danilo C. L. de Paula - 4.2.0-25 +- Resolves: bz#1810193 + (Upgrade components in virt:rhel module:stream for RHEL-8.3 release) + Another sync + +* Thu Jun 04 2020 Danilo C. L. de Paula - 4.2.0-23.el8 +- Resolves: bz#1810193 + (Upgrade components in virt:rhel module:stream for RHEL-8.3 release) + Another syncronization + * Mon Apr 27 2020 Danilo C. L. de Paula - 4.2.0 - Resolves: bz#1810193 (Upgrade components in virt:rhel module:stream for RHEL-8.3 release)